All of lore.kernel.org
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/4] net/qede: add FW debug data collection support
@ 2020-06-28  5:58 Rasesh Mody
  2020-06-28  5:58 ` [dpdk-dev] [PATCH 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
                   ` (8 more replies)
  0 siblings, 9 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-06-28  5:58 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev

Hi Jerin, Ferruh,

This patch-set adds an ability to collect FW and HW Debug Data/Dump
(referred to as FW/HW Dump) to QEDE PMD. The dump is collected either
when PMD detects an error or when a DPDK application asks PMD to
collect it upon detection of application error. This FW/HW Dump
needs to be saved to a file and sent to Marvell for analysis.

Please apply to dpdk-next-net-mrvl and dpdk-next-net trees.

Thanks!
-Rasesh

Rasesh Mody (4):
  net/qede/base: re-arrange few structures for DDC
  net/qede/base: add changes for debug data collection
  net/qede: add infrastructure for debug data collection
  net/qede: add support for get register operation

 drivers/net/qede/Makefile                     |    5 +-
 drivers/net/qede/base/bcm_osal.c              |   31 +
 drivers/net/qede/base/bcm_osal.h              |   18 +-
 drivers/net/qede/base/common_hsi.h            |    1 +
 drivers/net/qede/base/ecore.h                 |   54 +-
 drivers/net/qede/base/ecore_cxt.c             |  200 +-
 drivers/net/qede/base/ecore_cxt.h             |  140 +-
 drivers/net/qede/base/ecore_dev.c             |   13 +
 drivers/net/qede/base/ecore_hsi_common.h      |  184 +-
 drivers/net/qede/base/ecore_hsi_debug_tools.h |    2 +-
 drivers/net/qede/base/ecore_hsi_func_common.h |   17 +
 drivers/net/qede/base/ecore_init_fw_funcs.h   |    7 -
 drivers/net/qede/base/ecore_mcp.c             |  211 +
 drivers/net/qede/base/ecore_mcp_api.h         |   37 +
 drivers/net/qede/base/ecore_status.h          |    2 +
 drivers/net/qede/base/reg_addr.h              |  846 ++
 drivers/net/qede/qede_debug.c                 | 8119 +++++++++++++++++
 drivers/net/qede/qede_debug.h                 |  759 ++
 drivers/net/qede/qede_ethdev.c                |    2 +-
 drivers/net/qede/qede_ethdev.h                |   25 +
 drivers/net/qede/qede_if.h                    |   45 +
 drivers/net/qede/qede_main.c                  |   42 +-
 drivers/net/qede/qede_regs.c                  |  271 +
 23 files changed, 10872 insertions(+), 159 deletions(-)
 create mode 100644 drivers/net/qede/base/ecore_hsi_func_common.h
 create mode 100644 drivers/net/qede/qede_debug.c
 create mode 100644 drivers/net/qede/qede_debug.h
 create mode 100644 drivers/net/qede/qede_regs.c

-- 
2.18.0


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

* [dpdk-dev] [PATCH 1/4] net/qede/base: re-arrange few structures for DDC
  2020-06-28  5:58 [dpdk-dev] [PATCH 0/4] net/qede: add FW debug data collection support Rasesh Mody
@ 2020-06-28  5:58 ` Rasesh Mody
  2020-06-28  5:58 ` [dpdk-dev] [PATCH 2/4] net/qede/base: add changes for debug data collection Rasesh Mody
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-06-28  5:58 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

This patch rearranges some of the base driver structures which will be
also used by debug data collection (DDC) implementation. It adds a new
file ecore_hsi_func_common.h with Physical, Virtual memory descriptors.

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/qede/base/ecore.h                 |   2 +
 drivers/net/qede/base/ecore_cxt.c             | 140 ++----------------
 drivers/net/qede/base/ecore_cxt.h             | 135 ++++++++++++++++-
 drivers/net/qede/base/ecore_hsi_func_common.h |  17 +++
 drivers/net/qede/base/ecore_init_fw_funcs.h   |   7 -
 5 files changed, 163 insertions(+), 138 deletions(-)
 create mode 100644 drivers/net/qede/base/ecore_hsi_func_common.h

diff --git a/drivers/net/qede/base/ecore.h b/drivers/net/qede/base/ecore.h
index 498bb6f09..dc5fe4d80 100644
--- a/drivers/net/qede/base/ecore.h
+++ b/drivers/net/qede/base/ecore.h
@@ -24,6 +24,7 @@
 #include "ecore_hsi_debug_tools.h"
 #include "ecore_hsi_init_func.h"
 #include "ecore_hsi_init_tool.h"
+#include "ecore_hsi_func_common.h"
 #include "ecore_proto_if.h"
 #include "mcp_public.h"
 
@@ -671,6 +672,7 @@ struct ecore_hwfn {
 
 	struct dbg_tools_data		dbg_info;
 	void				*dbg_user_info;
+	struct virt_mem_desc		dbg_arrays[MAX_BIN_DBG_BUFFER_TYPE];
 
 	struct z_stream_s		*stream;
 
diff --git a/drivers/net/qede/base/ecore_cxt.c b/drivers/net/qede/base/ecore_cxt.c
index dda47ea67..23f37b1bf 100644
--- a/drivers/net/qede/base/ecore_cxt.c
+++ b/drivers/net/qede/base/ecore_cxt.c
@@ -20,12 +20,6 @@
 #include "ecore_sriov.h"
 #include "ecore_mcp.h"
 
-/* Max number of connection types in HW (DQ/CDU etc.) */
-#define MAX_CONN_TYPES		PROTOCOLID_COMMON
-#define NUM_TASK_TYPES		2
-#define NUM_TASK_PF_SEGMENTS	4
-#define NUM_TASK_VF_SEGMENTS	1
-
 /* Doorbell-Queue constants */
 #define DQ_RANGE_SHIFT	4
 #define DQ_RANGE_ALIGN	(1 << DQ_RANGE_SHIFT)
@@ -90,128 +84,6 @@ struct src_ent {
 /* Alignment is inherent to the type1_task_context structure */
 #define TYPE1_TASK_CXT_SIZE(p_hwfn) sizeof(union type1_task_context)
 
-/* PF per protocl configuration object */
-#define TASK_SEGMENTS   (NUM_TASK_PF_SEGMENTS + NUM_TASK_VF_SEGMENTS)
-#define TASK_SEGMENT_VF (NUM_TASK_PF_SEGMENTS)
-
-struct ecore_tid_seg {
-	u32 count;
-	u8 type;
-	bool has_fl_mem;
-};
-
-struct ecore_conn_type_cfg {
-	u32 cid_count;
-	u32 cids_per_vf;
-	struct ecore_tid_seg tid_seg[TASK_SEGMENTS];
-};
-
-/* ILT Client configuration,
- * Per connection type (protocol) resources (cids, tis, vf cids etc.)
- * 1 - for connection context (CDUC) and for each task context we need two
- * values, for regular task context and for force load memory
- */
-#define ILT_CLI_PF_BLOCKS	(1 + NUM_TASK_PF_SEGMENTS * 2)
-#define ILT_CLI_VF_BLOCKS	(1 + NUM_TASK_VF_SEGMENTS * 2)
-#define CDUC_BLK		(0)
-#define SRQ_BLK			(0)
-#define CDUT_SEG_BLK(n)		(1 + (u8)(n))
-#define CDUT_FL_SEG_BLK(n, X)	(1 + (n) + NUM_TASK_##X##_SEGMENTS)
-
-struct ilt_cfg_pair {
-	u32 reg;
-	u32 val;
-};
-
-struct ecore_ilt_cli_blk {
-	u32 total_size;		/* 0 means not active */
-	u32 real_size_in_page;
-	u32 start_line;
-	u32 dynamic_line_offset;
-	u32 dynamic_line_cnt;
-};
-
-struct ecore_ilt_client_cfg {
-	bool active;
-
-	/* ILT boundaries */
-	struct ilt_cfg_pair first;
-	struct ilt_cfg_pair last;
-	struct ilt_cfg_pair p_size;
-
-	/* ILT client blocks for PF */
-	struct ecore_ilt_cli_blk pf_blks[ILT_CLI_PF_BLOCKS];
-	u32 pf_total_lines;
-
-	/* ILT client blocks for VFs */
-	struct ecore_ilt_cli_blk vf_blks[ILT_CLI_VF_BLOCKS];
-	u32 vf_total_lines;
-};
-
-#define MAP_WORD_SIZE		sizeof(unsigned long)
-#define BITS_PER_MAP_WORD	(MAP_WORD_SIZE * 8)
-
-struct ecore_cid_acquired_map {
-	u32 start_cid;
-	u32 max_count;
-	u32 *cid_map;
-};
-
-struct ecore_src_t2 {
-	struct phys_mem_desc	*dma_mem;
-	u32			num_pages;
-	u64			first_free;
-	u64			last_free;
-};
-
-struct ecore_cxt_mngr {
-	/* Per protocl configuration */
-	struct ecore_conn_type_cfg conn_cfg[MAX_CONN_TYPES];
-
-	/* computed ILT structure */
-	struct ecore_ilt_client_cfg clients[ILT_CLI_MAX];
-
-	/* Task type sizes */
-	u32 task_type_size[NUM_TASK_TYPES];
-
-	/* total number of VFs for this hwfn -
-	 * ALL VFs are symmetric in terms of HW resources
-	 */
-	u32 vf_count;
-
-	/* Acquired CIDs */
-	struct ecore_cid_acquired_map acquired[MAX_CONN_TYPES];
-	struct ecore_cid_acquired_map *acquired_vf[MAX_CONN_TYPES];
-
-	/* ILT  shadow table */
-	struct phys_mem_desc		*ilt_shadow;
-	u32 pf_start_line;
-
-	/* Mutex for a dynamic ILT allocation */
-	osal_mutex_t mutex;
-
-	/* SRC T2 */
-	struct ecore_src_t2		src_t2;
-
-	/* The infrastructure originally was very generic and context/task
-	 * oriented - per connection-type we would set how many of those
-	 * are needed, and later when determining how much memory we're
-	 * needing for a given block we'd iterate over all the relevant
-	 * connection-types.
-	 * But since then we've had some additional resources, some of which
-	 * require memory which is indepent of the general context/task
-	 * scheme. We add those here explicitly per-feature.
-	 */
-
-	/* total number of SRQ's for this hwfn */
-	u32				srq_count;
-
-	/* Maximal number of L2 steering filters */
-	u32				arfs_count;
-
-	/* TODO - VF arfs filters ? */
-};
-
 static OSAL_INLINE bool tm_cid_proto(enum protocol_type type)
 {
 	return type == PROTOCOLID_TOE;
@@ -945,7 +817,7 @@ static enum _ecore_status_t ecore_cxt_src_t2_alloc(struct ecore_hwfn *p_hwfn)
 }
 
 #define for_each_ilt_valid_client(pos, clients)		\
-	for (pos = 0; pos < ILT_CLI_MAX; pos++)		\
+	for (pos = 0; pos < MAX_ILT_CLIENTS; pos++)		\
 		if (!clients[pos].active) {		\
 			continue;			\
 		} else					\
@@ -1238,7 +1110,7 @@ enum _ecore_status_t ecore_cxt_mngr_alloc(struct ecore_hwfn *p_hwfn)
 	clients[ILT_CLI_TSDM].p_size.reg = ILT_CFG_REG(TSDM, P_SIZE);
 
 	/* default ILT page size for all clients is 64K */
-	for (i = 0; i < ILT_CLI_MAX; i++)
+	for (i = 0; i < MAX_ILT_CLIENTS; i++)
 		p_mngr->clients[i].p_size.val = ILT_DEFAULT_HW_P_SIZE;
 
 	/* due to removal of ISCSI/FCoE files union type0_task_context
@@ -2306,3 +2178,11 @@ ecore_cxt_free_ilt_range(struct ecore_hwfn *p_hwfn,
 
 	return ECORE_SUCCESS;
 }
+
+static u16 ecore_blk_calculate_pages(struct ecore_ilt_cli_blk *p_blk)
+{
+	if (p_blk->real_size_in_page == 0)
+		return 0;
+
+	return DIV_ROUND_UP(p_blk->total_size, p_blk->real_size_in_page);
+}
diff --git a/drivers/net/qede/base/ecore_cxt.h b/drivers/net/qede/base/ecore_cxt.h
index 55f08027d..7b91b953e 100644
--- a/drivers/net/qede/base/ecore_cxt.h
+++ b/drivers/net/qede/base/ecore_cxt.h
@@ -31,7 +31,7 @@ enum ilt_clients {
 	ILT_CLI_TSDM,
 	ILT_CLI_RGFS,
 	ILT_CLI_TGFS,
-	ILT_CLI_MAX
+	MAX_ILT_CLIENTS
 };
 
 u32 ecore_cxt_get_proto_cid_count(struct ecore_hwfn *p_hwfn,
@@ -212,4 +212,137 @@ enum _ecore_status_t ecore_cxt_free_proto_ilt(struct ecore_hwfn *p_hwfn,
 #define ECORE_CTX_WORKING_MEM 0
 #define ECORE_CTX_FL_MEM 1
 
+/* Max number of connection types in HW (DQ/CDU etc.) */
+#define MAX_CONN_TYPES		PROTOCOLID_COMMON
+#define NUM_TASK_TYPES		2
+#define NUM_TASK_PF_SEGMENTS	4
+#define NUM_TASK_VF_SEGMENTS	1
+
+/* PF per protocl configuration object */
+#define TASK_SEGMENTS   (NUM_TASK_PF_SEGMENTS + NUM_TASK_VF_SEGMENTS)
+#define TASK_SEGMENT_VF (NUM_TASK_PF_SEGMENTS)
+
+struct ecore_tid_seg {
+	u32 count;
+	u8 type;
+	bool has_fl_mem;
+};
+
+struct ecore_conn_type_cfg {
+	u32 cid_count;
+	u32 cids_per_vf;
+	struct ecore_tid_seg tid_seg[TASK_SEGMENTS];
+};
+
+/* ILT Client configuration,
+ * Per connection type (protocol) resources (cids, tis, vf cids etc.)
+ * 1 - for connection context (CDUC) and for each task context we need two
+ * values, for regular task context and for force load memory
+ */
+#define ILT_CLI_PF_BLOCKS	(1 + NUM_TASK_PF_SEGMENTS * 2)
+#define ILT_CLI_VF_BLOCKS	(1 + NUM_TASK_VF_SEGMENTS * 2)
+#define CDUC_BLK		(0)
+#define SRQ_BLK			(0)
+#define CDUT_SEG_BLK(n)		(1 + (u8)(n))
+#define CDUT_FL_SEG_BLK(n, X)	(1 + (n) + NUM_TASK_##X##_SEGMENTS)
+
+struct ilt_cfg_pair {
+	u32 reg;
+	u32 val;
+};
+
+struct ecore_ilt_cli_blk {
+	u32 total_size;		/* 0 means not active */
+	u32 real_size_in_page;
+	u32 start_line;
+	u32 dynamic_line_offset;
+	u32 dynamic_line_cnt;
+};
+
+struct ecore_ilt_client_cfg {
+	bool active;
+
+	/* ILT boundaries */
+	struct ilt_cfg_pair first;
+	struct ilt_cfg_pair last;
+	struct ilt_cfg_pair p_size;
+
+	/* ILT client blocks for PF */
+	struct ecore_ilt_cli_blk pf_blks[ILT_CLI_PF_BLOCKS];
+	u32 pf_total_lines;
+
+	/* ILT client blocks for VFs */
+	struct ecore_ilt_cli_blk vf_blks[ILT_CLI_VF_BLOCKS];
+	u32 vf_total_lines;
+};
+
+#define MAP_WORD_SIZE		sizeof(unsigned long)
+#define BITS_PER_MAP_WORD	(MAP_WORD_SIZE * 8)
+
+struct ecore_cid_acquired_map {
+	u32 start_cid;
+	u32 max_count;
+	u32 *cid_map;
+};
+
+struct ecore_src_t2 {
+	struct phys_mem_desc	*dma_mem;
+	u32			num_pages;
+	u64			first_free;
+	u64			last_free;
+};
+
+struct ecore_cxt_mngr {
+	/* Per protocl configuration */
+	struct ecore_conn_type_cfg	conn_cfg[MAX_CONN_TYPES];
+
+	/* computed ILT structure */
+	struct ecore_ilt_client_cfg	clients[MAX_ILT_CLIENTS];
+
+	/* Task type sizes */
+	u32				task_type_size[NUM_TASK_TYPES];
+
+	/* total number of VFs for this hwfn -
+	 * ALL VFs are symmetric in terms of HW resources
+	 */
+	u32				vf_count;
+	u32				first_vf_in_pf;
+
+	/* Acquired CIDs */
+	struct ecore_cid_acquired_map acquired[MAX_CONN_TYPES];
+	struct ecore_cid_acquired_map *acquired_vf[MAX_CONN_TYPES];
+
+	/* ILT  shadow table */
+	struct phys_mem_desc		*ilt_shadow;
+	u32				ilt_shadow_size;
+	u32				pf_start_line;
+
+	/* Mutex for a dynamic ILT allocation */
+	osal_mutex_t mutex;
+
+	/* SRC T2 */
+	struct ecore_src_t2		src_t2;
+
+	/* The infrastructure originally was very generic and context/task
+	 * oriented - per connection-type we would set how many of those
+	 * are needed, and later when determining how much memory we're
+	 * needing for a given block we'd iterate over all the relevant
+	 * connection-types.
+	 * But since then we've had some additional resources, some of which
+	 * require memory which is indepent of the general context/task
+	 * scheme. We add those here explicitly per-feature.
+	 */
+
+	/* total number of SRQ's for this hwfn */
+	u32				srq_count;
+
+	/* Maximal number of L2 steering filters */
+	u32				arfs_count;
+
+	/* TODO - VF arfs filters ? */
+
+	u8				task_type_id;
+	u16				task_ctx_size;
+	u16				conn_ctx_size;
+};
 #endif /* _ECORE_CID_ */
diff --git a/drivers/net/qede/base/ecore_hsi_func_common.h b/drivers/net/qede/base/ecore_hsi_func_common.h
new file mode 100644
index 000000000..2cd175163
--- /dev/null
+++ b/drivers/net/qede/base/ecore_hsi_func_common.h
@@ -0,0 +1,17 @@
+#ifndef _HSI_FUNC_COMMON_H
+#define _HSI_FUNC_COMMON_H
+
+/* Physical memory descriptor */
+struct phys_mem_desc {
+	dma_addr_t phys_addr;
+	void *virt_addr;
+	u32 size; /* In bytes */
+};
+
+/* Virtual memory descriptor */
+struct virt_mem_desc {
+	void *ptr;
+	u32 size; /* In bytes */
+};
+
+#endif
diff --git a/drivers/net/qede/base/ecore_init_fw_funcs.h b/drivers/net/qede/base/ecore_init_fw_funcs.h
index 912451662..a393d088f 100644
--- a/drivers/net/qede/base/ecore_init_fw_funcs.h
+++ b/drivers/net/qede/base/ecore_init_fw_funcs.h
@@ -9,13 +9,6 @@
 #include "ecore_hsi_common.h"
 #include "ecore_hsi_eth.h"
 
-/* Physical memory descriptor */
-struct phys_mem_desc {
-	dma_addr_t phys_addr;
-	void *virt_addr;
-	u32 size; /* In bytes */
-};
-
 /* Returns the VOQ based on port and TC */
 #define VOQ(port, tc, max_phys_tcs_per_port) \
 	((tc) == PURE_LB_TC ? NUM_OF_PHYS_TCS * MAX_NUM_PORTS_BB + (port) : \
-- 
2.18.0


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

* [dpdk-dev] [PATCH 2/4] net/qede/base: add changes for debug data collection
  2020-06-28  5:58 [dpdk-dev] [PATCH 0/4] net/qede: add FW debug data collection support Rasesh Mody
  2020-06-28  5:58 ` [dpdk-dev] [PATCH 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
@ 2020-06-28  5:58 ` Rasesh Mody
  2020-06-28  5:58 ` [dpdk-dev] [PATCH 3/4] net/qede: add infrastructure " Rasesh Mody
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-06-28  5:58 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

This patch adds base driver APIs required for debug data collection.
It adds support for dumping internal lookup tables(ilt), reading nvram
image, register definitions.

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/qede/base/bcm_osal.c              |   6 +
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/qede/base/common_hsi.h            |   1 +
 drivers/net/qede/base/ecore.h                 |  52 +-
 drivers/net/qede/base/ecore_cxt.c             |  60 ++
 drivers/net/qede/base/ecore_cxt.h             |   5 +
 drivers/net/qede/base/ecore_dev.c             |  13 +
 drivers/net/qede/base/ecore_hsi_common.h      | 184 +++-
 drivers/net/qede/base/ecore_hsi_debug_tools.h |   2 +-
 drivers/net/qede/base/ecore_mcp.c             | 211 +++++
 drivers/net/qede/base/ecore_mcp_api.h         |  37 +
 drivers/net/qede/base/ecore_status.h          |   2 +
 drivers/net/qede/base/reg_addr.h              | 846 ++++++++++++++++++
 drivers/net/qede/qede_ethdev.c                |   1 -
 drivers/net/qede/qede_main.c                  |   3 +-
 15 files changed, 1414 insertions(+), 17 deletions(-)

diff --git a/drivers/net/qede/base/bcm_osal.c b/drivers/net/qede/base/bcm_osal.c
index 54e5e4f98..45557fe3c 100644
--- a/drivers/net/qede/base/bcm_osal.c
+++ b/drivers/net/qede/base/bcm_osal.c
@@ -289,3 +289,9 @@ u32 qede_crc32(u32 crc, u8 *ptr, u32 length)
 	}
 	return crc;
 }
+
+void qed_set_platform_str(struct ecore_hwfn *p_hwfn,
+			  char *buf_str, u32 buf_size)
+{
+	snprintf(buf_str, buf_size, "%s.", rte_version());
+}
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index 88a2500a5..6ea3e7dda 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -8,6 +8,7 @@
 #define __BCM_OSAL_H
 
 #include <stdbool.h>
+#include <time.h>
 #include <rte_bitops.h>
 #include <rte_byteorder.h>
 #include <rte_spinlock.h>
@@ -19,6 +20,7 @@
 #include <rte_debug.h>
 #include <rte_ether.h>
 #include <rte_io.h>
+#include <rte_version.h>
 
 /* Forward declaration */
 struct ecore_dev;
@@ -450,7 +452,11 @@ u32 qede_crc32(u32 crc, u8 *ptr, u32 length);
 
 #define OSAL_DIV_S64(a, b)	((a) / (b))
 #define OSAL_LLDP_RX_TLVS(p_hwfn, tlv_buf, tlv_size) nothing
-#define OSAL_GET_EPOCH(p_hwfn)	0
+void qed_set_platform_str(struct ecore_hwfn *p_hwfn,
+			  char *buf_str, u32 buf_size);
+#define OSAL_SET_PLATFORM_STR(p_hwfn, buf_str, buf_size) \
+	qed_set_platform_str(p_hwfn, buf_str, buf_size)
+#define OSAL_GET_EPOCH(p_hwfn) ((u32)time(NULL))
 #define OSAL_DBG_ALLOC_USER_DATA(p_hwfn, user_data_ptr) (0)
 #define OSAL_DB_REC_OCCURRED(p_hwfn) nothing
 
diff --git a/drivers/net/qede/base/common_hsi.h b/drivers/net/qede/base/common_hsi.h
index e230fe5ac..1a02d460b 100644
--- a/drivers/net/qede/base/common_hsi.h
+++ b/drivers/net/qede/base/common_hsi.h
@@ -145,6 +145,7 @@
 #define NUM_OF_CONNECTION_TYPES (8)
 #define NUM_OF_TASK_TYPES       (8)
 #define NUM_OF_LCIDS            (320)
+#define NUM_OF_LTIDS            (320)
 
 /* Global PXP windows (GTT) */
 #define NUM_OF_GTT          19
diff --git a/drivers/net/qede/base/ecore.h b/drivers/net/qede/base/ecore.h
index dc5fe4d80..63bd7466a 100644
--- a/drivers/net/qede/base/ecore.h
+++ b/drivers/net/qede/base/ecore.h
@@ -576,6 +576,12 @@ enum BAR_ID {
 	BAR_ID_1	/* Used for doorbells */
 };
 
+struct ecore_nvm_image_info {
+	u32				num_images;
+	struct bist_nvm_image_att	*image_att;
+	bool				valid;
+};
+
 struct ecore_hwfn {
 	struct ecore_dev		*p_dev;
 	u8				my_id;		/* ID inside the PF */
@@ -701,6 +707,9 @@ struct ecore_hwfn {
 	 */
 	bool b_en_pacing;
 
+	/* Nvm images number and attributes */
+	struct ecore_nvm_image_info     nvm_info;
+
 	struct phys_mem_desc            *fw_overlay_mem;
 
 	/* @DPDK */
@@ -714,26 +723,34 @@ enum ecore_mf_mode {
 	ECORE_MF_UFP,
 };
 
-/* @DPDK */
-struct ecore_dbg_feature {
-	u8				*dump_buf;
-	u32				buf_size;
-	u32				dumped_dwords;
+enum ecore_dev_type {
+	ECORE_DEV_TYPE_BB,
+	ECORE_DEV_TYPE_AH,
 };
 
-enum qed_dbg_features {
-	DBG_FEATURE_BUS,
+/* @DPDK */
+enum ecore_dbg_features {
 	DBG_FEATURE_GRC,
 	DBG_FEATURE_IDLE_CHK,
 	DBG_FEATURE_MCP_TRACE,
 	DBG_FEATURE_REG_FIFO,
+	DBG_FEATURE_IGU_FIFO,
 	DBG_FEATURE_PROTECTION_OVERRIDE,
+	DBG_FEATURE_FW_ASSERTS,
+	DBG_FEATURE_ILT,
 	DBG_FEATURE_NUM
 };
 
-enum ecore_dev_type {
-	ECORE_DEV_TYPE_BB,
-	ECORE_DEV_TYPE_AH,
+struct ecore_dbg_feature {
+	u8				*dump_buf;
+	u32				buf_size;
+	u32				dumped_dwords;
+};
+
+struct ecore_dbg_params {
+	struct ecore_dbg_feature features[DBG_FEATURE_NUM];
+	u8 engine_for_debug;
+	bool print_data;
 };
 
 struct ecore_dev {
@@ -914,10 +931,12 @@ struct ecore_dev {
 	void				*firmware;
 	u64				fw_len;
 #endif
+	bool				disable_ilt_dump;
 
 	/* @DPDK */
 	struct ecore_dbg_feature	dbg_features[DBG_FEATURE_NUM];
-	u8				engine_for_debug;
+	struct ecore_dbg_params		dbg_params;
+	osal_mutex_t			dbg_lock;
 };
 
 enum ecore_hsi_def_type {
@@ -1067,6 +1086,17 @@ enum _ecore_status_t ecore_all_ppfids_wr(struct ecore_hwfn *p_hwfn,
 enum _ecore_status_t ecore_llh_dump_ppfid(struct ecore_dev *p_dev, u8 ppfid);
 enum _ecore_status_t ecore_llh_dump_all(struct ecore_dev *p_dev);
 
+/**
+ * @brief ecore_set_platform_str - Set the debug dump platform string.
+ * Write the ecore version and device's string to the given buffer.
+ *
+ * @param p_hwfn
+ * @param buf_str
+ * @param buf_size
+ */
+void ecore_set_platform_str(struct ecore_hwfn *p_hwfn,
+			    char *buf_str, u32 buf_size);
+
 #define TSTORM_QZONE_START	PXP_VF_BAR0_START_SDM_ZONE_A
 
 #define MSTORM_QZONE_START(dev) \
diff --git a/drivers/net/qede/base/ecore_cxt.c b/drivers/net/qede/base/ecore_cxt.c
index 23f37b1bf..d3025724b 100644
--- a/drivers/net/qede/base/ecore_cxt.c
+++ b/drivers/net/qede/base/ecore_cxt.c
@@ -2186,3 +2186,63 @@ static u16 ecore_blk_calculate_pages(struct ecore_ilt_cli_blk *p_blk)
 
 	return DIV_ROUND_UP(p_blk->total_size, p_blk->real_size_in_page);
 }
+
+u16 ecore_get_cdut_num_pf_init_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 i, pages = 0;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_PF_SEGMENTS; i++) {
+		p_blk = &p_cli->pf_blks[CDUT_FL_SEG_BLK(i, PF)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
+
+u16 ecore_get_cdut_num_vf_init_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 i, pages = 0;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_VF_SEGMENTS; i++) {
+		p_blk = &p_cli->vf_blks[CDUT_FL_SEG_BLK(i, VF)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
+
+u16 ecore_get_cdut_num_pf_work_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 i, pages = 0;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_PF_SEGMENTS; i++) {
+		p_blk = &p_cli->pf_blks[CDUT_SEG_BLK(i)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
+
+u16 ecore_get_cdut_num_vf_work_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 pages = 0, i;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_VF_SEGMENTS; i++) {
+		p_blk = &p_cli->vf_blks[CDUT_SEG_BLK(i)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
diff --git a/drivers/net/qede/base/ecore_cxt.h b/drivers/net/qede/base/ecore_cxt.h
index 7b91b953e..80fe39ac0 100644
--- a/drivers/net/qede/base/ecore_cxt.h
+++ b/drivers/net/qede/base/ecore_cxt.h
@@ -345,4 +345,9 @@ struct ecore_cxt_mngr {
 	u16				task_ctx_size;
 	u16				conn_ctx_size;
 };
+
+u16 ecore_get_cdut_num_pf_init_pages(struct ecore_hwfn *p_hwfn);
+u16 ecore_get_cdut_num_vf_init_pages(struct ecore_hwfn *p_hwfn);
+u16 ecore_get_cdut_num_pf_work_pages(struct ecore_hwfn *p_hwfn);
+u16 ecore_get_cdut_num_vf_work_pages(struct ecore_hwfn *p_hwfn);
 #endif /* _ECORE_CID_ */
diff --git a/drivers/net/qede/base/ecore_dev.c b/drivers/net/qede/base/ecore_dev.c
index e18c2fa89..3f86abdec 100644
--- a/drivers/net/qede/base/ecore_dev.c
+++ b/drivers/net/qede/base/ecore_dev.c
@@ -6793,6 +6793,19 @@ void ecore_set_fw_mac_addr(__le16 *fw_msb,
 	((u8 *)fw_lsb)[1] = mac[4];
 }
 
+void ecore_set_platform_str(struct ecore_hwfn *p_hwfn,
+			    char *buf_str, u32 buf_size)
+{
+	u32 len;
+
+	OSAL_SNPRINTF(buf_str, buf_size, "Ecore %d.%d.%d.%d. ",
+		      ECORE_MAJOR_VERSION, ECORE_MINOR_VERSION,
+		      ECORE_REVISION_VERSION, ECORE_ENGINEERING_VERSION);
+
+	len = OSAL_STRLEN(buf_str);
+	OSAL_SET_PLATFORM_STR(p_hwfn, &buf_str[len], buf_size - len);
+}
+
 bool ecore_is_mf_fip_special(struct ecore_dev *p_dev)
 {
 	return !!OSAL_GET_BIT(ECORE_MF_FIP_SPECIAL, &p_dev->mf_bits);
diff --git a/drivers/net/qede/base/ecore_hsi_common.h b/drivers/net/qede/base/ecore_hsi_common.h
index 23cfcdeff..578c798a9 100644
--- a/drivers/net/qede/base/ecore_hsi_common.h
+++ b/drivers/net/qede/base/ecore_hsi_common.h
@@ -10,6 +10,7 @@
 /* Add include to common target */
 /********************************/
 #include "common_hsi.h"
+#include "mcp_public.h"
 
 
 /*
@@ -2229,7 +2230,40 @@ struct fw_info_location {
 };
 
 
-
+/* DMAE parameters */
+struct ecore_dmae_params {
+	u32 flags;
+/* If QED_DMAE_PARAMS_RW_REPL_SRC flag is set and the
+ * source is a block of length DMAE_MAX_RW_SIZE and the
+ * destination is larger, the source block will be duplicated as
+ * many times as required to fill the destination block. This is
+ * used mostly to write a zeroed buffer to destination address
+ * using DMA
+ */
+#define ECORE_DMAE_PARAMS_RW_REPL_SRC_MASK        0x1
+#define ECORE_DMAE_PARAMS_RW_REPL_SRC_SHIFT       0
+#define ECORE_DMAE_PARAMS_SRC_VF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_SRC_VF_VALID_SHIFT      1
+#define ECORE_DMAE_PARAMS_DST_VF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_DST_VF_VALID_SHIFT      2
+#define ECORE_DMAE_PARAMS_COMPLETION_DST_MASK     0x1
+#define ECORE_DMAE_PARAMS_COMPLETION_DST_SHIFT    3
+#define ECORE_DMAE_PARAMS_PORT_VALID_MASK         0x1
+#define ECORE_DMAE_PARAMS_PORT_VALID_SHIFT        4
+#define ECORE_DMAE_PARAMS_SRC_PF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_SRC_PF_VALID_SHIFT      5
+#define ECORE_DMAE_PARAMS_DST_PF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_DST_PF_VALID_SHIFT      6
+#define ECORE_DMAE_PARAMS_RESERVED_MASK           0x1FFFFFF
+#define ECORE_DMAE_PARAMS_RESERVED_SHIFT          7
+	u8 src_vfid;
+	u8 dst_vfid;
+	u8 port_id;
+	u8 src_pfid;
+	u8 dst_pfid;
+	u8 reserved1;
+	__le16 reserved2;
+};
 
 /*
  * IGU cleanup command
@@ -2543,4 +2577,152 @@ struct ystorm_core_conn_ag_ctx {
 	__le32 reg3 /* reg3 */;
 };
 
+/*********/
+/* DEBUG */
+/*********/
+
+#define MFW_TRACE_SIGNATURE	0x25071946
+
+/* The trace in the buffer */
+#define MFW_TRACE_EVENTID_MASK		0x00ffff
+#define MFW_TRACE_PRM_SIZE_MASK		0x0f0000
+#define MFW_TRACE_PRM_SIZE_OFFSET	16
+#define MFW_TRACE_ENTRY_SIZE		3
+
+struct mcp_trace {
+	u32	signature;	/* Help to identify that the trace is valid */
+	u32	size;		/* the size of the trace buffer in bytes*/
+	u32	curr_level;	/* 2 - all will be written to the buffer
+				 * 1 - debug trace will not be written
+				 * 0 - just errors will be written to the buffer
+				 */
+	/* a bit per module, 1 means mask it off, 0 means add it to the trace
+	 * buffer
+	 */
+	u32	modules_mask[2];
+
+	/* Warning: the following pointers are assumed to be 32bits as they are
+	 * used only in the MFW
+	 */
+	/* The next trace will be written to this offset */
+	u32	trace_prod;
+	/* The oldest valid trace starts at this offset (usually very close
+	 * after the current producer)
+	 */
+	u32	trace_oldest;
+};
+
+enum spad_sections {
+	SPAD_SECTION_TRACE,
+	SPAD_SECTION_NVM_CFG,
+	SPAD_SECTION_PUBLIC,
+	SPAD_SECTION_PRIVATE,
+	SPAD_SECTION_MAX
+};
+
+#define MCP_TRACE_SIZE          2048    /* 2kb */
+
+/* This section is located at a fixed location in the beginning of the
+ * scratchpad, to ensure that the MCP trace is not run over during MFW upgrade.
+ * All the rest of data has a floating location which differs from version to
+ * version, and is pointed by the mcp_meta_data below.
+ * Moreover, the spad_layout section is part of the MFW firmware, and is loaded
+ * with it from nvram in order to clear this portion.
+ */
+struct static_init {
+	u32 num_sections;
+	offsize_t sections[SPAD_SECTION_MAX];
+#define SECTION(_sec_) (*((offsize_t *)(STRUCT_OFFSET(sections[_sec_]))))
+
+	struct mcp_trace trace;
+#define MCP_TRACE_P ((struct mcp_trace *)(STRUCT_OFFSET(trace)))
+	u8 trace_buffer[MCP_TRACE_SIZE];
+#define MCP_TRACE_BUF ((u8 *)(STRUCT_OFFSET(trace_buffer)))
+	/* running_mfw has the same definition as in nvm_map.h.
+	 * This bit indicate both the running dir, and the running bundle.
+	 * It is set once when the LIM is loaded.
+	 */
+	u32 running_mfw;
+#define RUNNING_MFW (*((u32 *)(STRUCT_OFFSET(running_mfw))))
+	u32 build_time;
+#define MFW_BUILD_TIME (*((u32 *)(STRUCT_OFFSET(build_time))))
+	u32 reset_type;
+#define RESET_TYPE (*((u32 *)(STRUCT_OFFSET(reset_type))))
+	u32 mfw_secure_mode;
+#define MFW_SECURE_MODE (*((u32 *)(STRUCT_OFFSET(mfw_secure_mode))))
+	u16 pme_status_pf_bitmap;
+#define PME_STATUS_PF_BITMAP (*((u16 *)(STRUCT_OFFSET(pme_status_pf_bitmap))))
+	u16 pme_enable_pf_bitmap;
+#define PME_ENABLE_PF_BITMAP (*((u16 *)(STRUCT_OFFSET(pme_enable_pf_bitmap))))
+	u32 mim_nvm_addr;
+	u32 mim_start_addr;
+	u32 ah_pcie_link_params;
+#define AH_PCIE_LINK_PARAMS_LINK_SPEED_MASK     (0x000000ff)
+#define AH_PCIE_LINK_PARAMS_LINK_SPEED_SHIFT    (0)
+#define AH_PCIE_LINK_PARAMS_LINK_WIDTH_MASK     (0x0000ff00)
+#define AH_PCIE_LINK_PARAMS_LINK_WIDTH_SHIFT    (8)
+#define AH_PCIE_LINK_PARAMS_ASPM_MODE_MASK      (0x00ff0000)
+#define AH_PCIE_LINK_PARAMS_ASPM_MODE_SHIFT     (16)
+#define AH_PCIE_LINK_PARAMS_ASPM_CAP_MASK       (0xff000000)
+#define AH_PCIE_LINK_PARAMS_ASPM_CAP_SHIFT      (24)
+#define AH_PCIE_LINK_PARAMS (*((u32 *)(STRUCT_OFFSET(ah_pcie_link_params))))
+
+	u32 rsrv_persist[5];	/* Persist reserved for MFW upgrades */
+};
+
+#define NVM_MAGIC_VALUE		0x669955aa
+
+enum nvm_image_type {
+	NVM_TYPE_TIM1 = 0x01,
+	NVM_TYPE_TIM2 = 0x02,
+	NVM_TYPE_MIM1 = 0x03,
+	NVM_TYPE_MIM2 = 0x04,
+	NVM_TYPE_MBA = 0x05,
+	NVM_TYPE_MODULES_PN = 0x06,
+	NVM_TYPE_VPD = 0x07,
+	NVM_TYPE_MFW_TRACE1 = 0x08,
+	NVM_TYPE_MFW_TRACE2 = 0x09,
+	NVM_TYPE_NVM_CFG1 = 0x0a,
+	NVM_TYPE_L2B = 0x0b,
+	NVM_TYPE_DIR1 = 0x0c,
+	NVM_TYPE_EAGLE_FW1 = 0x0d,
+	NVM_TYPE_FALCON_FW1 = 0x0e,
+	NVM_TYPE_PCIE_FW1 = 0x0f,
+	NVM_TYPE_HW_SET = 0x10,
+	NVM_TYPE_LIM = 0x11,
+	NVM_TYPE_AVS_FW1 = 0x12,
+	NVM_TYPE_DIR2 = 0x13,
+	NVM_TYPE_CCM = 0x14,
+	NVM_TYPE_EAGLE_FW2 = 0x15,
+	NVM_TYPE_FALCON_FW2 = 0x16,
+	NVM_TYPE_PCIE_FW2 = 0x17,
+	NVM_TYPE_AVS_FW2 = 0x18,
+	NVM_TYPE_INIT_HW = 0x19,
+	NVM_TYPE_DEFAULT_CFG = 0x1a,
+	NVM_TYPE_MDUMP = 0x1b,
+	NVM_TYPE_META = 0x1c,
+	NVM_TYPE_ISCSI_CFG = 0x1d,
+	NVM_TYPE_FCOE_CFG = 0x1f,
+	NVM_TYPE_ETH_PHY_FW1 = 0x20,
+	NVM_TYPE_ETH_PHY_FW2 = 0x21,
+	NVM_TYPE_BDN = 0x22,
+	NVM_TYPE_8485X_PHY_FW = 0x23,
+	NVM_TYPE_PUB_KEY = 0x24,
+	NVM_TYPE_RECOVERY = 0x25,
+	NVM_TYPE_PLDM = 0x26,
+	NVM_TYPE_UPK1 = 0x27,
+	NVM_TYPE_UPK2 = 0x28,
+	NVM_TYPE_MASTER_KC = 0x29,
+	NVM_TYPE_BACKUP_KC = 0x2a,
+	NVM_TYPE_HW_DUMP = 0x2b,
+	NVM_TYPE_HW_DUMP_OUT = 0x2c,
+	NVM_TYPE_BIN_NVM_META = 0x30,
+	NVM_TYPE_ROM_TEST = 0xf0,
+	NVM_TYPE_88X33X0_PHY_FW = 0x31,
+	NVM_TYPE_88X33X0_PHY_SLAVE_FW = 0x32,
+	NVM_TYPE_MAX,
+};
+
+#define DIR_ID_1    (0)
+
 #endif /* __ECORE_HSI_COMMON__ */
diff --git a/drivers/net/qede/base/ecore_hsi_debug_tools.h b/drivers/net/qede/base/ecore_hsi_debug_tools.h
index eb72e93cf..c5ef67f84 100644
--- a/drivers/net/qede/base/ecore_hsi_debug_tools.h
+++ b/drivers/net/qede/base/ecore_hsi_debug_tools.h
@@ -245,6 +245,7 @@ struct dbg_mode_hdr {
  * Attention register
  */
 struct dbg_attn_reg {
+	struct dbg_mode_hdr mode /* Mode header */;
 /* The offset of this registers attentions within the blocks attentions list
  * (a value in the range 0..number of block attentions-1)
  */
@@ -1049,5 +1050,4 @@ struct dbg_tools_data {
 };
 
 
-
 #endif /* __ECORE_HSI_DEBUG_TOOLS__ */
diff --git a/drivers/net/qede/base/ecore_mcp.c b/drivers/net/qede/base/ecore_mcp.c
index 0a9e26805..cab089d81 100644
--- a/drivers/net/qede/base/ecore_mcp.c
+++ b/drivers/net/qede/base/ecore_mcp.c
@@ -3621,6 +3621,217 @@ enum _ecore_status_t ecore_mcp_bist_nvm_test_get_image_att(
 	return rc;
 }
 
+enum _ecore_status_t
+ecore_mcp_bist_nvm_get_num_images(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt, u32 *num_images)
+{
+	u32 drv_mb_param = 0, rsp;
+	enum _ecore_status_t rc = ECORE_SUCCESS;
+
+	SET_MFW_FIELD(drv_mb_param, DRV_MB_PARAM_BIST_TEST_INDEX,
+		      DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES);
+
+	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
+			   drv_mb_param, &rsp, num_images);
+	if (rc != ECORE_SUCCESS)
+		return rc;
+
+	if (rsp == FW_MSG_CODE_UNSUPPORTED)
+		rc = ECORE_NOTIMPL;
+	else if (rsp != FW_MSG_CODE_OK)
+		rc = ECORE_UNKNOWN_ERROR;
+
+	return rc;
+}
+
+enum _ecore_status_t
+ecore_mcp_bist_nvm_get_image_att(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 struct bist_nvm_image_att *p_image_att,
+				 u32 image_index)
+{
+	u32 buf_size, nvm_offset = 0, resp, param;
+	enum _ecore_status_t rc;
+
+	SET_MFW_FIELD(nvm_offset, DRV_MB_PARAM_BIST_TEST_INDEX,
+		      DRV_MB_PARAM_BIST_NVM_TEST_IMAGE_BY_INDEX);
+	SET_MFW_FIELD(nvm_offset, DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX,
+		      image_index);
+	rc = ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
+				  nvm_offset, &resp, &param, &buf_size,
+				  (u32 *)p_image_att);
+	if (rc != ECORE_SUCCESS)
+		return rc;
+
+	if (resp == FW_MSG_CODE_UNSUPPORTED)
+		rc = ECORE_NOTIMPL;
+	else if ((resp != FW_MSG_CODE_OK) || (p_image_att->return_code != 1))
+		rc = ECORE_UNKNOWN_ERROR;
+
+	return rc;
+}
+
+enum _ecore_status_t ecore_mcp_nvm_info_populate(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_nvm_image_info nvm_info;
+	struct ecore_ptt *p_ptt;
+	enum _ecore_status_t rc;
+	u32 i;
+
+	if (p_hwfn->nvm_info.valid)
+		return ECORE_SUCCESS;
+
+#ifndef ASIC_ONLY
+	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev) ||
+	    CHIP_REV_IS_TEDIBEAR(p_hwfn->p_dev))
+		return ECORE_SUCCESS;
+#endif
+
+	p_ptt = ecore_ptt_acquire(p_hwfn);
+	if (!p_ptt) {
+		DP_ERR(p_hwfn, "failed to acquire ptt\n");
+		return ECORE_BUSY;
+	}
+
+	/* Acquire from MFW the amount of available images */
+	OSAL_MEM_ZERO(&nvm_info, sizeof(nvm_info));
+	rc = ecore_mcp_bist_nvm_get_num_images(p_hwfn, p_ptt,
+					       &nvm_info.num_images);
+	if (rc == ECORE_NOTIMPL) {
+		DP_INFO(p_hwfn, "DRV_MSG_CODE_BIST_TEST is not supported\n");
+		goto out;
+	} else if ((rc != ECORE_SUCCESS) || (nvm_info.num_images == 0)) {
+		DP_ERR(p_hwfn, "Failed getting number of images\n");
+		goto err0;
+	}
+
+	nvm_info.image_att = OSAL_ALLOC(p_hwfn->p_dev, GFP_KERNEL,
+					 nvm_info.num_images *
+					 sizeof(struct bist_nvm_image_att));
+	if (!nvm_info.image_att) {
+		rc = ECORE_NOMEM;
+		goto err0;
+	}
+
+	/* Iterate over images and get their attributes */
+	for (i = 0; i < nvm_info.num_images; i++) {
+		rc = ecore_mcp_bist_nvm_get_image_att(p_hwfn, p_ptt,
+						      &nvm_info.image_att[i],
+						      i);
+		if (rc != ECORE_SUCCESS) {
+			DP_ERR(p_hwfn,
+			       "Failed getting image index %d attributes\n",
+			       i);
+			goto err1;
+		}
+
+		DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "image index %d, size %x\n", i,
+			   nvm_info.image_att[i].len);
+	}
+out:
+	/* Update hwfn's nvm_info */
+	if (nvm_info.num_images) {
+		p_hwfn->nvm_info.num_images = nvm_info.num_images;
+		if (p_hwfn->nvm_info.image_att)
+			OSAL_FREE(p_hwfn->p_dev, p_hwfn->nvm_info.image_att);
+		p_hwfn->nvm_info.image_att = nvm_info.image_att;
+		p_hwfn->nvm_info.valid = true;
+	}
+
+	ecore_ptt_release(p_hwfn, p_ptt);
+	return ECORE_SUCCESS;
+
+err1:
+	OSAL_FREE(p_hwfn->p_dev, nvm_info.image_att);
+err0:
+	ecore_ptt_release(p_hwfn, p_ptt);
+	return rc;
+}
+
+enum _ecore_status_t
+ecore_mcp_get_nvm_image_att(struct ecore_hwfn *p_hwfn,
+			    enum ecore_nvm_images image_id,
+			    struct ecore_nvm_image_att *p_image_att)
+{
+	enum nvm_image_type type;
+	u32 i;
+
+	/* Translate image_id into MFW definitions */
+	switch (image_id) {
+	case ECORE_NVM_IMAGE_ISCSI_CFG:
+		type = NVM_TYPE_ISCSI_CFG;
+		break;
+	case ECORE_NVM_IMAGE_FCOE_CFG:
+		type = NVM_TYPE_FCOE_CFG;
+		break;
+	case ECORE_NVM_IMAGE_MDUMP:
+		type = NVM_TYPE_MDUMP;
+		break;
+	case ECORE_NVM_IMAGE_NVM_CFG1:
+		type = NVM_TYPE_NVM_CFG1;
+		break;
+	case ECORE_NVM_IMAGE_DEFAULT_CFG:
+		type = NVM_TYPE_DEFAULT_CFG;
+		break;
+	case ECORE_NVM_IMAGE_NVM_META:
+		type = NVM_TYPE_META;
+		break;
+	default:
+		DP_NOTICE(p_hwfn, false, "Unknown request of image_id %08x\n",
+			  image_id);
+		return ECORE_INVAL;
+	}
+
+	ecore_mcp_nvm_info_populate(p_hwfn);
+	for (i = 0; i < p_hwfn->nvm_info.num_images; i++) {
+		if (type == p_hwfn->nvm_info.image_att[i].image_type)
+			break;
+	}
+	if (i == p_hwfn->nvm_info.num_images) {
+		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
+			   "Failed to find nvram image of type %08x\n",
+			   image_id);
+		return ECORE_NOENT;
+	}
+
+	p_image_att->start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr;
+	p_image_att->length = p_hwfn->nvm_info.image_att[i].len;
+
+	return ECORE_SUCCESS;
+}
+
+enum _ecore_status_t ecore_mcp_get_nvm_image(struct ecore_hwfn *p_hwfn,
+					     enum ecore_nvm_images image_id,
+					     u8 *p_buffer, u32 buffer_len)
+{
+	struct ecore_nvm_image_att image_att;
+	enum _ecore_status_t rc;
+
+	OSAL_MEM_ZERO(p_buffer, buffer_len);
+
+	rc = ecore_mcp_get_nvm_image_att(p_hwfn, image_id, &image_att);
+	if (rc != ECORE_SUCCESS)
+		return rc;
+
+	/* Validate sizes - both the image's and the supplied buffer's */
+	if (image_att.length <= 4) {
+		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
+			   "Image [%d] is too small - only %d bytes\n",
+			   image_id, image_att.length);
+		return ECORE_INVAL;
+	}
+
+	if (image_att.length > buffer_len) {
+		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
+			   "Image [%d] is too big - %08x bytes where only %08x are available\n",
+			   image_id, image_att.length, buffer_len);
+		return ECORE_NOMEM;
+	}
+
+	return ecore_mcp_nvm_read(p_hwfn->p_dev, image_att.start_addr,
+				  (u8 *)p_buffer, image_att.length);
+}
+
 enum _ecore_status_t
 ecore_mcp_get_temperature_info(struct ecore_hwfn *p_hwfn,
 			       struct ecore_ptt *p_ptt,
diff --git a/drivers/net/qede/base/ecore_mcp_api.h b/drivers/net/qede/base/ecore_mcp_api.h
index dc889ab8e..53c130be7 100644
--- a/drivers/net/qede/base/ecore_mcp_api.h
+++ b/drivers/net/qede/base/ecore_mcp_api.h
@@ -121,6 +121,10 @@ struct ecore_mcp_function_info {
 enum ecore_nvm_images {
 	ECORE_NVM_IMAGE_ISCSI_CFG,
 	ECORE_NVM_IMAGE_FCOE_CFG,
+	ECORE_NVM_IMAGE_MDUMP,
+	ECORE_NVM_IMAGE_NVM_CFG1,
+	ECORE_NVM_IMAGE_DEFAULT_CFG,
+	ECORE_NVM_IMAGE_NVM_META,
 };
 #endif
 
@@ -970,6 +974,39 @@ enum _ecore_status_t ecore_mcp_phy_read(struct ecore_dev *p_dev, u32 cmd,
 enum _ecore_status_t ecore_mcp_nvm_read(struct ecore_dev *p_dev, u32 addr,
 			   u8 *p_buf, u32 len);
 
+struct ecore_nvm_image_att {
+	u32 start_addr;
+	u32 length;
+};
+
+/**
+ * @brief Allows reading a whole nvram image
+ *
+ * @param p_hwfn
+ * @param image_id - image to get attributes for
+ * @param p_image_att - image attributes structure into which to fill data
+ *
+ * @return enum _ecore_status_t - ECORE_SUCCESS - operation was successful.
+ */
+enum _ecore_status_t
+ecore_mcp_get_nvm_image_att(struct ecore_hwfn *p_hwfn,
+			    enum ecore_nvm_images image_id,
+			    struct ecore_nvm_image_att *p_image_att);
+
+/**
+ * @brief Allows reading a whole nvram image
+ *
+ * @param p_hwfn
+ * @param image_id - image requested for reading
+ * @param p_buffer - allocated buffer into which to fill data
+ * @param buffer_len - length of the allocated buffer.
+ *
+ * @return ECORE_SUCCESS iff p_buffer now contains the nvram image.
+ */
+enum _ecore_status_t ecore_mcp_get_nvm_image(struct ecore_hwfn *p_hwfn,
+					     enum ecore_nvm_images image_id,
+					     u8 *p_buffer, u32 buffer_len);
+
 /**
  * @brief - Sends an NVM write command request to the MFW with
  *          payload.
diff --git a/drivers/net/qede/base/ecore_status.h b/drivers/net/qede/base/ecore_status.h
index b893f1d41..01cf9fd31 100644
--- a/drivers/net/qede/base/ecore_status.h
+++ b/drivers/net/qede/base/ecore_status.h
@@ -8,6 +8,8 @@
 #define __ECORE_STATUS_H__
 
 enum _ecore_status_t {
+	ECORE_NOENT = -15,
+	ECORE_CONN_REFUSED = -14,
 	ECORE_CONN_RESET = -13,
 	ECORE_UNKNOWN_ERROR  = -12,
 	ECORE_NORESOURCES	 = -11,
diff --git a/drivers/net/qede/base/reg_addr.h b/drivers/net/qede/base/reg_addr.h
index 91d889dc8..c84d3865f 100644
--- a/drivers/net/qede/base/reg_addr.h
+++ b/drivers/net/qede/base/reg_addr.h
@@ -1245,3 +1245,849 @@
 #define DORQ_REG_VF_USAGE_CNT_LIM 0x1009ccUL
 #define PGLUE_B_REG_SR_IOV_DISABLED_REQUEST 0x2aa06cUL
 #define PGLUE_B_REG_SR_IOV_DISABLED_REQUEST_CLR 0x2aa070UL
+
+#define PSWRQ2_REG_ILT_MEMORY_SIZE_BB 15200
+#define PSWRQ2_REG_ILT_MEMORY_SIZE_K2 22000
+#define TSEM_REG_DBG_GPRE_VECT 0x1701410UL
+#define MSEM_REG_DBG_GPRE_VECT 0x1801410UL
+#define USEM_REG_DBG_GPRE_VECT 0x1901410UL
+#define XSEM_REG_DBG_GPRE_VECT 0x1401410UL
+#define YSEM_REG_DBG_GPRE_VECT 0x1501410UL
+#define PSEM_REG_DBG_GPRE_VECT 0x1601410UL
+#define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE 0x000748UL
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_WRITE_DISABLE (0x1UL << 0)
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_WRITE_DISABLE_SHIFT 0
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_READ_DISABLE (0x1UL << 1)
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_READ_DISABLE_SHIFT 1
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_INTERRUPT_DISABLE (0x1UL << 2)
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_INTERRUPT_DISABLE_SHIFT 2
+#define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE 0x00074cUL
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_STORE_DATA_DISABLE (0x1UL << 0)
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_STORE_DATA_DISABLE_SHIFT 0
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_LOAD_DATA_DISABLE (0x1UL << 1)
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_LOAD_DATA_DISABLE_SHIFT 1
+#define NWS_REG_NWS_CMU_K2 0x720000UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_7_0_K2 0x000680UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_15_8_K2 0x000684UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_7_0_K2 0x0006c0UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_11_8_K2 0x0006c4UL
+#define MS_REG_MS_CMU_K2 0x6a4000UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X132_K2 0x000210UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X133_K2 0x000214UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X130_K2 0x000208UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X131_K2 0x00020cUL
+#define PHY_PCIE_REG_PHY0_K2 0x620000UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2 0x000210UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2 0x000214UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2 0x000208UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2 0x00020cUL
+#define PHY_PCIE_REG_PHY1_K2 0x624000UL
+#define PCIE_REG_DBG_REPEAT_THRESHOLD_COUNT_K2 0x054364UL
+#define PCIE_REG_DBG_FW_TRIGGER_ENABLE_K2 0x05436cUL
+#define RDIF_REG_DEBUG_ERROR_INFO 0x300400UL
+#define RDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define RDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define TDIF_REG_DEBUG_ERROR_INFO 0x310400UL
+#define TDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define TDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define SEM_FAST_REG_VFC_STATUS 0x000b4cUL
+  #define SEM_FAST_REG_VFC_STATUS_RESPONSE_READY (0x1UL << 0)
+  #define SEM_FAST_REG_VFC_STATUS_RESPONSE_READY_SHIFT 0
+  #define SEM_FAST_REG_VFC_STATUS_VFC_BUSY (0x1UL << 1)
+  #define SEM_FAST_REG_VFC_STATUS_VFC_BUSY_SHIFT 1
+  #define SEM_FAST_REG_VFC_STATUS_SENDING_CMD_ON_GOING (0x1UL << 2)
+  #define SEM_FAST_REG_VFC_STATUS_SENDING_CMD_ON_GOING_SHIFT 2
+#define RSS_REG_RSS_RAM_DATA_SIZE 4
+#define BRB_REG_BIG_RAM_DATA_SIZE 64
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_1 0x0084c0UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_2 0x0084e4UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_3 0x008508UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_4 0x00852cUL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_5 0x008550UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_6 0x008574UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_7 0x008598UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_NIG 0x0085bcUL
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_PXP 0x0085e0UL
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_MCP_OUT_0 0x008628UL
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR 0x008748UL
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_SYS_KILL 0x008604UL
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO31_SHIFT 31
+#define DBG_REG_FULL_BUFFER_THR 0x01045cUL
+#define MISC_REG_AEU_MASK_ATTN_MCP 0x008498UL
+#define MISC_REG_AEU_SYS_KILL_BEHAVIOR 0x008800UL
+#define MISC_REG_AEU_GENERAL_MASK 0x008828UL
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_PXP_CLOSE_MASK (0x1UL << 0)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_PXP_CLOSE_MASK_SHIFT 0
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_NIG_CLOSE_MASK (0x1UL << 1)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_NIG_CLOSE_MASK_SHIFT 1
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_SYS_KILL_MASK (0x1UL << 2)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_SYS_KILL_MASK_SHIFT 2
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_GLB_UNC_ERR_MASK (0x1UL << 3)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_GLB_UNC_ERR_MASK_SHIFT 3
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 84d2d2c03..717b80839 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -7,7 +7,6 @@
 #include "qede_ethdev.h"
 #include <rte_string_fns.h>
 #include <rte_alarm.h>
-#include <rte_version.h>
 #include <rte_kvargs.h>
 
 /* Globals */
diff --git a/drivers/net/qede/qede_main.c b/drivers/net/qede/qede_main.c
index 02f70beb3..51aa639c6 100644
--- a/drivers/net/qede/qede_main.c
+++ b/drivers/net/qede/qede_main.c
@@ -5,7 +5,6 @@
  */
 
 #include <limits.h>
-#include <time.h>
 #include <rte_alarm.h>
 #include <rte_string_fns.h>
 
@@ -66,7 +65,7 @@ qed_probe(struct ecore_dev *edev, struct rte_pci_device *pci_dev,
 	hw_prepare_params.initiate_pf_flr = true;
 	hw_prepare_params.allow_mdump = false;
 	hw_prepare_params.b_en_pacing = false;
-	hw_prepare_params.epoch = (u32)time(NULL);
+	hw_prepare_params.epoch = OSAL_GET_EPOCH(ECORE_LEADING_HWFN(edev));
 	rc = ecore_hw_prepare(edev, &hw_prepare_params);
 	if (rc) {
 		DP_ERR(edev, "hw prepare failed\n");
-- 
2.18.0


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

* [dpdk-dev] [PATCH 3/4] net/qede: add infrastructure for debug data collection
  2020-06-28  5:58 [dpdk-dev] [PATCH 0/4] net/qede: add FW debug data collection support Rasesh Mody
  2020-06-28  5:58 ` [dpdk-dev] [PATCH 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
  2020-06-28  5:58 ` [dpdk-dev] [PATCH 2/4] net/qede/base: add changes for debug data collection Rasesh Mody
@ 2020-06-28  5:58 ` Rasesh Mody
  2020-06-28 12:29   ` Jerin Jacob
  2020-06-28  5:58 ` [dpdk-dev] [PATCH 4/4] net/qede: add support for get register operation Rasesh Mody
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Rasesh Mody @ 2020-06-28  5:58 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

The patch adds QEDE PMD ops and APIs to calculate the size and collect
the debug dump for various firmware components. The patch adds new files
qede_debug.[ch] that has all the firmware debug data collection
infrastructure changes.

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/qede/Makefile        |    4 +-
 drivers/net/qede/base/bcm_osal.h |    5 +-
 drivers/net/qede/qede_debug.c    | 8119 ++++++++++++++++++++++++++++++
 drivers/net/qede/qede_debug.h    |  759 +++
 drivers/net/qede/qede_if.h       |   45 +
 drivers/net/qede/qede_main.c     |   39 +-
 6 files changed, 8967 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/qede/qede_debug.c
 create mode 100644 drivers/net/qede/qede_debug.h

diff --git a/drivers/net/qede/Makefile b/drivers/net/qede/Makefile
index 5810b4d49..3b00338ff 100644
--- a/drivers/net/qede/Makefile
+++ b/drivers/net/qede/Makefile
@@ -11,7 +11,6 @@ include $(RTE_SDK)/mk/rte.vars.mk
 LIB = librte_pmd_qede.a
 
 CFLAGS += -O3
-CFLAGS += $(WERROR_FLAGS)
 LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
 LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs
 LDLIBS += -lrte_bus_pci
@@ -37,7 +36,6 @@ CFLAGS_BASE_DRIVER += -Wno-missing-prototypes
 
 ifneq ($(CONFIG_RTE_TOOLCHAIN_ICC),y)
 CFLAGS_BASE_DRIVER += -Wno-unused-value
-CFLAGS_BASE_DRIVER += -Wno-format-nonliteral
 ifeq ($(OS_TYPE),Linux)
 ifeq ($(shell clang -Wno-shift-negative-value -Werror -E - < /dev/null > /dev/null 2>&1; echo $$?),0)
 CFLAGS_BASE_DRIVER += -Wno-shift-negative-value
@@ -48,6 +46,7 @@ endif
 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
 ifeq ($(shell test $(GCC_VERSION) -ge 44 && echo 1), 1)
 CFLAGS_BASE_DRIVER += -Wno-unused-but-set-variable
+CFLAGS += -Wno-format-nonliteral
 endif
 CFLAGS_BASE_DRIVER += -Wno-missing-declarations
 ifeq ($(shell test $(GCC_VERSION) -ge 46 && echo 1), 1)
@@ -104,5 +103,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_ethdev.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_main.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_rxtx.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_filter.c
+SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_debug.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index 6ea3e7dda..b4b94231b 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -457,7 +457,10 @@ void qed_set_platform_str(struct ecore_hwfn *p_hwfn,
 #define OSAL_SET_PLATFORM_STR(p_hwfn, buf_str, buf_size) \
 	qed_set_platform_str(p_hwfn, buf_str, buf_size)
 #define OSAL_GET_EPOCH(p_hwfn) ((u32)time(NULL))
-#define OSAL_DBG_ALLOC_USER_DATA(p_hwfn, user_data_ptr) (0)
+enum dbg_status	qed_dbg_alloc_user_data(struct ecore_hwfn *p_hwfn,
+					void **user_data_ptr);
+#define OSAL_DBG_ALLOC_USER_DATA(p_hwfn, user_data_ptr) \
+	qed_dbg_alloc_user_data(p_hwfn, user_data_ptr)
 #define OSAL_DB_REC_OCCURRED(p_hwfn) nothing
 
 #endif /* __BCM_OSAL_H */
diff --git a/drivers/net/qede/qede_debug.c b/drivers/net/qede/qede_debug.c
new file mode 100644
index 000000000..6fedd8f9c
--- /dev/null
+++ b/drivers/net/qede/qede_debug.c
@@ -0,0 +1,8119 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Marvell Semiconductor Inc.
+ * All rights reserved.
+ * www.marvell.com
+ */
+
+#include <rte_common.h>
+#include "base/bcm_osal.h"
+#include "base/ecore.h"
+#include "base/ecore_cxt.h"
+#include "base/ecore_hsi_common.h"
+#include "base/ecore_hw.h"
+#include "base/ecore_mcp.h"
+#include "base/reg_addr.h"
+#include "qede_debug.h"
+
+/* Memory groups enum */
+enum mem_groups {
+	MEM_GROUP_PXP_MEM,
+	MEM_GROUP_DMAE_MEM,
+	MEM_GROUP_CM_MEM,
+	MEM_GROUP_QM_MEM,
+	MEM_GROUP_DORQ_MEM,
+	MEM_GROUP_BRB_RAM,
+	MEM_GROUP_BRB_MEM,
+	MEM_GROUP_PRS_MEM,
+	MEM_GROUP_SDM_MEM,
+	MEM_GROUP_PBUF,
+	MEM_GROUP_IOR,
+	MEM_GROUP_RAM,
+	MEM_GROUP_BTB_RAM,
+	MEM_GROUP_RDIF_CTX,
+	MEM_GROUP_TDIF_CTX,
+	MEM_GROUP_CFC_MEM,
+	MEM_GROUP_CONN_CFC_MEM,
+	MEM_GROUP_CAU_PI,
+	MEM_GROUP_CAU_MEM,
+	MEM_GROUP_CAU_MEM_EXT,
+	MEM_GROUP_PXP_ILT,
+	MEM_GROUP_MULD_MEM,
+	MEM_GROUP_BTB_MEM,
+	MEM_GROUP_IGU_MEM,
+	MEM_GROUP_IGU_MSIX,
+	MEM_GROUP_CAU_SB,
+	MEM_GROUP_BMB_RAM,
+	MEM_GROUP_BMB_MEM,
+	MEM_GROUP_TM_MEM,
+	MEM_GROUP_TASK_CFC_MEM,
+	MEM_GROUPS_NUM
+};
+
+/* Memory groups names */
+static const char * const s_mem_group_names[] = {
+	"PXP_MEM",
+	"DMAE_MEM",
+	"CM_MEM",
+	"QM_MEM",
+	"DORQ_MEM",
+	"BRB_RAM",
+	"BRB_MEM",
+	"PRS_MEM",
+	"SDM_MEM",
+	"PBUF",
+	"IOR",
+	"RAM",
+	"BTB_RAM",
+	"RDIF_CTX",
+	"TDIF_CTX",
+	"CFC_MEM",
+	"CONN_CFC_MEM",
+	"CAU_PI",
+	"CAU_MEM",
+	"CAU_MEM_EXT",
+	"PXP_ILT",
+	"MULD_MEM",
+	"BTB_MEM",
+	"IGU_MEM",
+	"IGU_MSIX",
+	"CAU_SB",
+	"BMB_RAM",
+	"BMB_MEM",
+	"TM_MEM",
+	"TASK_CFC_MEM",
+};
+
+/* Idle check conditions */
+
+static u32 cond5(const u32 *r, const u32 *imm)
+{
+	return ((r[0] & imm[0]) != imm[1]) && ((r[1] & imm[2]) != imm[3]);
+}
+
+static u32 cond7(const u32 *r, const u32 *imm)
+{
+	return ((r[0] >> imm[0]) & imm[1]) != imm[2];
+}
+
+static u32 cond6(const u32 *r, const u32 *imm)
+{
+	return (r[0] & imm[0]) != imm[1];
+}
+
+static u32 cond9(const u32 *r, const u32 *imm)
+{
+	return ((r[0] & imm[0]) >> imm[1]) !=
+		(((r[0] & imm[2]) >> imm[3]) | ((r[1] & imm[4]) << imm[5]));
+}
+
+static u32 cond10(const u32 *r, const u32 *imm)
+{
+	return ((r[0] & imm[0]) >> imm[1]) != (r[0] & imm[2]);
+}
+
+static u32 cond4(const u32 *r, const u32 *imm)
+{
+	return (r[0] & ~imm[0]) != imm[1];
+}
+
+static u32 cond0(const u32 *r, const u32 *imm)
+{
+	return (r[0] & ~r[1]) != imm[0];
+}
+
+static u32 cond1(const u32 *r, const u32 *imm)
+{
+	return r[0] != imm[0];
+}
+
+static u32 cond11(const u32 *r, const u32 *imm)
+{
+	return r[0] != r[1] && r[2] == imm[0];
+}
+
+static u32 cond12(const u32 *r, const u32 *imm)
+{
+	return r[0] != r[1] && r[2] > imm[0];
+}
+
+static u32 cond3(const u32 *r, const __rte_unused u32 *imm)
+{
+	return r[0] != r[1];
+}
+
+static u32 cond13(const u32 *r, const u32 *imm)
+{
+	return r[0] & imm[0];
+}
+
+static u32 cond8(const u32 *r, const u32 *imm)
+{
+	return r[0] < (r[1] - imm[0]);
+}
+
+static u32 cond2(const u32 *r, const u32 *imm)
+{
+	return r[0] > imm[0];
+}
+
+/* Array of Idle Check conditions */
+static u32(*cond_arr[]) (const u32 *r, const u32 *imm) = {
+	cond0,
+	cond1,
+	cond2,
+	cond3,
+	cond4,
+	cond5,
+	cond6,
+	cond7,
+	cond8,
+	cond9,
+	cond10,
+	cond11,
+	cond12,
+	cond13,
+};
+
+#define NUM_PHYS_BLOCKS 84
+
+#define NUM_DBG_RESET_REGS 8
+
+/******************************* Data Types **********************************/
+
+enum hw_types {
+	HW_TYPE_ASIC,
+	PLATFORM_RESERVED,
+	PLATFORM_RESERVED2,
+	PLATFORM_RESERVED3,
+	PLATFORM_RESERVED4,
+	MAX_HW_TYPES
+};
+
+/* CM context types */
+enum cm_ctx_types {
+	CM_CTX_CONN_AG,
+	CM_CTX_CONN_ST,
+	CM_CTX_TASK_AG,
+	CM_CTX_TASK_ST,
+	NUM_CM_CTX_TYPES
+};
+
+/* Debug bus frame modes */
+enum dbg_bus_frame_modes {
+	DBG_BUS_FRAME_MODE_4ST = 0,	/* 4 Storm dwords (no HW) */
+	DBG_BUS_FRAME_MODE_2ST_2HW = 1,	/* 2 Storm dwords, 2 HW dwords */
+	DBG_BUS_FRAME_MODE_1ST_3HW = 2,	/* 1 Storm dwords, 3 HW dwords */
+	DBG_BUS_FRAME_MODE_4HW = 3,	/* 4 HW dwords (no Storms) */
+	DBG_BUS_FRAME_MODE_8HW = 4,	/* 8 HW dwords (no Storms) */
+	DBG_BUS_NUM_FRAME_MODES
+};
+
+/* Chip constant definitions */
+struct chip_defs {
+	const char *name;
+	u32 num_ilt_pages;
+};
+
+/* HW type constant definitions */
+struct hw_type_defs {
+	const char *name;
+	u32 delay_factor;
+	u32 dmae_thresh;
+	u32 log_thresh;
+};
+
+/* RBC reset definitions */
+struct rbc_reset_defs {
+	u32 reset_reg_addr;
+	u32 reset_val[MAX_CHIP_IDS];
+};
+
+/* Storm constant definitions.
+ * Addresses are in bytes, sizes are in quad-regs.
+ */
+struct storm_defs {
+	char letter;
+	enum block_id sem_block_id;
+	enum dbg_bus_clients dbg_client_id[MAX_CHIP_IDS];
+	bool has_vfc;
+	u32 sem_fast_mem_addr;
+	u32 sem_frame_mode_addr;
+	u32 sem_slow_enable_addr;
+	u32 sem_slow_mode_addr;
+	u32 sem_slow_mode1_conf_addr;
+	u32 sem_sync_dbg_empty_addr;
+	u32 sem_gpre_vect_addr;
+	u32 cm_ctx_wr_addr;
+	u32 cm_ctx_rd_addr[NUM_CM_CTX_TYPES];
+	u32 cm_ctx_lid_sizes[MAX_CHIP_IDS][NUM_CM_CTX_TYPES];
+};
+
+/* Debug Bus Constraint operation constant definitions */
+struct dbg_bus_constraint_op_defs {
+	u8 hw_op_val;
+	bool is_cyclic;
+};
+
+/* Storm Mode definitions */
+struct storm_mode_defs {
+	const char *name;
+	bool is_fast_dbg;
+	u8 id_in_hw;
+	u32 src_disable_reg_addr;
+	u32 src_enable_val;
+	bool exists[MAX_CHIP_IDS];
+};
+
+struct grc_param_defs {
+	u32 default_val[MAX_CHIP_IDS];
+	u32 min;
+	u32 max;
+	bool is_preset;
+	bool is_persistent;
+	u32 exclude_all_preset_val;
+	u32 crash_preset_val[MAX_CHIP_IDS];
+};
+
+/* Address is in 128b units. Width is in bits. */
+struct rss_mem_defs {
+	const char *mem_name;
+	const char *type_name;
+	u32 addr;
+	u32 entry_width;
+	u32 num_entries[MAX_CHIP_IDS];
+};
+
+struct vfc_ram_defs {
+	const char *mem_name;
+	const char *type_name;
+	u32 base_row;
+	u32 num_rows;
+};
+
+struct big_ram_defs {
+	const char *instance_name;
+	enum mem_groups mem_group_id;
+	enum mem_groups ram_mem_group_id;
+	enum dbg_grc_params grc_param;
+	u32 addr_reg_addr;
+	u32 data_reg_addr;
+	u32 is_256b_reg_addr;
+	u32 is_256b_bit_offset[MAX_CHIP_IDS];
+	u32 ram_size[MAX_CHIP_IDS]; /* In dwords */
+};
+
+struct phy_defs {
+	const char *phy_name;
+
+	/* PHY base GRC address */
+	u32 base_addr;
+
+	/* Relative address of indirect TBUS address register (bits 0..7) */
+	u32 tbus_addr_lo_addr;
+
+	/* Relative address of indirect TBUS address register (bits 8..10) */
+	u32 tbus_addr_hi_addr;
+
+	/* Relative address of indirect TBUS data register (bits 0..7) */
+	u32 tbus_data_lo_addr;
+
+	/* Relative address of indirect TBUS data register (bits 8..11) */
+	u32 tbus_data_hi_addr;
+};
+
+/* Split type definitions */
+struct split_type_defs {
+	const char *name;
+};
+
+/******************************** Constants **********************************/
+
+#define BYTES_IN_DWORD			sizeof(u32)
+/* In the macros below, size and offset are specified in bits */
+#define CEIL_DWORDS(size)		DIV_ROUND_UP(size, 32)
+#define FIELD_BIT_OFFSET(type, field)	type ## _ ## field ## _ ## OFFSET
+#define FIELD_BIT_SIZE(type, field)	type ## _ ## field ## _ ## SIZE
+#define FIELD_DWORD_OFFSET(type, field) \
+	 (int)(FIELD_BIT_OFFSET(type, field) / 32)
+#define FIELD_DWORD_SHIFT(type, field)	(FIELD_BIT_OFFSET(type, field) % 32)
+#define FIELD_BIT_MASK(type, field) \
+	(((1 << FIELD_BIT_SIZE(type, field)) - 1) << \
+	 FIELD_DWORD_SHIFT(type, field))
+
+#define SET_VAR_FIELD(var, type, field, val) \
+	do { \
+		var[FIELD_DWORD_OFFSET(type, field)] &=	\
+		(~FIELD_BIT_MASK(type, field));	\
+		var[FIELD_DWORD_OFFSET(type, field)] |= \
+		(val) << FIELD_DWORD_SHIFT(type, field); \
+	} while (0)
+
+#define ARR_REG_WR(dev, ptt, addr, arr, arr_size) \
+	do { \
+		for (i = 0; i < (arr_size); i++) \
+			ecore_wr(dev, ptt, addr,	(arr)[i]); \
+	} while (0)
+
+#define DWORDS_TO_BYTES(dwords)		((dwords) * BYTES_IN_DWORD)
+#define BYTES_TO_DWORDS(bytes)		((bytes) / BYTES_IN_DWORD)
+
+/* extra lines include a signature line + optional latency events line */
+#define NUM_EXTRA_DBG_LINES(block) \
+	(GET_FIELD((block)->flags, DBG_BLOCK_CHIP_HAS_LATENCY_EVENTS) ? 2 : 1)
+#define NUM_DBG_LINES(block) \
+	((block)->num_of_dbg_bus_lines + NUM_EXTRA_DBG_LINES(block))
+
+#define USE_DMAE			true
+#define PROTECT_WIDE_BUS		true
+
+#define RAM_LINES_TO_DWORDS(lines)	((lines) * 2)
+#define RAM_LINES_TO_BYTES(lines) \
+	DWORDS_TO_BYTES(RAM_LINES_TO_DWORDS(lines))
+
+#define REG_DUMP_LEN_SHIFT		24
+#define MEM_DUMP_ENTRY_SIZE_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_dump_mem))
+
+#define IDLE_CHK_RULE_SIZE_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_rule))
+
+#define IDLE_CHK_RESULT_HDR_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_result_hdr))
+
+#define IDLE_CHK_RESULT_REG_HDR_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_result_reg_hdr))
+
+#define PAGE_MEM_DESC_SIZE_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct phys_mem_desc))
+
+#define IDLE_CHK_MAX_ENTRIES_SIZE	32
+
+/* The sizes and offsets below are specified in bits */
+#define VFC_CAM_CMD_STRUCT_SIZE		64
+#define VFC_CAM_CMD_ROW_OFFSET		48
+#define VFC_CAM_CMD_ROW_SIZE		9
+#define VFC_CAM_ADDR_STRUCT_SIZE	16
+#define VFC_CAM_ADDR_OP_OFFSET		0
+#define VFC_CAM_ADDR_OP_SIZE		4
+#define VFC_CAM_RESP_STRUCT_SIZE	256
+#define VFC_RAM_ADDR_STRUCT_SIZE	16
+#define VFC_RAM_ADDR_OP_OFFSET		0
+#define VFC_RAM_ADDR_OP_SIZE		2
+#define VFC_RAM_ADDR_ROW_OFFSET		2
+#define VFC_RAM_ADDR_ROW_SIZE		10
+#define VFC_RAM_RESP_STRUCT_SIZE	256
+
+#define VFC_CAM_CMD_DWORDS		CEIL_DWORDS(VFC_CAM_CMD_STRUCT_SIZE)
+#define VFC_CAM_ADDR_DWORDS		CEIL_DWORDS(VFC_CAM_ADDR_STRUCT_SIZE)
+#define VFC_CAM_RESP_DWORDS		CEIL_DWORDS(VFC_CAM_RESP_STRUCT_SIZE)
+#define VFC_RAM_CMD_DWORDS		VFC_CAM_CMD_DWORDS
+#define VFC_RAM_ADDR_DWORDS		CEIL_DWORDS(VFC_RAM_ADDR_STRUCT_SIZE)
+#define VFC_RAM_RESP_DWORDS		CEIL_DWORDS(VFC_RAM_RESP_STRUCT_SIZE)
+
+#define NUM_VFC_RAM_TYPES		4
+
+#define VFC_CAM_NUM_ROWS		512
+
+#define VFC_OPCODE_CAM_RD		14
+#define VFC_OPCODE_RAM_RD		0
+
+#define NUM_RSS_MEM_TYPES		5
+
+#define NUM_BIG_RAM_TYPES		3
+#define BIG_RAM_NAME_LEN		3
+
+#define NUM_PHY_TBUS_ADDRESSES		2048
+#define PHY_DUMP_SIZE_DWORDS		(NUM_PHY_TBUS_ADDRESSES / 2)
+
+#define RESET_REG_UNRESET_OFFSET	4
+
+#define STALL_DELAY_MS			500
+
+#define STATIC_DEBUG_LINE_DWORDS	9
+
+#define NUM_COMMON_GLOBAL_PARAMS	11
+
+#define MAX_RECURSION_DEPTH		10
+
+#define FW_IMG_MAIN			1
+
+#define REG_FIFO_ELEMENT_DWORDS		2
+#define REG_FIFO_DEPTH_ELEMENTS		32
+#define REG_FIFO_DEPTH_DWORDS \
+	(REG_FIFO_ELEMENT_DWORDS * REG_FIFO_DEPTH_ELEMENTS)
+
+#define IGU_FIFO_ELEMENT_DWORDS		4
+#define IGU_FIFO_DEPTH_ELEMENTS		64
+#define IGU_FIFO_DEPTH_DWORDS \
+	(IGU_FIFO_ELEMENT_DWORDS * IGU_FIFO_DEPTH_ELEMENTS)
+
+#define PROTECTION_OVERRIDE_ELEMENT_DWORDS	2
+#define PROTECTION_OVERRIDE_DEPTH_ELEMENTS	20
+#define PROTECTION_OVERRIDE_DEPTH_DWORDS \
+	(PROTECTION_OVERRIDE_DEPTH_ELEMENTS * \
+	 PROTECTION_OVERRIDE_ELEMENT_DWORDS)
+
+#define MCP_SPAD_TRACE_OFFSIZE_ADDR \
+	(MCP_REG_SCRATCH + \
+	 offsetof(struct static_init, sections[SPAD_SECTION_TRACE]))
+
+#define MAX_SW_PLTAFORM_STR_SIZE	64
+
+#define EMPTY_FW_VERSION_STR		"???_???_???_???"
+#define EMPTY_FW_IMAGE_STR		"???????????????"
+
+/***************************** Constant Arrays *******************************/
+
+/* Chip constant definitions array */
+static struct chip_defs s_chip_defs[MAX_CHIP_IDS] = {
+	{"bb", PSWRQ2_REG_ILT_MEMORY_SIZE_BB / 2},
+	{"ah", PSWRQ2_REG_ILT_MEMORY_SIZE_K2 / 2}
+};
+
+/* Storm constant definitions array */
+static struct storm_defs s_storm_defs[] = {
+	/* Tstorm */
+	{'T', BLOCK_TSEM,
+		{DBG_BUS_CLIENT_RBCT, DBG_BUS_CLIENT_RBCT},
+		true,
+		TSEM_REG_FAST_MEMORY,
+		TSEM_REG_DBG_FRAME_MODE, TSEM_REG_SLOW_DBG_ACTIVE,
+		TSEM_REG_SLOW_DBG_MODE, TSEM_REG_DBG_MODE1_CFG,
+		TSEM_REG_SYNC_DBG_EMPTY, TSEM_REG_DBG_GPRE_VECT,
+		TCM_REG_CTX_RBC_ACCS,
+		{TCM_REG_AGG_CON_CTX, TCM_REG_SM_CON_CTX, TCM_REG_AGG_TASK_CTX,
+		 TCM_REG_SM_TASK_CTX},
+		{{4, 16, 2, 4}, {4, 16, 2, 4} } /* {bb} {k2} */
+	},
+
+	/* Mstorm */
+	{'M', BLOCK_MSEM,
+		{DBG_BUS_CLIENT_RBCT, DBG_BUS_CLIENT_RBCM},
+		false,
+		MSEM_REG_FAST_MEMORY,
+		MSEM_REG_DBG_FRAME_MODE,
+		MSEM_REG_SLOW_DBG_ACTIVE,
+		MSEM_REG_SLOW_DBG_MODE,
+		MSEM_REG_DBG_MODE1_CFG,
+		MSEM_REG_SYNC_DBG_EMPTY,
+		MSEM_REG_DBG_GPRE_VECT,
+		MCM_REG_CTX_RBC_ACCS,
+		{MCM_REG_AGG_CON_CTX, MCM_REG_SM_CON_CTX, MCM_REG_AGG_TASK_CTX,
+		 MCM_REG_SM_TASK_CTX },
+		{{1, 10, 2, 7}, {1, 10, 2, 7} } /* {bb} {k2}*/
+	},
+
+	/* Ustorm */
+	{'U', BLOCK_USEM,
+		{DBG_BUS_CLIENT_RBCU, DBG_BUS_CLIENT_RBCU},
+		false,
+		USEM_REG_FAST_MEMORY,
+		USEM_REG_DBG_FRAME_MODE,
+		USEM_REG_SLOW_DBG_ACTIVE,
+		USEM_REG_SLOW_DBG_MODE,
+		USEM_REG_DBG_MODE1_CFG,
+		USEM_REG_SYNC_DBG_EMPTY,
+		USEM_REG_DBG_GPRE_VECT,
+		UCM_REG_CTX_RBC_ACCS,
+		{UCM_REG_AGG_CON_CTX, UCM_REG_SM_CON_CTX, UCM_REG_AGG_TASK_CTX,
+		 UCM_REG_SM_TASK_CTX},
+		{{2, 13, 3, 3}, {2, 13, 3, 3} } /* {bb} {k2} */
+	},
+
+	/* Xstorm */
+	{'X', BLOCK_XSEM,
+		{DBG_BUS_CLIENT_RBCX, DBG_BUS_CLIENT_RBCX},
+		false,
+		XSEM_REG_FAST_MEMORY,
+		XSEM_REG_DBG_FRAME_MODE,
+		XSEM_REG_SLOW_DBG_ACTIVE,
+		XSEM_REG_SLOW_DBG_MODE,
+		XSEM_REG_DBG_MODE1_CFG,
+		XSEM_REG_SYNC_DBG_EMPTY,
+		XSEM_REG_DBG_GPRE_VECT,
+		XCM_REG_CTX_RBC_ACCS,
+		{XCM_REG_AGG_CON_CTX, XCM_REG_SM_CON_CTX, 0, 0},
+		{{9, 15, 0, 0}, {9, 15,	0, 0} } /* {bb} {k2} */
+	},
+
+	/* Ystorm */
+	{'Y', BLOCK_YSEM,
+		{DBG_BUS_CLIENT_RBCX, DBG_BUS_CLIENT_RBCY},
+		false,
+		YSEM_REG_FAST_MEMORY,
+		YSEM_REG_DBG_FRAME_MODE,
+		YSEM_REG_SLOW_DBG_ACTIVE,
+		YSEM_REG_SLOW_DBG_MODE,
+		YSEM_REG_DBG_MODE1_CFG,
+		YSEM_REG_SYNC_DBG_EMPTY,
+		YSEM_REG_DBG_GPRE_VECT,
+		YCM_REG_CTX_RBC_ACCS,
+		{YCM_REG_AGG_CON_CTX, YCM_REG_SM_CON_CTX, YCM_REG_AGG_TASK_CTX,
+		 YCM_REG_SM_TASK_CTX},
+		{{2, 3, 2, 12}, {2, 3, 2, 12} } /* {bb} {k2} */
+	},
+
+	/* Pstorm */
+	{'P', BLOCK_PSEM,
+		{DBG_BUS_CLIENT_RBCS, DBG_BUS_CLIENT_RBCS},
+		true,
+		PSEM_REG_FAST_MEMORY,
+		PSEM_REG_DBG_FRAME_MODE,
+		PSEM_REG_SLOW_DBG_ACTIVE,
+		PSEM_REG_SLOW_DBG_MODE,
+		PSEM_REG_DBG_MODE1_CFG,
+		PSEM_REG_SYNC_DBG_EMPTY,
+		PSEM_REG_DBG_GPRE_VECT,
+		PCM_REG_CTX_RBC_ACCS,
+		{0, PCM_REG_SM_CON_CTX, 0, 0},
+		{{0, 10, 0, 0}, {0, 10, 0, 0} } /* {bb} {k2} */
+	},
+};
+
+static struct hw_type_defs s_hw_type_defs[] = {
+	/* HW_TYPE_ASIC */
+	{"asic", 1, 256, 32768},
+	{"reserved", 0, 0, 0},
+	{"reserved2", 0, 0, 0},
+	{"reserved3", 0, 0, 0}
+};
+
+static struct grc_param_defs s_grc_param_defs[] = {
+	/* DBG_GRC_PARAM_DUMP_TSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_MSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_USTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_XSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_YSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_REGS */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_RAM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PBUF */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_IOR */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_VFC */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_CM_CTX */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_ILT */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_RSS */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_CAU */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_QM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_MCP */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_DORQ */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_CFC */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_IGU */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_BRB */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_BTB */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_BMB */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_RESERVED1 */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_MULD */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PRS */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_DMAE */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_TM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_SDM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_DIF */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_STATIC */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_UNSTALL */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_RESERVED2 */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_MCP_TRACE_META_SIZE */
+	{{0, 0}, 1, 0xffffffff, false, true, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_EXCLUDE_ALL */
+	{{0, 0}, 0, 1, true, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_CRASH */
+	{{0, 0}, 0, 1, true, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_PARITY_SAFE */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_CM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PHY */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_NO_MCP */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_NO_FW_VER */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_RESERVED3 */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_MCP_HW_DUMP */
+	{{0, 1}, 0, 1, false, false, 0, {0, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_ILT_CDUC */
+	{{1, 1}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_ILT_CDUT */
+	{{1, 1}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_CAU_EXT */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} }
+};
+
+static struct rss_mem_defs s_rss_mem_defs[] = {
+	{"rss_mem_cid", "rss_cid", 0, 32,
+	 {256, 320} },
+
+	{"rss_mem_key_msb", "rss_key", 1024, 256,
+	 {128, 208} },
+
+	{"rss_mem_key_lsb", "rss_key", 2048, 64,
+	 {128, 208} },
+
+	{"rss_mem_info", "rss_info", 3072, 16,
+	 {128, 208} },
+
+	{"rss_mem_ind", "rss_ind", 4096, 16,
+	 {16384, 26624} }
+};
+
+static struct vfc_ram_defs s_vfc_ram_defs[] = {
+	{"vfc_ram_tt1", "vfc_ram", 0, 512},
+	{"vfc_ram_mtt2", "vfc_ram", 512, 128},
+	{"vfc_ram_stt2", "vfc_ram", 640, 32},
+	{"vfc_ram_ro_vect", "vfc_ram", 672, 32}
+};
+
+static struct big_ram_defs s_big_ram_defs[] = {
+	{"BRB", MEM_GROUP_BRB_MEM, MEM_GROUP_BRB_RAM, DBG_GRC_PARAM_DUMP_BRB,
+	 BRB_REG_BIG_RAM_ADDRESS, BRB_REG_BIG_RAM_DATA,
+	 MISC_REG_BLOCK_256B_EN, {0, 0},
+	 {153600, 180224} },
+
+	{"BTB", MEM_GROUP_BTB_MEM, MEM_GROUP_BTB_RAM, DBG_GRC_PARAM_DUMP_BTB,
+	 BTB_REG_BIG_RAM_ADDRESS, BTB_REG_BIG_RAM_DATA,
+	 MISC_REG_BLOCK_256B_EN, {0, 1},
+	 {92160, 117760} },
+
+	{"BMB", MEM_GROUP_BMB_MEM, MEM_GROUP_BMB_RAM, DBG_GRC_PARAM_DUMP_BMB,
+	 BMB_REG_BIG_RAM_ADDRESS, BMB_REG_BIG_RAM_DATA,
+	 MISCS_REG_BLOCK_256B_EN, {0, 0},
+	 {36864, 36864} }
+};
+
+static struct rbc_reset_defs s_rbc_reset_defs[] = {
+	{MISCS_REG_RESET_PL_HV,
+	 {0x0, 0x400} },
+	{MISC_REG_RESET_PL_PDA_VMAIN_1,
+	 {0x4404040, 0x4404040} },
+	{MISC_REG_RESET_PL_PDA_VMAIN_2,
+	 {0x7, 0x7c00007} },
+	{MISC_REG_RESET_PL_PDA_VAUX,
+	 {0x2, 0x2} },
+};
+
+static struct phy_defs s_phy_defs[] = {
+	{"nw_phy", NWS_REG_NWS_CMU_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_7_0_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_15_8_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_7_0_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_11_8_K2},
+	{"sgmii_phy", MS_REG_MS_CMU_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X132_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X133_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X130_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X131_K2},
+	{"pcie_phy0", PHY_PCIE_REG_PHY0_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2},
+	{"pcie_phy1", PHY_PCIE_REG_PHY1_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2},
+};
+
+static struct split_type_defs s_split_type_defs[] = {
+	/* SPLIT_TYPE_NONE */
+	{"eng"},
+
+	/* SPLIT_TYPE_PORT */
+	{"port"},
+
+	/* SPLIT_TYPE_PF */
+	{"pf"},
+
+	/* SPLIT_TYPE_PORT_PF */
+	{"port"},
+
+	/* SPLIT_TYPE_VF */
+	{"vf"}
+};
+
+/******************************** Variables *********************************/
+
+/**
+ * The version of the calling app
+ */
+static u32 s_app_ver;
+
+/**************************** Private Functions ******************************/
+
+/* Reads and returns a single dword from the specified unaligned buffer */
+static u32 qed_read_unaligned_dword(u8 *buf)
+{
+	u32 dword;
+
+	memcpy((u8 *)&dword, buf, sizeof(dword));
+	return dword;
+}
+
+/* Sets the value of the specified GRC param */
+static void qed_grc_set_param(struct ecore_hwfn *p_hwfn,
+			      enum dbg_grc_params grc_param, u32 val)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	dev_data->grc.param_val[grc_param] = val;
+}
+
+/* Returns the value of the specified GRC param */
+static u32 qed_grc_get_param(struct ecore_hwfn *p_hwfn,
+			     enum dbg_grc_params grc_param)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	return dev_data->grc.param_val[grc_param];
+}
+
+/* Initializes the GRC parameters */
+static void qed_dbg_grc_init_params(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	if (!dev_data->grc.params_initialized) {
+		qed_dbg_grc_set_params_default(p_hwfn);
+		dev_data->grc.params_initialized = 1;
+	}
+}
+
+/* Sets pointer and size for the specified binary buffer type */
+static void qed_set_dbg_bin_buf(struct ecore_hwfn *p_hwfn,
+				enum bin_dbg_buffer_type buf_type,
+				const u32 *ptr, u32 size)
+{
+	struct virt_mem_desc *buf = &p_hwfn->dbg_arrays[buf_type];
+
+	buf->ptr = (void *)(osal_uintptr_t)ptr;
+	buf->size = size;
+}
+
+/* Initializes debug data for the specified device */
+static enum dbg_status qed_dbg_dev_init(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 num_pfs = 0, max_pfs_per_port = 0;
+
+	if (dev_data->initialized)
+		return DBG_STATUS_OK;
+
+	/* Set chip */
+	if (ECORE_IS_K2(p_hwfn->p_dev)) {
+		dev_data->chip_id = CHIP_K2;
+		dev_data->mode_enable[MODE_K2] = 1;
+		dev_data->num_vfs = MAX_NUM_VFS_K2;
+		num_pfs = MAX_NUM_PFS_K2;
+		max_pfs_per_port = MAX_NUM_PFS_K2 / 2;
+	} else if (ECORE_IS_BB_B0(p_hwfn->p_dev)) {
+		dev_data->chip_id = CHIP_BB;
+		dev_data->mode_enable[MODE_BB] = 1;
+		dev_data->num_vfs = MAX_NUM_VFS_BB;
+		num_pfs = MAX_NUM_PFS_BB;
+		max_pfs_per_port = MAX_NUM_PFS_BB;
+	} else {
+		return DBG_STATUS_UNKNOWN_CHIP;
+	}
+
+	/* Set HW type */
+	dev_data->hw_type = HW_TYPE_ASIC;
+	dev_data->mode_enable[MODE_ASIC] = 1;
+
+	/* Set port mode */
+	switch (p_hwfn->p_dev->num_ports_in_engine) {
+	case 1:
+		dev_data->mode_enable[MODE_PORTS_PER_ENG_1] = 1;
+		break;
+	case 2:
+		dev_data->mode_enable[MODE_PORTS_PER_ENG_2] = 1;
+		break;
+	case 4:
+		dev_data->mode_enable[MODE_PORTS_PER_ENG_4] = 1;
+		break;
+	}
+
+	/* Set 100G mode */
+	if (ECORE_IS_CMT(p_hwfn->p_dev))
+		dev_data->mode_enable[MODE_100G] = 1;
+
+	/* Set number of ports */
+	if (dev_data->mode_enable[MODE_PORTS_PER_ENG_1] ||
+	    dev_data->mode_enable[MODE_100G])
+		dev_data->num_ports = 1;
+	else if (dev_data->mode_enable[MODE_PORTS_PER_ENG_2])
+		dev_data->num_ports = 2;
+	else if (dev_data->mode_enable[MODE_PORTS_PER_ENG_4])
+		dev_data->num_ports = 4;
+
+	/* Set number of PFs per port */
+	dev_data->num_pfs_per_port = OSAL_MIN_T(u32,
+						num_pfs / dev_data->num_ports,
+						max_pfs_per_port);
+
+	/* Initializes the GRC parameters */
+	qed_dbg_grc_init_params(p_hwfn);
+
+	dev_data->use_dmae = true;
+	dev_data->initialized = 1;
+
+	return DBG_STATUS_OK;
+}
+
+static const struct dbg_block *get_dbg_block(struct ecore_hwfn *p_hwfn,
+					     enum block_id block_id)
+{
+	const struct dbg_block *dbg_block;
+
+	dbg_block = p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS].ptr;
+	return dbg_block + block_id;
+}
+
+static const struct dbg_block_chip *qed_get_dbg_block_per_chip(struct ecore_hwfn
+							       *p_hwfn,
+							       enum block_id
+							       block_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	return (const struct dbg_block_chip *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS_CHIP_DATA].ptr +
+	    block_id * MAX_CHIP_IDS + dev_data->chip_id;
+}
+
+static const struct dbg_reset_reg *qed_get_dbg_reset_reg(struct ecore_hwfn
+							 *p_hwfn,
+							 u8 reset_reg_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	return (const struct dbg_reset_reg *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_RESET_REGS].ptr +
+	    reset_reg_id * MAX_CHIP_IDS + dev_data->chip_id;
+}
+
+/* Reads the FW info structure for the specified Storm from the chip,
+ * and writes it to the specified fw_info pointer.
+ */
+static void qed_read_storm_fw_info(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   u8 storm_id, struct fw_info *fw_info)
+{
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	struct fw_info_location fw_info_location;
+	u32 addr, i, *dest;
+
+	memset(&fw_info_location, 0, sizeof(fw_info_location));
+	memset(fw_info, 0, sizeof(*fw_info));
+
+	/* Read first the address that points to fw_info location.
+	 * The address is located in the last line of the Storm RAM.
+	 */
+	addr = storm->sem_fast_mem_addr + SEM_FAST_REG_INT_RAM +
+	    DWORDS_TO_BYTES(SEM_FAST_REG_INT_RAM_SIZE) -
+	    sizeof(fw_info_location);
+
+	dest = (u32 *)&fw_info_location;
+
+	for (i = 0; i < BYTES_TO_DWORDS(sizeof(fw_info_location));
+	     i++, addr += BYTES_IN_DWORD)
+		dest[i] = ecore_rd(p_hwfn, p_ptt, addr);
+
+	/* Read FW version info from Storm RAM */
+	if (fw_info_location.size > 0 && fw_info_location.size <=
+	    sizeof(*fw_info)) {
+		addr = fw_info_location.grc_addr;
+		dest = (u32 *)fw_info;
+		for (i = 0; i < BYTES_TO_DWORDS(fw_info_location.size);
+		     i++, addr += BYTES_IN_DWORD)
+			dest[i] = ecore_rd(p_hwfn, p_ptt, addr);
+	}
+}
+
+/* Dumps the specified string to the specified buffer.
+ * Returns the dumped size in bytes.
+ */
+static u32 qed_dump_str(char *dump_buf, bool dump, const char *str)
+{
+	if (dump)
+		strcpy(dump_buf, str);
+
+	return (u32)strlen(str) + 1;
+}
+
+/* Dumps zeros to align the specified buffer to dwords.
+ * Returns the dumped size in bytes.
+ */
+static u32 qed_dump_align(char *dump_buf, bool dump, u32 byte_offset)
+{
+	u8 offset_in_dword, align_size;
+
+	offset_in_dword = (u8)(byte_offset & 0x3);
+	align_size = offset_in_dword ? BYTES_IN_DWORD - offset_in_dword : 0;
+
+	if (dump && align_size)
+		memset(dump_buf, 0, align_size);
+
+	return align_size;
+}
+
+/* Writes the specified string param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_str_param(u32 *dump_buf,
+			      bool dump,
+			      const char *param_name, const char *param_val)
+{
+	char *char_buf = (char *)dump_buf;
+	u32 offset = 0;
+
+	/* Dump param name */
+	offset += qed_dump_str(char_buf + offset, dump, param_name);
+
+	/* Indicate a string param value */
+	if (dump)
+		*(char_buf + offset) = 1;
+	offset++;
+
+	/* Dump param value */
+	offset += qed_dump_str(char_buf + offset, dump, param_val);
+
+	/* Align buffer to next dword */
+	offset += qed_dump_align(char_buf + offset, dump, offset);
+
+	return BYTES_TO_DWORDS(offset);
+}
+
+/* Writes the specified numeric param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_num_param(u32 *dump_buf,
+			      bool dump, const char *param_name, u32 param_val)
+{
+	char *char_buf = (char *)dump_buf;
+	u32 offset = 0;
+
+	/* Dump param name */
+	offset += qed_dump_str(char_buf + offset, dump, param_name);
+
+	/* Indicate a numeric param value */
+	if (dump)
+		*(char_buf + offset) = 0;
+	offset++;
+
+	/* Align buffer to next dword */
+	offset += qed_dump_align(char_buf + offset, dump, offset);
+
+	/* Dump param value (and change offset from bytes to dwords) */
+	offset = BYTES_TO_DWORDS(offset);
+	if (dump)
+		*(dump_buf + offset) = param_val;
+	offset++;
+
+	return offset;
+}
+
+/* Reads the FW version and writes it as a param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_fw_ver_param(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf, bool dump)
+{
+	char fw_ver_str[16] = EMPTY_FW_VERSION_STR;
+	char fw_img_str[16] = EMPTY_FW_IMAGE_STR;
+	struct fw_info fw_info = { {0}, {0} };
+	u32 offset = 0;
+
+	if (dump && !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_FW_VER)) {
+		/* Read FW info from chip */
+		qed_read_fw_info(p_hwfn, p_ptt, &fw_info);
+
+		/* Create FW version/image strings */
+		if (snprintf(fw_ver_str, sizeof(fw_ver_str),
+			     "%d_%d_%d_%d", fw_info.ver.num.major,
+			     fw_info.ver.num.minor, fw_info.ver.num.rev,
+			     fw_info.ver.num.eng) < 0)
+			DP_NOTICE(p_hwfn, false,
+				  "Unexpected debug error: invalid FW version string\n");
+		switch (fw_info.ver.image_id) {
+		case FW_IMG_MAIN:
+			strcpy(fw_img_str, "main");
+			break;
+		default:
+			strcpy(fw_img_str, "unknown");
+			break;
+		}
+	}
+
+	/* Dump FW version, image and timestamp */
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "fw-version", fw_ver_str);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "fw-image", fw_img_str);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "fw-timestamp", fw_info.ver.timestamp);
+
+	return offset;
+}
+
+/* Reads the MFW version and writes it as a param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_mfw_ver_param(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  u32 *dump_buf, bool dump)
+{
+	char mfw_ver_str[16] = EMPTY_FW_VERSION_STR;
+
+	if (dump &&
+	    !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_FW_VER)) {
+		u32 global_section_offsize, global_section_addr, mfw_ver;
+		u32 public_data_addr, global_section_offsize_addr;
+
+		/* Find MCP public data GRC address. Needs to be ORed with
+		 * MCP_REG_SCRATCH due to a HW bug.
+		 */
+		public_data_addr = ecore_rd(p_hwfn,
+					  p_ptt,
+					  MISC_REG_SHARED_MEM_ADDR) |
+				   MCP_REG_SCRATCH;
+
+		/* Find MCP public global section offset */
+		global_section_offsize_addr = public_data_addr +
+					      offsetof(struct mcp_public_data,
+						       sections) +
+					      sizeof(offsize_t) * PUBLIC_GLOBAL;
+		global_section_offsize = ecore_rd(p_hwfn, p_ptt,
+						global_section_offsize_addr);
+		global_section_addr =
+			MCP_REG_SCRATCH +
+			(global_section_offsize & OFFSIZE_OFFSET_MASK) * 4;
+
+		/* Read MFW version from MCP public global section */
+		mfw_ver = ecore_rd(p_hwfn, p_ptt,
+				 global_section_addr +
+				 offsetof(struct public_global, mfw_ver));
+
+		/* Dump MFW version param */
+		if (snprintf(mfw_ver_str, sizeof(mfw_ver_str), "%d_%d_%d_%d",
+			     (u8)(mfw_ver >> 24), (u8)(mfw_ver >> 16),
+			     (u8)(mfw_ver >> 8), (u8)mfw_ver) < 0)
+			DP_NOTICE(p_hwfn, false,
+				  "Unexpected debug error: invalid MFW version string\n");
+	}
+
+	return qed_dump_str_param(dump_buf, dump, "mfw-version", mfw_ver_str);
+}
+
+/* Reads the chip revision from the chip and writes it as a param to the
+ * specified buffer. Returns the dumped size in dwords.
+ */
+static u32 qed_dump_chip_revision_param(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	char param_str[3] = "??";
+
+	if (dev_data->hw_type == HW_TYPE_ASIC) {
+		u32 chip_rev, chip_metal;
+
+		chip_rev = ecore_rd(p_hwfn, p_ptt, MISCS_REG_CHIP_REV);
+		chip_metal = ecore_rd(p_hwfn, p_ptt, MISCS_REG_CHIP_METAL);
+
+		param_str[0] = 'a' + (u8)chip_rev;
+		param_str[1] = '0' + (u8)chip_metal;
+	}
+
+	return qed_dump_str_param(dump_buf, dump, "chip-revision", param_str);
+}
+
+/* Writes a section header to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_section_hdr(u32 *dump_buf,
+				bool dump, const char *name, u32 num_params)
+{
+	return qed_dump_num_param(dump_buf, dump, name, num_params);
+}
+
+/* Writes the common global params to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_common_global_params(struct ecore_hwfn *p_hwfn,
+					 struct ecore_ptt *p_ptt,
+					 u32 *dump_buf,
+					 bool dump,
+					 u8 num_specific_global_params)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	char sw_platform_str[MAX_SW_PLTAFORM_STR_SIZE];
+	u32 offset = 0;
+	u8 num_params;
+
+	/* Fill platform string */
+	ecore_set_platform_str(p_hwfn, sw_platform_str,
+			       MAX_SW_PLTAFORM_STR_SIZE);
+
+	/* Dump global params section header */
+	num_params = NUM_COMMON_GLOBAL_PARAMS + num_specific_global_params +
+		(dev_data->chip_id == CHIP_BB ? 1 : 0);
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "global_params", num_params);
+
+	/* Store params */
+	offset += qed_dump_fw_ver_param(p_hwfn, p_ptt, dump_buf + offset, dump);
+	offset += qed_dump_mfw_ver_param(p_hwfn,
+					 p_ptt, dump_buf + offset, dump);
+	offset += qed_dump_chip_revision_param(p_hwfn,
+					       p_ptt, dump_buf + offset, dump);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "tools-version", TOOLS_VERSION);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump,
+				     "chip",
+				     s_chip_defs[dev_data->chip_id].name);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump,
+				     "platform",
+				     s_hw_type_defs[dev_data->hw_type].name);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "sw-platform", sw_platform_str);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "pci-func", p_hwfn->abs_pf_id);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "epoch", OSAL_GET_EPOCH(p_hwfn));
+	if (dev_data->chip_id == CHIP_BB)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "path",
+					     ECORE_PATH_ID(p_hwfn));
+
+	return offset;
+}
+
+/* Writes the "last" section (including CRC) to the specified buffer at the
+ * given offset. Returns the dumped size in dwords.
+ */
+static u32 qed_dump_last_section(u32 *dump_buf, u32 offset, bool dump)
+{
+	u32 start_offset = offset;
+
+	/* Dump CRC section header */
+	offset += qed_dump_section_hdr(dump_buf + offset, dump, "last", 0);
+
+	/* Calculate CRC32 and add it to the dword after the "last" section */
+	if (dump)
+		*(dump_buf + offset) = ~OSAL_CRC32(0xffffffff,
+					      (u8 *)dump_buf,
+					      DWORDS_TO_BYTES(offset));
+
+	offset++;
+
+	return offset - start_offset;
+}
+
+/* Update blocks reset state  */
+static void qed_update_blocks_reset_state(struct ecore_hwfn *p_hwfn,
+					  struct ecore_ptt *p_ptt)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 reg_val[NUM_DBG_RESET_REGS] = { 0 };
+	u8 rst_reg_id;
+	u32 blk_id;
+
+	/* Read reset registers */
+	for (rst_reg_id = 0; rst_reg_id < NUM_DBG_RESET_REGS; rst_reg_id++) {
+		const struct dbg_reset_reg *rst_reg;
+		bool rst_reg_removed;
+		u32 rst_reg_addr;
+
+		rst_reg = qed_get_dbg_reset_reg(p_hwfn, rst_reg_id);
+		rst_reg_removed = GET_FIELD(rst_reg->data,
+					    DBG_RESET_REG_IS_REMOVED);
+		rst_reg_addr = DWORDS_TO_BYTES(GET_FIELD(rst_reg->data,
+							 DBG_RESET_REG_ADDR));
+
+		if (!rst_reg_removed)
+			reg_val[rst_reg_id] = ecore_rd(p_hwfn, p_ptt,
+						     rst_reg_addr);
+	}
+
+	/* Check if blocks are in reset */
+	for (blk_id = 0; blk_id < NUM_PHYS_BLOCKS; blk_id++) {
+		const struct dbg_block_chip *blk;
+		bool has_rst_reg;
+		bool is_removed;
+
+		blk = qed_get_dbg_block_per_chip(p_hwfn, (enum block_id)blk_id);
+		is_removed = GET_FIELD(blk->flags, DBG_BLOCK_CHIP_IS_REMOVED);
+		has_rst_reg = GET_FIELD(blk->flags,
+					DBG_BLOCK_CHIP_HAS_RESET_REG);
+
+		if (!is_removed && has_rst_reg)
+			dev_data->block_in_reset[blk_id] =
+			    !(reg_val[blk->reset_reg_id] &
+			      OSAL_BIT(blk->reset_reg_bit_offset));
+	}
+}
+
+/* is_mode_match recursive function */
+static bool qed_is_mode_match_rec(struct ecore_hwfn *p_hwfn,
+				  u16 *modes_buf_offset, u8 rec_depth)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	const u8 *dbg_array;
+	bool arg1, arg2;
+	u8 tree_val;
+
+	if (rec_depth > MAX_RECURSION_DEPTH) {
+		DP_NOTICE(p_hwfn, false,
+			  "Unexpected error: is_mode_match_rec exceeded the max recursion depth. This is probably due to a corrupt init/debug buffer.\n");
+		return false;
+	}
+
+	/* Get next element from modes tree buffer */
+	dbg_array = p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr;
+	tree_val = dbg_array[(*modes_buf_offset)++];
+
+	switch (tree_val) {
+	case INIT_MODE_OP_NOT:
+		return !qed_is_mode_match_rec(p_hwfn,
+					      modes_buf_offset, rec_depth + 1);
+	case INIT_MODE_OP_OR:
+	case INIT_MODE_OP_AND:
+		arg1 = qed_is_mode_match_rec(p_hwfn,
+					     modes_buf_offset, rec_depth + 1);
+		arg2 = qed_is_mode_match_rec(p_hwfn,
+					     modes_buf_offset, rec_depth + 1);
+		return (tree_val == INIT_MODE_OP_OR) ? (arg1 ||
+							arg2) : (arg1 && arg2);
+	default:
+		return dev_data->mode_enable[tree_val - MAX_INIT_MODE_OPS] > 0;
+	}
+}
+
+/* Returns true if the mode (specified using modes_buf_offset) is enabled */
+static bool qed_is_mode_match(struct ecore_hwfn *p_hwfn, u16 *modes_buf_offset)
+{
+	return qed_is_mode_match_rec(p_hwfn, modes_buf_offset, 0);
+}
+
+/* Enable / disable the Debug block */
+static void qed_bus_enable_dbg_block(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt, bool enable)
+{
+	ecore_wr(p_hwfn, p_ptt, DBG_REG_DBG_BLOCK_ON, enable ? 1 : 0);
+}
+
+/* Resets the Debug block */
+static void qed_bus_reset_dbg_block(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt)
+{
+	u32 reset_reg_addr, old_reset_reg_val, new_reset_reg_val;
+	const struct dbg_reset_reg *reset_reg;
+	const struct dbg_block_chip *block;
+
+	block = qed_get_dbg_block_per_chip(p_hwfn, BLOCK_DBG);
+	reset_reg = qed_get_dbg_reset_reg(p_hwfn, block->reset_reg_id);
+	reset_reg_addr =
+	    DWORDS_TO_BYTES(GET_FIELD(reset_reg->data, DBG_RESET_REG_ADDR));
+
+	old_reset_reg_val = ecore_rd(p_hwfn, p_ptt, reset_reg_addr);
+	new_reset_reg_val =
+	    old_reset_reg_val & ~OSAL_BIT(block->reset_reg_bit_offset);
+
+	ecore_wr(p_hwfn, p_ptt, reset_reg_addr, new_reset_reg_val);
+	ecore_wr(p_hwfn, p_ptt, reset_reg_addr, old_reset_reg_val);
+}
+
+/* Enable / disable Debug Bus clients according to the specified mask
+ * (1 = enable, 0 = disable).
+ */
+static void qed_bus_enable_clients(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt, u32 client_mask)
+{
+	ecore_wr(p_hwfn, p_ptt, DBG_REG_CLIENT_ENABLE, client_mask);
+}
+
+static void qed_bus_config_dbg_line(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    enum block_id block_id,
+				    u8 line_id,
+				    u8 enable_mask,
+				    u8 right_shift,
+				    u8 force_valid_mask, u8 force_frame_mask)
+{
+	const struct dbg_block_chip *block =
+		qed_get_dbg_block_per_chip(p_hwfn, block_id);
+
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_select_reg_addr),
+		 line_id);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_dword_enable_reg_addr),
+		 enable_mask);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_shift_reg_addr),
+		 right_shift);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_force_valid_reg_addr),
+		 force_valid_mask);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_force_frame_reg_addr),
+		 force_frame_mask);
+}
+
+/* Disable debug bus in all blocks */
+static void qed_bus_disable_blocks(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_id;
+
+	/* Disable all blocks */
+	for (block_id = 0; block_id < MAX_BLOCK_ID; block_id++) {
+		const struct dbg_block_chip *block_per_chip =
+		    qed_get_dbg_block_per_chip(p_hwfn,
+					       (enum block_id)block_id);
+
+		if (GET_FIELD(block_per_chip->flags,
+			      DBG_BLOCK_CHIP_IS_REMOVED) ||
+		    dev_data->block_in_reset[block_id])
+			continue;
+
+		/* Disable debug bus */
+		if (GET_FIELD(block_per_chip->flags,
+			      DBG_BLOCK_CHIP_HAS_DBG_BUS)) {
+			u32 dbg_en_addr =
+				block_per_chip->dbg_dword_enable_reg_addr;
+			u16 modes_buf_offset =
+			    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+				      DBG_MODE_HDR_MODES_BUF_OFFSET);
+			bool eval_mode =
+			    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+
+			if (!eval_mode ||
+			    qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				ecore_wr(p_hwfn, p_ptt,
+				       DWORDS_TO_BYTES(dbg_en_addr),
+				       0);
+		}
+	}
+}
+
+/* Returns true if the specified entity (indicated by GRC param) should be
+ * included in the dump, false otherwise.
+ */
+static bool qed_grc_is_included(struct ecore_hwfn *p_hwfn,
+				enum dbg_grc_params grc_param)
+{
+	return qed_grc_get_param(p_hwfn, grc_param) > 0;
+}
+
+/* Returns the storm_id that matches the specified Storm letter,
+ * or MAX_DBG_STORMS if invalid storm letter.
+ */
+static enum dbg_storms qed_get_id_from_letter(char storm_letter)
+{
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++)
+		if (s_storm_defs[storm_id].letter == storm_letter)
+			return (enum dbg_storms)storm_id;
+
+	return MAX_DBG_STORMS;
+}
+
+/* Returns true of the specified Storm should be included in the dump, false
+ * otherwise.
+ */
+static bool qed_grc_is_storm_included(struct ecore_hwfn *p_hwfn,
+				      enum dbg_storms storm)
+{
+	return qed_grc_get_param(p_hwfn, (enum dbg_grc_params)storm) > 0;
+}
+
+/* Returns true if the specified memory should be included in the dump, false
+ * otherwise.
+ */
+static bool qed_grc_is_mem_included(struct ecore_hwfn *p_hwfn,
+				    enum block_id block_id, u8 mem_group_id)
+{
+	const struct dbg_block *block;
+	u8 i;
+
+	block = get_dbg_block(p_hwfn, block_id);
+
+	/* If the block is associated with a Storm, check Storm match */
+	if (block->associated_storm_letter) {
+		enum dbg_storms associated_storm_id =
+		    qed_get_id_from_letter(block->associated_storm_letter);
+
+		if (associated_storm_id == MAX_DBG_STORMS ||
+		    !qed_grc_is_storm_included(p_hwfn, associated_storm_id))
+			return false;
+	}
+
+	for (i = 0; i < NUM_BIG_RAM_TYPES; i++) {
+		struct big_ram_defs *big_ram = &s_big_ram_defs[i];
+
+		if (mem_group_id == big_ram->mem_group_id ||
+		    mem_group_id == big_ram->ram_mem_group_id)
+			return qed_grc_is_included(p_hwfn, big_ram->grc_param);
+	}
+
+	switch (mem_group_id) {
+	case MEM_GROUP_PXP_ILT:
+	case MEM_GROUP_PXP_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PXP);
+	case MEM_GROUP_RAM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_RAM);
+	case MEM_GROUP_PBUF:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PBUF);
+	case MEM_GROUP_CAU_MEM:
+	case MEM_GROUP_CAU_SB:
+	case MEM_GROUP_CAU_PI:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CAU);
+	case MEM_GROUP_CAU_MEM_EXT:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CAU_EXT);
+	case MEM_GROUP_QM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_QM);
+	case MEM_GROUP_CFC_MEM:
+	case MEM_GROUP_CONN_CFC_MEM:
+	case MEM_GROUP_TASK_CFC_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CFC) ||
+		       qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM_CTX);
+	case MEM_GROUP_DORQ_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DORQ);
+	case MEM_GROUP_IGU_MEM:
+	case MEM_GROUP_IGU_MSIX:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_IGU);
+	case MEM_GROUP_MULD_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MULD);
+	case MEM_GROUP_PRS_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PRS);
+	case MEM_GROUP_DMAE_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DMAE);
+	case MEM_GROUP_TM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_TM);
+	case MEM_GROUP_SDM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_SDM);
+	case MEM_GROUP_TDIF_CTX:
+	case MEM_GROUP_RDIF_CTX:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DIF);
+	case MEM_GROUP_CM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM);
+	case MEM_GROUP_IOR:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_IOR);
+	default:
+		return true;
+	}
+}
+
+/* Stalls all Storms */
+static void qed_grc_stall_storms(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt, bool stall)
+{
+	u32 reg_addr;
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		if (!qed_grc_is_storm_included(p_hwfn,
+					       (enum dbg_storms)storm_id))
+			continue;
+
+		reg_addr = s_storm_defs[storm_id].sem_fast_mem_addr +
+		    SEM_FAST_REG_STALL_0;
+		ecore_wr(p_hwfn, p_ptt, reg_addr, stall ? 1 : 0);
+	}
+
+	OSAL_MSLEEP(STALL_DELAY_MS);
+}
+
+/* Takes all blocks out of reset. If rbc_only is true, only RBC clients are
+ * taken out of reset.
+ */
+static void qed_grc_unreset_blocks(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt, bool rbc_only)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 chip_id = dev_data->chip_id;
+	u32 i;
+
+	/* Take RBCs out of reset */
+	for (i = 0; i < OSAL_ARRAY_SIZE(s_rbc_reset_defs); i++)
+		if (s_rbc_reset_defs[i].reset_val[dev_data->chip_id])
+			ecore_wr(p_hwfn,
+			       p_ptt,
+			       s_rbc_reset_defs[i].reset_reg_addr +
+			       RESET_REG_UNRESET_OFFSET,
+			       s_rbc_reset_defs[i].reset_val[chip_id]);
+
+	if (!rbc_only) {
+		u32 reg_val[NUM_DBG_RESET_REGS] = { 0 };
+		u8 reset_reg_id;
+		u32 block_id;
+
+		/* Fill reset regs values */
+		for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
+			bool is_removed, has_reset_reg, unreset_before_dump;
+			const struct dbg_block_chip *block;
+
+			block = qed_get_dbg_block_per_chip(p_hwfn,
+							   (enum block_id)
+							   block_id);
+			is_removed =
+			    GET_FIELD(block->flags, DBG_BLOCK_CHIP_IS_REMOVED);
+			has_reset_reg =
+			    GET_FIELD(block->flags,
+				      DBG_BLOCK_CHIP_HAS_RESET_REG);
+			unreset_before_dump =
+			    GET_FIELD(block->flags,
+				      DBG_BLOCK_CHIP_UNRESET_BEFORE_DUMP);
+
+			if (!is_removed && has_reset_reg && unreset_before_dump)
+				reg_val[block->reset_reg_id] |=
+				    OSAL_BIT(block->reset_reg_bit_offset);
+		}
+
+		/* Write reset registers */
+		for (reset_reg_id = 0; reset_reg_id < NUM_DBG_RESET_REGS;
+		     reset_reg_id++) {
+			const struct dbg_reset_reg *reset_reg;
+			u32 reset_reg_addr;
+
+			reset_reg = qed_get_dbg_reset_reg(p_hwfn, reset_reg_id);
+
+			if (GET_FIELD
+			    (reset_reg->data, DBG_RESET_REG_IS_REMOVED))
+				continue;
+
+			if (reg_val[reset_reg_id]) {
+				reset_reg_addr =
+				    GET_FIELD(reset_reg->data,
+					      DBG_RESET_REG_ADDR);
+				ecore_wr(p_hwfn,
+				       p_ptt,
+				       DWORDS_TO_BYTES(reset_reg_addr) +
+				       RESET_REG_UNRESET_OFFSET,
+				       reg_val[reset_reg_id]);
+			}
+		}
+	}
+}
+
+/* Returns the attention block data of the specified block */
+static const struct dbg_attn_block_type_data *
+qed_get_block_attn_data(struct ecore_hwfn *p_hwfn,
+			enum block_id block_id, enum dbg_attn_type attn_type)
+{
+	const struct dbg_attn_block *base_attn_block_arr =
+	    (const struct dbg_attn_block *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr;
+
+	return &base_attn_block_arr[block_id].per_type_data[attn_type];
+}
+
+/* Returns the attention registers of the specified block */
+static const struct dbg_attn_reg *
+qed_get_block_attn_regs(struct ecore_hwfn *p_hwfn,
+			enum block_id block_id, enum dbg_attn_type attn_type,
+			u8 *num_attn_regs)
+{
+	const struct dbg_attn_block_type_data *block_type_data =
+	    qed_get_block_attn_data(p_hwfn, block_id, attn_type);
+
+	*num_attn_regs = block_type_data->num_regs;
+
+	return (const struct dbg_attn_reg *)
+		p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr +
+		block_type_data->regs_offset;
+}
+
+/* For each block, clear the status of all parities */
+static void qed_grc_clear_all_prty(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	const struct dbg_attn_reg *attn_reg_arr;
+	u8 reg_idx, num_attn_regs;
+	u32 block_id;
+
+	for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
+		if (dev_data->block_in_reset[block_id])
+			continue;
+
+		attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
+						       (enum block_id)block_id,
+						       ATTN_TYPE_PARITY,
+						       &num_attn_regs);
+
+		for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
+			const struct dbg_attn_reg *reg_data =
+				&attn_reg_arr[reg_idx];
+			u16 modes_buf_offset;
+			bool eval_mode;
+
+			/* Check mode */
+			eval_mode = GET_FIELD(reg_data->mode.data,
+					      DBG_MODE_HDR_EVAL_MODE) > 0;
+			modes_buf_offset =
+				GET_FIELD(reg_data->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+
+			/* If Mode match: clear parity status */
+			if (!eval_mode ||
+			    qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				ecore_rd(p_hwfn, p_ptt,
+				    DWORDS_TO_BYTES(reg_data->sts_clr_address));
+		}
+	}
+}
+
+/* Dumps GRC registers section header. Returns the dumped size in dwords.
+ * the following parameters are dumped:
+ * - count: no. of dumped entries
+ * - split_type: split type
+ * - split_id: split ID (dumped only if split_id != SPLIT_TYPE_NONE)
+ * - reg_type_name: register type name (dumped only if reg_type_name != NULL)
+ */
+static u32 qed_grc_dump_regs_hdr(u32 *dump_buf,
+				 bool dump,
+				 u32 num_reg_entries,
+				 enum init_split_types split_type,
+				 u8 split_id, const char *reg_type_name)
+{
+	u8 num_params = 2 +
+	    (split_type != SPLIT_TYPE_NONE ? 1 : 0) + (reg_type_name ? 1 : 0);
+	u32 offset = 0;
+
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "grc_regs", num_params);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "count", num_reg_entries);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "split",
+				     s_split_type_defs[split_type].name);
+	if (split_type != SPLIT_TYPE_NONE)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "id", split_id);
+	if (reg_type_name)
+		offset += qed_dump_str_param(dump_buf + offset,
+					     dump, "type", reg_type_name);
+
+	return offset;
+}
+
+/* Reads the specified registers into the specified buffer.
+ * The addr and len arguments are specified in dwords.
+ */
+void qed_read_regs(struct ecore_hwfn *p_hwfn,
+		   struct ecore_ptt *p_ptt, u32 *buf, u32 addr, u32 len)
+{
+	u32 i;
+
+	for (i = 0; i < len; i++)
+		buf[i] = ecore_rd(p_hwfn, p_ptt, DWORDS_TO_BYTES(addr + i));
+}
+
+/* Dumps the GRC registers in the specified address range.
+ * Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_addr_range(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   u32 *dump_buf,
+				   bool dump, u32 addr, u32 len, bool wide_bus,
+				   enum init_split_types split_type,
+				   u8 split_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 port_id = 0, pf_id = 0, vf_id = 0, fid = 0;
+	bool read_using_dmae = false;
+	u32 thresh;
+
+	if (!dump)
+		return len;
+
+	switch (split_type) {
+	case SPLIT_TYPE_PORT:
+		port_id = split_id;
+		break;
+	case SPLIT_TYPE_PF:
+		pf_id = split_id;
+		break;
+	case SPLIT_TYPE_PORT_PF:
+		port_id = split_id / dev_data->num_pfs_per_port;
+		pf_id = port_id + dev_data->num_ports *
+		    (split_id % dev_data->num_pfs_per_port);
+		break;
+	case SPLIT_TYPE_VF:
+		vf_id = split_id;
+		break;
+	default:
+		break;
+	}
+
+	/* Try reading using DMAE */
+	if (dev_data->use_dmae && split_type != SPLIT_TYPE_VF &&
+	    (len >= s_hw_type_defs[dev_data->hw_type].dmae_thresh ||
+	     (PROTECT_WIDE_BUS && wide_bus))) {
+		struct dmae_params dmae_params;
+
+		/* Set DMAE params */
+		memset(&dmae_params, 0, sizeof(dmae_params));
+		SET_FIELD(dmae_params.flags, DMAE_PARAMS_COMPLETION_DST, 1);
+		switch (split_type) {
+		case SPLIT_TYPE_PORT:
+			SET_FIELD(dmae_params.flags, DMAE_PARAMS_PORT_VALID,
+				  1);
+			dmae_params.port_id = port_id;
+			break;
+		case SPLIT_TYPE_PF:
+			SET_FIELD(dmae_params.flags,
+				  DMAE_PARAMS_SRC_PF_VALID, 1);
+			dmae_params.src_pf_id = pf_id;
+			break;
+		case SPLIT_TYPE_PORT_PF:
+			SET_FIELD(dmae_params.flags, DMAE_PARAMS_PORT_VALID,
+				  1);
+			SET_FIELD(dmae_params.flags,
+				  DMAE_PARAMS_SRC_PF_VALID, 1);
+			dmae_params.port_id = port_id;
+			dmae_params.src_pf_id = pf_id;
+			break;
+		default:
+			break;
+		}
+
+		/* Execute DMAE command */
+		read_using_dmae = !ecore_dmae_grc2host(p_hwfn,
+						     p_ptt,
+						     DWORDS_TO_BYTES(addr),
+						     (u64)(uintptr_t)(dump_buf),
+						     len, &dmae_params);
+		if (!read_using_dmae) {
+			dev_data->use_dmae = 0;
+			DP_VERBOSE(p_hwfn->p_dev,
+				   ECORE_MSG_DEBUG,
+				   "Failed reading from chip using DMAE, using GRC instead\n");
+		}
+	}
+
+	if (read_using_dmae)
+		goto print_log;
+
+	/* If not read using DMAE, read using GRC */
+
+	/* Set pretend */
+	if (split_type != dev_data->pretend.split_type ||
+	    split_id != dev_data->pretend.split_id) {
+		switch (split_type) {
+		case SPLIT_TYPE_PORT:
+			ecore_port_pretend(p_hwfn, p_ptt, port_id);
+			break;
+		case SPLIT_TYPE_PF:
+			fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
+					  pf_id);
+			ecore_fid_pretend(p_hwfn, p_ptt, fid);
+			break;
+		case SPLIT_TYPE_PORT_PF:
+			fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
+					  pf_id);
+			ecore_port_fid_pretend(p_hwfn, p_ptt, port_id, fid);
+			break;
+		case SPLIT_TYPE_VF:
+			fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_VFVALID, 1)
+			      | FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_VFID,
+					  vf_id);
+			ecore_fid_pretend(p_hwfn, p_ptt, fid);
+			break;
+		default:
+			break;
+		}
+
+		dev_data->pretend.split_type = (u8)split_type;
+		dev_data->pretend.split_id = split_id;
+	}
+
+	/* Read registers using GRC */
+	qed_read_regs(p_hwfn, p_ptt, dump_buf, addr, len);
+
+print_log:
+	/* Print log */
+	dev_data->num_regs_read += len;
+	thresh = s_hw_type_defs[dev_data->hw_type].log_thresh;
+	if ((dev_data->num_regs_read / thresh) >
+	    ((dev_data->num_regs_read - len) / thresh))
+		DP_VERBOSE(p_hwfn->p_dev,
+			   ECORE_MSG_DEBUG,
+			   "Dumped %d registers...\n", dev_data->num_regs_read);
+
+	return len;
+}
+
+/* Dumps GRC registers sequence header. Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_reg_entry_hdr(u32 *dump_buf,
+				      bool dump, u32 addr, u32 len)
+{
+	if (dump)
+		*dump_buf = addr | (len << REG_DUMP_LEN_SHIFT);
+
+	return 1;
+}
+
+/* Dumps GRC registers sequence. Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_reg_entry(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  u32 *dump_buf,
+				  bool dump, u32 addr, u32 len, bool wide_bus,
+				  enum init_split_types split_type, u8 split_id)
+{
+	u32 offset = 0;
+
+	offset += qed_grc_dump_reg_entry_hdr(dump_buf, dump, addr, len);
+	offset += qed_grc_dump_addr_range(p_hwfn,
+					  p_ptt,
+					  dump_buf + offset,
+					  dump, addr, len, wide_bus,
+					  split_type, split_id);
+
+	return offset;
+}
+
+/* Dumps GRC registers sequence with skip cycle.
+ * Returns the dumped size in dwords.
+ * - addr:	start GRC address in dwords
+ * - total_len:	total no. of dwords to dump
+ * - read_len:	no. consecutive dwords to read
+ * - skip_len:	no. of dwords to skip (and fill with zeros)
+ */
+static u32 qed_grc_dump_reg_entry_skip(struct ecore_hwfn *p_hwfn,
+				       struct ecore_ptt *p_ptt,
+				       u32 *dump_buf,
+				       bool dump,
+				       u32 addr,
+				       u32 total_len,
+				       u32 read_len, u32 skip_len)
+{
+	u32 offset = 0, reg_offset = 0;
+
+	offset += qed_grc_dump_reg_entry_hdr(dump_buf, dump, addr, total_len);
+
+	if (!dump)
+		return offset + total_len;
+
+	while (reg_offset < total_len) {
+		u32 curr_len = OSAL_MIN_T(u32, read_len,
+					  total_len - reg_offset);
+
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  dump,  addr, curr_len, false,
+						  SPLIT_TYPE_NONE, 0);
+		reg_offset += curr_len;
+		addr += curr_len;
+
+		if (reg_offset < total_len) {
+			curr_len = OSAL_MIN_T(u32, skip_len,
+					      total_len - skip_len);
+			memset(dump_buf + offset, 0, DWORDS_TO_BYTES(curr_len));
+			offset += curr_len;
+			reg_offset += curr_len;
+			addr += curr_len;
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC registers entries. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_regs_entries(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     struct virt_mem_desc input_regs_arr,
+				     u32 *dump_buf,
+				     bool dump,
+				     enum init_split_types split_type,
+				     u8 split_id,
+				     bool block_enable[MAX_BLOCK_ID],
+				     u32 *num_dumped_reg_entries)
+{
+	u32 i, offset = 0, input_offset = 0;
+	bool mode_match = true;
+
+	*num_dumped_reg_entries = 0;
+
+	while (input_offset < BYTES_TO_DWORDS(input_regs_arr.size)) {
+		const struct dbg_dump_cond_hdr *cond_hdr =
+		    (const struct dbg_dump_cond_hdr *)
+		    input_regs_arr.ptr + input_offset++;
+		u16 modes_buf_offset;
+		bool eval_mode;
+
+		/* Check mode/block */
+		eval_mode = GET_FIELD(cond_hdr->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		if (eval_mode) {
+			modes_buf_offset =
+				GET_FIELD(cond_hdr->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			mode_match = qed_is_mode_match(p_hwfn,
+						       &modes_buf_offset);
+		}
+
+		if (!mode_match || !block_enable[cond_hdr->block_id]) {
+			input_offset += cond_hdr->data_size;
+			continue;
+		}
+
+		for (i = 0; i < cond_hdr->data_size; i++, input_offset++) {
+			const struct dbg_dump_reg *reg =
+			    (const struct dbg_dump_reg *)
+			    input_regs_arr.ptr + input_offset;
+			u32 addr, len;
+			bool wide_bus;
+
+			addr = GET_FIELD(reg->data, DBG_DUMP_REG_ADDRESS);
+			len = GET_FIELD(reg->data, DBG_DUMP_REG_LENGTH);
+			wide_bus = GET_FIELD(reg->data, DBG_DUMP_REG_WIDE_BUS);
+			offset += qed_grc_dump_reg_entry(p_hwfn,
+							 p_ptt,
+							 dump_buf + offset,
+							 dump,
+							 addr,
+							 len,
+							 wide_bus,
+							 split_type, split_id);
+			(*num_dumped_reg_entries)++;
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC registers entries. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_split_data(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   struct virt_mem_desc input_regs_arr,
+				   u32 *dump_buf,
+				   bool dump,
+				   bool block_enable[MAX_BLOCK_ID],
+				   enum init_split_types split_type,
+				   u8 split_id, const char *reg_type_name)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	enum init_split_types hdr_split_type = split_type;
+	u32 num_dumped_reg_entries, offset;
+	u8 hdr_split_id = split_id;
+
+	/* In PORT_PF split type, print a port split header */
+	if (split_type == SPLIT_TYPE_PORT_PF) {
+		hdr_split_type = SPLIT_TYPE_PORT;
+		hdr_split_id = split_id / dev_data->num_pfs_per_port;
+	}
+
+	/* Calculate register dump header size (and skip it for now) */
+	offset = qed_grc_dump_regs_hdr(dump_buf,
+				       false,
+				       0,
+				       hdr_split_type,
+				       hdr_split_id, reg_type_name);
+
+	/* Dump registers */
+	offset += qed_grc_dump_regs_entries(p_hwfn,
+					    p_ptt,
+					    input_regs_arr,
+					    dump_buf + offset,
+					    dump,
+					    split_type,
+					    split_id,
+					    block_enable,
+					    &num_dumped_reg_entries);
+
+	/* Write register dump header */
+	if (dump && num_dumped_reg_entries > 0)
+		qed_grc_dump_regs_hdr(dump_buf,
+				      dump,
+				      num_dumped_reg_entries,
+				      hdr_split_type,
+				      hdr_split_id, reg_type_name);
+
+	return num_dumped_reg_entries > 0 ? offset : 0;
+}
+
+/* Dumps registers according to the input registers array. Returns the dumped
+ * size in dwords.
+ */
+static u32 qed_grc_dump_registers(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  u32 *dump_buf,
+				  bool dump,
+				  bool block_enable[MAX_BLOCK_ID],
+				  const char *reg_type_name)
+{
+	struct virt_mem_desc *dbg_buf =
+	    &p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG];
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 offset = 0, input_offset = 0;
+
+	while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
+		const struct dbg_dump_split_hdr *split_hdr;
+		struct virt_mem_desc curr_input_regs_arr;
+		enum init_split_types split_type;
+		u16 split_count = 0;
+		u32 split_data_size;
+		u8 split_id;
+
+		split_hdr =
+		    (const struct dbg_dump_split_hdr *)
+		    dbg_buf->ptr + input_offset++;
+		split_type =
+		    GET_FIELD(split_hdr->hdr,
+			      DBG_DUMP_SPLIT_HDR_SPLIT_TYPE_ID);
+		split_data_size = GET_FIELD(split_hdr->hdr,
+					    DBG_DUMP_SPLIT_HDR_DATA_SIZE);
+		curr_input_regs_arr.ptr =
+		    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG].ptr +
+		    input_offset;
+		curr_input_regs_arr.size = DWORDS_TO_BYTES(split_data_size);
+
+		switch (split_type) {
+		case SPLIT_TYPE_NONE:
+			split_count = 1;
+			break;
+		case SPLIT_TYPE_PORT:
+			split_count = dev_data->num_ports;
+			break;
+		case SPLIT_TYPE_PF:
+		case SPLIT_TYPE_PORT_PF:
+			split_count = dev_data->num_ports *
+			    dev_data->num_pfs_per_port;
+			break;
+		case SPLIT_TYPE_VF:
+			split_count = dev_data->num_vfs;
+			break;
+		default:
+			return 0;
+		}
+
+		for (split_id = 0; split_id < split_count; split_id++)
+			offset += qed_grc_dump_split_data(p_hwfn, p_ptt,
+							  curr_input_regs_arr,
+							  dump_buf + offset,
+							  dump, block_enable,
+							  split_type,
+							  split_id,
+							  reg_type_name);
+
+		input_offset += split_data_size;
+	}
+
+	/* Cancel pretends (pretend to original PF) */
+	if (dump) {
+		ecore_fid_pretend(p_hwfn, p_ptt,
+				FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
+					    p_hwfn->rel_pf_id));
+		dev_data->pretend.split_type = SPLIT_TYPE_NONE;
+		dev_data->pretend.split_id = 0;
+	}
+
+	return offset;
+}
+
+/* Dump reset registers. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_reset_regs(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   u32 *dump_buf, bool dump)
+{
+	u32 offset = 0, num_regs = 0;
+	u8 reset_reg_id;
+
+	/* Calculate header size */
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					false,
+					0, SPLIT_TYPE_NONE, 0, "RESET_REGS");
+
+	/* Write reset registers */
+	for (reset_reg_id = 0; reset_reg_id < NUM_DBG_RESET_REGS;
+	     reset_reg_id++) {
+		const struct dbg_reset_reg *reset_reg;
+		u32 reset_reg_addr;
+
+		reset_reg = qed_get_dbg_reset_reg(p_hwfn, reset_reg_id);
+
+		if (GET_FIELD(reset_reg->data, DBG_RESET_REG_IS_REMOVED))
+			continue;
+
+		reset_reg_addr = GET_FIELD(reset_reg->data, DBG_RESET_REG_ADDR);
+		offset += qed_grc_dump_reg_entry(p_hwfn,
+						 p_ptt,
+						 dump_buf + offset,
+						 dump,
+						 reset_reg_addr,
+						 1, false, SPLIT_TYPE_NONE, 0);
+		num_regs++;
+	}
+
+	/* Write header */
+	if (dump)
+		qed_grc_dump_regs_hdr(dump_buf,
+				      true, num_regs, SPLIT_TYPE_NONE,
+				      0, "RESET_REGS");
+
+	return offset;
+}
+
+/* Dump registers that are modified during GRC Dump and therefore must be
+ * dumped first. Returns the dumped size in dwords.
+ */
+static u32 qed_grc_dump_modified_regs(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_id, offset = 0, stall_regs_offset;
+	const struct dbg_attn_reg *attn_reg_arr;
+	u8 storm_id, reg_idx, num_attn_regs;
+	u32 num_reg_entries = 0;
+
+	/* Write empty header for attention registers */
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					false,
+					0, SPLIT_TYPE_NONE, 0, "ATTN_REGS");
+
+	/* Write parity registers */
+	for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
+		if (dev_data->block_in_reset[block_id] && dump)
+			continue;
+
+		attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
+						       (enum block_id)block_id,
+						       ATTN_TYPE_PARITY,
+						       &num_attn_regs);
+
+		for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
+			const struct dbg_attn_reg *reg_data =
+				&attn_reg_arr[reg_idx];
+			u16 modes_buf_offset;
+			bool eval_mode;
+			u32 addr;
+
+			/* Check mode */
+			eval_mode = GET_FIELD(reg_data->mode.data,
+					      DBG_MODE_HDR_EVAL_MODE) > 0;
+			modes_buf_offset =
+				GET_FIELD(reg_data->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			if (eval_mode &&
+			    !qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				continue;
+
+			/* Mode match: read & dump registers */
+			addr = reg_data->mask_address;
+			offset += qed_grc_dump_reg_entry(p_hwfn,
+							 p_ptt,
+							 dump_buf + offset,
+							 dump,
+							 addr,
+							 1, false,
+							 SPLIT_TYPE_NONE, 0);
+			addr = GET_FIELD(reg_data->data,
+					 DBG_ATTN_REG_STS_ADDRESS);
+			offset += qed_grc_dump_reg_entry(p_hwfn,
+							 p_ptt,
+							 dump_buf + offset,
+							 dump,
+							 addr,
+							 1, false,
+							 SPLIT_TYPE_NONE, 0);
+			num_reg_entries += 2;
+		}
+	}
+
+	/* Overwrite header for attention registers */
+	if (dump)
+		qed_grc_dump_regs_hdr(dump_buf,
+				      true,
+				      num_reg_entries,
+				      SPLIT_TYPE_NONE, 0, "ATTN_REGS");
+
+	/* Write empty header for stall registers */
+	stall_regs_offset = offset;
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					false, 0, SPLIT_TYPE_NONE, 0, "REGS");
+
+	/* Write Storm stall status registers */
+	for (storm_id = 0, num_reg_entries = 0; storm_id < MAX_DBG_STORMS;
+	     storm_id++) {
+		struct storm_defs *storm = &s_storm_defs[storm_id];
+		u32 addr;
+
+		if (dev_data->block_in_reset[storm->sem_block_id] && dump)
+			continue;
+
+		addr =
+		    BYTES_TO_DWORDS(storm->sem_fast_mem_addr +
+				    SEM_FAST_REG_STALLED);
+		offset += qed_grc_dump_reg_entry(p_hwfn,
+						 p_ptt,
+						 dump_buf + offset,
+						 dump,
+						 addr,
+						 1,
+						 false, SPLIT_TYPE_NONE, 0);
+		num_reg_entries++;
+	}
+
+	/* Overwrite header for stall registers */
+	if (dump)
+		qed_grc_dump_regs_hdr(dump_buf + stall_regs_offset,
+				      true,
+				      num_reg_entries,
+				      SPLIT_TYPE_NONE, 0, "REGS");
+
+	return offset;
+}
+
+/* Dumps registers that can't be represented in the debug arrays */
+static u32 qed_grc_dump_special_regs(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     u32 *dump_buf, bool dump)
+{
+	u32 offset = 0, addr;
+
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					dump, 2, SPLIT_TYPE_NONE, 0, "REGS");
+
+	/* Dump R/TDIF_REG_DEBUG_ERROR_INFO_SIZE (every 8'th register should be
+	 * skipped).
+	 */
+	addr = BYTES_TO_DWORDS(RDIF_REG_DEBUG_ERROR_INFO);
+	offset += qed_grc_dump_reg_entry_skip(p_hwfn,
+					      p_ptt,
+					      dump_buf + offset,
+					      dump,
+					      addr,
+					      RDIF_REG_DEBUG_ERROR_INFO_SIZE,
+					      7,
+					      1);
+	addr = BYTES_TO_DWORDS(TDIF_REG_DEBUG_ERROR_INFO);
+	offset +=
+	    qed_grc_dump_reg_entry_skip(p_hwfn,
+					p_ptt,
+					dump_buf + offset,
+					dump,
+					addr,
+					TDIF_REG_DEBUG_ERROR_INFO_SIZE,
+					7,
+					1);
+
+	return offset;
+}
+
+/* Dumps a GRC memory header (section and params). Returns the dumped size in
+ * dwords. The following parameters are dumped:
+ * - name:	   dumped only if it's not NULL.
+ * - addr:	   in dwords, dumped only if name is NULL.
+ * - len:	   in dwords, always dumped.
+ * - width:	   dumped if it's not zero.
+ * - packed:	   dumped only if it's not false.
+ * - mem_group:	   always dumped.
+ * - is_storm:	   true only if the memory is related to a Storm.
+ * - storm_letter: valid only if is_storm is true.
+ *
+ */
+static u32 qed_grc_dump_mem_hdr(struct ecore_hwfn *p_hwfn,
+				u32 *dump_buf,
+				bool dump,
+				const char *name,
+				u32 addr,
+				u32 len,
+				u32 bit_width,
+				bool packed,
+				const char *mem_group, char storm_letter)
+{
+	u8 num_params = 3;
+	u32 offset = 0;
+	char buf[64];
+
+	if (!len)
+		DP_NOTICE(p_hwfn, false,
+			  "Unexpected GRC Dump error: dumped memory size must be non-zero\n");
+
+	if (bit_width)
+		num_params++;
+	if (packed)
+		num_params++;
+
+	/* Dump section header */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "grc_mem", num_params);
+
+	if (name) {
+		/* Dump name */
+		if (storm_letter) {
+			strcpy(buf, "?STORM_");
+			buf[0] = storm_letter;
+			strcpy(buf + strlen(buf), name);
+		} else {
+			strcpy(buf, name);
+		}
+
+		offset += qed_dump_str_param(dump_buf + offset,
+					     dump, "name", buf);
+	} else {
+		/* Dump address */
+		u32 addr_in_bytes = DWORDS_TO_BYTES(addr);
+
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "addr", addr_in_bytes);
+	}
+
+	/* Dump len */
+	offset += qed_dump_num_param(dump_buf + offset, dump, "len", len);
+
+	/* Dump bit width */
+	if (bit_width)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "width", bit_width);
+
+	/* Dump packed */
+	if (packed)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "packed", 1);
+
+	/* Dump reg type */
+	if (storm_letter) {
+		strcpy(buf, "?STORM_");
+		buf[0] = storm_letter;
+		strcpy(buf + strlen(buf), mem_group);
+	} else {
+		strcpy(buf, mem_group);
+	}
+
+	offset += qed_dump_str_param(dump_buf + offset, dump, "type", buf);
+
+	return offset;
+}
+
+/* Dumps a single GRC memory. If name is NULL, the memory is stored by address.
+ * Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_mem(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt,
+			    u32 *dump_buf,
+			    bool dump,
+			    const char *name,
+			    u32 addr,
+			    u32 len,
+			    bool wide_bus,
+			    u32 bit_width,
+			    bool packed,
+			    const char *mem_group, char storm_letter)
+{
+	u32 offset = 0;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       name,
+				       addr,
+				       len,
+				       bit_width,
+				       packed, mem_group, storm_letter);
+	offset += qed_grc_dump_addr_range(p_hwfn,
+					  p_ptt,
+					  dump_buf + offset,
+					  dump, addr, len, wide_bus,
+					  SPLIT_TYPE_NONE, 0);
+
+	return offset;
+}
+
+/* Dumps GRC memories entries. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_mem_entries(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    struct virt_mem_desc input_mems_arr,
+				    u32 *dump_buf, bool dump)
+{
+	u32 i, offset = 0, input_offset = 0;
+	bool mode_match = true;
+
+	while (input_offset < BYTES_TO_DWORDS(input_mems_arr.size)) {
+		const struct dbg_dump_cond_hdr *cond_hdr;
+		u16 modes_buf_offset;
+		u32 num_entries;
+		bool eval_mode;
+
+		cond_hdr =
+		    (const struct dbg_dump_cond_hdr *)input_mems_arr.ptr +
+		    input_offset++;
+		num_entries = cond_hdr->data_size / MEM_DUMP_ENTRY_SIZE_DWORDS;
+
+		/* Check required mode */
+		eval_mode = GET_FIELD(cond_hdr->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		if (eval_mode) {
+			modes_buf_offset =
+				GET_FIELD(cond_hdr->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			mode_match = qed_is_mode_match(p_hwfn,
+						       &modes_buf_offset);
+		}
+
+		if (!mode_match) {
+			input_offset += cond_hdr->data_size;
+			continue;
+		}
+
+		for (i = 0; i < num_entries;
+		     i++, input_offset += MEM_DUMP_ENTRY_SIZE_DWORDS) {
+			const struct dbg_dump_mem *mem =
+			    (const struct dbg_dump_mem *)((u32 *)
+							  input_mems_arr.ptr
+							  + input_offset);
+			const struct dbg_block *block;
+			char storm_letter = 0;
+			u32 mem_addr, mem_len;
+			bool mem_wide_bus;
+			u8 mem_group_id;
+
+			mem_group_id = GET_FIELD(mem->dword0,
+						 DBG_DUMP_MEM_MEM_GROUP_ID);
+			if (mem_group_id >= MEM_GROUPS_NUM) {
+				DP_NOTICE(p_hwfn, false, "Invalid mem_group_id\n");
+				return 0;
+			}
+
+			if (!qed_grc_is_mem_included(p_hwfn,
+						     (enum block_id)
+						     cond_hdr->block_id,
+						     mem_group_id))
+				continue;
+
+			mem_addr = GET_FIELD(mem->dword0, DBG_DUMP_MEM_ADDRESS);
+			mem_len = GET_FIELD(mem->dword1, DBG_DUMP_MEM_LENGTH);
+			mem_wide_bus = GET_FIELD(mem->dword1,
+						 DBG_DUMP_MEM_WIDE_BUS);
+
+			block = get_dbg_block(p_hwfn,
+					      cond_hdr->block_id);
+
+			/* If memory is associated with Storm,
+			 * update storm details
+			 */
+			if (block->associated_storm_letter)
+				storm_letter = block->associated_storm_letter;
+
+			/* Dump memory */
+			offset += qed_grc_dump_mem(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						NULL,
+						mem_addr,
+						mem_len,
+						mem_wide_bus,
+						0,
+						false,
+						s_mem_group_names[mem_group_id],
+						storm_letter);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC memories according to the input array dump_mem.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_grc_dump_memories(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf, bool dump)
+{
+	struct virt_mem_desc *dbg_buf =
+	    &p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_MEM];
+	u32 offset = 0, input_offset = 0;
+
+	while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
+		const struct dbg_dump_split_hdr *split_hdr;
+		struct virt_mem_desc curr_input_mems_arr;
+		enum init_split_types split_type;
+		u32 split_data_size;
+
+		split_hdr =
+		    (const struct dbg_dump_split_hdr *)dbg_buf->ptr +
+		    input_offset++;
+		split_type = GET_FIELD(split_hdr->hdr,
+				       DBG_DUMP_SPLIT_HDR_SPLIT_TYPE_ID);
+		split_data_size = GET_FIELD(split_hdr->hdr,
+					    DBG_DUMP_SPLIT_HDR_DATA_SIZE);
+		curr_input_mems_arr.ptr = (u32 *)dbg_buf->ptr + input_offset;
+		curr_input_mems_arr.size = DWORDS_TO_BYTES(split_data_size);
+
+		if (split_type == SPLIT_TYPE_NONE)
+			offset += qed_grc_dump_mem_entries(p_hwfn,
+							   p_ptt,
+							   curr_input_mems_arr,
+							   dump_buf + offset,
+							   dump);
+		else
+			DP_NOTICE(p_hwfn, false,
+				  "Dumping split memories is currently not supported\n");
+
+		input_offset += split_data_size;
+	}
+
+	return offset;
+}
+
+/* Dumps GRC context data for the specified Storm.
+ * Returns the dumped size in dwords.
+ * The lid_size argument is specified in quad-regs.
+ */
+static u32 qed_grc_dump_ctx_data(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf,
+				 bool dump,
+				 const char *name,
+				 u32 num_lids,
+				 enum cm_ctx_types ctx_type, u8 storm_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	u32 i, lid, lid_size, total_size;
+	u32 rd_reg_addr, offset = 0;
+
+	/* Convert quad-regs to dwords */
+	lid_size = storm->cm_ctx_lid_sizes[dev_data->chip_id][ctx_type] * 4;
+
+	if (!lid_size)
+		return 0;
+
+	total_size = num_lids * lid_size;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       name,
+				       0,
+				       total_size,
+				       lid_size * 32,
+				       false, name, storm->letter);
+
+	if (!dump)
+		return offset + total_size;
+
+	rd_reg_addr = BYTES_TO_DWORDS(storm->cm_ctx_rd_addr[ctx_type]);
+
+	/* Dump context data */
+	for (lid = 0; lid < num_lids; lid++) {
+		for (i = 0; i < lid_size; i++) {
+			ecore_wr(p_hwfn,
+			       p_ptt, storm->cm_ctx_wr_addr, (i << 9) | lid);
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  rd_reg_addr,
+							  1,
+							  false,
+							  SPLIT_TYPE_NONE, 0);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC contexts. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_ctx(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	u32 offset = 0;
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		if (!qed_grc_is_storm_included(p_hwfn,
+					       (enum dbg_storms)storm_id))
+			continue;
+
+		/* Dump Conn AG context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"CONN_AG_CTX",
+						NUM_OF_LCIDS,
+						CM_CTX_CONN_AG, storm_id);
+
+		/* Dump Conn ST context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"CONN_ST_CTX",
+						NUM_OF_LCIDS,
+						CM_CTX_CONN_ST, storm_id);
+
+		/* Dump Task AG context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"TASK_AG_CTX",
+						NUM_OF_LTIDS,
+						CM_CTX_TASK_AG, storm_id);
+
+		/* Dump Task ST context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"TASK_ST_CTX",
+						NUM_OF_LTIDS,
+						CM_CTX_TASK_ST, storm_id);
+	}
+
+	return offset;
+}
+
+#define VFC_STATUS_RESP_READY_BIT	0
+#define VFC_STATUS_BUSY_BIT		1
+#define VFC_STATUS_SENDING_CMD_BIT	2
+
+#define VFC_POLLING_DELAY_MS	1
+#define VFC_POLLING_COUNT		20
+
+/* Reads data from VFC. Returns the number of dwords read (0 on error).
+ * Sizes are specified in dwords.
+ */
+static u32 qed_grc_dump_read_from_vfc(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      struct storm_defs *storm,
+				      u32 *cmd_data,
+				      u32 cmd_size,
+				      u32 *addr_data,
+				      u32 addr_size,
+				      u32 resp_size, u32 *dump_buf)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 vfc_status, polling_ms, polling_count = 0, i;
+	u32 reg_addr, sem_base;
+	bool is_ready = false;
+
+	sem_base = storm->sem_fast_mem_addr;
+	polling_ms = VFC_POLLING_DELAY_MS *
+	    s_hw_type_defs[dev_data->hw_type].delay_factor;
+
+	/* Write VFC command */
+	ARR_REG_WR(p_hwfn,
+		   p_ptt,
+		   sem_base + SEM_FAST_REG_VFC_DATA_WR,
+		   cmd_data, cmd_size);
+
+	/* Write VFC address */
+	ARR_REG_WR(p_hwfn,
+		   p_ptt,
+		   sem_base + SEM_FAST_REG_VFC_ADDR,
+		   addr_data, addr_size);
+
+	/* Read response */
+	for (i = 0; i < resp_size; i++) {
+		/* Poll until ready */
+		do {
+			reg_addr = sem_base + SEM_FAST_REG_VFC_STATUS;
+			qed_grc_dump_addr_range(p_hwfn,
+						p_ptt,
+						&vfc_status,
+						true,
+						BYTES_TO_DWORDS(reg_addr),
+						1,
+						false, SPLIT_TYPE_NONE, 0);
+			is_ready = vfc_status &
+				   OSAL_BIT(VFC_STATUS_RESP_READY_BIT);
+
+			if (!is_ready) {
+				if (polling_count++ == VFC_POLLING_COUNT)
+					return 0;
+
+				OSAL_MSLEEP(polling_ms);
+			}
+		} while (!is_ready);
+
+		reg_addr = sem_base + SEM_FAST_REG_VFC_DATA_RD;
+		qed_grc_dump_addr_range(p_hwfn,
+					p_ptt,
+					dump_buf + i,
+					true,
+					BYTES_TO_DWORDS(reg_addr),
+					1, false, SPLIT_TYPE_NONE, 0);
+	}
+
+	return resp_size;
+}
+
+/* Dump VFC CAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_vfc_cam(struct ecore_hwfn *p_hwfn,
+				struct ecore_ptt *p_ptt,
+				u32 *dump_buf, bool dump, u8 storm_id)
+{
+	u32 total_size = VFC_CAM_NUM_ROWS * VFC_CAM_RESP_DWORDS;
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	u32 cam_addr[VFC_CAM_ADDR_DWORDS] = { 0 };
+	u32 cam_cmd[VFC_CAM_CMD_DWORDS] = { 0 };
+	u32 row, offset = 0;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       "vfc_cam",
+				       0,
+				       total_size,
+				       256,
+				       false, "vfc_cam", storm->letter);
+
+	if (!dump)
+		return offset + total_size;
+
+	/* Prepare CAM address */
+	SET_VAR_FIELD(cam_addr, VFC_CAM_ADDR, OP, VFC_OPCODE_CAM_RD);
+
+	/* Read VFC CAM data */
+	for (row = 0; row < VFC_CAM_NUM_ROWS; row++) {
+		SET_VAR_FIELD(cam_cmd, VFC_CAM_CMD, ROW, row);
+		offset += qed_grc_dump_read_from_vfc(p_hwfn,
+						     p_ptt,
+						     storm,
+						     cam_cmd,
+						     VFC_CAM_CMD_DWORDS,
+						     cam_addr,
+						     VFC_CAM_ADDR_DWORDS,
+						     VFC_CAM_RESP_DWORDS,
+						     dump_buf + offset);
+	}
+
+	return offset;
+}
+
+/* Dump VFC RAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_vfc_ram(struct ecore_hwfn *p_hwfn,
+				struct ecore_ptt *p_ptt,
+				u32 *dump_buf,
+				bool dump,
+				u8 storm_id, struct vfc_ram_defs *ram_defs)
+{
+	u32 total_size = ram_defs->num_rows * VFC_RAM_RESP_DWORDS;
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	u32 ram_addr[VFC_RAM_ADDR_DWORDS] = { 0 };
+	u32 ram_cmd[VFC_RAM_CMD_DWORDS] = { 0 };
+	u32 row, offset = 0;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       ram_defs->mem_name,
+				       0,
+				       total_size,
+				       256,
+				       false,
+				       ram_defs->type_name,
+				       storm->letter);
+
+	if (!dump)
+		return offset + total_size;
+
+	/* Prepare RAM address */
+	SET_VAR_FIELD(ram_addr, VFC_RAM_ADDR, OP, VFC_OPCODE_RAM_RD);
+
+	/* Read VFC RAM data */
+	for (row = ram_defs->base_row;
+	     row < ram_defs->base_row + ram_defs->num_rows; row++) {
+		SET_VAR_FIELD(ram_addr, VFC_RAM_ADDR, ROW, row);
+		offset += qed_grc_dump_read_from_vfc(p_hwfn,
+						     p_ptt,
+						     storm,
+						     ram_cmd,
+						     VFC_RAM_CMD_DWORDS,
+						     ram_addr,
+						     VFC_RAM_ADDR_DWORDS,
+						     VFC_RAM_RESP_DWORDS,
+						     dump_buf + offset);
+	}
+
+	return offset;
+}
+
+/* Dumps GRC VFC data. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_vfc(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	u8 storm_id, i;
+	u32 offset = 0;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		if (!qed_grc_is_storm_included(p_hwfn,
+					       (enum dbg_storms)storm_id) ||
+		    !s_storm_defs[storm_id].has_vfc)
+			continue;
+
+		/* Read CAM */
+		offset += qed_grc_dump_vfc_cam(p_hwfn,
+					       p_ptt,
+					       dump_buf + offset,
+					       dump, storm_id);
+
+		/* Read RAM */
+		for (i = 0; i < NUM_VFC_RAM_TYPES; i++)
+			offset += qed_grc_dump_vfc_ram(p_hwfn,
+						       p_ptt,
+						       dump_buf + offset,
+						       dump,
+						       storm_id,
+						       &s_vfc_ram_defs[i]);
+	}
+
+	return offset;
+}
+
+/* Dumps GRC RSS data. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_rss(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 offset = 0;
+	u8 rss_mem_id;
+
+	for (rss_mem_id = 0; rss_mem_id < NUM_RSS_MEM_TYPES; rss_mem_id++) {
+		u32 rss_addr, num_entries, total_dwords;
+		struct rss_mem_defs *rss_defs;
+		u32 addr, num_dwords_to_read;
+		bool packed;
+
+		rss_defs = &s_rss_mem_defs[rss_mem_id];
+		rss_addr = rss_defs->addr;
+		num_entries = rss_defs->num_entries[dev_data->chip_id];
+		total_dwords = (num_entries * rss_defs->entry_width) / 32;
+		packed = (rss_defs->entry_width == 16);
+
+		offset += qed_grc_dump_mem_hdr(p_hwfn,
+					       dump_buf + offset,
+					       dump,
+					       rss_defs->mem_name,
+					       0,
+					       total_dwords,
+					       rss_defs->entry_width,
+					       packed,
+					       rss_defs->type_name, 0);
+
+		/* Dump RSS data */
+		if (!dump) {
+			offset += total_dwords;
+			continue;
+		}
+
+		addr = BYTES_TO_DWORDS(RSS_REG_RSS_RAM_DATA);
+		while (total_dwords) {
+			num_dwords_to_read = OSAL_MIN_T(u32,
+						      RSS_REG_RSS_RAM_DATA_SIZE,
+						      total_dwords);
+			ecore_wr(p_hwfn, p_ptt, RSS_REG_RSS_RAM_ADDR, rss_addr);
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  addr,
+							  num_dwords_to_read,
+							  false,
+							  SPLIT_TYPE_NONE, 0);
+			total_dwords -= num_dwords_to_read;
+			rss_addr++;
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC Big RAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_big_ram(struct ecore_hwfn *p_hwfn,
+				struct ecore_ptt *p_ptt,
+				u32 *dump_buf, bool dump, u8 big_ram_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_size, ram_size, offset = 0, reg_val, i;
+	char mem_name[12] = "???_BIG_RAM";
+	char type_name[8] = "???_RAM";
+	struct big_ram_defs *big_ram;
+
+	big_ram = &s_big_ram_defs[big_ram_id];
+	ram_size = big_ram->ram_size[dev_data->chip_id];
+
+	reg_val = ecore_rd(p_hwfn, p_ptt, big_ram->is_256b_reg_addr);
+	block_size = reg_val &
+		     OSAL_BIT(big_ram->is_256b_bit_offset[dev_data->chip_id]) ?
+								     256 : 128;
+
+	strncpy(type_name, big_ram->instance_name, BIG_RAM_NAME_LEN);
+	strncpy(mem_name, big_ram->instance_name, BIG_RAM_NAME_LEN);
+
+	/* Dump memory header */
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       mem_name,
+				       0,
+				       ram_size,
+				       block_size * 8,
+				       false, type_name, 0);
+
+	/* Read and dump Big RAM data */
+	if (!dump)
+		return offset + ram_size;
+
+	/* Dump Big RAM */
+	for (i = 0; i < DIV_ROUND_UP(ram_size, BRB_REG_BIG_RAM_DATA_SIZE);
+	     i++) {
+		u32 addr, len;
+
+		ecore_wr(p_hwfn, p_ptt, big_ram->addr_reg_addr, i);
+		addr = BYTES_TO_DWORDS(big_ram->data_reg_addr);
+		len = BRB_REG_BIG_RAM_DATA_SIZE;
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  dump,
+						  addr,
+						  len,
+						  false, SPLIT_TYPE_NONE, 0);
+	}
+
+	return offset;
+}
+
+/* Dumps MCP scratchpad. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_mcp(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	bool block_enable[MAX_BLOCK_ID] = { 0 };
+	u32 offset = 0, addr;
+	bool halted = false;
+
+	/* Halt MCP */
+	if (dump && !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP)) {
+		halted = !ecore_mcp_halt(p_hwfn, p_ptt);
+		if (!halted)
+			DP_NOTICE(p_hwfn, false, "MCP halt failed!\n");
+	}
+
+	/* Dump MCP scratchpad */
+	offset += qed_grc_dump_mem(p_hwfn,
+				   p_ptt,
+				   dump_buf + offset,
+				   dump,
+				   NULL,
+				   BYTES_TO_DWORDS(MCP_REG_SCRATCH),
+				   MCP_REG_SCRATCH_SIZE,
+				   false, 0, false, "MCP", 0);
+
+	/* Dump MCP cpu_reg_file */
+	offset += qed_grc_dump_mem(p_hwfn,
+				   p_ptt,
+				   dump_buf + offset,
+				   dump,
+				   NULL,
+				   BYTES_TO_DWORDS(MCP_REG_CPU_REG_FILE),
+				   MCP_REG_CPU_REG_FILE_SIZE,
+				   false, 0, false, "MCP", 0);
+
+	/* Dump MCP registers */
+	block_enable[BLOCK_MCP] = true;
+	offset += qed_grc_dump_registers(p_hwfn,
+					 p_ptt,
+					 dump_buf + offset,
+					 dump, block_enable, "MCP");
+
+	/* Dump required non-MCP registers */
+	offset += qed_grc_dump_regs_hdr(dump_buf + offset,
+					dump, 1, SPLIT_TYPE_NONE, 0,
+					"MCP");
+	addr = BYTES_TO_DWORDS(MISC_REG_SHARED_MEM_ADDR);
+	offset += qed_grc_dump_reg_entry(p_hwfn,
+					 p_ptt,
+					 dump_buf + offset,
+					 dump,
+					 addr,
+					 1,
+					 false, SPLIT_TYPE_NONE, 0);
+
+	/* Release MCP */
+	if (halted && ecore_mcp_resume(p_hwfn, p_ptt))
+		DP_NOTICE(p_hwfn, false, "Failed to resume MCP after halt!\n");
+
+	return offset;
+}
+
+/* Dumps the tbus indirect memory for all PHYs.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_grc_dump_phy(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	u32 offset = 0, tbus_lo_offset, tbus_hi_offset;
+	char mem_name[32];
+	u8 phy_id;
+
+	for (phy_id = 0; phy_id < OSAL_ARRAY_SIZE(s_phy_defs); phy_id++) {
+		u32 addr_lo_addr, addr_hi_addr, data_lo_addr, data_hi_addr;
+		struct phy_defs *phy_defs;
+		u8 *bytes_buf;
+
+		phy_defs = &s_phy_defs[phy_id];
+		addr_lo_addr = phy_defs->base_addr +
+			       phy_defs->tbus_addr_lo_addr;
+		addr_hi_addr = phy_defs->base_addr +
+			       phy_defs->tbus_addr_hi_addr;
+		data_lo_addr = phy_defs->base_addr +
+			       phy_defs->tbus_data_lo_addr;
+		data_hi_addr = phy_defs->base_addr +
+			       phy_defs->tbus_data_hi_addr;
+
+		if (snprintf(mem_name, sizeof(mem_name), "tbus_%s",
+			     phy_defs->phy_name) < 0)
+			DP_NOTICE(p_hwfn, false,
+				  "Unexpected debug error: invalid PHY memory name\n");
+
+		offset += qed_grc_dump_mem_hdr(p_hwfn,
+					       dump_buf + offset,
+					       dump,
+					       mem_name,
+					       0,
+					       PHY_DUMP_SIZE_DWORDS,
+					       16, true, mem_name, 0);
+
+		if (!dump) {
+			offset += PHY_DUMP_SIZE_DWORDS;
+			continue;
+		}
+
+		bytes_buf = (u8 *)(dump_buf + offset);
+		for (tbus_hi_offset = 0;
+		     tbus_hi_offset < (NUM_PHY_TBUS_ADDRESSES >> 8);
+		     tbus_hi_offset++) {
+			ecore_wr(p_hwfn, p_ptt, addr_hi_addr, tbus_hi_offset);
+			for (tbus_lo_offset = 0; tbus_lo_offset < 256;
+			     tbus_lo_offset++) {
+				ecore_wr(p_hwfn,
+				       p_ptt, addr_lo_addr, tbus_lo_offset);
+				*(bytes_buf++) = (u8)ecore_rd(p_hwfn,
+							    p_ptt,
+							    data_lo_addr);
+				*(bytes_buf++) = (u8)ecore_rd(p_hwfn,
+							    p_ptt,
+							    data_hi_addr);
+			}
+		}
+
+		offset += PHY_DUMP_SIZE_DWORDS;
+	}
+
+	return offset;
+}
+
+static enum dbg_status qed_find_nvram_image(struct ecore_hwfn *p_hwfn,
+					    struct ecore_ptt *p_ptt,
+					    u32 image_type,
+					    u32 *nvram_offset_bytes,
+					    u32 *nvram_size_bytes);
+
+static enum dbg_status qed_nvram_read(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 nvram_offset_bytes,
+				      u32 nvram_size_bytes, u32 *ret_buf);
+
+/* Dumps the MCP HW dump from NVRAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_mcp_hw_dump(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    u32 *dump_buf, bool dump)
+{
+	u32 hw_dump_offset_bytes = 0, hw_dump_size_bytes = 0;
+	u32 hw_dump_size_dwords = 0, offset = 0;
+	enum dbg_status status;
+
+	/* Read HW dump image from NVRAM */
+	status = qed_find_nvram_image(p_hwfn,
+				      p_ptt,
+				      NVM_TYPE_HW_DUMP_OUT,
+				      &hw_dump_offset_bytes,
+				      &hw_dump_size_bytes);
+	if (status != DBG_STATUS_OK)
+		return 0;
+
+	hw_dump_size_dwords = BYTES_TO_DWORDS(hw_dump_size_bytes);
+
+	/* Dump HW dump image section */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "mcp_hw_dump", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", hw_dump_size_dwords);
+
+	/* Read MCP HW dump image into dump buffer */
+	if (dump && hw_dump_size_dwords) {
+		status = qed_nvram_read(p_hwfn,
+					p_ptt,
+					hw_dump_offset_bytes,
+					hw_dump_size_bytes, dump_buf + offset);
+		if (status != DBG_STATUS_OK) {
+			DP_NOTICE(p_hwfn, false,
+				  "Failed to read MCP HW Dump image from NVRAM\n");
+			return 0;
+		}
+	}
+	offset += hw_dump_size_dwords;
+
+	return offset;
+}
+
+/* Dumps Static Debug data. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_static_debug(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_id, line_id, offset = 0, addr, len;
+
+	/* Don't dump static debug if a debug bus recording is in progress */
+	if (dump && ecore_rd(p_hwfn, p_ptt, DBG_REG_DBG_BLOCK_ON))
+		return 0;
+
+	if (dump) {
+		/* Disable debug bus in all blocks */
+		qed_bus_disable_blocks(p_hwfn, p_ptt);
+
+		qed_bus_reset_dbg_block(p_hwfn, p_ptt);
+		ecore_wr(p_hwfn,
+		       p_ptt, DBG_REG_FRAMING_MODE, DBG_BUS_FRAME_MODE_8HW);
+		ecore_wr(p_hwfn,
+		       p_ptt, DBG_REG_DEBUG_TARGET, DBG_BUS_TARGET_ID_INT_BUF);
+		ecore_wr(p_hwfn, p_ptt, DBG_REG_FULL_MODE, 1);
+		qed_bus_enable_dbg_block(p_hwfn, p_ptt, true);
+	}
+
+	/* Dump all static debug lines for each relevant block */
+	for (block_id = 0; block_id < MAX_BLOCK_ID; block_id++) {
+		const struct dbg_block_chip *block_per_chip;
+		const struct dbg_block *block;
+		bool is_removed, has_dbg_bus;
+		u16 modes_buf_offset;
+		u32 block_dwords;
+
+		block_per_chip =
+		    qed_get_dbg_block_per_chip(p_hwfn, (enum block_id)block_id);
+		is_removed = GET_FIELD(block_per_chip->flags,
+				       DBG_BLOCK_CHIP_IS_REMOVED);
+		has_dbg_bus = GET_FIELD(block_per_chip->flags,
+					DBG_BLOCK_CHIP_HAS_DBG_BUS);
+
+		/* read+clear for NWS parity is not working, skip NWS block */
+		if (block_id == BLOCK_NWS)
+			continue;
+
+		if (!is_removed && has_dbg_bus &&
+		    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+			      DBG_MODE_HDR_EVAL_MODE) > 0) {
+			modes_buf_offset =
+			    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+				      DBG_MODE_HDR_MODES_BUF_OFFSET);
+			if (!qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				has_dbg_bus = false;
+		}
+
+		if (is_removed || !has_dbg_bus)
+			continue;
+
+		block_dwords = NUM_DBG_LINES(block_per_chip) *
+			       STATIC_DEBUG_LINE_DWORDS;
+
+		/* Dump static section params */
+		block = get_dbg_block(p_hwfn, (enum block_id)block_id);
+		offset += qed_grc_dump_mem_hdr(p_hwfn,
+					       dump_buf + offset,
+					       dump,
+					       (const char *)block->name,
+					       0,
+					       block_dwords,
+					       32, false, "STATIC", 0);
+
+		if (!dump) {
+			offset += block_dwords;
+			continue;
+		}
+
+		/* If all lines are invalid - dump zeros */
+		if (dev_data->block_in_reset[block_id]) {
+			memset(dump_buf + offset, 0,
+			       DWORDS_TO_BYTES(block_dwords));
+			offset += block_dwords;
+			continue;
+		}
+
+		/* Enable block's client */
+		qed_bus_enable_clients(p_hwfn,
+				       p_ptt,
+				       OSAL_BIT(block_per_chip->dbg_client_id));
+
+		addr = BYTES_TO_DWORDS(DBG_REG_CALENDAR_OUT_DATA);
+		len = STATIC_DEBUG_LINE_DWORDS;
+		for (line_id = 0; line_id < (u32)NUM_DBG_LINES(block_per_chip);
+		     line_id++) {
+			/* Configure debug line ID */
+			qed_bus_config_dbg_line(p_hwfn,
+						p_ptt,
+						(enum block_id)block_id,
+						(u8)line_id, 0xf, 0, 0, 0);
+
+			/* Read debug line info */
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  addr,
+							  len,
+							  true, SPLIT_TYPE_NONE,
+							  0);
+		}
+
+		/* Disable block's client and debug output */
+		qed_bus_enable_clients(p_hwfn, p_ptt, 0);
+		qed_bus_config_dbg_line(p_hwfn, p_ptt,
+					(enum block_id)block_id, 0, 0, 0, 0, 0);
+	}
+
+	if (dump) {
+		qed_bus_enable_dbg_block(p_hwfn, p_ptt, false);
+		qed_bus_enable_clients(p_hwfn, p_ptt, 0);
+	}
+
+	return offset;
+}
+
+/* Performs GRC Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static enum dbg_status qed_grc_dump(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    u32 *dump_buf,
+				    bool dump, u32 *num_dumped_dwords)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 dwords_read, offset = 0;
+	bool parities_masked = false;
+	u8 i;
+
+	*num_dumped_dwords = 0;
+	dev_data->num_regs_read = 0;
+
+	/* Update reset state */
+	if (dump)
+		qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 4);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "grc-dump");
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "num-lcids",
+				     NUM_OF_LCIDS);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "num-ltids",
+				     NUM_OF_LTIDS);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "num-ports", dev_data->num_ports);
+
+	/* Dump reset registers (dumped before taking blocks out of reset ) */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS))
+		offset += qed_grc_dump_reset_regs(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset, dump);
+
+	/* Take all blocks out of reset (using reset registers) */
+	if (dump) {
+		qed_grc_unreset_blocks(p_hwfn, p_ptt, false);
+		qed_update_blocks_reset_state(p_hwfn, p_ptt);
+	}
+
+	/* Disable all parities using MFW command */
+	if (dump &&
+	    !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP)) {
+		parities_masked = !ecore_mcp_mask_parities(p_hwfn, p_ptt, 1);
+		if (!parities_masked) {
+			DP_NOTICE(p_hwfn, false,
+				  "Failed to mask parities using MFW\n");
+			if (qed_grc_get_param
+			    (p_hwfn, DBG_GRC_PARAM_PARITY_SAFE))
+				return DBG_STATUS_MCP_COULD_NOT_MASK_PRTY;
+		}
+	}
+
+	/* Dump modified registers (dumped before modifying them) */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS))
+		offset += qed_grc_dump_modified_regs(p_hwfn,
+						     p_ptt,
+						     dump_buf + offset, dump);
+
+	/* Stall storms */
+	if (dump &&
+	    (qed_grc_is_included(p_hwfn,
+				 DBG_GRC_PARAM_DUMP_IOR) ||
+	     qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_VFC)))
+		qed_grc_stall_storms(p_hwfn, p_ptt, true);
+
+	/* Dump all regs  */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS)) {
+		bool block_enable[MAX_BLOCK_ID];
+
+		/* Dump all blocks except MCP */
+		for (i = 0; i < MAX_BLOCK_ID; i++)
+			block_enable[i] = true;
+		block_enable[BLOCK_MCP] = false;
+		offset += qed_grc_dump_registers(p_hwfn,
+						 p_ptt,
+						 dump_buf +
+						 offset,
+						 dump,
+						 block_enable, NULL);
+
+		/* Dump special registers */
+		offset += qed_grc_dump_special_regs(p_hwfn,
+						    p_ptt,
+						    dump_buf + offset, dump);
+	}
+
+	/* Dump memories */
+	offset += qed_grc_dump_memories(p_hwfn, p_ptt, dump_buf + offset, dump);
+
+	/* Dump MCP */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MCP))
+		offset += qed_grc_dump_mcp(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump context */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM_CTX))
+		offset += qed_grc_dump_ctx(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump RSS memories */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_RSS))
+		offset += qed_grc_dump_rss(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump Big RAM */
+	for (i = 0; i < NUM_BIG_RAM_TYPES; i++)
+		if (qed_grc_is_included(p_hwfn, s_big_ram_defs[i].grc_param))
+			offset += qed_grc_dump_big_ram(p_hwfn,
+						       p_ptt,
+						       dump_buf + offset,
+						       dump, i);
+
+	/* Dump VFC */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_VFC)) {
+		dwords_read = qed_grc_dump_vfc(p_hwfn,
+					       p_ptt, dump_buf + offset, dump);
+		offset += dwords_read;
+		if (!dwords_read)
+			return DBG_STATUS_VFC_READ_ERROR;
+	}
+
+	/* Dump PHY tbus */
+	if (qed_grc_is_included(p_hwfn,
+				DBG_GRC_PARAM_DUMP_PHY) && dev_data->chip_id ==
+	    CHIP_K2 && dev_data->hw_type == HW_TYPE_ASIC)
+		offset += qed_grc_dump_phy(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump MCP HW Dump */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MCP_HW_DUMP) &&
+	    !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP) && 1)
+		offset += qed_grc_dump_mcp_hw_dump(p_hwfn,
+						   p_ptt,
+						   dump_buf + offset, dump);
+
+	/* Dump static debug data (only if not during debug bus recording) */
+	if (qed_grc_is_included(p_hwfn,
+				DBG_GRC_PARAM_DUMP_STATIC) &&
+	    (!dump || dev_data->bus.state == DBG_BUS_STATE_IDLE))
+		offset += qed_grc_dump_static_debug(p_hwfn,
+						    p_ptt,
+						    dump_buf + offset, dump);
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	if (dump) {
+		/* Unstall storms */
+		if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_UNSTALL))
+			qed_grc_stall_storms(p_hwfn, p_ptt, false);
+
+		/* Clear parity status */
+		qed_grc_clear_all_prty(p_hwfn, p_ptt);
+
+		/* Enable all parities using MFW command */
+		if (parities_masked)
+			ecore_mcp_mask_parities(p_hwfn, p_ptt, 0);
+	}
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Writes the specified failing Idle Check rule to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_idle_chk_dump_failure(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     u32 *
+				     dump_buf,
+				     bool dump,
+				     u16 rule_id,
+				     const struct dbg_idle_chk_rule *rule,
+				     u16 fail_entry_id, u32 *cond_reg_values)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	const struct dbg_idle_chk_cond_reg *cond_regs;
+	const struct dbg_idle_chk_info_reg *info_regs;
+	u32 i, next_reg_offset = 0, offset = 0;
+	struct dbg_idle_chk_result_hdr *hdr;
+	const union dbg_idle_chk_reg *regs;
+	u8 reg_id;
+
+	hdr = (struct dbg_idle_chk_result_hdr *)dump_buf;
+	regs = (const union dbg_idle_chk_reg *)
+		p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr +
+		rule->reg_offset;
+	cond_regs = &regs[0].cond_reg;
+	info_regs = &regs[rule->num_cond_regs].info_reg;
+
+	/* Dump rule data */
+	if (dump) {
+		memset(hdr, 0, sizeof(*hdr));
+		hdr->rule_id = rule_id;
+		hdr->mem_entry_id = fail_entry_id;
+		hdr->severity = rule->severity;
+		hdr->num_dumped_cond_regs = rule->num_cond_regs;
+	}
+
+	offset += IDLE_CHK_RESULT_HDR_DWORDS;
+
+	/* Dump condition register values */
+	for (reg_id = 0; reg_id < rule->num_cond_regs; reg_id++) {
+		const struct dbg_idle_chk_cond_reg *reg = &cond_regs[reg_id];
+		struct dbg_idle_chk_result_reg_hdr *reg_hdr;
+
+		reg_hdr =
+		    (struct dbg_idle_chk_result_reg_hdr *)(dump_buf + offset);
+
+		/* Write register header */
+		if (!dump) {
+			offset += IDLE_CHK_RESULT_REG_HDR_DWORDS +
+			    reg->entry_size;
+			continue;
+		}
+
+		offset += IDLE_CHK_RESULT_REG_HDR_DWORDS;
+		memset(reg_hdr, 0, sizeof(*reg_hdr));
+		reg_hdr->start_entry = reg->start_entry;
+		reg_hdr->size = reg->entry_size;
+		SET_FIELD(reg_hdr->data,
+			  DBG_IDLE_CHK_RESULT_REG_HDR_IS_MEM,
+			  reg->num_entries > 1 || reg->start_entry > 0 ? 1 : 0);
+		SET_FIELD(reg_hdr->data,
+			  DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID, reg_id);
+
+		/* Write register values */
+		for (i = 0; i < reg_hdr->size; i++, next_reg_offset++, offset++)
+			dump_buf[offset] = cond_reg_values[next_reg_offset];
+	}
+
+	/* Dump info register values */
+	for (reg_id = 0; reg_id < rule->num_info_regs; reg_id++) {
+		const struct dbg_idle_chk_info_reg *reg = &info_regs[reg_id];
+		u32 block_id;
+
+		/* Check if register's block is in reset */
+		if (!dump) {
+			offset += IDLE_CHK_RESULT_REG_HDR_DWORDS + reg->size;
+			continue;
+		}
+
+		block_id = GET_FIELD(reg->data, DBG_IDLE_CHK_INFO_REG_BLOCK_ID);
+		if (block_id >= MAX_BLOCK_ID) {
+			DP_NOTICE(p_hwfn, false, "Invalid block_id\n");
+			return 0;
+		}
+
+		if (!dev_data->block_in_reset[block_id]) {
+			struct dbg_idle_chk_result_reg_hdr *reg_hdr;
+			bool wide_bus, eval_mode, mode_match = true;
+			u16 modes_buf_offset;
+			u32 addr;
+
+			reg_hdr = (struct dbg_idle_chk_result_reg_hdr *)
+				  (dump_buf + offset);
+
+			/* Check mode */
+			eval_mode = GET_FIELD(reg->mode.data,
+					      DBG_MODE_HDR_EVAL_MODE) > 0;
+			if (eval_mode) {
+				modes_buf_offset =
+				    GET_FIELD(reg->mode.data,
+					      DBG_MODE_HDR_MODES_BUF_OFFSET);
+				mode_match =
+					qed_is_mode_match(p_hwfn,
+							  &modes_buf_offset);
+			}
+
+			if (!mode_match)
+				continue;
+
+			addr = GET_FIELD(reg->data,
+					 DBG_IDLE_CHK_INFO_REG_ADDRESS);
+			wide_bus = GET_FIELD(reg->data,
+					     DBG_IDLE_CHK_INFO_REG_WIDE_BUS);
+
+			/* Write register header */
+			offset += IDLE_CHK_RESULT_REG_HDR_DWORDS;
+			hdr->num_dumped_info_regs++;
+			memset(reg_hdr, 0, sizeof(*reg_hdr));
+			reg_hdr->size = reg->size;
+			SET_FIELD(reg_hdr->data,
+				  DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID,
+				  rule->num_cond_regs + reg_id);
+
+			/* Write register values */
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  addr,
+							  reg->size, wide_bus,
+							  SPLIT_TYPE_NONE, 0);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps idle check rule entries. Returns the dumped size in dwords. */
+static u32
+qed_idle_chk_dump_rule_entries(struct ecore_hwfn *p_hwfn,
+			       struct ecore_ptt *p_ptt,
+			       u32 *dump_buf, bool dump,
+			       const struct dbg_idle_chk_rule *input_rules,
+			       u32 num_input_rules, u32 *num_failing_rules)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 cond_reg_values[IDLE_CHK_MAX_ENTRIES_SIZE];
+	u32 i, offset = 0;
+	u16 entry_id;
+	u8 reg_id;
+
+	*num_failing_rules = 0;
+
+	for (i = 0; i < num_input_rules; i++) {
+		const struct dbg_idle_chk_cond_reg *cond_regs;
+		const struct dbg_idle_chk_rule *rule;
+		const union dbg_idle_chk_reg *regs;
+		u16 num_reg_entries = 1;
+		bool check_rule = true;
+		const u32 *imm_values;
+
+		rule = &input_rules[i];
+		regs = (const union dbg_idle_chk_reg *)
+			p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr +
+			rule->reg_offset;
+		cond_regs = &regs[0].cond_reg;
+		imm_values =
+		    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_IMMS].ptr +
+		    rule->imm_offset;
+
+		/* Check if all condition register blocks are out of reset, and
+		 * find maximal number of entries (all condition registers that
+		 * are memories must have the same size, which is > 1).
+		 */
+		for (reg_id = 0; reg_id < rule->num_cond_regs && check_rule;
+		     reg_id++) {
+			u32 block_id =
+				GET_FIELD(cond_regs[reg_id].data,
+					  DBG_IDLE_CHK_COND_REG_BLOCK_ID);
+
+			if (block_id >= MAX_BLOCK_ID) {
+				DP_NOTICE(p_hwfn, false, "Invalid block_id\n");
+				return 0;
+			}
+
+			check_rule = !dev_data->block_in_reset[block_id];
+			if (cond_regs[reg_id].num_entries > num_reg_entries)
+				num_reg_entries = cond_regs[reg_id].num_entries;
+		}
+
+		if (!check_rule && dump)
+			continue;
+
+		if (!dump) {
+			u32 entry_dump_size =
+				qed_idle_chk_dump_failure(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  false,
+							  rule->rule_id,
+							  rule,
+							  0,
+							  NULL);
+
+			offset += num_reg_entries * entry_dump_size;
+			(*num_failing_rules) += num_reg_entries;
+			continue;
+		}
+
+		/* Go over all register entries (number of entries is the same
+		 * for all condition registers).
+		 */
+		for (entry_id = 0; entry_id < num_reg_entries; entry_id++) {
+			u32 next_reg_offset = 0;
+
+			/* Read current entry of all condition registers */
+			for (reg_id = 0; reg_id < rule->num_cond_regs;
+			     reg_id++) {
+				const struct dbg_idle_chk_cond_reg *reg =
+					&cond_regs[reg_id];
+				u32 padded_entry_size, addr;
+				bool wide_bus;
+
+				/* Find GRC address (if it's a memory, the
+				 * address of the specific entry is calculated).
+				 */
+				addr = GET_FIELD(reg->data,
+						 DBG_IDLE_CHK_COND_REG_ADDRESS);
+				wide_bus =
+				    GET_FIELD(reg->data,
+					      DBG_IDLE_CHK_COND_REG_WIDE_BUS);
+				if (reg->num_entries > 1 ||
+				    reg->start_entry > 0) {
+					padded_entry_size =
+					   reg->entry_size > 1 ?
+					   OSAL_ROUNDUP_POW_OF_TWO(reg->entry_size) :
+					   1;
+					addr += (reg->start_entry + entry_id) *
+						padded_entry_size;
+				}
+
+				/* Read registers */
+				if (next_reg_offset + reg->entry_size >=
+				    IDLE_CHK_MAX_ENTRIES_SIZE) {
+					DP_NOTICE(p_hwfn, false,
+						  "idle check registers entry is too large\n");
+					return 0;
+				}
+
+				next_reg_offset +=
+				    qed_grc_dump_addr_range(p_hwfn, p_ptt,
+							    cond_reg_values +
+							    next_reg_offset,
+							    dump, addr,
+							    reg->entry_size,
+							    wide_bus,
+							    SPLIT_TYPE_NONE, 0);
+			}
+
+			/* Call rule condition function.
+			 * If returns true, it's a failure.
+			 */
+			if ((*cond_arr[rule->cond_id]) (cond_reg_values,
+							imm_values)) {
+				offset += qed_idle_chk_dump_failure(p_hwfn,
+							p_ptt,
+							dump_buf + offset,
+							dump,
+							rule->rule_id,
+							rule,
+							entry_id,
+							cond_reg_values);
+				(*num_failing_rules)++;
+			}
+		}
+	}
+
+	return offset;
+}
+
+/* Performs Idle Check Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+			     struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	struct virt_mem_desc *dbg_buf =
+	    &p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_RULES];
+	u32 num_failing_rules_offset, offset = 0,
+	    input_offset = 0, num_failing_rules = 0;
+
+	/* Dump global params  - 1 must match below amount of params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "idle-chk");
+
+	/* Dump idle check section header with a single parameter */
+	offset += qed_dump_section_hdr(dump_buf + offset, dump, "idle_chk", 1);
+	num_failing_rules_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "num_rules", 0);
+
+	while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
+		const struct dbg_idle_chk_cond_hdr *cond_hdr =
+		    (const struct dbg_idle_chk_cond_hdr *)dbg_buf->ptr +
+		    input_offset++;
+		bool eval_mode, mode_match = true;
+		u32 curr_failing_rules;
+		u16 modes_buf_offset;
+
+		/* Check mode */
+		eval_mode = GET_FIELD(cond_hdr->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		if (eval_mode) {
+			modes_buf_offset =
+				GET_FIELD(cond_hdr->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			mode_match = qed_is_mode_match(p_hwfn,
+						       &modes_buf_offset);
+		}
+
+		if (mode_match) {
+			const struct dbg_idle_chk_rule *rule =
+			    (const struct dbg_idle_chk_rule *)((u32 *)
+							       dbg_buf->ptr
+							       + input_offset);
+			u32 num_input_rules =
+				cond_hdr->data_size / IDLE_CHK_RULE_SIZE_DWORDS;
+			offset +=
+			    qed_idle_chk_dump_rule_entries(p_hwfn,
+							   p_ptt,
+							   dump_buf +
+							   offset,
+							   dump,
+							   rule,
+							   num_input_rules,
+							   &curr_failing_rules);
+			num_failing_rules += curr_failing_rules;
+		}
+
+		input_offset += cond_hdr->data_size;
+	}
+
+	/* Overwrite num_rules parameter */
+	if (dump)
+		qed_dump_num_param(dump_buf + num_failing_rules_offset,
+				   dump, "num_rules", num_failing_rules);
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	return offset;
+}
+
+/* Finds the meta data image in NVRAM */
+static enum dbg_status qed_find_nvram_image(struct ecore_hwfn *p_hwfn,
+					    struct ecore_ptt *p_ptt,
+					    u32 image_type,
+					    u32 *nvram_offset_bytes,
+					    u32 *nvram_size_bytes)
+{
+	u32 ret_mcp_resp, ret_mcp_param, ret_txn_size;
+	struct mcp_file_att file_att;
+	int nvm_result;
+
+	/* Call NVRAM get file command */
+	nvm_result = ecore_mcp_nvm_rd_cmd(p_hwfn,
+					p_ptt,
+					DRV_MSG_CODE_NVM_GET_FILE_ATT,
+					image_type,
+					&ret_mcp_resp,
+					&ret_mcp_param,
+					&ret_txn_size, (u32 *)&file_att);
+
+	/* Check response */
+	if (nvm_result ||
+	    (ret_mcp_resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_NVM_OK)
+		return DBG_STATUS_NVRAM_GET_IMAGE_FAILED;
+
+	/* Update return values */
+	*nvram_offset_bytes = file_att.nvm_start_addr;
+	*nvram_size_bytes = file_att.len;
+
+	DP_VERBOSE(p_hwfn->p_dev,
+		   ECORE_MSG_DEBUG,
+		   "find_nvram_image: found NVRAM image of type %d in NVRAM offset %d bytes with size %d bytes\n",
+		   image_type, *nvram_offset_bytes, *nvram_size_bytes);
+
+	/* Check alignment */
+	if (*nvram_size_bytes & 0x3)
+		return DBG_STATUS_NON_ALIGNED_NVRAM_IMAGE;
+
+	return DBG_STATUS_OK;
+}
+
+/* Reads data from NVRAM */
+static enum dbg_status qed_nvram_read(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 nvram_offset_bytes,
+				      u32 nvram_size_bytes, u32 *ret_buf)
+{
+	u32 ret_mcp_resp, ret_mcp_param, ret_read_size, bytes_to_copy;
+	s32 bytes_left = nvram_size_bytes;
+	u32 read_offset = 0, param = 0;
+
+	DP_NOTICE(p_hwfn->p_dev, false,
+		   "nvram_read: reading image of size %d bytes from NVRAM\n",
+		   nvram_size_bytes);
+
+	do {
+		bytes_to_copy =
+		    (bytes_left >
+		     MCP_DRV_NVM_BUF_LEN) ? MCP_DRV_NVM_BUF_LEN : bytes_left;
+
+		/* Call NVRAM read command */
+		SET_MFW_FIELD(param,
+			      DRV_MB_PARAM_NVM_OFFSET,
+			      nvram_offset_bytes + read_offset);
+		SET_MFW_FIELD(param, DRV_MB_PARAM_NVM_LEN, bytes_to_copy);
+		if (ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt,
+					 DRV_MSG_CODE_NVM_READ_NVRAM, param,
+					 &ret_mcp_resp,
+					 &ret_mcp_param, &ret_read_size,
+					 (u32 *)((u8 *)ret_buf +
+						 read_offset))) {
+			DP_NOTICE(p_hwfn->p_dev, false, "rc = DBG_STATUS_NVRAM_READ_FAILED\n");
+			return DBG_STATUS_NVRAM_READ_FAILED;
+		}
+
+		/* Check response */
+		if ((ret_mcp_resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_NVM_OK) {
+			DP_NOTICE(p_hwfn->p_dev, false, "rc = DBG_STATUS_NVRAM_READ_FAILED\n");
+			return DBG_STATUS_NVRAM_READ_FAILED;
+		}
+
+		/* Update read offset */
+		read_offset += ret_read_size;
+		bytes_left -= ret_read_size;
+	} while (bytes_left > 0);
+
+	return DBG_STATUS_OK;
+}
+
+/* Get info on the MCP Trace data in the scratchpad:
+ * - trace_data_grc_addr (OUT): trace data GRC address in bytes
+ * - trace_data_size (OUT): trace data size in bytes (without the header)
+ */
+static enum dbg_status qed_mcp_trace_get_data_info(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *trace_data_grc_addr,
+						   u32 *trace_data_size)
+{
+	u32 spad_trace_offsize, signature;
+
+	/* Read trace section offsize structure from MCP scratchpad */
+	spad_trace_offsize = ecore_rd(p_hwfn, p_ptt,
+				      MCP_SPAD_TRACE_OFFSIZE_ADDR);
+
+	/* Extract trace section address from offsize (in scratchpad) */
+	*trace_data_grc_addr =
+		MCP_REG_SCRATCH + SECTION_OFFSET(spad_trace_offsize);
+
+	/* Read signature from MCP trace section */
+	signature = ecore_rd(p_hwfn, p_ptt,
+			   *trace_data_grc_addr +
+			   offsetof(struct mcp_trace, signature));
+
+	if (signature != MFW_TRACE_SIGNATURE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Read trace size from MCP trace section */
+	*trace_data_size = ecore_rd(p_hwfn,
+				  p_ptt,
+				  *trace_data_grc_addr +
+				  offsetof(struct mcp_trace, size));
+
+	return DBG_STATUS_OK;
+}
+
+/* Reads MCP trace meta data image from NVRAM
+ * - running_bundle_id (OUT): running bundle ID (invalid when loaded from file)
+ * - trace_meta_offset (OUT): trace meta offset in NVRAM in bytes (invalid when
+ *			      loaded from file).
+ * - trace_meta_size (OUT):   size in bytes of the trace meta data.
+ */
+static enum dbg_status qed_mcp_trace_get_meta_info(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 trace_data_size_bytes,
+						   u32 *running_bundle_id,
+						   u32 *trace_meta_offset,
+						   u32 *trace_meta_size)
+{
+	u32 spad_trace_offsize, nvram_image_type, running_mfw_addr;
+
+	/* Read MCP trace section offsize structure from MCP scratchpad */
+	spad_trace_offsize = ecore_rd(p_hwfn, p_ptt,
+				      MCP_SPAD_TRACE_OFFSIZE_ADDR);
+
+	/* Find running bundle ID */
+	running_mfw_addr =
+		MCP_REG_SCRATCH + SECTION_OFFSET(spad_trace_offsize) +
+		SECTION_SIZE(spad_trace_offsize) + trace_data_size_bytes;
+	*running_bundle_id = ecore_rd(p_hwfn, p_ptt, running_mfw_addr);
+	if (*running_bundle_id > 1)
+		return DBG_STATUS_INVALID_NVRAM_BUNDLE;
+
+	/* Find image in NVRAM */
+	nvram_image_type =
+	    (*running_bundle_id ==
+	     DIR_ID_1) ? NVM_TYPE_MFW_TRACE1 : NVM_TYPE_MFW_TRACE2;
+	return qed_find_nvram_image(p_hwfn,
+				    p_ptt,
+				    nvram_image_type,
+				    trace_meta_offset, trace_meta_size);
+}
+
+/* Reads the MCP Trace meta data from NVRAM into the specified buffer */
+static enum dbg_status qed_mcp_trace_read_meta(struct ecore_hwfn *p_hwfn,
+					       struct ecore_ptt *p_ptt,
+					       u32 nvram_offset_in_bytes,
+					       u32 size_in_bytes, u32 *buf)
+{
+	u8 modules_num, module_len, i, *byte_buf = (u8 *)buf;
+	enum dbg_status status;
+	u32 signature;
+
+	/* Read meta data from NVRAM */
+	status = qed_nvram_read(p_hwfn,
+				p_ptt,
+				nvram_offset_in_bytes, size_in_bytes, buf);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Extract and check first signature */
+	signature = qed_read_unaligned_dword(byte_buf);
+	byte_buf += sizeof(signature);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Extract number of modules */
+	modules_num = *(byte_buf++);
+
+	/* Skip all modules */
+	for (i = 0; i < modules_num; i++) {
+		module_len = *(byte_buf++);
+		byte_buf += module_len;
+	}
+
+	/* Extract and check second signature */
+	signature = qed_read_unaligned_dword(byte_buf);
+	byte_buf += sizeof(signature);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	return DBG_STATUS_OK;
+}
+
+/* Dump MCP Trace */
+static enum dbg_status qed_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+					  struct ecore_ptt *p_ptt,
+					  u32 *dump_buf,
+					  bool dump, u32 *num_dumped_dwords)
+{
+	u32 trace_data_grc_addr, trace_data_size_bytes, trace_data_size_dwords;
+	u32 trace_meta_size_dwords = 0, running_bundle_id, offset = 0;
+	u32 trace_meta_offset_bytes = 0, trace_meta_size_bytes = 0;
+	enum dbg_status status;
+	int halted = 0;
+	bool use_mfw;
+
+	*num_dumped_dwords = 0;
+
+	use_mfw = !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP);
+
+	/* Get trace data info */
+	status = qed_mcp_trace_get_data_info(p_hwfn,
+					     p_ptt,
+					     &trace_data_grc_addr,
+					     &trace_data_size_bytes);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "mcp-trace");
+
+	/* Halt MCP while reading from scratchpad so the read data will be
+	 * consistent. if halt fails, MCP trace is taken anyway, with a small
+	 * risk that it may be corrupt.
+	 */
+	if (dump && use_mfw) {
+		halted = !ecore_mcp_halt(p_hwfn, p_ptt);
+		if (!halted)
+			DP_NOTICE(p_hwfn, false, "MCP halt failed!\n");
+	}
+
+	/* Find trace data size */
+	trace_data_size_dwords =
+	    DIV_ROUND_UP(trace_data_size_bytes + sizeof(struct mcp_trace),
+			 BYTES_IN_DWORD);
+
+	/* Dump trace data section header and param */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "mcp_trace_data", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", trace_data_size_dwords);
+
+	/* Read trace data from scratchpad into dump buffer */
+	offset += qed_grc_dump_addr_range(p_hwfn,
+					  p_ptt,
+					  dump_buf + offset,
+					  dump,
+					  BYTES_TO_DWORDS(trace_data_grc_addr),
+					  trace_data_size_dwords, false,
+					  SPLIT_TYPE_NONE, 0);
+
+	/* Resume MCP (only if halt succeeded) */
+	if (halted && ecore_mcp_resume(p_hwfn, p_ptt))
+		DP_NOTICE(p_hwfn, false, "Failed to resume MCP after halt!\n");
+
+	/* Dump trace meta section header */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "mcp_trace_meta", 1);
+
+	/* If MCP Trace meta size parameter was set, use it.
+	 * Otherwise, read trace meta.
+	 * trace_meta_size_bytes is dword-aligned.
+	 */
+	trace_meta_size_bytes =
+		qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_MCP_TRACE_META_SIZE);
+	if ((!trace_meta_size_bytes || dump) && use_mfw)
+		status = qed_mcp_trace_get_meta_info(p_hwfn,
+						     p_ptt,
+						     trace_data_size_bytes,
+						     &running_bundle_id,
+						     &trace_meta_offset_bytes,
+						     &trace_meta_size_bytes);
+	if (status == DBG_STATUS_OK)
+		trace_meta_size_dwords = BYTES_TO_DWORDS(trace_meta_size_bytes);
+
+	/* Dump trace meta size param */
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", trace_meta_size_dwords);
+
+	/* Read trace meta image into dump buffer */
+	if (dump && trace_meta_size_dwords)
+		status = qed_mcp_trace_read_meta(p_hwfn,
+						 p_ptt,
+						 trace_meta_offset_bytes,
+						 trace_meta_size_bytes,
+						 dump_buf + offset);
+	if (status == DBG_STATUS_OK)
+		offset += trace_meta_size_dwords;
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	/* If no mcp access, indicate that the dump doesn't contain the meta
+	 * data from NVRAM.
+	 */
+	return use_mfw ? status : DBG_STATUS_NVRAM_GET_IMAGE_FAILED;
+}
+
+/* Dump GRC FIFO */
+static enum dbg_status qed_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
+					 struct ecore_ptt *p_ptt,
+					 u32 *dump_buf,
+					 bool dump, u32 *num_dumped_dwords)
+{
+	u32 dwords_read, size_param_offset, offset = 0, addr, len;
+	bool fifo_has_data;
+
+	*num_dumped_dwords = 0;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "reg-fifo");
+
+	/* Dump fifo data section header and param. The size param is 0 for
+	 * now, and is overwritten after reading the FIFO.
+	 */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "reg_fifo_data", 1);
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+
+	if (!dump) {
+		/* FIFO max size is REG_FIFO_DEPTH_DWORDS. There is no way to
+		 * test how much data is available, except for reading it.
+		 */
+		offset += REG_FIFO_DEPTH_DWORDS;
+		goto out;
+	}
+
+	fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+			       GRC_REG_TRACE_FIFO_VALID_DATA) > 0;
+
+	/* Pull available data from fifo. Use DMAE since this is widebus memory
+	 * and must be accessed atomically. Test for dwords_read not passing
+	 * buffer size since more entries could be added to the buffer as we are
+	 * emptying it.
+	 */
+	addr = BYTES_TO_DWORDS(GRC_REG_TRACE_FIFO);
+	len = REG_FIFO_ELEMENT_DWORDS;
+	for (dwords_read = 0;
+	     fifo_has_data && dwords_read < REG_FIFO_DEPTH_DWORDS;
+	     dwords_read += REG_FIFO_ELEMENT_DWORDS) {
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  true,
+						  addr,
+						  len,
+						  true, SPLIT_TYPE_NONE,
+						  0);
+		fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+				       GRC_REG_TRACE_FIFO_VALID_DATA) > 0;
+	}
+
+	qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
+			   dwords_read);
+out:
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Dump IGU FIFO */
+static enum dbg_status qed_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
+					 struct ecore_ptt *p_ptt,
+					 u32 *dump_buf,
+					 bool dump, u32 *num_dumped_dwords)
+{
+	u32 dwords_read, size_param_offset, offset = 0, addr, len;
+	bool fifo_has_data;
+
+	*num_dumped_dwords = 0;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "igu-fifo");
+
+	/* Dump fifo data section header and param. The size param is 0 for
+	 * now, and is overwritten after reading the FIFO.
+	 */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "igu_fifo_data", 1);
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+
+	if (!dump) {
+		/* FIFO max size is IGU_FIFO_DEPTH_DWORDS. There is no way to
+		 * test how much data is available, except for reading it.
+		 */
+		offset += IGU_FIFO_DEPTH_DWORDS;
+		goto out;
+	}
+
+	fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+			       IGU_REG_ERROR_HANDLING_DATA_VALID) > 0;
+
+	/* Pull available data from fifo. Use DMAE since this is widebus memory
+	 * and must be accessed atomically. Test for dwords_read not passing
+	 * buffer size since more entries could be added to the buffer as we are
+	 * emptying it.
+	 */
+	addr = BYTES_TO_DWORDS(IGU_REG_ERROR_HANDLING_MEMORY);
+	len = IGU_FIFO_ELEMENT_DWORDS;
+	for (dwords_read = 0;
+	     fifo_has_data && dwords_read < IGU_FIFO_DEPTH_DWORDS;
+	     dwords_read += IGU_FIFO_ELEMENT_DWORDS) {
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  true,
+						  addr,
+						  len,
+						  true, SPLIT_TYPE_NONE,
+						  0);
+		fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+				       IGU_REG_ERROR_HANDLING_DATA_VALID) > 0;
+	}
+
+	qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
+			   dwords_read);
+out:
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Protection Override dump */
+static enum dbg_status qed_protection_override_dump(struct ecore_hwfn *p_hwfn,
+						    struct ecore_ptt *p_ptt,
+						    u32 *dump_buf,
+						    bool dump,
+						    u32 *num_dumped_dwords)
+{
+	u32 size_param_offset, override_window_dwords, offset = 0, addr;
+
+	*num_dumped_dwords = 0;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "protection-override");
+
+	/* Dump data section header and param. The size param is 0 for now,
+	 * and is overwritten after reading the data.
+	 */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "protection_override_data", 1);
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+
+	if (!dump) {
+		offset += PROTECTION_OVERRIDE_DEPTH_DWORDS;
+		goto out;
+	}
+
+	/* Add override window info to buffer */
+	override_window_dwords =
+		ecore_rd(p_hwfn, p_ptt, GRC_REG_NUMBER_VALID_OVERRIDE_WINDOW) *
+		PROTECTION_OVERRIDE_ELEMENT_DWORDS;
+	if (override_window_dwords) {
+		addr = BYTES_TO_DWORDS(GRC_REG_PROTECTION_OVERRIDE_WINDOW);
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  true,
+						  addr,
+						  override_window_dwords,
+						  true, SPLIT_TYPE_NONE, 0);
+		qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
+				   override_window_dwords);
+	}
+out:
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Performs FW Asserts Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
+			       struct ecore_ptt *p_ptt, u32 *dump_buf,
+			       bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	struct fw_asserts_ram_section *asserts;
+	char storm_letter_str[2] = "?";
+	struct fw_info fw_info;
+	u32 offset = 0;
+	u8 storm_id;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "fw-asserts");
+
+	/* Find Storm dump size */
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		u32 fw_asserts_section_addr, next_list_idx_addr, next_list_idx;
+		struct storm_defs *storm = &s_storm_defs[storm_id];
+		u32 last_list_idx, addr;
+
+		if (dev_data->block_in_reset[storm->sem_block_id])
+			continue;
+
+		/* Read FW info for the current Storm */
+		qed_read_storm_fw_info(p_hwfn, p_ptt, storm_id, &fw_info);
+
+		asserts = &fw_info.fw_asserts_section;
+
+		/* Dump FW Asserts section header and params */
+		storm_letter_str[0] = storm->letter;
+		offset += qed_dump_section_hdr(dump_buf + offset,
+					       dump, "fw_asserts", 2);
+		offset += qed_dump_str_param(dump_buf + offset,
+					     dump, "storm", storm_letter_str);
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump,
+					     "size",
+					     asserts->list_element_dword_size);
+
+		/* Read and dump FW Asserts data */
+		if (!dump) {
+			offset += asserts->list_element_dword_size;
+			continue;
+		}
+
+		fw_asserts_section_addr = storm->sem_fast_mem_addr +
+			SEM_FAST_REG_INT_RAM +
+			RAM_LINES_TO_BYTES(asserts->section_ram_line_offset);
+		next_list_idx_addr = fw_asserts_section_addr +
+			DWORDS_TO_BYTES(asserts->list_next_index_dword_offset);
+		next_list_idx = ecore_rd(p_hwfn, p_ptt, next_list_idx_addr);
+		last_list_idx = (next_list_idx > 0 ?
+				 next_list_idx :
+				 asserts->list_num_elements) - 1;
+		addr = BYTES_TO_DWORDS(fw_asserts_section_addr) +
+		       asserts->list_dword_offset +
+		       last_list_idx * asserts->list_element_dword_size;
+		offset +=
+		    qed_grc_dump_addr_range(p_hwfn, p_ptt,
+					    dump_buf + offset,
+					    dump, addr,
+					    asserts->list_element_dword_size,
+						  false, SPLIT_TYPE_NONE, 0);
+	}
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	return offset;
+}
+
+/* Dumps the specified ILT pages to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_ilt_dump_pages_range(u32 *dump_buf,
+				    bool dump,
+				    u32 start_page_id,
+				    u32 num_pages,
+				    struct phys_mem_desc *ilt_pages,
+				    bool dump_page_ids)
+{
+	u32 page_id, end_page_id, offset = 0;
+
+	if (num_pages == 0)
+		return offset;
+
+	end_page_id = start_page_id + num_pages - 1;
+
+	for (page_id = start_page_id; page_id <= end_page_id; page_id++) {
+		struct phys_mem_desc *mem_desc = &ilt_pages[page_id];
+
+		/**
+		 *
+		 * if (page_id >= ->p_cxt_mngr->ilt_shadow_size)
+		 *     break;
+		 */
+
+		if (!ilt_pages[page_id].virt_addr)
+			continue;
+
+		if (dump_page_ids) {
+			/* Copy page ID to dump buffer */
+			if (dump)
+				*(dump_buf + offset) = page_id;
+			offset++;
+		} else {
+			/* Copy page memory to dump buffer */
+			if (dump)
+				memcpy(dump_buf + offset,
+				       mem_desc->virt_addr, mem_desc->size);
+			offset += BYTES_TO_DWORDS(mem_desc->size);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps a section containing the dumped ILT pages.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_ilt_dump_pages_section(struct ecore_hwfn *p_hwfn,
+				      u32 *dump_buf,
+				      bool dump,
+				      u32 valid_conn_pf_pages,
+				      u32 valid_conn_vf_pages,
+				      struct phys_mem_desc *ilt_pages,
+				      bool dump_page_ids)
+{
+	struct ecore_ilt_client_cfg *clients = p_hwfn->p_cxt_mngr->clients;
+	u32 pf_start_line, start_page_id, offset = 0;
+	u32 cdut_pf_init_pages, cdut_vf_init_pages;
+	u32 cdut_pf_work_pages, cdut_vf_work_pages;
+	u32 base_data_offset, size_param_offset;
+	u32 cdut_pf_pages, cdut_vf_pages;
+	const char *section_name;
+	u8 i;
+
+	section_name = dump_page_ids ? "ilt_page_ids" : "ilt_page_mem";
+	cdut_pf_init_pages = ecore_get_cdut_num_pf_init_pages(p_hwfn);
+	cdut_vf_init_pages = ecore_get_cdut_num_vf_init_pages(p_hwfn);
+	cdut_pf_work_pages = ecore_get_cdut_num_pf_work_pages(p_hwfn);
+	cdut_vf_work_pages = ecore_get_cdut_num_vf_work_pages(p_hwfn);
+	cdut_pf_pages = cdut_pf_init_pages + cdut_pf_work_pages;
+	cdut_vf_pages = cdut_vf_init_pages + cdut_vf_work_pages;
+	pf_start_line = p_hwfn->p_cxt_mngr->pf_start_line;
+
+	offset +=
+	    qed_dump_section_hdr(dump_buf + offset, dump, section_name, 1);
+
+	/* Dump size parameter (0 for now, overwritten with real size later) */
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+	base_data_offset = offset;
+
+	/* CDUC pages are ordered as follows:
+	 * - PF pages - valid section (included in PF connection type mapping)
+	 * - PF pages - invalid section (not dumped)
+	 * - For each VF in the PF:
+	 *   - VF pages - valid section (included in VF connection type mapping)
+	 *   - VF pages - invalid section (not dumped)
+	 */
+	if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_DUMP_ILT_CDUC)) {
+		/* Dump connection PF pages */
+		start_page_id = clients[ILT_CLI_CDUC].first.val - pf_start_line;
+		offset += qed_ilt_dump_pages_range(dump_buf + offset,
+						   dump,
+						   start_page_id,
+						   valid_conn_pf_pages,
+						   ilt_pages, dump_page_ids);
+
+		/* Dump connection VF pages */
+		start_page_id += clients[ILT_CLI_CDUC].pf_total_lines;
+		for (i = 0; i < p_hwfn->p_cxt_mngr->vf_count;
+		     i++, start_page_id += clients[ILT_CLI_CDUC].vf_total_lines)
+			offset += qed_ilt_dump_pages_range(dump_buf + offset,
+							   dump,
+							   start_page_id,
+							   valid_conn_vf_pages,
+							   ilt_pages,
+							   dump_page_ids);
+	}
+
+	/* CDUT pages are ordered as follows:
+	 * - PF init pages (not dumped)
+	 * - PF work pages
+	 * - For each VF in the PF:
+	 *   - VF init pages (not dumped)
+	 *   - VF work pages
+	 */
+	if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_DUMP_ILT_CDUT)) {
+		/* Dump task PF pages */
+		start_page_id = clients[ILT_CLI_CDUT].first.val +
+		    cdut_pf_init_pages - pf_start_line;
+		offset += qed_ilt_dump_pages_range(dump_buf + offset,
+						   dump,
+						   start_page_id,
+						   cdut_pf_work_pages,
+						   ilt_pages, dump_page_ids);
+
+		/* Dump task VF pages */
+		start_page_id = clients[ILT_CLI_CDUT].first.val +
+		    cdut_pf_pages + cdut_vf_init_pages - pf_start_line;
+		for (i = 0; i < p_hwfn->p_cxt_mngr->vf_count;
+		     i++, start_page_id += cdut_vf_pages)
+			offset += qed_ilt_dump_pages_range(dump_buf + offset,
+							   dump,
+							   start_page_id,
+							   cdut_vf_work_pages,
+							   ilt_pages,
+							   dump_page_ids);
+	}
+
+	/* Overwrite size param */
+	if (dump)
+		qed_dump_num_param(dump_buf + size_param_offset,
+				   dump, "size", offset - base_data_offset);
+
+	return offset;
+}
+
+/* Performs ILT Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_ilt_dump(struct ecore_hwfn *p_hwfn,
+			struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	struct ecore_ilt_client_cfg *clients = p_hwfn->p_cxt_mngr->clients;
+	u32 valid_conn_vf_cids, valid_conn_vf_pages, offset = 0;
+	u32 valid_conn_pf_cids, valid_conn_pf_pages, num_pages;
+	u32 num_cids_per_page, conn_ctx_size;
+	u32 cduc_page_size, cdut_page_size;
+	struct phys_mem_desc *ilt_pages;
+	u8 conn_type;
+
+	cduc_page_size = 1 <<
+	    (clients[ILT_CLI_CDUC].p_size.val + PXP_ILT_PAGE_SIZE_NUM_BITS_MIN);
+	cdut_page_size = 1 <<
+	    (clients[ILT_CLI_CDUT].p_size.val + PXP_ILT_PAGE_SIZE_NUM_BITS_MIN);
+	conn_ctx_size = p_hwfn->p_cxt_mngr->conn_ctx_size;
+	num_cids_per_page = (int)(cduc_page_size / conn_ctx_size);
+	ilt_pages = p_hwfn->p_cxt_mngr->ilt_shadow;
+
+	/* Dump global params - 22 must match number of params below */
+	offset += qed_dump_common_global_params(p_hwfn, p_ptt,
+						dump_buf + offset, dump, 22);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "ilt-dump");
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-page-size", cduc_page_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-first-page-id",
+				     clients[ILT_CLI_CDUC].first.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-last-page-id",
+				     clients[ILT_CLI_CDUC].last.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-num-pf-pages",
+				     clients
+				     [ILT_CLI_CDUC].pf_total_lines);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-num-vf-pages",
+				     clients
+				     [ILT_CLI_CDUC].vf_total_lines);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "max-conn-ctx-size",
+				     conn_ctx_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-page-size", cdut_page_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-first-page-id",
+				     clients[ILT_CLI_CDUT].first.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-last-page-id",
+				     clients[ILT_CLI_CDUT].last.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-pf-init-pages",
+				     ecore_get_cdut_num_pf_init_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-vf-init-pages",
+				     ecore_get_cdut_num_vf_init_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-pf-work-pages",
+				     ecore_get_cdut_num_pf_work_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-vf-work-pages",
+				     ecore_get_cdut_num_vf_work_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "max-task-ctx-size",
+				     p_hwfn->p_cxt_mngr->task_ctx_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "task-type-id",
+				     p_hwfn->p_cxt_mngr->task_type_id);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "first-vf-id-in-pf",
+				     p_hwfn->p_cxt_mngr->first_vf_in_pf);
+	offset += /* 18 */ qed_dump_num_param(dump_buf + offset,
+					      dump,
+					      "num-vfs-in-pf",
+					      p_hwfn->p_cxt_mngr->vf_count);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "ptr-size-bytes", sizeof(void *));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "pf-start-line",
+				     p_hwfn->p_cxt_mngr->pf_start_line);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "page-mem-desc-size-dwords",
+				     PAGE_MEM_DESC_SIZE_DWORDS);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "ilt-shadow-size",
+				     p_hwfn->p_cxt_mngr->ilt_shadow_size);
+	/* Additional/Less parameters require matching of number in call to
+	 * dump_common_global_params()
+	 */
+
+	/* Dump section containing number of PF CIDs per connection type */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "num_pf_cids_per_conn_type", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", NUM_OF_CONNECTION_TYPES);
+	for (conn_type = 0, valid_conn_pf_cids = 0;
+	     conn_type < NUM_OF_CONNECTION_TYPES; conn_type++, offset++) {
+		u32 num_pf_cids =
+		    p_hwfn->p_cxt_mngr->conn_cfg[conn_type].cid_count;
+
+		if (dump)
+			*(dump_buf + offset) = num_pf_cids;
+		valid_conn_pf_cids += num_pf_cids;
+	}
+
+	/* Dump section containing number of VF CIDs per connection type */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "num_vf_cids_per_conn_type", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", NUM_OF_CONNECTION_TYPES);
+	for (conn_type = 0, valid_conn_vf_cids = 0;
+	     conn_type < NUM_OF_CONNECTION_TYPES; conn_type++, offset++) {
+		u32 num_vf_cids =
+		    p_hwfn->p_cxt_mngr->conn_cfg[conn_type].cids_per_vf;
+
+		if (dump)
+			*(dump_buf + offset) = num_vf_cids;
+		valid_conn_vf_cids += num_vf_cids;
+	}
+
+	/* Dump section containing physical memory descs for each ILT page */
+	num_pages = p_hwfn->p_cxt_mngr->ilt_shadow_size;
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "ilt_page_desc", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "size",
+				     num_pages * PAGE_MEM_DESC_SIZE_DWORDS);
+
+	/* Copy memory descriptors to dump buffer */
+	if (dump) {
+		u32 page_id;
+
+		for (page_id = 0; page_id < num_pages;
+		     page_id++, offset += PAGE_MEM_DESC_SIZE_DWORDS)
+			memcpy(dump_buf + offset,
+			       &ilt_pages[page_id],
+			       DWORDS_TO_BYTES(PAGE_MEM_DESC_SIZE_DWORDS));
+	} else {
+		offset += num_pages * PAGE_MEM_DESC_SIZE_DWORDS;
+	}
+
+	valid_conn_pf_pages = DIV_ROUND_UP(valid_conn_pf_cids,
+					   num_cids_per_page);
+	valid_conn_vf_pages = DIV_ROUND_UP(valid_conn_vf_cids,
+					   num_cids_per_page);
+
+	/* Dump ILT pages IDs */
+	offset += qed_ilt_dump_pages_section(p_hwfn,
+					     dump_buf + offset,
+					     dump,
+					     valid_conn_pf_pages,
+					     valid_conn_vf_pages,
+					     ilt_pages, true);
+
+	/* Dump ILT pages memory */
+	offset += qed_ilt_dump_pages_section(p_hwfn,
+					     dump_buf + offset,
+					     dump,
+					     valid_conn_pf_pages,
+					     valid_conn_vf_pages,
+					     ilt_pages, false);
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	return offset;
+}
+
+/***************************** Public Functions *******************************/
+
+enum dbg_status qed_dbg_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+				    const u8 * const bin_ptr)
+{
+	struct bin_buffer_hdr *buf_hdrs =
+			(struct bin_buffer_hdr *)(osal_uintptr_t)bin_ptr;
+	u8 buf_id;
+
+	/* Convert binary data to debug arrays */
+	for (buf_id = 0; buf_id < MAX_BIN_DBG_BUFFER_TYPE; buf_id++)
+		qed_set_dbg_bin_buf(p_hwfn,
+				    buf_id,
+				    (const u32 *)(bin_ptr +
+						  buf_hdrs[buf_id].offset),
+						  buf_hdrs[buf_id].length);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_set_app_ver(u32 ver)
+{
+	if (ver < TOOLS_VERSION)
+		return DBG_STATUS_UNSUPPORTED_APP_VERSION;
+
+	s_app_ver = ver;
+
+	return DBG_STATUS_OK;
+}
+
+bool qed_read_fw_info(struct ecore_hwfn *p_hwfn,
+		      struct ecore_ptt *p_ptt, struct fw_info *fw_info)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		struct storm_defs *storm = &s_storm_defs[storm_id];
+
+		/* Skip Storm if it's in reset */
+		if (dev_data->block_in_reset[storm->sem_block_id])
+			continue;
+
+		/* Read FW info for the current Storm */
+		qed_read_storm_fw_info(p_hwfn, p_ptt, storm_id, fw_info);
+
+		return true;
+	}
+
+	return false;
+}
+
+enum dbg_status qed_dbg_grc_config(struct ecore_hwfn *p_hwfn,
+				   enum dbg_grc_params grc_param, u32 val)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	enum dbg_status status;
+	int i;
+
+	DP_VERBOSE(p_hwfn->p_dev,
+		   ECORE_MSG_DEBUG,
+		   "dbg_grc_config: paramId = %d, val = %d\n", grc_param, val);
+
+	status = qed_dbg_dev_init(p_hwfn);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Initializes the GRC parameters (if not initialized). Needed in order
+	 * to set the default parameter values for the first time.
+	 */
+	qed_dbg_grc_init_params(p_hwfn);
+
+	if (grc_param >= MAX_DBG_GRC_PARAMS)
+		return DBG_STATUS_INVALID_ARGS;
+	if (val < s_grc_param_defs[grc_param].min ||
+	    val > s_grc_param_defs[grc_param].max)
+		return DBG_STATUS_INVALID_ARGS;
+
+	if (s_grc_param_defs[grc_param].is_preset) {
+		/* Preset param */
+
+		/* Disabling a preset is not allowed. Call
+		 * dbg_grc_set_params_default instead.
+		 */
+		if (!val)
+			return DBG_STATUS_INVALID_ARGS;
+
+		/* Update all params with the preset values */
+		for (i = 0; i < MAX_DBG_GRC_PARAMS; i++) {
+			struct grc_param_defs *defs = &s_grc_param_defs[i];
+			u32 preset_val;
+			/* Skip persistent params */
+			if (defs->is_persistent)
+				continue;
+
+			/* Find preset value */
+			if (grc_param == DBG_GRC_PARAM_EXCLUDE_ALL)
+				preset_val =
+				    defs->exclude_all_preset_val;
+			else if (grc_param == DBG_GRC_PARAM_CRASH)
+				preset_val =
+				    defs->crash_preset_val[dev_data->chip_id];
+			else
+				return DBG_STATUS_INVALID_ARGS;
+
+			qed_grc_set_param(p_hwfn, i, preset_val);
+		}
+	} else {
+		/* Regular param - set its value */
+		qed_grc_set_param(p_hwfn, grc_param, val);
+	}
+
+	return DBG_STATUS_OK;
+}
+
+/* Assign default GRC param values */
+void qed_dbg_grc_set_params_default(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 i;
+
+	for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
+		if (!s_grc_param_defs[i].is_persistent)
+			dev_data->grc.param_val[i] =
+			    s_grc_param_defs[i].default_val[dev_data->chip_id];
+}
+
+enum dbg_status qed_dbg_grc_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_MEM].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	return qed_grc_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_grc_dump(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf,
+				 u32 buf_size_in_dwords,
+				 u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_grc_get_dump_buf_size(p_hwfn,
+					       p_ptt,
+					       &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* GRC Dump */
+	status = qed_grc_dump(p_hwfn, p_ptt, dump_buf, true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_idle_chk_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	struct idle_chk_data *idle_chk = &dev_data->idle_chk;
+	enum dbg_status status;
+
+	*buf_size = 0;
+
+	status = qed_dbg_dev_init(p_hwfn);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_IMMS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_RULES].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	if (!idle_chk->buf_size_set) {
+		idle_chk->buf_size = qed_idle_chk_dump(p_hwfn,
+						       p_ptt, NULL, false);
+		idle_chk->buf_size_set = true;
+	}
+
+	*buf_size = idle_chk->buf_size;
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_idle_chk_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_grc_unreset_blocks(p_hwfn, p_ptt, true);
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	/* Idle Check Dump */
+	*num_dumped_dwords = qed_idle_chk_dump(p_hwfn, p_ptt, dump_buf, true);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_mcp_trace_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						    struct ecore_ptt *p_ptt,
+						    u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_mcp_trace_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+				       struct ecore_ptt *p_ptt,
+				       u32 *dump_buf,
+				       u32 buf_size_in_dwords,
+				       u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	status =
+		qed_dbg_mcp_trace_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK && status !=
+	    DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
+		return status;
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	/* Perform dump */
+	status = qed_mcp_trace_dump(p_hwfn,
+				    p_ptt, dump_buf, true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_reg_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_reg_fifo_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_reg_fifo_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	status = qed_reg_fifo_dump(p_hwfn,
+				   p_ptt, dump_buf, true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_igu_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_igu_fifo_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_igu_fifo_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	status = qed_igu_fifo_dump(p_hwfn,
+				   p_ptt, dump_buf, true, num_dumped_dwords);
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status
+qed_dbg_protection_override_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_protection_override_dump(p_hwfn,
+					    p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_protection_override_dump(struct ecore_hwfn *p_hwfn,
+						 struct ecore_ptt *p_ptt,
+						 u32 *dump_buf,
+						 u32 buf_size_in_dwords,
+						 u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords, *p_size = &needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status =
+		qed_dbg_protection_override_get_dump_buf_size(p_hwfn,
+							      p_ptt,
+							      p_size);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	status = qed_protection_override_dump(p_hwfn,
+					      p_ptt,
+					      dump_buf,
+					      true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_fw_asserts_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						     struct ecore_ptt *p_ptt,
+						     u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	*buf_size = qed_fw_asserts_dump(p_hwfn, p_ptt, NULL, false);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf,
+					u32 buf_size_in_dwords,
+					u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords, *p_size = &needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status =
+		qed_dbg_fw_asserts_get_dump_buf_size(p_hwfn,
+						     p_ptt,
+						     p_size);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	*num_dumped_dwords = qed_fw_asserts_dump(p_hwfn, p_ptt, dump_buf, true);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status qed_dbg_ilt_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						     struct ecore_ptt *p_ptt,
+						     u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	*buf_size = qed_ilt_dump(p_hwfn, p_ptt, NULL, false);
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status qed_dbg_ilt_dump(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf,
+					u32 buf_size_in_dwords,
+					u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_ilt_get_dump_buf_size(p_hwfn,
+					       p_ptt,
+					       &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	*num_dumped_dwords = qed_ilt_dump(p_hwfn, p_ptt, dump_buf, true);
+
+	/* Reveret GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_read_attn(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  enum block_id block_id,
+				  enum dbg_attn_type attn_type,
+				  bool clear_status,
+				  struct dbg_attn_block_result *results)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+	u8 reg_idx, num_attn_regs, num_result_regs = 0;
+	const struct dbg_attn_reg *attn_reg_arr;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
+					       block_id,
+					       attn_type, &num_attn_regs);
+
+	for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
+		const struct dbg_attn_reg *reg_data = &attn_reg_arr[reg_idx];
+		struct dbg_attn_reg_result *reg_result;
+		u32 sts_addr, sts_val;
+		u16 modes_buf_offset;
+		bool eval_mode;
+
+		/* Check mode */
+		eval_mode = GET_FIELD(reg_data->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		modes_buf_offset = GET_FIELD(reg_data->mode.data,
+					     DBG_MODE_HDR_MODES_BUF_OFFSET);
+		if (eval_mode && !qed_is_mode_match(p_hwfn, &modes_buf_offset))
+			continue;
+
+		/* Mode match - read attention status register */
+		sts_addr = DWORDS_TO_BYTES(clear_status ?
+					   reg_data->sts_clr_address :
+					   GET_FIELD(reg_data->data,
+						     DBG_ATTN_REG_STS_ADDRESS));
+		sts_val = ecore_rd(p_hwfn, p_ptt, sts_addr);
+		if (!sts_val)
+			continue;
+
+		/* Non-zero attention status - add to results */
+		reg_result = &results->reg_results[num_result_regs];
+		SET_FIELD(reg_result->data,
+			  DBG_ATTN_REG_RESULT_STS_ADDRESS, sts_addr);
+		SET_FIELD(reg_result->data,
+			  DBG_ATTN_REG_RESULT_NUM_REG_ATTN,
+			  GET_FIELD(reg_data->data, DBG_ATTN_REG_NUM_REG_ATTN));
+		reg_result->block_attn_offset = reg_data->block_attn_offset;
+		reg_result->sts_val = sts_val;
+		reg_result->mask_val = ecore_rd(p_hwfn,
+					      p_ptt,
+					      DWORDS_TO_BYTES
+					      (reg_data->mask_address));
+		num_result_regs++;
+	}
+
+	results->block_id = (u8)block_id;
+	results->names_offset =
+	    qed_get_block_attn_data(p_hwfn, block_id, attn_type)->names_offset;
+	SET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_ATTN_TYPE, attn_type);
+	SET_FIELD(results->data,
+		  DBG_ATTN_BLOCK_RESULT_NUM_REGS, num_result_regs);
+
+	return DBG_STATUS_OK;
+}
+
+/******************************* Data Types **********************************/
+
+/* REG fifo element */
+struct reg_fifo_element {
+	u64 data;
+#define REG_FIFO_ELEMENT_ADDRESS_SHIFT		0
+#define REG_FIFO_ELEMENT_ADDRESS_MASK		0x7fffff
+#define REG_FIFO_ELEMENT_ACCESS_SHIFT		23
+#define REG_FIFO_ELEMENT_ACCESS_MASK		0x1
+#define REG_FIFO_ELEMENT_PF_SHIFT		24
+#define REG_FIFO_ELEMENT_PF_MASK		0xf
+#define REG_FIFO_ELEMENT_VF_SHIFT		28
+#define REG_FIFO_ELEMENT_VF_MASK		0xff
+#define REG_FIFO_ELEMENT_PORT_SHIFT		36
+#define REG_FIFO_ELEMENT_PORT_MASK		0x3
+#define REG_FIFO_ELEMENT_PRIVILEGE_SHIFT	38
+#define REG_FIFO_ELEMENT_PRIVILEGE_MASK		0x3
+#define REG_FIFO_ELEMENT_PROTECTION_SHIFT	40
+#define REG_FIFO_ELEMENT_PROTECTION_MASK	0x7
+#define REG_FIFO_ELEMENT_MASTER_SHIFT		43
+#define REG_FIFO_ELEMENT_MASTER_MASK		0xf
+#define REG_FIFO_ELEMENT_ERROR_SHIFT		47
+#define REG_FIFO_ELEMENT_ERROR_MASK		0x1f
+};
+
+/* REG fifo error element */
+struct reg_fifo_err {
+	u32 err_code;
+	const char *err_msg;
+};
+
+/* IGU fifo element */
+struct igu_fifo_element {
+	u32 dword0;
+#define IGU_FIFO_ELEMENT_DWORD0_FID_SHIFT		0
+#define IGU_FIFO_ELEMENT_DWORD0_FID_MASK		0xff
+#define IGU_FIFO_ELEMENT_DWORD0_IS_PF_SHIFT		8
+#define IGU_FIFO_ELEMENT_DWORD0_IS_PF_MASK		0x1
+#define IGU_FIFO_ELEMENT_DWORD0_SOURCE_SHIFT		9
+#define IGU_FIFO_ELEMENT_DWORD0_SOURCE_MASK		0xf
+#define IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE_SHIFT		13
+#define IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE_MASK		0xf
+#define IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR_SHIFT		17
+#define IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR_MASK		0x7fff
+	u32 dword1;
+	u32 dword2;
+#define IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD_SHIFT	0
+#define IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD_MASK		0x1
+#define IGU_FIFO_ELEMENT_DWORD12_WR_DATA_SHIFT		1
+#define IGU_FIFO_ELEMENT_DWORD12_WR_DATA_MASK		0xffffffff
+	u32 reserved;
+};
+
+struct igu_fifo_wr_data {
+	u32 data;
+#define IGU_FIFO_WR_DATA_PROD_CONS_SHIFT		0
+#define IGU_FIFO_WR_DATA_PROD_CONS_MASK			0xffffff
+#define IGU_FIFO_WR_DATA_UPDATE_FLAG_SHIFT		24
+#define IGU_FIFO_WR_DATA_UPDATE_FLAG_MASK		0x1
+#define IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB_SHIFT	25
+#define IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB_MASK		0x3
+#define IGU_FIFO_WR_DATA_SEGMENT_SHIFT			27
+#define IGU_FIFO_WR_DATA_SEGMENT_MASK			0x1
+#define IGU_FIFO_WR_DATA_TIMER_MASK_SHIFT		28
+#define IGU_FIFO_WR_DATA_TIMER_MASK_MASK		0x1
+#define IGU_FIFO_WR_DATA_CMD_TYPE_SHIFT			31
+#define IGU_FIFO_WR_DATA_CMD_TYPE_MASK			0x1
+};
+
+struct igu_fifo_cleanup_wr_data {
+	u32 data;
+#define IGU_FIFO_CLEANUP_WR_DATA_RESERVED_SHIFT		0
+#define IGU_FIFO_CLEANUP_WR_DATA_RESERVED_MASK		0x7ffffff
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL_SHIFT	27
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL_MASK	0x1
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE_SHIFT	28
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE_MASK	0x7
+#define IGU_FIFO_CLEANUP_WR_DATA_CMD_TYPE_SHIFT		31
+#define IGU_FIFO_CLEANUP_WR_DATA_CMD_TYPE_MASK		0x1
+};
+
+/* Protection override element */
+struct protection_override_element {
+	u64 data;
+#define PROTECTION_OVERRIDE_ELEMENT_ADDRESS_SHIFT		0
+#define PROTECTION_OVERRIDE_ELEMENT_ADDRESS_MASK		0x7fffff
+#define PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE_SHIFT		23
+#define PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE_MASK		0xffffff
+#define PROTECTION_OVERRIDE_ELEMENT_READ_SHIFT			47
+#define PROTECTION_OVERRIDE_ELEMENT_READ_MASK			0x1
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_SHIFT			48
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_MASK			0x1
+#define PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION_SHIFT	49
+#define PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION_MASK	0x7
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION_SHIFT	52
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION_MASK	0x7
+};
+
+enum igu_fifo_sources {
+	IGU_SRC_PXP0,
+	IGU_SRC_PXP1,
+	IGU_SRC_PXP2,
+	IGU_SRC_PXP3,
+	IGU_SRC_PXP4,
+	IGU_SRC_PXP5,
+	IGU_SRC_PXP6,
+	IGU_SRC_PXP7,
+	IGU_SRC_CAU,
+	IGU_SRC_ATTN,
+	IGU_SRC_GRC
+};
+
+enum igu_fifo_addr_types {
+	IGU_ADDR_TYPE_MSIX_MEM,
+	IGU_ADDR_TYPE_WRITE_PBA,
+	IGU_ADDR_TYPE_WRITE_INT_ACK,
+	IGU_ADDR_TYPE_WRITE_ATTN_BITS,
+	IGU_ADDR_TYPE_READ_INT,
+	IGU_ADDR_TYPE_WRITE_PROD_UPDATE,
+	IGU_ADDR_TYPE_RESERVED
+};
+
+struct igu_fifo_addr_data {
+	u16 start_addr;
+	u16 end_addr;
+	const char *desc;
+	const char *vf_desc;
+	enum igu_fifo_addr_types type;
+};
+
+/******************************** Constants **********************************/
+
+#define MAX_MSG_LEN				1024
+
+#define MCP_TRACE_MAX_MODULE_LEN		8
+#define MCP_TRACE_FORMAT_MAX_PARAMS		3
+#define MCP_TRACE_FORMAT_PARAM_WIDTH \
+	(MCP_TRACE_FORMAT_P2_SIZE_OFFSET - MCP_TRACE_FORMAT_P1_SIZE_OFFSET)
+
+#define REG_FIFO_ELEMENT_ADDR_FACTOR		4
+#define REG_FIFO_ELEMENT_IS_PF_VF_VAL		127
+
+#define PROTECTION_OVERRIDE_ELEMENT_ADDR_FACTOR	4
+
+/***************************** Constant Arrays *******************************/
+
+/* Status string array */
+static const char * const s_status_str[] = {
+	/* DBG_STATUS_OK */
+	"Operation completed successfully",
+
+	/* DBG_STATUS_APP_VERSION_NOT_SET */
+	"Debug application version wasn't set",
+
+	/* DBG_STATUS_UNSUPPORTED_APP_VERSION */
+	"Unsupported debug application version",
+
+	/* DBG_STATUS_DBG_BLOCK_NOT_RESET */
+	"The debug block wasn't reset since the last recording",
+
+	/* DBG_STATUS_INVALID_ARGS */
+	"Invalid arguments",
+
+	/* DBG_STATUS_OUTPUT_ALREADY_SET */
+	"The debug output was already set",
+
+	/* DBG_STATUS_INVALID_PCI_BUF_SIZE */
+	"Invalid PCI buffer size",
+
+	/* DBG_STATUS_PCI_BUF_ALLOC_FAILED */
+	"PCI buffer allocation failed",
+
+	/* DBG_STATUS_PCI_BUF_NOT_ALLOCATED */
+	"A PCI buffer wasn't allocated",
+
+	/* DBG_STATUS_INVALID_FILTER_TRIGGER_DWORDS */
+	"The filter/trigger constraint dword offsets are not enabled for recording",
+
+
+	/* DBG_STATUS_VFC_READ_ERROR */
+	"Error reading from VFC",
+
+	/* DBG_STATUS_STORM_ALREADY_ENABLED */
+	"The Storm was already enabled",
+
+	/* DBG_STATUS_STORM_NOT_ENABLED */
+	"The specified Storm wasn't enabled",
+
+	/* DBG_STATUS_BLOCK_ALREADY_ENABLED */
+	"The block was already enabled",
+
+	/* DBG_STATUS_BLOCK_NOT_ENABLED */
+	"The specified block wasn't enabled",
+
+	/* DBG_STATUS_NO_INPUT_ENABLED */
+	"No input was enabled for recording",
+
+	/* DBG_STATUS_NO_FILTER_TRIGGER_256B */
+	"Filters and triggers are not allowed in E4 256-bit mode",
+
+	/* DBG_STATUS_FILTER_ALREADY_ENABLED */
+	"The filter was already enabled",
+
+	/* DBG_STATUS_TRIGGER_ALREADY_ENABLED */
+	"The trigger was already enabled",
+
+	/* DBG_STATUS_TRIGGER_NOT_ENABLED */
+	"The trigger wasn't enabled",
+
+	/* DBG_STATUS_CANT_ADD_CONSTRAINT */
+	"A constraint can be added only after a filter was enabled or a trigger state was added",
+
+	/* DBG_STATUS_TOO_MANY_TRIGGER_STATES */
+	"Cannot add more than 3 trigger states",
+
+	/* DBG_STATUS_TOO_MANY_CONSTRAINTS */
+	"Cannot add more than 4 constraints per filter or trigger state",
+
+	/* DBG_STATUS_RECORDING_NOT_STARTED */
+	"The recording wasn't started",
+
+	/* DBG_STATUS_DATA_DIDNT_TRIGGER */
+	"A trigger was configured, but it didn't trigger",
+
+	/* DBG_STATUS_NO_DATA_RECORDED */
+	"No data was recorded",
+
+	/* DBG_STATUS_DUMP_BUF_TOO_SMALL */
+	"Dump buffer is too small",
+
+	/* DBG_STATUS_DUMP_NOT_CHUNK_ALIGNED */
+	"Dumped data is not aligned to chunks",
+
+	/* DBG_STATUS_UNKNOWN_CHIP */
+	"Unknown chip",
+
+	/* DBG_STATUS_VIRT_MEM_ALLOC_FAILED */
+	"Failed allocating virtual memory",
+
+	/* DBG_STATUS_BLOCK_IN_RESET */
+	"The input block is in reset",
+
+	/* DBG_STATUS_INVALID_TRACE_SIGNATURE */
+	"Invalid MCP trace signature found in NVRAM",
+
+	/* DBG_STATUS_INVALID_NVRAM_BUNDLE */
+	"Invalid bundle ID found in NVRAM",
+
+	/* DBG_STATUS_NVRAM_GET_IMAGE_FAILED */
+	"Failed getting NVRAM image",
+
+	/* DBG_STATUS_NON_ALIGNED_NVRAM_IMAGE */
+	"NVRAM image is not dword-aligned",
+
+	/* DBG_STATUS_NVRAM_READ_FAILED */
+	"Failed reading from NVRAM",
+
+	/* DBG_STATUS_IDLE_CHK_PARSE_FAILED */
+	"Idle check parsing failed",
+
+	/* DBG_STATUS_MCP_TRACE_BAD_DATA */
+	"MCP Trace data is corrupt",
+
+	/* DBG_STATUS_MCP_TRACE_NO_META */
+	"Dump doesn't contain meta data - it must be provided in image file",
+
+	/* DBG_STATUS_MCP_COULD_NOT_HALT */
+	"Failed to halt MCP",
+
+	/* DBG_STATUS_MCP_COULD_NOT_RESUME */
+	"Failed to resume MCP after halt",
+
+	/* DBG_STATUS_RESERVED0 */
+	"",
+
+	/* DBG_STATUS_SEMI_FIFO_NOT_EMPTY */
+	"Failed to empty SEMI sync FIFO",
+
+	/* DBG_STATUS_IGU_FIFO_BAD_DATA */
+	"IGU FIFO data is corrupt",
+
+	/* DBG_STATUS_MCP_COULD_NOT_MASK_PRTY */
+	"MCP failed to mask parities",
+
+	/* DBG_STATUS_FW_ASSERTS_PARSE_FAILED */
+	"FW Asserts parsing failed",
+
+	/* DBG_STATUS_REG_FIFO_BAD_DATA */
+	"GRC FIFO data is corrupt",
+
+	/* DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA */
+	"Protection Override data is corrupt",
+
+	/* DBG_STATUS_DBG_ARRAY_NOT_SET */
+	"Debug arrays were not set (when using binary files, dbg_set_bin_ptr must be called)",
+
+	/* DBG_STATUS_RESERVED1 */
+	"",
+
+	/* DBG_STATUS_NON_MATCHING_LINES */
+	"Non-matching debug lines - in E4, all lines must be of the same type (either 128b or 256b)",
+
+	/* DBG_STATUS_INSUFFICIENT_HW_IDS */
+	"Insufficient HW IDs. Try to record less Storms/blocks",
+
+	/* DBG_STATUS_DBG_BUS_IN_USE */
+	"The debug bus is in use",
+
+	/* DBG_STATUS_INVALID_STORM_DBG_MODE */
+	"The storm debug mode is not supported in the current chip",
+
+	/* DBG_STATUS_OTHER_ENGINE_BB_ONLY */
+	"Other engine is supported only in BB",
+
+	/* DBG_STATUS_FILTER_SINGLE_HW_ID */
+	"The configured filter mode requires a single Storm/block input",
+
+	/* DBG_STATUS_TRIGGER_SINGLE_HW_ID */
+	"The configured filter mode requires that all the constraints of a single trigger state will be defined on a single Storm/block input",
+
+	/* DBG_STATUS_MISSING_TRIGGER_STATE_STORM */
+	"When triggering on Storm data, the Storm to trigger on must be specified"
+};
+
+/* Idle check severity names array */
+static const char * const s_idle_chk_severity_str[] = {
+	"Error",
+	"Error if no traffic",
+	"Warning"
+};
+
+/* MCP Trace level names array */
+static const char * const s_mcp_trace_level_str[] = {
+	"ERROR",
+	"TRACE",
+	"DEBUG"
+};
+
+/* Access type names array */
+static const char * const s_access_strs[] = {
+	"read",
+	"write"
+};
+
+/* Privilege type names array */
+static const char * const s_privilege_strs[] = {
+	"VF",
+	"PDA",
+	"HV",
+	"UA"
+};
+
+/* Protection type names array */
+static const char * const s_protection_strs[] = {
+	"(default)",
+	"(default)",
+	"(default)",
+	"(default)",
+	"override VF",
+	"override PDA",
+	"override HV",
+	"override UA"
+};
+
+/* Master type names array */
+static const char * const s_master_strs[] = {
+	"???",
+	"pxp",
+	"mcp",
+	"msdm",
+	"psdm",
+	"ysdm",
+	"usdm",
+	"tsdm",
+	"xsdm",
+	"dbu",
+	"dmae",
+	"jdap",
+	"???",
+	"???",
+	"???",
+	"???"
+};
+
+/* REG FIFO error messages array */
+static struct reg_fifo_err s_reg_fifo_errors[] = {
+	{1, "grc timeout"},
+	{2, "address doesn't belong to any block"},
+	{4, "reserved address in block or write to read-only address"},
+	{8, "privilege/protection mismatch"},
+	{16, "path isolation error"},
+	{17, "RSL error"}
+};
+
+/* IGU FIFO sources array */
+static const char * const s_igu_fifo_source_strs[] = {
+	"TSTORM",
+	"MSTORM",
+	"USTORM",
+	"XSTORM",
+	"YSTORM",
+	"PSTORM",
+	"PCIE",
+	"NIG_QM_PBF",
+	"CAU",
+	"ATTN",
+	"GRC",
+};
+
+/* IGU FIFO error messages */
+static const char * const s_igu_fifo_error_strs[] = {
+	"no error",
+	"length error",
+	"function disabled",
+	"VF sent command to attention address",
+	"host sent prod update command",
+	"read of during interrupt register while in MIMD mode",
+	"access to PXP BAR reserved address",
+	"producer update command to attention index",
+	"unknown error",
+	"SB index not valid",
+	"SB relative index and FID not found",
+	"FID not match",
+	"command with error flag asserted (PCI error or CAU discard)",
+	"VF sent cleanup and RF cleanup is disabled",
+	"cleanup command on type bigger than 4"
+};
+
+/* IGU FIFO address data */
+static const struct igu_fifo_addr_data s_igu_fifo_addr_data[] = {
+	{0x0, 0x101, "MSI-X Memory", NULL,
+	 IGU_ADDR_TYPE_MSIX_MEM},
+	{0x102, 0x1ff, "reserved", NULL,
+	 IGU_ADDR_TYPE_RESERVED},
+	{0x200, 0x200, "Write PBA[0:63]", NULL,
+	 IGU_ADDR_TYPE_WRITE_PBA},
+	{0x201, 0x201, "Write PBA[64:127]", "reserved",
+	 IGU_ADDR_TYPE_WRITE_PBA},
+	{0x202, 0x202, "Write PBA[128]", "reserved",
+	 IGU_ADDR_TYPE_WRITE_PBA},
+	{0x203, 0x3ff, "reserved", NULL,
+	 IGU_ADDR_TYPE_RESERVED},
+	{0x400, 0x5ef, "Write interrupt acknowledgment", NULL,
+	 IGU_ADDR_TYPE_WRITE_INT_ACK},
+	{0x5f0, 0x5f0, "Attention bits update", NULL,
+	 IGU_ADDR_TYPE_WRITE_ATTN_BITS},
+	{0x5f1, 0x5f1, "Attention bits set", NULL,
+	 IGU_ADDR_TYPE_WRITE_ATTN_BITS},
+	{0x5f2, 0x5f2, "Attention bits clear", NULL,
+	 IGU_ADDR_TYPE_WRITE_ATTN_BITS},
+	{0x5f3, 0x5f3, "Read interrupt 0:63 with mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f4, 0x5f4, "Read interrupt 0:31 with mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f5, 0x5f5, "Read interrupt 32:63 with mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f6, 0x5f6, "Read interrupt 0:63 without mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f7, 0x5ff, "reserved", NULL,
+	 IGU_ADDR_TYPE_RESERVED},
+	{0x600, 0x7ff, "Producer update", NULL,
+	 IGU_ADDR_TYPE_WRITE_PROD_UPDATE}
+};
+
+/******************************** Variables **********************************/
+
+/* Temporary buffer, used for print size calculations */
+static char s_temp_buf[MAX_MSG_LEN];
+
+/**************************** Private Functions ******************************/
+
+static u32 qed_cyclic_add(u32 a, u32 b, u32 size)
+{
+	return (a + b) % size;
+}
+
+static u32 qed_cyclic_sub(u32 a, u32 b, u32 size)
+{
+	return (size + a - b) % size;
+}
+
+/* Reads the specified number of bytes from the specified cyclic buffer (up to 4
+ * bytes) and returns them as a dword value. the specified buffer offset is
+ * updated.
+ */
+static u32 qed_read_from_cyclic_buf(void *buf,
+				    u32 *offset,
+				    u32 buf_size, u8 num_bytes_to_read)
+{
+	u8 i, *val_ptr, *bytes_buf = (u8 *)buf;
+	u32 val = 0;
+
+	val_ptr = (u8 *)&val;
+
+	/* Assume running on a LITTLE ENDIAN and the buffer is network order
+	 * (BIG ENDIAN), as high order bytes are placed in lower memory address.
+	 */
+	for (i = 0; i < num_bytes_to_read; i++) {
+		val_ptr[i] = bytes_buf[*offset];
+		*offset = qed_cyclic_add(*offset, 1, buf_size);
+	}
+
+	return val;
+}
+
+/* Reads and returns the next byte from the specified buffer.
+ * The specified buffer offset is updated.
+ */
+static u8 qed_read_byte_from_buf(void *buf, u32 *offset)
+{
+	return ((u8 *)buf)[(*offset)++];
+}
+
+/* Reads and returns the next dword from the specified buffer.
+ * The specified buffer offset is updated.
+ */
+static u32 qed_read_dword_from_buf(void *buf, u32 *offset)
+{
+	u32 dword_val = *(u32 *)&((u8 *)buf)[*offset];
+
+	*offset += 4;
+
+	return dword_val;
+}
+
+/* Reads the next string from the specified buffer, and copies it to the
+ * specified pointer. The specified buffer offset is updated.
+ */
+static void qed_read_str_from_buf(void *buf, u32 *offset, u32 size, char *dest)
+{
+	const char *source_str = &((const char *)buf)[*offset];
+
+	OSAL_STRNCPY(dest, source_str, size);
+	dest[size - 1] = '\0';
+	*offset += size;
+}
+
+/* Returns a pointer to the specified offset (in bytes) of the specified buffer.
+ * If the specified buffer in NULL, a temporary buffer pointer is returned.
+ */
+static char *qed_get_buf_ptr(void *buf, u32 offset)
+{
+	return buf ? (char *)buf + offset : s_temp_buf;
+}
+
+/* Reads a param from the specified buffer. Returns the number of dwords read.
+ * If the returned str_param is NULL, the param is numeric and its value is
+ * returned in num_param.
+ * Otheriwise, the param is a string and its pointer is returned in str_param.
+ */
+static u32 qed_read_param(u32 *dump_buf,
+			  const char **param_name,
+			  const char **param_str_val, u32 *param_num_val)
+{
+	char *char_buf = (char *)dump_buf;
+	size_t offset = 0;
+
+	/* Extract param name */
+	*param_name = char_buf;
+	offset += strlen(*param_name) + 1;
+
+	/* Check param type */
+	if (*(char_buf + offset++)) {
+		/* String param */
+		*param_str_val = char_buf + offset;
+		*param_num_val = 0;
+		offset += strlen(*param_str_val) + 1;
+		if (offset & 0x3)
+			offset += (4 - (offset & 0x3));
+	} else {
+		/* Numeric param */
+		*param_str_val = NULL;
+		if (offset & 0x3)
+			offset += (4 - (offset & 0x3));
+		*param_num_val = *(u32 *)(char_buf + offset);
+		offset += 4;
+	}
+
+	return (u32)offset / 4;
+}
+
+/* Reads a section header from the specified buffer.
+ * Returns the number of dwords read.
+ */
+static u32 qed_read_section_hdr(u32 *dump_buf,
+				const char **section_name,
+				u32 *num_section_params)
+{
+	const char *param_str_val;
+
+	return qed_read_param(dump_buf,
+			      section_name, &param_str_val, num_section_params);
+}
+
+/* Reads section params from the specified buffer and prints them to the results
+ * buffer. Returns the number of dwords read.
+ */
+static u32 qed_print_section_params(u32 *dump_buf,
+				    u32 num_section_params,
+				    char *results_buf, u32 *num_chars_printed)
+{
+	u32 i, dump_offset = 0, results_offset = 0;
+
+	for (i = 0; i < num_section_params; i++) {
+		const char *param_name, *param_str_val;
+		u32 param_num_val = 0;
+
+		dump_offset += qed_read_param(dump_buf + dump_offset,
+					      &param_name,
+					      &param_str_val, &param_num_val);
+
+		if (param_str_val) {
+			results_offset +=
+				sprintf(qed_get_buf_ptr(results_buf,
+							results_offset),
+					"%s: %s\n", param_name, param_str_val);
+		} else if (strcmp(param_name, "fw-timestamp")) {
+			results_offset +=
+				sprintf(qed_get_buf_ptr(results_buf,
+							results_offset),
+					"%s: %d\n", param_name, param_num_val);
+		}
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf, results_offset),
+				  "\n");
+
+	*num_chars_printed = results_offset;
+
+	return dump_offset;
+}
+
+/* Returns the block name that matches the specified block ID,
+ * or NULL if not found.
+ */
+static const char *qed_dbg_get_block_name(struct ecore_hwfn *p_hwfn,
+					  enum block_id block_id)
+{
+	const struct dbg_block_user *block =
+	    (const struct dbg_block_user *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS_USER_DATA].ptr + block_id;
+
+	return (const char *)block->name;
+}
+
+static struct dbg_tools_user_data *qed_dbg_get_user_data(struct ecore_hwfn
+							 *p_hwfn)
+{
+	return (struct dbg_tools_user_data *)p_hwfn->dbg_user_info;
+}
+
+/* Parses the idle check rules and returns the number of characters printed.
+ * In case of parsing error, returns 0.
+ */
+static u32 qed_parse_idle_chk_dump_rules(struct ecore_hwfn *p_hwfn,
+					 u32 *dump_buf,
+					 u32 *dump_buf_end,
+					 u32 num_rules,
+					 bool print_fw_idle_chk,
+					 char *results_buf,
+					 u32 *num_errors, u32 *num_warnings)
+{
+	/* Offset in results_buf in bytes */
+	u32 results_offset = 0;
+
+	u32 rule_idx;
+	u16 i, j;
+
+	*num_errors = 0;
+	*num_warnings = 0;
+
+	/* Go over dumped results */
+	for (rule_idx = 0; rule_idx < num_rules && dump_buf < dump_buf_end;
+	     rule_idx++) {
+		const struct dbg_idle_chk_rule_parsing_data *rule_parsing_data;
+		struct dbg_idle_chk_result_hdr *hdr;
+		const char *parsing_str, *lsi_msg;
+		u32 parsing_str_offset;
+		bool has_fw_msg;
+		u8 curr_reg_id;
+
+		hdr = (struct dbg_idle_chk_result_hdr *)dump_buf;
+		rule_parsing_data =
+		    (const struct dbg_idle_chk_rule_parsing_data *)
+		    p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_PARSING_DATA].ptr +
+		    hdr->rule_id;
+		parsing_str_offset =
+		    GET_FIELD(rule_parsing_data->data,
+			      DBG_IDLE_CHK_RULE_PARSING_DATA_STR_OFFSET);
+		has_fw_msg =
+		    GET_FIELD(rule_parsing_data->data,
+			      DBG_IDLE_CHK_RULE_PARSING_DATA_HAS_FW_MSG) > 0;
+		parsing_str = (const char *)
+		    p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr +
+		    parsing_str_offset;
+		lsi_msg = parsing_str;
+		curr_reg_id = 0;
+
+		if (hdr->severity >= MAX_DBG_IDLE_CHK_SEVERITY_TYPES)
+			return 0;
+
+		/* Skip rule header */
+		dump_buf += BYTES_TO_DWORDS(sizeof(*hdr));
+
+		/* Update errors/warnings count */
+		if (hdr->severity == IDLE_CHK_SEVERITY_ERROR ||
+		    hdr->severity == IDLE_CHK_SEVERITY_ERROR_NO_TRAFFIC)
+			(*num_errors)++;
+		else
+			(*num_warnings)++;
+
+		/* Print rule severity */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset), "%s: ",
+			    s_idle_chk_severity_str[hdr->severity]);
+
+		/* Print rule message */
+		if (has_fw_msg)
+			parsing_str += strlen(parsing_str) + 1;
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset), "%s.",
+			    has_fw_msg &&
+			    print_fw_idle_chk ? parsing_str : lsi_msg);
+		parsing_str += strlen(parsing_str) + 1;
+
+		/* Print register values */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset), " Registers:");
+		for (i = 0;
+		     i < hdr->num_dumped_cond_regs + hdr->num_dumped_info_regs;
+		     i++) {
+			struct dbg_idle_chk_result_reg_hdr *reg_hdr;
+			bool is_mem;
+			u8 reg_id;
+
+			reg_hdr =
+				(struct dbg_idle_chk_result_reg_hdr *)dump_buf;
+			is_mem = GET_FIELD(reg_hdr->data,
+					   DBG_IDLE_CHK_RESULT_REG_HDR_IS_MEM);
+			reg_id = GET_FIELD(reg_hdr->data,
+					   DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID);
+
+			/* Skip reg header */
+			dump_buf += BYTES_TO_DWORDS(sizeof(*reg_hdr));
+
+			/* Skip register names until the required reg_id is
+			 * reached.
+			 */
+			for (; reg_id > curr_reg_id;
+			     curr_reg_id++, parsing_str += strlen(parsing_str) +
+			     1);
+
+			results_offset +=
+			    sprintf(qed_get_buf_ptr(results_buf,
+						    results_offset), " %s",
+				    parsing_str);
+			if (i < hdr->num_dumped_cond_regs && is_mem)
+				results_offset +=
+				    sprintf(qed_get_buf_ptr(results_buf,
+							    results_offset),
+					    "[%d]", hdr->mem_entry_id +
+					    reg_hdr->start_entry);
+			results_offset +=
+			    sprintf(qed_get_buf_ptr(results_buf,
+						    results_offset), "=");
+			for (j = 0; j < reg_hdr->size; j++, dump_buf++) {
+				results_offset +=
+				    sprintf(qed_get_buf_ptr(results_buf,
+							    results_offset),
+					    "0x%x", *dump_buf);
+				if (j < reg_hdr->size - 1)
+					results_offset +=
+					    sprintf(qed_get_buf_ptr
+						    (results_buf,
+						     results_offset), ",");
+			}
+		}
+
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf, results_offset), "\n");
+	}
+
+	/* Check if end of dump buffer was exceeded */
+	if (dump_buf > dump_buf_end)
+		return 0;
+
+	return results_offset;
+}
+
+/* Parses an idle check dump buffer.
+ * If result_buf is not NULL, the idle check results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+					       u32 *dump_buf,
+					       u32 num_dumped_dwords,
+					       char *results_buf,
+					       u32 *parsed_results_bytes,
+					       u32 *num_errors,
+					       u32 *num_warnings)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 *dump_buf_end = dump_buf + num_dumped_dwords;
+	u32 num_section_params = 0, num_rules;
+
+	/* Offset in results_buf in bytes */
+	u32 results_offset = 0;
+
+	*parsed_results_bytes = 0;
+	*num_errors = 0;
+	*num_warnings = 0;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_PARSING_DATA].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read idle_chk section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "idle_chk") || num_section_params != 1)
+		return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &num_rules);
+	if (strcmp(param_name, "num_rules"))
+		return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+
+	if (num_rules) {
+		u32 rules_print_size;
+
+		/* Print FW output */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "FW_IDLE_CHECK:\n");
+		rules_print_size =
+			qed_parse_idle_chk_dump_rules(p_hwfn,
+						      dump_buf,
+						      dump_buf_end,
+						      num_rules,
+						      true,
+						      results_buf ?
+						      results_buf +
+						      results_offset :
+						      NULL,
+						      num_errors,
+						      num_warnings);
+		results_offset += rules_print_size;
+		if (!rules_print_size)
+			return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+
+		/* Print LSI output */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nLSI_IDLE_CHECK:\n");
+		rules_print_size =
+			qed_parse_idle_chk_dump_rules(p_hwfn,
+						      dump_buf,
+						      dump_buf_end,
+						      num_rules,
+						      false,
+						      results_buf ?
+						      results_buf +
+						      results_offset :
+						      NULL,
+						      num_errors,
+						      num_warnings);
+		results_offset += rules_print_size;
+		if (!rules_print_size)
+			return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+	}
+
+	/* Print errors/warnings count */
+	if (*num_errors)
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nIdle Check failed!!! (with %d errors and %d warnings)\n",
+			    *num_errors, *num_warnings);
+	else if (*num_warnings)
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nIdle Check completed successfully (with %d warnings)\n",
+			    *num_warnings);
+	else
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nIdle Check completed successfully\n");
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+/* Allocates and fills MCP Trace meta data based on the specified meta data
+ * dump buffer.
+ * Returns debug status code.
+ */
+static enum dbg_status
+qed_mcp_trace_alloc_meta_data(struct ecore_hwfn *p_hwfn,
+			      const u32 *meta_buf)
+{
+	struct dbg_tools_user_data *dev_user_data;
+	u32 offset = 0, signature, i;
+	struct mcp_trace_meta *meta;
+	u8 *meta_buf_bytes = (u8 *)(osal_uintptr_t)meta_buf;
+
+	dev_user_data = qed_dbg_get_user_data(p_hwfn);
+	meta = &dev_user_data->mcp_trace_meta;
+
+	/* Free the previous meta before loading a new one. */
+	if (meta->is_allocated)
+		qed_mcp_trace_free_meta_data(p_hwfn);
+
+	OSAL_MEMSET(meta, 0, sizeof(*meta));
+
+	/* Read first signature */
+	signature = qed_read_dword_from_buf(meta_buf_bytes, &offset);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Read no. of modules and allocate memory for their pointers */
+	meta->modules_num = qed_read_byte_from_buf(meta_buf_bytes, &offset);
+	meta->modules = (char **)OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
+				    meta->modules_num * sizeof(char *));
+	if (!meta->modules)
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	/* Allocate and read all module strings */
+	for (i = 0; i < meta->modules_num; i++) {
+		u8 module_len = qed_read_byte_from_buf(meta_buf_bytes, &offset);
+
+		*(meta->modules + i) = (char *)OSAL_ZALLOC(p_hwfn->p_dev,
+							   GFP_KERNEL,
+							   module_len);
+		if (!(*(meta->modules + i))) {
+			/* Update number of modules to be released */
+			meta->modules_num = i ? i - 1 : 0;
+			return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+		}
+
+		qed_read_str_from_buf(meta_buf_bytes, &offset, module_len,
+				      *(meta->modules + i));
+		if (module_len > MCP_TRACE_MAX_MODULE_LEN)
+			(*(meta->modules + i))[MCP_TRACE_MAX_MODULE_LEN] = '\0';
+	}
+
+	/* Read second signature */
+	signature = qed_read_dword_from_buf(meta_buf_bytes, &offset);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Read number of formats and allocate memory for all formats */
+	meta->formats_num = qed_read_dword_from_buf(meta_buf_bytes, &offset);
+	meta->formats =
+		(struct mcp_trace_format *)OSAL_ZALLOC(p_hwfn->p_dev,
+						       GFP_KERNEL,
+						       meta->formats_num *
+					       sizeof(struct mcp_trace_format));
+	if (!meta->formats)
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	/* Allocate and read all strings */
+	for (i = 0; i < meta->formats_num; i++) {
+		struct mcp_trace_format *format_ptr = &meta->formats[i];
+		u8 format_len;
+
+		format_ptr->data = qed_read_dword_from_buf(meta_buf_bytes,
+							   &offset);
+		format_len = GET_MFW_FIELD(format_ptr->data,
+					   MCP_TRACE_FORMAT_LEN);
+		format_ptr->format_str = (char *)OSAL_ZALLOC(p_hwfn->p_dev,
+							     GFP_KERNEL,
+							     format_len);
+		if (!format_ptr->format_str) {
+			/* Update number of modules to be released */
+			meta->formats_num = i ? i - 1 : 0;
+			return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+		}
+
+		qed_read_str_from_buf(meta_buf_bytes,
+				      &offset,
+				      format_len, format_ptr->format_str);
+	}
+
+	meta->is_allocated = true;
+	return DBG_STATUS_OK;
+}
+
+/* Parses an MCP trace buffer. If result_buf is not NULL, the MCP Trace results
+ * are printed to it. The parsing status is returned.
+ * Arguments:
+ * trace_buf - MCP trace cyclic buffer
+ * trace_buf_size - MCP trace cyclic buffer size in bytes
+ * data_offset - offset in bytes of the data to parse in the MCP trace cyclic
+ *		 buffer.
+ * data_size - size in bytes of data to parse.
+ * parsed_buf - destination buffer for parsed data.
+ * parsed_results_bytes - size of parsed data in bytes.
+ */
+static enum dbg_status qed_parse_mcp_trace_buf(struct ecore_hwfn *p_hwfn,
+					       u8 *trace_buf,
+					       u32 trace_buf_size,
+					       u32 data_offset,
+					       u32 data_size,
+					       char *parsed_buf,
+					       u32 *parsed_results_bytes)
+{
+	struct dbg_tools_user_data *dev_user_data;
+	struct mcp_trace_meta *meta;
+	u32 param_mask, param_shift;
+	enum dbg_status status;
+
+	dev_user_data = qed_dbg_get_user_data(p_hwfn);
+	meta = &dev_user_data->mcp_trace_meta;
+	*parsed_results_bytes = 0;
+
+	if (!meta->is_allocated)
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+	status = DBG_STATUS_OK;
+
+	while (data_size) {
+		struct mcp_trace_format *format_ptr;
+		u8 format_level, format_module;
+		u32 params[3] = { 0, 0, 0 };
+		u32 header, format_idx, i;
+
+		if (data_size < MFW_TRACE_ENTRY_SIZE)
+			return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+		header = qed_read_from_cyclic_buf(trace_buf,
+						  &data_offset,
+						  trace_buf_size,
+						  MFW_TRACE_ENTRY_SIZE);
+		data_size -= MFW_TRACE_ENTRY_SIZE;
+		format_idx = header & MFW_TRACE_EVENTID_MASK;
+
+		/* Skip message if its index doesn't exist in the meta data */
+		if (format_idx >= meta->formats_num) {
+			u8 format_size = (u8)GET_MFW_FIELD(header,
+							   MFW_TRACE_PRM_SIZE);
+
+			if (data_size < format_size)
+				return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+			data_offset = qed_cyclic_add(data_offset,
+						     format_size,
+						     trace_buf_size);
+			data_size -= format_size;
+			continue;
+		}
+
+		format_ptr =
+			(struct mcp_trace_format *)&meta->formats[format_idx];
+
+		for (i = 0,
+		     param_mask = MCP_TRACE_FORMAT_P1_SIZE_MASK, param_shift =
+		     MCP_TRACE_FORMAT_P1_SIZE_OFFSET;
+		     i < MCP_TRACE_FORMAT_MAX_PARAMS;
+		     i++, param_mask <<= MCP_TRACE_FORMAT_PARAM_WIDTH,
+		     param_shift += MCP_TRACE_FORMAT_PARAM_WIDTH) {
+			/* Extract param size (0..3) */
+			u8 param_size = (u8)((format_ptr->data & param_mask) >>
+					     param_shift);
+
+			/* If the param size is zero, there are no other
+			 * parameters.
+			 */
+			if (!param_size)
+				break;
+
+			/* Size is encoded using 2 bits, where 3 is used to
+			 * encode 4.
+			 */
+			if (param_size == 3)
+				param_size = 4;
+
+			if (data_size < param_size)
+				return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+			params[i] = qed_read_from_cyclic_buf(trace_buf,
+							     &data_offset,
+							     trace_buf_size,
+							     param_size);
+			data_size -= param_size;
+		}
+
+		format_level = (u8)GET_MFW_FIELD(format_ptr->data,
+						 MCP_TRACE_FORMAT_LEVEL);
+		format_module = (u8)GET_MFW_FIELD(format_ptr->data,
+						  MCP_TRACE_FORMAT_MODULE);
+		if (format_level >= OSAL_ARRAY_SIZE(s_mcp_trace_level_str))
+			return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+		/* Print current message to results buffer */
+		*parsed_results_bytes +=
+			OSAL_SPRINTF(qed_get_buf_ptr(parsed_buf,
+						*parsed_results_bytes),
+				"%s %-8s: ",
+				s_mcp_trace_level_str[format_level],
+				meta->modules[format_module]);
+		*parsed_results_bytes +=
+		    sprintf(qed_get_buf_ptr(parsed_buf, *parsed_results_bytes),
+			    format_ptr->format_str,
+			    params[0], params[1], params[2]);
+	}
+
+	/* Add string NULL terminator */
+	(*parsed_results_bytes)++;
+
+	return status;
+}
+
+/* Parses an MCP Trace dump buffer.
+ * If result_buf is not NULL, the MCP Trace results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+						u32 *dump_buf,
+						char *results_buf,
+						u32 *parsed_results_bytes,
+						bool free_meta_data)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 data_size, trace_data_dwords, trace_meta_dwords;
+	u32 offset, results_offset, results_buf_bytes;
+	u32 param_num_val, num_section_params;
+	struct mcp_trace *trace;
+	enum dbg_status status;
+	const u32 *meta_buf;
+	u8 *trace_buf;
+
+	*parsed_results_bytes = 0;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read trace_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "mcp_trace_data") || num_section_params != 1)
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	trace_data_dwords = param_num_val;
+
+	/* Prepare trace info */
+	trace = (struct mcp_trace *)dump_buf;
+	if (trace->signature != MFW_TRACE_SIGNATURE || !trace->size)
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+	trace_buf = (u8 *)dump_buf + sizeof(*trace);
+	offset = trace->trace_oldest;
+	data_size = qed_cyclic_sub(trace->trace_prod, offset, trace->size);
+	dump_buf += trace_data_dwords;
+
+	/* Read meta_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "mcp_trace_meta"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	trace_meta_dwords = param_num_val;
+
+	/* Choose meta data buffer */
+	if (!trace_meta_dwords) {
+		/* Dump doesn't include meta data */
+		struct dbg_tools_user_data *dev_user_data =
+			qed_dbg_get_user_data(p_hwfn);
+
+		if (!dev_user_data->mcp_trace_user_meta_buf)
+			return DBG_STATUS_MCP_TRACE_NO_META;
+
+		meta_buf = dev_user_data->mcp_trace_user_meta_buf;
+	} else {
+		/* Dump includes meta data */
+		meta_buf = dump_buf;
+	}
+
+	/* Allocate meta data memory */
+	status = qed_mcp_trace_alloc_meta_data(p_hwfn, meta_buf);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	status = qed_parse_mcp_trace_buf(p_hwfn,
+					 trace_buf,
+					 trace->size,
+					 offset,
+					 data_size,
+					 results_buf ?
+					 results_buf + results_offset :
+					 NULL,
+					 &results_buf_bytes);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (free_meta_data)
+		qed_mcp_trace_free_meta_data(p_hwfn);
+
+	*parsed_results_bytes = results_offset + results_buf_bytes;
+
+	return DBG_STATUS_OK;
+}
+
+/* Parses a Reg FIFO dump buffer.
+ * If result_buf is not NULL, the Reg FIFO results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_reg_fifo_dump(u32 *dump_buf,
+					       char *results_buf,
+					       u32 *parsed_results_bytes)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 param_num_val, num_section_params, num_elements;
+	struct reg_fifo_element *elements;
+	u8 i, j, err_code, vf_val;
+	u32 results_offset = 0;
+	char vf_str[4];
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read reg_fifo_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "reg_fifo_data"))
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+	if (param_num_val % REG_FIFO_ELEMENT_DWORDS)
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+	num_elements = param_num_val / REG_FIFO_ELEMENT_DWORDS;
+	elements = (struct reg_fifo_element *)dump_buf;
+
+	/* Decode elements */
+	for (i = 0; i < num_elements; i++) {
+		const char *err_msg = NULL;
+
+		/* Discover if element belongs to a VF or a PF */
+		vf_val = GET_FIELD(elements[i].data, REG_FIFO_ELEMENT_VF);
+		if (vf_val == REG_FIFO_ELEMENT_IS_PF_VF_VAL)
+			sprintf(vf_str, "%s", "N/A");
+		else
+			sprintf(vf_str, "%d", vf_val);
+
+		/* Find error message */
+		err_code = GET_FIELD(elements[i].data, REG_FIFO_ELEMENT_ERROR);
+		for (j = 0; j < OSAL_ARRAY_SIZE(s_reg_fifo_errors) && !err_msg;
+		     j++)
+			if (err_code == s_reg_fifo_errors[j].err_code)
+				err_msg = s_reg_fifo_errors[j].err_msg;
+
+		/* Add parsed element to parsed buffer */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "raw: 0x%016lx, address: 0x%07x, access: %-5s, pf: %2d, vf: %s, port: %d, privilege: %-3s, protection: %-12s, master: %-4s, error: %s\n",
+			    elements[i].data,
+			    (u32)GET_FIELD(elements[i].data,
+					   REG_FIFO_ELEMENT_ADDRESS) *
+			    REG_FIFO_ELEMENT_ADDR_FACTOR,
+			    s_access_strs[GET_FIELD(elements[i].data,
+						    REG_FIFO_ELEMENT_ACCESS)],
+			    (u32)GET_FIELD(elements[i].data,
+					   REG_FIFO_ELEMENT_PF),
+			    vf_str,
+			    (u32)GET_FIELD(elements[i].data,
+					   REG_FIFO_ELEMENT_PORT),
+			    s_privilege_strs[GET_FIELD(elements[i].data,
+						REG_FIFO_ELEMENT_PRIVILEGE)],
+			    s_protection_strs[GET_FIELD(elements[i].data,
+						REG_FIFO_ELEMENT_PROTECTION)],
+			    s_master_strs[GET_FIELD(elements[i].data,
+						    REG_FIFO_ELEMENT_MASTER)],
+			    err_msg ? err_msg : "unknown error code");
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						  results_offset),
+				  "fifo contained %d elements", num_elements);
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status qed_parse_igu_fifo_element(struct igu_fifo_element
+						  *element, char
+						  *results_buf,
+						  u32 *results_offset)
+{
+	const struct igu_fifo_addr_data *found_addr = NULL;
+	u8 source, err_type, i, is_cleanup;
+	char parsed_addr_data[32];
+	char parsed_wr_data[256];
+	u32 wr_data, prod_cons;
+	bool is_wr_cmd, is_pf;
+	u16 cmd_addr;
+	u64 dword12;
+
+	/* Dword12 (dword index 1 and 2) contains bits 32..95 of the
+	 * FIFO element.
+	 */
+	dword12 = ((u64)element->dword2 << 32) | element->dword1;
+	is_wr_cmd = GET_FIELD(dword12, IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD);
+	is_pf = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_IS_PF);
+	cmd_addr = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR);
+	source = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_SOURCE);
+	err_type = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE);
+
+	if (source >= OSAL_ARRAY_SIZE(s_igu_fifo_source_strs))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	if (err_type >= OSAL_ARRAY_SIZE(s_igu_fifo_error_strs))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+
+	/* Find address data */
+	for (i = 0; i < OSAL_ARRAY_SIZE(s_igu_fifo_addr_data) && !found_addr;
+	     i++) {
+		const struct igu_fifo_addr_data *curr_addr =
+			&s_igu_fifo_addr_data[i];
+
+		if (cmd_addr >= curr_addr->start_addr && cmd_addr <=
+		    curr_addr->end_addr)
+			found_addr = curr_addr;
+	}
+
+	if (!found_addr)
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+
+	/* Prepare parsed address data */
+	switch (found_addr->type) {
+	case IGU_ADDR_TYPE_MSIX_MEM:
+		sprintf(parsed_addr_data, " vector_num = 0x%x", cmd_addr / 2);
+		break;
+	case IGU_ADDR_TYPE_WRITE_INT_ACK:
+	case IGU_ADDR_TYPE_WRITE_PROD_UPDATE:
+		sprintf(parsed_addr_data,
+			" SB = 0x%x", cmd_addr - found_addr->start_addr);
+		break;
+	default:
+		parsed_addr_data[0] = '\0';
+	}
+
+	if (!is_wr_cmd) {
+		parsed_wr_data[0] = '\0';
+		goto out;
+	}
+
+	/* Prepare parsed write data */
+	wr_data = GET_FIELD(dword12, IGU_FIFO_ELEMENT_DWORD12_WR_DATA);
+	prod_cons = GET_FIELD(wr_data, IGU_FIFO_WR_DATA_PROD_CONS);
+	is_cleanup = GET_FIELD(wr_data, IGU_FIFO_WR_DATA_CMD_TYPE);
+
+	if (source == IGU_SRC_ATTN) {
+		sprintf(parsed_wr_data, "prod: 0x%x, ", prod_cons);
+	} else {
+		if (is_cleanup) {
+			u8 cleanup_val, cleanup_type;
+
+			cleanup_val =
+				GET_FIELD(wr_data,
+					  IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL);
+			cleanup_type =
+			    GET_FIELD(wr_data,
+				      IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE);
+
+			sprintf(parsed_wr_data,
+				"cmd_type: cleanup, cleanup_val: %s, cleanup_type : %d, ",
+				cleanup_val ? "set" : "clear",
+				cleanup_type);
+		} else {
+			u8 update_flag, en_dis_int_for_sb, segment;
+			u8 timer_mask;
+
+			update_flag = GET_FIELD(wr_data,
+						IGU_FIFO_WR_DATA_UPDATE_FLAG);
+			en_dis_int_for_sb =
+				GET_FIELD(wr_data,
+					  IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB);
+			segment = GET_FIELD(wr_data,
+					    IGU_FIFO_WR_DATA_SEGMENT);
+			timer_mask = GET_FIELD(wr_data,
+					       IGU_FIFO_WR_DATA_TIMER_MASK);
+
+			sprintf(parsed_wr_data,
+				"cmd_type: prod/cons update, prod/cons: 0x%x, update_flag: %s, en_dis_int_for_sb : %s, segment : %s, timer_mask = %d, ",
+				prod_cons,
+				update_flag ? "update" : "nop",
+				en_dis_int_for_sb ?
+				(en_dis_int_for_sb == 1 ? "disable" : "nop") :
+				"enable",
+				segment ? "attn" : "regular",
+				timer_mask);
+		}
+	}
+out:
+	/* Add parsed element to parsed buffer */
+	*results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						   *results_offset),
+				   "raw: 0x%01x%08x%08x, %s: %d, source : %s, type : %s, cmd_addr : 0x%x(%s%s), %serror: %s\n",
+				   element->dword2, element->dword1,
+				   element->dword0,
+				   is_pf ? "pf" : "vf",
+				   GET_FIELD(element->dword0,
+					     IGU_FIFO_ELEMENT_DWORD0_FID),
+				   s_igu_fifo_source_strs[source],
+				   is_wr_cmd ? "wr" : "rd",
+				   cmd_addr,
+				   (!is_pf && found_addr->vf_desc)
+				   ? found_addr->vf_desc
+				   : found_addr->desc,
+				   parsed_addr_data,
+				   parsed_wr_data,
+				   s_igu_fifo_error_strs[err_type]);
+
+	return DBG_STATUS_OK;
+}
+
+/* Parses an IGU FIFO dump buffer.
+ * If result_buf is not NULL, the IGU FIFO results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_igu_fifo_dump(u32 *dump_buf,
+					       char *results_buf,
+					       u32 *parsed_results_bytes)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 param_num_val, num_section_params, num_elements;
+	struct igu_fifo_element *elements;
+	enum dbg_status status;
+	u32 results_offset = 0;
+	u8 i;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read igu_fifo_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "igu_fifo_data"))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	if (param_num_val % IGU_FIFO_ELEMENT_DWORDS)
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	num_elements = param_num_val / IGU_FIFO_ELEMENT_DWORDS;
+	elements = (struct igu_fifo_element *)dump_buf;
+
+	/* Decode elements */
+	for (i = 0; i < num_elements; i++) {
+		status = qed_parse_igu_fifo_element(&elements[i],
+						    results_buf,
+						    &results_offset);
+		if (status != DBG_STATUS_OK)
+			return status;
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						  results_offset),
+				  "fifo contained %d elements", num_elements);
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status
+qed_parse_protection_override_dump(u32 *dump_buf,
+				   char *results_buf,
+				   u32 *parsed_results_bytes)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 param_num_val, num_section_params, num_elements;
+	struct protection_override_element *elements;
+	u32 results_offset = 0;
+	u8 i;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read protection_override_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "protection_override_data"))
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+	if (param_num_val % PROTECTION_OVERRIDE_ELEMENT_DWORDS)
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+	num_elements = param_num_val / PROTECTION_OVERRIDE_ELEMENT_DWORDS;
+	elements = (struct protection_override_element *)dump_buf;
+
+	/* Decode elements */
+	for (i = 0; i < num_elements; i++) {
+		u32 address = GET_FIELD(elements[i].data,
+					PROTECTION_OVERRIDE_ELEMENT_ADDRESS) *
+			      PROTECTION_OVERRIDE_ELEMENT_ADDR_FACTOR;
+
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "window %2d, address: 0x%07x, size: %7d regs, read: %d, write: %d, read protection: %-12s, write protection: %-12s\n",
+			    i, address,
+			    (u32)GET_FIELD(elements[i].data,
+				      PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE),
+			    (u32)GET_FIELD(elements[i].data,
+				      PROTECTION_OVERRIDE_ELEMENT_READ),
+			    (u32)GET_FIELD(elements[i].data,
+				      PROTECTION_OVERRIDE_ELEMENT_WRITE),
+			    s_protection_strs[GET_FIELD(elements[i].data,
+				PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION)],
+			    s_protection_strs[GET_FIELD(elements[i].data,
+				PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION)]);
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						  results_offset),
+				  "protection override contained %d elements",
+				  num_elements);
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+/* Parses a FW Asserts dump buffer.
+ * If result_buf is not NULL, the FW Asserts results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_fw_asserts_dump(u32 *dump_buf,
+						 char *results_buf,
+						 u32 *parsed_results_bytes)
+{
+	u32 num_section_params, param_num_val, i, results_offset = 0;
+	const char *param_name, *param_str_val, *section_name;
+	bool last_section_found = false;
+
+	*parsed_results_bytes = 0;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	while (!last_section_found) {
+		dump_buf += qed_read_section_hdr(dump_buf,
+						 &section_name,
+						 &num_section_params);
+		if (!strcmp(section_name, "fw_asserts")) {
+			/* Extract params */
+			const char *storm_letter = NULL;
+			u32 storm_dump_size = 0;
+
+			for (i = 0; i < num_section_params; i++) {
+				dump_buf += qed_read_param(dump_buf,
+							   &param_name,
+							   &param_str_val,
+							   &param_num_val);
+				if (!strcmp(param_name, "storm"))
+					storm_letter = param_str_val;
+				else if (!strcmp(param_name, "size"))
+					storm_dump_size = param_num_val;
+				else
+					return
+					    DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+			}
+
+			if (!storm_letter || !storm_dump_size)
+				return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+
+			/* Print data */
+			results_offset +=
+			    sprintf(qed_get_buf_ptr(results_buf,
+						    results_offset),
+				    "\n%sSTORM_ASSERT: size=%d\n",
+				    storm_letter, storm_dump_size);
+			for (i = 0; i < storm_dump_size; i++, dump_buf++)
+				results_offset +=
+				    sprintf(qed_get_buf_ptr(results_buf,
+							    results_offset),
+					    "%08x\n", *dump_buf);
+		} else if (!strcmp(section_name, "last")) {
+			last_section_found = true;
+		} else {
+			return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+		}
+	}
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+/***************************** Public Functions *******************************/
+
+enum dbg_status qed_dbg_user_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+					 const u8 * const bin_ptr)
+{
+	struct bin_buffer_hdr *buf_hdrs =
+			(struct bin_buffer_hdr *)(osal_uintptr_t)bin_ptr;
+	u8 buf_id;
+
+	/* Convert binary data to debug arrays */
+	for (buf_id = 0; buf_id < MAX_BIN_DBG_BUFFER_TYPE; buf_id++)
+		qed_set_dbg_bin_buf(p_hwfn,
+				    (enum bin_dbg_buffer_type)buf_id,
+				    (const u32 *)(bin_ptr +
+						  buf_hdrs[buf_id].offset),
+						  buf_hdrs[buf_id].length);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_alloc_user_data(__rte_unused struct ecore_hwfn *p_hwfn,
+					void **user_data_ptr)
+{
+	*user_data_ptr = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
+				     sizeof(struct dbg_tools_user_data));
+	if (!(*user_data_ptr))
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	return DBG_STATUS_OK;
+}
+
+const char *qed_dbg_get_status_str(enum dbg_status status)
+{
+	return (status <
+		MAX_DBG_STATUS) ? s_status_str[status] : "Invalid debug status";
+}
+
+enum dbg_status qed_get_idle_chk_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32 num_dumped_dwords,
+						  u32 *results_buf_size)
+{
+	u32 num_errors, num_warnings;
+
+	return qed_parse_idle_chk_dump(p_hwfn,
+				       dump_buf,
+				       num_dumped_dwords,
+				       NULL,
+				       results_buf_size,
+				       &num_errors, &num_warnings);
+}
+
+enum dbg_status qed_print_idle_chk_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf,
+					   u32 *num_errors,
+					   u32 *num_warnings)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_idle_chk_dump(p_hwfn,
+				       dump_buf,
+				       num_dumped_dwords,
+				       results_buf,
+				       &parsed_buf_size,
+				       num_errors, num_warnings);
+}
+
+void qed_dbg_mcp_trace_set_meta_data(struct ecore_hwfn *p_hwfn,
+				     const u32 *meta_buf)
+{
+	struct dbg_tools_user_data *dev_user_data =
+		qed_dbg_get_user_data(p_hwfn);
+
+	dev_user_data->mcp_trace_user_meta_buf = meta_buf;
+}
+
+enum dbg_status
+qed_get_mcp_trace_results_buf_size(struct ecore_hwfn *p_hwfn,
+				   u32 *dump_buf,
+				   __rte_unused u32 num_dumped_dwords,
+				   u32 *results_buf_size)
+{
+	return qed_parse_mcp_trace_dump(p_hwfn,
+					dump_buf, NULL, results_buf_size, true);
+}
+
+enum dbg_status qed_print_mcp_trace_results(struct ecore_hwfn *p_hwfn,
+					    u32 *dump_buf,
+					    __rte_unused u32 num_dumped_dwords,
+					    char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_mcp_trace_dump(p_hwfn,
+					dump_buf,
+					results_buf, &parsed_buf_size, true);
+}
+
+enum dbg_status qed_print_mcp_trace_results_cont(struct ecore_hwfn *p_hwfn,
+						 u32 *dump_buf,
+						 char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_mcp_trace_dump(p_hwfn, dump_buf, results_buf,
+					&parsed_buf_size, false);
+}
+
+enum dbg_status qed_print_mcp_trace_line(struct ecore_hwfn *p_hwfn,
+					 u8 *dump_buf,
+					 u32 num_dumped_bytes,
+					 char *results_buf)
+{
+	u32 parsed_results_bytes;
+
+	return qed_parse_mcp_trace_buf(p_hwfn,
+				       dump_buf,
+				       num_dumped_bytes,
+				       0,
+				       num_dumped_bytes,
+				       results_buf, &parsed_results_bytes);
+}
+
+/* Frees the specified MCP Trace meta data */
+void qed_mcp_trace_free_meta_data(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_user_data *dev_user_data;
+	struct mcp_trace_meta *meta;
+	u32 i;
+
+	dev_user_data = qed_dbg_get_user_data(p_hwfn);
+	meta = &dev_user_data->mcp_trace_meta;
+	if (!meta->is_allocated)
+		return;
+
+	/* Release modules */
+	if (meta->modules) {
+		for (i = 0; i < meta->modules_num; i++)
+			OSAL_FREE(p_hwfn, meta->modules[i]);
+		OSAL_FREE(p_hwfn, meta->modules);
+	}
+
+	/* Release formats */
+	if (meta->formats) {
+		for (i = 0; i < meta->formats_num; i++)
+			OSAL_FREE(p_hwfn, meta->formats[i].format_str);
+		OSAL_FREE(p_hwfn, meta->formats);
+	}
+
+	meta->is_allocated = false;
+}
+
+enum dbg_status
+qed_get_reg_fifo_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
+				  u32 *dump_buf,
+				  __rte_unused u32 num_dumped_dwords,
+				  u32 *results_buf_size)
+{
+	return qed_parse_reg_fifo_dump(dump_buf, NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_reg_fifo_results(__rte_unused struct ecore_hwfn *p_hwfn,
+			   u32 *dump_buf,
+			   __rte_unused u32 num_dumped_dwords,
+			   char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_reg_fifo_dump(dump_buf, results_buf, &parsed_buf_size);
+}
+
+enum dbg_status
+qed_get_igu_fifo_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
+				  u32 *dump_buf,
+				  __rte_unused u32 num_dumped_dwords,
+				  u32 *results_buf_size)
+{
+	return qed_parse_igu_fifo_dump(dump_buf, NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_igu_fifo_results(__rte_unused struct ecore_hwfn *p_hwfn,
+			   u32 *dump_buf,
+			   __rte_unused u32 num_dumped_dwords,
+			   char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_igu_fifo_dump(dump_buf, results_buf, &parsed_buf_size);
+}
+
+enum dbg_status
+qed_get_protection_override_results_buf_size(__rte_unused
+					     struct ecore_hwfn *p_hwfn,
+					     u32 *dump_buf,
+					     __rte_unused u32 num_dumped_dwords,
+					     u32 *results_buf_size)
+{
+	return qed_parse_protection_override_dump(dump_buf,
+						  NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_protection_override_results(__rte_unused struct ecore_hwfn *p_hwfn,
+				      u32 *dump_buf,
+				      __rte_unused u32 num_dumped_dwords,
+				      char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_protection_override_dump(dump_buf,
+						  results_buf,
+						  &parsed_buf_size);
+}
+
+enum dbg_status
+qed_get_fw_asserts_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
+				    u32 *dump_buf,
+				    __rte_unused u32 num_dumped_dwords,
+				    u32 *results_buf_size)
+{
+	return qed_parse_fw_asserts_dump(dump_buf, NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_fw_asserts_results(__rte_unused struct ecore_hwfn *p_hwfn,
+			     u32 *dump_buf,
+			     __rte_unused u32 num_dumped_dwords,
+			     char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_fw_asserts_dump(dump_buf,
+					 results_buf, &parsed_buf_size);
+}
+
+enum dbg_status qed_dbg_parse_attn(struct ecore_hwfn *p_hwfn,
+				   struct dbg_attn_block_result *results)
+{
+	const u32 *block_attn_name_offsets;
+	const char *attn_name_base;
+	const char *block_name;
+	enum dbg_attn_type attn_type;
+	u8 num_regs, i, j;
+
+	num_regs = GET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_NUM_REGS);
+	attn_type = GET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_ATTN_TYPE);
+	block_name = qed_dbg_get_block_name(p_hwfn, results->block_id);
+	if (!block_name)
+		return DBG_STATUS_INVALID_ARGS;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_INDEXES].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_NAME_OFFSETS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	block_attn_name_offsets =
+	    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_NAME_OFFSETS].ptr +
+	    results->names_offset;
+
+	attn_name_base = p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr;
+
+	/* Go over registers with a non-zero attention status */
+	for (i = 0; i < num_regs; i++) {
+		struct dbg_attn_bit_mapping *bit_mapping;
+		struct dbg_attn_reg_result *reg_result;
+		u8 num_reg_attn, bit_idx = 0;
+
+		reg_result = &results->reg_results[i];
+		num_reg_attn = GET_FIELD(reg_result->data,
+					 DBG_ATTN_REG_RESULT_NUM_REG_ATTN);
+		bit_mapping = (struct dbg_attn_bit_mapping *)
+		    p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_INDEXES].ptr +
+		    reg_result->block_attn_offset;
+
+		/* Go over attention status bits */
+		for (j = 0; j < num_reg_attn; j++, bit_idx++) {
+			u16 attn_idx_val = GET_FIELD(bit_mapping[j].data,
+						     DBG_ATTN_BIT_MAPPING_VAL);
+			const char *attn_name, *attn_type_str, *masked_str;
+			u32 attn_name_offset;
+			u32 sts_addr;
+
+			/* Check if bit mask should be advanced (due to unused
+			 * bits).
+			 */
+			if (GET_FIELD(bit_mapping[j].data,
+				      DBG_ATTN_BIT_MAPPING_IS_UNUSED_BIT_CNT)) {
+				bit_idx += (u8)attn_idx_val;
+				continue;
+			}
+
+			/* Check current bit index */
+			if (!(reg_result->sts_val & OSAL_BIT(bit_idx)))
+				continue;
+
+			/* An attention bit with value=1 was found
+			 * Find attention name
+			 */
+			attn_name_offset =
+				block_attn_name_offsets[attn_idx_val];
+			attn_name = attn_name_base + attn_name_offset;
+			attn_type_str =
+				(attn_type ==
+				 ATTN_TYPE_INTERRUPT ? "Interrupt" :
+				 "Parity");
+			masked_str = reg_result->mask_val & OSAL_BIT(bit_idx) ?
+				     " [masked]" : "";
+			sts_addr = GET_FIELD(reg_result->data,
+					     DBG_ATTN_REG_RESULT_STS_ADDRESS);
+			DP_NOTICE(p_hwfn, false,
+				  "%s (%s) : %s [address 0x%08x, bit %d]%s\n",
+				  block_name, attn_type_str, attn_name,
+				  sts_addr * 4, bit_idx, masked_str);
+		}
+	}
+
+	return DBG_STATUS_OK;
+}
+
+/* Wrapper for unifying the idle_chk and mcp_trace api */
+static enum dbg_status
+qed_print_idle_chk_results_wrapper(struct ecore_hwfn *p_hwfn,
+				   u32 *dump_buf,
+				   u32 num_dumped_dwords,
+				   char *results_buf)
+{
+	u32 num_errors, num_warnnings;
+
+	return qed_print_idle_chk_results(p_hwfn, dump_buf, num_dumped_dwords,
+					  results_buf, &num_errors,
+					  &num_warnnings);
+}
+
+/* Feature meta data lookup table */
+static struct {
+	const char *name;
+	enum dbg_status (*get_size)(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt, u32 *size);
+	enum dbg_status (*perform_dump)(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt, u32 *dump_buf,
+					u32 buf_size, u32 *dumped_dwords);
+	enum dbg_status (*print_results)(struct ecore_hwfn *p_hwfn,
+					 u32 *dump_buf, u32 num_dumped_dwords,
+					 char *results_buf);
+	enum dbg_status (*results_buf_size)(struct ecore_hwfn *p_hwfn,
+					    u32 *dump_buf,
+					    u32 num_dumped_dwords,
+					    u32 *results_buf_size);
+} qed_features_lookup[] = {
+	{
+	"grc", qed_dbg_grc_get_dump_buf_size,
+		    qed_dbg_grc_dump, NULL, NULL}, {
+	"idle_chk",
+		    qed_dbg_idle_chk_get_dump_buf_size,
+		    qed_dbg_idle_chk_dump,
+		    qed_print_idle_chk_results_wrapper,
+		    qed_get_idle_chk_results_buf_size}, {
+	"mcp_trace",
+		    qed_dbg_mcp_trace_get_dump_buf_size,
+		    qed_dbg_mcp_trace_dump, qed_print_mcp_trace_results,
+		    qed_get_mcp_trace_results_buf_size}, {
+	"reg_fifo",
+		    qed_dbg_reg_fifo_get_dump_buf_size,
+		    qed_dbg_reg_fifo_dump, qed_print_reg_fifo_results,
+		    qed_get_reg_fifo_results_buf_size}, {
+	"igu_fifo",
+		    qed_dbg_igu_fifo_get_dump_buf_size,
+		    qed_dbg_igu_fifo_dump, qed_print_igu_fifo_results,
+		    qed_get_igu_fifo_results_buf_size}, {
+	"protection_override",
+		    qed_dbg_protection_override_get_dump_buf_size,
+		    qed_dbg_protection_override_dump,
+		    qed_print_protection_override_results,
+		    qed_get_protection_override_results_buf_size}, {
+	"fw_asserts",
+		    qed_dbg_fw_asserts_get_dump_buf_size,
+		    qed_dbg_fw_asserts_dump,
+		    qed_print_fw_asserts_results,
+		    qed_get_fw_asserts_results_buf_size}, {
+	"ilt",
+		    qed_dbg_ilt_get_dump_buf_size,
+		    qed_dbg_ilt_dump, NULL, NULL},};
+
+#define QED_RESULTS_BUF_MIN_SIZE 16
+/* Generic function for decoding debug feature info */
+static enum dbg_status format_feature(struct ecore_hwfn *p_hwfn,
+				      enum ecore_dbg_features feature_idx)
+{
+	struct ecore_dbg_feature *feature =
+	    &p_hwfn->p_dev->dbg_params.features[feature_idx];
+	u32 text_size_bytes, null_char_pos, i;
+	enum dbg_status rc;
+	char *text_buf;
+
+	/* Check if feature supports formatting capability */
+	if (!qed_features_lookup[feature_idx].results_buf_size)
+		return DBG_STATUS_OK;
+
+	/* Obtain size of formatted output */
+	rc = qed_features_lookup[feature_idx].results_buf_size(p_hwfn,
+						(u32 *)feature->dump_buf,
+						feature->dumped_dwords,
+						&text_size_bytes);
+	if (rc != DBG_STATUS_OK)
+		return rc;
+
+	/* Make sure that the allocated size is a multiple of dword (4 bytes) */
+	null_char_pos = text_size_bytes - 1;
+	text_size_bytes = (text_size_bytes + 3) & ~0x3;
+
+	if (text_size_bytes < QED_RESULTS_BUF_MIN_SIZE) {
+		DP_NOTICE(p_hwfn->p_dev, false,
+			  "formatted size of feature was too small %d. Aborting\n",
+			  text_size_bytes);
+		return DBG_STATUS_INVALID_ARGS;
+	}
+
+	/* Allocate temp text buf */
+	text_buf = OSAL_VZALLOC(p_hwfn, text_size_bytes);
+	if (!text_buf) {
+		DP_NOTICE(p_hwfn->p_dev, false,
+			  "failed to allocate text buffer. Aborting\n");
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+	}
+
+	/* Decode feature opcodes to string on temp buf */
+	rc = qed_features_lookup[feature_idx].print_results(p_hwfn,
+						(u32 *)feature->dump_buf,
+						feature->dumped_dwords,
+						text_buf);
+	if (rc != DBG_STATUS_OK) {
+		OSAL_VFREE(p_hwfn, text_buf);
+		return rc;
+	}
+
+	/* Replace the original null character with a '\n' character.
+	 * The bytes that were added as a result of the dword alignment are also
+	 * padded with '\n' characters.
+	 */
+	for (i = null_char_pos; i < text_size_bytes; i++)
+		text_buf[i] = '\n';
+
+
+	/* Free the old dump_buf and point the dump_buf to the newly allocagted
+	 * and formatted text buffer.
+	 */
+	OSAL_VFREE(p_hwfn, feature->dump_buf);
+	feature->dump_buf = (u8 *)text_buf;
+	feature->buf_size = text_size_bytes;
+	feature->dumped_dwords = text_size_bytes / 4;
+	return rc;
+}
+
+#define MAX_DBG_FEATURE_SIZE_DWORDS	0x3FFFFFFF
+
+/* Generic function for performing the dump of a debug feature. */
+static enum dbg_status qed_dbg_dump(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    enum ecore_dbg_features feature_idx)
+{
+	struct ecore_dbg_feature *feature =
+	    &p_hwfn->p_dev->dbg_params.features[feature_idx];
+	u32 buf_size_dwords;
+	enum dbg_status rc;
+
+	DP_NOTICE(p_hwfn->p_dev, false, "Collecting a debug feature [\"%s\"]\n",
+		  qed_features_lookup[feature_idx].name);
+
+	/* Dump_buf was already allocated need to free (this can happen if dump
+	 * was called but file was never read).
+	 * We can't use the buffer as is since size may have changed.
+	 */
+	if (feature->dump_buf) {
+		OSAL_VFREE(p_hwfn, feature->dump_buf);
+		feature->dump_buf = NULL;
+	}
+
+	/* Get buffer size from hsi, allocate accordingly, and perform the
+	 * dump.
+	 */
+	rc = qed_features_lookup[feature_idx].get_size(p_hwfn, p_ptt,
+						       &buf_size_dwords);
+	if (rc != DBG_STATUS_OK && rc != DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
+		return rc;
+
+	if (buf_size_dwords > MAX_DBG_FEATURE_SIZE_DWORDS) {
+		feature->buf_size = 0;
+		DP_NOTICE(p_hwfn->p_dev, false,
+			  "Debug feature [\"%s\"] size (0x%x dwords) exceeds maximum size (0x%x dwords)\n",
+			  qed_features_lookup[feature_idx].name,
+			  buf_size_dwords, MAX_DBG_FEATURE_SIZE_DWORDS);
+
+		return DBG_STATUS_OK;
+	}
+
+	feature->buf_size = buf_size_dwords * sizeof(u32);
+	feature->dump_buf = OSAL_ZALLOC(p_hwfn, GFP_KERNEL, feature->buf_size);
+	if (!feature->dump_buf)
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	rc = qed_features_lookup[feature_idx].perform_dump(p_hwfn, p_ptt,
+					(u32 *)feature->dump_buf,
+					feature->buf_size / sizeof(u32),
+					&feature->dumped_dwords);
+
+	/* If mcp is stuck we get DBG_STATUS_NVRAM_GET_IMAGE_FAILED error.
+	 * In this case the buffer holds valid binary data, but we wont able
+	 * to parse it (since parsing relies on data in NVRAM which is only
+	 * accessible when MFW is responsive). skip the formatting but return
+	 * success so that binary data is provided.
+	 */
+	if (rc == DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
+		return DBG_STATUS_OK;
+
+	if (rc != DBG_STATUS_OK)
+		return rc;
+
+	/* Format output */
+	rc = format_feature(p_hwfn, feature_idx);
+	return rc;
+}
+
+int qed_dbg_grc(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_GRC, num_dumped_bytes);
+}
+
+int qed_dbg_grc_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_GRC);
+}
+
+int
+qed_dbg_idle_chk(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_IDLE_CHK,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_idle_chk_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_IDLE_CHK);
+}
+
+int
+qed_dbg_reg_fifo(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_REG_FIFO,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_reg_fifo_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_REG_FIFO);
+}
+
+int
+qed_dbg_igu_fifo(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_IGU_FIFO,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_igu_fifo_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_IGU_FIFO);
+}
+
+static int qed_dbg_nvm_image_length(struct ecore_hwfn *p_hwfn,
+				    enum ecore_nvm_images image_id, u32 *length)
+{
+	struct ecore_nvm_image_att image_att;
+	int rc;
+
+	*length = 0;
+	rc = ecore_mcp_get_nvm_image_att(p_hwfn, image_id, &image_att);
+	if (rc)
+		return rc;
+
+	*length = image_att.length;
+
+	return rc;
+}
+
+int qed_dbg_protection_override(struct ecore_dev *edev, void *buffer,
+				u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_PROTECTION_OVERRIDE,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_protection_override_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_PROTECTION_OVERRIDE);
+}
+
+int qed_dbg_fw_asserts(struct ecore_dev *edev, void *buffer,
+		       u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_FW_ASSERTS,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_fw_asserts_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_FW_ASSERTS);
+}
+
+int qed_dbg_ilt(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_ILT, num_dumped_bytes);
+}
+
+int qed_dbg_ilt_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_ILT);
+}
+
+int qed_dbg_mcp_trace(struct ecore_dev *edev, void *buffer,
+		      u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_MCP_TRACE,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_mcp_trace_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_MCP_TRACE);
+}
+
+/* Defines the amount of bytes allocated for recording the length of debug
+ * feature buffer.
+ */
+#define REGDUMP_HEADER_SIZE			sizeof(u32)
+#define REGDUMP_HEADER_SIZE_SHIFT		0
+#define REGDUMP_HEADER_SIZE_MASK		0xffffff
+#define REGDUMP_HEADER_FEATURE_SHIFT		24
+#define REGDUMP_HEADER_FEATURE_MASK		0x3f
+#define REGDUMP_HEADER_OMIT_ENGINE_SHIFT	30
+#define REGDUMP_HEADER_OMIT_ENGINE_MASK		0x1
+#define REGDUMP_HEADER_ENGINE_SHIFT		31
+#define REGDUMP_HEADER_ENGINE_MASK		0x1
+#define REGDUMP_MAX_SIZE			0x1000000
+#define ILT_DUMP_MAX_SIZE			(1024 * 1024 * 15)
+
+enum debug_print_features {
+	OLD_MODE = 0,
+	IDLE_CHK = 1,
+	GRC_DUMP = 2,
+	MCP_TRACE = 3,
+	REG_FIFO = 4,
+	PROTECTION_OVERRIDE = 5,
+	IGU_FIFO = 6,
+	PHY = 7,
+	FW_ASSERTS = 8,
+	NVM_CFG1 = 9,
+	DEFAULT_CFG = 10,
+	NVM_META = 11,
+	MDUMP = 12,
+	ILT_DUMP = 13,
+};
+
+static u32 qed_calc_regdump_header(struct ecore_dev *edev,
+				   enum debug_print_features feature,
+				   int engine, u32 feature_size, u8 omit_engine)
+{
+	u32 res = 0;
+
+	SET_FIELD(res, REGDUMP_HEADER_SIZE, feature_size);
+	if (res != feature_size)
+		DP_NOTICE(edev, false,
+			  "Feature %d is too large (size 0x%x) and will corrupt the dump\n",
+			  feature, feature_size);
+
+	SET_FIELD(res, REGDUMP_HEADER_FEATURE, feature);
+	SET_FIELD(res, REGDUMP_HEADER_OMIT_ENGINE, omit_engine);
+	SET_FIELD(res, REGDUMP_HEADER_ENGINE, engine);
+
+	return res;
+}
+
+int qed_dbg_all_data(struct ecore_dev *edev, void *buffer)
+{
+	u8 cur_engine, omit_engine = 0, org_engine;
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	int grc_params[MAX_DBG_GRC_PARAMS], i;
+	u32 offset = 0, feature_size;
+	int rc;
+
+	for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
+		grc_params[i] = dev_data->grc.param_val[i];
+
+	if (!ECORE_IS_CMT(edev))
+		omit_engine = 1;
+
+	OSAL_MUTEX_ACQUIRE(&edev->dbg_lock);
+
+	org_engine = qed_get_debug_engine(edev);
+	for (cur_engine = 0; cur_engine < edev->num_hwfns; cur_engine++) {
+		/* Collect idle_chks and grcDump for each hw function */
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+			   "obtaining idle_chk and grcdump for current engine\n");
+		qed_set_debug_engine(edev, cur_engine);
+
+		/* First idle_chk */
+		rc = qed_dbg_idle_chk(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, IDLE_CHK, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_idle_chk failed. rc = %d\n", rc);
+		}
+
+		/* Second idle_chk */
+		rc = qed_dbg_idle_chk(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, IDLE_CHK, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_idle_chk failed. rc = %d\n", rc);
+		}
+
+		/* reg_fifo dump */
+		rc = qed_dbg_reg_fifo(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, REG_FIFO, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_reg_fifo failed. rc = %d\n", rc);
+		}
+
+		/* igu_fifo dump */
+		rc = qed_dbg_igu_fifo(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, IGU_FIFO, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_igu_fifo failed. rc = %d", rc);
+		}
+
+		/* protection_override dump */
+		rc = qed_dbg_protection_override(edev, (u8 *)buffer + offset +
+						 REGDUMP_HEADER_SIZE,
+						 &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, PROTECTION_OVERRIDE,
+						    cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev,
+			       "qed_dbg_protection_override failed. rc = %d\n",
+			       rc);
+		}
+
+		/* fw_asserts dump */
+		rc = qed_dbg_fw_asserts(edev, (u8 *)buffer + offset +
+					REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, FW_ASSERTS,
+						    cur_engine, feature_size,
+						    omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_fw_asserts failed. rc = %d\n",
+			       rc);
+		}
+
+		/* GRC dump - must be last because when mcp stuck it will
+		 * clutter idle_chk, reg_fifo, ...
+		 */
+		for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
+			dev_data->grc.param_val[i] = grc_params[i];
+
+		rc = qed_dbg_grc(edev, (u8 *)buffer + offset +
+				 REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, GRC_DUMP,
+						    cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_grc failed. rc = %d", rc);
+		}
+	}
+
+	qed_set_debug_engine(edev, org_engine);
+
+	/* mcp_trace */
+	rc = qed_dbg_mcp_trace(edev, (u8 *)buffer + offset +
+			       REGDUMP_HEADER_SIZE, &feature_size);
+	if (!rc) {
+		*(u32 *)((u8 *)buffer + offset) =
+		    qed_calc_regdump_header(edev, MCP_TRACE, cur_engine,
+					    feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+	} else {
+		DP_ERR(edev, "qed_dbg_mcp_trace failed. rc = %d\n", rc);
+	}
+
+	OSAL_MUTEX_RELEASE(&edev->dbg_lock);
+
+	return 0;
+}
+
+int qed_dbg_all_data_size(struct ecore_dev *edev)
+{
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	u32 regs_len = 0, image_len = 0, ilt_len = 0, total_ilt_len = 0;
+	u8 cur_engine, org_engine;
+
+	edev->disable_ilt_dump = false;
+	org_engine = qed_get_debug_engine(edev);
+	for (cur_engine = 0; cur_engine < edev->num_hwfns; cur_engine++) {
+		/* Engine specific */
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+			   "calculating idle_chk and grcdump register length for current engine\n");
+		qed_set_debug_engine(edev, cur_engine);
+		regs_len += REGDUMP_HEADER_SIZE + qed_dbg_idle_chk_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_idle_chk_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_grc_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_reg_fifo_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_igu_fifo_size(edev) +
+			    REGDUMP_HEADER_SIZE +
+			    qed_dbg_protection_override_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_fw_asserts_size(edev);
+
+		ilt_len = REGDUMP_HEADER_SIZE + qed_dbg_ilt_size(edev);
+		if (ilt_len < ILT_DUMP_MAX_SIZE) {
+			total_ilt_len += ilt_len;
+			regs_len += ilt_len;
+		}
+	}
+
+	qed_set_debug_engine(edev, org_engine);
+
+	/* Engine common */
+	regs_len += REGDUMP_HEADER_SIZE + qed_dbg_mcp_trace_size(edev);
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_NVM_CFG1, &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_DEFAULT_CFG,
+				 &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_NVM_META, &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_MDUMP, &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+
+	if (regs_len > REGDUMP_MAX_SIZE) {
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+			   "Dump exceeds max size 0x%x, disable ILT dump\n",
+			   REGDUMP_MAX_SIZE);
+		edev->disable_ilt_dump = true;
+		regs_len -= total_ilt_len;
+	}
+
+	return regs_len;
+}
+
+int qed_dbg_feature(struct ecore_dev *edev, void *buffer,
+		    enum ecore_dbg_features feature, u32 *num_dumped_bytes)
+{
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	struct ecore_dbg_feature *qed_feature =
+		&edev->dbg_params.features[feature];
+	enum dbg_status dbg_rc;
+	struct ecore_ptt *p_ptt;
+	int rc = 0;
+
+	/* Acquire ptt */
+	p_ptt = ecore_ptt_acquire(p_hwfn);
+	if (!p_ptt)
+		return -EINVAL;
+
+	/* Get dump */
+	dbg_rc = qed_dbg_dump(p_hwfn, p_ptt, feature);
+	if (dbg_rc != DBG_STATUS_OK) {
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG, "%s\n",
+			   qed_dbg_get_status_str(dbg_rc));
+		*num_dumped_bytes = 0;
+		rc = -EINVAL;
+		goto out;
+	}
+
+	DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+		   "copying debug feature to external buffer\n");
+	memcpy(buffer, qed_feature->dump_buf, qed_feature->buf_size);
+	*num_dumped_bytes = edev->dbg_params.features[feature].dumped_dwords *
+			    4;
+
+out:
+	ecore_ptt_release(p_hwfn, p_ptt);
+	return rc;
+}
+
+int
+qed_dbg_feature_size(struct ecore_dev *edev, enum ecore_dbg_features feature)
+{
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	struct ecore_dbg_feature *qed_feature = &edev->dbg_features[feature];
+	struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
+	u32 buf_size_dwords;
+	enum dbg_status rc;
+
+	if (!p_ptt)
+		return -EINVAL;
+
+	rc = qed_features_lookup[feature].get_size(p_hwfn, p_ptt,
+						   &buf_size_dwords);
+	if (rc != DBG_STATUS_OK)
+		buf_size_dwords = 0;
+
+	/* Feature will not be dumped if it exceeds maximum size */
+	if (buf_size_dwords > MAX_DBG_FEATURE_SIZE_DWORDS)
+		buf_size_dwords = 0;
+
+	ecore_ptt_release(p_hwfn, p_ptt);
+	qed_feature->buf_size = buf_size_dwords * sizeof(u32);
+	return qed_feature->buf_size;
+}
+
+u8 qed_get_debug_engine(struct ecore_dev *edev)
+{
+	return edev->dbg_params.engine_for_debug;
+}
+
+void qed_set_debug_engine(struct ecore_dev *edev, int engine_number)
+{
+	DP_VERBOSE(edev, ECORE_MSG_DEBUG, "set debug engine to %d\n",
+		   engine_number);
+	edev->dbg_params.engine_for_debug = engine_number;
+}
+
+void qed_dbg_pf_init(struct ecore_dev *edev)
+{
+	const u8 *dbg_values = NULL;
+	int i;
+
+	PMD_INIT_FUNC_TRACE(edev);
+
+	OSAL_MUTEX_INIT(&edev->dbg_lock);
+
+	/* Sync ver with debugbus qed code */
+	qed_dbg_set_app_ver(TOOLS_VERSION);
+
+	/* Debug values are after init values.
+	 * The offset is the first dword of the file.
+	 */
+	/* TBD: change hardcoded value to offset from FW file */
+	dbg_values = (const u8 *)edev->firmware + 1337296;
+
+	for_each_hwfn(edev, i) {
+		qed_dbg_set_bin_ptr(&edev->hwfns[i], dbg_values);
+		qed_dbg_user_set_bin_ptr(&edev->hwfns[i], dbg_values);
+	}
+
+	/* Set the hwfn to be 0 as default */
+	edev->dbg_params.engine_for_debug = 0;
+}
+
+void qed_dbg_pf_exit(struct ecore_dev *edev)
+{
+	struct ecore_dbg_feature *feature = NULL;
+	enum ecore_dbg_features feature_idx;
+
+	PMD_INIT_FUNC_TRACE(edev);
+
+	/* debug features' buffers may be allocated if debug feature was used
+	 * but dump wasn't called
+	 */
+	for (feature_idx = 0; feature_idx < DBG_FEATURE_NUM; feature_idx++) {
+		feature = &edev->dbg_features[feature_idx];
+		if (feature->dump_buf) {
+			OSAL_VFREE(edev, feature->dump_buf);
+			feature->dump_buf = NULL;
+		}
+	}
+
+	OSAL_MUTEX_DEALLOC(&edev->dbg_lock);
+}
diff --git a/drivers/net/qede/qede_debug.h b/drivers/net/qede/qede_debug.h
new file mode 100644
index 000000000..93e1bd710
--- /dev/null
+++ b/drivers/net/qede/qede_debug.h
@@ -0,0 +1,759 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Marvell Semiconductor Inc.
+ * All rights reserved.
+ * www.marvell.com
+ */
+
+#ifndef _QED_DEBUG_H
+#define _QED_DEBUG_H
+
+/* Forward Declaration */
+struct ecore_dev;
+enum ecore_dbg_features;
+
+int qed_dbg_grc(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes);
+int qed_dbg_grc_size(struct ecore_dev *edev);
+int qed_dbg_idle_chk(struct ecore_dev *edev, void *buffer,
+		     u32 *num_dumped_bytes);
+int qed_dbg_idle_chk_size(struct ecore_dev *edev);
+int qed_dbg_reg_fifo(struct ecore_dev *edev, void *buffer,
+		     u32 *num_dumped_bytes);
+int qed_dbg_reg_fifo_size(struct ecore_dev *edev);
+int qed_dbg_igu_fifo(struct ecore_dev *edev, void *buffer,
+		     u32 *num_dumped_bytes);
+int qed_dbg_igu_fifo_size(struct ecore_dev *edev);
+int qed_dbg_protection_override(struct ecore_dev *edev, void *buffer,
+				u32 *num_dumped_bytes);
+int qed_dbg_protection_override_size(struct ecore_dev *edev);
+int qed_dbg_fw_asserts(struct ecore_dev *edev, void *buffer,
+		       u32 *num_dumped_bytes);
+int qed_dbg_fw_asserts_size(struct ecore_dev *edev);
+int qed_dbg_ilt(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes);
+int qed_dbg_ilt_size(struct ecore_dev *edev);
+int qed_dbg_mcp_trace(struct ecore_dev *edev, void *buffer,
+		      u32 *num_dumped_bytes);
+int qed_dbg_mcp_trace_size(struct ecore_dev *edev);
+int qed_dbg_all_data(struct ecore_dev *edev, void *buffer);
+int qed_dbg_all_data_size(struct ecore_dev *edev);
+u8 qed_get_debug_engine(struct ecore_dev *edev);
+void qed_set_debug_engine(struct ecore_dev *edev, int engine_number);
+int qed_dbg_feature(struct ecore_dev *edev, void *buffer,
+		    enum ecore_dbg_features feature, u32 *num_dumped_bytes);
+int
+qed_dbg_feature_size(struct ecore_dev *edev, enum ecore_dbg_features feature);
+
+void qed_dbg_pf_init(struct ecore_dev *edev);
+void qed_dbg_pf_exit(struct ecore_dev *edev);
+
+/***************************** Public Functions *******************************/
+
+/**
+ * @brief qed_dbg_set_bin_ptr - Sets a pointer to the binary data with debug
+ *	arrays.
+ *
+ * @param p_hwfn -	    HW device data
+ * @param bin_ptr - a pointer to the binary data with debug arrays.
+ */
+enum dbg_status qed_dbg_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+				    const u8 * const bin_ptr);
+
+/**
+ * @brief qed_dbg_set_app_ver - Sets the version of the calling app.
+ *
+ * The application should call this function with the TOOLS_VERSION
+ * it compiles with. Must be called before all other debug functions.
+ *
+ * @return error if one of the following holds:
+ *      - the specified app version is not supported
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_set_app_ver(u32 ver);
+
+/**
+ * @brief qed_read_regs - Reads registers into a buffer (using GRC).
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf - Destination buffer.
+ * @param addr - Source GRC address in dwords.
+ * @param len - Number of registers to read.
+ */
+void qed_read_regs(struct ecore_hwfn *p_hwfn,
+		   struct ecore_ptt *p_ptt, u32 *buf, u32 addr, u32 len);
+
+/**
+ * @brief qed_read_fw_info - Reads FW info from the chip.
+ *
+ * The FW info contains FW-related information, such as the FW version,
+ * FW image (main/L2B/kuku), FW timestamp, etc.
+ * The FW info is read from the internal RAM of the first Storm that is not in
+ * reset.
+ *
+ * @param p_hwfn -	    HW device data
+ * @param p_ptt -	    Ptt window used for writing the registers.
+ * @param fw_info -	Out: a pointer to write the FW info into.
+ *
+ * @return true if the FW info was read successfully from one of the Storms,
+ * or false if all Storms are in reset.
+ */
+bool qed_read_fw_info(struct ecore_hwfn *p_hwfn,
+		      struct ecore_ptt *p_ptt, struct fw_info *fw_info);
+/**
+ * @brief qed_dbg_grc_config - Sets the value of a GRC parameter.
+ *
+ * @param p_hwfn -	HW device data
+ * @param grc_param -	GRC parameter
+ * @param val -		Value to set.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- grc_param is invalid
+ *	- val is outside the allowed boundaries
+ */
+enum dbg_status qed_dbg_grc_config(struct ecore_hwfn *p_hwfn,
+				   enum dbg_grc_params grc_param, u32 val);
+
+/**
+ * @brief qed_dbg_grc_set_params_default - Reverts all GRC parameters to their
+ *	default value.
+ *
+ * @param p_hwfn		- HW device data
+ */
+void qed_dbg_grc_set_params_default(struct ecore_hwfn *p_hwfn);
+/**
+ * @brief qed_dbg_grc_get_dump_buf_size - Returns the required buffer size for
+ *	GRC Dump.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for the GRC Dump
+ *	data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_grc_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size);
+
+/**
+ * @brief qed_dbg_grc_dump - Dumps GRC data into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the collected GRC data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified dump buffer is too small
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_grc_dump(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf,
+				 u32 buf_size_in_dwords,
+				 u32 *num_dumped_dwords);
+/**
+ * @brief qed_dbg_idle_chk_get_dump_buf_size - Returns the required buffer size
+ *	for idle check results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for the idle check
+ *	data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_idle_chk_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size);
+
+/**
+ * @brief qed_dbg_idle_chk_dump - Performs idle check and writes the results
+ *	into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the idle check data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_mcp_trace_get_dump_buf_size - Returns the required buffer size
+ *	for mcp trace results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for mcp trace data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the trace data in MCP scratchpad contain an invalid signature
+ *	- the bundle ID in NVRAM is invalid
+ *	- the trace meta data cannot be found (in NVRAM or image file)
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_mcp_trace_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						    struct ecore_ptt *p_ptt,
+						    u32 *buf_size);
+
+/**
+ * @brief qed_dbg_mcp_trace_dump - Performs mcp trace and writes the results
+ *	into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the mcp trace data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- the trace data in MCP scratchpad contain an invalid signature
+ *	- the bundle ID in NVRAM is invalid
+ *	- the trace meta data cannot be found (in NVRAM or image file)
+ *	- the trace meta data cannot be read (from NVRAM or image file)
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+				       struct ecore_ptt *p_ptt,
+				       u32 *dump_buf,
+				       u32 buf_size_in_dwords,
+				       u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_reg_fifo_get_dump_buf_size - Returns the required buffer size
+ *	for grc trace fifo results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for reg fifo data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_reg_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size);
+
+/**
+ * @brief qed_dbg_reg_fifo_dump - Reads the reg fifo and writes the results into
+ *	the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the reg fifo data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- DMAE transaction failed
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_igu_fifo_get_dump_buf_size - Returns the required buffer size
+ *	for the IGU fifo results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for the IGU fifo
+ *	data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_igu_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size);
+
+/**
+ * @brief qed_dbg_igu_fifo_dump - Reads the IGU fifo and writes the results into
+ *	the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the IGU fifo data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- DMAE transaction failed
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_protection_override_get_dump_buf_size - Returns the required
+ *	buffer size for protection override window results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for protection
+ *	override data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status
+qed_dbg_protection_override_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size);
+/**
+ * @brief qed_dbg_protection_override_dump - Reads protection override window
+ *	entries and writes the results into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the protection override data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- DMAE transaction failed
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_protection_override_dump(struct ecore_hwfn *p_hwfn,
+						 struct ecore_ptt *p_ptt,
+						 u32 *dump_buf,
+						 u32 buf_size_in_dwords,
+						 u32 *num_dumped_dwords);
+/**
+ * @brief qed_dbg_fw_asserts_get_dump_buf_size - Returns the required buffer
+ *	size for FW Asserts results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for FW Asserts data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_fw_asserts_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						     struct ecore_ptt *p_ptt,
+						     u32 *buf_size);
+/**
+ * @brief qed_dbg_fw_asserts_dump - Reads the FW Asserts and writes the results
+ *	into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the FW Asserts data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf,
+					u32 buf_size_in_dwords,
+					u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_read_attn - Reads the attention registers of the specified
+ * block and type, and writes the results into the specified buffer.
+ *
+ * @param p_hwfn -	 HW device data
+ * @param p_ptt -	 Ptt window used for writing the registers.
+ * @param block -	 Block ID.
+ * @param attn_type -	 Attention type.
+ * @param clear_status - Indicates if the attention status should be cleared.
+ * @param results -	 OUT: Pointer to write the read results into
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_read_attn(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  enum block_id block,
+				  enum dbg_attn_type attn_type,
+				  bool clear_status,
+				  struct dbg_attn_block_result *results);
+
+/**
+ * @brief qed_dbg_print_attn - Prints attention registers values in the
+ *	specified results struct.
+ *
+ * @param p_hwfn
+ * @param results - Pointer to the attention read results
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_print_attn(struct ecore_hwfn *p_hwfn,
+				   struct dbg_attn_block_result *results);
+
+/******************************* Data Types **********************************/
+
+struct mcp_trace_format {
+	u32 data;
+#define MCP_TRACE_FORMAT_MODULE_MASK	0x0000ffff
+#define MCP_TRACE_FORMAT_MODULE_OFFSET	0
+#define MCP_TRACE_FORMAT_LEVEL_MASK	0x00030000
+#define MCP_TRACE_FORMAT_LEVEL_OFFSET	16
+#define MCP_TRACE_FORMAT_P1_SIZE_MASK	0x000c0000
+#define MCP_TRACE_FORMAT_P1_SIZE_OFFSET 18
+#define MCP_TRACE_FORMAT_P2_SIZE_MASK	0x00300000
+#define MCP_TRACE_FORMAT_P2_SIZE_OFFSET 20
+#define MCP_TRACE_FORMAT_P3_SIZE_MASK	0x00c00000
+#define MCP_TRACE_FORMAT_P3_SIZE_OFFSET 22
+#define MCP_TRACE_FORMAT_LEN_MASK	0xff000000
+#define MCP_TRACE_FORMAT_LEN_OFFSET	24
+
+	char *format_str;
+};
+
+/* MCP Trace Meta data structure */
+struct mcp_trace_meta {
+	u32 modules_num;
+	char **modules;
+	u32 formats_num;
+	struct mcp_trace_format *formats;
+	bool is_allocated;
+};
+
+/* Debug Tools user data */
+struct dbg_tools_user_data {
+	struct mcp_trace_meta mcp_trace_meta;
+	const u32 *mcp_trace_user_meta_buf;
+};
+
+/******************************** Constants **********************************/
+
+#define MAX_NAME_LEN	16
+
+/***************************** Public Functions *******************************/
+
+/**
+ * @brief qed_dbg_user_set_bin_ptr - Sets a pointer to the binary data with
+ *	debug arrays.
+ *
+ * @param p_hwfn - HW device data
+ * @param bin_ptr - a pointer to the binary data with debug arrays.
+ */
+enum dbg_status qed_dbg_user_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+					 const u8 * const bin_ptr);
+
+/**
+ * @brief qed_dbg_alloc_user_data - Allocates user debug data.
+ *
+ * @param p_hwfn -		 HW device data
+ * @param user_data_ptr - OUT: a pointer to the allocated memory.
+ */
+enum dbg_status qed_dbg_alloc_user_data(struct ecore_hwfn *p_hwfn,
+					void **user_data_ptr);
+
+/**
+ * @brief qed_dbg_get_status_str - Returns a string for the specified status.
+ *
+ * @param status - a debug status code.
+ *
+ * @return a string for the specified status
+ */
+const char *qed_dbg_get_status_str(enum dbg_status status);
+
+/**
+ * @brief qed_get_idle_chk_results_buf_size - Returns the required buffer size
+ *	for idle check results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - idle check dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_idle_chk_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32  num_dumped_dwords,
+						  u32 *results_buf_size);
+/**
+ * @brief qed_print_idle_chk_results - Prints idle check results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - idle check dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the idle check results.
+ * @param num_errors - OUT: number of errors found in idle check.
+ * @param num_warnings - OUT: number of warnings found in idle check.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_idle_chk_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf,
+					   u32 *num_errors,
+					   u32 *num_warnings);
+
+/**
+ * @brief qed_dbg_mcp_trace_set_meta_data - Sets the MCP Trace meta data.
+ *
+ * Needed in case the MCP Trace dump doesn't contain the meta data (e.g. due to
+ * no NVRAM access).
+ *
+ * @param data - pointer to MCP Trace meta data
+ * @param size - size of MCP Trace meta data in dwords
+ */
+void qed_dbg_mcp_trace_set_meta_data(struct ecore_hwfn *p_hwfn,
+				     const u32 *meta_buf);
+
+/**
+ * @brief qed_get_mcp_trace_results_buf_size - Returns the required buffer size
+ *	for MCP Trace results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - MCP Trace dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_mcp_trace_results_buf_size(struct ecore_hwfn *p_hwfn,
+						   u32 *dump_buf,
+						   u32 num_dumped_dwords,
+						   u32 *results_buf_size);
+
+/**
+ * @brief qed_print_mcp_trace_results - Prints MCP Trace results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - mcp trace dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the mcp trace results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_mcp_trace_results(struct ecore_hwfn *p_hwfn,
+					    u32 *dump_buf,
+					    u32 num_dumped_dwords,
+					    char *results_buf);
+
+/**
+ * @brief qed_print_mcp_trace_results_cont - Prints MCP Trace results, and
+ * keeps the MCP trace meta data allocated, to support continuous MCP Trace
+ * parsing. After the continuous parsing ends, mcp_trace_free_meta_data should
+ * be called to free the meta data.
+ *
+ * @param p_hwfn -	      HW device data
+ * @param dump_buf -	      mcp trace dump buffer, starting from the header.
+ * @param results_buf -	      buffer for printing the mcp trace results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_mcp_trace_results_cont(struct ecore_hwfn *p_hwfn,
+						 u32 *dump_buf,
+						 char *results_buf);
+
+/**
+ * @brief print_mcp_trace_line - Prints MCP Trace results for a single line
+ *
+ * @param p_hwfn -	      HW device data
+ * @param dump_buf -	      mcp trace dump buffer, starting from the header.
+ * @param num_dumped_bytes -  number of bytes that were dumped.
+ * @param results_buf -	      buffer for printing the mcp trace results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_mcp_trace_line(struct ecore_hwfn *p_hwfn,
+					 u8 *dump_buf,
+					 u32 num_dumped_bytes,
+					 char *results_buf);
+
+/**
+ * @brief mcp_trace_free_meta_data - Frees the MCP Trace meta data.
+ * Should be called after continuous MCP Trace parsing.
+ *
+ * @param p_hwfn - HW device data
+ */
+void qed_mcp_trace_free_meta_data(struct ecore_hwfn *p_hwfn);
+
+/**
+ * @brief qed_get_reg_fifo_results_buf_size - Returns the required buffer size
+ *	for reg_fifo results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - reg fifo dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_reg_fifo_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32 num_dumped_dwords,
+						  u32 *results_buf_size);
+
+/**
+ * @brief qed_print_reg_fifo_results - Prints reg fifo results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - reg fifo dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the reg fifo results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_reg_fifo_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf);
+
+/**
+ * @brief qed_get_igu_fifo_results_buf_size - Returns the required buffer size
+ *	for igu_fifo results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - IGU fifo dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_igu_fifo_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32 num_dumped_dwords,
+						  u32 *results_buf_size);
+
+/**
+ * @brief qed_print_igu_fifo_results - Prints IGU fifo results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - IGU fifo dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the IGU fifo results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_igu_fifo_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf);
+
+/**
+ * @brief qed_get_protection_override_results_buf_size - Returns the required
+ *	buffer size for protection override results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - protection override dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status
+qed_get_protection_override_results_buf_size(struct ecore_hwfn *p_hwfn,
+					     u32 *dump_buf,
+					     u32 num_dumped_dwords,
+					     u32 *results_buf_size);
+
+/**
+ * @brief qed_print_protection_override_results - Prints protection override
+ *	results.
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - protection override dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the reg fifo results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_protection_override_results(struct ecore_hwfn *p_hwfn,
+						      u32 *dump_buf,
+						      u32 num_dumped_dwords,
+						      char *results_buf);
+
+/**
+ * @brief qed_get_fw_asserts_results_buf_size - Returns the required buffer size
+ *	for FW Asserts results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - FW Asserts dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_fw_asserts_results_buf_size(struct ecore_hwfn *p_hwfn,
+						    u32 *dump_buf,
+						    u32 num_dumped_dwords,
+						    u32 *results_buf_size);
+
+/**
+ * @brief qed_print_fw_asserts_results - Prints FW Asserts results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - FW Asserts dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the FW Asserts results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_fw_asserts_results(struct ecore_hwfn *p_hwfn,
+					     u32 *dump_buf,
+					     u32 num_dumped_dwords,
+					     char *results_buf);
+
+/**
+ * @brief qed_dbg_parse_attn - Parses and prints attention registers values in
+ * the specified results struct.
+ *
+ * @param p_hwfn -  HW device data
+ * @param results - Pointer to the attention read results
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_parse_attn(struct ecore_hwfn *p_hwfn,
+				   struct dbg_attn_block_result *results);
+
+#endif
diff --git a/drivers/net/qede/qede_if.h b/drivers/net/qede/qede_if.h
index 858cd51d5..c5ae3fb2e 100644
--- a/drivers/net/qede/qede_if.h
+++ b/drivers/net/qede/qede_if.h
@@ -189,6 +189,51 @@ struct qed_common_ops {
 			      uint32_t dp_module, uint8_t dp_level);
 
 	int (*send_drv_state)(struct ecore_dev *edev, bool active);
+
+	/* ###############  DEBUG *************************/
+
+	int     (*dbg_grc)(struct ecore_dev       *edev,
+			   void		 *buffer,
+			   u32		  *num_dumped_bytes);
+	int     (*dbg_grc_size)(struct ecore_dev *edev);
+
+	int     (*dbg_idle_chk)(struct ecore_dev  *edev,
+				void	    *buffer,
+				u32	     *num_dumped_bytes);
+	int     (*dbg_idle_chk_size)(struct ecore_dev *edev);
+
+	int     (*dbg_reg_fifo)(struct ecore_dev  *edev,
+				void	    *buffer,
+				u32	     *num_dumped_bytes);
+	int     (*dbg_reg_fifo_size)(struct ecore_dev *edev);
+
+	int     (*dbg_mcp_trace)(struct ecore_dev *edev,
+				 void	   *buffer,
+				 u32	    *num_dumped_bytes);
+	int     (*dbg_mcp_trace_size)(struct ecore_dev *edev);
+
+	int	(*dbg_protection_override)(struct ecore_dev *edev, void *buffer,
+					   u32 *num_dumped_bytes);
+	int     (*dbg_protection_override_size)(struct ecore_dev *edev);
+
+	int	(*dbg_igu_fifo_size)(struct ecore_dev *edev);
+	int	(*dbg_igu_fifo)(struct ecore_dev *edev, void *buffer,
+				u32 *num_dumped_bytes);
+
+	int	(*dbg_fw_asserts)(struct ecore_dev *edev, void *buffer,
+				  u32 *num_dumped_bytes);
+
+	int	(*dbg_fw_asserts_size)(struct ecore_dev *edev);
+
+	int	(*dbg_ilt)(struct ecore_dev *edev, void *buffer,
+			   u32 *num_dumped_bytes);
+
+	int	(*dbg_ilt_size)(struct ecore_dev *edev);
+
+	u8      (*dbg_get_debug_engine)(struct ecore_dev *edev);
+	void    (*dbg_set_debug_engine)(struct ecore_dev  *edev,
+					int	     engine_number);
+
 };
 
 /* Externs */
diff --git a/drivers/net/qede/qede_main.c b/drivers/net/qede/qede_main.c
index 51aa639c6..987a6f1e1 100644
--- a/drivers/net/qede/qede_main.c
+++ b/drivers/net/qede/qede_main.c
@@ -9,6 +9,8 @@
 #include <rte_string_fns.h>
 
 #include "qede_ethdev.h"
+/* ######### DEBUG ###########*/
+#include "qede_debug.h"
 
 /* Alarm timeout. */
 #define QEDE_ALARM_TIMEOUT_US 100000
@@ -276,10 +278,15 @@ static int qed_slowpath_start(struct ecore_dev *edev,
 	qed_start_iov_task(edev);
 
 #ifdef CONFIG_ECORE_BINARY_FW
-	if (IS_PF(edev))
+	if (IS_PF(edev)) {
 		data = (const uint8_t *)edev->firmware + sizeof(u32);
+
+		/* ############### DEBUG ################## */
+		qed_dbg_pf_init(edev);
+	}
 #endif
 
+
 	/* Start the slowpath */
 	memset(&hw_init_params, 0, sizeof(hw_init_params));
 	hw_init_params.b_hw_start = true;
@@ -779,6 +786,36 @@ const struct qed_common_ops qed_common_ops_pass = {
 	INIT_STRUCT_FIELD(slowpath_stop, &qed_slowpath_stop),
 	INIT_STRUCT_FIELD(remove, &qed_remove),
 	INIT_STRUCT_FIELD(send_drv_state, &qed_send_drv_state),
+	/* ############### DEBUG ####################*/
+
+	INIT_STRUCT_FIELD(dbg_get_debug_engine, &qed_get_debug_engine),
+	INIT_STRUCT_FIELD(dbg_set_debug_engine, &qed_set_debug_engine),
+
+	INIT_STRUCT_FIELD(dbg_protection_override,
+			  &qed_dbg_protection_override),
+	INIT_STRUCT_FIELD(dbg_protection_override_size,
+			  &qed_dbg_protection_override_size),
+
+	INIT_STRUCT_FIELD(dbg_grc, &qed_dbg_grc),
+	INIT_STRUCT_FIELD(dbg_grc_size, &qed_dbg_grc_size),
+
+	INIT_STRUCT_FIELD(dbg_idle_chk, &qed_dbg_idle_chk),
+	INIT_STRUCT_FIELD(dbg_idle_chk_size, &qed_dbg_idle_chk_size),
+
+	INIT_STRUCT_FIELD(dbg_mcp_trace, &qed_dbg_mcp_trace),
+	INIT_STRUCT_FIELD(dbg_mcp_trace_size, &qed_dbg_mcp_trace_size),
+
+	INIT_STRUCT_FIELD(dbg_fw_asserts, &qed_dbg_fw_asserts),
+	INIT_STRUCT_FIELD(dbg_fw_asserts_size, &qed_dbg_fw_asserts_size),
+
+	INIT_STRUCT_FIELD(dbg_ilt, &qed_dbg_ilt),
+	INIT_STRUCT_FIELD(dbg_ilt_size, &qed_dbg_ilt_size),
+
+	INIT_STRUCT_FIELD(dbg_reg_fifo_size, &qed_dbg_reg_fifo_size),
+	INIT_STRUCT_FIELD(dbg_reg_fifo, &qed_dbg_reg_fifo),
+
+	INIT_STRUCT_FIELD(dbg_igu_fifo_size, &qed_dbg_igu_fifo_size),
+	INIT_STRUCT_FIELD(dbg_igu_fifo, &qed_dbg_igu_fifo),
 };
 
 const struct qed_eth_ops qed_eth_ops_pass = {
-- 
2.18.0


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

* [dpdk-dev] [PATCH 4/4] net/qede: add support for get register operation
  2020-06-28  5:58 [dpdk-dev] [PATCH 0/4] net/qede: add FW debug data collection support Rasesh Mody
                   ` (2 preceding siblings ...)
  2020-06-28  5:58 ` [dpdk-dev] [PATCH 3/4] net/qede: add infrastructure " Rasesh Mody
@ 2020-06-28  5:58 ` Rasesh Mody
  2020-06-28 12:23   ` Jerin Jacob
  2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 0/4] net/qede: add FW debug data collection support Rasesh Mody
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Rasesh Mody @ 2020-06-28  5:58 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

Add support for .get_reg eth_dev ops which will be used to collect the
firmware debug data.

PMD on detecting on some HW errors will collect the FW/HW Dump to a
buffer and then it will save it to a file implemented in
qede_save_fw_dump().

Dump file location and name:
Location: <RTE_SDK> or DPDK root
Name: qede_pmd_dump_mm-dd-yy_hh-mm-ss.bin

DPDK applications can initiate a debug data collection by invoking DPDK
library’s rte_eth_dev_get_reg_info() API. This API invokes .get_reg()
interface in the PMD.

PMD implementation of .get_reg() collects the FW/HW Dump, saves it to
data field of rte_dev_reg_info and passes it to the application. It’s
the responsibility of the application to save the FW/HW Dump to a file.
We recommendation using the file name format used by qede_save_fw_dump().

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/qede/Makefile        |   1 +
 drivers/net/qede/base/bcm_osal.c |  25 +++
 drivers/net/qede/base/bcm_osal.h |   5 +
 drivers/net/qede/qede_ethdev.c   |   1 +
 drivers/net/qede/qede_ethdev.h   |  25 +++
 drivers/net/qede/qede_regs.c     | 271 +++++++++++++++++++++++++++++++
 6 files changed, 328 insertions(+)
 create mode 100644 drivers/net/qede/qede_regs.c

diff --git a/drivers/net/qede/Makefile b/drivers/net/qede/Makefile
index 3b00338ff..0e8a67b0d 100644
--- a/drivers/net/qede/Makefile
+++ b/drivers/net/qede/Makefile
@@ -104,5 +104,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_main.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_rxtx.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_filter.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_debug.c
+SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_regs.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/qede/base/bcm_osal.c b/drivers/net/qede/base/bcm_osal.c
index 45557fe3c..65837b53d 100644
--- a/drivers/net/qede/base/bcm_osal.c
+++ b/drivers/net/qede/base/bcm_osal.c
@@ -246,6 +246,28 @@ qede_get_mcp_proto_stats(struct ecore_dev *edev,
 	}
 }
 
+static void qede_hw_err_handler(void *dev, enum ecore_hw_err_type err_type)
+{
+	struct ecore_dev *edev = dev;
+
+	switch (err_type) {
+	case ECORE_HW_ERR_FAN_FAIL:
+		break;
+
+	case ECORE_HW_ERR_MFW_RESP_FAIL:
+	case ECORE_HW_ERR_HW_ATTN:
+	case ECORE_HW_ERR_DMAE_FAIL:
+	case ECORE_HW_ERR_RAMROD_FAIL:
+	case ECORE_HW_ERR_FW_ASSERT:
+		OSAL_SAVE_FW_DUMP(0); /* Using port 0 as default port_id */
+		break;
+
+	default:
+		DP_NOTICE(edev, false, "Unknown HW error [%d]\n", err_type);
+		return;
+	}
+}
+
 void
 qede_hw_err_notify(struct ecore_hwfn *p_hwfn, enum ecore_hw_err_type err_type)
 {
@@ -275,6 +297,9 @@ qede_hw_err_notify(struct ecore_hwfn *p_hwfn, enum ecore_hw_err_type err_type)
 	}
 
 	DP_ERR(p_hwfn, "HW error occurred [%s]\n", err_str);
+
+	qede_hw_err_handler(p_hwfn->p_dev, err_type);
+
 	ecore_int_attn_clr_enable(p_hwfn->p_dev, true);
 }
 
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index b4b94231b..5d4df5907 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -371,6 +371,11 @@ void qede_hw_err_notify(struct ecore_hwfn *p_hwfn,
 
 /* TODO: */
 #define OSAL_SCHEDULE_RECOVERY_HANDLER(hwfn) nothing
+
+int qede_save_fw_dump(uint8_t port_id);
+
+#define OSAL_SAVE_FW_DUMP(port_id) qede_save_fw_dump(port_id)
+
 #define OSAL_HW_ERROR_OCCURRED(hwfn, err_type) \
 	qede_hw_err_notify(hwfn, err_type)
 
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 717b80839..52a4f046b 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -2430,6 +2430,7 @@ static const struct eth_dev_ops qede_eth_dev_ops = {
 	.udp_tunnel_port_add = qede_udp_dst_port_add,
 	.udp_tunnel_port_del = qede_udp_dst_port_del,
 	.fw_version_get = qede_fw_version_get,
+	.get_reg = qede_get_regs,
 };
 
 static const struct eth_dev_ops qede_eth_vf_dev_ops = {
diff --git a/drivers/net/qede/qede_ethdev.h b/drivers/net/qede/qede_ethdev.h
index b988a73f2..76c5dae3b 100644
--- a/drivers/net/qede/qede_ethdev.h
+++ b/drivers/net/qede/qede_ethdev.h
@@ -214,6 +214,8 @@ struct qede_tunn_params {
 	uint16_t udp_port;
 };
 
+#define QEDE_FW_DUMP_FILE_SIZE 128
+
 /*
  *  Structure to store private data for each port.
  */
@@ -252,6 +254,7 @@ struct qede_dev {
 	char drv_ver[QEDE_PMD_DRV_VER_STR_SIZE];
 	bool vport_started;
 	int vlan_offload_mask;
+	char dump_file[QEDE_FW_DUMP_FILE_SIZE];
 	void *ethdev;
 };
 
@@ -313,4 +316,26 @@ void qede_config_accept_any_vlan(struct qede_dev *qdev, bool flg);
 int qede_ucast_filter(struct rte_eth_dev *eth_dev,
 		      struct ecore_filter_ucast *ucast,
 		      bool add);
+
+#define REGDUMP_HEADER_SIZE sizeof(u32)
+#define REGDUMP_HEADER_FEATURE_SHIFT 24
+#define REGDUMP_HEADER_ENGINE_SHIFT 31
+#define REGDUMP_HEADER_OMIT_ENGINE_SHIFT 30
+
+enum debug_print_features {
+	OLD_MODE = 0,
+	IDLE_CHK = 1,
+	GRC_DUMP = 2,
+	MCP_TRACE = 3,
+	REG_FIFO = 4,
+	PROTECTION_OVERRIDE = 5,
+	IGU_FIFO = 6,
+	PHY = 7,
+	FW_ASSERTS = 8,
+};
+
+int qede_get_regs_len(struct qede_dev *qdev);
+int qede_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs);
+void qede_config_rx_mode(struct rte_eth_dev *eth_dev);
+void qed_dbg_dump(struct rte_eth_dev *eth_dev);
 #endif /* _QEDE_ETHDEV_H_ */
diff --git a/drivers/net/qede/qede_regs.c b/drivers/net/qede/qede_regs.c
new file mode 100644
index 000000000..4409d2180
--- /dev/null
+++ b/drivers/net/qede/qede_regs.c
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Marvell Semiconductor Inc.
+ * All rights reserved.
+ * www.marvell.com
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <time.h>
+#include <rte_ethdev.h>
+#include "base/bcm_osal.h"
+#include "qede_ethdev.h"
+
+int
+qede_get_regs_len(struct qede_dev *qdev)
+{
+	struct ecore_dev *edev = &qdev->edev;
+	int cur_engine, num_of_hwfns, regs_len = 0;
+	uint8_t org_engine;
+
+	if (IS_VF(edev))
+		return 0;
+
+	if (qdev->ops && qdev->ops->common) {
+		num_of_hwfns = qdev->dev_info.common.num_hwfns;
+		org_engine = qdev->ops->common->dbg_get_debug_engine(edev);
+		for (cur_engine = 0; cur_engine < num_of_hwfns; cur_engine++) {
+			/* compute requierd buffer size for idle_chks and
+			 * grcDump for each hw function
+			 */
+			DP_NOTICE(edev, false,
+				"Calculating idle_chk and grcdump register length for current engine\n");
+			qdev->ops->common->dbg_set_debug_engine(edev,
+								cur_engine);
+			regs_len += REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_idle_chk_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_idle_chk_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_grc_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_reg_fifo_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_protection_override_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_igu_fifo_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_fw_asserts_size(edev);
+		}
+		/* compute requierd buffer size for mcp trace and add it to the
+		 * total requierd buffer size
+		 */
+		regs_len += REGDUMP_HEADER_SIZE +
+			    qdev->ops->common->dbg_mcp_trace_size(edev);
+
+		qdev->ops->common->dbg_set_debug_engine(edev, org_engine);
+	}
+	DP_NOTICE(edev, false, "Total length = %u\n", regs_len);
+
+	return regs_len;
+}
+
+static uint32_t
+qede_calc_regdump_header(enum debug_print_features feature, int engine,
+			 uint32_t feature_size, uint8_t omit_engine)
+{
+	/* insert the engine, feature and mode inside the header and
+	 * combine it with feature size
+	 */
+	return (feature_size | (feature << REGDUMP_HEADER_FEATURE_SHIFT) |
+		(omit_engine << REGDUMP_HEADER_OMIT_ENGINE_SHIFT) |
+		(engine << REGDUMP_HEADER_ENGINE_SHIFT));
+}
+
+int qede_get_regs(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs)
+{
+	struct qede_dev *qdev = eth_dev->data->dev_private;
+	struct ecore_dev *edev = &qdev->edev;
+	uint32_t *buffer = regs->data;
+	int cur_engine, num_of_hwfns;
+	/* '1' tells the parser to omit the engine number in the output files */
+	uint8_t omit_engine = 0;
+	uint8_t org_engine;
+	uint32_t feature_size;
+	uint32_t offset = 0;
+
+	if (IS_VF(edev))
+		return -ENOTSUP;
+
+	if (buffer == NULL) {
+		regs->length = qede_get_regs_len(qdev);
+		regs->width =  sizeof(uint32_t);
+		DP_INFO(edev, "Length %u\n", regs->length);
+		return 0;
+	}
+
+	memset(buffer, 0, regs->length);
+	num_of_hwfns = qdev->dev_info.common.num_hwfns;
+	if (num_of_hwfns == 1)
+		omit_engine = 1;
+
+	OSAL_MUTEX_ACQUIRE(&edev->dbg_lock);
+
+	org_engine = qdev->ops->common->dbg_get_debug_engine(edev);
+	for (cur_engine = 0; cur_engine < num_of_hwfns; cur_engine++) {
+		/* collect idle_chks and grcDump for each hw function */
+		DP_NOTICE(edev, false, "obtaining idle_chk and grcdump for current engine\n");
+		qdev->ops->common->dbg_set_debug_engine(edev, cur_engine);
+
+		/* first idle_chk */
+		qdev->ops->common->dbg_idle_chk(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(IDLE_CHK, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Idle Check1 feature_size %u\n",
+			  feature_size);
+
+		/* second idle_chk */
+		qdev->ops->common->dbg_idle_chk(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(IDLE_CHK, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Idle Check2 feature_size %u\n",
+			  feature_size);
+
+		/* reg_fifo dump */
+		qdev->ops->common->dbg_reg_fifo(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(REG_FIFO, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Reg fifo feature_size %u\n",
+			  feature_size);
+
+		/* igu_fifo dump */
+		qdev->ops->common->dbg_igu_fifo(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(IGU_FIFO, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "IGU fifo feature_size %u\n",
+			  feature_size);
+
+		/* protection_override dump */
+		qdev->ops->common->dbg_protection_override(edev,
+							   (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+		       qede_calc_regdump_header(PROTECTION_OVERRIDE, cur_engine,
+						feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Protection override feature_size %u\n",
+			  feature_size);
+
+		/* fw_asserts dump */
+		qdev->ops->common->dbg_fw_asserts(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(FW_ASSERTS, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "FW assert feature_size %u\n",
+			  feature_size);
+
+		/* grc dump */
+		qdev->ops->common->dbg_grc(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(GRC_DUMP, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "GRC dump feature_size %u\n",
+			  feature_size);
+	}
+
+	/* mcp_trace */
+	qdev->ops->common->dbg_mcp_trace(edev, (uint8_t *)buffer +
+		offset + REGDUMP_HEADER_SIZE, &feature_size);
+	*(uint32_t *)((uint8_t *)buffer + offset) =
+		qede_calc_regdump_header(MCP_TRACE, cur_engine, feature_size,
+					 omit_engine);
+	offset += (feature_size + REGDUMP_HEADER_SIZE);
+	DP_NOTICE(edev, false, "MCP trace feature_size %u\n", feature_size);
+
+	qdev->ops->common->dbg_set_debug_engine(edev, org_engine);
+
+	OSAL_MUTEX_RELEASE(&edev->dbg_lock);
+
+	return 0;
+}
+
+static void
+qede_set_fw_dump_file_name(struct qede_dev *qdev)
+{
+	time_t ltime;
+	struct tm *tm;
+
+	ltime = time(NULL);
+	tm = localtime(&ltime);
+	snprintf(qdev->dump_file, QEDE_FW_DUMP_FILE_SIZE,
+		 "qede_pmd_dump_%02d-%02d-%02d_%02d-%02d-%02d.bin",
+		 tm->tm_mon + 1, (int)tm->tm_mday, 1900 + tm->tm_year,
+		 tm->tm_hour, tm->tm_min, tm->tm_sec);
+}
+
+static int
+qede_write_fwdump(const char *dump_file, void *dump, size_t len)
+{
+	int err = 0;
+	FILE *f;
+	size_t bytes;
+
+	f = fopen(dump_file, "wb+");
+
+	if (!f) {
+		fprintf(stderr, "Can't open file %s: %s\n",
+			dump_file, strerror(errno));
+		return 1;
+	}
+	bytes = fwrite(dump, 1, len, f);
+	if (bytes != len) {
+		fprintf(stderr, "Can not write all of dump data bytes=%ld len=%ld\n",
+			bytes, len);
+		err = 1;
+	}
+
+	if (fclose(f)) {
+		fprintf(stderr, "Can't close file %s: %s\n",
+			dump_file, strerror(errno));
+		err = 1;
+	}
+
+	return err;
+}
+
+int
+qede_save_fw_dump(uint8_t port_id)
+{
+	struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id];
+	struct rte_dev_reg_info regs;
+	struct qede_dev *qdev = eth_dev->data->dev_private;
+	struct ecore_dev *edev = &qdev->edev;
+	int rc = 0;
+
+	if (!rte_eth_dev_is_valid_port(port_id)) {
+		DP_ERR(edev, "port %u invalid port ID", port_id);
+		return -ENODEV;
+	}
+
+	memset(&regs, 0, sizeof(regs));
+	regs.length = qede_get_regs_len(qdev);
+	regs.data = OSAL_ZALLOC(eth_dev, GFP_KERNEL, regs.length);
+	if (regs.data) {
+		qede_get_regs(eth_dev, &regs);
+		qede_set_fw_dump_file_name(qdev);
+		rc = qede_write_fwdump(qdev->dump_file, regs.data, regs.length);
+		if (!rc)
+			DP_NOTICE(edev, false, "FW dump written to %s file\n",
+				  qdev->dump_file);
+		OSAL_FREE(edev, regs.data);
+	}
+
+	return rc;
+}
-- 
2.18.0


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

* Re: [dpdk-dev] [PATCH 4/4] net/qede: add support for get register operation
  2020-06-28  5:58 ` [dpdk-dev] [PATCH 4/4] net/qede: add support for get register operation Rasesh Mody
@ 2020-06-28 12:23   ` Jerin Jacob
  2020-06-30  7:37     ` [dpdk-dev] [EXT] " Rasesh Mody
  0 siblings, 1 reply; 37+ messages in thread
From: Jerin Jacob @ 2020-06-28 12:23 UTC (permalink / raw)
  To: Rasesh Mody
  Cc: Jerin Jacob, Ferruh Yigit, dpdk-dev, GR-Everest-DPDK-Dev, Igor Russkikh

On Sun, Jun 28, 2020 at 11:29 AM Rasesh Mody <rmody@marvell.com> wrote:
>
> Add support for .get_reg eth_dev ops which will be used to collect the
> firmware debug data.
>
> PMD on detecting on some HW errors will collect the FW/HW Dump to a
> buffer and then it will save it to a file implemented in
> qede_save_fw_dump().
>
> Dump file location and name:
> Location: <RTE_SDK> or DPDK root
> Name: qede_pmd_dump_mm-dd-yy_hh-mm-ss.bin
>
> DPDK applications can initiate a debug data collection by invoking DPDK
> library’s rte_eth_dev_get_reg_info() API. This API invokes .get_reg()
> interface in the PMD.
>
> PMD implementation of .get_reg() collects the FW/HW Dump, saves it to
> data field of rte_dev_reg_info and passes it to the application. It’s
> the responsibility of the application to save the FW/HW Dump to a file.
> We recommendation using the file name format used by qede_save_fw_dump().
>
> Signed-off-by: Rasesh Mody <rmody@marvell.com>
> Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
> ---
>  drivers/net/qede/Makefile        |   1 +
>  drivers/net/qede/base/bcm_osal.c |  25 +++
>  drivers/net/qede/base/bcm_osal.h |   5 +
>  drivers/net/qede/qede_ethdev.c   |   1 +
>  drivers/net/qede/qede_ethdev.h   |  25 +++
>  drivers/net/qede/qede_regs.c     | 271 +++++++++++++++++++++++++++++++
>  6 files changed, 328 insertions(+)
>  create mode 100644 drivers/net/qede/qede_regs.c
>

> diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
> index 717b80839..52a4f046b 100644
> --- a/drivers/net/qede/qede_ethdev.c
> +++ b/drivers/net/qede/qede_ethdev.c
> @@ -2430,6 +2430,7 @@ static const struct eth_dev_ops qede_eth_dev_ops = {
>         .udp_tunnel_port_add = qede_udp_dst_port_add,
>         .udp_tunnel_port_del = qede_udp_dst_port_del,
>         .fw_version_get = qede_fw_version_get,
> +       .get_reg = qede_get_regs,

Please update this feature in doc/guides/nics/features/qede.ini.


>  };

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

* Re: [dpdk-dev] [PATCH 3/4] net/qede: add infrastructure for debug data collection
  2020-06-28  5:58 ` [dpdk-dev] [PATCH 3/4] net/qede: add infrastructure " Rasesh Mody
@ 2020-06-28 12:29   ` Jerin Jacob
  2020-06-30  7:38     ` [dpdk-dev] [EXT] " Rasesh Mody
  0 siblings, 1 reply; 37+ messages in thread
From: Jerin Jacob @ 2020-06-28 12:29 UTC (permalink / raw)
  To: Rasesh Mody
  Cc: Jerin Jacob, Ferruh Yigit, dpdk-dev, GR-Everest-DPDK-Dev, Igor Russkikh

On Sun, Jun 28, 2020 at 11:29 AM Rasesh Mody <rmody@marvell.com> wrote:
>
> The patch adds QEDE PMD ops and APIs to calculate the size and collect
> the debug dump for various firmware components. The patch adds new files
> qede_debug.[ch] that has all the firmware debug data collection
> infrastructure changes.
>
> Signed-off-by: Rasesh Mody <rmody@marvell.com>
> Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
> ---
>  drivers/net/qede/Makefile        |    4 +-
>  drivers/net/qede/base/bcm_osal.h |    5 +-
>  drivers/net/qede/qede_debug.c    | 8119 ++++++++++++++++++++++++++++++
>  drivers/net/qede/qede_debug.h    |  759 +++
>  drivers/net/qede/qede_if.h       |   45 +
>  drivers/net/qede/qede_main.c     |   39 +-
>  6 files changed, 8967 insertions(+), 4 deletions(-)
>  create mode 100644 drivers/net/qede/qede_debug.c
>  create mode 100644 drivers/net/qede/qede_debug.h

Please fix the following checkpatch issues.


CHECK:MACRO_ARG_REUSE: Macro argument reuse 'field' - possible side-effects?
#494: FILE: drivers/net/qede/qede_debug.c:339:
+#define FIELD_BIT_MASK(type, field) \
+ (((1 << FIELD_BIT_SIZE(type, field)) - 1) << \
+ FIELD_DWORD_SHIFT(type, field))

CHECK:MACRO_ARG_REUSE: Macro argument reuse 'var' - possible side-effects?
#498: FILE: drivers/net/qede/qede_debug.c:343:
+#define SET_VAR_FIELD(var, type, field, val) \
+ do { \
+ var[FIELD_DWORD_OFFSET(type, field)] &= \
+ (~FIELD_BIT_MASK(type, field)); \
+ var[FIELD_DWORD_OFFSET(type, field)] |= \
+ (val) << FIELD_DWORD_SHIFT(type, field); \
+ } while (0)

CHECK:MACRO_ARG_REUSE: Macro argument reuse 'field' - possible side-effects?
#498: FILE: drivers/net/qede/qede_debug.c:343:
+#define SET_VAR_FIELD(var, type, field, val) \
+ do { \
+ var[FIELD_DWORD_OFFSET(type, field)] &= \
+ (~FIELD_BIT_MASK(type, field)); \
+ var[FIELD_DWORD_OFFSET(type, field)] |= \
+ (val) << FIELD_DWORD_SHIFT(type, field); \
+ } while (0)

CHECK:MACRO_ARG_REUSE: Macro argument reuse 'block' - possible side-effects?
#518: FILE: drivers/net/qede/qede_debug.c:363:
+#define NUM_DBG_LINES(block) \
+ ((block)->num_of_dbg_bus_lines + NUM_EXTRA_DBG_LINES(block))

WARNING:TYPO_SPELLING: 'DIDNT' may be misspelled - perhaps 'DIDN'T'?
#5814: FILE: drivers/net/qede/qede_debug.c:5659:
+ /* DBG_STATUS_DATA_DIDNT_TRIGGER */

ERROR:TRAILING_STATEMENTS: trailing statements should be on next line
#6344: FILE: drivers/net/qede/qede_debug.c:6189:
+ for (; reg_id > curr_reg_id;
[...]
+     1);

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

* Re: [dpdk-dev] [EXT] Re: [PATCH 4/4] net/qede: add support for get register operation
  2020-06-28 12:23   ` Jerin Jacob
@ 2020-06-30  7:37     ` Rasesh Mody
  0 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-06-30  7:37 UTC (permalink / raw)
  To: Jerin Jacob
  Cc: Jerin Jacob Kollanukkaran, Ferruh Yigit, dpdk-dev,
	GR-Everest-DPDK-Dev, Igor Russkikh

Hi Jerin,

>From: Jerin Jacob <jerinjacobk@gmail.com>
>Sent: Sunday, June 28, 2020 5:23 AM
>
>----------------------------------------------------------------------
>On Sun, Jun 28, 2020 at 11:29 AM Rasesh Mody <rmody@marvell.com> wrote:
>>
>> Add support for .get_reg eth_dev ops which will be used to collect the
>> firmware debug data.
>>
>> PMD on detecting on some HW errors will collect the FW/HW Dump to a
>> buffer and then it will save it to a file implemented in
>> qede_save_fw_dump().
>>
>> Dump file location and name:
>> Location: <RTE_SDK> or DPDK root
>> Name: qede_pmd_dump_mm-dd-yy_hh-mm-ss.bin
>>
>> DPDK applications can initiate a debug data collection by invoking
>> DPDK library’s rte_eth_dev_get_reg_info() API. This API invokes
>> .get_reg() interface in the PMD.
>>
>> PMD implementation of .get_reg() collects the FW/HW Dump, saves it to
>> data field of rte_dev_reg_info and passes it to the application. It’s
>> the responsibility of the application to save the FW/HW Dump to a file.
>> We recommendation using the file name format used by
>qede_save_fw_dump().
>>
>> Signed-off-by: Rasesh Mody <rmody@marvell.com>
>> Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
>> ---
>>  drivers/net/qede/Makefile        |   1 +
>>  drivers/net/qede/base/bcm_osal.c |  25 +++
>>  drivers/net/qede/base/bcm_osal.h |   5 +
>>  drivers/net/qede/qede_ethdev.c   |   1 +
>>  drivers/net/qede/qede_ethdev.h   |  25 +++
>>  drivers/net/qede/qede_regs.c     | 271
>+++++++++++++++++++++++++++++++
>>  6 files changed, 328 insertions(+)
>>  create mode 100644 drivers/net/qede/qede_regs.c
>>
>
>> diff --git a/drivers/net/qede/qede_ethdev.c
>> b/drivers/net/qede/qede_ethdev.c index 717b80839..52a4f046b 100644
>> --- a/drivers/net/qede/qede_ethdev.c
>> +++ b/drivers/net/qede/qede_ethdev.c
>> @@ -2430,6 +2430,7 @@ static const struct eth_dev_ops
>qede_eth_dev_ops = {
>>         .udp_tunnel_port_add = qede_udp_dst_port_add,
>>         .udp_tunnel_port_del = qede_udp_dst_port_del,
>>         .fw_version_get = qede_fw_version_get,
>> +       .get_reg = qede_get_regs,
>
>Please update this feature in doc/guides/nics/features/qede.ini.

Sure, I'll take care of this in v2 series.

Thanks!
-Rasesh

>
>
>>  };


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

* Re: [dpdk-dev] [EXT] Re: [PATCH 3/4] net/qede: add infrastructure for debug data collection
  2020-06-28 12:29   ` Jerin Jacob
@ 2020-06-30  7:38     ` Rasesh Mody
  0 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-06-30  7:38 UTC (permalink / raw)
  To: Jerin Jacob
  Cc: Jerin Jacob Kollanukkaran, Ferruh Yigit, dpdk-dev,
	GR-Everest-DPDK-Dev, Igor Russkikh

>From: Jerin Jacob <jerinjacobk@gmail.com>
>Sent: Sunday, June 28, 2020 5:30 AM
>
>----------------------------------------------------------------------
>On Sun, Jun 28, 2020 at 11:29 AM Rasesh Mody <rmody@marvell.com> wrote:
>>
>> The patch adds QEDE PMD ops and APIs to calculate the size and collect
>> the debug dump for various firmware components. The patch adds new
>> files qede_debug.[ch] that has all the firmware debug data collection
>> infrastructure changes.
>>
>> Signed-off-by: Rasesh Mody <rmody@marvell.com>
>> Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
>> ---
>>  drivers/net/qede/Makefile        |    4 +-
>>  drivers/net/qede/base/bcm_osal.h |    5 +-
>>  drivers/net/qede/qede_debug.c    | 8119
>++++++++++++++++++++++++++++++
>>  drivers/net/qede/qede_debug.h    |  759 +++
>>  drivers/net/qede/qede_if.h       |   45 +
>>  drivers/net/qede/qede_main.c     |   39 +-
>>  6 files changed, 8967 insertions(+), 4 deletions(-)  create mode
>> 100644 drivers/net/qede/qede_debug.c  create mode 100644
>> drivers/net/qede/qede_debug.h
>
>Please fix the following checkpatch issues.
>
>
>CHECK:MACRO_ARG_REUSE: Macro argument reuse 'field' - possible side-
>effects?
>#494: FILE: drivers/net/qede/qede_debug.c:339:
>+#define FIELD_BIT_MASK(type, field) \
>+ (((1 << FIELD_BIT_SIZE(type, field)) - 1) << \
>+FIELD_DWORD_SHIFT(type, field))
>
>CHECK:MACRO_ARG_REUSE: Macro argument reuse 'var' - possible side-
>effects?
>#498: FILE: drivers/net/qede/qede_debug.c:343:
>+#define SET_VAR_FIELD(var, type, field, val) \  do { \
>+var[FIELD_DWORD_OFFSET(type, field)] &= \  (~FIELD_BIT_MASK(type,
>+field)); \  var[FIELD_DWORD_OFFSET(type, field)] |= \
>+ (val) << FIELD_DWORD_SHIFT(type, field); \  } while (0)
>
>CHECK:MACRO_ARG_REUSE: Macro argument reuse 'field' - possible side-
>effects?
>#498: FILE: drivers/net/qede/qede_debug.c:343:
>+#define SET_VAR_FIELD(var, type, field, val) \  do { \
>+var[FIELD_DWORD_OFFSET(type, field)] &= \  (~FIELD_BIT_MASK(type,
>+field)); \  var[FIELD_DWORD_OFFSET(type, field)] |= \
>+ (val) << FIELD_DWORD_SHIFT(type, field); \  } while (0)
>
>CHECK:MACRO_ARG_REUSE: Macro argument reuse 'block' - possible side-
>effects?
>#518: FILE: drivers/net/qede/qede_debug.c:363:
>+#define NUM_DBG_LINES(block) \
>+ ((block)->num_of_dbg_bus_lines + NUM_EXTRA_DBG_LINES(block))

Please ignore MACRO_ARG_REUSE checks as we do not see any side effects.

>
>WARNING:TYPO_SPELLING: 'DIDNT' may be misspelled - perhaps 'DIDN'T'?
>#5814: FILE: drivers/net/qede/qede_debug.c:5659:
>+ /* DBG_STATUS_DATA_DIDNT_TRIGGER */

This seems to be a false positive, however it can be renamed.

>
>ERROR:TRAILING_STATEMENTS: trailing statements should be on next line
>#6344: FILE: drivers/net/qede/qede_debug.c:6189:
>+ for (; reg_id > curr_reg_id;
>[...]
>+     1);

Will address in v2 series.


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

* [dpdk-dev] [PATCH v2 0/4] net/qede: add FW debug data collection support
  2020-06-28  5:58 [dpdk-dev] [PATCH 0/4] net/qede: add FW debug data collection support Rasesh Mody
                   ` (3 preceding siblings ...)
  2020-06-28  5:58 ` [dpdk-dev] [PATCH 4/4] net/qede: add support for get register operation Rasesh Mody
@ 2020-06-30  8:32 ` Rasesh Mody
  2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 " Rasesh Mody
                     ` (4 more replies)
  2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
                   ` (3 subsequent siblings)
  8 siblings, 5 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-06-30  8:32 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev

Hi Jerin, Ferruh,

This patch-set adds an ability to collect FW and HW Debug Data/Dump
(referred to as FW/HW Dump) to QEDE PMD. The dump is collected either
when PMD detects an error or when a DPDK application asks PMD to
collect it upon detection of application error. This FW/HW Dump
needs to be saved to a file and sent to Marvell for analysis.

Please apply to dpdk-next-net-mrvl and dpdk-next-net trees.

v2:
Addressed checkpatch issues and updated supported features. 

Thanks!
-Rasesh

Rasesh Mody (4):
  net/qede/base: re-arrange few structures for DDC
  net/qede/base: add changes for debug data collection
  net/qede: add infrastructure for debug data collection
  net/qede: add support for get register operation

 doc/guides/nics/features/qede.ini             |    1 +
 drivers/net/qede/Makefile                     |    5 +-
 drivers/net/qede/base/bcm_osal.c              |   31 +
 drivers/net/qede/base/bcm_osal.h              |   18 +-
 drivers/net/qede/base/common_hsi.h            |    1 +
 drivers/net/qede/base/ecore.h                 |   54 +-
 drivers/net/qede/base/ecore_cxt.c             |  200 +-
 drivers/net/qede/base/ecore_cxt.h             |  140 +-
 drivers/net/qede/base/ecore_dev.c             |   13 +
 drivers/net/qede/base/ecore_hsi_common.h      |  184 +-
 drivers/net/qede/base/ecore_hsi_debug_tools.h |    2 +-
 drivers/net/qede/base/ecore_hsi_func_common.h |   17 +
 drivers/net/qede/base/ecore_init_fw_funcs.h   |    7 -
 drivers/net/qede/base/ecore_mcp.c             |  211 +
 drivers/net/qede/base/ecore_mcp_api.h         |   37 +
 drivers/net/qede/base/ecore_status.h          |    2 +
 drivers/net/qede/base/reg_addr.h              |  846 ++
 drivers/net/qede/qede_debug.c                 | 8120 +++++++++++++++++
 drivers/net/qede/qede_debug.h                 |  759 ++
 drivers/net/qede/qede_ethdev.c                |    2 +-
 drivers/net/qede/qede_ethdev.h                |   25 +
 drivers/net/qede/qede_if.h                    |   45 +
 drivers/net/qede/qede_main.c                  |   42 +-
 drivers/net/qede/qede_regs.c                  |  271 +
 24 files changed, 10874 insertions(+), 159 deletions(-)
 create mode 100644 drivers/net/qede/base/ecore_hsi_func_common.h
 create mode 100644 drivers/net/qede/qede_debug.c
 create mode 100644 drivers/net/qede/qede_debug.h
 create mode 100644 drivers/net/qede/qede_regs.c

-- 
2.18.0


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

* [dpdk-dev] [PATCH v2 1/4] net/qede/base: re-arrange few structures for DDC
  2020-06-28  5:58 [dpdk-dev] [PATCH 0/4] net/qede: add FW debug data collection support Rasesh Mody
                   ` (4 preceding siblings ...)
  2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 0/4] net/qede: add FW debug data collection support Rasesh Mody
@ 2020-06-30  8:32 ` Rasesh Mody
  2020-06-30 17:47   ` Jerin Jacob
  2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 2/4] net/qede/base: add changes for debug data collection Rasesh Mody
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Rasesh Mody @ 2020-06-30  8:32 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

This patch rearranges some of the base driver structures which will be
also used by debug data collection (DDC) implementation. It adds a new
file ecore_hsi_func_common.h with Physical, Virtual memory descriptors.

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/qede/base/ecore.h                 |   2 +
 drivers/net/qede/base/ecore_cxt.c             | 140 ++----------------
 drivers/net/qede/base/ecore_cxt.h             | 135 ++++++++++++++++-
 drivers/net/qede/base/ecore_hsi_func_common.h |  17 +++
 drivers/net/qede/base/ecore_init_fw_funcs.h   |   7 -
 5 files changed, 163 insertions(+), 138 deletions(-)
 create mode 100644 drivers/net/qede/base/ecore_hsi_func_common.h

diff --git a/drivers/net/qede/base/ecore.h b/drivers/net/qede/base/ecore.h
index 498bb6f09..dc5fe4d80 100644
--- a/drivers/net/qede/base/ecore.h
+++ b/drivers/net/qede/base/ecore.h
@@ -24,6 +24,7 @@
 #include "ecore_hsi_debug_tools.h"
 #include "ecore_hsi_init_func.h"
 #include "ecore_hsi_init_tool.h"
+#include "ecore_hsi_func_common.h"
 #include "ecore_proto_if.h"
 #include "mcp_public.h"
 
@@ -671,6 +672,7 @@ struct ecore_hwfn {
 
 	struct dbg_tools_data		dbg_info;
 	void				*dbg_user_info;
+	struct virt_mem_desc		dbg_arrays[MAX_BIN_DBG_BUFFER_TYPE];
 
 	struct z_stream_s		*stream;
 
diff --git a/drivers/net/qede/base/ecore_cxt.c b/drivers/net/qede/base/ecore_cxt.c
index dda47ea67..23f37b1bf 100644
--- a/drivers/net/qede/base/ecore_cxt.c
+++ b/drivers/net/qede/base/ecore_cxt.c
@@ -20,12 +20,6 @@
 #include "ecore_sriov.h"
 #include "ecore_mcp.h"
 
-/* Max number of connection types in HW (DQ/CDU etc.) */
-#define MAX_CONN_TYPES		PROTOCOLID_COMMON
-#define NUM_TASK_TYPES		2
-#define NUM_TASK_PF_SEGMENTS	4
-#define NUM_TASK_VF_SEGMENTS	1
-
 /* Doorbell-Queue constants */
 #define DQ_RANGE_SHIFT	4
 #define DQ_RANGE_ALIGN	(1 << DQ_RANGE_SHIFT)
@@ -90,128 +84,6 @@ struct src_ent {
 /* Alignment is inherent to the type1_task_context structure */
 #define TYPE1_TASK_CXT_SIZE(p_hwfn) sizeof(union type1_task_context)
 
-/* PF per protocl configuration object */
-#define TASK_SEGMENTS   (NUM_TASK_PF_SEGMENTS + NUM_TASK_VF_SEGMENTS)
-#define TASK_SEGMENT_VF (NUM_TASK_PF_SEGMENTS)
-
-struct ecore_tid_seg {
-	u32 count;
-	u8 type;
-	bool has_fl_mem;
-};
-
-struct ecore_conn_type_cfg {
-	u32 cid_count;
-	u32 cids_per_vf;
-	struct ecore_tid_seg tid_seg[TASK_SEGMENTS];
-};
-
-/* ILT Client configuration,
- * Per connection type (protocol) resources (cids, tis, vf cids etc.)
- * 1 - for connection context (CDUC) and for each task context we need two
- * values, for regular task context and for force load memory
- */
-#define ILT_CLI_PF_BLOCKS	(1 + NUM_TASK_PF_SEGMENTS * 2)
-#define ILT_CLI_VF_BLOCKS	(1 + NUM_TASK_VF_SEGMENTS * 2)
-#define CDUC_BLK		(0)
-#define SRQ_BLK			(0)
-#define CDUT_SEG_BLK(n)		(1 + (u8)(n))
-#define CDUT_FL_SEG_BLK(n, X)	(1 + (n) + NUM_TASK_##X##_SEGMENTS)
-
-struct ilt_cfg_pair {
-	u32 reg;
-	u32 val;
-};
-
-struct ecore_ilt_cli_blk {
-	u32 total_size;		/* 0 means not active */
-	u32 real_size_in_page;
-	u32 start_line;
-	u32 dynamic_line_offset;
-	u32 dynamic_line_cnt;
-};
-
-struct ecore_ilt_client_cfg {
-	bool active;
-
-	/* ILT boundaries */
-	struct ilt_cfg_pair first;
-	struct ilt_cfg_pair last;
-	struct ilt_cfg_pair p_size;
-
-	/* ILT client blocks for PF */
-	struct ecore_ilt_cli_blk pf_blks[ILT_CLI_PF_BLOCKS];
-	u32 pf_total_lines;
-
-	/* ILT client blocks for VFs */
-	struct ecore_ilt_cli_blk vf_blks[ILT_CLI_VF_BLOCKS];
-	u32 vf_total_lines;
-};
-
-#define MAP_WORD_SIZE		sizeof(unsigned long)
-#define BITS_PER_MAP_WORD	(MAP_WORD_SIZE * 8)
-
-struct ecore_cid_acquired_map {
-	u32 start_cid;
-	u32 max_count;
-	u32 *cid_map;
-};
-
-struct ecore_src_t2 {
-	struct phys_mem_desc	*dma_mem;
-	u32			num_pages;
-	u64			first_free;
-	u64			last_free;
-};
-
-struct ecore_cxt_mngr {
-	/* Per protocl configuration */
-	struct ecore_conn_type_cfg conn_cfg[MAX_CONN_TYPES];
-
-	/* computed ILT structure */
-	struct ecore_ilt_client_cfg clients[ILT_CLI_MAX];
-
-	/* Task type sizes */
-	u32 task_type_size[NUM_TASK_TYPES];
-
-	/* total number of VFs for this hwfn -
-	 * ALL VFs are symmetric in terms of HW resources
-	 */
-	u32 vf_count;
-
-	/* Acquired CIDs */
-	struct ecore_cid_acquired_map acquired[MAX_CONN_TYPES];
-	struct ecore_cid_acquired_map *acquired_vf[MAX_CONN_TYPES];
-
-	/* ILT  shadow table */
-	struct phys_mem_desc		*ilt_shadow;
-	u32 pf_start_line;
-
-	/* Mutex for a dynamic ILT allocation */
-	osal_mutex_t mutex;
-
-	/* SRC T2 */
-	struct ecore_src_t2		src_t2;
-
-	/* The infrastructure originally was very generic and context/task
-	 * oriented - per connection-type we would set how many of those
-	 * are needed, and later when determining how much memory we're
-	 * needing for a given block we'd iterate over all the relevant
-	 * connection-types.
-	 * But since then we've had some additional resources, some of which
-	 * require memory which is indepent of the general context/task
-	 * scheme. We add those here explicitly per-feature.
-	 */
-
-	/* total number of SRQ's for this hwfn */
-	u32				srq_count;
-
-	/* Maximal number of L2 steering filters */
-	u32				arfs_count;
-
-	/* TODO - VF arfs filters ? */
-};
-
 static OSAL_INLINE bool tm_cid_proto(enum protocol_type type)
 {
 	return type == PROTOCOLID_TOE;
@@ -945,7 +817,7 @@ static enum _ecore_status_t ecore_cxt_src_t2_alloc(struct ecore_hwfn *p_hwfn)
 }
 
 #define for_each_ilt_valid_client(pos, clients)		\
-	for (pos = 0; pos < ILT_CLI_MAX; pos++)		\
+	for (pos = 0; pos < MAX_ILT_CLIENTS; pos++)		\
 		if (!clients[pos].active) {		\
 			continue;			\
 		} else					\
@@ -1238,7 +1110,7 @@ enum _ecore_status_t ecore_cxt_mngr_alloc(struct ecore_hwfn *p_hwfn)
 	clients[ILT_CLI_TSDM].p_size.reg = ILT_CFG_REG(TSDM, P_SIZE);
 
 	/* default ILT page size for all clients is 64K */
-	for (i = 0; i < ILT_CLI_MAX; i++)
+	for (i = 0; i < MAX_ILT_CLIENTS; i++)
 		p_mngr->clients[i].p_size.val = ILT_DEFAULT_HW_P_SIZE;
 
 	/* due to removal of ISCSI/FCoE files union type0_task_context
@@ -2306,3 +2178,11 @@ ecore_cxt_free_ilt_range(struct ecore_hwfn *p_hwfn,
 
 	return ECORE_SUCCESS;
 }
+
+static u16 ecore_blk_calculate_pages(struct ecore_ilt_cli_blk *p_blk)
+{
+	if (p_blk->real_size_in_page == 0)
+		return 0;
+
+	return DIV_ROUND_UP(p_blk->total_size, p_blk->real_size_in_page);
+}
diff --git a/drivers/net/qede/base/ecore_cxt.h b/drivers/net/qede/base/ecore_cxt.h
index 55f08027d..7b91b953e 100644
--- a/drivers/net/qede/base/ecore_cxt.h
+++ b/drivers/net/qede/base/ecore_cxt.h
@@ -31,7 +31,7 @@ enum ilt_clients {
 	ILT_CLI_TSDM,
 	ILT_CLI_RGFS,
 	ILT_CLI_TGFS,
-	ILT_CLI_MAX
+	MAX_ILT_CLIENTS
 };
 
 u32 ecore_cxt_get_proto_cid_count(struct ecore_hwfn *p_hwfn,
@@ -212,4 +212,137 @@ enum _ecore_status_t ecore_cxt_free_proto_ilt(struct ecore_hwfn *p_hwfn,
 #define ECORE_CTX_WORKING_MEM 0
 #define ECORE_CTX_FL_MEM 1
 
+/* Max number of connection types in HW (DQ/CDU etc.) */
+#define MAX_CONN_TYPES		PROTOCOLID_COMMON
+#define NUM_TASK_TYPES		2
+#define NUM_TASK_PF_SEGMENTS	4
+#define NUM_TASK_VF_SEGMENTS	1
+
+/* PF per protocl configuration object */
+#define TASK_SEGMENTS   (NUM_TASK_PF_SEGMENTS + NUM_TASK_VF_SEGMENTS)
+#define TASK_SEGMENT_VF (NUM_TASK_PF_SEGMENTS)
+
+struct ecore_tid_seg {
+	u32 count;
+	u8 type;
+	bool has_fl_mem;
+};
+
+struct ecore_conn_type_cfg {
+	u32 cid_count;
+	u32 cids_per_vf;
+	struct ecore_tid_seg tid_seg[TASK_SEGMENTS];
+};
+
+/* ILT Client configuration,
+ * Per connection type (protocol) resources (cids, tis, vf cids etc.)
+ * 1 - for connection context (CDUC) and for each task context we need two
+ * values, for regular task context and for force load memory
+ */
+#define ILT_CLI_PF_BLOCKS	(1 + NUM_TASK_PF_SEGMENTS * 2)
+#define ILT_CLI_VF_BLOCKS	(1 + NUM_TASK_VF_SEGMENTS * 2)
+#define CDUC_BLK		(0)
+#define SRQ_BLK			(0)
+#define CDUT_SEG_BLK(n)		(1 + (u8)(n))
+#define CDUT_FL_SEG_BLK(n, X)	(1 + (n) + NUM_TASK_##X##_SEGMENTS)
+
+struct ilt_cfg_pair {
+	u32 reg;
+	u32 val;
+};
+
+struct ecore_ilt_cli_blk {
+	u32 total_size;		/* 0 means not active */
+	u32 real_size_in_page;
+	u32 start_line;
+	u32 dynamic_line_offset;
+	u32 dynamic_line_cnt;
+};
+
+struct ecore_ilt_client_cfg {
+	bool active;
+
+	/* ILT boundaries */
+	struct ilt_cfg_pair first;
+	struct ilt_cfg_pair last;
+	struct ilt_cfg_pair p_size;
+
+	/* ILT client blocks for PF */
+	struct ecore_ilt_cli_blk pf_blks[ILT_CLI_PF_BLOCKS];
+	u32 pf_total_lines;
+
+	/* ILT client blocks for VFs */
+	struct ecore_ilt_cli_blk vf_blks[ILT_CLI_VF_BLOCKS];
+	u32 vf_total_lines;
+};
+
+#define MAP_WORD_SIZE		sizeof(unsigned long)
+#define BITS_PER_MAP_WORD	(MAP_WORD_SIZE * 8)
+
+struct ecore_cid_acquired_map {
+	u32 start_cid;
+	u32 max_count;
+	u32 *cid_map;
+};
+
+struct ecore_src_t2 {
+	struct phys_mem_desc	*dma_mem;
+	u32			num_pages;
+	u64			first_free;
+	u64			last_free;
+};
+
+struct ecore_cxt_mngr {
+	/* Per protocl configuration */
+	struct ecore_conn_type_cfg	conn_cfg[MAX_CONN_TYPES];
+
+	/* computed ILT structure */
+	struct ecore_ilt_client_cfg	clients[MAX_ILT_CLIENTS];
+
+	/* Task type sizes */
+	u32				task_type_size[NUM_TASK_TYPES];
+
+	/* total number of VFs for this hwfn -
+	 * ALL VFs are symmetric in terms of HW resources
+	 */
+	u32				vf_count;
+	u32				first_vf_in_pf;
+
+	/* Acquired CIDs */
+	struct ecore_cid_acquired_map acquired[MAX_CONN_TYPES];
+	struct ecore_cid_acquired_map *acquired_vf[MAX_CONN_TYPES];
+
+	/* ILT  shadow table */
+	struct phys_mem_desc		*ilt_shadow;
+	u32				ilt_shadow_size;
+	u32				pf_start_line;
+
+	/* Mutex for a dynamic ILT allocation */
+	osal_mutex_t mutex;
+
+	/* SRC T2 */
+	struct ecore_src_t2		src_t2;
+
+	/* The infrastructure originally was very generic and context/task
+	 * oriented - per connection-type we would set how many of those
+	 * are needed, and later when determining how much memory we're
+	 * needing for a given block we'd iterate over all the relevant
+	 * connection-types.
+	 * But since then we've had some additional resources, some of which
+	 * require memory which is indepent of the general context/task
+	 * scheme. We add those here explicitly per-feature.
+	 */
+
+	/* total number of SRQ's for this hwfn */
+	u32				srq_count;
+
+	/* Maximal number of L2 steering filters */
+	u32				arfs_count;
+
+	/* TODO - VF arfs filters ? */
+
+	u8				task_type_id;
+	u16				task_ctx_size;
+	u16				conn_ctx_size;
+};
 #endif /* _ECORE_CID_ */
diff --git a/drivers/net/qede/base/ecore_hsi_func_common.h b/drivers/net/qede/base/ecore_hsi_func_common.h
new file mode 100644
index 000000000..2cd175163
--- /dev/null
+++ b/drivers/net/qede/base/ecore_hsi_func_common.h
@@ -0,0 +1,17 @@
+#ifndef _HSI_FUNC_COMMON_H
+#define _HSI_FUNC_COMMON_H
+
+/* Physical memory descriptor */
+struct phys_mem_desc {
+	dma_addr_t phys_addr;
+	void *virt_addr;
+	u32 size; /* In bytes */
+};
+
+/* Virtual memory descriptor */
+struct virt_mem_desc {
+	void *ptr;
+	u32 size; /* In bytes */
+};
+
+#endif
diff --git a/drivers/net/qede/base/ecore_init_fw_funcs.h b/drivers/net/qede/base/ecore_init_fw_funcs.h
index 912451662..a393d088f 100644
--- a/drivers/net/qede/base/ecore_init_fw_funcs.h
+++ b/drivers/net/qede/base/ecore_init_fw_funcs.h
@@ -9,13 +9,6 @@
 #include "ecore_hsi_common.h"
 #include "ecore_hsi_eth.h"
 
-/* Physical memory descriptor */
-struct phys_mem_desc {
-	dma_addr_t phys_addr;
-	void *virt_addr;
-	u32 size; /* In bytes */
-};
-
 /* Returns the VOQ based on port and TC */
 #define VOQ(port, tc, max_phys_tcs_per_port) \
 	((tc) == PURE_LB_TC ? NUM_OF_PHYS_TCS * MAX_NUM_PORTS_BB + (port) : \
-- 
2.18.0


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

* [dpdk-dev] [PATCH v2 2/4] net/qede/base: add changes for debug data collection
  2020-06-28  5:58 [dpdk-dev] [PATCH 0/4] net/qede: add FW debug data collection support Rasesh Mody
                   ` (5 preceding siblings ...)
  2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
@ 2020-06-30  8:32 ` Rasesh Mody
  2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 3/4] net/qede: add infrastructure " Rasesh Mody
  2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 4/4] net/qede: add support for get register operation Rasesh Mody
  8 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-06-30  8:32 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

This patch adds base driver APIs required for debug data collection.
It adds support for dumping internal lookup tables(ilt), reading nvram
image, register definitions.

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/qede/base/bcm_osal.c              |   6 +
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/qede/base/common_hsi.h            |   1 +
 drivers/net/qede/base/ecore.h                 |  52 +-
 drivers/net/qede/base/ecore_cxt.c             |  60 ++
 drivers/net/qede/base/ecore_cxt.h             |   5 +
 drivers/net/qede/base/ecore_dev.c             |  13 +
 drivers/net/qede/base/ecore_hsi_common.h      | 184 +++-
 drivers/net/qede/base/ecore_hsi_debug_tools.h |   2 +-
 drivers/net/qede/base/ecore_mcp.c             | 211 +++++
 drivers/net/qede/base/ecore_mcp_api.h         |  37 +
 drivers/net/qede/base/ecore_status.h          |   2 +
 drivers/net/qede/base/reg_addr.h              | 846 ++++++++++++++++++
 drivers/net/qede/qede_ethdev.c                |   1 -
 drivers/net/qede/qede_main.c                  |   3 +-
 15 files changed, 1414 insertions(+), 17 deletions(-)

diff --git a/drivers/net/qede/base/bcm_osal.c b/drivers/net/qede/base/bcm_osal.c
index 54e5e4f98..45557fe3c 100644
--- a/drivers/net/qede/base/bcm_osal.c
+++ b/drivers/net/qede/base/bcm_osal.c
@@ -289,3 +289,9 @@ u32 qede_crc32(u32 crc, u8 *ptr, u32 length)
 	}
 	return crc;
 }
+
+void qed_set_platform_str(struct ecore_hwfn *p_hwfn,
+			  char *buf_str, u32 buf_size)
+{
+	snprintf(buf_str, buf_size, "%s.", rte_version());
+}
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index 88a2500a5..6ea3e7dda 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -8,6 +8,7 @@
 #define __BCM_OSAL_H
 
 #include <stdbool.h>
+#include <time.h>
 #include <rte_bitops.h>
 #include <rte_byteorder.h>
 #include <rte_spinlock.h>
@@ -19,6 +20,7 @@
 #include <rte_debug.h>
 #include <rte_ether.h>
 #include <rte_io.h>
+#include <rte_version.h>
 
 /* Forward declaration */
 struct ecore_dev;
@@ -450,7 +452,11 @@ u32 qede_crc32(u32 crc, u8 *ptr, u32 length);
 
 #define OSAL_DIV_S64(a, b)	((a) / (b))
 #define OSAL_LLDP_RX_TLVS(p_hwfn, tlv_buf, tlv_size) nothing
-#define OSAL_GET_EPOCH(p_hwfn)	0
+void qed_set_platform_str(struct ecore_hwfn *p_hwfn,
+			  char *buf_str, u32 buf_size);
+#define OSAL_SET_PLATFORM_STR(p_hwfn, buf_str, buf_size) \
+	qed_set_platform_str(p_hwfn, buf_str, buf_size)
+#define OSAL_GET_EPOCH(p_hwfn) ((u32)time(NULL))
 #define OSAL_DBG_ALLOC_USER_DATA(p_hwfn, user_data_ptr) (0)
 #define OSAL_DB_REC_OCCURRED(p_hwfn) nothing
 
diff --git a/drivers/net/qede/base/common_hsi.h b/drivers/net/qede/base/common_hsi.h
index e230fe5ac..1a02d460b 100644
--- a/drivers/net/qede/base/common_hsi.h
+++ b/drivers/net/qede/base/common_hsi.h
@@ -145,6 +145,7 @@
 #define NUM_OF_CONNECTION_TYPES (8)
 #define NUM_OF_TASK_TYPES       (8)
 #define NUM_OF_LCIDS            (320)
+#define NUM_OF_LTIDS            (320)
 
 /* Global PXP windows (GTT) */
 #define NUM_OF_GTT          19
diff --git a/drivers/net/qede/base/ecore.h b/drivers/net/qede/base/ecore.h
index dc5fe4d80..63bd7466a 100644
--- a/drivers/net/qede/base/ecore.h
+++ b/drivers/net/qede/base/ecore.h
@@ -576,6 +576,12 @@ enum BAR_ID {
 	BAR_ID_1	/* Used for doorbells */
 };
 
+struct ecore_nvm_image_info {
+	u32				num_images;
+	struct bist_nvm_image_att	*image_att;
+	bool				valid;
+};
+
 struct ecore_hwfn {
 	struct ecore_dev		*p_dev;
 	u8				my_id;		/* ID inside the PF */
@@ -701,6 +707,9 @@ struct ecore_hwfn {
 	 */
 	bool b_en_pacing;
 
+	/* Nvm images number and attributes */
+	struct ecore_nvm_image_info     nvm_info;
+
 	struct phys_mem_desc            *fw_overlay_mem;
 
 	/* @DPDK */
@@ -714,26 +723,34 @@ enum ecore_mf_mode {
 	ECORE_MF_UFP,
 };
 
-/* @DPDK */
-struct ecore_dbg_feature {
-	u8				*dump_buf;
-	u32				buf_size;
-	u32				dumped_dwords;
+enum ecore_dev_type {
+	ECORE_DEV_TYPE_BB,
+	ECORE_DEV_TYPE_AH,
 };
 
-enum qed_dbg_features {
-	DBG_FEATURE_BUS,
+/* @DPDK */
+enum ecore_dbg_features {
 	DBG_FEATURE_GRC,
 	DBG_FEATURE_IDLE_CHK,
 	DBG_FEATURE_MCP_TRACE,
 	DBG_FEATURE_REG_FIFO,
+	DBG_FEATURE_IGU_FIFO,
 	DBG_FEATURE_PROTECTION_OVERRIDE,
+	DBG_FEATURE_FW_ASSERTS,
+	DBG_FEATURE_ILT,
 	DBG_FEATURE_NUM
 };
 
-enum ecore_dev_type {
-	ECORE_DEV_TYPE_BB,
-	ECORE_DEV_TYPE_AH,
+struct ecore_dbg_feature {
+	u8				*dump_buf;
+	u32				buf_size;
+	u32				dumped_dwords;
+};
+
+struct ecore_dbg_params {
+	struct ecore_dbg_feature features[DBG_FEATURE_NUM];
+	u8 engine_for_debug;
+	bool print_data;
 };
 
 struct ecore_dev {
@@ -914,10 +931,12 @@ struct ecore_dev {
 	void				*firmware;
 	u64				fw_len;
 #endif
+	bool				disable_ilt_dump;
 
 	/* @DPDK */
 	struct ecore_dbg_feature	dbg_features[DBG_FEATURE_NUM];
-	u8				engine_for_debug;
+	struct ecore_dbg_params		dbg_params;
+	osal_mutex_t			dbg_lock;
 };
 
 enum ecore_hsi_def_type {
@@ -1067,6 +1086,17 @@ enum _ecore_status_t ecore_all_ppfids_wr(struct ecore_hwfn *p_hwfn,
 enum _ecore_status_t ecore_llh_dump_ppfid(struct ecore_dev *p_dev, u8 ppfid);
 enum _ecore_status_t ecore_llh_dump_all(struct ecore_dev *p_dev);
 
+/**
+ * @brief ecore_set_platform_str - Set the debug dump platform string.
+ * Write the ecore version and device's string to the given buffer.
+ *
+ * @param p_hwfn
+ * @param buf_str
+ * @param buf_size
+ */
+void ecore_set_platform_str(struct ecore_hwfn *p_hwfn,
+			    char *buf_str, u32 buf_size);
+
 #define TSTORM_QZONE_START	PXP_VF_BAR0_START_SDM_ZONE_A
 
 #define MSTORM_QZONE_START(dev) \
diff --git a/drivers/net/qede/base/ecore_cxt.c b/drivers/net/qede/base/ecore_cxt.c
index 23f37b1bf..d3025724b 100644
--- a/drivers/net/qede/base/ecore_cxt.c
+++ b/drivers/net/qede/base/ecore_cxt.c
@@ -2186,3 +2186,63 @@ static u16 ecore_blk_calculate_pages(struct ecore_ilt_cli_blk *p_blk)
 
 	return DIV_ROUND_UP(p_blk->total_size, p_blk->real_size_in_page);
 }
+
+u16 ecore_get_cdut_num_pf_init_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 i, pages = 0;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_PF_SEGMENTS; i++) {
+		p_blk = &p_cli->pf_blks[CDUT_FL_SEG_BLK(i, PF)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
+
+u16 ecore_get_cdut_num_vf_init_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 i, pages = 0;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_VF_SEGMENTS; i++) {
+		p_blk = &p_cli->vf_blks[CDUT_FL_SEG_BLK(i, VF)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
+
+u16 ecore_get_cdut_num_pf_work_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 i, pages = 0;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_PF_SEGMENTS; i++) {
+		p_blk = &p_cli->pf_blks[CDUT_SEG_BLK(i)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
+
+u16 ecore_get_cdut_num_vf_work_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 pages = 0, i;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_VF_SEGMENTS; i++) {
+		p_blk = &p_cli->vf_blks[CDUT_SEG_BLK(i)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
diff --git a/drivers/net/qede/base/ecore_cxt.h b/drivers/net/qede/base/ecore_cxt.h
index 7b91b953e..80fe39ac0 100644
--- a/drivers/net/qede/base/ecore_cxt.h
+++ b/drivers/net/qede/base/ecore_cxt.h
@@ -345,4 +345,9 @@ struct ecore_cxt_mngr {
 	u16				task_ctx_size;
 	u16				conn_ctx_size;
 };
+
+u16 ecore_get_cdut_num_pf_init_pages(struct ecore_hwfn *p_hwfn);
+u16 ecore_get_cdut_num_vf_init_pages(struct ecore_hwfn *p_hwfn);
+u16 ecore_get_cdut_num_pf_work_pages(struct ecore_hwfn *p_hwfn);
+u16 ecore_get_cdut_num_vf_work_pages(struct ecore_hwfn *p_hwfn);
 #endif /* _ECORE_CID_ */
diff --git a/drivers/net/qede/base/ecore_dev.c b/drivers/net/qede/base/ecore_dev.c
index e18c2fa89..3f86abdec 100644
--- a/drivers/net/qede/base/ecore_dev.c
+++ b/drivers/net/qede/base/ecore_dev.c
@@ -6793,6 +6793,19 @@ void ecore_set_fw_mac_addr(__le16 *fw_msb,
 	((u8 *)fw_lsb)[1] = mac[4];
 }
 
+void ecore_set_platform_str(struct ecore_hwfn *p_hwfn,
+			    char *buf_str, u32 buf_size)
+{
+	u32 len;
+
+	OSAL_SNPRINTF(buf_str, buf_size, "Ecore %d.%d.%d.%d. ",
+		      ECORE_MAJOR_VERSION, ECORE_MINOR_VERSION,
+		      ECORE_REVISION_VERSION, ECORE_ENGINEERING_VERSION);
+
+	len = OSAL_STRLEN(buf_str);
+	OSAL_SET_PLATFORM_STR(p_hwfn, &buf_str[len], buf_size - len);
+}
+
 bool ecore_is_mf_fip_special(struct ecore_dev *p_dev)
 {
 	return !!OSAL_GET_BIT(ECORE_MF_FIP_SPECIAL, &p_dev->mf_bits);
diff --git a/drivers/net/qede/base/ecore_hsi_common.h b/drivers/net/qede/base/ecore_hsi_common.h
index 23cfcdeff..578c798a9 100644
--- a/drivers/net/qede/base/ecore_hsi_common.h
+++ b/drivers/net/qede/base/ecore_hsi_common.h
@@ -10,6 +10,7 @@
 /* Add include to common target */
 /********************************/
 #include "common_hsi.h"
+#include "mcp_public.h"
 
 
 /*
@@ -2229,7 +2230,40 @@ struct fw_info_location {
 };
 
 
-
+/* DMAE parameters */
+struct ecore_dmae_params {
+	u32 flags;
+/* If QED_DMAE_PARAMS_RW_REPL_SRC flag is set and the
+ * source is a block of length DMAE_MAX_RW_SIZE and the
+ * destination is larger, the source block will be duplicated as
+ * many times as required to fill the destination block. This is
+ * used mostly to write a zeroed buffer to destination address
+ * using DMA
+ */
+#define ECORE_DMAE_PARAMS_RW_REPL_SRC_MASK        0x1
+#define ECORE_DMAE_PARAMS_RW_REPL_SRC_SHIFT       0
+#define ECORE_DMAE_PARAMS_SRC_VF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_SRC_VF_VALID_SHIFT      1
+#define ECORE_DMAE_PARAMS_DST_VF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_DST_VF_VALID_SHIFT      2
+#define ECORE_DMAE_PARAMS_COMPLETION_DST_MASK     0x1
+#define ECORE_DMAE_PARAMS_COMPLETION_DST_SHIFT    3
+#define ECORE_DMAE_PARAMS_PORT_VALID_MASK         0x1
+#define ECORE_DMAE_PARAMS_PORT_VALID_SHIFT        4
+#define ECORE_DMAE_PARAMS_SRC_PF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_SRC_PF_VALID_SHIFT      5
+#define ECORE_DMAE_PARAMS_DST_PF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_DST_PF_VALID_SHIFT      6
+#define ECORE_DMAE_PARAMS_RESERVED_MASK           0x1FFFFFF
+#define ECORE_DMAE_PARAMS_RESERVED_SHIFT          7
+	u8 src_vfid;
+	u8 dst_vfid;
+	u8 port_id;
+	u8 src_pfid;
+	u8 dst_pfid;
+	u8 reserved1;
+	__le16 reserved2;
+};
 
 /*
  * IGU cleanup command
@@ -2543,4 +2577,152 @@ struct ystorm_core_conn_ag_ctx {
 	__le32 reg3 /* reg3 */;
 };
 
+/*********/
+/* DEBUG */
+/*********/
+
+#define MFW_TRACE_SIGNATURE	0x25071946
+
+/* The trace in the buffer */
+#define MFW_TRACE_EVENTID_MASK		0x00ffff
+#define MFW_TRACE_PRM_SIZE_MASK		0x0f0000
+#define MFW_TRACE_PRM_SIZE_OFFSET	16
+#define MFW_TRACE_ENTRY_SIZE		3
+
+struct mcp_trace {
+	u32	signature;	/* Help to identify that the trace is valid */
+	u32	size;		/* the size of the trace buffer in bytes*/
+	u32	curr_level;	/* 2 - all will be written to the buffer
+				 * 1 - debug trace will not be written
+				 * 0 - just errors will be written to the buffer
+				 */
+	/* a bit per module, 1 means mask it off, 0 means add it to the trace
+	 * buffer
+	 */
+	u32	modules_mask[2];
+
+	/* Warning: the following pointers are assumed to be 32bits as they are
+	 * used only in the MFW
+	 */
+	/* The next trace will be written to this offset */
+	u32	trace_prod;
+	/* The oldest valid trace starts at this offset (usually very close
+	 * after the current producer)
+	 */
+	u32	trace_oldest;
+};
+
+enum spad_sections {
+	SPAD_SECTION_TRACE,
+	SPAD_SECTION_NVM_CFG,
+	SPAD_SECTION_PUBLIC,
+	SPAD_SECTION_PRIVATE,
+	SPAD_SECTION_MAX
+};
+
+#define MCP_TRACE_SIZE          2048    /* 2kb */
+
+/* This section is located at a fixed location in the beginning of the
+ * scratchpad, to ensure that the MCP trace is not run over during MFW upgrade.
+ * All the rest of data has a floating location which differs from version to
+ * version, and is pointed by the mcp_meta_data below.
+ * Moreover, the spad_layout section is part of the MFW firmware, and is loaded
+ * with it from nvram in order to clear this portion.
+ */
+struct static_init {
+	u32 num_sections;
+	offsize_t sections[SPAD_SECTION_MAX];
+#define SECTION(_sec_) (*((offsize_t *)(STRUCT_OFFSET(sections[_sec_]))))
+
+	struct mcp_trace trace;
+#define MCP_TRACE_P ((struct mcp_trace *)(STRUCT_OFFSET(trace)))
+	u8 trace_buffer[MCP_TRACE_SIZE];
+#define MCP_TRACE_BUF ((u8 *)(STRUCT_OFFSET(trace_buffer)))
+	/* running_mfw has the same definition as in nvm_map.h.
+	 * This bit indicate both the running dir, and the running bundle.
+	 * It is set once when the LIM is loaded.
+	 */
+	u32 running_mfw;
+#define RUNNING_MFW (*((u32 *)(STRUCT_OFFSET(running_mfw))))
+	u32 build_time;
+#define MFW_BUILD_TIME (*((u32 *)(STRUCT_OFFSET(build_time))))
+	u32 reset_type;
+#define RESET_TYPE (*((u32 *)(STRUCT_OFFSET(reset_type))))
+	u32 mfw_secure_mode;
+#define MFW_SECURE_MODE (*((u32 *)(STRUCT_OFFSET(mfw_secure_mode))))
+	u16 pme_status_pf_bitmap;
+#define PME_STATUS_PF_BITMAP (*((u16 *)(STRUCT_OFFSET(pme_status_pf_bitmap))))
+	u16 pme_enable_pf_bitmap;
+#define PME_ENABLE_PF_BITMAP (*((u16 *)(STRUCT_OFFSET(pme_enable_pf_bitmap))))
+	u32 mim_nvm_addr;
+	u32 mim_start_addr;
+	u32 ah_pcie_link_params;
+#define AH_PCIE_LINK_PARAMS_LINK_SPEED_MASK     (0x000000ff)
+#define AH_PCIE_LINK_PARAMS_LINK_SPEED_SHIFT    (0)
+#define AH_PCIE_LINK_PARAMS_LINK_WIDTH_MASK     (0x0000ff00)
+#define AH_PCIE_LINK_PARAMS_LINK_WIDTH_SHIFT    (8)
+#define AH_PCIE_LINK_PARAMS_ASPM_MODE_MASK      (0x00ff0000)
+#define AH_PCIE_LINK_PARAMS_ASPM_MODE_SHIFT     (16)
+#define AH_PCIE_LINK_PARAMS_ASPM_CAP_MASK       (0xff000000)
+#define AH_PCIE_LINK_PARAMS_ASPM_CAP_SHIFT      (24)
+#define AH_PCIE_LINK_PARAMS (*((u32 *)(STRUCT_OFFSET(ah_pcie_link_params))))
+
+	u32 rsrv_persist[5];	/* Persist reserved for MFW upgrades */
+};
+
+#define NVM_MAGIC_VALUE		0x669955aa
+
+enum nvm_image_type {
+	NVM_TYPE_TIM1 = 0x01,
+	NVM_TYPE_TIM2 = 0x02,
+	NVM_TYPE_MIM1 = 0x03,
+	NVM_TYPE_MIM2 = 0x04,
+	NVM_TYPE_MBA = 0x05,
+	NVM_TYPE_MODULES_PN = 0x06,
+	NVM_TYPE_VPD = 0x07,
+	NVM_TYPE_MFW_TRACE1 = 0x08,
+	NVM_TYPE_MFW_TRACE2 = 0x09,
+	NVM_TYPE_NVM_CFG1 = 0x0a,
+	NVM_TYPE_L2B = 0x0b,
+	NVM_TYPE_DIR1 = 0x0c,
+	NVM_TYPE_EAGLE_FW1 = 0x0d,
+	NVM_TYPE_FALCON_FW1 = 0x0e,
+	NVM_TYPE_PCIE_FW1 = 0x0f,
+	NVM_TYPE_HW_SET = 0x10,
+	NVM_TYPE_LIM = 0x11,
+	NVM_TYPE_AVS_FW1 = 0x12,
+	NVM_TYPE_DIR2 = 0x13,
+	NVM_TYPE_CCM = 0x14,
+	NVM_TYPE_EAGLE_FW2 = 0x15,
+	NVM_TYPE_FALCON_FW2 = 0x16,
+	NVM_TYPE_PCIE_FW2 = 0x17,
+	NVM_TYPE_AVS_FW2 = 0x18,
+	NVM_TYPE_INIT_HW = 0x19,
+	NVM_TYPE_DEFAULT_CFG = 0x1a,
+	NVM_TYPE_MDUMP = 0x1b,
+	NVM_TYPE_META = 0x1c,
+	NVM_TYPE_ISCSI_CFG = 0x1d,
+	NVM_TYPE_FCOE_CFG = 0x1f,
+	NVM_TYPE_ETH_PHY_FW1 = 0x20,
+	NVM_TYPE_ETH_PHY_FW2 = 0x21,
+	NVM_TYPE_BDN = 0x22,
+	NVM_TYPE_8485X_PHY_FW = 0x23,
+	NVM_TYPE_PUB_KEY = 0x24,
+	NVM_TYPE_RECOVERY = 0x25,
+	NVM_TYPE_PLDM = 0x26,
+	NVM_TYPE_UPK1 = 0x27,
+	NVM_TYPE_UPK2 = 0x28,
+	NVM_TYPE_MASTER_KC = 0x29,
+	NVM_TYPE_BACKUP_KC = 0x2a,
+	NVM_TYPE_HW_DUMP = 0x2b,
+	NVM_TYPE_HW_DUMP_OUT = 0x2c,
+	NVM_TYPE_BIN_NVM_META = 0x30,
+	NVM_TYPE_ROM_TEST = 0xf0,
+	NVM_TYPE_88X33X0_PHY_FW = 0x31,
+	NVM_TYPE_88X33X0_PHY_SLAVE_FW = 0x32,
+	NVM_TYPE_MAX,
+};
+
+#define DIR_ID_1    (0)
+
 #endif /* __ECORE_HSI_COMMON__ */
diff --git a/drivers/net/qede/base/ecore_hsi_debug_tools.h b/drivers/net/qede/base/ecore_hsi_debug_tools.h
index eb72e93cf..c5ef67f84 100644
--- a/drivers/net/qede/base/ecore_hsi_debug_tools.h
+++ b/drivers/net/qede/base/ecore_hsi_debug_tools.h
@@ -245,6 +245,7 @@ struct dbg_mode_hdr {
  * Attention register
  */
 struct dbg_attn_reg {
+	struct dbg_mode_hdr mode /* Mode header */;
 /* The offset of this registers attentions within the blocks attentions list
  * (a value in the range 0..number of block attentions-1)
  */
@@ -1049,5 +1050,4 @@ struct dbg_tools_data {
 };
 
 
-
 #endif /* __ECORE_HSI_DEBUG_TOOLS__ */
diff --git a/drivers/net/qede/base/ecore_mcp.c b/drivers/net/qede/base/ecore_mcp.c
index 0a9e26805..cab089d81 100644
--- a/drivers/net/qede/base/ecore_mcp.c
+++ b/drivers/net/qede/base/ecore_mcp.c
@@ -3621,6 +3621,217 @@ enum _ecore_status_t ecore_mcp_bist_nvm_test_get_image_att(
 	return rc;
 }
 
+enum _ecore_status_t
+ecore_mcp_bist_nvm_get_num_images(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt, u32 *num_images)
+{
+	u32 drv_mb_param = 0, rsp;
+	enum _ecore_status_t rc = ECORE_SUCCESS;
+
+	SET_MFW_FIELD(drv_mb_param, DRV_MB_PARAM_BIST_TEST_INDEX,
+		      DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES);
+
+	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
+			   drv_mb_param, &rsp, num_images);
+	if (rc != ECORE_SUCCESS)
+		return rc;
+
+	if (rsp == FW_MSG_CODE_UNSUPPORTED)
+		rc = ECORE_NOTIMPL;
+	else if (rsp != FW_MSG_CODE_OK)
+		rc = ECORE_UNKNOWN_ERROR;
+
+	return rc;
+}
+
+enum _ecore_status_t
+ecore_mcp_bist_nvm_get_image_att(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 struct bist_nvm_image_att *p_image_att,
+				 u32 image_index)
+{
+	u32 buf_size, nvm_offset = 0, resp, param;
+	enum _ecore_status_t rc;
+
+	SET_MFW_FIELD(nvm_offset, DRV_MB_PARAM_BIST_TEST_INDEX,
+		      DRV_MB_PARAM_BIST_NVM_TEST_IMAGE_BY_INDEX);
+	SET_MFW_FIELD(nvm_offset, DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX,
+		      image_index);
+	rc = ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
+				  nvm_offset, &resp, &param, &buf_size,
+				  (u32 *)p_image_att);
+	if (rc != ECORE_SUCCESS)
+		return rc;
+
+	if (resp == FW_MSG_CODE_UNSUPPORTED)
+		rc = ECORE_NOTIMPL;
+	else if ((resp != FW_MSG_CODE_OK) || (p_image_att->return_code != 1))
+		rc = ECORE_UNKNOWN_ERROR;
+
+	return rc;
+}
+
+enum _ecore_status_t ecore_mcp_nvm_info_populate(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_nvm_image_info nvm_info;
+	struct ecore_ptt *p_ptt;
+	enum _ecore_status_t rc;
+	u32 i;
+
+	if (p_hwfn->nvm_info.valid)
+		return ECORE_SUCCESS;
+
+#ifndef ASIC_ONLY
+	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev) ||
+	    CHIP_REV_IS_TEDIBEAR(p_hwfn->p_dev))
+		return ECORE_SUCCESS;
+#endif
+
+	p_ptt = ecore_ptt_acquire(p_hwfn);
+	if (!p_ptt) {
+		DP_ERR(p_hwfn, "failed to acquire ptt\n");
+		return ECORE_BUSY;
+	}
+
+	/* Acquire from MFW the amount of available images */
+	OSAL_MEM_ZERO(&nvm_info, sizeof(nvm_info));
+	rc = ecore_mcp_bist_nvm_get_num_images(p_hwfn, p_ptt,
+					       &nvm_info.num_images);
+	if (rc == ECORE_NOTIMPL) {
+		DP_INFO(p_hwfn, "DRV_MSG_CODE_BIST_TEST is not supported\n");
+		goto out;
+	} else if ((rc != ECORE_SUCCESS) || (nvm_info.num_images == 0)) {
+		DP_ERR(p_hwfn, "Failed getting number of images\n");
+		goto err0;
+	}
+
+	nvm_info.image_att = OSAL_ALLOC(p_hwfn->p_dev, GFP_KERNEL,
+					 nvm_info.num_images *
+					 sizeof(struct bist_nvm_image_att));
+	if (!nvm_info.image_att) {
+		rc = ECORE_NOMEM;
+		goto err0;
+	}
+
+	/* Iterate over images and get their attributes */
+	for (i = 0; i < nvm_info.num_images; i++) {
+		rc = ecore_mcp_bist_nvm_get_image_att(p_hwfn, p_ptt,
+						      &nvm_info.image_att[i],
+						      i);
+		if (rc != ECORE_SUCCESS) {
+			DP_ERR(p_hwfn,
+			       "Failed getting image index %d attributes\n",
+			       i);
+			goto err1;
+		}
+
+		DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "image index %d, size %x\n", i,
+			   nvm_info.image_att[i].len);
+	}
+out:
+	/* Update hwfn's nvm_info */
+	if (nvm_info.num_images) {
+		p_hwfn->nvm_info.num_images = nvm_info.num_images;
+		if (p_hwfn->nvm_info.image_att)
+			OSAL_FREE(p_hwfn->p_dev, p_hwfn->nvm_info.image_att);
+		p_hwfn->nvm_info.image_att = nvm_info.image_att;
+		p_hwfn->nvm_info.valid = true;
+	}
+
+	ecore_ptt_release(p_hwfn, p_ptt);
+	return ECORE_SUCCESS;
+
+err1:
+	OSAL_FREE(p_hwfn->p_dev, nvm_info.image_att);
+err0:
+	ecore_ptt_release(p_hwfn, p_ptt);
+	return rc;
+}
+
+enum _ecore_status_t
+ecore_mcp_get_nvm_image_att(struct ecore_hwfn *p_hwfn,
+			    enum ecore_nvm_images image_id,
+			    struct ecore_nvm_image_att *p_image_att)
+{
+	enum nvm_image_type type;
+	u32 i;
+
+	/* Translate image_id into MFW definitions */
+	switch (image_id) {
+	case ECORE_NVM_IMAGE_ISCSI_CFG:
+		type = NVM_TYPE_ISCSI_CFG;
+		break;
+	case ECORE_NVM_IMAGE_FCOE_CFG:
+		type = NVM_TYPE_FCOE_CFG;
+		break;
+	case ECORE_NVM_IMAGE_MDUMP:
+		type = NVM_TYPE_MDUMP;
+		break;
+	case ECORE_NVM_IMAGE_NVM_CFG1:
+		type = NVM_TYPE_NVM_CFG1;
+		break;
+	case ECORE_NVM_IMAGE_DEFAULT_CFG:
+		type = NVM_TYPE_DEFAULT_CFG;
+		break;
+	case ECORE_NVM_IMAGE_NVM_META:
+		type = NVM_TYPE_META;
+		break;
+	default:
+		DP_NOTICE(p_hwfn, false, "Unknown request of image_id %08x\n",
+			  image_id);
+		return ECORE_INVAL;
+	}
+
+	ecore_mcp_nvm_info_populate(p_hwfn);
+	for (i = 0; i < p_hwfn->nvm_info.num_images; i++) {
+		if (type == p_hwfn->nvm_info.image_att[i].image_type)
+			break;
+	}
+	if (i == p_hwfn->nvm_info.num_images) {
+		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
+			   "Failed to find nvram image of type %08x\n",
+			   image_id);
+		return ECORE_NOENT;
+	}
+
+	p_image_att->start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr;
+	p_image_att->length = p_hwfn->nvm_info.image_att[i].len;
+
+	return ECORE_SUCCESS;
+}
+
+enum _ecore_status_t ecore_mcp_get_nvm_image(struct ecore_hwfn *p_hwfn,
+					     enum ecore_nvm_images image_id,
+					     u8 *p_buffer, u32 buffer_len)
+{
+	struct ecore_nvm_image_att image_att;
+	enum _ecore_status_t rc;
+
+	OSAL_MEM_ZERO(p_buffer, buffer_len);
+
+	rc = ecore_mcp_get_nvm_image_att(p_hwfn, image_id, &image_att);
+	if (rc != ECORE_SUCCESS)
+		return rc;
+
+	/* Validate sizes - both the image's and the supplied buffer's */
+	if (image_att.length <= 4) {
+		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
+			   "Image [%d] is too small - only %d bytes\n",
+			   image_id, image_att.length);
+		return ECORE_INVAL;
+	}
+
+	if (image_att.length > buffer_len) {
+		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
+			   "Image [%d] is too big - %08x bytes where only %08x are available\n",
+			   image_id, image_att.length, buffer_len);
+		return ECORE_NOMEM;
+	}
+
+	return ecore_mcp_nvm_read(p_hwfn->p_dev, image_att.start_addr,
+				  (u8 *)p_buffer, image_att.length);
+}
+
 enum _ecore_status_t
 ecore_mcp_get_temperature_info(struct ecore_hwfn *p_hwfn,
 			       struct ecore_ptt *p_ptt,
diff --git a/drivers/net/qede/base/ecore_mcp_api.h b/drivers/net/qede/base/ecore_mcp_api.h
index dc889ab8e..53c130be7 100644
--- a/drivers/net/qede/base/ecore_mcp_api.h
+++ b/drivers/net/qede/base/ecore_mcp_api.h
@@ -121,6 +121,10 @@ struct ecore_mcp_function_info {
 enum ecore_nvm_images {
 	ECORE_NVM_IMAGE_ISCSI_CFG,
 	ECORE_NVM_IMAGE_FCOE_CFG,
+	ECORE_NVM_IMAGE_MDUMP,
+	ECORE_NVM_IMAGE_NVM_CFG1,
+	ECORE_NVM_IMAGE_DEFAULT_CFG,
+	ECORE_NVM_IMAGE_NVM_META,
 };
 #endif
 
@@ -970,6 +974,39 @@ enum _ecore_status_t ecore_mcp_phy_read(struct ecore_dev *p_dev, u32 cmd,
 enum _ecore_status_t ecore_mcp_nvm_read(struct ecore_dev *p_dev, u32 addr,
 			   u8 *p_buf, u32 len);
 
+struct ecore_nvm_image_att {
+	u32 start_addr;
+	u32 length;
+};
+
+/**
+ * @brief Allows reading a whole nvram image
+ *
+ * @param p_hwfn
+ * @param image_id - image to get attributes for
+ * @param p_image_att - image attributes structure into which to fill data
+ *
+ * @return enum _ecore_status_t - ECORE_SUCCESS - operation was successful.
+ */
+enum _ecore_status_t
+ecore_mcp_get_nvm_image_att(struct ecore_hwfn *p_hwfn,
+			    enum ecore_nvm_images image_id,
+			    struct ecore_nvm_image_att *p_image_att);
+
+/**
+ * @brief Allows reading a whole nvram image
+ *
+ * @param p_hwfn
+ * @param image_id - image requested for reading
+ * @param p_buffer - allocated buffer into which to fill data
+ * @param buffer_len - length of the allocated buffer.
+ *
+ * @return ECORE_SUCCESS iff p_buffer now contains the nvram image.
+ */
+enum _ecore_status_t ecore_mcp_get_nvm_image(struct ecore_hwfn *p_hwfn,
+					     enum ecore_nvm_images image_id,
+					     u8 *p_buffer, u32 buffer_len);
+
 /**
  * @brief - Sends an NVM write command request to the MFW with
  *          payload.
diff --git a/drivers/net/qede/base/ecore_status.h b/drivers/net/qede/base/ecore_status.h
index b893f1d41..01cf9fd31 100644
--- a/drivers/net/qede/base/ecore_status.h
+++ b/drivers/net/qede/base/ecore_status.h
@@ -8,6 +8,8 @@
 #define __ECORE_STATUS_H__
 
 enum _ecore_status_t {
+	ECORE_NOENT = -15,
+	ECORE_CONN_REFUSED = -14,
 	ECORE_CONN_RESET = -13,
 	ECORE_UNKNOWN_ERROR  = -12,
 	ECORE_NORESOURCES	 = -11,
diff --git a/drivers/net/qede/base/reg_addr.h b/drivers/net/qede/base/reg_addr.h
index 91d889dc8..c84d3865f 100644
--- a/drivers/net/qede/base/reg_addr.h
+++ b/drivers/net/qede/base/reg_addr.h
@@ -1245,3 +1245,849 @@
 #define DORQ_REG_VF_USAGE_CNT_LIM 0x1009ccUL
 #define PGLUE_B_REG_SR_IOV_DISABLED_REQUEST 0x2aa06cUL
 #define PGLUE_B_REG_SR_IOV_DISABLED_REQUEST_CLR 0x2aa070UL
+
+#define PSWRQ2_REG_ILT_MEMORY_SIZE_BB 15200
+#define PSWRQ2_REG_ILT_MEMORY_SIZE_K2 22000
+#define TSEM_REG_DBG_GPRE_VECT 0x1701410UL
+#define MSEM_REG_DBG_GPRE_VECT 0x1801410UL
+#define USEM_REG_DBG_GPRE_VECT 0x1901410UL
+#define XSEM_REG_DBG_GPRE_VECT 0x1401410UL
+#define YSEM_REG_DBG_GPRE_VECT 0x1501410UL
+#define PSEM_REG_DBG_GPRE_VECT 0x1601410UL
+#define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE 0x000748UL
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_WRITE_DISABLE (0x1UL << 0)
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_WRITE_DISABLE_SHIFT 0
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_READ_DISABLE (0x1UL << 1)
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_READ_DISABLE_SHIFT 1
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_INTERRUPT_DISABLE (0x1UL << 2)
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_INTERRUPT_DISABLE_SHIFT 2
+#define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE 0x00074cUL
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_STORE_DATA_DISABLE (0x1UL << 0)
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_STORE_DATA_DISABLE_SHIFT 0
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_LOAD_DATA_DISABLE (0x1UL << 1)
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_LOAD_DATA_DISABLE_SHIFT 1
+#define NWS_REG_NWS_CMU_K2 0x720000UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_7_0_K2 0x000680UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_15_8_K2 0x000684UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_7_0_K2 0x0006c0UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_11_8_K2 0x0006c4UL
+#define MS_REG_MS_CMU_K2 0x6a4000UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X132_K2 0x000210UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X133_K2 0x000214UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X130_K2 0x000208UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X131_K2 0x00020cUL
+#define PHY_PCIE_REG_PHY0_K2 0x620000UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2 0x000210UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2 0x000214UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2 0x000208UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2 0x00020cUL
+#define PHY_PCIE_REG_PHY1_K2 0x624000UL
+#define PCIE_REG_DBG_REPEAT_THRESHOLD_COUNT_K2 0x054364UL
+#define PCIE_REG_DBG_FW_TRIGGER_ENABLE_K2 0x05436cUL
+#define RDIF_REG_DEBUG_ERROR_INFO 0x300400UL
+#define RDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define RDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define TDIF_REG_DEBUG_ERROR_INFO 0x310400UL
+#define TDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define TDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define SEM_FAST_REG_VFC_STATUS 0x000b4cUL
+  #define SEM_FAST_REG_VFC_STATUS_RESPONSE_READY (0x1UL << 0)
+  #define SEM_FAST_REG_VFC_STATUS_RESPONSE_READY_SHIFT 0
+  #define SEM_FAST_REG_VFC_STATUS_VFC_BUSY (0x1UL << 1)
+  #define SEM_FAST_REG_VFC_STATUS_VFC_BUSY_SHIFT 1
+  #define SEM_FAST_REG_VFC_STATUS_SENDING_CMD_ON_GOING (0x1UL << 2)
+  #define SEM_FAST_REG_VFC_STATUS_SENDING_CMD_ON_GOING_SHIFT 2
+#define RSS_REG_RSS_RAM_DATA_SIZE 4
+#define BRB_REG_BIG_RAM_DATA_SIZE 64
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_1 0x0084c0UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_2 0x0084e4UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_3 0x008508UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_4 0x00852cUL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_5 0x008550UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_6 0x008574UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_7 0x008598UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_NIG 0x0085bcUL
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_PXP 0x0085e0UL
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_MCP_OUT_0 0x008628UL
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR 0x008748UL
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_SYS_KILL 0x008604UL
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO31_SHIFT 31
+#define DBG_REG_FULL_BUFFER_THR 0x01045cUL
+#define MISC_REG_AEU_MASK_ATTN_MCP 0x008498UL
+#define MISC_REG_AEU_SYS_KILL_BEHAVIOR 0x008800UL
+#define MISC_REG_AEU_GENERAL_MASK 0x008828UL
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_PXP_CLOSE_MASK (0x1UL << 0)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_PXP_CLOSE_MASK_SHIFT 0
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_NIG_CLOSE_MASK (0x1UL << 1)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_NIG_CLOSE_MASK_SHIFT 1
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_SYS_KILL_MASK (0x1UL << 2)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_SYS_KILL_MASK_SHIFT 2
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_GLB_UNC_ERR_MASK (0x1UL << 3)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_GLB_UNC_ERR_MASK_SHIFT 3
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 84d2d2c03..717b80839 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -7,7 +7,6 @@
 #include "qede_ethdev.h"
 #include <rte_string_fns.h>
 #include <rte_alarm.h>
-#include <rte_version.h>
 #include <rte_kvargs.h>
 
 /* Globals */
diff --git a/drivers/net/qede/qede_main.c b/drivers/net/qede/qede_main.c
index 02f70beb3..51aa639c6 100644
--- a/drivers/net/qede/qede_main.c
+++ b/drivers/net/qede/qede_main.c
@@ -5,7 +5,6 @@
  */
 
 #include <limits.h>
-#include <time.h>
 #include <rte_alarm.h>
 #include <rte_string_fns.h>
 
@@ -66,7 +65,7 @@ qed_probe(struct ecore_dev *edev, struct rte_pci_device *pci_dev,
 	hw_prepare_params.initiate_pf_flr = true;
 	hw_prepare_params.allow_mdump = false;
 	hw_prepare_params.b_en_pacing = false;
-	hw_prepare_params.epoch = (u32)time(NULL);
+	hw_prepare_params.epoch = OSAL_GET_EPOCH(ECORE_LEADING_HWFN(edev));
 	rc = ecore_hw_prepare(edev, &hw_prepare_params);
 	if (rc) {
 		DP_ERR(edev, "hw prepare failed\n");
-- 
2.18.0


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

* [dpdk-dev] [PATCH v2 3/4] net/qede: add infrastructure for debug data collection
  2020-06-28  5:58 [dpdk-dev] [PATCH 0/4] net/qede: add FW debug data collection support Rasesh Mody
                   ` (6 preceding siblings ...)
  2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 2/4] net/qede/base: add changes for debug data collection Rasesh Mody
@ 2020-06-30  8:32 ` Rasesh Mody
  2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 4/4] net/qede: add support for get register operation Rasesh Mody
  8 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-06-30  8:32 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

The patch adds QEDE PMD ops and APIs to calculate the size and collect
the debug dump for various firmware components. The patch adds new files
qede_debug.[ch] that has all the firmware debug data collection
infrastructure changes.

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/qede/Makefile        |    4 +-
 drivers/net/qede/base/bcm_osal.h |    5 +-
 drivers/net/qede/qede_debug.c    | 8120 ++++++++++++++++++++++++++++++
 drivers/net/qede/qede_debug.h    |  759 +++
 drivers/net/qede/qede_if.h       |   45 +
 drivers/net/qede/qede_main.c     |   39 +-
 6 files changed, 8968 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/qede/qede_debug.c
 create mode 100644 drivers/net/qede/qede_debug.h

diff --git a/drivers/net/qede/Makefile b/drivers/net/qede/Makefile
index 5810b4d49..3b00338ff 100644
--- a/drivers/net/qede/Makefile
+++ b/drivers/net/qede/Makefile
@@ -11,7 +11,6 @@ include $(RTE_SDK)/mk/rte.vars.mk
 LIB = librte_pmd_qede.a
 
 CFLAGS += -O3
-CFLAGS += $(WERROR_FLAGS)
 LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
 LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs
 LDLIBS += -lrte_bus_pci
@@ -37,7 +36,6 @@ CFLAGS_BASE_DRIVER += -Wno-missing-prototypes
 
 ifneq ($(CONFIG_RTE_TOOLCHAIN_ICC),y)
 CFLAGS_BASE_DRIVER += -Wno-unused-value
-CFLAGS_BASE_DRIVER += -Wno-format-nonliteral
 ifeq ($(OS_TYPE),Linux)
 ifeq ($(shell clang -Wno-shift-negative-value -Werror -E - < /dev/null > /dev/null 2>&1; echo $$?),0)
 CFLAGS_BASE_DRIVER += -Wno-shift-negative-value
@@ -48,6 +46,7 @@ endif
 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
 ifeq ($(shell test $(GCC_VERSION) -ge 44 && echo 1), 1)
 CFLAGS_BASE_DRIVER += -Wno-unused-but-set-variable
+CFLAGS += -Wno-format-nonliteral
 endif
 CFLAGS_BASE_DRIVER += -Wno-missing-declarations
 ifeq ($(shell test $(GCC_VERSION) -ge 46 && echo 1), 1)
@@ -104,5 +103,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_ethdev.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_main.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_rxtx.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_filter.c
+SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_debug.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index 6ea3e7dda..b4b94231b 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -457,7 +457,10 @@ void qed_set_platform_str(struct ecore_hwfn *p_hwfn,
 #define OSAL_SET_PLATFORM_STR(p_hwfn, buf_str, buf_size) \
 	qed_set_platform_str(p_hwfn, buf_str, buf_size)
 #define OSAL_GET_EPOCH(p_hwfn) ((u32)time(NULL))
-#define OSAL_DBG_ALLOC_USER_DATA(p_hwfn, user_data_ptr) (0)
+enum dbg_status	qed_dbg_alloc_user_data(struct ecore_hwfn *p_hwfn,
+					void **user_data_ptr);
+#define OSAL_DBG_ALLOC_USER_DATA(p_hwfn, user_data_ptr) \
+	qed_dbg_alloc_user_data(p_hwfn, user_data_ptr)
 #define OSAL_DB_REC_OCCURRED(p_hwfn) nothing
 
 #endif /* __BCM_OSAL_H */
diff --git a/drivers/net/qede/qede_debug.c b/drivers/net/qede/qede_debug.c
new file mode 100644
index 000000000..d02cde5c4
--- /dev/null
+++ b/drivers/net/qede/qede_debug.c
@@ -0,0 +1,8120 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Marvell Semiconductor Inc.
+ * All rights reserved.
+ * www.marvell.com
+ */
+
+#include <rte_common.h>
+#include "base/bcm_osal.h"
+#include "base/ecore.h"
+#include "base/ecore_cxt.h"
+#include "base/ecore_hsi_common.h"
+#include "base/ecore_hw.h"
+#include "base/ecore_mcp.h"
+#include "base/reg_addr.h"
+#include "qede_debug.h"
+
+/* Memory groups enum */
+enum mem_groups {
+	MEM_GROUP_PXP_MEM,
+	MEM_GROUP_DMAE_MEM,
+	MEM_GROUP_CM_MEM,
+	MEM_GROUP_QM_MEM,
+	MEM_GROUP_DORQ_MEM,
+	MEM_GROUP_BRB_RAM,
+	MEM_GROUP_BRB_MEM,
+	MEM_GROUP_PRS_MEM,
+	MEM_GROUP_SDM_MEM,
+	MEM_GROUP_PBUF,
+	MEM_GROUP_IOR,
+	MEM_GROUP_RAM,
+	MEM_GROUP_BTB_RAM,
+	MEM_GROUP_RDIF_CTX,
+	MEM_GROUP_TDIF_CTX,
+	MEM_GROUP_CFC_MEM,
+	MEM_GROUP_CONN_CFC_MEM,
+	MEM_GROUP_CAU_PI,
+	MEM_GROUP_CAU_MEM,
+	MEM_GROUP_CAU_MEM_EXT,
+	MEM_GROUP_PXP_ILT,
+	MEM_GROUP_MULD_MEM,
+	MEM_GROUP_BTB_MEM,
+	MEM_GROUP_IGU_MEM,
+	MEM_GROUP_IGU_MSIX,
+	MEM_GROUP_CAU_SB,
+	MEM_GROUP_BMB_RAM,
+	MEM_GROUP_BMB_MEM,
+	MEM_GROUP_TM_MEM,
+	MEM_GROUP_TASK_CFC_MEM,
+	MEM_GROUPS_NUM
+};
+
+/* Memory groups names */
+static const char * const s_mem_group_names[] = {
+	"PXP_MEM",
+	"DMAE_MEM",
+	"CM_MEM",
+	"QM_MEM",
+	"DORQ_MEM",
+	"BRB_RAM",
+	"BRB_MEM",
+	"PRS_MEM",
+	"SDM_MEM",
+	"PBUF",
+	"IOR",
+	"RAM",
+	"BTB_RAM",
+	"RDIF_CTX",
+	"TDIF_CTX",
+	"CFC_MEM",
+	"CONN_CFC_MEM",
+	"CAU_PI",
+	"CAU_MEM",
+	"CAU_MEM_EXT",
+	"PXP_ILT",
+	"MULD_MEM",
+	"BTB_MEM",
+	"IGU_MEM",
+	"IGU_MSIX",
+	"CAU_SB",
+	"BMB_RAM",
+	"BMB_MEM",
+	"TM_MEM",
+	"TASK_CFC_MEM",
+};
+
+/* Idle check conditions */
+
+static u32 cond5(const u32 *r, const u32 *imm)
+{
+	return ((r[0] & imm[0]) != imm[1]) && ((r[1] & imm[2]) != imm[3]);
+}
+
+static u32 cond7(const u32 *r, const u32 *imm)
+{
+	return ((r[0] >> imm[0]) & imm[1]) != imm[2];
+}
+
+static u32 cond6(const u32 *r, const u32 *imm)
+{
+	return (r[0] & imm[0]) != imm[1];
+}
+
+static u32 cond9(const u32 *r, const u32 *imm)
+{
+	return ((r[0] & imm[0]) >> imm[1]) !=
+		(((r[0] & imm[2]) >> imm[3]) | ((r[1] & imm[4]) << imm[5]));
+}
+
+static u32 cond10(const u32 *r, const u32 *imm)
+{
+	return ((r[0] & imm[0]) >> imm[1]) != (r[0] & imm[2]);
+}
+
+static u32 cond4(const u32 *r, const u32 *imm)
+{
+	return (r[0] & ~imm[0]) != imm[1];
+}
+
+static u32 cond0(const u32 *r, const u32 *imm)
+{
+	return (r[0] & ~r[1]) != imm[0];
+}
+
+static u32 cond1(const u32 *r, const u32 *imm)
+{
+	return r[0] != imm[0];
+}
+
+static u32 cond11(const u32 *r, const u32 *imm)
+{
+	return r[0] != r[1] && r[2] == imm[0];
+}
+
+static u32 cond12(const u32 *r, const u32 *imm)
+{
+	return r[0] != r[1] && r[2] > imm[0];
+}
+
+static u32 cond3(const u32 *r, const __rte_unused u32 *imm)
+{
+	return r[0] != r[1];
+}
+
+static u32 cond13(const u32 *r, const u32 *imm)
+{
+	return r[0] & imm[0];
+}
+
+static u32 cond8(const u32 *r, const u32 *imm)
+{
+	return r[0] < (r[1] - imm[0]);
+}
+
+static u32 cond2(const u32 *r, const u32 *imm)
+{
+	return r[0] > imm[0];
+}
+
+/* Array of Idle Check conditions */
+static u32(*cond_arr[]) (const u32 *r, const u32 *imm) = {
+	cond0,
+	cond1,
+	cond2,
+	cond3,
+	cond4,
+	cond5,
+	cond6,
+	cond7,
+	cond8,
+	cond9,
+	cond10,
+	cond11,
+	cond12,
+	cond13,
+};
+
+#define NUM_PHYS_BLOCKS 84
+
+#define NUM_DBG_RESET_REGS 8
+
+/******************************* Data Types **********************************/
+
+enum hw_types {
+	HW_TYPE_ASIC,
+	PLATFORM_RESERVED,
+	PLATFORM_RESERVED2,
+	PLATFORM_RESERVED3,
+	PLATFORM_RESERVED4,
+	MAX_HW_TYPES
+};
+
+/* CM context types */
+enum cm_ctx_types {
+	CM_CTX_CONN_AG,
+	CM_CTX_CONN_ST,
+	CM_CTX_TASK_AG,
+	CM_CTX_TASK_ST,
+	NUM_CM_CTX_TYPES
+};
+
+/* Debug bus frame modes */
+enum dbg_bus_frame_modes {
+	DBG_BUS_FRAME_MODE_4ST = 0,	/* 4 Storm dwords (no HW) */
+	DBG_BUS_FRAME_MODE_2ST_2HW = 1,	/* 2 Storm dwords, 2 HW dwords */
+	DBG_BUS_FRAME_MODE_1ST_3HW = 2,	/* 1 Storm dwords, 3 HW dwords */
+	DBG_BUS_FRAME_MODE_4HW = 3,	/* 4 HW dwords (no Storms) */
+	DBG_BUS_FRAME_MODE_8HW = 4,	/* 8 HW dwords (no Storms) */
+	DBG_BUS_NUM_FRAME_MODES
+};
+
+/* Chip constant definitions */
+struct chip_defs {
+	const char *name;
+	u32 num_ilt_pages;
+};
+
+/* HW type constant definitions */
+struct hw_type_defs {
+	const char *name;
+	u32 delay_factor;
+	u32 dmae_thresh;
+	u32 log_thresh;
+};
+
+/* RBC reset definitions */
+struct rbc_reset_defs {
+	u32 reset_reg_addr;
+	u32 reset_val[MAX_CHIP_IDS];
+};
+
+/* Storm constant definitions.
+ * Addresses are in bytes, sizes are in quad-regs.
+ */
+struct storm_defs {
+	char letter;
+	enum block_id sem_block_id;
+	enum dbg_bus_clients dbg_client_id[MAX_CHIP_IDS];
+	bool has_vfc;
+	u32 sem_fast_mem_addr;
+	u32 sem_frame_mode_addr;
+	u32 sem_slow_enable_addr;
+	u32 sem_slow_mode_addr;
+	u32 sem_slow_mode1_conf_addr;
+	u32 sem_sync_dbg_empty_addr;
+	u32 sem_gpre_vect_addr;
+	u32 cm_ctx_wr_addr;
+	u32 cm_ctx_rd_addr[NUM_CM_CTX_TYPES];
+	u32 cm_ctx_lid_sizes[MAX_CHIP_IDS][NUM_CM_CTX_TYPES];
+};
+
+/* Debug Bus Constraint operation constant definitions */
+struct dbg_bus_constraint_op_defs {
+	u8 hw_op_val;
+	bool is_cyclic;
+};
+
+/* Storm Mode definitions */
+struct storm_mode_defs {
+	const char *name;
+	bool is_fast_dbg;
+	u8 id_in_hw;
+	u32 src_disable_reg_addr;
+	u32 src_enable_val;
+	bool exists[MAX_CHIP_IDS];
+};
+
+struct grc_param_defs {
+	u32 default_val[MAX_CHIP_IDS];
+	u32 min;
+	u32 max;
+	bool is_preset;
+	bool is_persistent;
+	u32 exclude_all_preset_val;
+	u32 crash_preset_val[MAX_CHIP_IDS];
+};
+
+/* Address is in 128b units. Width is in bits. */
+struct rss_mem_defs {
+	const char *mem_name;
+	const char *type_name;
+	u32 addr;
+	u32 entry_width;
+	u32 num_entries[MAX_CHIP_IDS];
+};
+
+struct vfc_ram_defs {
+	const char *mem_name;
+	const char *type_name;
+	u32 base_row;
+	u32 num_rows;
+};
+
+struct big_ram_defs {
+	const char *instance_name;
+	enum mem_groups mem_group_id;
+	enum mem_groups ram_mem_group_id;
+	enum dbg_grc_params grc_param;
+	u32 addr_reg_addr;
+	u32 data_reg_addr;
+	u32 is_256b_reg_addr;
+	u32 is_256b_bit_offset[MAX_CHIP_IDS];
+	u32 ram_size[MAX_CHIP_IDS]; /* In dwords */
+};
+
+struct phy_defs {
+	const char *phy_name;
+
+	/* PHY base GRC address */
+	u32 base_addr;
+
+	/* Relative address of indirect TBUS address register (bits 0..7) */
+	u32 tbus_addr_lo_addr;
+
+	/* Relative address of indirect TBUS address register (bits 8..10) */
+	u32 tbus_addr_hi_addr;
+
+	/* Relative address of indirect TBUS data register (bits 0..7) */
+	u32 tbus_data_lo_addr;
+
+	/* Relative address of indirect TBUS data register (bits 8..11) */
+	u32 tbus_data_hi_addr;
+};
+
+/* Split type definitions */
+struct split_type_defs {
+	const char *name;
+};
+
+/******************************** Constants **********************************/
+
+#define BYTES_IN_DWORD			sizeof(u32)
+/* In the macros below, size and offset are specified in bits */
+#define CEIL_DWORDS(size)		DIV_ROUND_UP(size, 32)
+#define FIELD_BIT_OFFSET(type, field)	type ## _ ## field ## _ ## OFFSET
+#define FIELD_BIT_SIZE(type, field)	type ## _ ## field ## _ ## SIZE
+#define FIELD_DWORD_OFFSET(type, field) \
+	 (int)(FIELD_BIT_OFFSET(type, field) / 32)
+#define FIELD_DWORD_SHIFT(type, field)	(FIELD_BIT_OFFSET(type, field) % 32)
+#define FIELD_BIT_MASK(type, field) \
+	(((1 << FIELD_BIT_SIZE(type, field)) - 1) << \
+	 FIELD_DWORD_SHIFT(type, field))
+
+#define SET_VAR_FIELD(var, type, field, val) \
+	do { \
+		var[FIELD_DWORD_OFFSET(type, field)] &=	\
+		(~FIELD_BIT_MASK(type, field));	\
+		var[FIELD_DWORD_OFFSET(type, field)] |= \
+		(val) << FIELD_DWORD_SHIFT(type, field); \
+	} while (0)
+
+#define ARR_REG_WR(dev, ptt, addr, arr, arr_size) \
+	do { \
+		for (i = 0; i < (arr_size); i++) \
+			ecore_wr(dev, ptt, addr,	(arr)[i]); \
+	} while (0)
+
+#define DWORDS_TO_BYTES(dwords)		((dwords) * BYTES_IN_DWORD)
+#define BYTES_TO_DWORDS(bytes)		((bytes) / BYTES_IN_DWORD)
+
+/* extra lines include a signature line + optional latency events line */
+#define NUM_EXTRA_DBG_LINES(block) \
+	(GET_FIELD((block)->flags, DBG_BLOCK_CHIP_HAS_LATENCY_EVENTS) ? 2 : 1)
+#define NUM_DBG_LINES(block) \
+	((block)->num_of_dbg_bus_lines + NUM_EXTRA_DBG_LINES(block))
+
+#define USE_DMAE			true
+#define PROTECT_WIDE_BUS		true
+
+#define RAM_LINES_TO_DWORDS(lines)	((lines) * 2)
+#define RAM_LINES_TO_BYTES(lines) \
+	DWORDS_TO_BYTES(RAM_LINES_TO_DWORDS(lines))
+
+#define REG_DUMP_LEN_SHIFT		24
+#define MEM_DUMP_ENTRY_SIZE_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_dump_mem))
+
+#define IDLE_CHK_RULE_SIZE_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_rule))
+
+#define IDLE_CHK_RESULT_HDR_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_result_hdr))
+
+#define IDLE_CHK_RESULT_REG_HDR_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_result_reg_hdr))
+
+#define PAGE_MEM_DESC_SIZE_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct phys_mem_desc))
+
+#define IDLE_CHK_MAX_ENTRIES_SIZE	32
+
+/* The sizes and offsets below are specified in bits */
+#define VFC_CAM_CMD_STRUCT_SIZE		64
+#define VFC_CAM_CMD_ROW_OFFSET		48
+#define VFC_CAM_CMD_ROW_SIZE		9
+#define VFC_CAM_ADDR_STRUCT_SIZE	16
+#define VFC_CAM_ADDR_OP_OFFSET		0
+#define VFC_CAM_ADDR_OP_SIZE		4
+#define VFC_CAM_RESP_STRUCT_SIZE	256
+#define VFC_RAM_ADDR_STRUCT_SIZE	16
+#define VFC_RAM_ADDR_OP_OFFSET		0
+#define VFC_RAM_ADDR_OP_SIZE		2
+#define VFC_RAM_ADDR_ROW_OFFSET		2
+#define VFC_RAM_ADDR_ROW_SIZE		10
+#define VFC_RAM_RESP_STRUCT_SIZE	256
+
+#define VFC_CAM_CMD_DWORDS		CEIL_DWORDS(VFC_CAM_CMD_STRUCT_SIZE)
+#define VFC_CAM_ADDR_DWORDS		CEIL_DWORDS(VFC_CAM_ADDR_STRUCT_SIZE)
+#define VFC_CAM_RESP_DWORDS		CEIL_DWORDS(VFC_CAM_RESP_STRUCT_SIZE)
+#define VFC_RAM_CMD_DWORDS		VFC_CAM_CMD_DWORDS
+#define VFC_RAM_ADDR_DWORDS		CEIL_DWORDS(VFC_RAM_ADDR_STRUCT_SIZE)
+#define VFC_RAM_RESP_DWORDS		CEIL_DWORDS(VFC_RAM_RESP_STRUCT_SIZE)
+
+#define NUM_VFC_RAM_TYPES		4
+
+#define VFC_CAM_NUM_ROWS		512
+
+#define VFC_OPCODE_CAM_RD		14
+#define VFC_OPCODE_RAM_RD		0
+
+#define NUM_RSS_MEM_TYPES		5
+
+#define NUM_BIG_RAM_TYPES		3
+#define BIG_RAM_NAME_LEN		3
+
+#define NUM_PHY_TBUS_ADDRESSES		2048
+#define PHY_DUMP_SIZE_DWORDS		(NUM_PHY_TBUS_ADDRESSES / 2)
+
+#define RESET_REG_UNRESET_OFFSET	4
+
+#define STALL_DELAY_MS			500
+
+#define STATIC_DEBUG_LINE_DWORDS	9
+
+#define NUM_COMMON_GLOBAL_PARAMS	11
+
+#define MAX_RECURSION_DEPTH		10
+
+#define FW_IMG_MAIN			1
+
+#define REG_FIFO_ELEMENT_DWORDS		2
+#define REG_FIFO_DEPTH_ELEMENTS		32
+#define REG_FIFO_DEPTH_DWORDS \
+	(REG_FIFO_ELEMENT_DWORDS * REG_FIFO_DEPTH_ELEMENTS)
+
+#define IGU_FIFO_ELEMENT_DWORDS		4
+#define IGU_FIFO_DEPTH_ELEMENTS		64
+#define IGU_FIFO_DEPTH_DWORDS \
+	(IGU_FIFO_ELEMENT_DWORDS * IGU_FIFO_DEPTH_ELEMENTS)
+
+#define PROTECTION_OVERRIDE_ELEMENT_DWORDS	2
+#define PROTECTION_OVERRIDE_DEPTH_ELEMENTS	20
+#define PROTECTION_OVERRIDE_DEPTH_DWORDS \
+	(PROTECTION_OVERRIDE_DEPTH_ELEMENTS * \
+	 PROTECTION_OVERRIDE_ELEMENT_DWORDS)
+
+#define MCP_SPAD_TRACE_OFFSIZE_ADDR \
+	(MCP_REG_SCRATCH + \
+	 offsetof(struct static_init, sections[SPAD_SECTION_TRACE]))
+
+#define MAX_SW_PLTAFORM_STR_SIZE	64
+
+#define EMPTY_FW_VERSION_STR		"???_???_???_???"
+#define EMPTY_FW_IMAGE_STR		"???????????????"
+
+/***************************** Constant Arrays *******************************/
+
+/* Chip constant definitions array */
+static struct chip_defs s_chip_defs[MAX_CHIP_IDS] = {
+	{"bb", PSWRQ2_REG_ILT_MEMORY_SIZE_BB / 2},
+	{"ah", PSWRQ2_REG_ILT_MEMORY_SIZE_K2 / 2}
+};
+
+/* Storm constant definitions array */
+static struct storm_defs s_storm_defs[] = {
+	/* Tstorm */
+	{'T', BLOCK_TSEM,
+		{DBG_BUS_CLIENT_RBCT, DBG_BUS_CLIENT_RBCT},
+		true,
+		TSEM_REG_FAST_MEMORY,
+		TSEM_REG_DBG_FRAME_MODE, TSEM_REG_SLOW_DBG_ACTIVE,
+		TSEM_REG_SLOW_DBG_MODE, TSEM_REG_DBG_MODE1_CFG,
+		TSEM_REG_SYNC_DBG_EMPTY, TSEM_REG_DBG_GPRE_VECT,
+		TCM_REG_CTX_RBC_ACCS,
+		{TCM_REG_AGG_CON_CTX, TCM_REG_SM_CON_CTX, TCM_REG_AGG_TASK_CTX,
+		 TCM_REG_SM_TASK_CTX},
+		{{4, 16, 2, 4}, {4, 16, 2, 4} } /* {bb} {k2} */
+	},
+
+	/* Mstorm */
+	{'M', BLOCK_MSEM,
+		{DBG_BUS_CLIENT_RBCT, DBG_BUS_CLIENT_RBCM},
+		false,
+		MSEM_REG_FAST_MEMORY,
+		MSEM_REG_DBG_FRAME_MODE,
+		MSEM_REG_SLOW_DBG_ACTIVE,
+		MSEM_REG_SLOW_DBG_MODE,
+		MSEM_REG_DBG_MODE1_CFG,
+		MSEM_REG_SYNC_DBG_EMPTY,
+		MSEM_REG_DBG_GPRE_VECT,
+		MCM_REG_CTX_RBC_ACCS,
+		{MCM_REG_AGG_CON_CTX, MCM_REG_SM_CON_CTX, MCM_REG_AGG_TASK_CTX,
+		 MCM_REG_SM_TASK_CTX },
+		{{1, 10, 2, 7}, {1, 10, 2, 7} } /* {bb} {k2}*/
+	},
+
+	/* Ustorm */
+	{'U', BLOCK_USEM,
+		{DBG_BUS_CLIENT_RBCU, DBG_BUS_CLIENT_RBCU},
+		false,
+		USEM_REG_FAST_MEMORY,
+		USEM_REG_DBG_FRAME_MODE,
+		USEM_REG_SLOW_DBG_ACTIVE,
+		USEM_REG_SLOW_DBG_MODE,
+		USEM_REG_DBG_MODE1_CFG,
+		USEM_REG_SYNC_DBG_EMPTY,
+		USEM_REG_DBG_GPRE_VECT,
+		UCM_REG_CTX_RBC_ACCS,
+		{UCM_REG_AGG_CON_CTX, UCM_REG_SM_CON_CTX, UCM_REG_AGG_TASK_CTX,
+		 UCM_REG_SM_TASK_CTX},
+		{{2, 13, 3, 3}, {2, 13, 3, 3} } /* {bb} {k2} */
+	},
+
+	/* Xstorm */
+	{'X', BLOCK_XSEM,
+		{DBG_BUS_CLIENT_RBCX, DBG_BUS_CLIENT_RBCX},
+		false,
+		XSEM_REG_FAST_MEMORY,
+		XSEM_REG_DBG_FRAME_MODE,
+		XSEM_REG_SLOW_DBG_ACTIVE,
+		XSEM_REG_SLOW_DBG_MODE,
+		XSEM_REG_DBG_MODE1_CFG,
+		XSEM_REG_SYNC_DBG_EMPTY,
+		XSEM_REG_DBG_GPRE_VECT,
+		XCM_REG_CTX_RBC_ACCS,
+		{XCM_REG_AGG_CON_CTX, XCM_REG_SM_CON_CTX, 0, 0},
+		{{9, 15, 0, 0}, {9, 15,	0, 0} } /* {bb} {k2} */
+	},
+
+	/* Ystorm */
+	{'Y', BLOCK_YSEM,
+		{DBG_BUS_CLIENT_RBCX, DBG_BUS_CLIENT_RBCY},
+		false,
+		YSEM_REG_FAST_MEMORY,
+		YSEM_REG_DBG_FRAME_MODE,
+		YSEM_REG_SLOW_DBG_ACTIVE,
+		YSEM_REG_SLOW_DBG_MODE,
+		YSEM_REG_DBG_MODE1_CFG,
+		YSEM_REG_SYNC_DBG_EMPTY,
+		YSEM_REG_DBG_GPRE_VECT,
+		YCM_REG_CTX_RBC_ACCS,
+		{YCM_REG_AGG_CON_CTX, YCM_REG_SM_CON_CTX, YCM_REG_AGG_TASK_CTX,
+		 YCM_REG_SM_TASK_CTX},
+		{{2, 3, 2, 12}, {2, 3, 2, 12} } /* {bb} {k2} */
+	},
+
+	/* Pstorm */
+	{'P', BLOCK_PSEM,
+		{DBG_BUS_CLIENT_RBCS, DBG_BUS_CLIENT_RBCS},
+		true,
+		PSEM_REG_FAST_MEMORY,
+		PSEM_REG_DBG_FRAME_MODE,
+		PSEM_REG_SLOW_DBG_ACTIVE,
+		PSEM_REG_SLOW_DBG_MODE,
+		PSEM_REG_DBG_MODE1_CFG,
+		PSEM_REG_SYNC_DBG_EMPTY,
+		PSEM_REG_DBG_GPRE_VECT,
+		PCM_REG_CTX_RBC_ACCS,
+		{0, PCM_REG_SM_CON_CTX, 0, 0},
+		{{0, 10, 0, 0}, {0, 10, 0, 0} } /* {bb} {k2} */
+	},
+};
+
+static struct hw_type_defs s_hw_type_defs[] = {
+	/* HW_TYPE_ASIC */
+	{"asic", 1, 256, 32768},
+	{"reserved", 0, 0, 0},
+	{"reserved2", 0, 0, 0},
+	{"reserved3", 0, 0, 0}
+};
+
+static struct grc_param_defs s_grc_param_defs[] = {
+	/* DBG_GRC_PARAM_DUMP_TSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_MSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_USTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_XSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_YSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_REGS */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_RAM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PBUF */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_IOR */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_VFC */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_CM_CTX */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_ILT */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_RSS */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_CAU */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_QM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_MCP */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_DORQ */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_CFC */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_IGU */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_BRB */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_BTB */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_BMB */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_RESERVED1 */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_MULD */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PRS */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_DMAE */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_TM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_SDM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_DIF */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_STATIC */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_UNSTALL */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_RESERVED2 */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_MCP_TRACE_META_SIZE */
+	{{0, 0}, 1, 0xffffffff, false, true, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_EXCLUDE_ALL */
+	{{0, 0}, 0, 1, true, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_CRASH */
+	{{0, 0}, 0, 1, true, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_PARITY_SAFE */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_CM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PHY */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_NO_MCP */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_NO_FW_VER */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_RESERVED3 */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_MCP_HW_DUMP */
+	{{0, 1}, 0, 1, false, false, 0, {0, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_ILT_CDUC */
+	{{1, 1}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_ILT_CDUT */
+	{{1, 1}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_CAU_EXT */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} }
+};
+
+static struct rss_mem_defs s_rss_mem_defs[] = {
+	{"rss_mem_cid", "rss_cid", 0, 32,
+	 {256, 320} },
+
+	{"rss_mem_key_msb", "rss_key", 1024, 256,
+	 {128, 208} },
+
+	{"rss_mem_key_lsb", "rss_key", 2048, 64,
+	 {128, 208} },
+
+	{"rss_mem_info", "rss_info", 3072, 16,
+	 {128, 208} },
+
+	{"rss_mem_ind", "rss_ind", 4096, 16,
+	 {16384, 26624} }
+};
+
+static struct vfc_ram_defs s_vfc_ram_defs[] = {
+	{"vfc_ram_tt1", "vfc_ram", 0, 512},
+	{"vfc_ram_mtt2", "vfc_ram", 512, 128},
+	{"vfc_ram_stt2", "vfc_ram", 640, 32},
+	{"vfc_ram_ro_vect", "vfc_ram", 672, 32}
+};
+
+static struct big_ram_defs s_big_ram_defs[] = {
+	{"BRB", MEM_GROUP_BRB_MEM, MEM_GROUP_BRB_RAM, DBG_GRC_PARAM_DUMP_BRB,
+	 BRB_REG_BIG_RAM_ADDRESS, BRB_REG_BIG_RAM_DATA,
+	 MISC_REG_BLOCK_256B_EN, {0, 0},
+	 {153600, 180224} },
+
+	{"BTB", MEM_GROUP_BTB_MEM, MEM_GROUP_BTB_RAM, DBG_GRC_PARAM_DUMP_BTB,
+	 BTB_REG_BIG_RAM_ADDRESS, BTB_REG_BIG_RAM_DATA,
+	 MISC_REG_BLOCK_256B_EN, {0, 1},
+	 {92160, 117760} },
+
+	{"BMB", MEM_GROUP_BMB_MEM, MEM_GROUP_BMB_RAM, DBG_GRC_PARAM_DUMP_BMB,
+	 BMB_REG_BIG_RAM_ADDRESS, BMB_REG_BIG_RAM_DATA,
+	 MISCS_REG_BLOCK_256B_EN, {0, 0},
+	 {36864, 36864} }
+};
+
+static struct rbc_reset_defs s_rbc_reset_defs[] = {
+	{MISCS_REG_RESET_PL_HV,
+	 {0x0, 0x400} },
+	{MISC_REG_RESET_PL_PDA_VMAIN_1,
+	 {0x4404040, 0x4404040} },
+	{MISC_REG_RESET_PL_PDA_VMAIN_2,
+	 {0x7, 0x7c00007} },
+	{MISC_REG_RESET_PL_PDA_VAUX,
+	 {0x2, 0x2} },
+};
+
+static struct phy_defs s_phy_defs[] = {
+	{"nw_phy", NWS_REG_NWS_CMU_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_7_0_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_15_8_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_7_0_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_11_8_K2},
+	{"sgmii_phy", MS_REG_MS_CMU_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X132_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X133_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X130_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X131_K2},
+	{"pcie_phy0", PHY_PCIE_REG_PHY0_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2},
+	{"pcie_phy1", PHY_PCIE_REG_PHY1_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2},
+};
+
+static struct split_type_defs s_split_type_defs[] = {
+	/* SPLIT_TYPE_NONE */
+	{"eng"},
+
+	/* SPLIT_TYPE_PORT */
+	{"port"},
+
+	/* SPLIT_TYPE_PF */
+	{"pf"},
+
+	/* SPLIT_TYPE_PORT_PF */
+	{"port"},
+
+	/* SPLIT_TYPE_VF */
+	{"vf"}
+};
+
+/******************************** Variables *********************************/
+
+/**
+ * The version of the calling app
+ */
+static u32 s_app_ver;
+
+/**************************** Private Functions ******************************/
+
+/* Reads and returns a single dword from the specified unaligned buffer */
+static u32 qed_read_unaligned_dword(u8 *buf)
+{
+	u32 dword;
+
+	memcpy((u8 *)&dword, buf, sizeof(dword));
+	return dword;
+}
+
+/* Sets the value of the specified GRC param */
+static void qed_grc_set_param(struct ecore_hwfn *p_hwfn,
+			      enum dbg_grc_params grc_param, u32 val)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	dev_data->grc.param_val[grc_param] = val;
+}
+
+/* Returns the value of the specified GRC param */
+static u32 qed_grc_get_param(struct ecore_hwfn *p_hwfn,
+			     enum dbg_grc_params grc_param)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	return dev_data->grc.param_val[grc_param];
+}
+
+/* Initializes the GRC parameters */
+static void qed_dbg_grc_init_params(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	if (!dev_data->grc.params_initialized) {
+		qed_dbg_grc_set_params_default(p_hwfn);
+		dev_data->grc.params_initialized = 1;
+	}
+}
+
+/* Sets pointer and size for the specified binary buffer type */
+static void qed_set_dbg_bin_buf(struct ecore_hwfn *p_hwfn,
+				enum bin_dbg_buffer_type buf_type,
+				const u32 *ptr, u32 size)
+{
+	struct virt_mem_desc *buf = &p_hwfn->dbg_arrays[buf_type];
+
+	buf->ptr = (void *)(osal_uintptr_t)ptr;
+	buf->size = size;
+}
+
+/* Initializes debug data for the specified device */
+static enum dbg_status qed_dbg_dev_init(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 num_pfs = 0, max_pfs_per_port = 0;
+
+	if (dev_data->initialized)
+		return DBG_STATUS_OK;
+
+	/* Set chip */
+	if (ECORE_IS_K2(p_hwfn->p_dev)) {
+		dev_data->chip_id = CHIP_K2;
+		dev_data->mode_enable[MODE_K2] = 1;
+		dev_data->num_vfs = MAX_NUM_VFS_K2;
+		num_pfs = MAX_NUM_PFS_K2;
+		max_pfs_per_port = MAX_NUM_PFS_K2 / 2;
+	} else if (ECORE_IS_BB_B0(p_hwfn->p_dev)) {
+		dev_data->chip_id = CHIP_BB;
+		dev_data->mode_enable[MODE_BB] = 1;
+		dev_data->num_vfs = MAX_NUM_VFS_BB;
+		num_pfs = MAX_NUM_PFS_BB;
+		max_pfs_per_port = MAX_NUM_PFS_BB;
+	} else {
+		return DBG_STATUS_UNKNOWN_CHIP;
+	}
+
+	/* Set HW type */
+	dev_data->hw_type = HW_TYPE_ASIC;
+	dev_data->mode_enable[MODE_ASIC] = 1;
+
+	/* Set port mode */
+	switch (p_hwfn->p_dev->num_ports_in_engine) {
+	case 1:
+		dev_data->mode_enable[MODE_PORTS_PER_ENG_1] = 1;
+		break;
+	case 2:
+		dev_data->mode_enable[MODE_PORTS_PER_ENG_2] = 1;
+		break;
+	case 4:
+		dev_data->mode_enable[MODE_PORTS_PER_ENG_4] = 1;
+		break;
+	}
+
+	/* Set 100G mode */
+	if (ECORE_IS_CMT(p_hwfn->p_dev))
+		dev_data->mode_enable[MODE_100G] = 1;
+
+	/* Set number of ports */
+	if (dev_data->mode_enable[MODE_PORTS_PER_ENG_1] ||
+	    dev_data->mode_enable[MODE_100G])
+		dev_data->num_ports = 1;
+	else if (dev_data->mode_enable[MODE_PORTS_PER_ENG_2])
+		dev_data->num_ports = 2;
+	else if (dev_data->mode_enable[MODE_PORTS_PER_ENG_4])
+		dev_data->num_ports = 4;
+
+	/* Set number of PFs per port */
+	dev_data->num_pfs_per_port = OSAL_MIN_T(u32,
+						num_pfs / dev_data->num_ports,
+						max_pfs_per_port);
+
+	/* Initializes the GRC parameters */
+	qed_dbg_grc_init_params(p_hwfn);
+
+	dev_data->use_dmae = true;
+	dev_data->initialized = 1;
+
+	return DBG_STATUS_OK;
+}
+
+static const struct dbg_block *get_dbg_block(struct ecore_hwfn *p_hwfn,
+					     enum block_id block_id)
+{
+	const struct dbg_block *dbg_block;
+
+	dbg_block = p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS].ptr;
+	return dbg_block + block_id;
+}
+
+static const struct dbg_block_chip *qed_get_dbg_block_per_chip(struct ecore_hwfn
+							       *p_hwfn,
+							       enum block_id
+							       block_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	return (const struct dbg_block_chip *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS_CHIP_DATA].ptr +
+	    block_id * MAX_CHIP_IDS + dev_data->chip_id;
+}
+
+static const struct dbg_reset_reg *qed_get_dbg_reset_reg(struct ecore_hwfn
+							 *p_hwfn,
+							 u8 reset_reg_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	return (const struct dbg_reset_reg *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_RESET_REGS].ptr +
+	    reset_reg_id * MAX_CHIP_IDS + dev_data->chip_id;
+}
+
+/* Reads the FW info structure for the specified Storm from the chip,
+ * and writes it to the specified fw_info pointer.
+ */
+static void qed_read_storm_fw_info(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   u8 storm_id, struct fw_info *fw_info)
+{
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	struct fw_info_location fw_info_location;
+	u32 addr, i, *dest;
+
+	memset(&fw_info_location, 0, sizeof(fw_info_location));
+	memset(fw_info, 0, sizeof(*fw_info));
+
+	/* Read first the address that points to fw_info location.
+	 * The address is located in the last line of the Storm RAM.
+	 */
+	addr = storm->sem_fast_mem_addr + SEM_FAST_REG_INT_RAM +
+	    DWORDS_TO_BYTES(SEM_FAST_REG_INT_RAM_SIZE) -
+	    sizeof(fw_info_location);
+
+	dest = (u32 *)&fw_info_location;
+
+	for (i = 0; i < BYTES_TO_DWORDS(sizeof(fw_info_location));
+	     i++, addr += BYTES_IN_DWORD)
+		dest[i] = ecore_rd(p_hwfn, p_ptt, addr);
+
+	/* Read FW version info from Storm RAM */
+	if (fw_info_location.size > 0 && fw_info_location.size <=
+	    sizeof(*fw_info)) {
+		addr = fw_info_location.grc_addr;
+		dest = (u32 *)fw_info;
+		for (i = 0; i < BYTES_TO_DWORDS(fw_info_location.size);
+		     i++, addr += BYTES_IN_DWORD)
+			dest[i] = ecore_rd(p_hwfn, p_ptt, addr);
+	}
+}
+
+/* Dumps the specified string to the specified buffer.
+ * Returns the dumped size in bytes.
+ */
+static u32 qed_dump_str(char *dump_buf, bool dump, const char *str)
+{
+	if (dump)
+		strcpy(dump_buf, str);
+
+	return (u32)strlen(str) + 1;
+}
+
+/* Dumps zeros to align the specified buffer to dwords.
+ * Returns the dumped size in bytes.
+ */
+static u32 qed_dump_align(char *dump_buf, bool dump, u32 byte_offset)
+{
+	u8 offset_in_dword, align_size;
+
+	offset_in_dword = (u8)(byte_offset & 0x3);
+	align_size = offset_in_dword ? BYTES_IN_DWORD - offset_in_dword : 0;
+
+	if (dump && align_size)
+		memset(dump_buf, 0, align_size);
+
+	return align_size;
+}
+
+/* Writes the specified string param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_str_param(u32 *dump_buf,
+			      bool dump,
+			      const char *param_name, const char *param_val)
+{
+	char *char_buf = (char *)dump_buf;
+	u32 offset = 0;
+
+	/* Dump param name */
+	offset += qed_dump_str(char_buf + offset, dump, param_name);
+
+	/* Indicate a string param value */
+	if (dump)
+		*(char_buf + offset) = 1;
+	offset++;
+
+	/* Dump param value */
+	offset += qed_dump_str(char_buf + offset, dump, param_val);
+
+	/* Align buffer to next dword */
+	offset += qed_dump_align(char_buf + offset, dump, offset);
+
+	return BYTES_TO_DWORDS(offset);
+}
+
+/* Writes the specified numeric param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_num_param(u32 *dump_buf,
+			      bool dump, const char *param_name, u32 param_val)
+{
+	char *char_buf = (char *)dump_buf;
+	u32 offset = 0;
+
+	/* Dump param name */
+	offset += qed_dump_str(char_buf + offset, dump, param_name);
+
+	/* Indicate a numeric param value */
+	if (dump)
+		*(char_buf + offset) = 0;
+	offset++;
+
+	/* Align buffer to next dword */
+	offset += qed_dump_align(char_buf + offset, dump, offset);
+
+	/* Dump param value (and change offset from bytes to dwords) */
+	offset = BYTES_TO_DWORDS(offset);
+	if (dump)
+		*(dump_buf + offset) = param_val;
+	offset++;
+
+	return offset;
+}
+
+/* Reads the FW version and writes it as a param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_fw_ver_param(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf, bool dump)
+{
+	char fw_ver_str[16] = EMPTY_FW_VERSION_STR;
+	char fw_img_str[16] = EMPTY_FW_IMAGE_STR;
+	struct fw_info fw_info = { {0}, {0} };
+	u32 offset = 0;
+
+	if (dump && !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_FW_VER)) {
+		/* Read FW info from chip */
+		qed_read_fw_info(p_hwfn, p_ptt, &fw_info);
+
+		/* Create FW version/image strings */
+		if (snprintf(fw_ver_str, sizeof(fw_ver_str),
+			     "%d_%d_%d_%d", fw_info.ver.num.major,
+			     fw_info.ver.num.minor, fw_info.ver.num.rev,
+			     fw_info.ver.num.eng) < 0)
+			DP_NOTICE(p_hwfn, false,
+				  "Unexpected debug error: invalid FW version string\n");
+		switch (fw_info.ver.image_id) {
+		case FW_IMG_MAIN:
+			strcpy(fw_img_str, "main");
+			break;
+		default:
+			strcpy(fw_img_str, "unknown");
+			break;
+		}
+	}
+
+	/* Dump FW version, image and timestamp */
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "fw-version", fw_ver_str);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "fw-image", fw_img_str);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "fw-timestamp", fw_info.ver.timestamp);
+
+	return offset;
+}
+
+/* Reads the MFW version and writes it as a param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_mfw_ver_param(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  u32 *dump_buf, bool dump)
+{
+	char mfw_ver_str[16] = EMPTY_FW_VERSION_STR;
+
+	if (dump &&
+	    !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_FW_VER)) {
+		u32 global_section_offsize, global_section_addr, mfw_ver;
+		u32 public_data_addr, global_section_offsize_addr;
+
+		/* Find MCP public data GRC address. Needs to be ORed with
+		 * MCP_REG_SCRATCH due to a HW bug.
+		 */
+		public_data_addr = ecore_rd(p_hwfn,
+					  p_ptt,
+					  MISC_REG_SHARED_MEM_ADDR) |
+				   MCP_REG_SCRATCH;
+
+		/* Find MCP public global section offset */
+		global_section_offsize_addr = public_data_addr +
+					      offsetof(struct mcp_public_data,
+						       sections) +
+					      sizeof(offsize_t) * PUBLIC_GLOBAL;
+		global_section_offsize = ecore_rd(p_hwfn, p_ptt,
+						global_section_offsize_addr);
+		global_section_addr =
+			MCP_REG_SCRATCH +
+			(global_section_offsize & OFFSIZE_OFFSET_MASK) * 4;
+
+		/* Read MFW version from MCP public global section */
+		mfw_ver = ecore_rd(p_hwfn, p_ptt,
+				 global_section_addr +
+				 offsetof(struct public_global, mfw_ver));
+
+		/* Dump MFW version param */
+		if (snprintf(mfw_ver_str, sizeof(mfw_ver_str), "%d_%d_%d_%d",
+			     (u8)(mfw_ver >> 24), (u8)(mfw_ver >> 16),
+			     (u8)(mfw_ver >> 8), (u8)mfw_ver) < 0)
+			DP_NOTICE(p_hwfn, false,
+				  "Unexpected debug error: invalid MFW version string\n");
+	}
+
+	return qed_dump_str_param(dump_buf, dump, "mfw-version", mfw_ver_str);
+}
+
+/* Reads the chip revision from the chip and writes it as a param to the
+ * specified buffer. Returns the dumped size in dwords.
+ */
+static u32 qed_dump_chip_revision_param(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	char param_str[3] = "??";
+
+	if (dev_data->hw_type == HW_TYPE_ASIC) {
+		u32 chip_rev, chip_metal;
+
+		chip_rev = ecore_rd(p_hwfn, p_ptt, MISCS_REG_CHIP_REV);
+		chip_metal = ecore_rd(p_hwfn, p_ptt, MISCS_REG_CHIP_METAL);
+
+		param_str[0] = 'a' + (u8)chip_rev;
+		param_str[1] = '0' + (u8)chip_metal;
+	}
+
+	return qed_dump_str_param(dump_buf, dump, "chip-revision", param_str);
+}
+
+/* Writes a section header to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_section_hdr(u32 *dump_buf,
+				bool dump, const char *name, u32 num_params)
+{
+	return qed_dump_num_param(dump_buf, dump, name, num_params);
+}
+
+/* Writes the common global params to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_common_global_params(struct ecore_hwfn *p_hwfn,
+					 struct ecore_ptt *p_ptt,
+					 u32 *dump_buf,
+					 bool dump,
+					 u8 num_specific_global_params)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	char sw_platform_str[MAX_SW_PLTAFORM_STR_SIZE];
+	u32 offset = 0;
+	u8 num_params;
+
+	/* Fill platform string */
+	ecore_set_platform_str(p_hwfn, sw_platform_str,
+			       MAX_SW_PLTAFORM_STR_SIZE);
+
+	/* Dump global params section header */
+	num_params = NUM_COMMON_GLOBAL_PARAMS + num_specific_global_params +
+		(dev_data->chip_id == CHIP_BB ? 1 : 0);
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "global_params", num_params);
+
+	/* Store params */
+	offset += qed_dump_fw_ver_param(p_hwfn, p_ptt, dump_buf + offset, dump);
+	offset += qed_dump_mfw_ver_param(p_hwfn,
+					 p_ptt, dump_buf + offset, dump);
+	offset += qed_dump_chip_revision_param(p_hwfn,
+					       p_ptt, dump_buf + offset, dump);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "tools-version", TOOLS_VERSION);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump,
+				     "chip",
+				     s_chip_defs[dev_data->chip_id].name);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump,
+				     "platform",
+				     s_hw_type_defs[dev_data->hw_type].name);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "sw-platform", sw_platform_str);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "pci-func", p_hwfn->abs_pf_id);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "epoch", OSAL_GET_EPOCH(p_hwfn));
+	if (dev_data->chip_id == CHIP_BB)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "path",
+					     ECORE_PATH_ID(p_hwfn));
+
+	return offset;
+}
+
+/* Writes the "last" section (including CRC) to the specified buffer at the
+ * given offset. Returns the dumped size in dwords.
+ */
+static u32 qed_dump_last_section(u32 *dump_buf, u32 offset, bool dump)
+{
+	u32 start_offset = offset;
+
+	/* Dump CRC section header */
+	offset += qed_dump_section_hdr(dump_buf + offset, dump, "last", 0);
+
+	/* Calculate CRC32 and add it to the dword after the "last" section */
+	if (dump)
+		*(dump_buf + offset) = ~OSAL_CRC32(0xffffffff,
+					      (u8 *)dump_buf,
+					      DWORDS_TO_BYTES(offset));
+
+	offset++;
+
+	return offset - start_offset;
+}
+
+/* Update blocks reset state  */
+static void qed_update_blocks_reset_state(struct ecore_hwfn *p_hwfn,
+					  struct ecore_ptt *p_ptt)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 reg_val[NUM_DBG_RESET_REGS] = { 0 };
+	u8 rst_reg_id;
+	u32 blk_id;
+
+	/* Read reset registers */
+	for (rst_reg_id = 0; rst_reg_id < NUM_DBG_RESET_REGS; rst_reg_id++) {
+		const struct dbg_reset_reg *rst_reg;
+		bool rst_reg_removed;
+		u32 rst_reg_addr;
+
+		rst_reg = qed_get_dbg_reset_reg(p_hwfn, rst_reg_id);
+		rst_reg_removed = GET_FIELD(rst_reg->data,
+					    DBG_RESET_REG_IS_REMOVED);
+		rst_reg_addr = DWORDS_TO_BYTES(GET_FIELD(rst_reg->data,
+							 DBG_RESET_REG_ADDR));
+
+		if (!rst_reg_removed)
+			reg_val[rst_reg_id] = ecore_rd(p_hwfn, p_ptt,
+						     rst_reg_addr);
+	}
+
+	/* Check if blocks are in reset */
+	for (blk_id = 0; blk_id < NUM_PHYS_BLOCKS; blk_id++) {
+		const struct dbg_block_chip *blk;
+		bool has_rst_reg;
+		bool is_removed;
+
+		blk = qed_get_dbg_block_per_chip(p_hwfn, (enum block_id)blk_id);
+		is_removed = GET_FIELD(blk->flags, DBG_BLOCK_CHIP_IS_REMOVED);
+		has_rst_reg = GET_FIELD(blk->flags,
+					DBG_BLOCK_CHIP_HAS_RESET_REG);
+
+		if (!is_removed && has_rst_reg)
+			dev_data->block_in_reset[blk_id] =
+			    !(reg_val[blk->reset_reg_id] &
+			      OSAL_BIT(blk->reset_reg_bit_offset));
+	}
+}
+
+/* is_mode_match recursive function */
+static bool qed_is_mode_match_rec(struct ecore_hwfn *p_hwfn,
+				  u16 *modes_buf_offset, u8 rec_depth)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	const u8 *dbg_array;
+	bool arg1, arg2;
+	u8 tree_val;
+
+	if (rec_depth > MAX_RECURSION_DEPTH) {
+		DP_NOTICE(p_hwfn, false,
+			  "Unexpected error: is_mode_match_rec exceeded the max recursion depth. This is probably due to a corrupt init/debug buffer.\n");
+		return false;
+	}
+
+	/* Get next element from modes tree buffer */
+	dbg_array = p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr;
+	tree_val = dbg_array[(*modes_buf_offset)++];
+
+	switch (tree_val) {
+	case INIT_MODE_OP_NOT:
+		return !qed_is_mode_match_rec(p_hwfn,
+					      modes_buf_offset, rec_depth + 1);
+	case INIT_MODE_OP_OR:
+	case INIT_MODE_OP_AND:
+		arg1 = qed_is_mode_match_rec(p_hwfn,
+					     modes_buf_offset, rec_depth + 1);
+		arg2 = qed_is_mode_match_rec(p_hwfn,
+					     modes_buf_offset, rec_depth + 1);
+		return (tree_val == INIT_MODE_OP_OR) ? (arg1 ||
+							arg2) : (arg1 && arg2);
+	default:
+		return dev_data->mode_enable[tree_val - MAX_INIT_MODE_OPS] > 0;
+	}
+}
+
+/* Returns true if the mode (specified using modes_buf_offset) is enabled */
+static bool qed_is_mode_match(struct ecore_hwfn *p_hwfn, u16 *modes_buf_offset)
+{
+	return qed_is_mode_match_rec(p_hwfn, modes_buf_offset, 0);
+}
+
+/* Enable / disable the Debug block */
+static void qed_bus_enable_dbg_block(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt, bool enable)
+{
+	ecore_wr(p_hwfn, p_ptt, DBG_REG_DBG_BLOCK_ON, enable ? 1 : 0);
+}
+
+/* Resets the Debug block */
+static void qed_bus_reset_dbg_block(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt)
+{
+	u32 reset_reg_addr, old_reset_reg_val, new_reset_reg_val;
+	const struct dbg_reset_reg *reset_reg;
+	const struct dbg_block_chip *block;
+
+	block = qed_get_dbg_block_per_chip(p_hwfn, BLOCK_DBG);
+	reset_reg = qed_get_dbg_reset_reg(p_hwfn, block->reset_reg_id);
+	reset_reg_addr =
+	    DWORDS_TO_BYTES(GET_FIELD(reset_reg->data, DBG_RESET_REG_ADDR));
+
+	old_reset_reg_val = ecore_rd(p_hwfn, p_ptt, reset_reg_addr);
+	new_reset_reg_val =
+	    old_reset_reg_val & ~OSAL_BIT(block->reset_reg_bit_offset);
+
+	ecore_wr(p_hwfn, p_ptt, reset_reg_addr, new_reset_reg_val);
+	ecore_wr(p_hwfn, p_ptt, reset_reg_addr, old_reset_reg_val);
+}
+
+/* Enable / disable Debug Bus clients according to the specified mask
+ * (1 = enable, 0 = disable).
+ */
+static void qed_bus_enable_clients(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt, u32 client_mask)
+{
+	ecore_wr(p_hwfn, p_ptt, DBG_REG_CLIENT_ENABLE, client_mask);
+}
+
+static void qed_bus_config_dbg_line(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    enum block_id block_id,
+				    u8 line_id,
+				    u8 enable_mask,
+				    u8 right_shift,
+				    u8 force_valid_mask, u8 force_frame_mask)
+{
+	const struct dbg_block_chip *block =
+		qed_get_dbg_block_per_chip(p_hwfn, block_id);
+
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_select_reg_addr),
+		 line_id);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_dword_enable_reg_addr),
+		 enable_mask);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_shift_reg_addr),
+		 right_shift);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_force_valid_reg_addr),
+		 force_valid_mask);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_force_frame_reg_addr),
+		 force_frame_mask);
+}
+
+/* Disable debug bus in all blocks */
+static void qed_bus_disable_blocks(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_id;
+
+	/* Disable all blocks */
+	for (block_id = 0; block_id < MAX_BLOCK_ID; block_id++) {
+		const struct dbg_block_chip *block_per_chip =
+		    qed_get_dbg_block_per_chip(p_hwfn,
+					       (enum block_id)block_id);
+
+		if (GET_FIELD(block_per_chip->flags,
+			      DBG_BLOCK_CHIP_IS_REMOVED) ||
+		    dev_data->block_in_reset[block_id])
+			continue;
+
+		/* Disable debug bus */
+		if (GET_FIELD(block_per_chip->flags,
+			      DBG_BLOCK_CHIP_HAS_DBG_BUS)) {
+			u32 dbg_en_addr =
+				block_per_chip->dbg_dword_enable_reg_addr;
+			u16 modes_buf_offset =
+			    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+				      DBG_MODE_HDR_MODES_BUF_OFFSET);
+			bool eval_mode =
+			    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+
+			if (!eval_mode ||
+			    qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				ecore_wr(p_hwfn, p_ptt,
+				       DWORDS_TO_BYTES(dbg_en_addr),
+				       0);
+		}
+	}
+}
+
+/* Returns true if the specified entity (indicated by GRC param) should be
+ * included in the dump, false otherwise.
+ */
+static bool qed_grc_is_included(struct ecore_hwfn *p_hwfn,
+				enum dbg_grc_params grc_param)
+{
+	return qed_grc_get_param(p_hwfn, grc_param) > 0;
+}
+
+/* Returns the storm_id that matches the specified Storm letter,
+ * or MAX_DBG_STORMS if invalid storm letter.
+ */
+static enum dbg_storms qed_get_id_from_letter(char storm_letter)
+{
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++)
+		if (s_storm_defs[storm_id].letter == storm_letter)
+			return (enum dbg_storms)storm_id;
+
+	return MAX_DBG_STORMS;
+}
+
+/* Returns true of the specified Storm should be included in the dump, false
+ * otherwise.
+ */
+static bool qed_grc_is_storm_included(struct ecore_hwfn *p_hwfn,
+				      enum dbg_storms storm)
+{
+	return qed_grc_get_param(p_hwfn, (enum dbg_grc_params)storm) > 0;
+}
+
+/* Returns true if the specified memory should be included in the dump, false
+ * otherwise.
+ */
+static bool qed_grc_is_mem_included(struct ecore_hwfn *p_hwfn,
+				    enum block_id block_id, u8 mem_group_id)
+{
+	const struct dbg_block *block;
+	u8 i;
+
+	block = get_dbg_block(p_hwfn, block_id);
+
+	/* If the block is associated with a Storm, check Storm match */
+	if (block->associated_storm_letter) {
+		enum dbg_storms associated_storm_id =
+		    qed_get_id_from_letter(block->associated_storm_letter);
+
+		if (associated_storm_id == MAX_DBG_STORMS ||
+		    !qed_grc_is_storm_included(p_hwfn, associated_storm_id))
+			return false;
+	}
+
+	for (i = 0; i < NUM_BIG_RAM_TYPES; i++) {
+		struct big_ram_defs *big_ram = &s_big_ram_defs[i];
+
+		if (mem_group_id == big_ram->mem_group_id ||
+		    mem_group_id == big_ram->ram_mem_group_id)
+			return qed_grc_is_included(p_hwfn, big_ram->grc_param);
+	}
+
+	switch (mem_group_id) {
+	case MEM_GROUP_PXP_ILT:
+	case MEM_GROUP_PXP_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PXP);
+	case MEM_GROUP_RAM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_RAM);
+	case MEM_GROUP_PBUF:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PBUF);
+	case MEM_GROUP_CAU_MEM:
+	case MEM_GROUP_CAU_SB:
+	case MEM_GROUP_CAU_PI:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CAU);
+	case MEM_GROUP_CAU_MEM_EXT:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CAU_EXT);
+	case MEM_GROUP_QM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_QM);
+	case MEM_GROUP_CFC_MEM:
+	case MEM_GROUP_CONN_CFC_MEM:
+	case MEM_GROUP_TASK_CFC_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CFC) ||
+		       qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM_CTX);
+	case MEM_GROUP_DORQ_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DORQ);
+	case MEM_GROUP_IGU_MEM:
+	case MEM_GROUP_IGU_MSIX:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_IGU);
+	case MEM_GROUP_MULD_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MULD);
+	case MEM_GROUP_PRS_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PRS);
+	case MEM_GROUP_DMAE_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DMAE);
+	case MEM_GROUP_TM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_TM);
+	case MEM_GROUP_SDM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_SDM);
+	case MEM_GROUP_TDIF_CTX:
+	case MEM_GROUP_RDIF_CTX:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DIF);
+	case MEM_GROUP_CM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM);
+	case MEM_GROUP_IOR:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_IOR);
+	default:
+		return true;
+	}
+}
+
+/* Stalls all Storms */
+static void qed_grc_stall_storms(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt, bool stall)
+{
+	u32 reg_addr;
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		if (!qed_grc_is_storm_included(p_hwfn,
+					       (enum dbg_storms)storm_id))
+			continue;
+
+		reg_addr = s_storm_defs[storm_id].sem_fast_mem_addr +
+		    SEM_FAST_REG_STALL_0;
+		ecore_wr(p_hwfn, p_ptt, reg_addr, stall ? 1 : 0);
+	}
+
+	OSAL_MSLEEP(STALL_DELAY_MS);
+}
+
+/* Takes all blocks out of reset. If rbc_only is true, only RBC clients are
+ * taken out of reset.
+ */
+static void qed_grc_unreset_blocks(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt, bool rbc_only)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 chip_id = dev_data->chip_id;
+	u32 i;
+
+	/* Take RBCs out of reset */
+	for (i = 0; i < OSAL_ARRAY_SIZE(s_rbc_reset_defs); i++)
+		if (s_rbc_reset_defs[i].reset_val[dev_data->chip_id])
+			ecore_wr(p_hwfn,
+			       p_ptt,
+			       s_rbc_reset_defs[i].reset_reg_addr +
+			       RESET_REG_UNRESET_OFFSET,
+			       s_rbc_reset_defs[i].reset_val[chip_id]);
+
+	if (!rbc_only) {
+		u32 reg_val[NUM_DBG_RESET_REGS] = { 0 };
+		u8 reset_reg_id;
+		u32 block_id;
+
+		/* Fill reset regs values */
+		for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
+			bool is_removed, has_reset_reg, unreset_before_dump;
+			const struct dbg_block_chip *block;
+
+			block = qed_get_dbg_block_per_chip(p_hwfn,
+							   (enum block_id)
+							   block_id);
+			is_removed =
+			    GET_FIELD(block->flags, DBG_BLOCK_CHIP_IS_REMOVED);
+			has_reset_reg =
+			    GET_FIELD(block->flags,
+				      DBG_BLOCK_CHIP_HAS_RESET_REG);
+			unreset_before_dump =
+			    GET_FIELD(block->flags,
+				      DBG_BLOCK_CHIP_UNRESET_BEFORE_DUMP);
+
+			if (!is_removed && has_reset_reg && unreset_before_dump)
+				reg_val[block->reset_reg_id] |=
+				    OSAL_BIT(block->reset_reg_bit_offset);
+		}
+
+		/* Write reset registers */
+		for (reset_reg_id = 0; reset_reg_id < NUM_DBG_RESET_REGS;
+		     reset_reg_id++) {
+			const struct dbg_reset_reg *reset_reg;
+			u32 reset_reg_addr;
+
+			reset_reg = qed_get_dbg_reset_reg(p_hwfn, reset_reg_id);
+
+			if (GET_FIELD
+			    (reset_reg->data, DBG_RESET_REG_IS_REMOVED))
+				continue;
+
+			if (reg_val[reset_reg_id]) {
+				reset_reg_addr =
+				    GET_FIELD(reset_reg->data,
+					      DBG_RESET_REG_ADDR);
+				ecore_wr(p_hwfn,
+				       p_ptt,
+				       DWORDS_TO_BYTES(reset_reg_addr) +
+				       RESET_REG_UNRESET_OFFSET,
+				       reg_val[reset_reg_id]);
+			}
+		}
+	}
+}
+
+/* Returns the attention block data of the specified block */
+static const struct dbg_attn_block_type_data *
+qed_get_block_attn_data(struct ecore_hwfn *p_hwfn,
+			enum block_id block_id, enum dbg_attn_type attn_type)
+{
+	const struct dbg_attn_block *base_attn_block_arr =
+	    (const struct dbg_attn_block *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr;
+
+	return &base_attn_block_arr[block_id].per_type_data[attn_type];
+}
+
+/* Returns the attention registers of the specified block */
+static const struct dbg_attn_reg *
+qed_get_block_attn_regs(struct ecore_hwfn *p_hwfn,
+			enum block_id block_id, enum dbg_attn_type attn_type,
+			u8 *num_attn_regs)
+{
+	const struct dbg_attn_block_type_data *block_type_data =
+	    qed_get_block_attn_data(p_hwfn, block_id, attn_type);
+
+	*num_attn_regs = block_type_data->num_regs;
+
+	return (const struct dbg_attn_reg *)
+		p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr +
+		block_type_data->regs_offset;
+}
+
+/* For each block, clear the status of all parities */
+static void qed_grc_clear_all_prty(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	const struct dbg_attn_reg *attn_reg_arr;
+	u8 reg_idx, num_attn_regs;
+	u32 block_id;
+
+	for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
+		if (dev_data->block_in_reset[block_id])
+			continue;
+
+		attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
+						       (enum block_id)block_id,
+						       ATTN_TYPE_PARITY,
+						       &num_attn_regs);
+
+		for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
+			const struct dbg_attn_reg *reg_data =
+				&attn_reg_arr[reg_idx];
+			u16 modes_buf_offset;
+			bool eval_mode;
+
+			/* Check mode */
+			eval_mode = GET_FIELD(reg_data->mode.data,
+					      DBG_MODE_HDR_EVAL_MODE) > 0;
+			modes_buf_offset =
+				GET_FIELD(reg_data->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+
+			/* If Mode match: clear parity status */
+			if (!eval_mode ||
+			    qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				ecore_rd(p_hwfn, p_ptt,
+				    DWORDS_TO_BYTES(reg_data->sts_clr_address));
+		}
+	}
+}
+
+/* Dumps GRC registers section header. Returns the dumped size in dwords.
+ * the following parameters are dumped:
+ * - count: no. of dumped entries
+ * - split_type: split type
+ * - split_id: split ID (dumped only if split_id != SPLIT_TYPE_NONE)
+ * - reg_type_name: register type name (dumped only if reg_type_name != NULL)
+ */
+static u32 qed_grc_dump_regs_hdr(u32 *dump_buf,
+				 bool dump,
+				 u32 num_reg_entries,
+				 enum init_split_types split_type,
+				 u8 split_id, const char *reg_type_name)
+{
+	u8 num_params = 2 +
+	    (split_type != SPLIT_TYPE_NONE ? 1 : 0) + (reg_type_name ? 1 : 0);
+	u32 offset = 0;
+
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "grc_regs", num_params);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "count", num_reg_entries);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "split",
+				     s_split_type_defs[split_type].name);
+	if (split_type != SPLIT_TYPE_NONE)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "id", split_id);
+	if (reg_type_name)
+		offset += qed_dump_str_param(dump_buf + offset,
+					     dump, "type", reg_type_name);
+
+	return offset;
+}
+
+/* Reads the specified registers into the specified buffer.
+ * The addr and len arguments are specified in dwords.
+ */
+void qed_read_regs(struct ecore_hwfn *p_hwfn,
+		   struct ecore_ptt *p_ptt, u32 *buf, u32 addr, u32 len)
+{
+	u32 i;
+
+	for (i = 0; i < len; i++)
+		buf[i] = ecore_rd(p_hwfn, p_ptt, DWORDS_TO_BYTES(addr + i));
+}
+
+/* Dumps the GRC registers in the specified address range.
+ * Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_addr_range(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   u32 *dump_buf,
+				   bool dump, u32 addr, u32 len, bool wide_bus,
+				   enum init_split_types split_type,
+				   u8 split_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 port_id = 0, pf_id = 0, vf_id = 0, fid = 0;
+	bool read_using_dmae = false;
+	u32 thresh;
+
+	if (!dump)
+		return len;
+
+	switch (split_type) {
+	case SPLIT_TYPE_PORT:
+		port_id = split_id;
+		break;
+	case SPLIT_TYPE_PF:
+		pf_id = split_id;
+		break;
+	case SPLIT_TYPE_PORT_PF:
+		port_id = split_id / dev_data->num_pfs_per_port;
+		pf_id = port_id + dev_data->num_ports *
+		    (split_id % dev_data->num_pfs_per_port);
+		break;
+	case SPLIT_TYPE_VF:
+		vf_id = split_id;
+		break;
+	default:
+		break;
+	}
+
+	/* Try reading using DMAE */
+	if (dev_data->use_dmae && split_type != SPLIT_TYPE_VF &&
+	    (len >= s_hw_type_defs[dev_data->hw_type].dmae_thresh ||
+	     (PROTECT_WIDE_BUS && wide_bus))) {
+		struct dmae_params dmae_params;
+
+		/* Set DMAE params */
+		memset(&dmae_params, 0, sizeof(dmae_params));
+		SET_FIELD(dmae_params.flags, DMAE_PARAMS_COMPLETION_DST, 1);
+		switch (split_type) {
+		case SPLIT_TYPE_PORT:
+			SET_FIELD(dmae_params.flags, DMAE_PARAMS_PORT_VALID,
+				  1);
+			dmae_params.port_id = port_id;
+			break;
+		case SPLIT_TYPE_PF:
+			SET_FIELD(dmae_params.flags,
+				  DMAE_PARAMS_SRC_PF_VALID, 1);
+			dmae_params.src_pf_id = pf_id;
+			break;
+		case SPLIT_TYPE_PORT_PF:
+			SET_FIELD(dmae_params.flags, DMAE_PARAMS_PORT_VALID,
+				  1);
+			SET_FIELD(dmae_params.flags,
+				  DMAE_PARAMS_SRC_PF_VALID, 1);
+			dmae_params.port_id = port_id;
+			dmae_params.src_pf_id = pf_id;
+			break;
+		default:
+			break;
+		}
+
+		/* Execute DMAE command */
+		read_using_dmae = !ecore_dmae_grc2host(p_hwfn,
+						     p_ptt,
+						     DWORDS_TO_BYTES(addr),
+						     (u64)(uintptr_t)(dump_buf),
+						     len, &dmae_params);
+		if (!read_using_dmae) {
+			dev_data->use_dmae = 0;
+			DP_VERBOSE(p_hwfn->p_dev,
+				   ECORE_MSG_DEBUG,
+				   "Failed reading from chip using DMAE, using GRC instead\n");
+		}
+	}
+
+	if (read_using_dmae)
+		goto print_log;
+
+	/* If not read using DMAE, read using GRC */
+
+	/* Set pretend */
+	if (split_type != dev_data->pretend.split_type ||
+	    split_id != dev_data->pretend.split_id) {
+		switch (split_type) {
+		case SPLIT_TYPE_PORT:
+			ecore_port_pretend(p_hwfn, p_ptt, port_id);
+			break;
+		case SPLIT_TYPE_PF:
+			fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
+					  pf_id);
+			ecore_fid_pretend(p_hwfn, p_ptt, fid);
+			break;
+		case SPLIT_TYPE_PORT_PF:
+			fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
+					  pf_id);
+			ecore_port_fid_pretend(p_hwfn, p_ptt, port_id, fid);
+			break;
+		case SPLIT_TYPE_VF:
+			fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_VFVALID, 1)
+			      | FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_VFID,
+					  vf_id);
+			ecore_fid_pretend(p_hwfn, p_ptt, fid);
+			break;
+		default:
+			break;
+		}
+
+		dev_data->pretend.split_type = (u8)split_type;
+		dev_data->pretend.split_id = split_id;
+	}
+
+	/* Read registers using GRC */
+	qed_read_regs(p_hwfn, p_ptt, dump_buf, addr, len);
+
+print_log:
+	/* Print log */
+	dev_data->num_regs_read += len;
+	thresh = s_hw_type_defs[dev_data->hw_type].log_thresh;
+	if ((dev_data->num_regs_read / thresh) >
+	    ((dev_data->num_regs_read - len) / thresh))
+		DP_VERBOSE(p_hwfn->p_dev,
+			   ECORE_MSG_DEBUG,
+			   "Dumped %d registers...\n", dev_data->num_regs_read);
+
+	return len;
+}
+
+/* Dumps GRC registers sequence header. Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_reg_entry_hdr(u32 *dump_buf,
+				      bool dump, u32 addr, u32 len)
+{
+	if (dump)
+		*dump_buf = addr | (len << REG_DUMP_LEN_SHIFT);
+
+	return 1;
+}
+
+/* Dumps GRC registers sequence. Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_reg_entry(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  u32 *dump_buf,
+				  bool dump, u32 addr, u32 len, bool wide_bus,
+				  enum init_split_types split_type, u8 split_id)
+{
+	u32 offset = 0;
+
+	offset += qed_grc_dump_reg_entry_hdr(dump_buf, dump, addr, len);
+	offset += qed_grc_dump_addr_range(p_hwfn,
+					  p_ptt,
+					  dump_buf + offset,
+					  dump, addr, len, wide_bus,
+					  split_type, split_id);
+
+	return offset;
+}
+
+/* Dumps GRC registers sequence with skip cycle.
+ * Returns the dumped size in dwords.
+ * - addr:	start GRC address in dwords
+ * - total_len:	total no. of dwords to dump
+ * - read_len:	no. consecutive dwords to read
+ * - skip_len:	no. of dwords to skip (and fill with zeros)
+ */
+static u32 qed_grc_dump_reg_entry_skip(struct ecore_hwfn *p_hwfn,
+				       struct ecore_ptt *p_ptt,
+				       u32 *dump_buf,
+				       bool dump,
+				       u32 addr,
+				       u32 total_len,
+				       u32 read_len, u32 skip_len)
+{
+	u32 offset = 0, reg_offset = 0;
+
+	offset += qed_grc_dump_reg_entry_hdr(dump_buf, dump, addr, total_len);
+
+	if (!dump)
+		return offset + total_len;
+
+	while (reg_offset < total_len) {
+		u32 curr_len = OSAL_MIN_T(u32, read_len,
+					  total_len - reg_offset);
+
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  dump,  addr, curr_len, false,
+						  SPLIT_TYPE_NONE, 0);
+		reg_offset += curr_len;
+		addr += curr_len;
+
+		if (reg_offset < total_len) {
+			curr_len = OSAL_MIN_T(u32, skip_len,
+					      total_len - skip_len);
+			memset(dump_buf + offset, 0, DWORDS_TO_BYTES(curr_len));
+			offset += curr_len;
+			reg_offset += curr_len;
+			addr += curr_len;
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC registers entries. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_regs_entries(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     struct virt_mem_desc input_regs_arr,
+				     u32 *dump_buf,
+				     bool dump,
+				     enum init_split_types split_type,
+				     u8 split_id,
+				     bool block_enable[MAX_BLOCK_ID],
+				     u32 *num_dumped_reg_entries)
+{
+	u32 i, offset = 0, input_offset = 0;
+	bool mode_match = true;
+
+	*num_dumped_reg_entries = 0;
+
+	while (input_offset < BYTES_TO_DWORDS(input_regs_arr.size)) {
+		const struct dbg_dump_cond_hdr *cond_hdr =
+		    (const struct dbg_dump_cond_hdr *)
+		    input_regs_arr.ptr + input_offset++;
+		u16 modes_buf_offset;
+		bool eval_mode;
+
+		/* Check mode/block */
+		eval_mode = GET_FIELD(cond_hdr->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		if (eval_mode) {
+			modes_buf_offset =
+				GET_FIELD(cond_hdr->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			mode_match = qed_is_mode_match(p_hwfn,
+						       &modes_buf_offset);
+		}
+
+		if (!mode_match || !block_enable[cond_hdr->block_id]) {
+			input_offset += cond_hdr->data_size;
+			continue;
+		}
+
+		for (i = 0; i < cond_hdr->data_size; i++, input_offset++) {
+			const struct dbg_dump_reg *reg =
+			    (const struct dbg_dump_reg *)
+			    input_regs_arr.ptr + input_offset;
+			u32 addr, len;
+			bool wide_bus;
+
+			addr = GET_FIELD(reg->data, DBG_DUMP_REG_ADDRESS);
+			len = GET_FIELD(reg->data, DBG_DUMP_REG_LENGTH);
+			wide_bus = GET_FIELD(reg->data, DBG_DUMP_REG_WIDE_BUS);
+			offset += qed_grc_dump_reg_entry(p_hwfn,
+							 p_ptt,
+							 dump_buf + offset,
+							 dump,
+							 addr,
+							 len,
+							 wide_bus,
+							 split_type, split_id);
+			(*num_dumped_reg_entries)++;
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC registers entries. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_split_data(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   struct virt_mem_desc input_regs_arr,
+				   u32 *dump_buf,
+				   bool dump,
+				   bool block_enable[MAX_BLOCK_ID],
+				   enum init_split_types split_type,
+				   u8 split_id, const char *reg_type_name)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	enum init_split_types hdr_split_type = split_type;
+	u32 num_dumped_reg_entries, offset;
+	u8 hdr_split_id = split_id;
+
+	/* In PORT_PF split type, print a port split header */
+	if (split_type == SPLIT_TYPE_PORT_PF) {
+		hdr_split_type = SPLIT_TYPE_PORT;
+		hdr_split_id = split_id / dev_data->num_pfs_per_port;
+	}
+
+	/* Calculate register dump header size (and skip it for now) */
+	offset = qed_grc_dump_regs_hdr(dump_buf,
+				       false,
+				       0,
+				       hdr_split_type,
+				       hdr_split_id, reg_type_name);
+
+	/* Dump registers */
+	offset += qed_grc_dump_regs_entries(p_hwfn,
+					    p_ptt,
+					    input_regs_arr,
+					    dump_buf + offset,
+					    dump,
+					    split_type,
+					    split_id,
+					    block_enable,
+					    &num_dumped_reg_entries);
+
+	/* Write register dump header */
+	if (dump && num_dumped_reg_entries > 0)
+		qed_grc_dump_regs_hdr(dump_buf,
+				      dump,
+				      num_dumped_reg_entries,
+				      hdr_split_type,
+				      hdr_split_id, reg_type_name);
+
+	return num_dumped_reg_entries > 0 ? offset : 0;
+}
+
+/* Dumps registers according to the input registers array. Returns the dumped
+ * size in dwords.
+ */
+static u32 qed_grc_dump_registers(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  u32 *dump_buf,
+				  bool dump,
+				  bool block_enable[MAX_BLOCK_ID],
+				  const char *reg_type_name)
+{
+	struct virt_mem_desc *dbg_buf =
+	    &p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG];
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 offset = 0, input_offset = 0;
+
+	while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
+		const struct dbg_dump_split_hdr *split_hdr;
+		struct virt_mem_desc curr_input_regs_arr;
+		enum init_split_types split_type;
+		u16 split_count = 0;
+		u32 split_data_size;
+		u8 split_id;
+
+		split_hdr =
+		    (const struct dbg_dump_split_hdr *)
+		    dbg_buf->ptr + input_offset++;
+		split_type =
+		    GET_FIELD(split_hdr->hdr,
+			      DBG_DUMP_SPLIT_HDR_SPLIT_TYPE_ID);
+		split_data_size = GET_FIELD(split_hdr->hdr,
+					    DBG_DUMP_SPLIT_HDR_DATA_SIZE);
+		curr_input_regs_arr.ptr =
+		    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG].ptr +
+		    input_offset;
+		curr_input_regs_arr.size = DWORDS_TO_BYTES(split_data_size);
+
+		switch (split_type) {
+		case SPLIT_TYPE_NONE:
+			split_count = 1;
+			break;
+		case SPLIT_TYPE_PORT:
+			split_count = dev_data->num_ports;
+			break;
+		case SPLIT_TYPE_PF:
+		case SPLIT_TYPE_PORT_PF:
+			split_count = dev_data->num_ports *
+			    dev_data->num_pfs_per_port;
+			break;
+		case SPLIT_TYPE_VF:
+			split_count = dev_data->num_vfs;
+			break;
+		default:
+			return 0;
+		}
+
+		for (split_id = 0; split_id < split_count; split_id++)
+			offset += qed_grc_dump_split_data(p_hwfn, p_ptt,
+							  curr_input_regs_arr,
+							  dump_buf + offset,
+							  dump, block_enable,
+							  split_type,
+							  split_id,
+							  reg_type_name);
+
+		input_offset += split_data_size;
+	}
+
+	/* Cancel pretends (pretend to original PF) */
+	if (dump) {
+		ecore_fid_pretend(p_hwfn, p_ptt,
+				FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
+					    p_hwfn->rel_pf_id));
+		dev_data->pretend.split_type = SPLIT_TYPE_NONE;
+		dev_data->pretend.split_id = 0;
+	}
+
+	return offset;
+}
+
+/* Dump reset registers. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_reset_regs(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   u32 *dump_buf, bool dump)
+{
+	u32 offset = 0, num_regs = 0;
+	u8 reset_reg_id;
+
+	/* Calculate header size */
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					false,
+					0, SPLIT_TYPE_NONE, 0, "RESET_REGS");
+
+	/* Write reset registers */
+	for (reset_reg_id = 0; reset_reg_id < NUM_DBG_RESET_REGS;
+	     reset_reg_id++) {
+		const struct dbg_reset_reg *reset_reg;
+		u32 reset_reg_addr;
+
+		reset_reg = qed_get_dbg_reset_reg(p_hwfn, reset_reg_id);
+
+		if (GET_FIELD(reset_reg->data, DBG_RESET_REG_IS_REMOVED))
+			continue;
+
+		reset_reg_addr = GET_FIELD(reset_reg->data, DBG_RESET_REG_ADDR);
+		offset += qed_grc_dump_reg_entry(p_hwfn,
+						 p_ptt,
+						 dump_buf + offset,
+						 dump,
+						 reset_reg_addr,
+						 1, false, SPLIT_TYPE_NONE, 0);
+		num_regs++;
+	}
+
+	/* Write header */
+	if (dump)
+		qed_grc_dump_regs_hdr(dump_buf,
+				      true, num_regs, SPLIT_TYPE_NONE,
+				      0, "RESET_REGS");
+
+	return offset;
+}
+
+/* Dump registers that are modified during GRC Dump and therefore must be
+ * dumped first. Returns the dumped size in dwords.
+ */
+static u32 qed_grc_dump_modified_regs(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_id, offset = 0, stall_regs_offset;
+	const struct dbg_attn_reg *attn_reg_arr;
+	u8 storm_id, reg_idx, num_attn_regs;
+	u32 num_reg_entries = 0;
+
+	/* Write empty header for attention registers */
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					false,
+					0, SPLIT_TYPE_NONE, 0, "ATTN_REGS");
+
+	/* Write parity registers */
+	for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
+		if (dev_data->block_in_reset[block_id] && dump)
+			continue;
+
+		attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
+						       (enum block_id)block_id,
+						       ATTN_TYPE_PARITY,
+						       &num_attn_regs);
+
+		for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
+			const struct dbg_attn_reg *reg_data =
+				&attn_reg_arr[reg_idx];
+			u16 modes_buf_offset;
+			bool eval_mode;
+			u32 addr;
+
+			/* Check mode */
+			eval_mode = GET_FIELD(reg_data->mode.data,
+					      DBG_MODE_HDR_EVAL_MODE) > 0;
+			modes_buf_offset =
+				GET_FIELD(reg_data->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			if (eval_mode &&
+			    !qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				continue;
+
+			/* Mode match: read & dump registers */
+			addr = reg_data->mask_address;
+			offset += qed_grc_dump_reg_entry(p_hwfn,
+							 p_ptt,
+							 dump_buf + offset,
+							 dump,
+							 addr,
+							 1, false,
+							 SPLIT_TYPE_NONE, 0);
+			addr = GET_FIELD(reg_data->data,
+					 DBG_ATTN_REG_STS_ADDRESS);
+			offset += qed_grc_dump_reg_entry(p_hwfn,
+							 p_ptt,
+							 dump_buf + offset,
+							 dump,
+							 addr,
+							 1, false,
+							 SPLIT_TYPE_NONE, 0);
+			num_reg_entries += 2;
+		}
+	}
+
+	/* Overwrite header for attention registers */
+	if (dump)
+		qed_grc_dump_regs_hdr(dump_buf,
+				      true,
+				      num_reg_entries,
+				      SPLIT_TYPE_NONE, 0, "ATTN_REGS");
+
+	/* Write empty header for stall registers */
+	stall_regs_offset = offset;
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					false, 0, SPLIT_TYPE_NONE, 0, "REGS");
+
+	/* Write Storm stall status registers */
+	for (storm_id = 0, num_reg_entries = 0; storm_id < MAX_DBG_STORMS;
+	     storm_id++) {
+		struct storm_defs *storm = &s_storm_defs[storm_id];
+		u32 addr;
+
+		if (dev_data->block_in_reset[storm->sem_block_id] && dump)
+			continue;
+
+		addr =
+		    BYTES_TO_DWORDS(storm->sem_fast_mem_addr +
+				    SEM_FAST_REG_STALLED);
+		offset += qed_grc_dump_reg_entry(p_hwfn,
+						 p_ptt,
+						 dump_buf + offset,
+						 dump,
+						 addr,
+						 1,
+						 false, SPLIT_TYPE_NONE, 0);
+		num_reg_entries++;
+	}
+
+	/* Overwrite header for stall registers */
+	if (dump)
+		qed_grc_dump_regs_hdr(dump_buf + stall_regs_offset,
+				      true,
+				      num_reg_entries,
+				      SPLIT_TYPE_NONE, 0, "REGS");
+
+	return offset;
+}
+
+/* Dumps registers that can't be represented in the debug arrays */
+static u32 qed_grc_dump_special_regs(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     u32 *dump_buf, bool dump)
+{
+	u32 offset = 0, addr;
+
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					dump, 2, SPLIT_TYPE_NONE, 0, "REGS");
+
+	/* Dump R/TDIF_REG_DEBUG_ERROR_INFO_SIZE (every 8'th register should be
+	 * skipped).
+	 */
+	addr = BYTES_TO_DWORDS(RDIF_REG_DEBUG_ERROR_INFO);
+	offset += qed_grc_dump_reg_entry_skip(p_hwfn,
+					      p_ptt,
+					      dump_buf + offset,
+					      dump,
+					      addr,
+					      RDIF_REG_DEBUG_ERROR_INFO_SIZE,
+					      7,
+					      1);
+	addr = BYTES_TO_DWORDS(TDIF_REG_DEBUG_ERROR_INFO);
+	offset +=
+	    qed_grc_dump_reg_entry_skip(p_hwfn,
+					p_ptt,
+					dump_buf + offset,
+					dump,
+					addr,
+					TDIF_REG_DEBUG_ERROR_INFO_SIZE,
+					7,
+					1);
+
+	return offset;
+}
+
+/* Dumps a GRC memory header (section and params). Returns the dumped size in
+ * dwords. The following parameters are dumped:
+ * - name:	   dumped only if it's not NULL.
+ * - addr:	   in dwords, dumped only if name is NULL.
+ * - len:	   in dwords, always dumped.
+ * - width:	   dumped if it's not zero.
+ * - packed:	   dumped only if it's not false.
+ * - mem_group:	   always dumped.
+ * - is_storm:	   true only if the memory is related to a Storm.
+ * - storm_letter: valid only if is_storm is true.
+ *
+ */
+static u32 qed_grc_dump_mem_hdr(struct ecore_hwfn *p_hwfn,
+				u32 *dump_buf,
+				bool dump,
+				const char *name,
+				u32 addr,
+				u32 len,
+				u32 bit_width,
+				bool packed,
+				const char *mem_group, char storm_letter)
+{
+	u8 num_params = 3;
+	u32 offset = 0;
+	char buf[64];
+
+	if (!len)
+		DP_NOTICE(p_hwfn, false,
+			  "Unexpected GRC Dump error: dumped memory size must be non-zero\n");
+
+	if (bit_width)
+		num_params++;
+	if (packed)
+		num_params++;
+
+	/* Dump section header */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "grc_mem", num_params);
+
+	if (name) {
+		/* Dump name */
+		if (storm_letter) {
+			strcpy(buf, "?STORM_");
+			buf[0] = storm_letter;
+			strcpy(buf + strlen(buf), name);
+		} else {
+			strcpy(buf, name);
+		}
+
+		offset += qed_dump_str_param(dump_buf + offset,
+					     dump, "name", buf);
+	} else {
+		/* Dump address */
+		u32 addr_in_bytes = DWORDS_TO_BYTES(addr);
+
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "addr", addr_in_bytes);
+	}
+
+	/* Dump len */
+	offset += qed_dump_num_param(dump_buf + offset, dump, "len", len);
+
+	/* Dump bit width */
+	if (bit_width)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "width", bit_width);
+
+	/* Dump packed */
+	if (packed)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "packed", 1);
+
+	/* Dump reg type */
+	if (storm_letter) {
+		strcpy(buf, "?STORM_");
+		buf[0] = storm_letter;
+		strcpy(buf + strlen(buf), mem_group);
+	} else {
+		strcpy(buf, mem_group);
+	}
+
+	offset += qed_dump_str_param(dump_buf + offset, dump, "type", buf);
+
+	return offset;
+}
+
+/* Dumps a single GRC memory. If name is NULL, the memory is stored by address.
+ * Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_mem(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt,
+			    u32 *dump_buf,
+			    bool dump,
+			    const char *name,
+			    u32 addr,
+			    u32 len,
+			    bool wide_bus,
+			    u32 bit_width,
+			    bool packed,
+			    const char *mem_group, char storm_letter)
+{
+	u32 offset = 0;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       name,
+				       addr,
+				       len,
+				       bit_width,
+				       packed, mem_group, storm_letter);
+	offset += qed_grc_dump_addr_range(p_hwfn,
+					  p_ptt,
+					  dump_buf + offset,
+					  dump, addr, len, wide_bus,
+					  SPLIT_TYPE_NONE, 0);
+
+	return offset;
+}
+
+/* Dumps GRC memories entries. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_mem_entries(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    struct virt_mem_desc input_mems_arr,
+				    u32 *dump_buf, bool dump)
+{
+	u32 i, offset = 0, input_offset = 0;
+	bool mode_match = true;
+
+	while (input_offset < BYTES_TO_DWORDS(input_mems_arr.size)) {
+		const struct dbg_dump_cond_hdr *cond_hdr;
+		u16 modes_buf_offset;
+		u32 num_entries;
+		bool eval_mode;
+
+		cond_hdr =
+		    (const struct dbg_dump_cond_hdr *)input_mems_arr.ptr +
+		    input_offset++;
+		num_entries = cond_hdr->data_size / MEM_DUMP_ENTRY_SIZE_DWORDS;
+
+		/* Check required mode */
+		eval_mode = GET_FIELD(cond_hdr->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		if (eval_mode) {
+			modes_buf_offset =
+				GET_FIELD(cond_hdr->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			mode_match = qed_is_mode_match(p_hwfn,
+						       &modes_buf_offset);
+		}
+
+		if (!mode_match) {
+			input_offset += cond_hdr->data_size;
+			continue;
+		}
+
+		for (i = 0; i < num_entries;
+		     i++, input_offset += MEM_DUMP_ENTRY_SIZE_DWORDS) {
+			const struct dbg_dump_mem *mem =
+			    (const struct dbg_dump_mem *)((u32 *)
+							  input_mems_arr.ptr
+							  + input_offset);
+			const struct dbg_block *block;
+			char storm_letter = 0;
+			u32 mem_addr, mem_len;
+			bool mem_wide_bus;
+			u8 mem_group_id;
+
+			mem_group_id = GET_FIELD(mem->dword0,
+						 DBG_DUMP_MEM_MEM_GROUP_ID);
+			if (mem_group_id >= MEM_GROUPS_NUM) {
+				DP_NOTICE(p_hwfn, false, "Invalid mem_group_id\n");
+				return 0;
+			}
+
+			if (!qed_grc_is_mem_included(p_hwfn,
+						     (enum block_id)
+						     cond_hdr->block_id,
+						     mem_group_id))
+				continue;
+
+			mem_addr = GET_FIELD(mem->dword0, DBG_DUMP_MEM_ADDRESS);
+			mem_len = GET_FIELD(mem->dword1, DBG_DUMP_MEM_LENGTH);
+			mem_wide_bus = GET_FIELD(mem->dword1,
+						 DBG_DUMP_MEM_WIDE_BUS);
+
+			block = get_dbg_block(p_hwfn,
+					      cond_hdr->block_id);
+
+			/* If memory is associated with Storm,
+			 * update storm details
+			 */
+			if (block->associated_storm_letter)
+				storm_letter = block->associated_storm_letter;
+
+			/* Dump memory */
+			offset += qed_grc_dump_mem(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						NULL,
+						mem_addr,
+						mem_len,
+						mem_wide_bus,
+						0,
+						false,
+						s_mem_group_names[mem_group_id],
+						storm_letter);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC memories according to the input array dump_mem.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_grc_dump_memories(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf, bool dump)
+{
+	struct virt_mem_desc *dbg_buf =
+	    &p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_MEM];
+	u32 offset = 0, input_offset = 0;
+
+	while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
+		const struct dbg_dump_split_hdr *split_hdr;
+		struct virt_mem_desc curr_input_mems_arr;
+		enum init_split_types split_type;
+		u32 split_data_size;
+
+		split_hdr =
+		    (const struct dbg_dump_split_hdr *)dbg_buf->ptr +
+		    input_offset++;
+		split_type = GET_FIELD(split_hdr->hdr,
+				       DBG_DUMP_SPLIT_HDR_SPLIT_TYPE_ID);
+		split_data_size = GET_FIELD(split_hdr->hdr,
+					    DBG_DUMP_SPLIT_HDR_DATA_SIZE);
+		curr_input_mems_arr.ptr = (u32 *)dbg_buf->ptr + input_offset;
+		curr_input_mems_arr.size = DWORDS_TO_BYTES(split_data_size);
+
+		if (split_type == SPLIT_TYPE_NONE)
+			offset += qed_grc_dump_mem_entries(p_hwfn,
+							   p_ptt,
+							   curr_input_mems_arr,
+							   dump_buf + offset,
+							   dump);
+		else
+			DP_NOTICE(p_hwfn, false,
+				  "Dumping split memories is currently not supported\n");
+
+		input_offset += split_data_size;
+	}
+
+	return offset;
+}
+
+/* Dumps GRC context data for the specified Storm.
+ * Returns the dumped size in dwords.
+ * The lid_size argument is specified in quad-regs.
+ */
+static u32 qed_grc_dump_ctx_data(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf,
+				 bool dump,
+				 const char *name,
+				 u32 num_lids,
+				 enum cm_ctx_types ctx_type, u8 storm_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	u32 i, lid, lid_size, total_size;
+	u32 rd_reg_addr, offset = 0;
+
+	/* Convert quad-regs to dwords */
+	lid_size = storm->cm_ctx_lid_sizes[dev_data->chip_id][ctx_type] * 4;
+
+	if (!lid_size)
+		return 0;
+
+	total_size = num_lids * lid_size;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       name,
+				       0,
+				       total_size,
+				       lid_size * 32,
+				       false, name, storm->letter);
+
+	if (!dump)
+		return offset + total_size;
+
+	rd_reg_addr = BYTES_TO_DWORDS(storm->cm_ctx_rd_addr[ctx_type]);
+
+	/* Dump context data */
+	for (lid = 0; lid < num_lids; lid++) {
+		for (i = 0; i < lid_size; i++) {
+			ecore_wr(p_hwfn,
+			       p_ptt, storm->cm_ctx_wr_addr, (i << 9) | lid);
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  rd_reg_addr,
+							  1,
+							  false,
+							  SPLIT_TYPE_NONE, 0);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC contexts. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_ctx(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	u32 offset = 0;
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		if (!qed_grc_is_storm_included(p_hwfn,
+					       (enum dbg_storms)storm_id))
+			continue;
+
+		/* Dump Conn AG context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"CONN_AG_CTX",
+						NUM_OF_LCIDS,
+						CM_CTX_CONN_AG, storm_id);
+
+		/* Dump Conn ST context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"CONN_ST_CTX",
+						NUM_OF_LCIDS,
+						CM_CTX_CONN_ST, storm_id);
+
+		/* Dump Task AG context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"TASK_AG_CTX",
+						NUM_OF_LTIDS,
+						CM_CTX_TASK_AG, storm_id);
+
+		/* Dump Task ST context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"TASK_ST_CTX",
+						NUM_OF_LTIDS,
+						CM_CTX_TASK_ST, storm_id);
+	}
+
+	return offset;
+}
+
+#define VFC_STATUS_RESP_READY_BIT	0
+#define VFC_STATUS_BUSY_BIT		1
+#define VFC_STATUS_SENDING_CMD_BIT	2
+
+#define VFC_POLLING_DELAY_MS	1
+#define VFC_POLLING_COUNT		20
+
+/* Reads data from VFC. Returns the number of dwords read (0 on error).
+ * Sizes are specified in dwords.
+ */
+static u32 qed_grc_dump_read_from_vfc(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      struct storm_defs *storm,
+				      u32 *cmd_data,
+				      u32 cmd_size,
+				      u32 *addr_data,
+				      u32 addr_size,
+				      u32 resp_size, u32 *dump_buf)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 vfc_status, polling_ms, polling_count = 0, i;
+	u32 reg_addr, sem_base;
+	bool is_ready = false;
+
+	sem_base = storm->sem_fast_mem_addr;
+	polling_ms = VFC_POLLING_DELAY_MS *
+	    s_hw_type_defs[dev_data->hw_type].delay_factor;
+
+	/* Write VFC command */
+	ARR_REG_WR(p_hwfn,
+		   p_ptt,
+		   sem_base + SEM_FAST_REG_VFC_DATA_WR,
+		   cmd_data, cmd_size);
+
+	/* Write VFC address */
+	ARR_REG_WR(p_hwfn,
+		   p_ptt,
+		   sem_base + SEM_FAST_REG_VFC_ADDR,
+		   addr_data, addr_size);
+
+	/* Read response */
+	for (i = 0; i < resp_size; i++) {
+		/* Poll until ready */
+		do {
+			reg_addr = sem_base + SEM_FAST_REG_VFC_STATUS;
+			qed_grc_dump_addr_range(p_hwfn,
+						p_ptt,
+						&vfc_status,
+						true,
+						BYTES_TO_DWORDS(reg_addr),
+						1,
+						false, SPLIT_TYPE_NONE, 0);
+			is_ready = vfc_status &
+				   OSAL_BIT(VFC_STATUS_RESP_READY_BIT);
+
+			if (!is_ready) {
+				if (polling_count++ == VFC_POLLING_COUNT)
+					return 0;
+
+				OSAL_MSLEEP(polling_ms);
+			}
+		} while (!is_ready);
+
+		reg_addr = sem_base + SEM_FAST_REG_VFC_DATA_RD;
+		qed_grc_dump_addr_range(p_hwfn,
+					p_ptt,
+					dump_buf + i,
+					true,
+					BYTES_TO_DWORDS(reg_addr),
+					1, false, SPLIT_TYPE_NONE, 0);
+	}
+
+	return resp_size;
+}
+
+/* Dump VFC CAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_vfc_cam(struct ecore_hwfn *p_hwfn,
+				struct ecore_ptt *p_ptt,
+				u32 *dump_buf, bool dump, u8 storm_id)
+{
+	u32 total_size = VFC_CAM_NUM_ROWS * VFC_CAM_RESP_DWORDS;
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	u32 cam_addr[VFC_CAM_ADDR_DWORDS] = { 0 };
+	u32 cam_cmd[VFC_CAM_CMD_DWORDS] = { 0 };
+	u32 row, offset = 0;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       "vfc_cam",
+				       0,
+				       total_size,
+				       256,
+				       false, "vfc_cam", storm->letter);
+
+	if (!dump)
+		return offset + total_size;
+
+	/* Prepare CAM address */
+	SET_VAR_FIELD(cam_addr, VFC_CAM_ADDR, OP, VFC_OPCODE_CAM_RD);
+
+	/* Read VFC CAM data */
+	for (row = 0; row < VFC_CAM_NUM_ROWS; row++) {
+		SET_VAR_FIELD(cam_cmd, VFC_CAM_CMD, ROW, row);
+		offset += qed_grc_dump_read_from_vfc(p_hwfn,
+						     p_ptt,
+						     storm,
+						     cam_cmd,
+						     VFC_CAM_CMD_DWORDS,
+						     cam_addr,
+						     VFC_CAM_ADDR_DWORDS,
+						     VFC_CAM_RESP_DWORDS,
+						     dump_buf + offset);
+	}
+
+	return offset;
+}
+
+/* Dump VFC RAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_vfc_ram(struct ecore_hwfn *p_hwfn,
+				struct ecore_ptt *p_ptt,
+				u32 *dump_buf,
+				bool dump,
+				u8 storm_id, struct vfc_ram_defs *ram_defs)
+{
+	u32 total_size = ram_defs->num_rows * VFC_RAM_RESP_DWORDS;
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	u32 ram_addr[VFC_RAM_ADDR_DWORDS] = { 0 };
+	u32 ram_cmd[VFC_RAM_CMD_DWORDS] = { 0 };
+	u32 row, offset = 0;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       ram_defs->mem_name,
+				       0,
+				       total_size,
+				       256,
+				       false,
+				       ram_defs->type_name,
+				       storm->letter);
+
+	if (!dump)
+		return offset + total_size;
+
+	/* Prepare RAM address */
+	SET_VAR_FIELD(ram_addr, VFC_RAM_ADDR, OP, VFC_OPCODE_RAM_RD);
+
+	/* Read VFC RAM data */
+	for (row = ram_defs->base_row;
+	     row < ram_defs->base_row + ram_defs->num_rows; row++) {
+		SET_VAR_FIELD(ram_addr, VFC_RAM_ADDR, ROW, row);
+		offset += qed_grc_dump_read_from_vfc(p_hwfn,
+						     p_ptt,
+						     storm,
+						     ram_cmd,
+						     VFC_RAM_CMD_DWORDS,
+						     ram_addr,
+						     VFC_RAM_ADDR_DWORDS,
+						     VFC_RAM_RESP_DWORDS,
+						     dump_buf + offset);
+	}
+
+	return offset;
+}
+
+/* Dumps GRC VFC data. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_vfc(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	u8 storm_id, i;
+	u32 offset = 0;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		if (!qed_grc_is_storm_included(p_hwfn,
+					       (enum dbg_storms)storm_id) ||
+		    !s_storm_defs[storm_id].has_vfc)
+			continue;
+
+		/* Read CAM */
+		offset += qed_grc_dump_vfc_cam(p_hwfn,
+					       p_ptt,
+					       dump_buf + offset,
+					       dump, storm_id);
+
+		/* Read RAM */
+		for (i = 0; i < NUM_VFC_RAM_TYPES; i++)
+			offset += qed_grc_dump_vfc_ram(p_hwfn,
+						       p_ptt,
+						       dump_buf + offset,
+						       dump,
+						       storm_id,
+						       &s_vfc_ram_defs[i]);
+	}
+
+	return offset;
+}
+
+/* Dumps GRC RSS data. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_rss(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 offset = 0;
+	u8 rss_mem_id;
+
+	for (rss_mem_id = 0; rss_mem_id < NUM_RSS_MEM_TYPES; rss_mem_id++) {
+		u32 rss_addr, num_entries, total_dwords;
+		struct rss_mem_defs *rss_defs;
+		u32 addr, num_dwords_to_read;
+		bool packed;
+
+		rss_defs = &s_rss_mem_defs[rss_mem_id];
+		rss_addr = rss_defs->addr;
+		num_entries = rss_defs->num_entries[dev_data->chip_id];
+		total_dwords = (num_entries * rss_defs->entry_width) / 32;
+		packed = (rss_defs->entry_width == 16);
+
+		offset += qed_grc_dump_mem_hdr(p_hwfn,
+					       dump_buf + offset,
+					       dump,
+					       rss_defs->mem_name,
+					       0,
+					       total_dwords,
+					       rss_defs->entry_width,
+					       packed,
+					       rss_defs->type_name, 0);
+
+		/* Dump RSS data */
+		if (!dump) {
+			offset += total_dwords;
+			continue;
+		}
+
+		addr = BYTES_TO_DWORDS(RSS_REG_RSS_RAM_DATA);
+		while (total_dwords) {
+			num_dwords_to_read = OSAL_MIN_T(u32,
+						      RSS_REG_RSS_RAM_DATA_SIZE,
+						      total_dwords);
+			ecore_wr(p_hwfn, p_ptt, RSS_REG_RSS_RAM_ADDR, rss_addr);
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  addr,
+							  num_dwords_to_read,
+							  false,
+							  SPLIT_TYPE_NONE, 0);
+			total_dwords -= num_dwords_to_read;
+			rss_addr++;
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC Big RAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_big_ram(struct ecore_hwfn *p_hwfn,
+				struct ecore_ptt *p_ptt,
+				u32 *dump_buf, bool dump, u8 big_ram_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_size, ram_size, offset = 0, reg_val, i;
+	char mem_name[12] = "???_BIG_RAM";
+	char type_name[8] = "???_RAM";
+	struct big_ram_defs *big_ram;
+
+	big_ram = &s_big_ram_defs[big_ram_id];
+	ram_size = big_ram->ram_size[dev_data->chip_id];
+
+	reg_val = ecore_rd(p_hwfn, p_ptt, big_ram->is_256b_reg_addr);
+	block_size = reg_val &
+		     OSAL_BIT(big_ram->is_256b_bit_offset[dev_data->chip_id]) ?
+								     256 : 128;
+
+	strncpy(type_name, big_ram->instance_name, BIG_RAM_NAME_LEN);
+	strncpy(mem_name, big_ram->instance_name, BIG_RAM_NAME_LEN);
+
+	/* Dump memory header */
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       mem_name,
+				       0,
+				       ram_size,
+				       block_size * 8,
+				       false, type_name, 0);
+
+	/* Read and dump Big RAM data */
+	if (!dump)
+		return offset + ram_size;
+
+	/* Dump Big RAM */
+	for (i = 0; i < DIV_ROUND_UP(ram_size, BRB_REG_BIG_RAM_DATA_SIZE);
+	     i++) {
+		u32 addr, len;
+
+		ecore_wr(p_hwfn, p_ptt, big_ram->addr_reg_addr, i);
+		addr = BYTES_TO_DWORDS(big_ram->data_reg_addr);
+		len = BRB_REG_BIG_RAM_DATA_SIZE;
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  dump,
+						  addr,
+						  len,
+						  false, SPLIT_TYPE_NONE, 0);
+	}
+
+	return offset;
+}
+
+/* Dumps MCP scratchpad. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_mcp(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	bool block_enable[MAX_BLOCK_ID] = { 0 };
+	u32 offset = 0, addr;
+	bool halted = false;
+
+	/* Halt MCP */
+	if (dump && !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP)) {
+		halted = !ecore_mcp_halt(p_hwfn, p_ptt);
+		if (!halted)
+			DP_NOTICE(p_hwfn, false, "MCP halt failed!\n");
+	}
+
+	/* Dump MCP scratchpad */
+	offset += qed_grc_dump_mem(p_hwfn,
+				   p_ptt,
+				   dump_buf + offset,
+				   dump,
+				   NULL,
+				   BYTES_TO_DWORDS(MCP_REG_SCRATCH),
+				   MCP_REG_SCRATCH_SIZE,
+				   false, 0, false, "MCP", 0);
+
+	/* Dump MCP cpu_reg_file */
+	offset += qed_grc_dump_mem(p_hwfn,
+				   p_ptt,
+				   dump_buf + offset,
+				   dump,
+				   NULL,
+				   BYTES_TO_DWORDS(MCP_REG_CPU_REG_FILE),
+				   MCP_REG_CPU_REG_FILE_SIZE,
+				   false, 0, false, "MCP", 0);
+
+	/* Dump MCP registers */
+	block_enable[BLOCK_MCP] = true;
+	offset += qed_grc_dump_registers(p_hwfn,
+					 p_ptt,
+					 dump_buf + offset,
+					 dump, block_enable, "MCP");
+
+	/* Dump required non-MCP registers */
+	offset += qed_grc_dump_regs_hdr(dump_buf + offset,
+					dump, 1, SPLIT_TYPE_NONE, 0,
+					"MCP");
+	addr = BYTES_TO_DWORDS(MISC_REG_SHARED_MEM_ADDR);
+	offset += qed_grc_dump_reg_entry(p_hwfn,
+					 p_ptt,
+					 dump_buf + offset,
+					 dump,
+					 addr,
+					 1,
+					 false, SPLIT_TYPE_NONE, 0);
+
+	/* Release MCP */
+	if (halted && ecore_mcp_resume(p_hwfn, p_ptt))
+		DP_NOTICE(p_hwfn, false, "Failed to resume MCP after halt!\n");
+
+	return offset;
+}
+
+/* Dumps the tbus indirect memory for all PHYs.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_grc_dump_phy(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	u32 offset = 0, tbus_lo_offset, tbus_hi_offset;
+	char mem_name[32];
+	u8 phy_id;
+
+	for (phy_id = 0; phy_id < OSAL_ARRAY_SIZE(s_phy_defs); phy_id++) {
+		u32 addr_lo_addr, addr_hi_addr, data_lo_addr, data_hi_addr;
+		struct phy_defs *phy_defs;
+		u8 *bytes_buf;
+
+		phy_defs = &s_phy_defs[phy_id];
+		addr_lo_addr = phy_defs->base_addr +
+			       phy_defs->tbus_addr_lo_addr;
+		addr_hi_addr = phy_defs->base_addr +
+			       phy_defs->tbus_addr_hi_addr;
+		data_lo_addr = phy_defs->base_addr +
+			       phy_defs->tbus_data_lo_addr;
+		data_hi_addr = phy_defs->base_addr +
+			       phy_defs->tbus_data_hi_addr;
+
+		if (snprintf(mem_name, sizeof(mem_name), "tbus_%s",
+			     phy_defs->phy_name) < 0)
+			DP_NOTICE(p_hwfn, false,
+				  "Unexpected debug error: invalid PHY memory name\n");
+
+		offset += qed_grc_dump_mem_hdr(p_hwfn,
+					       dump_buf + offset,
+					       dump,
+					       mem_name,
+					       0,
+					       PHY_DUMP_SIZE_DWORDS,
+					       16, true, mem_name, 0);
+
+		if (!dump) {
+			offset += PHY_DUMP_SIZE_DWORDS;
+			continue;
+		}
+
+		bytes_buf = (u8 *)(dump_buf + offset);
+		for (tbus_hi_offset = 0;
+		     tbus_hi_offset < (NUM_PHY_TBUS_ADDRESSES >> 8);
+		     tbus_hi_offset++) {
+			ecore_wr(p_hwfn, p_ptt, addr_hi_addr, tbus_hi_offset);
+			for (tbus_lo_offset = 0; tbus_lo_offset < 256;
+			     tbus_lo_offset++) {
+				ecore_wr(p_hwfn,
+				       p_ptt, addr_lo_addr, tbus_lo_offset);
+				*(bytes_buf++) = (u8)ecore_rd(p_hwfn,
+							    p_ptt,
+							    data_lo_addr);
+				*(bytes_buf++) = (u8)ecore_rd(p_hwfn,
+							    p_ptt,
+							    data_hi_addr);
+			}
+		}
+
+		offset += PHY_DUMP_SIZE_DWORDS;
+	}
+
+	return offset;
+}
+
+static enum dbg_status qed_find_nvram_image(struct ecore_hwfn *p_hwfn,
+					    struct ecore_ptt *p_ptt,
+					    u32 image_type,
+					    u32 *nvram_offset_bytes,
+					    u32 *nvram_size_bytes);
+
+static enum dbg_status qed_nvram_read(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 nvram_offset_bytes,
+				      u32 nvram_size_bytes, u32 *ret_buf);
+
+/* Dumps the MCP HW dump from NVRAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_mcp_hw_dump(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    u32 *dump_buf, bool dump)
+{
+	u32 hw_dump_offset_bytes = 0, hw_dump_size_bytes = 0;
+	u32 hw_dump_size_dwords = 0, offset = 0;
+	enum dbg_status status;
+
+	/* Read HW dump image from NVRAM */
+	status = qed_find_nvram_image(p_hwfn,
+				      p_ptt,
+				      NVM_TYPE_HW_DUMP_OUT,
+				      &hw_dump_offset_bytes,
+				      &hw_dump_size_bytes);
+	if (status != DBG_STATUS_OK)
+		return 0;
+
+	hw_dump_size_dwords = BYTES_TO_DWORDS(hw_dump_size_bytes);
+
+	/* Dump HW dump image section */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "mcp_hw_dump", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", hw_dump_size_dwords);
+
+	/* Read MCP HW dump image into dump buffer */
+	if (dump && hw_dump_size_dwords) {
+		status = qed_nvram_read(p_hwfn,
+					p_ptt,
+					hw_dump_offset_bytes,
+					hw_dump_size_bytes, dump_buf + offset);
+		if (status != DBG_STATUS_OK) {
+			DP_NOTICE(p_hwfn, false,
+				  "Failed to read MCP HW Dump image from NVRAM\n");
+			return 0;
+		}
+	}
+	offset += hw_dump_size_dwords;
+
+	return offset;
+}
+
+/* Dumps Static Debug data. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_static_debug(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_id, line_id, offset = 0, addr, len;
+
+	/* Don't dump static debug if a debug bus recording is in progress */
+	if (dump && ecore_rd(p_hwfn, p_ptt, DBG_REG_DBG_BLOCK_ON))
+		return 0;
+
+	if (dump) {
+		/* Disable debug bus in all blocks */
+		qed_bus_disable_blocks(p_hwfn, p_ptt);
+
+		qed_bus_reset_dbg_block(p_hwfn, p_ptt);
+		ecore_wr(p_hwfn,
+		       p_ptt, DBG_REG_FRAMING_MODE, DBG_BUS_FRAME_MODE_8HW);
+		ecore_wr(p_hwfn,
+		       p_ptt, DBG_REG_DEBUG_TARGET, DBG_BUS_TARGET_ID_INT_BUF);
+		ecore_wr(p_hwfn, p_ptt, DBG_REG_FULL_MODE, 1);
+		qed_bus_enable_dbg_block(p_hwfn, p_ptt, true);
+	}
+
+	/* Dump all static debug lines for each relevant block */
+	for (block_id = 0; block_id < MAX_BLOCK_ID; block_id++) {
+		const struct dbg_block_chip *block_per_chip;
+		const struct dbg_block *block;
+		bool is_removed, has_dbg_bus;
+		u16 modes_buf_offset;
+		u32 block_dwords;
+
+		block_per_chip =
+		    qed_get_dbg_block_per_chip(p_hwfn, (enum block_id)block_id);
+		is_removed = GET_FIELD(block_per_chip->flags,
+				       DBG_BLOCK_CHIP_IS_REMOVED);
+		has_dbg_bus = GET_FIELD(block_per_chip->flags,
+					DBG_BLOCK_CHIP_HAS_DBG_BUS);
+
+		/* read+clear for NWS parity is not working, skip NWS block */
+		if (block_id == BLOCK_NWS)
+			continue;
+
+		if (!is_removed && has_dbg_bus &&
+		    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+			      DBG_MODE_HDR_EVAL_MODE) > 0) {
+			modes_buf_offset =
+			    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+				      DBG_MODE_HDR_MODES_BUF_OFFSET);
+			if (!qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				has_dbg_bus = false;
+		}
+
+		if (is_removed || !has_dbg_bus)
+			continue;
+
+		block_dwords = NUM_DBG_LINES(block_per_chip) *
+			       STATIC_DEBUG_LINE_DWORDS;
+
+		/* Dump static section params */
+		block = get_dbg_block(p_hwfn, (enum block_id)block_id);
+		offset += qed_grc_dump_mem_hdr(p_hwfn,
+					       dump_buf + offset,
+					       dump,
+					       (const char *)block->name,
+					       0,
+					       block_dwords,
+					       32, false, "STATIC", 0);
+
+		if (!dump) {
+			offset += block_dwords;
+			continue;
+		}
+
+		/* If all lines are invalid - dump zeros */
+		if (dev_data->block_in_reset[block_id]) {
+			memset(dump_buf + offset, 0,
+			       DWORDS_TO_BYTES(block_dwords));
+			offset += block_dwords;
+			continue;
+		}
+
+		/* Enable block's client */
+		qed_bus_enable_clients(p_hwfn,
+				       p_ptt,
+				       OSAL_BIT(block_per_chip->dbg_client_id));
+
+		addr = BYTES_TO_DWORDS(DBG_REG_CALENDAR_OUT_DATA);
+		len = STATIC_DEBUG_LINE_DWORDS;
+		for (line_id = 0; line_id < (u32)NUM_DBG_LINES(block_per_chip);
+		     line_id++) {
+			/* Configure debug line ID */
+			qed_bus_config_dbg_line(p_hwfn,
+						p_ptt,
+						(enum block_id)block_id,
+						(u8)line_id, 0xf, 0, 0, 0);
+
+			/* Read debug line info */
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  addr,
+							  len,
+							  true, SPLIT_TYPE_NONE,
+							  0);
+		}
+
+		/* Disable block's client and debug output */
+		qed_bus_enable_clients(p_hwfn, p_ptt, 0);
+		qed_bus_config_dbg_line(p_hwfn, p_ptt,
+					(enum block_id)block_id, 0, 0, 0, 0, 0);
+	}
+
+	if (dump) {
+		qed_bus_enable_dbg_block(p_hwfn, p_ptt, false);
+		qed_bus_enable_clients(p_hwfn, p_ptt, 0);
+	}
+
+	return offset;
+}
+
+/* Performs GRC Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static enum dbg_status qed_grc_dump(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    u32 *dump_buf,
+				    bool dump, u32 *num_dumped_dwords)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 dwords_read, offset = 0;
+	bool parities_masked = false;
+	u8 i;
+
+	*num_dumped_dwords = 0;
+	dev_data->num_regs_read = 0;
+
+	/* Update reset state */
+	if (dump)
+		qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 4);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "grc-dump");
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "num-lcids",
+				     NUM_OF_LCIDS);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "num-ltids",
+				     NUM_OF_LTIDS);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "num-ports", dev_data->num_ports);
+
+	/* Dump reset registers (dumped before taking blocks out of reset ) */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS))
+		offset += qed_grc_dump_reset_regs(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset, dump);
+
+	/* Take all blocks out of reset (using reset registers) */
+	if (dump) {
+		qed_grc_unreset_blocks(p_hwfn, p_ptt, false);
+		qed_update_blocks_reset_state(p_hwfn, p_ptt);
+	}
+
+	/* Disable all parities using MFW command */
+	if (dump &&
+	    !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP)) {
+		parities_masked = !ecore_mcp_mask_parities(p_hwfn, p_ptt, 1);
+		if (!parities_masked) {
+			DP_NOTICE(p_hwfn, false,
+				  "Failed to mask parities using MFW\n");
+			if (qed_grc_get_param
+			    (p_hwfn, DBG_GRC_PARAM_PARITY_SAFE))
+				return DBG_STATUS_MCP_COULD_NOT_MASK_PRTY;
+		}
+	}
+
+	/* Dump modified registers (dumped before modifying them) */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS))
+		offset += qed_grc_dump_modified_regs(p_hwfn,
+						     p_ptt,
+						     dump_buf + offset, dump);
+
+	/* Stall storms */
+	if (dump &&
+	    (qed_grc_is_included(p_hwfn,
+				 DBG_GRC_PARAM_DUMP_IOR) ||
+	     qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_VFC)))
+		qed_grc_stall_storms(p_hwfn, p_ptt, true);
+
+	/* Dump all regs  */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS)) {
+		bool block_enable[MAX_BLOCK_ID];
+
+		/* Dump all blocks except MCP */
+		for (i = 0; i < MAX_BLOCK_ID; i++)
+			block_enable[i] = true;
+		block_enable[BLOCK_MCP] = false;
+		offset += qed_grc_dump_registers(p_hwfn,
+						 p_ptt,
+						 dump_buf +
+						 offset,
+						 dump,
+						 block_enable, NULL);
+
+		/* Dump special registers */
+		offset += qed_grc_dump_special_regs(p_hwfn,
+						    p_ptt,
+						    dump_buf + offset, dump);
+	}
+
+	/* Dump memories */
+	offset += qed_grc_dump_memories(p_hwfn, p_ptt, dump_buf + offset, dump);
+
+	/* Dump MCP */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MCP))
+		offset += qed_grc_dump_mcp(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump context */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM_CTX))
+		offset += qed_grc_dump_ctx(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump RSS memories */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_RSS))
+		offset += qed_grc_dump_rss(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump Big RAM */
+	for (i = 0; i < NUM_BIG_RAM_TYPES; i++)
+		if (qed_grc_is_included(p_hwfn, s_big_ram_defs[i].grc_param))
+			offset += qed_grc_dump_big_ram(p_hwfn,
+						       p_ptt,
+						       dump_buf + offset,
+						       dump, i);
+
+	/* Dump VFC */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_VFC)) {
+		dwords_read = qed_grc_dump_vfc(p_hwfn,
+					       p_ptt, dump_buf + offset, dump);
+		offset += dwords_read;
+		if (!dwords_read)
+			return DBG_STATUS_VFC_READ_ERROR;
+	}
+
+	/* Dump PHY tbus */
+	if (qed_grc_is_included(p_hwfn,
+				DBG_GRC_PARAM_DUMP_PHY) && dev_data->chip_id ==
+	    CHIP_K2 && dev_data->hw_type == HW_TYPE_ASIC)
+		offset += qed_grc_dump_phy(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump MCP HW Dump */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MCP_HW_DUMP) &&
+	    !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP) && 1)
+		offset += qed_grc_dump_mcp_hw_dump(p_hwfn,
+						   p_ptt,
+						   dump_buf + offset, dump);
+
+	/* Dump static debug data (only if not during debug bus recording) */
+	if (qed_grc_is_included(p_hwfn,
+				DBG_GRC_PARAM_DUMP_STATIC) &&
+	    (!dump || dev_data->bus.state == DBG_BUS_STATE_IDLE))
+		offset += qed_grc_dump_static_debug(p_hwfn,
+						    p_ptt,
+						    dump_buf + offset, dump);
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	if (dump) {
+		/* Unstall storms */
+		if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_UNSTALL))
+			qed_grc_stall_storms(p_hwfn, p_ptt, false);
+
+		/* Clear parity status */
+		qed_grc_clear_all_prty(p_hwfn, p_ptt);
+
+		/* Enable all parities using MFW command */
+		if (parities_masked)
+			ecore_mcp_mask_parities(p_hwfn, p_ptt, 0);
+	}
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Writes the specified failing Idle Check rule to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_idle_chk_dump_failure(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     u32 *
+				     dump_buf,
+				     bool dump,
+				     u16 rule_id,
+				     const struct dbg_idle_chk_rule *rule,
+				     u16 fail_entry_id, u32 *cond_reg_values)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	const struct dbg_idle_chk_cond_reg *cond_regs;
+	const struct dbg_idle_chk_info_reg *info_regs;
+	u32 i, next_reg_offset = 0, offset = 0;
+	struct dbg_idle_chk_result_hdr *hdr;
+	const union dbg_idle_chk_reg *regs;
+	u8 reg_id;
+
+	hdr = (struct dbg_idle_chk_result_hdr *)dump_buf;
+	regs = (const union dbg_idle_chk_reg *)
+		p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr +
+		rule->reg_offset;
+	cond_regs = &regs[0].cond_reg;
+	info_regs = &regs[rule->num_cond_regs].info_reg;
+
+	/* Dump rule data */
+	if (dump) {
+		memset(hdr, 0, sizeof(*hdr));
+		hdr->rule_id = rule_id;
+		hdr->mem_entry_id = fail_entry_id;
+		hdr->severity = rule->severity;
+		hdr->num_dumped_cond_regs = rule->num_cond_regs;
+	}
+
+	offset += IDLE_CHK_RESULT_HDR_DWORDS;
+
+	/* Dump condition register values */
+	for (reg_id = 0; reg_id < rule->num_cond_regs; reg_id++) {
+		const struct dbg_idle_chk_cond_reg *reg = &cond_regs[reg_id];
+		struct dbg_idle_chk_result_reg_hdr *reg_hdr;
+
+		reg_hdr =
+		    (struct dbg_idle_chk_result_reg_hdr *)(dump_buf + offset);
+
+		/* Write register header */
+		if (!dump) {
+			offset += IDLE_CHK_RESULT_REG_HDR_DWORDS +
+			    reg->entry_size;
+			continue;
+		}
+
+		offset += IDLE_CHK_RESULT_REG_HDR_DWORDS;
+		memset(reg_hdr, 0, sizeof(*reg_hdr));
+		reg_hdr->start_entry = reg->start_entry;
+		reg_hdr->size = reg->entry_size;
+		SET_FIELD(reg_hdr->data,
+			  DBG_IDLE_CHK_RESULT_REG_HDR_IS_MEM,
+			  reg->num_entries > 1 || reg->start_entry > 0 ? 1 : 0);
+		SET_FIELD(reg_hdr->data,
+			  DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID, reg_id);
+
+		/* Write register values */
+		for (i = 0; i < reg_hdr->size; i++, next_reg_offset++, offset++)
+			dump_buf[offset] = cond_reg_values[next_reg_offset];
+	}
+
+	/* Dump info register values */
+	for (reg_id = 0; reg_id < rule->num_info_regs; reg_id++) {
+		const struct dbg_idle_chk_info_reg *reg = &info_regs[reg_id];
+		u32 block_id;
+
+		/* Check if register's block is in reset */
+		if (!dump) {
+			offset += IDLE_CHK_RESULT_REG_HDR_DWORDS + reg->size;
+			continue;
+		}
+
+		block_id = GET_FIELD(reg->data, DBG_IDLE_CHK_INFO_REG_BLOCK_ID);
+		if (block_id >= MAX_BLOCK_ID) {
+			DP_NOTICE(p_hwfn, false, "Invalid block_id\n");
+			return 0;
+		}
+
+		if (!dev_data->block_in_reset[block_id]) {
+			struct dbg_idle_chk_result_reg_hdr *reg_hdr;
+			bool wide_bus, eval_mode, mode_match = true;
+			u16 modes_buf_offset;
+			u32 addr;
+
+			reg_hdr = (struct dbg_idle_chk_result_reg_hdr *)
+				  (dump_buf + offset);
+
+			/* Check mode */
+			eval_mode = GET_FIELD(reg->mode.data,
+					      DBG_MODE_HDR_EVAL_MODE) > 0;
+			if (eval_mode) {
+				modes_buf_offset =
+				    GET_FIELD(reg->mode.data,
+					      DBG_MODE_HDR_MODES_BUF_OFFSET);
+				mode_match =
+					qed_is_mode_match(p_hwfn,
+							  &modes_buf_offset);
+			}
+
+			if (!mode_match)
+				continue;
+
+			addr = GET_FIELD(reg->data,
+					 DBG_IDLE_CHK_INFO_REG_ADDRESS);
+			wide_bus = GET_FIELD(reg->data,
+					     DBG_IDLE_CHK_INFO_REG_WIDE_BUS);
+
+			/* Write register header */
+			offset += IDLE_CHK_RESULT_REG_HDR_DWORDS;
+			hdr->num_dumped_info_regs++;
+			memset(reg_hdr, 0, sizeof(*reg_hdr));
+			reg_hdr->size = reg->size;
+			SET_FIELD(reg_hdr->data,
+				  DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID,
+				  rule->num_cond_regs + reg_id);
+
+			/* Write register values */
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  addr,
+							  reg->size, wide_bus,
+							  SPLIT_TYPE_NONE, 0);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps idle check rule entries. Returns the dumped size in dwords. */
+static u32
+qed_idle_chk_dump_rule_entries(struct ecore_hwfn *p_hwfn,
+			       struct ecore_ptt *p_ptt,
+			       u32 *dump_buf, bool dump,
+			       const struct dbg_idle_chk_rule *input_rules,
+			       u32 num_input_rules, u32 *num_failing_rules)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 cond_reg_values[IDLE_CHK_MAX_ENTRIES_SIZE];
+	u32 i, offset = 0;
+	u16 entry_id;
+	u8 reg_id;
+
+	*num_failing_rules = 0;
+
+	for (i = 0; i < num_input_rules; i++) {
+		const struct dbg_idle_chk_cond_reg *cond_regs;
+		const struct dbg_idle_chk_rule *rule;
+		const union dbg_idle_chk_reg *regs;
+		u16 num_reg_entries = 1;
+		bool check_rule = true;
+		const u32 *imm_values;
+
+		rule = &input_rules[i];
+		regs = (const union dbg_idle_chk_reg *)
+			p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr +
+			rule->reg_offset;
+		cond_regs = &regs[0].cond_reg;
+		imm_values =
+		    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_IMMS].ptr +
+		    rule->imm_offset;
+
+		/* Check if all condition register blocks are out of reset, and
+		 * find maximal number of entries (all condition registers that
+		 * are memories must have the same size, which is > 1).
+		 */
+		for (reg_id = 0; reg_id < rule->num_cond_regs && check_rule;
+		     reg_id++) {
+			u32 block_id =
+				GET_FIELD(cond_regs[reg_id].data,
+					  DBG_IDLE_CHK_COND_REG_BLOCK_ID);
+
+			if (block_id >= MAX_BLOCK_ID) {
+				DP_NOTICE(p_hwfn, false, "Invalid block_id\n");
+				return 0;
+			}
+
+			check_rule = !dev_data->block_in_reset[block_id];
+			if (cond_regs[reg_id].num_entries > num_reg_entries)
+				num_reg_entries = cond_regs[reg_id].num_entries;
+		}
+
+		if (!check_rule && dump)
+			continue;
+
+		if (!dump) {
+			u32 entry_dump_size =
+				qed_idle_chk_dump_failure(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  false,
+							  rule->rule_id,
+							  rule,
+							  0,
+							  NULL);
+
+			offset += num_reg_entries * entry_dump_size;
+			(*num_failing_rules) += num_reg_entries;
+			continue;
+		}
+
+		/* Go over all register entries (number of entries is the same
+		 * for all condition registers).
+		 */
+		for (entry_id = 0; entry_id < num_reg_entries; entry_id++) {
+			u32 next_reg_offset = 0;
+
+			/* Read current entry of all condition registers */
+			for (reg_id = 0; reg_id < rule->num_cond_regs;
+			     reg_id++) {
+				const struct dbg_idle_chk_cond_reg *reg =
+					&cond_regs[reg_id];
+				u32 padded_entry_size, addr;
+				bool wide_bus;
+
+				/* Find GRC address (if it's a memory, the
+				 * address of the specific entry is calculated).
+				 */
+				addr = GET_FIELD(reg->data,
+						 DBG_IDLE_CHK_COND_REG_ADDRESS);
+				wide_bus =
+				    GET_FIELD(reg->data,
+					      DBG_IDLE_CHK_COND_REG_WIDE_BUS);
+				if (reg->num_entries > 1 ||
+				    reg->start_entry > 0) {
+					padded_entry_size =
+					   reg->entry_size > 1 ?
+					   OSAL_ROUNDUP_POW_OF_TWO(reg->entry_size) :
+					   1;
+					addr += (reg->start_entry + entry_id) *
+						padded_entry_size;
+				}
+
+				/* Read registers */
+				if (next_reg_offset + reg->entry_size >=
+				    IDLE_CHK_MAX_ENTRIES_SIZE) {
+					DP_NOTICE(p_hwfn, false,
+						  "idle check registers entry is too large\n");
+					return 0;
+				}
+
+				next_reg_offset +=
+				    qed_grc_dump_addr_range(p_hwfn, p_ptt,
+							    cond_reg_values +
+							    next_reg_offset,
+							    dump, addr,
+							    reg->entry_size,
+							    wide_bus,
+							    SPLIT_TYPE_NONE, 0);
+			}
+
+			/* Call rule condition function.
+			 * If returns true, it's a failure.
+			 */
+			if ((*cond_arr[rule->cond_id]) (cond_reg_values,
+							imm_values)) {
+				offset += qed_idle_chk_dump_failure(p_hwfn,
+							p_ptt,
+							dump_buf + offset,
+							dump,
+							rule->rule_id,
+							rule,
+							entry_id,
+							cond_reg_values);
+				(*num_failing_rules)++;
+			}
+		}
+	}
+
+	return offset;
+}
+
+/* Performs Idle Check Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+			     struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	struct virt_mem_desc *dbg_buf =
+	    &p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_RULES];
+	u32 num_failing_rules_offset, offset = 0,
+	    input_offset = 0, num_failing_rules = 0;
+
+	/* Dump global params  - 1 must match below amount of params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "idle-chk");
+
+	/* Dump idle check section header with a single parameter */
+	offset += qed_dump_section_hdr(dump_buf + offset, dump, "idle_chk", 1);
+	num_failing_rules_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "num_rules", 0);
+
+	while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
+		const struct dbg_idle_chk_cond_hdr *cond_hdr =
+		    (const struct dbg_idle_chk_cond_hdr *)dbg_buf->ptr +
+		    input_offset++;
+		bool eval_mode, mode_match = true;
+		u32 curr_failing_rules;
+		u16 modes_buf_offset;
+
+		/* Check mode */
+		eval_mode = GET_FIELD(cond_hdr->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		if (eval_mode) {
+			modes_buf_offset =
+				GET_FIELD(cond_hdr->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			mode_match = qed_is_mode_match(p_hwfn,
+						       &modes_buf_offset);
+		}
+
+		if (mode_match) {
+			const struct dbg_idle_chk_rule *rule =
+			    (const struct dbg_idle_chk_rule *)((u32 *)
+							       dbg_buf->ptr
+							       + input_offset);
+			u32 num_input_rules =
+				cond_hdr->data_size / IDLE_CHK_RULE_SIZE_DWORDS;
+			offset +=
+			    qed_idle_chk_dump_rule_entries(p_hwfn,
+							   p_ptt,
+							   dump_buf +
+							   offset,
+							   dump,
+							   rule,
+							   num_input_rules,
+							   &curr_failing_rules);
+			num_failing_rules += curr_failing_rules;
+		}
+
+		input_offset += cond_hdr->data_size;
+	}
+
+	/* Overwrite num_rules parameter */
+	if (dump)
+		qed_dump_num_param(dump_buf + num_failing_rules_offset,
+				   dump, "num_rules", num_failing_rules);
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	return offset;
+}
+
+/* Finds the meta data image in NVRAM */
+static enum dbg_status qed_find_nvram_image(struct ecore_hwfn *p_hwfn,
+					    struct ecore_ptt *p_ptt,
+					    u32 image_type,
+					    u32 *nvram_offset_bytes,
+					    u32 *nvram_size_bytes)
+{
+	u32 ret_mcp_resp, ret_mcp_param, ret_txn_size;
+	struct mcp_file_att file_att;
+	int nvm_result;
+
+	/* Call NVRAM get file command */
+	nvm_result = ecore_mcp_nvm_rd_cmd(p_hwfn,
+					p_ptt,
+					DRV_MSG_CODE_NVM_GET_FILE_ATT,
+					image_type,
+					&ret_mcp_resp,
+					&ret_mcp_param,
+					&ret_txn_size, (u32 *)&file_att);
+
+	/* Check response */
+	if (nvm_result ||
+	    (ret_mcp_resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_NVM_OK)
+		return DBG_STATUS_NVRAM_GET_IMAGE_FAILED;
+
+	/* Update return values */
+	*nvram_offset_bytes = file_att.nvm_start_addr;
+	*nvram_size_bytes = file_att.len;
+
+	DP_VERBOSE(p_hwfn->p_dev,
+		   ECORE_MSG_DEBUG,
+		   "find_nvram_image: found NVRAM image of type %d in NVRAM offset %d bytes with size %d bytes\n",
+		   image_type, *nvram_offset_bytes, *nvram_size_bytes);
+
+	/* Check alignment */
+	if (*nvram_size_bytes & 0x3)
+		return DBG_STATUS_NON_ALIGNED_NVRAM_IMAGE;
+
+	return DBG_STATUS_OK;
+}
+
+/* Reads data from NVRAM */
+static enum dbg_status qed_nvram_read(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 nvram_offset_bytes,
+				      u32 nvram_size_bytes, u32 *ret_buf)
+{
+	u32 ret_mcp_resp, ret_mcp_param, ret_read_size, bytes_to_copy;
+	s32 bytes_left = nvram_size_bytes;
+	u32 read_offset = 0, param = 0;
+
+	DP_NOTICE(p_hwfn->p_dev, false,
+		   "nvram_read: reading image of size %d bytes from NVRAM\n",
+		   nvram_size_bytes);
+
+	do {
+		bytes_to_copy =
+		    (bytes_left >
+		     MCP_DRV_NVM_BUF_LEN) ? MCP_DRV_NVM_BUF_LEN : bytes_left;
+
+		/* Call NVRAM read command */
+		SET_MFW_FIELD(param,
+			      DRV_MB_PARAM_NVM_OFFSET,
+			      nvram_offset_bytes + read_offset);
+		SET_MFW_FIELD(param, DRV_MB_PARAM_NVM_LEN, bytes_to_copy);
+		if (ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt,
+					 DRV_MSG_CODE_NVM_READ_NVRAM, param,
+					 &ret_mcp_resp,
+					 &ret_mcp_param, &ret_read_size,
+					 (u32 *)((u8 *)ret_buf +
+						 read_offset))) {
+			DP_NOTICE(p_hwfn->p_dev, false, "rc = DBG_STATUS_NVRAM_READ_FAILED\n");
+			return DBG_STATUS_NVRAM_READ_FAILED;
+		}
+
+		/* Check response */
+		if ((ret_mcp_resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_NVM_OK) {
+			DP_NOTICE(p_hwfn->p_dev, false, "rc = DBG_STATUS_NVRAM_READ_FAILED\n");
+			return DBG_STATUS_NVRAM_READ_FAILED;
+		}
+
+		/* Update read offset */
+		read_offset += ret_read_size;
+		bytes_left -= ret_read_size;
+	} while (bytes_left > 0);
+
+	return DBG_STATUS_OK;
+}
+
+/* Get info on the MCP Trace data in the scratchpad:
+ * - trace_data_grc_addr (OUT): trace data GRC address in bytes
+ * - trace_data_size (OUT): trace data size in bytes (without the header)
+ */
+static enum dbg_status qed_mcp_trace_get_data_info(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *trace_data_grc_addr,
+						   u32 *trace_data_size)
+{
+	u32 spad_trace_offsize, signature;
+
+	/* Read trace section offsize structure from MCP scratchpad */
+	spad_trace_offsize = ecore_rd(p_hwfn, p_ptt,
+				      MCP_SPAD_TRACE_OFFSIZE_ADDR);
+
+	/* Extract trace section address from offsize (in scratchpad) */
+	*trace_data_grc_addr =
+		MCP_REG_SCRATCH + SECTION_OFFSET(spad_trace_offsize);
+
+	/* Read signature from MCP trace section */
+	signature = ecore_rd(p_hwfn, p_ptt,
+			   *trace_data_grc_addr +
+			   offsetof(struct mcp_trace, signature));
+
+	if (signature != MFW_TRACE_SIGNATURE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Read trace size from MCP trace section */
+	*trace_data_size = ecore_rd(p_hwfn,
+				  p_ptt,
+				  *trace_data_grc_addr +
+				  offsetof(struct mcp_trace, size));
+
+	return DBG_STATUS_OK;
+}
+
+/* Reads MCP trace meta data image from NVRAM
+ * - running_bundle_id (OUT): running bundle ID (invalid when loaded from file)
+ * - trace_meta_offset (OUT): trace meta offset in NVRAM in bytes (invalid when
+ *			      loaded from file).
+ * - trace_meta_size (OUT):   size in bytes of the trace meta data.
+ */
+static enum dbg_status qed_mcp_trace_get_meta_info(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 trace_data_size_bytes,
+						   u32 *running_bundle_id,
+						   u32 *trace_meta_offset,
+						   u32 *trace_meta_size)
+{
+	u32 spad_trace_offsize, nvram_image_type, running_mfw_addr;
+
+	/* Read MCP trace section offsize structure from MCP scratchpad */
+	spad_trace_offsize = ecore_rd(p_hwfn, p_ptt,
+				      MCP_SPAD_TRACE_OFFSIZE_ADDR);
+
+	/* Find running bundle ID */
+	running_mfw_addr =
+		MCP_REG_SCRATCH + SECTION_OFFSET(spad_trace_offsize) +
+		SECTION_SIZE(spad_trace_offsize) + trace_data_size_bytes;
+	*running_bundle_id = ecore_rd(p_hwfn, p_ptt, running_mfw_addr);
+	if (*running_bundle_id > 1)
+		return DBG_STATUS_INVALID_NVRAM_BUNDLE;
+
+	/* Find image in NVRAM */
+	nvram_image_type =
+	    (*running_bundle_id ==
+	     DIR_ID_1) ? NVM_TYPE_MFW_TRACE1 : NVM_TYPE_MFW_TRACE2;
+	return qed_find_nvram_image(p_hwfn,
+				    p_ptt,
+				    nvram_image_type,
+				    trace_meta_offset, trace_meta_size);
+}
+
+/* Reads the MCP Trace meta data from NVRAM into the specified buffer */
+static enum dbg_status qed_mcp_trace_read_meta(struct ecore_hwfn *p_hwfn,
+					       struct ecore_ptt *p_ptt,
+					       u32 nvram_offset_in_bytes,
+					       u32 size_in_bytes, u32 *buf)
+{
+	u8 modules_num, module_len, i, *byte_buf = (u8 *)buf;
+	enum dbg_status status;
+	u32 signature;
+
+	/* Read meta data from NVRAM */
+	status = qed_nvram_read(p_hwfn,
+				p_ptt,
+				nvram_offset_in_bytes, size_in_bytes, buf);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Extract and check first signature */
+	signature = qed_read_unaligned_dword(byte_buf);
+	byte_buf += sizeof(signature);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Extract number of modules */
+	modules_num = *(byte_buf++);
+
+	/* Skip all modules */
+	for (i = 0; i < modules_num; i++) {
+		module_len = *(byte_buf++);
+		byte_buf += module_len;
+	}
+
+	/* Extract and check second signature */
+	signature = qed_read_unaligned_dword(byte_buf);
+	byte_buf += sizeof(signature);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	return DBG_STATUS_OK;
+}
+
+/* Dump MCP Trace */
+static enum dbg_status qed_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+					  struct ecore_ptt *p_ptt,
+					  u32 *dump_buf,
+					  bool dump, u32 *num_dumped_dwords)
+{
+	u32 trace_data_grc_addr, trace_data_size_bytes, trace_data_size_dwords;
+	u32 trace_meta_size_dwords = 0, running_bundle_id, offset = 0;
+	u32 trace_meta_offset_bytes = 0, trace_meta_size_bytes = 0;
+	enum dbg_status status;
+	int halted = 0;
+	bool use_mfw;
+
+	*num_dumped_dwords = 0;
+
+	use_mfw = !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP);
+
+	/* Get trace data info */
+	status = qed_mcp_trace_get_data_info(p_hwfn,
+					     p_ptt,
+					     &trace_data_grc_addr,
+					     &trace_data_size_bytes);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "mcp-trace");
+
+	/* Halt MCP while reading from scratchpad so the read data will be
+	 * consistent. if halt fails, MCP trace is taken anyway, with a small
+	 * risk that it may be corrupt.
+	 */
+	if (dump && use_mfw) {
+		halted = !ecore_mcp_halt(p_hwfn, p_ptt);
+		if (!halted)
+			DP_NOTICE(p_hwfn, false, "MCP halt failed!\n");
+	}
+
+	/* Find trace data size */
+	trace_data_size_dwords =
+	    DIV_ROUND_UP(trace_data_size_bytes + sizeof(struct mcp_trace),
+			 BYTES_IN_DWORD);
+
+	/* Dump trace data section header and param */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "mcp_trace_data", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", trace_data_size_dwords);
+
+	/* Read trace data from scratchpad into dump buffer */
+	offset += qed_grc_dump_addr_range(p_hwfn,
+					  p_ptt,
+					  dump_buf + offset,
+					  dump,
+					  BYTES_TO_DWORDS(trace_data_grc_addr),
+					  trace_data_size_dwords, false,
+					  SPLIT_TYPE_NONE, 0);
+
+	/* Resume MCP (only if halt succeeded) */
+	if (halted && ecore_mcp_resume(p_hwfn, p_ptt))
+		DP_NOTICE(p_hwfn, false, "Failed to resume MCP after halt!\n");
+
+	/* Dump trace meta section header */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "mcp_trace_meta", 1);
+
+	/* If MCP Trace meta size parameter was set, use it.
+	 * Otherwise, read trace meta.
+	 * trace_meta_size_bytes is dword-aligned.
+	 */
+	trace_meta_size_bytes =
+		qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_MCP_TRACE_META_SIZE);
+	if ((!trace_meta_size_bytes || dump) && use_mfw)
+		status = qed_mcp_trace_get_meta_info(p_hwfn,
+						     p_ptt,
+						     trace_data_size_bytes,
+						     &running_bundle_id,
+						     &trace_meta_offset_bytes,
+						     &trace_meta_size_bytes);
+	if (status == DBG_STATUS_OK)
+		trace_meta_size_dwords = BYTES_TO_DWORDS(trace_meta_size_bytes);
+
+	/* Dump trace meta size param */
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", trace_meta_size_dwords);
+
+	/* Read trace meta image into dump buffer */
+	if (dump && trace_meta_size_dwords)
+		status = qed_mcp_trace_read_meta(p_hwfn,
+						 p_ptt,
+						 trace_meta_offset_bytes,
+						 trace_meta_size_bytes,
+						 dump_buf + offset);
+	if (status == DBG_STATUS_OK)
+		offset += trace_meta_size_dwords;
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	/* If no mcp access, indicate that the dump doesn't contain the meta
+	 * data from NVRAM.
+	 */
+	return use_mfw ? status : DBG_STATUS_NVRAM_GET_IMAGE_FAILED;
+}
+
+/* Dump GRC FIFO */
+static enum dbg_status qed_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
+					 struct ecore_ptt *p_ptt,
+					 u32 *dump_buf,
+					 bool dump, u32 *num_dumped_dwords)
+{
+	u32 dwords_read, size_param_offset, offset = 0, addr, len;
+	bool fifo_has_data;
+
+	*num_dumped_dwords = 0;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "reg-fifo");
+
+	/* Dump fifo data section header and param. The size param is 0 for
+	 * now, and is overwritten after reading the FIFO.
+	 */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "reg_fifo_data", 1);
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+
+	if (!dump) {
+		/* FIFO max size is REG_FIFO_DEPTH_DWORDS. There is no way to
+		 * test how much data is available, except for reading it.
+		 */
+		offset += REG_FIFO_DEPTH_DWORDS;
+		goto out;
+	}
+
+	fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+			       GRC_REG_TRACE_FIFO_VALID_DATA) > 0;
+
+	/* Pull available data from fifo. Use DMAE since this is widebus memory
+	 * and must be accessed atomically. Test for dwords_read not passing
+	 * buffer size since more entries could be added to the buffer as we are
+	 * emptying it.
+	 */
+	addr = BYTES_TO_DWORDS(GRC_REG_TRACE_FIFO);
+	len = REG_FIFO_ELEMENT_DWORDS;
+	for (dwords_read = 0;
+	     fifo_has_data && dwords_read < REG_FIFO_DEPTH_DWORDS;
+	     dwords_read += REG_FIFO_ELEMENT_DWORDS) {
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  true,
+						  addr,
+						  len,
+						  true, SPLIT_TYPE_NONE,
+						  0);
+		fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+				       GRC_REG_TRACE_FIFO_VALID_DATA) > 0;
+	}
+
+	qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
+			   dwords_read);
+out:
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Dump IGU FIFO */
+static enum dbg_status qed_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
+					 struct ecore_ptt *p_ptt,
+					 u32 *dump_buf,
+					 bool dump, u32 *num_dumped_dwords)
+{
+	u32 dwords_read, size_param_offset, offset = 0, addr, len;
+	bool fifo_has_data;
+
+	*num_dumped_dwords = 0;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "igu-fifo");
+
+	/* Dump fifo data section header and param. The size param is 0 for
+	 * now, and is overwritten after reading the FIFO.
+	 */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "igu_fifo_data", 1);
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+
+	if (!dump) {
+		/* FIFO max size is IGU_FIFO_DEPTH_DWORDS. There is no way to
+		 * test how much data is available, except for reading it.
+		 */
+		offset += IGU_FIFO_DEPTH_DWORDS;
+		goto out;
+	}
+
+	fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+			       IGU_REG_ERROR_HANDLING_DATA_VALID) > 0;
+
+	/* Pull available data from fifo. Use DMAE since this is widebus memory
+	 * and must be accessed atomically. Test for dwords_read not passing
+	 * buffer size since more entries could be added to the buffer as we are
+	 * emptying it.
+	 */
+	addr = BYTES_TO_DWORDS(IGU_REG_ERROR_HANDLING_MEMORY);
+	len = IGU_FIFO_ELEMENT_DWORDS;
+	for (dwords_read = 0;
+	     fifo_has_data && dwords_read < IGU_FIFO_DEPTH_DWORDS;
+	     dwords_read += IGU_FIFO_ELEMENT_DWORDS) {
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  true,
+						  addr,
+						  len,
+						  true, SPLIT_TYPE_NONE,
+						  0);
+		fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+				       IGU_REG_ERROR_HANDLING_DATA_VALID) > 0;
+	}
+
+	qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
+			   dwords_read);
+out:
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Protection Override dump */
+static enum dbg_status qed_protection_override_dump(struct ecore_hwfn *p_hwfn,
+						    struct ecore_ptt *p_ptt,
+						    u32 *dump_buf,
+						    bool dump,
+						    u32 *num_dumped_dwords)
+{
+	u32 size_param_offset, override_window_dwords, offset = 0, addr;
+
+	*num_dumped_dwords = 0;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "protection-override");
+
+	/* Dump data section header and param. The size param is 0 for now,
+	 * and is overwritten after reading the data.
+	 */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "protection_override_data", 1);
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+
+	if (!dump) {
+		offset += PROTECTION_OVERRIDE_DEPTH_DWORDS;
+		goto out;
+	}
+
+	/* Add override window info to buffer */
+	override_window_dwords =
+		ecore_rd(p_hwfn, p_ptt, GRC_REG_NUMBER_VALID_OVERRIDE_WINDOW) *
+		PROTECTION_OVERRIDE_ELEMENT_DWORDS;
+	if (override_window_dwords) {
+		addr = BYTES_TO_DWORDS(GRC_REG_PROTECTION_OVERRIDE_WINDOW);
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  true,
+						  addr,
+						  override_window_dwords,
+						  true, SPLIT_TYPE_NONE, 0);
+		qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
+				   override_window_dwords);
+	}
+out:
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Performs FW Asserts Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
+			       struct ecore_ptt *p_ptt, u32 *dump_buf,
+			       bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	struct fw_asserts_ram_section *asserts;
+	char storm_letter_str[2] = "?";
+	struct fw_info fw_info;
+	u32 offset = 0;
+	u8 storm_id;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "fw-asserts");
+
+	/* Find Storm dump size */
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		u32 fw_asserts_section_addr, next_list_idx_addr, next_list_idx;
+		struct storm_defs *storm = &s_storm_defs[storm_id];
+		u32 last_list_idx, addr;
+
+		if (dev_data->block_in_reset[storm->sem_block_id])
+			continue;
+
+		/* Read FW info for the current Storm */
+		qed_read_storm_fw_info(p_hwfn, p_ptt, storm_id, &fw_info);
+
+		asserts = &fw_info.fw_asserts_section;
+
+		/* Dump FW Asserts section header and params */
+		storm_letter_str[0] = storm->letter;
+		offset += qed_dump_section_hdr(dump_buf + offset,
+					       dump, "fw_asserts", 2);
+		offset += qed_dump_str_param(dump_buf + offset,
+					     dump, "storm", storm_letter_str);
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump,
+					     "size",
+					     asserts->list_element_dword_size);
+
+		/* Read and dump FW Asserts data */
+		if (!dump) {
+			offset += asserts->list_element_dword_size;
+			continue;
+		}
+
+		fw_asserts_section_addr = storm->sem_fast_mem_addr +
+			SEM_FAST_REG_INT_RAM +
+			RAM_LINES_TO_BYTES(asserts->section_ram_line_offset);
+		next_list_idx_addr = fw_asserts_section_addr +
+			DWORDS_TO_BYTES(asserts->list_next_index_dword_offset);
+		next_list_idx = ecore_rd(p_hwfn, p_ptt, next_list_idx_addr);
+		last_list_idx = (next_list_idx > 0 ?
+				 next_list_idx :
+				 asserts->list_num_elements) - 1;
+		addr = BYTES_TO_DWORDS(fw_asserts_section_addr) +
+		       asserts->list_dword_offset +
+		       last_list_idx * asserts->list_element_dword_size;
+		offset +=
+		    qed_grc_dump_addr_range(p_hwfn, p_ptt,
+					    dump_buf + offset,
+					    dump, addr,
+					    asserts->list_element_dword_size,
+						  false, SPLIT_TYPE_NONE, 0);
+	}
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	return offset;
+}
+
+/* Dumps the specified ILT pages to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_ilt_dump_pages_range(u32 *dump_buf,
+				    bool dump,
+				    u32 start_page_id,
+				    u32 num_pages,
+				    struct phys_mem_desc *ilt_pages,
+				    bool dump_page_ids)
+{
+	u32 page_id, end_page_id, offset = 0;
+
+	if (num_pages == 0)
+		return offset;
+
+	end_page_id = start_page_id + num_pages - 1;
+
+	for (page_id = start_page_id; page_id <= end_page_id; page_id++) {
+		struct phys_mem_desc *mem_desc = &ilt_pages[page_id];
+
+		/**
+		 *
+		 * if (page_id >= ->p_cxt_mngr->ilt_shadow_size)
+		 *     break;
+		 */
+
+		if (!ilt_pages[page_id].virt_addr)
+			continue;
+
+		if (dump_page_ids) {
+			/* Copy page ID to dump buffer */
+			if (dump)
+				*(dump_buf + offset) = page_id;
+			offset++;
+		} else {
+			/* Copy page memory to dump buffer */
+			if (dump)
+				memcpy(dump_buf + offset,
+				       mem_desc->virt_addr, mem_desc->size);
+			offset += BYTES_TO_DWORDS(mem_desc->size);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps a section containing the dumped ILT pages.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_ilt_dump_pages_section(struct ecore_hwfn *p_hwfn,
+				      u32 *dump_buf,
+				      bool dump,
+				      u32 valid_conn_pf_pages,
+				      u32 valid_conn_vf_pages,
+				      struct phys_mem_desc *ilt_pages,
+				      bool dump_page_ids)
+{
+	struct ecore_ilt_client_cfg *clients = p_hwfn->p_cxt_mngr->clients;
+	u32 pf_start_line, start_page_id, offset = 0;
+	u32 cdut_pf_init_pages, cdut_vf_init_pages;
+	u32 cdut_pf_work_pages, cdut_vf_work_pages;
+	u32 base_data_offset, size_param_offset;
+	u32 cdut_pf_pages, cdut_vf_pages;
+	const char *section_name;
+	u8 i;
+
+	section_name = dump_page_ids ? "ilt_page_ids" : "ilt_page_mem";
+	cdut_pf_init_pages = ecore_get_cdut_num_pf_init_pages(p_hwfn);
+	cdut_vf_init_pages = ecore_get_cdut_num_vf_init_pages(p_hwfn);
+	cdut_pf_work_pages = ecore_get_cdut_num_pf_work_pages(p_hwfn);
+	cdut_vf_work_pages = ecore_get_cdut_num_vf_work_pages(p_hwfn);
+	cdut_pf_pages = cdut_pf_init_pages + cdut_pf_work_pages;
+	cdut_vf_pages = cdut_vf_init_pages + cdut_vf_work_pages;
+	pf_start_line = p_hwfn->p_cxt_mngr->pf_start_line;
+
+	offset +=
+	    qed_dump_section_hdr(dump_buf + offset, dump, section_name, 1);
+
+	/* Dump size parameter (0 for now, overwritten with real size later) */
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+	base_data_offset = offset;
+
+	/* CDUC pages are ordered as follows:
+	 * - PF pages - valid section (included in PF connection type mapping)
+	 * - PF pages - invalid section (not dumped)
+	 * - For each VF in the PF:
+	 *   - VF pages - valid section (included in VF connection type mapping)
+	 *   - VF pages - invalid section (not dumped)
+	 */
+	if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_DUMP_ILT_CDUC)) {
+		/* Dump connection PF pages */
+		start_page_id = clients[ILT_CLI_CDUC].first.val - pf_start_line;
+		offset += qed_ilt_dump_pages_range(dump_buf + offset,
+						   dump,
+						   start_page_id,
+						   valid_conn_pf_pages,
+						   ilt_pages, dump_page_ids);
+
+		/* Dump connection VF pages */
+		start_page_id += clients[ILT_CLI_CDUC].pf_total_lines;
+		for (i = 0; i < p_hwfn->p_cxt_mngr->vf_count;
+		     i++, start_page_id += clients[ILT_CLI_CDUC].vf_total_lines)
+			offset += qed_ilt_dump_pages_range(dump_buf + offset,
+							   dump,
+							   start_page_id,
+							   valid_conn_vf_pages,
+							   ilt_pages,
+							   dump_page_ids);
+	}
+
+	/* CDUT pages are ordered as follows:
+	 * - PF init pages (not dumped)
+	 * - PF work pages
+	 * - For each VF in the PF:
+	 *   - VF init pages (not dumped)
+	 *   - VF work pages
+	 */
+	if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_DUMP_ILT_CDUT)) {
+		/* Dump task PF pages */
+		start_page_id = clients[ILT_CLI_CDUT].first.val +
+		    cdut_pf_init_pages - pf_start_line;
+		offset += qed_ilt_dump_pages_range(dump_buf + offset,
+						   dump,
+						   start_page_id,
+						   cdut_pf_work_pages,
+						   ilt_pages, dump_page_ids);
+
+		/* Dump task VF pages */
+		start_page_id = clients[ILT_CLI_CDUT].first.val +
+		    cdut_pf_pages + cdut_vf_init_pages - pf_start_line;
+		for (i = 0; i < p_hwfn->p_cxt_mngr->vf_count;
+		     i++, start_page_id += cdut_vf_pages)
+			offset += qed_ilt_dump_pages_range(dump_buf + offset,
+							   dump,
+							   start_page_id,
+							   cdut_vf_work_pages,
+							   ilt_pages,
+							   dump_page_ids);
+	}
+
+	/* Overwrite size param */
+	if (dump)
+		qed_dump_num_param(dump_buf + size_param_offset,
+				   dump, "size", offset - base_data_offset);
+
+	return offset;
+}
+
+/* Performs ILT Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_ilt_dump(struct ecore_hwfn *p_hwfn,
+			struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	struct ecore_ilt_client_cfg *clients = p_hwfn->p_cxt_mngr->clients;
+	u32 valid_conn_vf_cids, valid_conn_vf_pages, offset = 0;
+	u32 valid_conn_pf_cids, valid_conn_pf_pages, num_pages;
+	u32 num_cids_per_page, conn_ctx_size;
+	u32 cduc_page_size, cdut_page_size;
+	struct phys_mem_desc *ilt_pages;
+	u8 conn_type;
+
+	cduc_page_size = 1 <<
+	    (clients[ILT_CLI_CDUC].p_size.val + PXP_ILT_PAGE_SIZE_NUM_BITS_MIN);
+	cdut_page_size = 1 <<
+	    (clients[ILT_CLI_CDUT].p_size.val + PXP_ILT_PAGE_SIZE_NUM_BITS_MIN);
+	conn_ctx_size = p_hwfn->p_cxt_mngr->conn_ctx_size;
+	num_cids_per_page = (int)(cduc_page_size / conn_ctx_size);
+	ilt_pages = p_hwfn->p_cxt_mngr->ilt_shadow;
+
+	/* Dump global params - 22 must match number of params below */
+	offset += qed_dump_common_global_params(p_hwfn, p_ptt,
+						dump_buf + offset, dump, 22);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "ilt-dump");
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-page-size", cduc_page_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-first-page-id",
+				     clients[ILT_CLI_CDUC].first.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-last-page-id",
+				     clients[ILT_CLI_CDUC].last.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-num-pf-pages",
+				     clients
+				     [ILT_CLI_CDUC].pf_total_lines);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-num-vf-pages",
+				     clients
+				     [ILT_CLI_CDUC].vf_total_lines);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "max-conn-ctx-size",
+				     conn_ctx_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-page-size", cdut_page_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-first-page-id",
+				     clients[ILT_CLI_CDUT].first.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-last-page-id",
+				     clients[ILT_CLI_CDUT].last.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-pf-init-pages",
+				     ecore_get_cdut_num_pf_init_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-vf-init-pages",
+				     ecore_get_cdut_num_vf_init_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-pf-work-pages",
+				     ecore_get_cdut_num_pf_work_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-vf-work-pages",
+				     ecore_get_cdut_num_vf_work_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "max-task-ctx-size",
+				     p_hwfn->p_cxt_mngr->task_ctx_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "task-type-id",
+				     p_hwfn->p_cxt_mngr->task_type_id);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "first-vf-id-in-pf",
+				     p_hwfn->p_cxt_mngr->first_vf_in_pf);
+	offset += /* 18 */ qed_dump_num_param(dump_buf + offset,
+					      dump,
+					      "num-vfs-in-pf",
+					      p_hwfn->p_cxt_mngr->vf_count);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "ptr-size-bytes", sizeof(void *));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "pf-start-line",
+				     p_hwfn->p_cxt_mngr->pf_start_line);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "page-mem-desc-size-dwords",
+				     PAGE_MEM_DESC_SIZE_DWORDS);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "ilt-shadow-size",
+				     p_hwfn->p_cxt_mngr->ilt_shadow_size);
+	/* Additional/Less parameters require matching of number in call to
+	 * dump_common_global_params()
+	 */
+
+	/* Dump section containing number of PF CIDs per connection type */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "num_pf_cids_per_conn_type", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", NUM_OF_CONNECTION_TYPES);
+	for (conn_type = 0, valid_conn_pf_cids = 0;
+	     conn_type < NUM_OF_CONNECTION_TYPES; conn_type++, offset++) {
+		u32 num_pf_cids =
+		    p_hwfn->p_cxt_mngr->conn_cfg[conn_type].cid_count;
+
+		if (dump)
+			*(dump_buf + offset) = num_pf_cids;
+		valid_conn_pf_cids += num_pf_cids;
+	}
+
+	/* Dump section containing number of VF CIDs per connection type */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "num_vf_cids_per_conn_type", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", NUM_OF_CONNECTION_TYPES);
+	for (conn_type = 0, valid_conn_vf_cids = 0;
+	     conn_type < NUM_OF_CONNECTION_TYPES; conn_type++, offset++) {
+		u32 num_vf_cids =
+		    p_hwfn->p_cxt_mngr->conn_cfg[conn_type].cids_per_vf;
+
+		if (dump)
+			*(dump_buf + offset) = num_vf_cids;
+		valid_conn_vf_cids += num_vf_cids;
+	}
+
+	/* Dump section containing physical memory descs for each ILT page */
+	num_pages = p_hwfn->p_cxt_mngr->ilt_shadow_size;
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "ilt_page_desc", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "size",
+				     num_pages * PAGE_MEM_DESC_SIZE_DWORDS);
+
+	/* Copy memory descriptors to dump buffer */
+	if (dump) {
+		u32 page_id;
+
+		for (page_id = 0; page_id < num_pages;
+		     page_id++, offset += PAGE_MEM_DESC_SIZE_DWORDS)
+			memcpy(dump_buf + offset,
+			       &ilt_pages[page_id],
+			       DWORDS_TO_BYTES(PAGE_MEM_DESC_SIZE_DWORDS));
+	} else {
+		offset += num_pages * PAGE_MEM_DESC_SIZE_DWORDS;
+	}
+
+	valid_conn_pf_pages = DIV_ROUND_UP(valid_conn_pf_cids,
+					   num_cids_per_page);
+	valid_conn_vf_pages = DIV_ROUND_UP(valid_conn_vf_cids,
+					   num_cids_per_page);
+
+	/* Dump ILT pages IDs */
+	offset += qed_ilt_dump_pages_section(p_hwfn,
+					     dump_buf + offset,
+					     dump,
+					     valid_conn_pf_pages,
+					     valid_conn_vf_pages,
+					     ilt_pages, true);
+
+	/* Dump ILT pages memory */
+	offset += qed_ilt_dump_pages_section(p_hwfn,
+					     dump_buf + offset,
+					     dump,
+					     valid_conn_pf_pages,
+					     valid_conn_vf_pages,
+					     ilt_pages, false);
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	return offset;
+}
+
+/***************************** Public Functions *******************************/
+
+enum dbg_status qed_dbg_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+				    const u8 * const bin_ptr)
+{
+	struct bin_buffer_hdr *buf_hdrs =
+			(struct bin_buffer_hdr *)(osal_uintptr_t)bin_ptr;
+	u8 buf_id;
+
+	/* Convert binary data to debug arrays */
+	for (buf_id = 0; buf_id < MAX_BIN_DBG_BUFFER_TYPE; buf_id++)
+		qed_set_dbg_bin_buf(p_hwfn,
+				    buf_id,
+				    (const u32 *)(bin_ptr +
+						  buf_hdrs[buf_id].offset),
+						  buf_hdrs[buf_id].length);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_set_app_ver(u32 ver)
+{
+	if (ver < TOOLS_VERSION)
+		return DBG_STATUS_UNSUPPORTED_APP_VERSION;
+
+	s_app_ver = ver;
+
+	return DBG_STATUS_OK;
+}
+
+bool qed_read_fw_info(struct ecore_hwfn *p_hwfn,
+		      struct ecore_ptt *p_ptt, struct fw_info *fw_info)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		struct storm_defs *storm = &s_storm_defs[storm_id];
+
+		/* Skip Storm if it's in reset */
+		if (dev_data->block_in_reset[storm->sem_block_id])
+			continue;
+
+		/* Read FW info for the current Storm */
+		qed_read_storm_fw_info(p_hwfn, p_ptt, storm_id, fw_info);
+
+		return true;
+	}
+
+	return false;
+}
+
+enum dbg_status qed_dbg_grc_config(struct ecore_hwfn *p_hwfn,
+				   enum dbg_grc_params grc_param, u32 val)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	enum dbg_status status;
+	int i;
+
+	DP_VERBOSE(p_hwfn->p_dev,
+		   ECORE_MSG_DEBUG,
+		   "dbg_grc_config: paramId = %d, val = %d\n", grc_param, val);
+
+	status = qed_dbg_dev_init(p_hwfn);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Initializes the GRC parameters (if not initialized). Needed in order
+	 * to set the default parameter values for the first time.
+	 */
+	qed_dbg_grc_init_params(p_hwfn);
+
+	if (grc_param >= MAX_DBG_GRC_PARAMS)
+		return DBG_STATUS_INVALID_ARGS;
+	if (val < s_grc_param_defs[grc_param].min ||
+	    val > s_grc_param_defs[grc_param].max)
+		return DBG_STATUS_INVALID_ARGS;
+
+	if (s_grc_param_defs[grc_param].is_preset) {
+		/* Preset param */
+
+		/* Disabling a preset is not allowed. Call
+		 * dbg_grc_set_params_default instead.
+		 */
+		if (!val)
+			return DBG_STATUS_INVALID_ARGS;
+
+		/* Update all params with the preset values */
+		for (i = 0; i < MAX_DBG_GRC_PARAMS; i++) {
+			struct grc_param_defs *defs = &s_grc_param_defs[i];
+			u32 preset_val;
+			/* Skip persistent params */
+			if (defs->is_persistent)
+				continue;
+
+			/* Find preset value */
+			if (grc_param == DBG_GRC_PARAM_EXCLUDE_ALL)
+				preset_val =
+				    defs->exclude_all_preset_val;
+			else if (grc_param == DBG_GRC_PARAM_CRASH)
+				preset_val =
+				    defs->crash_preset_val[dev_data->chip_id];
+			else
+				return DBG_STATUS_INVALID_ARGS;
+
+			qed_grc_set_param(p_hwfn, i, preset_val);
+		}
+	} else {
+		/* Regular param - set its value */
+		qed_grc_set_param(p_hwfn, grc_param, val);
+	}
+
+	return DBG_STATUS_OK;
+}
+
+/* Assign default GRC param values */
+void qed_dbg_grc_set_params_default(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 i;
+
+	for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
+		if (!s_grc_param_defs[i].is_persistent)
+			dev_data->grc.param_val[i] =
+			    s_grc_param_defs[i].default_val[dev_data->chip_id];
+}
+
+enum dbg_status qed_dbg_grc_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_MEM].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	return qed_grc_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_grc_dump(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf,
+				 u32 buf_size_in_dwords,
+				 u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_grc_get_dump_buf_size(p_hwfn,
+					       p_ptt,
+					       &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* GRC Dump */
+	status = qed_grc_dump(p_hwfn, p_ptt, dump_buf, true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_idle_chk_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	struct idle_chk_data *idle_chk = &dev_data->idle_chk;
+	enum dbg_status status;
+
+	*buf_size = 0;
+
+	status = qed_dbg_dev_init(p_hwfn);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_IMMS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_RULES].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	if (!idle_chk->buf_size_set) {
+		idle_chk->buf_size = qed_idle_chk_dump(p_hwfn,
+						       p_ptt, NULL, false);
+		idle_chk->buf_size_set = true;
+	}
+
+	*buf_size = idle_chk->buf_size;
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_idle_chk_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_grc_unreset_blocks(p_hwfn, p_ptt, true);
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	/* Idle Check Dump */
+	*num_dumped_dwords = qed_idle_chk_dump(p_hwfn, p_ptt, dump_buf, true);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_mcp_trace_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						    struct ecore_ptt *p_ptt,
+						    u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_mcp_trace_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+				       struct ecore_ptt *p_ptt,
+				       u32 *dump_buf,
+				       u32 buf_size_in_dwords,
+				       u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	status =
+		qed_dbg_mcp_trace_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK && status !=
+	    DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
+		return status;
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	/* Perform dump */
+	status = qed_mcp_trace_dump(p_hwfn,
+				    p_ptt, dump_buf, true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_reg_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_reg_fifo_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_reg_fifo_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	status = qed_reg_fifo_dump(p_hwfn,
+				   p_ptt, dump_buf, true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_igu_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_igu_fifo_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_igu_fifo_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	status = qed_igu_fifo_dump(p_hwfn,
+				   p_ptt, dump_buf, true, num_dumped_dwords);
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status
+qed_dbg_protection_override_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_protection_override_dump(p_hwfn,
+					    p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_protection_override_dump(struct ecore_hwfn *p_hwfn,
+						 struct ecore_ptt *p_ptt,
+						 u32 *dump_buf,
+						 u32 buf_size_in_dwords,
+						 u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords, *p_size = &needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status =
+		qed_dbg_protection_override_get_dump_buf_size(p_hwfn,
+							      p_ptt,
+							      p_size);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	status = qed_protection_override_dump(p_hwfn,
+					      p_ptt,
+					      dump_buf,
+					      true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_fw_asserts_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						     struct ecore_ptt *p_ptt,
+						     u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	*buf_size = qed_fw_asserts_dump(p_hwfn, p_ptt, NULL, false);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf,
+					u32 buf_size_in_dwords,
+					u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords, *p_size = &needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status =
+		qed_dbg_fw_asserts_get_dump_buf_size(p_hwfn,
+						     p_ptt,
+						     p_size);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	*num_dumped_dwords = qed_fw_asserts_dump(p_hwfn, p_ptt, dump_buf, true);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status qed_dbg_ilt_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						     struct ecore_ptt *p_ptt,
+						     u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	*buf_size = qed_ilt_dump(p_hwfn, p_ptt, NULL, false);
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status qed_dbg_ilt_dump(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf,
+					u32 buf_size_in_dwords,
+					u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_ilt_get_dump_buf_size(p_hwfn,
+					       p_ptt,
+					       &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	*num_dumped_dwords = qed_ilt_dump(p_hwfn, p_ptt, dump_buf, true);
+
+	/* Reveret GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_read_attn(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  enum block_id block_id,
+				  enum dbg_attn_type attn_type,
+				  bool clear_status,
+				  struct dbg_attn_block_result *results)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+	u8 reg_idx, num_attn_regs, num_result_regs = 0;
+	const struct dbg_attn_reg *attn_reg_arr;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
+					       block_id,
+					       attn_type, &num_attn_regs);
+
+	for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
+		const struct dbg_attn_reg *reg_data = &attn_reg_arr[reg_idx];
+		struct dbg_attn_reg_result *reg_result;
+		u32 sts_addr, sts_val;
+		u16 modes_buf_offset;
+		bool eval_mode;
+
+		/* Check mode */
+		eval_mode = GET_FIELD(reg_data->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		modes_buf_offset = GET_FIELD(reg_data->mode.data,
+					     DBG_MODE_HDR_MODES_BUF_OFFSET);
+		if (eval_mode && !qed_is_mode_match(p_hwfn, &modes_buf_offset))
+			continue;
+
+		/* Mode match - read attention status register */
+		sts_addr = DWORDS_TO_BYTES(clear_status ?
+					   reg_data->sts_clr_address :
+					   GET_FIELD(reg_data->data,
+						     DBG_ATTN_REG_STS_ADDRESS));
+		sts_val = ecore_rd(p_hwfn, p_ptt, sts_addr);
+		if (!sts_val)
+			continue;
+
+		/* Non-zero attention status - add to results */
+		reg_result = &results->reg_results[num_result_regs];
+		SET_FIELD(reg_result->data,
+			  DBG_ATTN_REG_RESULT_STS_ADDRESS, sts_addr);
+		SET_FIELD(reg_result->data,
+			  DBG_ATTN_REG_RESULT_NUM_REG_ATTN,
+			  GET_FIELD(reg_data->data, DBG_ATTN_REG_NUM_REG_ATTN));
+		reg_result->block_attn_offset = reg_data->block_attn_offset;
+		reg_result->sts_val = sts_val;
+		reg_result->mask_val = ecore_rd(p_hwfn,
+					      p_ptt,
+					      DWORDS_TO_BYTES
+					      (reg_data->mask_address));
+		num_result_regs++;
+	}
+
+	results->block_id = (u8)block_id;
+	results->names_offset =
+	    qed_get_block_attn_data(p_hwfn, block_id, attn_type)->names_offset;
+	SET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_ATTN_TYPE, attn_type);
+	SET_FIELD(results->data,
+		  DBG_ATTN_BLOCK_RESULT_NUM_REGS, num_result_regs);
+
+	return DBG_STATUS_OK;
+}
+
+/******************************* Data Types **********************************/
+
+/* REG fifo element */
+struct reg_fifo_element {
+	u64 data;
+#define REG_FIFO_ELEMENT_ADDRESS_SHIFT		0
+#define REG_FIFO_ELEMENT_ADDRESS_MASK		0x7fffff
+#define REG_FIFO_ELEMENT_ACCESS_SHIFT		23
+#define REG_FIFO_ELEMENT_ACCESS_MASK		0x1
+#define REG_FIFO_ELEMENT_PF_SHIFT		24
+#define REG_FIFO_ELEMENT_PF_MASK		0xf
+#define REG_FIFO_ELEMENT_VF_SHIFT		28
+#define REG_FIFO_ELEMENT_VF_MASK		0xff
+#define REG_FIFO_ELEMENT_PORT_SHIFT		36
+#define REG_FIFO_ELEMENT_PORT_MASK		0x3
+#define REG_FIFO_ELEMENT_PRIVILEGE_SHIFT	38
+#define REG_FIFO_ELEMENT_PRIVILEGE_MASK		0x3
+#define REG_FIFO_ELEMENT_PROTECTION_SHIFT	40
+#define REG_FIFO_ELEMENT_PROTECTION_MASK	0x7
+#define REG_FIFO_ELEMENT_MASTER_SHIFT		43
+#define REG_FIFO_ELEMENT_MASTER_MASK		0xf
+#define REG_FIFO_ELEMENT_ERROR_SHIFT		47
+#define REG_FIFO_ELEMENT_ERROR_MASK		0x1f
+};
+
+/* REG fifo error element */
+struct reg_fifo_err {
+	u32 err_code;
+	const char *err_msg;
+};
+
+/* IGU fifo element */
+struct igu_fifo_element {
+	u32 dword0;
+#define IGU_FIFO_ELEMENT_DWORD0_FID_SHIFT		0
+#define IGU_FIFO_ELEMENT_DWORD0_FID_MASK		0xff
+#define IGU_FIFO_ELEMENT_DWORD0_IS_PF_SHIFT		8
+#define IGU_FIFO_ELEMENT_DWORD0_IS_PF_MASK		0x1
+#define IGU_FIFO_ELEMENT_DWORD0_SOURCE_SHIFT		9
+#define IGU_FIFO_ELEMENT_DWORD0_SOURCE_MASK		0xf
+#define IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE_SHIFT		13
+#define IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE_MASK		0xf
+#define IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR_SHIFT		17
+#define IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR_MASK		0x7fff
+	u32 dword1;
+	u32 dword2;
+#define IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD_SHIFT	0
+#define IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD_MASK		0x1
+#define IGU_FIFO_ELEMENT_DWORD12_WR_DATA_SHIFT		1
+#define IGU_FIFO_ELEMENT_DWORD12_WR_DATA_MASK		0xffffffff
+	u32 reserved;
+};
+
+struct igu_fifo_wr_data {
+	u32 data;
+#define IGU_FIFO_WR_DATA_PROD_CONS_SHIFT		0
+#define IGU_FIFO_WR_DATA_PROD_CONS_MASK			0xffffff
+#define IGU_FIFO_WR_DATA_UPDATE_FLAG_SHIFT		24
+#define IGU_FIFO_WR_DATA_UPDATE_FLAG_MASK		0x1
+#define IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB_SHIFT	25
+#define IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB_MASK		0x3
+#define IGU_FIFO_WR_DATA_SEGMENT_SHIFT			27
+#define IGU_FIFO_WR_DATA_SEGMENT_MASK			0x1
+#define IGU_FIFO_WR_DATA_TIMER_MASK_SHIFT		28
+#define IGU_FIFO_WR_DATA_TIMER_MASK_MASK		0x1
+#define IGU_FIFO_WR_DATA_CMD_TYPE_SHIFT			31
+#define IGU_FIFO_WR_DATA_CMD_TYPE_MASK			0x1
+};
+
+struct igu_fifo_cleanup_wr_data {
+	u32 data;
+#define IGU_FIFO_CLEANUP_WR_DATA_RESERVED_SHIFT		0
+#define IGU_FIFO_CLEANUP_WR_DATA_RESERVED_MASK		0x7ffffff
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL_SHIFT	27
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL_MASK	0x1
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE_SHIFT	28
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE_MASK	0x7
+#define IGU_FIFO_CLEANUP_WR_DATA_CMD_TYPE_SHIFT		31
+#define IGU_FIFO_CLEANUP_WR_DATA_CMD_TYPE_MASK		0x1
+};
+
+/* Protection override element */
+struct protection_override_element {
+	u64 data;
+#define PROTECTION_OVERRIDE_ELEMENT_ADDRESS_SHIFT		0
+#define PROTECTION_OVERRIDE_ELEMENT_ADDRESS_MASK		0x7fffff
+#define PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE_SHIFT		23
+#define PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE_MASK		0xffffff
+#define PROTECTION_OVERRIDE_ELEMENT_READ_SHIFT			47
+#define PROTECTION_OVERRIDE_ELEMENT_READ_MASK			0x1
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_SHIFT			48
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_MASK			0x1
+#define PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION_SHIFT	49
+#define PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION_MASK	0x7
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION_SHIFT	52
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION_MASK	0x7
+};
+
+enum igu_fifo_sources {
+	IGU_SRC_PXP0,
+	IGU_SRC_PXP1,
+	IGU_SRC_PXP2,
+	IGU_SRC_PXP3,
+	IGU_SRC_PXP4,
+	IGU_SRC_PXP5,
+	IGU_SRC_PXP6,
+	IGU_SRC_PXP7,
+	IGU_SRC_CAU,
+	IGU_SRC_ATTN,
+	IGU_SRC_GRC
+};
+
+enum igu_fifo_addr_types {
+	IGU_ADDR_TYPE_MSIX_MEM,
+	IGU_ADDR_TYPE_WRITE_PBA,
+	IGU_ADDR_TYPE_WRITE_INT_ACK,
+	IGU_ADDR_TYPE_WRITE_ATTN_BITS,
+	IGU_ADDR_TYPE_READ_INT,
+	IGU_ADDR_TYPE_WRITE_PROD_UPDATE,
+	IGU_ADDR_TYPE_RESERVED
+};
+
+struct igu_fifo_addr_data {
+	u16 start_addr;
+	u16 end_addr;
+	const char *desc;
+	const char *vf_desc;
+	enum igu_fifo_addr_types type;
+};
+
+/******************************** Constants **********************************/
+
+#define MAX_MSG_LEN				1024
+
+#define MCP_TRACE_MAX_MODULE_LEN		8
+#define MCP_TRACE_FORMAT_MAX_PARAMS		3
+#define MCP_TRACE_FORMAT_PARAM_WIDTH \
+	(MCP_TRACE_FORMAT_P2_SIZE_OFFSET - MCP_TRACE_FORMAT_P1_SIZE_OFFSET)
+
+#define REG_FIFO_ELEMENT_ADDR_FACTOR		4
+#define REG_FIFO_ELEMENT_IS_PF_VF_VAL		127
+
+#define PROTECTION_OVERRIDE_ELEMENT_ADDR_FACTOR	4
+
+/***************************** Constant Arrays *******************************/
+
+/* Status string array */
+static const char * const s_status_str[] = {
+	/* DBG_STATUS_OK */
+	"Operation completed successfully",
+
+	/* DBG_STATUS_APP_VERSION_NOT_SET */
+	"Debug application version wasn't set",
+
+	/* DBG_STATUS_UNSUPPORTED_APP_VERSION */
+	"Unsupported debug application version",
+
+	/* DBG_STATUS_DBG_BLOCK_NOT_RESET */
+	"The debug block wasn't reset since the last recording",
+
+	/* DBG_STATUS_INVALID_ARGS */
+	"Invalid arguments",
+
+	/* DBG_STATUS_OUTPUT_ALREADY_SET */
+	"The debug output was already set",
+
+	/* DBG_STATUS_INVALID_PCI_BUF_SIZE */
+	"Invalid PCI buffer size",
+
+	/* DBG_STATUS_PCI_BUF_ALLOC_FAILED */
+	"PCI buffer allocation failed",
+
+	/* DBG_STATUS_PCI_BUF_NOT_ALLOCATED */
+	"A PCI buffer wasn't allocated",
+
+	/* DBG_STATUS_INVALID_FILTER_TRIGGER_DWORDS */
+	"The filter/trigger constraint dword offsets are not enabled for recording",
+
+
+	/* DBG_STATUS_VFC_READ_ERROR */
+	"Error reading from VFC",
+
+	/* DBG_STATUS_STORM_ALREADY_ENABLED */
+	"The Storm was already enabled",
+
+	/* DBG_STATUS_STORM_NOT_ENABLED */
+	"The specified Storm wasn't enabled",
+
+	/* DBG_STATUS_BLOCK_ALREADY_ENABLED */
+	"The block was already enabled",
+
+	/* DBG_STATUS_BLOCK_NOT_ENABLED */
+	"The specified block wasn't enabled",
+
+	/* DBG_STATUS_NO_INPUT_ENABLED */
+	"No input was enabled for recording",
+
+	/* DBG_STATUS_NO_FILTER_TRIGGER_256B */
+	"Filters and triggers are not allowed in E4 256-bit mode",
+
+	/* DBG_STATUS_FILTER_ALREADY_ENABLED */
+	"The filter was already enabled",
+
+	/* DBG_STATUS_TRIGGER_ALREADY_ENABLED */
+	"The trigger was already enabled",
+
+	/* DBG_STATUS_TRIGGER_NOT_ENABLED */
+	"The trigger wasn't enabled",
+
+	/* DBG_STATUS_CANT_ADD_CONSTRAINT */
+	"A constraint can be added only after a filter was enabled or a trigger state was added",
+
+	/* DBG_STATUS_TOO_MANY_TRIGGER_STATES */
+	"Cannot add more than 3 trigger states",
+
+	/* DBG_STATUS_TOO_MANY_CONSTRAINTS */
+	"Cannot add more than 4 constraints per filter or trigger state",
+
+	/* DBG_STATUS_RECORDING_NOT_STARTED */
+	"The recording wasn't started",
+
+	/* DBG_STATUS_DATA_DID_NOT_TRIGGER */
+	"A trigger was configured, but it didn't trigger",
+
+	/* DBG_STATUS_NO_DATA_RECORDED */
+	"No data was recorded",
+
+	/* DBG_STATUS_DUMP_BUF_TOO_SMALL */
+	"Dump buffer is too small",
+
+	/* DBG_STATUS_DUMP_NOT_CHUNK_ALIGNED */
+	"Dumped data is not aligned to chunks",
+
+	/* DBG_STATUS_UNKNOWN_CHIP */
+	"Unknown chip",
+
+	/* DBG_STATUS_VIRT_MEM_ALLOC_FAILED */
+	"Failed allocating virtual memory",
+
+	/* DBG_STATUS_BLOCK_IN_RESET */
+	"The input block is in reset",
+
+	/* DBG_STATUS_INVALID_TRACE_SIGNATURE */
+	"Invalid MCP trace signature found in NVRAM",
+
+	/* DBG_STATUS_INVALID_NVRAM_BUNDLE */
+	"Invalid bundle ID found in NVRAM",
+
+	/* DBG_STATUS_NVRAM_GET_IMAGE_FAILED */
+	"Failed getting NVRAM image",
+
+	/* DBG_STATUS_NON_ALIGNED_NVRAM_IMAGE */
+	"NVRAM image is not dword-aligned",
+
+	/* DBG_STATUS_NVRAM_READ_FAILED */
+	"Failed reading from NVRAM",
+
+	/* DBG_STATUS_IDLE_CHK_PARSE_FAILED */
+	"Idle check parsing failed",
+
+	/* DBG_STATUS_MCP_TRACE_BAD_DATA */
+	"MCP Trace data is corrupt",
+
+	/* DBG_STATUS_MCP_TRACE_NO_META */
+	"Dump doesn't contain meta data - it must be provided in image file",
+
+	/* DBG_STATUS_MCP_COULD_NOT_HALT */
+	"Failed to halt MCP",
+
+	/* DBG_STATUS_MCP_COULD_NOT_RESUME */
+	"Failed to resume MCP after halt",
+
+	/* DBG_STATUS_RESERVED0 */
+	"",
+
+	/* DBG_STATUS_SEMI_FIFO_NOT_EMPTY */
+	"Failed to empty SEMI sync FIFO",
+
+	/* DBG_STATUS_IGU_FIFO_BAD_DATA */
+	"IGU FIFO data is corrupt",
+
+	/* DBG_STATUS_MCP_COULD_NOT_MASK_PRTY */
+	"MCP failed to mask parities",
+
+	/* DBG_STATUS_FW_ASSERTS_PARSE_FAILED */
+	"FW Asserts parsing failed",
+
+	/* DBG_STATUS_REG_FIFO_BAD_DATA */
+	"GRC FIFO data is corrupt",
+
+	/* DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA */
+	"Protection Override data is corrupt",
+
+	/* DBG_STATUS_DBG_ARRAY_NOT_SET */
+	"Debug arrays were not set (when using binary files, dbg_set_bin_ptr must be called)",
+
+	/* DBG_STATUS_RESERVED1 */
+	"",
+
+	/* DBG_STATUS_NON_MATCHING_LINES */
+	"Non-matching debug lines - in E4, all lines must be of the same type (either 128b or 256b)",
+
+	/* DBG_STATUS_INSUFFICIENT_HW_IDS */
+	"Insufficient HW IDs. Try to record less Storms/blocks",
+
+	/* DBG_STATUS_DBG_BUS_IN_USE */
+	"The debug bus is in use",
+
+	/* DBG_STATUS_INVALID_STORM_DBG_MODE */
+	"The storm debug mode is not supported in the current chip",
+
+	/* DBG_STATUS_OTHER_ENGINE_BB_ONLY */
+	"Other engine is supported only in BB",
+
+	/* DBG_STATUS_FILTER_SINGLE_HW_ID */
+	"The configured filter mode requires a single Storm/block input",
+
+	/* DBG_STATUS_TRIGGER_SINGLE_HW_ID */
+	"The configured filter mode requires that all the constraints of a single trigger state will be defined on a single Storm/block input",
+
+	/* DBG_STATUS_MISSING_TRIGGER_STATE_STORM */
+	"When triggering on Storm data, the Storm to trigger on must be specified"
+};
+
+/* Idle check severity names array */
+static const char * const s_idle_chk_severity_str[] = {
+	"Error",
+	"Error if no traffic",
+	"Warning"
+};
+
+/* MCP Trace level names array */
+static const char * const s_mcp_trace_level_str[] = {
+	"ERROR",
+	"TRACE",
+	"DEBUG"
+};
+
+/* Access type names array */
+static const char * const s_access_strs[] = {
+	"read",
+	"write"
+};
+
+/* Privilege type names array */
+static const char * const s_privilege_strs[] = {
+	"VF",
+	"PDA",
+	"HV",
+	"UA"
+};
+
+/* Protection type names array */
+static const char * const s_protection_strs[] = {
+	"(default)",
+	"(default)",
+	"(default)",
+	"(default)",
+	"override VF",
+	"override PDA",
+	"override HV",
+	"override UA"
+};
+
+/* Master type names array */
+static const char * const s_master_strs[] = {
+	"???",
+	"pxp",
+	"mcp",
+	"msdm",
+	"psdm",
+	"ysdm",
+	"usdm",
+	"tsdm",
+	"xsdm",
+	"dbu",
+	"dmae",
+	"jdap",
+	"???",
+	"???",
+	"???",
+	"???"
+};
+
+/* REG FIFO error messages array */
+static struct reg_fifo_err s_reg_fifo_errors[] = {
+	{1, "grc timeout"},
+	{2, "address doesn't belong to any block"},
+	{4, "reserved address in block or write to read-only address"},
+	{8, "privilege/protection mismatch"},
+	{16, "path isolation error"},
+	{17, "RSL error"}
+};
+
+/* IGU FIFO sources array */
+static const char * const s_igu_fifo_source_strs[] = {
+	"TSTORM",
+	"MSTORM",
+	"USTORM",
+	"XSTORM",
+	"YSTORM",
+	"PSTORM",
+	"PCIE",
+	"NIG_QM_PBF",
+	"CAU",
+	"ATTN",
+	"GRC",
+};
+
+/* IGU FIFO error messages */
+static const char * const s_igu_fifo_error_strs[] = {
+	"no error",
+	"length error",
+	"function disabled",
+	"VF sent command to attention address",
+	"host sent prod update command",
+	"read of during interrupt register while in MIMD mode",
+	"access to PXP BAR reserved address",
+	"producer update command to attention index",
+	"unknown error",
+	"SB index not valid",
+	"SB relative index and FID not found",
+	"FID not match",
+	"command with error flag asserted (PCI error or CAU discard)",
+	"VF sent cleanup and RF cleanup is disabled",
+	"cleanup command on type bigger than 4"
+};
+
+/* IGU FIFO address data */
+static const struct igu_fifo_addr_data s_igu_fifo_addr_data[] = {
+	{0x0, 0x101, "MSI-X Memory", NULL,
+	 IGU_ADDR_TYPE_MSIX_MEM},
+	{0x102, 0x1ff, "reserved", NULL,
+	 IGU_ADDR_TYPE_RESERVED},
+	{0x200, 0x200, "Write PBA[0:63]", NULL,
+	 IGU_ADDR_TYPE_WRITE_PBA},
+	{0x201, 0x201, "Write PBA[64:127]", "reserved",
+	 IGU_ADDR_TYPE_WRITE_PBA},
+	{0x202, 0x202, "Write PBA[128]", "reserved",
+	 IGU_ADDR_TYPE_WRITE_PBA},
+	{0x203, 0x3ff, "reserved", NULL,
+	 IGU_ADDR_TYPE_RESERVED},
+	{0x400, 0x5ef, "Write interrupt acknowledgment", NULL,
+	 IGU_ADDR_TYPE_WRITE_INT_ACK},
+	{0x5f0, 0x5f0, "Attention bits update", NULL,
+	 IGU_ADDR_TYPE_WRITE_ATTN_BITS},
+	{0x5f1, 0x5f1, "Attention bits set", NULL,
+	 IGU_ADDR_TYPE_WRITE_ATTN_BITS},
+	{0x5f2, 0x5f2, "Attention bits clear", NULL,
+	 IGU_ADDR_TYPE_WRITE_ATTN_BITS},
+	{0x5f3, 0x5f3, "Read interrupt 0:63 with mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f4, 0x5f4, "Read interrupt 0:31 with mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f5, 0x5f5, "Read interrupt 32:63 with mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f6, 0x5f6, "Read interrupt 0:63 without mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f7, 0x5ff, "reserved", NULL,
+	 IGU_ADDR_TYPE_RESERVED},
+	{0x600, 0x7ff, "Producer update", NULL,
+	 IGU_ADDR_TYPE_WRITE_PROD_UPDATE}
+};
+
+/******************************** Variables **********************************/
+
+/* Temporary buffer, used for print size calculations */
+static char s_temp_buf[MAX_MSG_LEN];
+
+/**************************** Private Functions ******************************/
+
+static u32 qed_cyclic_add(u32 a, u32 b, u32 size)
+{
+	return (a + b) % size;
+}
+
+static u32 qed_cyclic_sub(u32 a, u32 b, u32 size)
+{
+	return (size + a - b) % size;
+}
+
+/* Reads the specified number of bytes from the specified cyclic buffer (up to 4
+ * bytes) and returns them as a dword value. the specified buffer offset is
+ * updated.
+ */
+static u32 qed_read_from_cyclic_buf(void *buf,
+				    u32 *offset,
+				    u32 buf_size, u8 num_bytes_to_read)
+{
+	u8 i, *val_ptr, *bytes_buf = (u8 *)buf;
+	u32 val = 0;
+
+	val_ptr = (u8 *)&val;
+
+	/* Assume running on a LITTLE ENDIAN and the buffer is network order
+	 * (BIG ENDIAN), as high order bytes are placed in lower memory address.
+	 */
+	for (i = 0; i < num_bytes_to_read; i++) {
+		val_ptr[i] = bytes_buf[*offset];
+		*offset = qed_cyclic_add(*offset, 1, buf_size);
+	}
+
+	return val;
+}
+
+/* Reads and returns the next byte from the specified buffer.
+ * The specified buffer offset is updated.
+ */
+static u8 qed_read_byte_from_buf(void *buf, u32 *offset)
+{
+	return ((u8 *)buf)[(*offset)++];
+}
+
+/* Reads and returns the next dword from the specified buffer.
+ * The specified buffer offset is updated.
+ */
+static u32 qed_read_dword_from_buf(void *buf, u32 *offset)
+{
+	u32 dword_val = *(u32 *)&((u8 *)buf)[*offset];
+
+	*offset += 4;
+
+	return dword_val;
+}
+
+/* Reads the next string from the specified buffer, and copies it to the
+ * specified pointer. The specified buffer offset is updated.
+ */
+static void qed_read_str_from_buf(void *buf, u32 *offset, u32 size, char *dest)
+{
+	const char *source_str = &((const char *)buf)[*offset];
+
+	OSAL_STRNCPY(dest, source_str, size);
+	dest[size - 1] = '\0';
+	*offset += size;
+}
+
+/* Returns a pointer to the specified offset (in bytes) of the specified buffer.
+ * If the specified buffer in NULL, a temporary buffer pointer is returned.
+ */
+static char *qed_get_buf_ptr(void *buf, u32 offset)
+{
+	return buf ? (char *)buf + offset : s_temp_buf;
+}
+
+/* Reads a param from the specified buffer. Returns the number of dwords read.
+ * If the returned str_param is NULL, the param is numeric and its value is
+ * returned in num_param.
+ * Otheriwise, the param is a string and its pointer is returned in str_param.
+ */
+static u32 qed_read_param(u32 *dump_buf,
+			  const char **param_name,
+			  const char **param_str_val, u32 *param_num_val)
+{
+	char *char_buf = (char *)dump_buf;
+	size_t offset = 0;
+
+	/* Extract param name */
+	*param_name = char_buf;
+	offset += strlen(*param_name) + 1;
+
+	/* Check param type */
+	if (*(char_buf + offset++)) {
+		/* String param */
+		*param_str_val = char_buf + offset;
+		*param_num_val = 0;
+		offset += strlen(*param_str_val) + 1;
+		if (offset & 0x3)
+			offset += (4 - (offset & 0x3));
+	} else {
+		/* Numeric param */
+		*param_str_val = NULL;
+		if (offset & 0x3)
+			offset += (4 - (offset & 0x3));
+		*param_num_val = *(u32 *)(char_buf + offset);
+		offset += 4;
+	}
+
+	return (u32)offset / 4;
+}
+
+/* Reads a section header from the specified buffer.
+ * Returns the number of dwords read.
+ */
+static u32 qed_read_section_hdr(u32 *dump_buf,
+				const char **section_name,
+				u32 *num_section_params)
+{
+	const char *param_str_val;
+
+	return qed_read_param(dump_buf,
+			      section_name, &param_str_val, num_section_params);
+}
+
+/* Reads section params from the specified buffer and prints them to the results
+ * buffer. Returns the number of dwords read.
+ */
+static u32 qed_print_section_params(u32 *dump_buf,
+				    u32 num_section_params,
+				    char *results_buf, u32 *num_chars_printed)
+{
+	u32 i, dump_offset = 0, results_offset = 0;
+
+	for (i = 0; i < num_section_params; i++) {
+		const char *param_name, *param_str_val;
+		u32 param_num_val = 0;
+
+		dump_offset += qed_read_param(dump_buf + dump_offset,
+					      &param_name,
+					      &param_str_val, &param_num_val);
+
+		if (param_str_val) {
+			results_offset +=
+				sprintf(qed_get_buf_ptr(results_buf,
+							results_offset),
+					"%s: %s\n", param_name, param_str_val);
+		} else if (strcmp(param_name, "fw-timestamp")) {
+			results_offset +=
+				sprintf(qed_get_buf_ptr(results_buf,
+							results_offset),
+					"%s: %d\n", param_name, param_num_val);
+		}
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf, results_offset),
+				  "\n");
+
+	*num_chars_printed = results_offset;
+
+	return dump_offset;
+}
+
+/* Returns the block name that matches the specified block ID,
+ * or NULL if not found.
+ */
+static const char *qed_dbg_get_block_name(struct ecore_hwfn *p_hwfn,
+					  enum block_id block_id)
+{
+	const struct dbg_block_user *block =
+	    (const struct dbg_block_user *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS_USER_DATA].ptr + block_id;
+
+	return (const char *)block->name;
+}
+
+static struct dbg_tools_user_data *qed_dbg_get_user_data(struct ecore_hwfn
+							 *p_hwfn)
+{
+	return (struct dbg_tools_user_data *)p_hwfn->dbg_user_info;
+}
+
+/* Parses the idle check rules and returns the number of characters printed.
+ * In case of parsing error, returns 0.
+ */
+static u32 qed_parse_idle_chk_dump_rules(struct ecore_hwfn *p_hwfn,
+					 u32 *dump_buf,
+					 u32 *dump_buf_end,
+					 u32 num_rules,
+					 bool print_fw_idle_chk,
+					 char *results_buf,
+					 u32 *num_errors, u32 *num_warnings)
+{
+	/* Offset in results_buf in bytes */
+	u32 results_offset = 0;
+
+	u32 rule_idx;
+	u16 i, j;
+
+	*num_errors = 0;
+	*num_warnings = 0;
+
+	/* Go over dumped results */
+	for (rule_idx = 0; rule_idx < num_rules && dump_buf < dump_buf_end;
+	     rule_idx++) {
+		const struct dbg_idle_chk_rule_parsing_data *rule_parsing_data;
+		struct dbg_idle_chk_result_hdr *hdr;
+		const char *parsing_str, *lsi_msg;
+		u32 parsing_str_offset;
+		bool has_fw_msg;
+		u8 curr_reg_id;
+
+		hdr = (struct dbg_idle_chk_result_hdr *)dump_buf;
+		rule_parsing_data =
+		    (const struct dbg_idle_chk_rule_parsing_data *)
+		    p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_PARSING_DATA].ptr +
+		    hdr->rule_id;
+		parsing_str_offset =
+		    GET_FIELD(rule_parsing_data->data,
+			      DBG_IDLE_CHK_RULE_PARSING_DATA_STR_OFFSET);
+		has_fw_msg =
+		    GET_FIELD(rule_parsing_data->data,
+			      DBG_IDLE_CHK_RULE_PARSING_DATA_HAS_FW_MSG) > 0;
+		parsing_str = (const char *)
+		    p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr +
+		    parsing_str_offset;
+		lsi_msg = parsing_str;
+		curr_reg_id = 0;
+
+		if (hdr->severity >= MAX_DBG_IDLE_CHK_SEVERITY_TYPES)
+			return 0;
+
+		/* Skip rule header */
+		dump_buf += BYTES_TO_DWORDS(sizeof(*hdr));
+
+		/* Update errors/warnings count */
+		if (hdr->severity == IDLE_CHK_SEVERITY_ERROR ||
+		    hdr->severity == IDLE_CHK_SEVERITY_ERROR_NO_TRAFFIC)
+			(*num_errors)++;
+		else
+			(*num_warnings)++;
+
+		/* Print rule severity */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset), "%s: ",
+			    s_idle_chk_severity_str[hdr->severity]);
+
+		/* Print rule message */
+		if (has_fw_msg)
+			parsing_str += strlen(parsing_str) + 1;
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset), "%s.",
+			    has_fw_msg &&
+			    print_fw_idle_chk ? parsing_str : lsi_msg);
+		parsing_str += strlen(parsing_str) + 1;
+
+		/* Print register values */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset), " Registers:");
+		for (i = 0;
+		     i < hdr->num_dumped_cond_regs + hdr->num_dumped_info_regs;
+		     i++) {
+			struct dbg_idle_chk_result_reg_hdr *reg_hdr;
+			bool is_mem;
+			u8 reg_id;
+
+			reg_hdr =
+				(struct dbg_idle_chk_result_reg_hdr *)dump_buf;
+			is_mem = GET_FIELD(reg_hdr->data,
+					   DBG_IDLE_CHK_RESULT_REG_HDR_IS_MEM);
+			reg_id = GET_FIELD(reg_hdr->data,
+					   DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID);
+
+			/* Skip reg header */
+			dump_buf += BYTES_TO_DWORDS(sizeof(*reg_hdr));
+
+			/* Skip register names until the required reg_id is
+			 * reached.
+			 */
+			while (reg_id > curr_reg_id) {
+				curr_reg_id++;
+				parsing_str += strlen(parsing_str) + 1;
+			}
+
+			results_offset +=
+			    sprintf(qed_get_buf_ptr(results_buf,
+						    results_offset), " %s",
+				    parsing_str);
+			if (i < hdr->num_dumped_cond_regs && is_mem)
+				results_offset +=
+				    sprintf(qed_get_buf_ptr(results_buf,
+							    results_offset),
+					    "[%d]", hdr->mem_entry_id +
+					    reg_hdr->start_entry);
+			results_offset +=
+			    sprintf(qed_get_buf_ptr(results_buf,
+						    results_offset), "=");
+			for (j = 0; j < reg_hdr->size; j++, dump_buf++) {
+				results_offset +=
+				    sprintf(qed_get_buf_ptr(results_buf,
+							    results_offset),
+					    "0x%x", *dump_buf);
+				if (j < reg_hdr->size - 1)
+					results_offset +=
+					    sprintf(qed_get_buf_ptr
+						    (results_buf,
+						     results_offset), ",");
+			}
+		}
+
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf, results_offset), "\n");
+	}
+
+	/* Check if end of dump buffer was exceeded */
+	if (dump_buf > dump_buf_end)
+		return 0;
+
+	return results_offset;
+}
+
+/* Parses an idle check dump buffer.
+ * If result_buf is not NULL, the idle check results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+					       u32 *dump_buf,
+					       u32 num_dumped_dwords,
+					       char *results_buf,
+					       u32 *parsed_results_bytes,
+					       u32 *num_errors,
+					       u32 *num_warnings)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 *dump_buf_end = dump_buf + num_dumped_dwords;
+	u32 num_section_params = 0, num_rules;
+
+	/* Offset in results_buf in bytes */
+	u32 results_offset = 0;
+
+	*parsed_results_bytes = 0;
+	*num_errors = 0;
+	*num_warnings = 0;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_PARSING_DATA].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read idle_chk section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "idle_chk") || num_section_params != 1)
+		return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &num_rules);
+	if (strcmp(param_name, "num_rules"))
+		return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+
+	if (num_rules) {
+		u32 rules_print_size;
+
+		/* Print FW output */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "FW_IDLE_CHECK:\n");
+		rules_print_size =
+			qed_parse_idle_chk_dump_rules(p_hwfn,
+						      dump_buf,
+						      dump_buf_end,
+						      num_rules,
+						      true,
+						      results_buf ?
+						      results_buf +
+						      results_offset :
+						      NULL,
+						      num_errors,
+						      num_warnings);
+		results_offset += rules_print_size;
+		if (!rules_print_size)
+			return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+
+		/* Print LSI output */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nLSI_IDLE_CHECK:\n");
+		rules_print_size =
+			qed_parse_idle_chk_dump_rules(p_hwfn,
+						      dump_buf,
+						      dump_buf_end,
+						      num_rules,
+						      false,
+						      results_buf ?
+						      results_buf +
+						      results_offset :
+						      NULL,
+						      num_errors,
+						      num_warnings);
+		results_offset += rules_print_size;
+		if (!rules_print_size)
+			return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+	}
+
+	/* Print errors/warnings count */
+	if (*num_errors)
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nIdle Check failed!!! (with %d errors and %d warnings)\n",
+			    *num_errors, *num_warnings);
+	else if (*num_warnings)
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nIdle Check completed successfully (with %d warnings)\n",
+			    *num_warnings);
+	else
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nIdle Check completed successfully\n");
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+/* Allocates and fills MCP Trace meta data based on the specified meta data
+ * dump buffer.
+ * Returns debug status code.
+ */
+static enum dbg_status
+qed_mcp_trace_alloc_meta_data(struct ecore_hwfn *p_hwfn,
+			      const u32 *meta_buf)
+{
+	struct dbg_tools_user_data *dev_user_data;
+	u32 offset = 0, signature, i;
+	struct mcp_trace_meta *meta;
+	u8 *meta_buf_bytes = (u8 *)(osal_uintptr_t)meta_buf;
+
+	dev_user_data = qed_dbg_get_user_data(p_hwfn);
+	meta = &dev_user_data->mcp_trace_meta;
+
+	/* Free the previous meta before loading a new one. */
+	if (meta->is_allocated)
+		qed_mcp_trace_free_meta_data(p_hwfn);
+
+	OSAL_MEMSET(meta, 0, sizeof(*meta));
+
+	/* Read first signature */
+	signature = qed_read_dword_from_buf(meta_buf_bytes, &offset);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Read no. of modules and allocate memory for their pointers */
+	meta->modules_num = qed_read_byte_from_buf(meta_buf_bytes, &offset);
+	meta->modules = (char **)OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
+				    meta->modules_num * sizeof(char *));
+	if (!meta->modules)
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	/* Allocate and read all module strings */
+	for (i = 0; i < meta->modules_num; i++) {
+		u8 module_len = qed_read_byte_from_buf(meta_buf_bytes, &offset);
+
+		*(meta->modules + i) = (char *)OSAL_ZALLOC(p_hwfn->p_dev,
+							   GFP_KERNEL,
+							   module_len);
+		if (!(*(meta->modules + i))) {
+			/* Update number of modules to be released */
+			meta->modules_num = i ? i - 1 : 0;
+			return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+		}
+
+		qed_read_str_from_buf(meta_buf_bytes, &offset, module_len,
+				      *(meta->modules + i));
+		if (module_len > MCP_TRACE_MAX_MODULE_LEN)
+			(*(meta->modules + i))[MCP_TRACE_MAX_MODULE_LEN] = '\0';
+	}
+
+	/* Read second signature */
+	signature = qed_read_dword_from_buf(meta_buf_bytes, &offset);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Read number of formats and allocate memory for all formats */
+	meta->formats_num = qed_read_dword_from_buf(meta_buf_bytes, &offset);
+	meta->formats =
+		(struct mcp_trace_format *)OSAL_ZALLOC(p_hwfn->p_dev,
+						       GFP_KERNEL,
+						       meta->formats_num *
+					       sizeof(struct mcp_trace_format));
+	if (!meta->formats)
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	/* Allocate and read all strings */
+	for (i = 0; i < meta->formats_num; i++) {
+		struct mcp_trace_format *format_ptr = &meta->formats[i];
+		u8 format_len;
+
+		format_ptr->data = qed_read_dword_from_buf(meta_buf_bytes,
+							   &offset);
+		format_len = GET_MFW_FIELD(format_ptr->data,
+					   MCP_TRACE_FORMAT_LEN);
+		format_ptr->format_str = (char *)OSAL_ZALLOC(p_hwfn->p_dev,
+							     GFP_KERNEL,
+							     format_len);
+		if (!format_ptr->format_str) {
+			/* Update number of modules to be released */
+			meta->formats_num = i ? i - 1 : 0;
+			return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+		}
+
+		qed_read_str_from_buf(meta_buf_bytes,
+				      &offset,
+				      format_len, format_ptr->format_str);
+	}
+
+	meta->is_allocated = true;
+	return DBG_STATUS_OK;
+}
+
+/* Parses an MCP trace buffer. If result_buf is not NULL, the MCP Trace results
+ * are printed to it. The parsing status is returned.
+ * Arguments:
+ * trace_buf - MCP trace cyclic buffer
+ * trace_buf_size - MCP trace cyclic buffer size in bytes
+ * data_offset - offset in bytes of the data to parse in the MCP trace cyclic
+ *		 buffer.
+ * data_size - size in bytes of data to parse.
+ * parsed_buf - destination buffer for parsed data.
+ * parsed_results_bytes - size of parsed data in bytes.
+ */
+static enum dbg_status qed_parse_mcp_trace_buf(struct ecore_hwfn *p_hwfn,
+					       u8 *trace_buf,
+					       u32 trace_buf_size,
+					       u32 data_offset,
+					       u32 data_size,
+					       char *parsed_buf,
+					       u32 *parsed_results_bytes)
+{
+	struct dbg_tools_user_data *dev_user_data;
+	struct mcp_trace_meta *meta;
+	u32 param_mask, param_shift;
+	enum dbg_status status;
+
+	dev_user_data = qed_dbg_get_user_data(p_hwfn);
+	meta = &dev_user_data->mcp_trace_meta;
+	*parsed_results_bytes = 0;
+
+	if (!meta->is_allocated)
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+	status = DBG_STATUS_OK;
+
+	while (data_size) {
+		struct mcp_trace_format *format_ptr;
+		u8 format_level, format_module;
+		u32 params[3] = { 0, 0, 0 };
+		u32 header, format_idx, i;
+
+		if (data_size < MFW_TRACE_ENTRY_SIZE)
+			return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+		header = qed_read_from_cyclic_buf(trace_buf,
+						  &data_offset,
+						  trace_buf_size,
+						  MFW_TRACE_ENTRY_SIZE);
+		data_size -= MFW_TRACE_ENTRY_SIZE;
+		format_idx = header & MFW_TRACE_EVENTID_MASK;
+
+		/* Skip message if its index doesn't exist in the meta data */
+		if (format_idx >= meta->formats_num) {
+			u8 format_size = (u8)GET_MFW_FIELD(header,
+							   MFW_TRACE_PRM_SIZE);
+
+			if (data_size < format_size)
+				return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+			data_offset = qed_cyclic_add(data_offset,
+						     format_size,
+						     trace_buf_size);
+			data_size -= format_size;
+			continue;
+		}
+
+		format_ptr =
+			(struct mcp_trace_format *)&meta->formats[format_idx];
+
+		for (i = 0,
+		     param_mask = MCP_TRACE_FORMAT_P1_SIZE_MASK, param_shift =
+		     MCP_TRACE_FORMAT_P1_SIZE_OFFSET;
+		     i < MCP_TRACE_FORMAT_MAX_PARAMS;
+		     i++, param_mask <<= MCP_TRACE_FORMAT_PARAM_WIDTH,
+		     param_shift += MCP_TRACE_FORMAT_PARAM_WIDTH) {
+			/* Extract param size (0..3) */
+			u8 param_size = (u8)((format_ptr->data & param_mask) >>
+					     param_shift);
+
+			/* If the param size is zero, there are no other
+			 * parameters.
+			 */
+			if (!param_size)
+				break;
+
+			/* Size is encoded using 2 bits, where 3 is used to
+			 * encode 4.
+			 */
+			if (param_size == 3)
+				param_size = 4;
+
+			if (data_size < param_size)
+				return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+			params[i] = qed_read_from_cyclic_buf(trace_buf,
+							     &data_offset,
+							     trace_buf_size,
+							     param_size);
+			data_size -= param_size;
+		}
+
+		format_level = (u8)GET_MFW_FIELD(format_ptr->data,
+						 MCP_TRACE_FORMAT_LEVEL);
+		format_module = (u8)GET_MFW_FIELD(format_ptr->data,
+						  MCP_TRACE_FORMAT_MODULE);
+		if (format_level >= OSAL_ARRAY_SIZE(s_mcp_trace_level_str))
+			return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+		/* Print current message to results buffer */
+		*parsed_results_bytes +=
+			OSAL_SPRINTF(qed_get_buf_ptr(parsed_buf,
+						*parsed_results_bytes),
+				"%s %-8s: ",
+				s_mcp_trace_level_str[format_level],
+				meta->modules[format_module]);
+		*parsed_results_bytes +=
+		    sprintf(qed_get_buf_ptr(parsed_buf, *parsed_results_bytes),
+			    format_ptr->format_str,
+			    params[0], params[1], params[2]);
+	}
+
+	/* Add string NULL terminator */
+	(*parsed_results_bytes)++;
+
+	return status;
+}
+
+/* Parses an MCP Trace dump buffer.
+ * If result_buf is not NULL, the MCP Trace results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+						u32 *dump_buf,
+						char *results_buf,
+						u32 *parsed_results_bytes,
+						bool free_meta_data)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 data_size, trace_data_dwords, trace_meta_dwords;
+	u32 offset, results_offset, results_buf_bytes;
+	u32 param_num_val, num_section_params;
+	struct mcp_trace *trace;
+	enum dbg_status status;
+	const u32 *meta_buf;
+	u8 *trace_buf;
+
+	*parsed_results_bytes = 0;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read trace_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "mcp_trace_data") || num_section_params != 1)
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	trace_data_dwords = param_num_val;
+
+	/* Prepare trace info */
+	trace = (struct mcp_trace *)dump_buf;
+	if (trace->signature != MFW_TRACE_SIGNATURE || !trace->size)
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+	trace_buf = (u8 *)dump_buf + sizeof(*trace);
+	offset = trace->trace_oldest;
+	data_size = qed_cyclic_sub(trace->trace_prod, offset, trace->size);
+	dump_buf += trace_data_dwords;
+
+	/* Read meta_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "mcp_trace_meta"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	trace_meta_dwords = param_num_val;
+
+	/* Choose meta data buffer */
+	if (!trace_meta_dwords) {
+		/* Dump doesn't include meta data */
+		struct dbg_tools_user_data *dev_user_data =
+			qed_dbg_get_user_data(p_hwfn);
+
+		if (!dev_user_data->mcp_trace_user_meta_buf)
+			return DBG_STATUS_MCP_TRACE_NO_META;
+
+		meta_buf = dev_user_data->mcp_trace_user_meta_buf;
+	} else {
+		/* Dump includes meta data */
+		meta_buf = dump_buf;
+	}
+
+	/* Allocate meta data memory */
+	status = qed_mcp_trace_alloc_meta_data(p_hwfn, meta_buf);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	status = qed_parse_mcp_trace_buf(p_hwfn,
+					 trace_buf,
+					 trace->size,
+					 offset,
+					 data_size,
+					 results_buf ?
+					 results_buf + results_offset :
+					 NULL,
+					 &results_buf_bytes);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (free_meta_data)
+		qed_mcp_trace_free_meta_data(p_hwfn);
+
+	*parsed_results_bytes = results_offset + results_buf_bytes;
+
+	return DBG_STATUS_OK;
+}
+
+/* Parses a Reg FIFO dump buffer.
+ * If result_buf is not NULL, the Reg FIFO results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_reg_fifo_dump(u32 *dump_buf,
+					       char *results_buf,
+					       u32 *parsed_results_bytes)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 param_num_val, num_section_params, num_elements;
+	struct reg_fifo_element *elements;
+	u8 i, j, err_code, vf_val;
+	u32 results_offset = 0;
+	char vf_str[4];
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read reg_fifo_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "reg_fifo_data"))
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+	if (param_num_val % REG_FIFO_ELEMENT_DWORDS)
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+	num_elements = param_num_val / REG_FIFO_ELEMENT_DWORDS;
+	elements = (struct reg_fifo_element *)dump_buf;
+
+	/* Decode elements */
+	for (i = 0; i < num_elements; i++) {
+		const char *err_msg = NULL;
+
+		/* Discover if element belongs to a VF or a PF */
+		vf_val = GET_FIELD(elements[i].data, REG_FIFO_ELEMENT_VF);
+		if (vf_val == REG_FIFO_ELEMENT_IS_PF_VF_VAL)
+			sprintf(vf_str, "%s", "N/A");
+		else
+			sprintf(vf_str, "%d", vf_val);
+
+		/* Find error message */
+		err_code = GET_FIELD(elements[i].data, REG_FIFO_ELEMENT_ERROR);
+		for (j = 0; j < OSAL_ARRAY_SIZE(s_reg_fifo_errors) && !err_msg;
+		     j++)
+			if (err_code == s_reg_fifo_errors[j].err_code)
+				err_msg = s_reg_fifo_errors[j].err_msg;
+
+		/* Add parsed element to parsed buffer */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "raw: 0x%016lx, address: 0x%07x, access: %-5s, pf: %2d, vf: %s, port: %d, privilege: %-3s, protection: %-12s, master: %-4s, error: %s\n",
+			    elements[i].data,
+			    (u32)GET_FIELD(elements[i].data,
+					   REG_FIFO_ELEMENT_ADDRESS) *
+			    REG_FIFO_ELEMENT_ADDR_FACTOR,
+			    s_access_strs[GET_FIELD(elements[i].data,
+						    REG_FIFO_ELEMENT_ACCESS)],
+			    (u32)GET_FIELD(elements[i].data,
+					   REG_FIFO_ELEMENT_PF),
+			    vf_str,
+			    (u32)GET_FIELD(elements[i].data,
+					   REG_FIFO_ELEMENT_PORT),
+			    s_privilege_strs[GET_FIELD(elements[i].data,
+						REG_FIFO_ELEMENT_PRIVILEGE)],
+			    s_protection_strs[GET_FIELD(elements[i].data,
+						REG_FIFO_ELEMENT_PROTECTION)],
+			    s_master_strs[GET_FIELD(elements[i].data,
+						    REG_FIFO_ELEMENT_MASTER)],
+			    err_msg ? err_msg : "unknown error code");
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						  results_offset),
+				  "fifo contained %d elements", num_elements);
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status qed_parse_igu_fifo_element(struct igu_fifo_element
+						  *element, char
+						  *results_buf,
+						  u32 *results_offset)
+{
+	const struct igu_fifo_addr_data *found_addr = NULL;
+	u8 source, err_type, i, is_cleanup;
+	char parsed_addr_data[32];
+	char parsed_wr_data[256];
+	u32 wr_data, prod_cons;
+	bool is_wr_cmd, is_pf;
+	u16 cmd_addr;
+	u64 dword12;
+
+	/* Dword12 (dword index 1 and 2) contains bits 32..95 of the
+	 * FIFO element.
+	 */
+	dword12 = ((u64)element->dword2 << 32) | element->dword1;
+	is_wr_cmd = GET_FIELD(dword12, IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD);
+	is_pf = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_IS_PF);
+	cmd_addr = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR);
+	source = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_SOURCE);
+	err_type = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE);
+
+	if (source >= OSAL_ARRAY_SIZE(s_igu_fifo_source_strs))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	if (err_type >= OSAL_ARRAY_SIZE(s_igu_fifo_error_strs))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+
+	/* Find address data */
+	for (i = 0; i < OSAL_ARRAY_SIZE(s_igu_fifo_addr_data) && !found_addr;
+	     i++) {
+		const struct igu_fifo_addr_data *curr_addr =
+			&s_igu_fifo_addr_data[i];
+
+		if (cmd_addr >= curr_addr->start_addr && cmd_addr <=
+		    curr_addr->end_addr)
+			found_addr = curr_addr;
+	}
+
+	if (!found_addr)
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+
+	/* Prepare parsed address data */
+	switch (found_addr->type) {
+	case IGU_ADDR_TYPE_MSIX_MEM:
+		sprintf(parsed_addr_data, " vector_num = 0x%x", cmd_addr / 2);
+		break;
+	case IGU_ADDR_TYPE_WRITE_INT_ACK:
+	case IGU_ADDR_TYPE_WRITE_PROD_UPDATE:
+		sprintf(parsed_addr_data,
+			" SB = 0x%x", cmd_addr - found_addr->start_addr);
+		break;
+	default:
+		parsed_addr_data[0] = '\0';
+	}
+
+	if (!is_wr_cmd) {
+		parsed_wr_data[0] = '\0';
+		goto out;
+	}
+
+	/* Prepare parsed write data */
+	wr_data = GET_FIELD(dword12, IGU_FIFO_ELEMENT_DWORD12_WR_DATA);
+	prod_cons = GET_FIELD(wr_data, IGU_FIFO_WR_DATA_PROD_CONS);
+	is_cleanup = GET_FIELD(wr_data, IGU_FIFO_WR_DATA_CMD_TYPE);
+
+	if (source == IGU_SRC_ATTN) {
+		sprintf(parsed_wr_data, "prod: 0x%x, ", prod_cons);
+	} else {
+		if (is_cleanup) {
+			u8 cleanup_val, cleanup_type;
+
+			cleanup_val =
+				GET_FIELD(wr_data,
+					  IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL);
+			cleanup_type =
+			    GET_FIELD(wr_data,
+				      IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE);
+
+			sprintf(parsed_wr_data,
+				"cmd_type: cleanup, cleanup_val: %s, cleanup_type : %d, ",
+				cleanup_val ? "set" : "clear",
+				cleanup_type);
+		} else {
+			u8 update_flag, en_dis_int_for_sb, segment;
+			u8 timer_mask;
+
+			update_flag = GET_FIELD(wr_data,
+						IGU_FIFO_WR_DATA_UPDATE_FLAG);
+			en_dis_int_for_sb =
+				GET_FIELD(wr_data,
+					  IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB);
+			segment = GET_FIELD(wr_data,
+					    IGU_FIFO_WR_DATA_SEGMENT);
+			timer_mask = GET_FIELD(wr_data,
+					       IGU_FIFO_WR_DATA_TIMER_MASK);
+
+			sprintf(parsed_wr_data,
+				"cmd_type: prod/cons update, prod/cons: 0x%x, update_flag: %s, en_dis_int_for_sb : %s, segment : %s, timer_mask = %d, ",
+				prod_cons,
+				update_flag ? "update" : "nop",
+				en_dis_int_for_sb ?
+				(en_dis_int_for_sb == 1 ? "disable" : "nop") :
+				"enable",
+				segment ? "attn" : "regular",
+				timer_mask);
+		}
+	}
+out:
+	/* Add parsed element to parsed buffer */
+	*results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						   *results_offset),
+				   "raw: 0x%01x%08x%08x, %s: %d, source : %s, type : %s, cmd_addr : 0x%x(%s%s), %serror: %s\n",
+				   element->dword2, element->dword1,
+				   element->dword0,
+				   is_pf ? "pf" : "vf",
+				   GET_FIELD(element->dword0,
+					     IGU_FIFO_ELEMENT_DWORD0_FID),
+				   s_igu_fifo_source_strs[source],
+				   is_wr_cmd ? "wr" : "rd",
+				   cmd_addr,
+				   (!is_pf && found_addr->vf_desc)
+				   ? found_addr->vf_desc
+				   : found_addr->desc,
+				   parsed_addr_data,
+				   parsed_wr_data,
+				   s_igu_fifo_error_strs[err_type]);
+
+	return DBG_STATUS_OK;
+}
+
+/* Parses an IGU FIFO dump buffer.
+ * If result_buf is not NULL, the IGU FIFO results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_igu_fifo_dump(u32 *dump_buf,
+					       char *results_buf,
+					       u32 *parsed_results_bytes)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 param_num_val, num_section_params, num_elements;
+	struct igu_fifo_element *elements;
+	enum dbg_status status;
+	u32 results_offset = 0;
+	u8 i;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read igu_fifo_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "igu_fifo_data"))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	if (param_num_val % IGU_FIFO_ELEMENT_DWORDS)
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	num_elements = param_num_val / IGU_FIFO_ELEMENT_DWORDS;
+	elements = (struct igu_fifo_element *)dump_buf;
+
+	/* Decode elements */
+	for (i = 0; i < num_elements; i++) {
+		status = qed_parse_igu_fifo_element(&elements[i],
+						    results_buf,
+						    &results_offset);
+		if (status != DBG_STATUS_OK)
+			return status;
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						  results_offset),
+				  "fifo contained %d elements", num_elements);
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status
+qed_parse_protection_override_dump(u32 *dump_buf,
+				   char *results_buf,
+				   u32 *parsed_results_bytes)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 param_num_val, num_section_params, num_elements;
+	struct protection_override_element *elements;
+	u32 results_offset = 0;
+	u8 i;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read protection_override_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "protection_override_data"))
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+	if (param_num_val % PROTECTION_OVERRIDE_ELEMENT_DWORDS)
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+	num_elements = param_num_val / PROTECTION_OVERRIDE_ELEMENT_DWORDS;
+	elements = (struct protection_override_element *)dump_buf;
+
+	/* Decode elements */
+	for (i = 0; i < num_elements; i++) {
+		u32 address = GET_FIELD(elements[i].data,
+					PROTECTION_OVERRIDE_ELEMENT_ADDRESS) *
+			      PROTECTION_OVERRIDE_ELEMENT_ADDR_FACTOR;
+
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "window %2d, address: 0x%07x, size: %7d regs, read: %d, write: %d, read protection: %-12s, write protection: %-12s\n",
+			    i, address,
+			    (u32)GET_FIELD(elements[i].data,
+				      PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE),
+			    (u32)GET_FIELD(elements[i].data,
+				      PROTECTION_OVERRIDE_ELEMENT_READ),
+			    (u32)GET_FIELD(elements[i].data,
+				      PROTECTION_OVERRIDE_ELEMENT_WRITE),
+			    s_protection_strs[GET_FIELD(elements[i].data,
+				PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION)],
+			    s_protection_strs[GET_FIELD(elements[i].data,
+				PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION)]);
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						  results_offset),
+				  "protection override contained %d elements",
+				  num_elements);
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+/* Parses a FW Asserts dump buffer.
+ * If result_buf is not NULL, the FW Asserts results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_fw_asserts_dump(u32 *dump_buf,
+						 char *results_buf,
+						 u32 *parsed_results_bytes)
+{
+	u32 num_section_params, param_num_val, i, results_offset = 0;
+	const char *param_name, *param_str_val, *section_name;
+	bool last_section_found = false;
+
+	*parsed_results_bytes = 0;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	while (!last_section_found) {
+		dump_buf += qed_read_section_hdr(dump_buf,
+						 &section_name,
+						 &num_section_params);
+		if (!strcmp(section_name, "fw_asserts")) {
+			/* Extract params */
+			const char *storm_letter = NULL;
+			u32 storm_dump_size = 0;
+
+			for (i = 0; i < num_section_params; i++) {
+				dump_buf += qed_read_param(dump_buf,
+							   &param_name,
+							   &param_str_val,
+							   &param_num_val);
+				if (!strcmp(param_name, "storm"))
+					storm_letter = param_str_val;
+				else if (!strcmp(param_name, "size"))
+					storm_dump_size = param_num_val;
+				else
+					return
+					    DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+			}
+
+			if (!storm_letter || !storm_dump_size)
+				return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+
+			/* Print data */
+			results_offset +=
+			    sprintf(qed_get_buf_ptr(results_buf,
+						    results_offset),
+				    "\n%sSTORM_ASSERT: size=%d\n",
+				    storm_letter, storm_dump_size);
+			for (i = 0; i < storm_dump_size; i++, dump_buf++)
+				results_offset +=
+				    sprintf(qed_get_buf_ptr(results_buf,
+							    results_offset),
+					    "%08x\n", *dump_buf);
+		} else if (!strcmp(section_name, "last")) {
+			last_section_found = true;
+		} else {
+			return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+		}
+	}
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+/***************************** Public Functions *******************************/
+
+enum dbg_status qed_dbg_user_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+					 const u8 * const bin_ptr)
+{
+	struct bin_buffer_hdr *buf_hdrs =
+			(struct bin_buffer_hdr *)(osal_uintptr_t)bin_ptr;
+	u8 buf_id;
+
+	/* Convert binary data to debug arrays */
+	for (buf_id = 0; buf_id < MAX_BIN_DBG_BUFFER_TYPE; buf_id++)
+		qed_set_dbg_bin_buf(p_hwfn,
+				    (enum bin_dbg_buffer_type)buf_id,
+				    (const u32 *)(bin_ptr +
+						  buf_hdrs[buf_id].offset),
+						  buf_hdrs[buf_id].length);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_alloc_user_data(__rte_unused struct ecore_hwfn *p_hwfn,
+					void **user_data_ptr)
+{
+	*user_data_ptr = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
+				     sizeof(struct dbg_tools_user_data));
+	if (!(*user_data_ptr))
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	return DBG_STATUS_OK;
+}
+
+const char *qed_dbg_get_status_str(enum dbg_status status)
+{
+	return (status <
+		MAX_DBG_STATUS) ? s_status_str[status] : "Invalid debug status";
+}
+
+enum dbg_status qed_get_idle_chk_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32 num_dumped_dwords,
+						  u32 *results_buf_size)
+{
+	u32 num_errors, num_warnings;
+
+	return qed_parse_idle_chk_dump(p_hwfn,
+				       dump_buf,
+				       num_dumped_dwords,
+				       NULL,
+				       results_buf_size,
+				       &num_errors, &num_warnings);
+}
+
+enum dbg_status qed_print_idle_chk_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf,
+					   u32 *num_errors,
+					   u32 *num_warnings)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_idle_chk_dump(p_hwfn,
+				       dump_buf,
+				       num_dumped_dwords,
+				       results_buf,
+				       &parsed_buf_size,
+				       num_errors, num_warnings);
+}
+
+void qed_dbg_mcp_trace_set_meta_data(struct ecore_hwfn *p_hwfn,
+				     const u32 *meta_buf)
+{
+	struct dbg_tools_user_data *dev_user_data =
+		qed_dbg_get_user_data(p_hwfn);
+
+	dev_user_data->mcp_trace_user_meta_buf = meta_buf;
+}
+
+enum dbg_status
+qed_get_mcp_trace_results_buf_size(struct ecore_hwfn *p_hwfn,
+				   u32 *dump_buf,
+				   __rte_unused u32 num_dumped_dwords,
+				   u32 *results_buf_size)
+{
+	return qed_parse_mcp_trace_dump(p_hwfn,
+					dump_buf, NULL, results_buf_size, true);
+}
+
+enum dbg_status qed_print_mcp_trace_results(struct ecore_hwfn *p_hwfn,
+					    u32 *dump_buf,
+					    __rte_unused u32 num_dumped_dwords,
+					    char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_mcp_trace_dump(p_hwfn,
+					dump_buf,
+					results_buf, &parsed_buf_size, true);
+}
+
+enum dbg_status qed_print_mcp_trace_results_cont(struct ecore_hwfn *p_hwfn,
+						 u32 *dump_buf,
+						 char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_mcp_trace_dump(p_hwfn, dump_buf, results_buf,
+					&parsed_buf_size, false);
+}
+
+enum dbg_status qed_print_mcp_trace_line(struct ecore_hwfn *p_hwfn,
+					 u8 *dump_buf,
+					 u32 num_dumped_bytes,
+					 char *results_buf)
+{
+	u32 parsed_results_bytes;
+
+	return qed_parse_mcp_trace_buf(p_hwfn,
+				       dump_buf,
+				       num_dumped_bytes,
+				       0,
+				       num_dumped_bytes,
+				       results_buf, &parsed_results_bytes);
+}
+
+/* Frees the specified MCP Trace meta data */
+void qed_mcp_trace_free_meta_data(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_user_data *dev_user_data;
+	struct mcp_trace_meta *meta;
+	u32 i;
+
+	dev_user_data = qed_dbg_get_user_data(p_hwfn);
+	meta = &dev_user_data->mcp_trace_meta;
+	if (!meta->is_allocated)
+		return;
+
+	/* Release modules */
+	if (meta->modules) {
+		for (i = 0; i < meta->modules_num; i++)
+			OSAL_FREE(p_hwfn, meta->modules[i]);
+		OSAL_FREE(p_hwfn, meta->modules);
+	}
+
+	/* Release formats */
+	if (meta->formats) {
+		for (i = 0; i < meta->formats_num; i++)
+			OSAL_FREE(p_hwfn, meta->formats[i].format_str);
+		OSAL_FREE(p_hwfn, meta->formats);
+	}
+
+	meta->is_allocated = false;
+}
+
+enum dbg_status
+qed_get_reg_fifo_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
+				  u32 *dump_buf,
+				  __rte_unused u32 num_dumped_dwords,
+				  u32 *results_buf_size)
+{
+	return qed_parse_reg_fifo_dump(dump_buf, NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_reg_fifo_results(__rte_unused struct ecore_hwfn *p_hwfn,
+			   u32 *dump_buf,
+			   __rte_unused u32 num_dumped_dwords,
+			   char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_reg_fifo_dump(dump_buf, results_buf, &parsed_buf_size);
+}
+
+enum dbg_status
+qed_get_igu_fifo_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
+				  u32 *dump_buf,
+				  __rte_unused u32 num_dumped_dwords,
+				  u32 *results_buf_size)
+{
+	return qed_parse_igu_fifo_dump(dump_buf, NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_igu_fifo_results(__rte_unused struct ecore_hwfn *p_hwfn,
+			   u32 *dump_buf,
+			   __rte_unused u32 num_dumped_dwords,
+			   char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_igu_fifo_dump(dump_buf, results_buf, &parsed_buf_size);
+}
+
+enum dbg_status
+qed_get_protection_override_results_buf_size(__rte_unused
+					     struct ecore_hwfn *p_hwfn,
+					     u32 *dump_buf,
+					     __rte_unused u32 num_dumped_dwords,
+					     u32 *results_buf_size)
+{
+	return qed_parse_protection_override_dump(dump_buf,
+						  NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_protection_override_results(__rte_unused struct ecore_hwfn *p_hwfn,
+				      u32 *dump_buf,
+				      __rte_unused u32 num_dumped_dwords,
+				      char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_protection_override_dump(dump_buf,
+						  results_buf,
+						  &parsed_buf_size);
+}
+
+enum dbg_status
+qed_get_fw_asserts_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
+				    u32 *dump_buf,
+				    __rte_unused u32 num_dumped_dwords,
+				    u32 *results_buf_size)
+{
+	return qed_parse_fw_asserts_dump(dump_buf, NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_fw_asserts_results(__rte_unused struct ecore_hwfn *p_hwfn,
+			     u32 *dump_buf,
+			     __rte_unused u32 num_dumped_dwords,
+			     char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_fw_asserts_dump(dump_buf,
+					 results_buf, &parsed_buf_size);
+}
+
+enum dbg_status qed_dbg_parse_attn(struct ecore_hwfn *p_hwfn,
+				   struct dbg_attn_block_result *results)
+{
+	const u32 *block_attn_name_offsets;
+	const char *attn_name_base;
+	const char *block_name;
+	enum dbg_attn_type attn_type;
+	u8 num_regs, i, j;
+
+	num_regs = GET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_NUM_REGS);
+	attn_type = GET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_ATTN_TYPE);
+	block_name = qed_dbg_get_block_name(p_hwfn, results->block_id);
+	if (!block_name)
+		return DBG_STATUS_INVALID_ARGS;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_INDEXES].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_NAME_OFFSETS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	block_attn_name_offsets =
+	    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_NAME_OFFSETS].ptr +
+	    results->names_offset;
+
+	attn_name_base = p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr;
+
+	/* Go over registers with a non-zero attention status */
+	for (i = 0; i < num_regs; i++) {
+		struct dbg_attn_bit_mapping *bit_mapping;
+		struct dbg_attn_reg_result *reg_result;
+		u8 num_reg_attn, bit_idx = 0;
+
+		reg_result = &results->reg_results[i];
+		num_reg_attn = GET_FIELD(reg_result->data,
+					 DBG_ATTN_REG_RESULT_NUM_REG_ATTN);
+		bit_mapping = (struct dbg_attn_bit_mapping *)
+		    p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_INDEXES].ptr +
+		    reg_result->block_attn_offset;
+
+		/* Go over attention status bits */
+		for (j = 0; j < num_reg_attn; j++, bit_idx++) {
+			u16 attn_idx_val = GET_FIELD(bit_mapping[j].data,
+						     DBG_ATTN_BIT_MAPPING_VAL);
+			const char *attn_name, *attn_type_str, *masked_str;
+			u32 attn_name_offset;
+			u32 sts_addr;
+
+			/* Check if bit mask should be advanced (due to unused
+			 * bits).
+			 */
+			if (GET_FIELD(bit_mapping[j].data,
+				      DBG_ATTN_BIT_MAPPING_IS_UNUSED_BIT_CNT)) {
+				bit_idx += (u8)attn_idx_val;
+				continue;
+			}
+
+			/* Check current bit index */
+			if (!(reg_result->sts_val & OSAL_BIT(bit_idx)))
+				continue;
+
+			/* An attention bit with value=1 was found
+			 * Find attention name
+			 */
+			attn_name_offset =
+				block_attn_name_offsets[attn_idx_val];
+			attn_name = attn_name_base + attn_name_offset;
+			attn_type_str =
+				(attn_type ==
+				 ATTN_TYPE_INTERRUPT ? "Interrupt" :
+				 "Parity");
+			masked_str = reg_result->mask_val & OSAL_BIT(bit_idx) ?
+				     " [masked]" : "";
+			sts_addr = GET_FIELD(reg_result->data,
+					     DBG_ATTN_REG_RESULT_STS_ADDRESS);
+			DP_NOTICE(p_hwfn, false,
+				  "%s (%s) : %s [address 0x%08x, bit %d]%s\n",
+				  block_name, attn_type_str, attn_name,
+				  sts_addr * 4, bit_idx, masked_str);
+		}
+	}
+
+	return DBG_STATUS_OK;
+}
+
+/* Wrapper for unifying the idle_chk and mcp_trace api */
+static enum dbg_status
+qed_print_idle_chk_results_wrapper(struct ecore_hwfn *p_hwfn,
+				   u32 *dump_buf,
+				   u32 num_dumped_dwords,
+				   char *results_buf)
+{
+	u32 num_errors, num_warnnings;
+
+	return qed_print_idle_chk_results(p_hwfn, dump_buf, num_dumped_dwords,
+					  results_buf, &num_errors,
+					  &num_warnnings);
+}
+
+/* Feature meta data lookup table */
+static struct {
+	const char *name;
+	enum dbg_status (*get_size)(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt, u32 *size);
+	enum dbg_status (*perform_dump)(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt, u32 *dump_buf,
+					u32 buf_size, u32 *dumped_dwords);
+	enum dbg_status (*print_results)(struct ecore_hwfn *p_hwfn,
+					 u32 *dump_buf, u32 num_dumped_dwords,
+					 char *results_buf);
+	enum dbg_status (*results_buf_size)(struct ecore_hwfn *p_hwfn,
+					    u32 *dump_buf,
+					    u32 num_dumped_dwords,
+					    u32 *results_buf_size);
+} qed_features_lookup[] = {
+	{
+	"grc", qed_dbg_grc_get_dump_buf_size,
+		    qed_dbg_grc_dump, NULL, NULL}, {
+	"idle_chk",
+		    qed_dbg_idle_chk_get_dump_buf_size,
+		    qed_dbg_idle_chk_dump,
+		    qed_print_idle_chk_results_wrapper,
+		    qed_get_idle_chk_results_buf_size}, {
+	"mcp_trace",
+		    qed_dbg_mcp_trace_get_dump_buf_size,
+		    qed_dbg_mcp_trace_dump, qed_print_mcp_trace_results,
+		    qed_get_mcp_trace_results_buf_size}, {
+	"reg_fifo",
+		    qed_dbg_reg_fifo_get_dump_buf_size,
+		    qed_dbg_reg_fifo_dump, qed_print_reg_fifo_results,
+		    qed_get_reg_fifo_results_buf_size}, {
+	"igu_fifo",
+		    qed_dbg_igu_fifo_get_dump_buf_size,
+		    qed_dbg_igu_fifo_dump, qed_print_igu_fifo_results,
+		    qed_get_igu_fifo_results_buf_size}, {
+	"protection_override",
+		    qed_dbg_protection_override_get_dump_buf_size,
+		    qed_dbg_protection_override_dump,
+		    qed_print_protection_override_results,
+		    qed_get_protection_override_results_buf_size}, {
+	"fw_asserts",
+		    qed_dbg_fw_asserts_get_dump_buf_size,
+		    qed_dbg_fw_asserts_dump,
+		    qed_print_fw_asserts_results,
+		    qed_get_fw_asserts_results_buf_size}, {
+	"ilt",
+		    qed_dbg_ilt_get_dump_buf_size,
+		    qed_dbg_ilt_dump, NULL, NULL},};
+
+#define QED_RESULTS_BUF_MIN_SIZE 16
+/* Generic function for decoding debug feature info */
+static enum dbg_status format_feature(struct ecore_hwfn *p_hwfn,
+				      enum ecore_dbg_features feature_idx)
+{
+	struct ecore_dbg_feature *feature =
+	    &p_hwfn->p_dev->dbg_params.features[feature_idx];
+	u32 text_size_bytes, null_char_pos, i;
+	enum dbg_status rc;
+	char *text_buf;
+
+	/* Check if feature supports formatting capability */
+	if (!qed_features_lookup[feature_idx].results_buf_size)
+		return DBG_STATUS_OK;
+
+	/* Obtain size of formatted output */
+	rc = qed_features_lookup[feature_idx].results_buf_size(p_hwfn,
+						(u32 *)feature->dump_buf,
+						feature->dumped_dwords,
+						&text_size_bytes);
+	if (rc != DBG_STATUS_OK)
+		return rc;
+
+	/* Make sure that the allocated size is a multiple of dword (4 bytes) */
+	null_char_pos = text_size_bytes - 1;
+	text_size_bytes = (text_size_bytes + 3) & ~0x3;
+
+	if (text_size_bytes < QED_RESULTS_BUF_MIN_SIZE) {
+		DP_NOTICE(p_hwfn->p_dev, false,
+			  "formatted size of feature was too small %d. Aborting\n",
+			  text_size_bytes);
+		return DBG_STATUS_INVALID_ARGS;
+	}
+
+	/* Allocate temp text buf */
+	text_buf = OSAL_VZALLOC(p_hwfn, text_size_bytes);
+	if (!text_buf) {
+		DP_NOTICE(p_hwfn->p_dev, false,
+			  "failed to allocate text buffer. Aborting\n");
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+	}
+
+	/* Decode feature opcodes to string on temp buf */
+	rc = qed_features_lookup[feature_idx].print_results(p_hwfn,
+						(u32 *)feature->dump_buf,
+						feature->dumped_dwords,
+						text_buf);
+	if (rc != DBG_STATUS_OK) {
+		OSAL_VFREE(p_hwfn, text_buf);
+		return rc;
+	}
+
+	/* Replace the original null character with a '\n' character.
+	 * The bytes that were added as a result of the dword alignment are also
+	 * padded with '\n' characters.
+	 */
+	for (i = null_char_pos; i < text_size_bytes; i++)
+		text_buf[i] = '\n';
+
+
+	/* Free the old dump_buf and point the dump_buf to the newly allocagted
+	 * and formatted text buffer.
+	 */
+	OSAL_VFREE(p_hwfn, feature->dump_buf);
+	feature->dump_buf = (u8 *)text_buf;
+	feature->buf_size = text_size_bytes;
+	feature->dumped_dwords = text_size_bytes / 4;
+	return rc;
+}
+
+#define MAX_DBG_FEATURE_SIZE_DWORDS	0x3FFFFFFF
+
+/* Generic function for performing the dump of a debug feature. */
+static enum dbg_status qed_dbg_dump(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    enum ecore_dbg_features feature_idx)
+{
+	struct ecore_dbg_feature *feature =
+	    &p_hwfn->p_dev->dbg_params.features[feature_idx];
+	u32 buf_size_dwords;
+	enum dbg_status rc;
+
+	DP_NOTICE(p_hwfn->p_dev, false, "Collecting a debug feature [\"%s\"]\n",
+		  qed_features_lookup[feature_idx].name);
+
+	/* Dump_buf was already allocated need to free (this can happen if dump
+	 * was called but file was never read).
+	 * We can't use the buffer as is since size may have changed.
+	 */
+	if (feature->dump_buf) {
+		OSAL_VFREE(p_hwfn, feature->dump_buf);
+		feature->dump_buf = NULL;
+	}
+
+	/* Get buffer size from hsi, allocate accordingly, and perform the
+	 * dump.
+	 */
+	rc = qed_features_lookup[feature_idx].get_size(p_hwfn, p_ptt,
+						       &buf_size_dwords);
+	if (rc != DBG_STATUS_OK && rc != DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
+		return rc;
+
+	if (buf_size_dwords > MAX_DBG_FEATURE_SIZE_DWORDS) {
+		feature->buf_size = 0;
+		DP_NOTICE(p_hwfn->p_dev, false,
+			  "Debug feature [\"%s\"] size (0x%x dwords) exceeds maximum size (0x%x dwords)\n",
+			  qed_features_lookup[feature_idx].name,
+			  buf_size_dwords, MAX_DBG_FEATURE_SIZE_DWORDS);
+
+		return DBG_STATUS_OK;
+	}
+
+	feature->buf_size = buf_size_dwords * sizeof(u32);
+	feature->dump_buf = OSAL_ZALLOC(p_hwfn, GFP_KERNEL, feature->buf_size);
+	if (!feature->dump_buf)
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	rc = qed_features_lookup[feature_idx].perform_dump(p_hwfn, p_ptt,
+					(u32 *)feature->dump_buf,
+					feature->buf_size / sizeof(u32),
+					&feature->dumped_dwords);
+
+	/* If mcp is stuck we get DBG_STATUS_NVRAM_GET_IMAGE_FAILED error.
+	 * In this case the buffer holds valid binary data, but we wont able
+	 * to parse it (since parsing relies on data in NVRAM which is only
+	 * accessible when MFW is responsive). skip the formatting but return
+	 * success so that binary data is provided.
+	 */
+	if (rc == DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
+		return DBG_STATUS_OK;
+
+	if (rc != DBG_STATUS_OK)
+		return rc;
+
+	/* Format output */
+	rc = format_feature(p_hwfn, feature_idx);
+	return rc;
+}
+
+int qed_dbg_grc(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_GRC, num_dumped_bytes);
+}
+
+int qed_dbg_grc_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_GRC);
+}
+
+int
+qed_dbg_idle_chk(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_IDLE_CHK,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_idle_chk_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_IDLE_CHK);
+}
+
+int
+qed_dbg_reg_fifo(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_REG_FIFO,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_reg_fifo_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_REG_FIFO);
+}
+
+int
+qed_dbg_igu_fifo(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_IGU_FIFO,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_igu_fifo_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_IGU_FIFO);
+}
+
+static int qed_dbg_nvm_image_length(struct ecore_hwfn *p_hwfn,
+				    enum ecore_nvm_images image_id, u32 *length)
+{
+	struct ecore_nvm_image_att image_att;
+	int rc;
+
+	*length = 0;
+	rc = ecore_mcp_get_nvm_image_att(p_hwfn, image_id, &image_att);
+	if (rc)
+		return rc;
+
+	*length = image_att.length;
+
+	return rc;
+}
+
+int qed_dbg_protection_override(struct ecore_dev *edev, void *buffer,
+				u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_PROTECTION_OVERRIDE,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_protection_override_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_PROTECTION_OVERRIDE);
+}
+
+int qed_dbg_fw_asserts(struct ecore_dev *edev, void *buffer,
+		       u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_FW_ASSERTS,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_fw_asserts_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_FW_ASSERTS);
+}
+
+int qed_dbg_ilt(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_ILT, num_dumped_bytes);
+}
+
+int qed_dbg_ilt_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_ILT);
+}
+
+int qed_dbg_mcp_trace(struct ecore_dev *edev, void *buffer,
+		      u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_MCP_TRACE,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_mcp_trace_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_MCP_TRACE);
+}
+
+/* Defines the amount of bytes allocated for recording the length of debug
+ * feature buffer.
+ */
+#define REGDUMP_HEADER_SIZE			sizeof(u32)
+#define REGDUMP_HEADER_SIZE_SHIFT		0
+#define REGDUMP_HEADER_SIZE_MASK		0xffffff
+#define REGDUMP_HEADER_FEATURE_SHIFT		24
+#define REGDUMP_HEADER_FEATURE_MASK		0x3f
+#define REGDUMP_HEADER_OMIT_ENGINE_SHIFT	30
+#define REGDUMP_HEADER_OMIT_ENGINE_MASK		0x1
+#define REGDUMP_HEADER_ENGINE_SHIFT		31
+#define REGDUMP_HEADER_ENGINE_MASK		0x1
+#define REGDUMP_MAX_SIZE			0x1000000
+#define ILT_DUMP_MAX_SIZE			(1024 * 1024 * 15)
+
+enum debug_print_features {
+	OLD_MODE = 0,
+	IDLE_CHK = 1,
+	GRC_DUMP = 2,
+	MCP_TRACE = 3,
+	REG_FIFO = 4,
+	PROTECTION_OVERRIDE = 5,
+	IGU_FIFO = 6,
+	PHY = 7,
+	FW_ASSERTS = 8,
+	NVM_CFG1 = 9,
+	DEFAULT_CFG = 10,
+	NVM_META = 11,
+	MDUMP = 12,
+	ILT_DUMP = 13,
+};
+
+static u32 qed_calc_regdump_header(struct ecore_dev *edev,
+				   enum debug_print_features feature,
+				   int engine, u32 feature_size, u8 omit_engine)
+{
+	u32 res = 0;
+
+	SET_FIELD(res, REGDUMP_HEADER_SIZE, feature_size);
+	if (res != feature_size)
+		DP_NOTICE(edev, false,
+			  "Feature %d is too large (size 0x%x) and will corrupt the dump\n",
+			  feature, feature_size);
+
+	SET_FIELD(res, REGDUMP_HEADER_FEATURE, feature);
+	SET_FIELD(res, REGDUMP_HEADER_OMIT_ENGINE, omit_engine);
+	SET_FIELD(res, REGDUMP_HEADER_ENGINE, engine);
+
+	return res;
+}
+
+int qed_dbg_all_data(struct ecore_dev *edev, void *buffer)
+{
+	u8 cur_engine, omit_engine = 0, org_engine;
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	int grc_params[MAX_DBG_GRC_PARAMS], i;
+	u32 offset = 0, feature_size;
+	int rc;
+
+	for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
+		grc_params[i] = dev_data->grc.param_val[i];
+
+	if (!ECORE_IS_CMT(edev))
+		omit_engine = 1;
+
+	OSAL_MUTEX_ACQUIRE(&edev->dbg_lock);
+
+	org_engine = qed_get_debug_engine(edev);
+	for (cur_engine = 0; cur_engine < edev->num_hwfns; cur_engine++) {
+		/* Collect idle_chks and grcDump for each hw function */
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+			   "obtaining idle_chk and grcdump for current engine\n");
+		qed_set_debug_engine(edev, cur_engine);
+
+		/* First idle_chk */
+		rc = qed_dbg_idle_chk(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, IDLE_CHK, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_idle_chk failed. rc = %d\n", rc);
+		}
+
+		/* Second idle_chk */
+		rc = qed_dbg_idle_chk(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, IDLE_CHK, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_idle_chk failed. rc = %d\n", rc);
+		}
+
+		/* reg_fifo dump */
+		rc = qed_dbg_reg_fifo(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, REG_FIFO, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_reg_fifo failed. rc = %d\n", rc);
+		}
+
+		/* igu_fifo dump */
+		rc = qed_dbg_igu_fifo(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, IGU_FIFO, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_igu_fifo failed. rc = %d", rc);
+		}
+
+		/* protection_override dump */
+		rc = qed_dbg_protection_override(edev, (u8 *)buffer + offset +
+						 REGDUMP_HEADER_SIZE,
+						 &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, PROTECTION_OVERRIDE,
+						    cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev,
+			       "qed_dbg_protection_override failed. rc = %d\n",
+			       rc);
+		}
+
+		/* fw_asserts dump */
+		rc = qed_dbg_fw_asserts(edev, (u8 *)buffer + offset +
+					REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, FW_ASSERTS,
+						    cur_engine, feature_size,
+						    omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_fw_asserts failed. rc = %d\n",
+			       rc);
+		}
+
+		/* GRC dump - must be last because when mcp stuck it will
+		 * clutter idle_chk, reg_fifo, ...
+		 */
+		for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
+			dev_data->grc.param_val[i] = grc_params[i];
+
+		rc = qed_dbg_grc(edev, (u8 *)buffer + offset +
+				 REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, GRC_DUMP,
+						    cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_grc failed. rc = %d", rc);
+		}
+	}
+
+	qed_set_debug_engine(edev, org_engine);
+
+	/* mcp_trace */
+	rc = qed_dbg_mcp_trace(edev, (u8 *)buffer + offset +
+			       REGDUMP_HEADER_SIZE, &feature_size);
+	if (!rc) {
+		*(u32 *)((u8 *)buffer + offset) =
+		    qed_calc_regdump_header(edev, MCP_TRACE, cur_engine,
+					    feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+	} else {
+		DP_ERR(edev, "qed_dbg_mcp_trace failed. rc = %d\n", rc);
+	}
+
+	OSAL_MUTEX_RELEASE(&edev->dbg_lock);
+
+	return 0;
+}
+
+int qed_dbg_all_data_size(struct ecore_dev *edev)
+{
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	u32 regs_len = 0, image_len = 0, ilt_len = 0, total_ilt_len = 0;
+	u8 cur_engine, org_engine;
+
+	edev->disable_ilt_dump = false;
+	org_engine = qed_get_debug_engine(edev);
+	for (cur_engine = 0; cur_engine < edev->num_hwfns; cur_engine++) {
+		/* Engine specific */
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+			   "calculating idle_chk and grcdump register length for current engine\n");
+		qed_set_debug_engine(edev, cur_engine);
+		regs_len += REGDUMP_HEADER_SIZE + qed_dbg_idle_chk_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_idle_chk_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_grc_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_reg_fifo_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_igu_fifo_size(edev) +
+			    REGDUMP_HEADER_SIZE +
+			    qed_dbg_protection_override_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_fw_asserts_size(edev);
+
+		ilt_len = REGDUMP_HEADER_SIZE + qed_dbg_ilt_size(edev);
+		if (ilt_len < ILT_DUMP_MAX_SIZE) {
+			total_ilt_len += ilt_len;
+			regs_len += ilt_len;
+		}
+	}
+
+	qed_set_debug_engine(edev, org_engine);
+
+	/* Engine common */
+	regs_len += REGDUMP_HEADER_SIZE + qed_dbg_mcp_trace_size(edev);
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_NVM_CFG1, &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_DEFAULT_CFG,
+				 &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_NVM_META, &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_MDUMP, &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+
+	if (regs_len > REGDUMP_MAX_SIZE) {
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+			   "Dump exceeds max size 0x%x, disable ILT dump\n",
+			   REGDUMP_MAX_SIZE);
+		edev->disable_ilt_dump = true;
+		regs_len -= total_ilt_len;
+	}
+
+	return regs_len;
+}
+
+int qed_dbg_feature(struct ecore_dev *edev, void *buffer,
+		    enum ecore_dbg_features feature, u32 *num_dumped_bytes)
+{
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	struct ecore_dbg_feature *qed_feature =
+		&edev->dbg_params.features[feature];
+	enum dbg_status dbg_rc;
+	struct ecore_ptt *p_ptt;
+	int rc = 0;
+
+	/* Acquire ptt */
+	p_ptt = ecore_ptt_acquire(p_hwfn);
+	if (!p_ptt)
+		return -EINVAL;
+
+	/* Get dump */
+	dbg_rc = qed_dbg_dump(p_hwfn, p_ptt, feature);
+	if (dbg_rc != DBG_STATUS_OK) {
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG, "%s\n",
+			   qed_dbg_get_status_str(dbg_rc));
+		*num_dumped_bytes = 0;
+		rc = -EINVAL;
+		goto out;
+	}
+
+	DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+		   "copying debug feature to external buffer\n");
+	memcpy(buffer, qed_feature->dump_buf, qed_feature->buf_size);
+	*num_dumped_bytes = edev->dbg_params.features[feature].dumped_dwords *
+			    4;
+
+out:
+	ecore_ptt_release(p_hwfn, p_ptt);
+	return rc;
+}
+
+int
+qed_dbg_feature_size(struct ecore_dev *edev, enum ecore_dbg_features feature)
+{
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	struct ecore_dbg_feature *qed_feature = &edev->dbg_features[feature];
+	struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
+	u32 buf_size_dwords;
+	enum dbg_status rc;
+
+	if (!p_ptt)
+		return -EINVAL;
+
+	rc = qed_features_lookup[feature].get_size(p_hwfn, p_ptt,
+						   &buf_size_dwords);
+	if (rc != DBG_STATUS_OK)
+		buf_size_dwords = 0;
+
+	/* Feature will not be dumped if it exceeds maximum size */
+	if (buf_size_dwords > MAX_DBG_FEATURE_SIZE_DWORDS)
+		buf_size_dwords = 0;
+
+	ecore_ptt_release(p_hwfn, p_ptt);
+	qed_feature->buf_size = buf_size_dwords * sizeof(u32);
+	return qed_feature->buf_size;
+}
+
+u8 qed_get_debug_engine(struct ecore_dev *edev)
+{
+	return edev->dbg_params.engine_for_debug;
+}
+
+void qed_set_debug_engine(struct ecore_dev *edev, int engine_number)
+{
+	DP_VERBOSE(edev, ECORE_MSG_DEBUG, "set debug engine to %d\n",
+		   engine_number);
+	edev->dbg_params.engine_for_debug = engine_number;
+}
+
+void qed_dbg_pf_init(struct ecore_dev *edev)
+{
+	const u8 *dbg_values = NULL;
+	int i;
+
+	PMD_INIT_FUNC_TRACE(edev);
+
+	OSAL_MUTEX_INIT(&edev->dbg_lock);
+
+	/* Sync ver with debugbus qed code */
+	qed_dbg_set_app_ver(TOOLS_VERSION);
+
+	/* Debug values are after init values.
+	 * The offset is the first dword of the file.
+	 */
+	/* TBD: change hardcoded value to offset from FW file */
+	dbg_values = (const u8 *)edev->firmware + 1337296;
+
+	for_each_hwfn(edev, i) {
+		qed_dbg_set_bin_ptr(&edev->hwfns[i], dbg_values);
+		qed_dbg_user_set_bin_ptr(&edev->hwfns[i], dbg_values);
+	}
+
+	/* Set the hwfn to be 0 as default */
+	edev->dbg_params.engine_for_debug = 0;
+}
+
+void qed_dbg_pf_exit(struct ecore_dev *edev)
+{
+	struct ecore_dbg_feature *feature = NULL;
+	enum ecore_dbg_features feature_idx;
+
+	PMD_INIT_FUNC_TRACE(edev);
+
+	/* debug features' buffers may be allocated if debug feature was used
+	 * but dump wasn't called
+	 */
+	for (feature_idx = 0; feature_idx < DBG_FEATURE_NUM; feature_idx++) {
+		feature = &edev->dbg_features[feature_idx];
+		if (feature->dump_buf) {
+			OSAL_VFREE(edev, feature->dump_buf);
+			feature->dump_buf = NULL;
+		}
+	}
+
+	OSAL_MUTEX_DEALLOC(&edev->dbg_lock);
+}
diff --git a/drivers/net/qede/qede_debug.h b/drivers/net/qede/qede_debug.h
new file mode 100644
index 000000000..93e1bd710
--- /dev/null
+++ b/drivers/net/qede/qede_debug.h
@@ -0,0 +1,759 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Marvell Semiconductor Inc.
+ * All rights reserved.
+ * www.marvell.com
+ */
+
+#ifndef _QED_DEBUG_H
+#define _QED_DEBUG_H
+
+/* Forward Declaration */
+struct ecore_dev;
+enum ecore_dbg_features;
+
+int qed_dbg_grc(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes);
+int qed_dbg_grc_size(struct ecore_dev *edev);
+int qed_dbg_idle_chk(struct ecore_dev *edev, void *buffer,
+		     u32 *num_dumped_bytes);
+int qed_dbg_idle_chk_size(struct ecore_dev *edev);
+int qed_dbg_reg_fifo(struct ecore_dev *edev, void *buffer,
+		     u32 *num_dumped_bytes);
+int qed_dbg_reg_fifo_size(struct ecore_dev *edev);
+int qed_dbg_igu_fifo(struct ecore_dev *edev, void *buffer,
+		     u32 *num_dumped_bytes);
+int qed_dbg_igu_fifo_size(struct ecore_dev *edev);
+int qed_dbg_protection_override(struct ecore_dev *edev, void *buffer,
+				u32 *num_dumped_bytes);
+int qed_dbg_protection_override_size(struct ecore_dev *edev);
+int qed_dbg_fw_asserts(struct ecore_dev *edev, void *buffer,
+		       u32 *num_dumped_bytes);
+int qed_dbg_fw_asserts_size(struct ecore_dev *edev);
+int qed_dbg_ilt(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes);
+int qed_dbg_ilt_size(struct ecore_dev *edev);
+int qed_dbg_mcp_trace(struct ecore_dev *edev, void *buffer,
+		      u32 *num_dumped_bytes);
+int qed_dbg_mcp_trace_size(struct ecore_dev *edev);
+int qed_dbg_all_data(struct ecore_dev *edev, void *buffer);
+int qed_dbg_all_data_size(struct ecore_dev *edev);
+u8 qed_get_debug_engine(struct ecore_dev *edev);
+void qed_set_debug_engine(struct ecore_dev *edev, int engine_number);
+int qed_dbg_feature(struct ecore_dev *edev, void *buffer,
+		    enum ecore_dbg_features feature, u32 *num_dumped_bytes);
+int
+qed_dbg_feature_size(struct ecore_dev *edev, enum ecore_dbg_features feature);
+
+void qed_dbg_pf_init(struct ecore_dev *edev);
+void qed_dbg_pf_exit(struct ecore_dev *edev);
+
+/***************************** Public Functions *******************************/
+
+/**
+ * @brief qed_dbg_set_bin_ptr - Sets a pointer to the binary data with debug
+ *	arrays.
+ *
+ * @param p_hwfn -	    HW device data
+ * @param bin_ptr - a pointer to the binary data with debug arrays.
+ */
+enum dbg_status qed_dbg_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+				    const u8 * const bin_ptr);
+
+/**
+ * @brief qed_dbg_set_app_ver - Sets the version of the calling app.
+ *
+ * The application should call this function with the TOOLS_VERSION
+ * it compiles with. Must be called before all other debug functions.
+ *
+ * @return error if one of the following holds:
+ *      - the specified app version is not supported
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_set_app_ver(u32 ver);
+
+/**
+ * @brief qed_read_regs - Reads registers into a buffer (using GRC).
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf - Destination buffer.
+ * @param addr - Source GRC address in dwords.
+ * @param len - Number of registers to read.
+ */
+void qed_read_regs(struct ecore_hwfn *p_hwfn,
+		   struct ecore_ptt *p_ptt, u32 *buf, u32 addr, u32 len);
+
+/**
+ * @brief qed_read_fw_info - Reads FW info from the chip.
+ *
+ * The FW info contains FW-related information, such as the FW version,
+ * FW image (main/L2B/kuku), FW timestamp, etc.
+ * The FW info is read from the internal RAM of the first Storm that is not in
+ * reset.
+ *
+ * @param p_hwfn -	    HW device data
+ * @param p_ptt -	    Ptt window used for writing the registers.
+ * @param fw_info -	Out: a pointer to write the FW info into.
+ *
+ * @return true if the FW info was read successfully from one of the Storms,
+ * or false if all Storms are in reset.
+ */
+bool qed_read_fw_info(struct ecore_hwfn *p_hwfn,
+		      struct ecore_ptt *p_ptt, struct fw_info *fw_info);
+/**
+ * @brief qed_dbg_grc_config - Sets the value of a GRC parameter.
+ *
+ * @param p_hwfn -	HW device data
+ * @param grc_param -	GRC parameter
+ * @param val -		Value to set.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- grc_param is invalid
+ *	- val is outside the allowed boundaries
+ */
+enum dbg_status qed_dbg_grc_config(struct ecore_hwfn *p_hwfn,
+				   enum dbg_grc_params grc_param, u32 val);
+
+/**
+ * @brief qed_dbg_grc_set_params_default - Reverts all GRC parameters to their
+ *	default value.
+ *
+ * @param p_hwfn		- HW device data
+ */
+void qed_dbg_grc_set_params_default(struct ecore_hwfn *p_hwfn);
+/**
+ * @brief qed_dbg_grc_get_dump_buf_size - Returns the required buffer size for
+ *	GRC Dump.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for the GRC Dump
+ *	data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_grc_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size);
+
+/**
+ * @brief qed_dbg_grc_dump - Dumps GRC data into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the collected GRC data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified dump buffer is too small
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_grc_dump(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf,
+				 u32 buf_size_in_dwords,
+				 u32 *num_dumped_dwords);
+/**
+ * @brief qed_dbg_idle_chk_get_dump_buf_size - Returns the required buffer size
+ *	for idle check results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for the idle check
+ *	data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_idle_chk_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size);
+
+/**
+ * @brief qed_dbg_idle_chk_dump - Performs idle check and writes the results
+ *	into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the idle check data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_mcp_trace_get_dump_buf_size - Returns the required buffer size
+ *	for mcp trace results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for mcp trace data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the trace data in MCP scratchpad contain an invalid signature
+ *	- the bundle ID in NVRAM is invalid
+ *	- the trace meta data cannot be found (in NVRAM or image file)
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_mcp_trace_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						    struct ecore_ptt *p_ptt,
+						    u32 *buf_size);
+
+/**
+ * @brief qed_dbg_mcp_trace_dump - Performs mcp trace and writes the results
+ *	into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the mcp trace data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- the trace data in MCP scratchpad contain an invalid signature
+ *	- the bundle ID in NVRAM is invalid
+ *	- the trace meta data cannot be found (in NVRAM or image file)
+ *	- the trace meta data cannot be read (from NVRAM or image file)
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+				       struct ecore_ptt *p_ptt,
+				       u32 *dump_buf,
+				       u32 buf_size_in_dwords,
+				       u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_reg_fifo_get_dump_buf_size - Returns the required buffer size
+ *	for grc trace fifo results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for reg fifo data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_reg_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size);
+
+/**
+ * @brief qed_dbg_reg_fifo_dump - Reads the reg fifo and writes the results into
+ *	the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the reg fifo data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- DMAE transaction failed
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_igu_fifo_get_dump_buf_size - Returns the required buffer size
+ *	for the IGU fifo results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for the IGU fifo
+ *	data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_igu_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size);
+
+/**
+ * @brief qed_dbg_igu_fifo_dump - Reads the IGU fifo and writes the results into
+ *	the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the IGU fifo data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- DMAE transaction failed
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_protection_override_get_dump_buf_size - Returns the required
+ *	buffer size for protection override window results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for protection
+ *	override data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status
+qed_dbg_protection_override_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size);
+/**
+ * @brief qed_dbg_protection_override_dump - Reads protection override window
+ *	entries and writes the results into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the protection override data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- DMAE transaction failed
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_protection_override_dump(struct ecore_hwfn *p_hwfn,
+						 struct ecore_ptt *p_ptt,
+						 u32 *dump_buf,
+						 u32 buf_size_in_dwords,
+						 u32 *num_dumped_dwords);
+/**
+ * @brief qed_dbg_fw_asserts_get_dump_buf_size - Returns the required buffer
+ *	size for FW Asserts results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for FW Asserts data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_fw_asserts_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						     struct ecore_ptt *p_ptt,
+						     u32 *buf_size);
+/**
+ * @brief qed_dbg_fw_asserts_dump - Reads the FW Asserts and writes the results
+ *	into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the FW Asserts data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf,
+					u32 buf_size_in_dwords,
+					u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_read_attn - Reads the attention registers of the specified
+ * block and type, and writes the results into the specified buffer.
+ *
+ * @param p_hwfn -	 HW device data
+ * @param p_ptt -	 Ptt window used for writing the registers.
+ * @param block -	 Block ID.
+ * @param attn_type -	 Attention type.
+ * @param clear_status - Indicates if the attention status should be cleared.
+ * @param results -	 OUT: Pointer to write the read results into
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_read_attn(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  enum block_id block,
+				  enum dbg_attn_type attn_type,
+				  bool clear_status,
+				  struct dbg_attn_block_result *results);
+
+/**
+ * @brief qed_dbg_print_attn - Prints attention registers values in the
+ *	specified results struct.
+ *
+ * @param p_hwfn
+ * @param results - Pointer to the attention read results
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_print_attn(struct ecore_hwfn *p_hwfn,
+				   struct dbg_attn_block_result *results);
+
+/******************************* Data Types **********************************/
+
+struct mcp_trace_format {
+	u32 data;
+#define MCP_TRACE_FORMAT_MODULE_MASK	0x0000ffff
+#define MCP_TRACE_FORMAT_MODULE_OFFSET	0
+#define MCP_TRACE_FORMAT_LEVEL_MASK	0x00030000
+#define MCP_TRACE_FORMAT_LEVEL_OFFSET	16
+#define MCP_TRACE_FORMAT_P1_SIZE_MASK	0x000c0000
+#define MCP_TRACE_FORMAT_P1_SIZE_OFFSET 18
+#define MCP_TRACE_FORMAT_P2_SIZE_MASK	0x00300000
+#define MCP_TRACE_FORMAT_P2_SIZE_OFFSET 20
+#define MCP_TRACE_FORMAT_P3_SIZE_MASK	0x00c00000
+#define MCP_TRACE_FORMAT_P3_SIZE_OFFSET 22
+#define MCP_TRACE_FORMAT_LEN_MASK	0xff000000
+#define MCP_TRACE_FORMAT_LEN_OFFSET	24
+
+	char *format_str;
+};
+
+/* MCP Trace Meta data structure */
+struct mcp_trace_meta {
+	u32 modules_num;
+	char **modules;
+	u32 formats_num;
+	struct mcp_trace_format *formats;
+	bool is_allocated;
+};
+
+/* Debug Tools user data */
+struct dbg_tools_user_data {
+	struct mcp_trace_meta mcp_trace_meta;
+	const u32 *mcp_trace_user_meta_buf;
+};
+
+/******************************** Constants **********************************/
+
+#define MAX_NAME_LEN	16
+
+/***************************** Public Functions *******************************/
+
+/**
+ * @brief qed_dbg_user_set_bin_ptr - Sets a pointer to the binary data with
+ *	debug arrays.
+ *
+ * @param p_hwfn - HW device data
+ * @param bin_ptr - a pointer to the binary data with debug arrays.
+ */
+enum dbg_status qed_dbg_user_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+					 const u8 * const bin_ptr);
+
+/**
+ * @brief qed_dbg_alloc_user_data - Allocates user debug data.
+ *
+ * @param p_hwfn -		 HW device data
+ * @param user_data_ptr - OUT: a pointer to the allocated memory.
+ */
+enum dbg_status qed_dbg_alloc_user_data(struct ecore_hwfn *p_hwfn,
+					void **user_data_ptr);
+
+/**
+ * @brief qed_dbg_get_status_str - Returns a string for the specified status.
+ *
+ * @param status - a debug status code.
+ *
+ * @return a string for the specified status
+ */
+const char *qed_dbg_get_status_str(enum dbg_status status);
+
+/**
+ * @brief qed_get_idle_chk_results_buf_size - Returns the required buffer size
+ *	for idle check results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - idle check dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_idle_chk_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32  num_dumped_dwords,
+						  u32 *results_buf_size);
+/**
+ * @brief qed_print_idle_chk_results - Prints idle check results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - idle check dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the idle check results.
+ * @param num_errors - OUT: number of errors found in idle check.
+ * @param num_warnings - OUT: number of warnings found in idle check.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_idle_chk_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf,
+					   u32 *num_errors,
+					   u32 *num_warnings);
+
+/**
+ * @brief qed_dbg_mcp_trace_set_meta_data - Sets the MCP Trace meta data.
+ *
+ * Needed in case the MCP Trace dump doesn't contain the meta data (e.g. due to
+ * no NVRAM access).
+ *
+ * @param data - pointer to MCP Trace meta data
+ * @param size - size of MCP Trace meta data in dwords
+ */
+void qed_dbg_mcp_trace_set_meta_data(struct ecore_hwfn *p_hwfn,
+				     const u32 *meta_buf);
+
+/**
+ * @brief qed_get_mcp_trace_results_buf_size - Returns the required buffer size
+ *	for MCP Trace results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - MCP Trace dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_mcp_trace_results_buf_size(struct ecore_hwfn *p_hwfn,
+						   u32 *dump_buf,
+						   u32 num_dumped_dwords,
+						   u32 *results_buf_size);
+
+/**
+ * @brief qed_print_mcp_trace_results - Prints MCP Trace results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - mcp trace dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the mcp trace results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_mcp_trace_results(struct ecore_hwfn *p_hwfn,
+					    u32 *dump_buf,
+					    u32 num_dumped_dwords,
+					    char *results_buf);
+
+/**
+ * @brief qed_print_mcp_trace_results_cont - Prints MCP Trace results, and
+ * keeps the MCP trace meta data allocated, to support continuous MCP Trace
+ * parsing. After the continuous parsing ends, mcp_trace_free_meta_data should
+ * be called to free the meta data.
+ *
+ * @param p_hwfn -	      HW device data
+ * @param dump_buf -	      mcp trace dump buffer, starting from the header.
+ * @param results_buf -	      buffer for printing the mcp trace results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_mcp_trace_results_cont(struct ecore_hwfn *p_hwfn,
+						 u32 *dump_buf,
+						 char *results_buf);
+
+/**
+ * @brief print_mcp_trace_line - Prints MCP Trace results for a single line
+ *
+ * @param p_hwfn -	      HW device data
+ * @param dump_buf -	      mcp trace dump buffer, starting from the header.
+ * @param num_dumped_bytes -  number of bytes that were dumped.
+ * @param results_buf -	      buffer for printing the mcp trace results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_mcp_trace_line(struct ecore_hwfn *p_hwfn,
+					 u8 *dump_buf,
+					 u32 num_dumped_bytes,
+					 char *results_buf);
+
+/**
+ * @brief mcp_trace_free_meta_data - Frees the MCP Trace meta data.
+ * Should be called after continuous MCP Trace parsing.
+ *
+ * @param p_hwfn - HW device data
+ */
+void qed_mcp_trace_free_meta_data(struct ecore_hwfn *p_hwfn);
+
+/**
+ * @brief qed_get_reg_fifo_results_buf_size - Returns the required buffer size
+ *	for reg_fifo results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - reg fifo dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_reg_fifo_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32 num_dumped_dwords,
+						  u32 *results_buf_size);
+
+/**
+ * @brief qed_print_reg_fifo_results - Prints reg fifo results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - reg fifo dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the reg fifo results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_reg_fifo_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf);
+
+/**
+ * @brief qed_get_igu_fifo_results_buf_size - Returns the required buffer size
+ *	for igu_fifo results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - IGU fifo dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_igu_fifo_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32 num_dumped_dwords,
+						  u32 *results_buf_size);
+
+/**
+ * @brief qed_print_igu_fifo_results - Prints IGU fifo results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - IGU fifo dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the IGU fifo results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_igu_fifo_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf);
+
+/**
+ * @brief qed_get_protection_override_results_buf_size - Returns the required
+ *	buffer size for protection override results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - protection override dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status
+qed_get_protection_override_results_buf_size(struct ecore_hwfn *p_hwfn,
+					     u32 *dump_buf,
+					     u32 num_dumped_dwords,
+					     u32 *results_buf_size);
+
+/**
+ * @brief qed_print_protection_override_results - Prints protection override
+ *	results.
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - protection override dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the reg fifo results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_protection_override_results(struct ecore_hwfn *p_hwfn,
+						      u32 *dump_buf,
+						      u32 num_dumped_dwords,
+						      char *results_buf);
+
+/**
+ * @brief qed_get_fw_asserts_results_buf_size - Returns the required buffer size
+ *	for FW Asserts results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - FW Asserts dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_fw_asserts_results_buf_size(struct ecore_hwfn *p_hwfn,
+						    u32 *dump_buf,
+						    u32 num_dumped_dwords,
+						    u32 *results_buf_size);
+
+/**
+ * @brief qed_print_fw_asserts_results - Prints FW Asserts results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - FW Asserts dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the FW Asserts results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_fw_asserts_results(struct ecore_hwfn *p_hwfn,
+					     u32 *dump_buf,
+					     u32 num_dumped_dwords,
+					     char *results_buf);
+
+/**
+ * @brief qed_dbg_parse_attn - Parses and prints attention registers values in
+ * the specified results struct.
+ *
+ * @param p_hwfn -  HW device data
+ * @param results - Pointer to the attention read results
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_parse_attn(struct ecore_hwfn *p_hwfn,
+				   struct dbg_attn_block_result *results);
+
+#endif
diff --git a/drivers/net/qede/qede_if.h b/drivers/net/qede/qede_if.h
index 858cd51d5..c5ae3fb2e 100644
--- a/drivers/net/qede/qede_if.h
+++ b/drivers/net/qede/qede_if.h
@@ -189,6 +189,51 @@ struct qed_common_ops {
 			      uint32_t dp_module, uint8_t dp_level);
 
 	int (*send_drv_state)(struct ecore_dev *edev, bool active);
+
+	/* ###############  DEBUG *************************/
+
+	int     (*dbg_grc)(struct ecore_dev       *edev,
+			   void		 *buffer,
+			   u32		  *num_dumped_bytes);
+	int     (*dbg_grc_size)(struct ecore_dev *edev);
+
+	int     (*dbg_idle_chk)(struct ecore_dev  *edev,
+				void	    *buffer,
+				u32	     *num_dumped_bytes);
+	int     (*dbg_idle_chk_size)(struct ecore_dev *edev);
+
+	int     (*dbg_reg_fifo)(struct ecore_dev  *edev,
+				void	    *buffer,
+				u32	     *num_dumped_bytes);
+	int     (*dbg_reg_fifo_size)(struct ecore_dev *edev);
+
+	int     (*dbg_mcp_trace)(struct ecore_dev *edev,
+				 void	   *buffer,
+				 u32	    *num_dumped_bytes);
+	int     (*dbg_mcp_trace_size)(struct ecore_dev *edev);
+
+	int	(*dbg_protection_override)(struct ecore_dev *edev, void *buffer,
+					   u32 *num_dumped_bytes);
+	int     (*dbg_protection_override_size)(struct ecore_dev *edev);
+
+	int	(*dbg_igu_fifo_size)(struct ecore_dev *edev);
+	int	(*dbg_igu_fifo)(struct ecore_dev *edev, void *buffer,
+				u32 *num_dumped_bytes);
+
+	int	(*dbg_fw_asserts)(struct ecore_dev *edev, void *buffer,
+				  u32 *num_dumped_bytes);
+
+	int	(*dbg_fw_asserts_size)(struct ecore_dev *edev);
+
+	int	(*dbg_ilt)(struct ecore_dev *edev, void *buffer,
+			   u32 *num_dumped_bytes);
+
+	int	(*dbg_ilt_size)(struct ecore_dev *edev);
+
+	u8      (*dbg_get_debug_engine)(struct ecore_dev *edev);
+	void    (*dbg_set_debug_engine)(struct ecore_dev  *edev,
+					int	     engine_number);
+
 };
 
 /* Externs */
diff --git a/drivers/net/qede/qede_main.c b/drivers/net/qede/qede_main.c
index 51aa639c6..987a6f1e1 100644
--- a/drivers/net/qede/qede_main.c
+++ b/drivers/net/qede/qede_main.c
@@ -9,6 +9,8 @@
 #include <rte_string_fns.h>
 
 #include "qede_ethdev.h"
+/* ######### DEBUG ###########*/
+#include "qede_debug.h"
 
 /* Alarm timeout. */
 #define QEDE_ALARM_TIMEOUT_US 100000
@@ -276,10 +278,15 @@ static int qed_slowpath_start(struct ecore_dev *edev,
 	qed_start_iov_task(edev);
 
 #ifdef CONFIG_ECORE_BINARY_FW
-	if (IS_PF(edev))
+	if (IS_PF(edev)) {
 		data = (const uint8_t *)edev->firmware + sizeof(u32);
+
+		/* ############### DEBUG ################## */
+		qed_dbg_pf_init(edev);
+	}
 #endif
 
+
 	/* Start the slowpath */
 	memset(&hw_init_params, 0, sizeof(hw_init_params));
 	hw_init_params.b_hw_start = true;
@@ -779,6 +786,36 @@ const struct qed_common_ops qed_common_ops_pass = {
 	INIT_STRUCT_FIELD(slowpath_stop, &qed_slowpath_stop),
 	INIT_STRUCT_FIELD(remove, &qed_remove),
 	INIT_STRUCT_FIELD(send_drv_state, &qed_send_drv_state),
+	/* ############### DEBUG ####################*/
+
+	INIT_STRUCT_FIELD(dbg_get_debug_engine, &qed_get_debug_engine),
+	INIT_STRUCT_FIELD(dbg_set_debug_engine, &qed_set_debug_engine),
+
+	INIT_STRUCT_FIELD(dbg_protection_override,
+			  &qed_dbg_protection_override),
+	INIT_STRUCT_FIELD(dbg_protection_override_size,
+			  &qed_dbg_protection_override_size),
+
+	INIT_STRUCT_FIELD(dbg_grc, &qed_dbg_grc),
+	INIT_STRUCT_FIELD(dbg_grc_size, &qed_dbg_grc_size),
+
+	INIT_STRUCT_FIELD(dbg_idle_chk, &qed_dbg_idle_chk),
+	INIT_STRUCT_FIELD(dbg_idle_chk_size, &qed_dbg_idle_chk_size),
+
+	INIT_STRUCT_FIELD(dbg_mcp_trace, &qed_dbg_mcp_trace),
+	INIT_STRUCT_FIELD(dbg_mcp_trace_size, &qed_dbg_mcp_trace_size),
+
+	INIT_STRUCT_FIELD(dbg_fw_asserts, &qed_dbg_fw_asserts),
+	INIT_STRUCT_FIELD(dbg_fw_asserts_size, &qed_dbg_fw_asserts_size),
+
+	INIT_STRUCT_FIELD(dbg_ilt, &qed_dbg_ilt),
+	INIT_STRUCT_FIELD(dbg_ilt_size, &qed_dbg_ilt_size),
+
+	INIT_STRUCT_FIELD(dbg_reg_fifo_size, &qed_dbg_reg_fifo_size),
+	INIT_STRUCT_FIELD(dbg_reg_fifo, &qed_dbg_reg_fifo),
+
+	INIT_STRUCT_FIELD(dbg_igu_fifo_size, &qed_dbg_igu_fifo_size),
+	INIT_STRUCT_FIELD(dbg_igu_fifo, &qed_dbg_igu_fifo),
 };
 
 const struct qed_eth_ops qed_eth_ops_pass = {
-- 
2.18.0


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

* [dpdk-dev] [PATCH v2 4/4] net/qede: add support for get register operation
  2020-06-28  5:58 [dpdk-dev] [PATCH 0/4] net/qede: add FW debug data collection support Rasesh Mody
                   ` (7 preceding siblings ...)
  2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 3/4] net/qede: add infrastructure " Rasesh Mody
@ 2020-06-30  8:32 ` Rasesh Mody
  8 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-06-30  8:32 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

Add support for .get_reg eth_dev ops which will be used to collect the
firmware debug data.

PMD on detecting on some HW errors will collect the FW/HW Dump to a
buffer and then it will save it to a file implemented in
qede_save_fw_dump().

Dump file location and name:
Location: <RTE_SDK> or DPDK root
Name: qede_pmd_dump_mm-dd-yy_hh-mm-ss.bin

DPDK applications can initiate a debug data collection by invoking DPDK
library’s rte_eth_dev_get_reg_info() API. This API invokes .get_reg()
interface in the PMD.

PMD implementation of .get_reg() collects the FW/HW Dump, saves it to
data field of rte_dev_reg_info and passes it to the application. It’s
the responsibility of the application to save the FW/HW Dump to a file.
We recommendation using the file name format used by qede_save_fw_dump().

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 doc/guides/nics/features/qede.ini |   1 +
 drivers/net/qede/Makefile         |   1 +
 drivers/net/qede/base/bcm_osal.c  |  25 +++
 drivers/net/qede/base/bcm_osal.h  |   5 +
 drivers/net/qede/qede_ethdev.c    |   1 +
 drivers/net/qede/qede_ethdev.h    |  25 +++
 drivers/net/qede/qede_regs.c      | 271 ++++++++++++++++++++++++++++++
 7 files changed, 329 insertions(+)
 create mode 100644 drivers/net/qede/qede_regs.c

diff --git a/doc/guides/nics/features/qede.ini b/doc/guides/nics/features/qede.ini
index 20c90e626..f8716523e 100644
--- a/doc/guides/nics/features/qede.ini
+++ b/doc/guides/nics/features/qede.ini
@@ -31,6 +31,7 @@ Packet type parsing  = Y
 Basic stats          = Y
 Extended stats       = Y
 Stats per queue      = Y
+Registers dump       = Y
 Multiprocess aware   = Y
 Linux UIO            = Y
 Linux VFIO           = Y
diff --git a/drivers/net/qede/Makefile b/drivers/net/qede/Makefile
index 3b00338ff..0e8a67b0d 100644
--- a/drivers/net/qede/Makefile
+++ b/drivers/net/qede/Makefile
@@ -104,5 +104,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_main.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_rxtx.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_filter.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_debug.c
+SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_regs.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/qede/base/bcm_osal.c b/drivers/net/qede/base/bcm_osal.c
index 45557fe3c..65837b53d 100644
--- a/drivers/net/qede/base/bcm_osal.c
+++ b/drivers/net/qede/base/bcm_osal.c
@@ -246,6 +246,28 @@ qede_get_mcp_proto_stats(struct ecore_dev *edev,
 	}
 }
 
+static void qede_hw_err_handler(void *dev, enum ecore_hw_err_type err_type)
+{
+	struct ecore_dev *edev = dev;
+
+	switch (err_type) {
+	case ECORE_HW_ERR_FAN_FAIL:
+		break;
+
+	case ECORE_HW_ERR_MFW_RESP_FAIL:
+	case ECORE_HW_ERR_HW_ATTN:
+	case ECORE_HW_ERR_DMAE_FAIL:
+	case ECORE_HW_ERR_RAMROD_FAIL:
+	case ECORE_HW_ERR_FW_ASSERT:
+		OSAL_SAVE_FW_DUMP(0); /* Using port 0 as default port_id */
+		break;
+
+	default:
+		DP_NOTICE(edev, false, "Unknown HW error [%d]\n", err_type);
+		return;
+	}
+}
+
 void
 qede_hw_err_notify(struct ecore_hwfn *p_hwfn, enum ecore_hw_err_type err_type)
 {
@@ -275,6 +297,9 @@ qede_hw_err_notify(struct ecore_hwfn *p_hwfn, enum ecore_hw_err_type err_type)
 	}
 
 	DP_ERR(p_hwfn, "HW error occurred [%s]\n", err_str);
+
+	qede_hw_err_handler(p_hwfn->p_dev, err_type);
+
 	ecore_int_attn_clr_enable(p_hwfn->p_dev, true);
 }
 
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index b4b94231b..5d4df5907 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -371,6 +371,11 @@ void qede_hw_err_notify(struct ecore_hwfn *p_hwfn,
 
 /* TODO: */
 #define OSAL_SCHEDULE_RECOVERY_HANDLER(hwfn) nothing
+
+int qede_save_fw_dump(uint8_t port_id);
+
+#define OSAL_SAVE_FW_DUMP(port_id) qede_save_fw_dump(port_id)
+
 #define OSAL_HW_ERROR_OCCURRED(hwfn, err_type) \
 	qede_hw_err_notify(hwfn, err_type)
 
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 717b80839..52a4f046b 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -2430,6 +2430,7 @@ static const struct eth_dev_ops qede_eth_dev_ops = {
 	.udp_tunnel_port_add = qede_udp_dst_port_add,
 	.udp_tunnel_port_del = qede_udp_dst_port_del,
 	.fw_version_get = qede_fw_version_get,
+	.get_reg = qede_get_regs,
 };
 
 static const struct eth_dev_ops qede_eth_vf_dev_ops = {
diff --git a/drivers/net/qede/qede_ethdev.h b/drivers/net/qede/qede_ethdev.h
index b988a73f2..76c5dae3b 100644
--- a/drivers/net/qede/qede_ethdev.h
+++ b/drivers/net/qede/qede_ethdev.h
@@ -214,6 +214,8 @@ struct qede_tunn_params {
 	uint16_t udp_port;
 };
 
+#define QEDE_FW_DUMP_FILE_SIZE 128
+
 /*
  *  Structure to store private data for each port.
  */
@@ -252,6 +254,7 @@ struct qede_dev {
 	char drv_ver[QEDE_PMD_DRV_VER_STR_SIZE];
 	bool vport_started;
 	int vlan_offload_mask;
+	char dump_file[QEDE_FW_DUMP_FILE_SIZE];
 	void *ethdev;
 };
 
@@ -313,4 +316,26 @@ void qede_config_accept_any_vlan(struct qede_dev *qdev, bool flg);
 int qede_ucast_filter(struct rte_eth_dev *eth_dev,
 		      struct ecore_filter_ucast *ucast,
 		      bool add);
+
+#define REGDUMP_HEADER_SIZE sizeof(u32)
+#define REGDUMP_HEADER_FEATURE_SHIFT 24
+#define REGDUMP_HEADER_ENGINE_SHIFT 31
+#define REGDUMP_HEADER_OMIT_ENGINE_SHIFT 30
+
+enum debug_print_features {
+	OLD_MODE = 0,
+	IDLE_CHK = 1,
+	GRC_DUMP = 2,
+	MCP_TRACE = 3,
+	REG_FIFO = 4,
+	PROTECTION_OVERRIDE = 5,
+	IGU_FIFO = 6,
+	PHY = 7,
+	FW_ASSERTS = 8,
+};
+
+int qede_get_regs_len(struct qede_dev *qdev);
+int qede_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs);
+void qede_config_rx_mode(struct rte_eth_dev *eth_dev);
+void qed_dbg_dump(struct rte_eth_dev *eth_dev);
 #endif /* _QEDE_ETHDEV_H_ */
diff --git a/drivers/net/qede/qede_regs.c b/drivers/net/qede/qede_regs.c
new file mode 100644
index 000000000..4409d2180
--- /dev/null
+++ b/drivers/net/qede/qede_regs.c
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Marvell Semiconductor Inc.
+ * All rights reserved.
+ * www.marvell.com
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <time.h>
+#include <rte_ethdev.h>
+#include "base/bcm_osal.h"
+#include "qede_ethdev.h"
+
+int
+qede_get_regs_len(struct qede_dev *qdev)
+{
+	struct ecore_dev *edev = &qdev->edev;
+	int cur_engine, num_of_hwfns, regs_len = 0;
+	uint8_t org_engine;
+
+	if (IS_VF(edev))
+		return 0;
+
+	if (qdev->ops && qdev->ops->common) {
+		num_of_hwfns = qdev->dev_info.common.num_hwfns;
+		org_engine = qdev->ops->common->dbg_get_debug_engine(edev);
+		for (cur_engine = 0; cur_engine < num_of_hwfns; cur_engine++) {
+			/* compute requierd buffer size for idle_chks and
+			 * grcDump for each hw function
+			 */
+			DP_NOTICE(edev, false,
+				"Calculating idle_chk and grcdump register length for current engine\n");
+			qdev->ops->common->dbg_set_debug_engine(edev,
+								cur_engine);
+			regs_len += REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_idle_chk_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_idle_chk_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_grc_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_reg_fifo_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_protection_override_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_igu_fifo_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_fw_asserts_size(edev);
+		}
+		/* compute requierd buffer size for mcp trace and add it to the
+		 * total requierd buffer size
+		 */
+		regs_len += REGDUMP_HEADER_SIZE +
+			    qdev->ops->common->dbg_mcp_trace_size(edev);
+
+		qdev->ops->common->dbg_set_debug_engine(edev, org_engine);
+	}
+	DP_NOTICE(edev, false, "Total length = %u\n", regs_len);
+
+	return regs_len;
+}
+
+static uint32_t
+qede_calc_regdump_header(enum debug_print_features feature, int engine,
+			 uint32_t feature_size, uint8_t omit_engine)
+{
+	/* insert the engine, feature and mode inside the header and
+	 * combine it with feature size
+	 */
+	return (feature_size | (feature << REGDUMP_HEADER_FEATURE_SHIFT) |
+		(omit_engine << REGDUMP_HEADER_OMIT_ENGINE_SHIFT) |
+		(engine << REGDUMP_HEADER_ENGINE_SHIFT));
+}
+
+int qede_get_regs(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs)
+{
+	struct qede_dev *qdev = eth_dev->data->dev_private;
+	struct ecore_dev *edev = &qdev->edev;
+	uint32_t *buffer = regs->data;
+	int cur_engine, num_of_hwfns;
+	/* '1' tells the parser to omit the engine number in the output files */
+	uint8_t omit_engine = 0;
+	uint8_t org_engine;
+	uint32_t feature_size;
+	uint32_t offset = 0;
+
+	if (IS_VF(edev))
+		return -ENOTSUP;
+
+	if (buffer == NULL) {
+		regs->length = qede_get_regs_len(qdev);
+		regs->width =  sizeof(uint32_t);
+		DP_INFO(edev, "Length %u\n", regs->length);
+		return 0;
+	}
+
+	memset(buffer, 0, regs->length);
+	num_of_hwfns = qdev->dev_info.common.num_hwfns;
+	if (num_of_hwfns == 1)
+		omit_engine = 1;
+
+	OSAL_MUTEX_ACQUIRE(&edev->dbg_lock);
+
+	org_engine = qdev->ops->common->dbg_get_debug_engine(edev);
+	for (cur_engine = 0; cur_engine < num_of_hwfns; cur_engine++) {
+		/* collect idle_chks and grcDump for each hw function */
+		DP_NOTICE(edev, false, "obtaining idle_chk and grcdump for current engine\n");
+		qdev->ops->common->dbg_set_debug_engine(edev, cur_engine);
+
+		/* first idle_chk */
+		qdev->ops->common->dbg_idle_chk(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(IDLE_CHK, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Idle Check1 feature_size %u\n",
+			  feature_size);
+
+		/* second idle_chk */
+		qdev->ops->common->dbg_idle_chk(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(IDLE_CHK, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Idle Check2 feature_size %u\n",
+			  feature_size);
+
+		/* reg_fifo dump */
+		qdev->ops->common->dbg_reg_fifo(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(REG_FIFO, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Reg fifo feature_size %u\n",
+			  feature_size);
+
+		/* igu_fifo dump */
+		qdev->ops->common->dbg_igu_fifo(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(IGU_FIFO, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "IGU fifo feature_size %u\n",
+			  feature_size);
+
+		/* protection_override dump */
+		qdev->ops->common->dbg_protection_override(edev,
+							   (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+		       qede_calc_regdump_header(PROTECTION_OVERRIDE, cur_engine,
+						feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Protection override feature_size %u\n",
+			  feature_size);
+
+		/* fw_asserts dump */
+		qdev->ops->common->dbg_fw_asserts(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(FW_ASSERTS, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "FW assert feature_size %u\n",
+			  feature_size);
+
+		/* grc dump */
+		qdev->ops->common->dbg_grc(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(GRC_DUMP, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "GRC dump feature_size %u\n",
+			  feature_size);
+	}
+
+	/* mcp_trace */
+	qdev->ops->common->dbg_mcp_trace(edev, (uint8_t *)buffer +
+		offset + REGDUMP_HEADER_SIZE, &feature_size);
+	*(uint32_t *)((uint8_t *)buffer + offset) =
+		qede_calc_regdump_header(MCP_TRACE, cur_engine, feature_size,
+					 omit_engine);
+	offset += (feature_size + REGDUMP_HEADER_SIZE);
+	DP_NOTICE(edev, false, "MCP trace feature_size %u\n", feature_size);
+
+	qdev->ops->common->dbg_set_debug_engine(edev, org_engine);
+
+	OSAL_MUTEX_RELEASE(&edev->dbg_lock);
+
+	return 0;
+}
+
+static void
+qede_set_fw_dump_file_name(struct qede_dev *qdev)
+{
+	time_t ltime;
+	struct tm *tm;
+
+	ltime = time(NULL);
+	tm = localtime(&ltime);
+	snprintf(qdev->dump_file, QEDE_FW_DUMP_FILE_SIZE,
+		 "qede_pmd_dump_%02d-%02d-%02d_%02d-%02d-%02d.bin",
+		 tm->tm_mon + 1, (int)tm->tm_mday, 1900 + tm->tm_year,
+		 tm->tm_hour, tm->tm_min, tm->tm_sec);
+}
+
+static int
+qede_write_fwdump(const char *dump_file, void *dump, size_t len)
+{
+	int err = 0;
+	FILE *f;
+	size_t bytes;
+
+	f = fopen(dump_file, "wb+");
+
+	if (!f) {
+		fprintf(stderr, "Can't open file %s: %s\n",
+			dump_file, strerror(errno));
+		return 1;
+	}
+	bytes = fwrite(dump, 1, len, f);
+	if (bytes != len) {
+		fprintf(stderr, "Can not write all of dump data bytes=%ld len=%ld\n",
+			bytes, len);
+		err = 1;
+	}
+
+	if (fclose(f)) {
+		fprintf(stderr, "Can't close file %s: %s\n",
+			dump_file, strerror(errno));
+		err = 1;
+	}
+
+	return err;
+}
+
+int
+qede_save_fw_dump(uint8_t port_id)
+{
+	struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id];
+	struct rte_dev_reg_info regs;
+	struct qede_dev *qdev = eth_dev->data->dev_private;
+	struct ecore_dev *edev = &qdev->edev;
+	int rc = 0;
+
+	if (!rte_eth_dev_is_valid_port(port_id)) {
+		DP_ERR(edev, "port %u invalid port ID", port_id);
+		return -ENODEV;
+	}
+
+	memset(&regs, 0, sizeof(regs));
+	regs.length = qede_get_regs_len(qdev);
+	regs.data = OSAL_ZALLOC(eth_dev, GFP_KERNEL, regs.length);
+	if (regs.data) {
+		qede_get_regs(eth_dev, &regs);
+		qede_set_fw_dump_file_name(qdev);
+		rc = qede_write_fwdump(qdev->dump_file, regs.data, regs.length);
+		if (!rc)
+			DP_NOTICE(edev, false, "FW dump written to %s file\n",
+				  qdev->dump_file);
+		OSAL_FREE(edev, regs.data);
+	}
+
+	return rc;
+}
-- 
2.18.0


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

* Re: [dpdk-dev] [PATCH v2 1/4] net/qede/base: re-arrange few structures for DDC
  2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
@ 2020-06-30 17:47   ` Jerin Jacob
  2020-07-07 21:20     ` [dpdk-dev] [EXT] " Rasesh Mody
  0 siblings, 1 reply; 37+ messages in thread
From: Jerin Jacob @ 2020-06-30 17:47 UTC (permalink / raw)
  To: Rasesh Mody
  Cc: Jerin Jacob, Ferruh Yigit, dpdk-dev, GR-Everest-DPDK-Dev, Igor Russkikh

On Tue, Jun 30, 2020 at 2:03 PM Rasesh Mody <rmody@marvell.com> wrote:
>
> This patch rearranges some of the base driver structures which will be
> also used by debug data collection (DDC) implementation. It adds a new
> file ecore_hsi_func_common.h with Physical, Virtual memory descriptors.
>
> Signed-off-by: Rasesh Mody <rmody@marvell.com>
> Signed-off-by: Igor Russkikh <irusskikh@marvell.com>


This series has shared lib failure. GCC version log at [1]


ccache gcc -Idrivers/net/qede/base/f6110d5@@qede_base@sta
-Idrivers/net/qede/base -I../drivers/net/qede/base -Ilib/librte_net
-I../lib/librte_net -I. -I.. -Iconfig -I../config
-Ilib/librte_eal/include -I../lib/librte_eal/include -Ilib/librt
e_eal/linux/include -I../lib/librte_eal/linux/include
-Ilib/librte_eal/x86/include -I../lib/librte_eal/x86/include
-Ilib/librte_eal/common -I../lib/librte_eal/common -Ilib/librte_eal
-I../lib/librte_eal -Ilib/librte_kvargs -I../lib/librte_k
vargs -Ilib/librte_metrics -I../lib/librte_metrics
-Ilib/librte_telemetry -I../lib/librte_telemetry -Ilib/librte_mbuf
-I../lib/librte_mbuf -Ilib/librte_mempool -I../lib/librte_mempool
-Ilib/librte_ring -I../lib/librte_ring -fdiagnostics-col
or=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Werror -O2
-g -include rte_config.h -Wextra -Wcast-qual -Wdeprecated
-Wformat-nonliteral -Wformat-security -Wmissing-declarations
-Wmissing-prototypes -Wnested-externs -Wold-style-
definition -Wpointer-arith -Wsign-compare -Wstrict-prototypes -Wundef
-Wwrite-strings -Wno-address-of-packed-member -Wno-packed-not-aligned
-Wno-missing-field-initializers -Wno-zero-length-bounds -D_GNU_SOURCE
-fPIC -march=native -DALLOW_EX
PERIMENTAL_API -DALLOW_INTERNAL_API -Wno-format-truncation
-Wno-unused-parameter -Wno-sign-compare -Wno-missing-prototypes
-Wno-cast-qual -Wno-unused-function -Wno-unused-variable
-Wno-strict-aliasing -Wno-missing-prototypes -Wno-unused-val
ue -Wno-format-nonliteral -Wno-shift-negative-value
-Wno-unused-but-set-variable -Wno-missing-declarations
-Wno-maybe-uninitialized -Wno-strict-prototypes
-Wno-shift-negative-value -Wno-implicit-fallthrough
-Wno-format-extra-args -Wno-empty
-body -MD -MQ 'drivers/net/qede/base/f6110d5@@qede_base@sta/ecore_dev.c.o'
-MF 'drivers/net/qede/base/f6110d5@@qede_base@sta/ecore_dev.c.o.d' -o
'drivers/net/qede/base/f6110d5@@qede_base@sta/ecore_dev.c.o' -c
../drivers/net/qede/base/ecore_
dev.c
../drivers/net/qede/base/ecore_dev.c: In function ‘ecore_resc_alloc’:
../drivers/net/qede/base/ecore_dev.c:2515:6: error: implicit
conversion from ‘enum dbg_status’ to ‘enum _ecore_status_t’
[-Werror=enum-conversion]
 2515 |   rc = OSAL_DBG_ALLOC_USER_DATA(p_hwfn, &p_hwfn->dbg_user_info);
      |      ^
../drivers/net/qede/base/ecore_dev.c:2522:6: error: implicit
conversion from ‘enum dbg_status’ to ‘enum _ecore_status_t’
[-Werror=enum-conversion]
 2522 |   rc = OSAL_DBG_ALLOC_USER_DATA(p_hwfn, &p_hwfn->dbg_user_info);
      |      ^
cc1: all warnings being treated as errors
[1612/2184] Linking static target drivers/libtmp_rte_pmd_null_crypto.a

[1]
[master]dell[dpdk-next-net-mrvl] $ gcc -v
Using built-in specs.
COLLECT_GCC=/usr/bin/gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --prefix=/usr
--libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man
--infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/
--enable-languages=c,c++,ada,fortran,go,lto,objc
,obj-c++,d --with-isl --with-linker-hash-style=gnu --with-system-zlib
--enable-__cxa_atexit --enable-cet=auto --enable-checking=release
--enable-clocale=gnu --enable-default-pie --enable-default-ssp
--enable-gnu-indirect-function --enable-g
nu-unique-object --enable-install-libiberty --enable-linker-build-id
--enable-lto --enable-multilib --enable-plugin --enable-shared
--enable-threads=posix --disable-libssp --disable-libstdcxx-pch
--disable-libunwind-exceptions --disable-wer
ror gdc_include_dir=/usr/include/dlang/gdc
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 10.1.0 (GCC)


> ---
>  drivers/net/qede/base/ecore.h                 |   2 +
>  drivers/net/qede/base/ecore_cxt.c             | 140 ++----------------
>  drivers/net/qede/base/ecore_cxt.h             | 135 ++++++++++++++++-
>  drivers/net/qede/base/ecore_hsi_func_common.h |  17 +++
>  drivers/net/qede/base/ecore_init_fw_funcs.h   |   7 -
>  5 files changed, 163 insertions(+), 138 deletions(-)
>  create mode 100644 drivers/net/qede/base/ecore_hsi_func_common.h
>
> diff --git a/drivers/net/qede/base/ecore.h b/drivers/net/qede/base/ecore.h
> index 498bb6f09..dc5fe4d80 100644
> --- a/drivers/net/qede/base/ecore.h
> +++ b/drivers/net/qede/base/ecore.h
> @@ -24,6 +24,7 @@
>  #include "ecore_hsi_debug_tools.h"
>  #include "ecore_hsi_init_func.h"
>  #include "ecore_hsi_init_tool.h"
> +#include "ecore_hsi_func_common.h"
>  #include "ecore_proto_if.h"
>  #include "mcp_public.h"
>
> @@ -671,6 +672,7 @@ struct ecore_hwfn {
>
>         struct dbg_tools_data           dbg_info;
>         void                            *dbg_user_info;
> +       struct virt_mem_desc            dbg_arrays[MAX_BIN_DBG_BUFFER_TYPE];
>
>         struct z_stream_s               *stream;
>
> diff --git a/drivers/net/qede/base/ecore_cxt.c b/drivers/net/qede/base/ecore_cxt.c
> index dda47ea67..23f37b1bf 100644
> --- a/drivers/net/qede/base/ecore_cxt.c
> +++ b/drivers/net/qede/base/ecore_cxt.c
> @@ -20,12 +20,6 @@
>  #include "ecore_sriov.h"
>  #include "ecore_mcp.h"
>
> -/* Max number of connection types in HW (DQ/CDU etc.) */
> -#define MAX_CONN_TYPES         PROTOCOLID_COMMON
> -#define NUM_TASK_TYPES         2
> -#define NUM_TASK_PF_SEGMENTS   4
> -#define NUM_TASK_VF_SEGMENTS   1
> -
>  /* Doorbell-Queue constants */
>  #define DQ_RANGE_SHIFT 4
>  #define DQ_RANGE_ALIGN (1 << DQ_RANGE_SHIFT)
> @@ -90,128 +84,6 @@ struct src_ent {
>  /* Alignment is inherent to the type1_task_context structure */
>  #define TYPE1_TASK_CXT_SIZE(p_hwfn) sizeof(union type1_task_context)
>
> -/* PF per protocl configuration object */
> -#define TASK_SEGMENTS   (NUM_TASK_PF_SEGMENTS + NUM_TASK_VF_SEGMENTS)
> -#define TASK_SEGMENT_VF (NUM_TASK_PF_SEGMENTS)
> -
> -struct ecore_tid_seg {
> -       u32 count;
> -       u8 type;
> -       bool has_fl_mem;
> -};
> -
> -struct ecore_conn_type_cfg {
> -       u32 cid_count;
> -       u32 cids_per_vf;
> -       struct ecore_tid_seg tid_seg[TASK_SEGMENTS];
> -};
> -
> -/* ILT Client configuration,
> - * Per connection type (protocol) resources (cids, tis, vf cids etc.)
> - * 1 - for connection context (CDUC) and for each task context we need two
> - * values, for regular task context and for force load memory
> - */
> -#define ILT_CLI_PF_BLOCKS      (1 + NUM_TASK_PF_SEGMENTS * 2)
> -#define ILT_CLI_VF_BLOCKS      (1 + NUM_TASK_VF_SEGMENTS * 2)
> -#define CDUC_BLK               (0)
> -#define SRQ_BLK                        (0)
> -#define CDUT_SEG_BLK(n)                (1 + (u8)(n))
> -#define CDUT_FL_SEG_BLK(n, X)  (1 + (n) + NUM_TASK_##X##_SEGMENTS)
> -
> -struct ilt_cfg_pair {
> -       u32 reg;
> -       u32 val;
> -};
> -
> -struct ecore_ilt_cli_blk {
> -       u32 total_size;         /* 0 means not active */
> -       u32 real_size_in_page;
> -       u32 start_line;
> -       u32 dynamic_line_offset;
> -       u32 dynamic_line_cnt;
> -};
> -
> -struct ecore_ilt_client_cfg {
> -       bool active;
> -
> -       /* ILT boundaries */
> -       struct ilt_cfg_pair first;
> -       struct ilt_cfg_pair last;
> -       struct ilt_cfg_pair p_size;
> -
> -       /* ILT client blocks for PF */
> -       struct ecore_ilt_cli_blk pf_blks[ILT_CLI_PF_BLOCKS];
> -       u32 pf_total_lines;
> -
> -       /* ILT client blocks for VFs */
> -       struct ecore_ilt_cli_blk vf_blks[ILT_CLI_VF_BLOCKS];
> -       u32 vf_total_lines;
> -};
> -
> -#define MAP_WORD_SIZE          sizeof(unsigned long)
> -#define BITS_PER_MAP_WORD      (MAP_WORD_SIZE * 8)
> -
> -struct ecore_cid_acquired_map {
> -       u32 start_cid;
> -       u32 max_count;
> -       u32 *cid_map;
> -};
> -
> -struct ecore_src_t2 {
> -       struct phys_mem_desc    *dma_mem;
> -       u32                     num_pages;
> -       u64                     first_free;
> -       u64                     last_free;
> -};
> -
> -struct ecore_cxt_mngr {
> -       /* Per protocl configuration */
> -       struct ecore_conn_type_cfg conn_cfg[MAX_CONN_TYPES];
> -
> -       /* computed ILT structure */
> -       struct ecore_ilt_client_cfg clients[ILT_CLI_MAX];
> -
> -       /* Task type sizes */
> -       u32 task_type_size[NUM_TASK_TYPES];
> -
> -       /* total number of VFs for this hwfn -
> -        * ALL VFs are symmetric in terms of HW resources
> -        */
> -       u32 vf_count;
> -
> -       /* Acquired CIDs */
> -       struct ecore_cid_acquired_map acquired[MAX_CONN_TYPES];
> -       struct ecore_cid_acquired_map *acquired_vf[MAX_CONN_TYPES];
> -
> -       /* ILT  shadow table */
> -       struct phys_mem_desc            *ilt_shadow;
> -       u32 pf_start_line;
> -
> -       /* Mutex for a dynamic ILT allocation */
> -       osal_mutex_t mutex;
> -
> -       /* SRC T2 */
> -       struct ecore_src_t2             src_t2;
> -
> -       /* The infrastructure originally was very generic and context/task
> -        * oriented - per connection-type we would set how many of those
> -        * are needed, and later when determining how much memory we're
> -        * needing for a given block we'd iterate over all the relevant
> -        * connection-types.
> -        * But since then we've had some additional resources, some of which
> -        * require memory which is indepent of the general context/task
> -        * scheme. We add those here explicitly per-feature.
> -        */
> -
> -       /* total number of SRQ's for this hwfn */
> -       u32                             srq_count;
> -
> -       /* Maximal number of L2 steering filters */
> -       u32                             arfs_count;
> -
> -       /* TODO - VF arfs filters ? */
> -};
> -
>  static OSAL_INLINE bool tm_cid_proto(enum protocol_type type)
>  {
>         return type == PROTOCOLID_TOE;
> @@ -945,7 +817,7 @@ static enum _ecore_status_t ecore_cxt_src_t2_alloc(struct ecore_hwfn *p_hwfn)
>  }
>
>  #define for_each_ilt_valid_client(pos, clients)                \
> -       for (pos = 0; pos < ILT_CLI_MAX; pos++)         \
> +       for (pos = 0; pos < MAX_ILT_CLIENTS; pos++)             \
>                 if (!clients[pos].active) {             \
>                         continue;                       \
>                 } else                                  \
> @@ -1238,7 +1110,7 @@ enum _ecore_status_t ecore_cxt_mngr_alloc(struct ecore_hwfn *p_hwfn)
>         clients[ILT_CLI_TSDM].p_size.reg = ILT_CFG_REG(TSDM, P_SIZE);
>
>         /* default ILT page size for all clients is 64K */
> -       for (i = 0; i < ILT_CLI_MAX; i++)
> +       for (i = 0; i < MAX_ILT_CLIENTS; i++)
>                 p_mngr->clients[i].p_size.val = ILT_DEFAULT_HW_P_SIZE;
>
>         /* due to removal of ISCSI/FCoE files union type0_task_context
> @@ -2306,3 +2178,11 @@ ecore_cxt_free_ilt_range(struct ecore_hwfn *p_hwfn,
>
>         return ECORE_SUCCESS;
>  }
> +
> +static u16 ecore_blk_calculate_pages(struct ecore_ilt_cli_blk *p_blk)
> +{
> +       if (p_blk->real_size_in_page == 0)
> +               return 0;
> +
> +       return DIV_ROUND_UP(p_blk->total_size, p_blk->real_size_in_page);
> +}
> diff --git a/drivers/net/qede/base/ecore_cxt.h b/drivers/net/qede/base/ecore_cxt.h
> index 55f08027d..7b91b953e 100644
> --- a/drivers/net/qede/base/ecore_cxt.h
> +++ b/drivers/net/qede/base/ecore_cxt.h
> @@ -31,7 +31,7 @@ enum ilt_clients {
>         ILT_CLI_TSDM,
>         ILT_CLI_RGFS,
>         ILT_CLI_TGFS,
> -       ILT_CLI_MAX
> +       MAX_ILT_CLIENTS
>  };
>
>  u32 ecore_cxt_get_proto_cid_count(struct ecore_hwfn *p_hwfn,
> @@ -212,4 +212,137 @@ enum _ecore_status_t ecore_cxt_free_proto_ilt(struct ecore_hwfn *p_hwfn,
>  #define ECORE_CTX_WORKING_MEM 0
>  #define ECORE_CTX_FL_MEM 1
>
> +/* Max number of connection types in HW (DQ/CDU etc.) */
> +#define MAX_CONN_TYPES         PROTOCOLID_COMMON
> +#define NUM_TASK_TYPES         2
> +#define NUM_TASK_PF_SEGMENTS   4
> +#define NUM_TASK_VF_SEGMENTS   1
> +
> +/* PF per protocl configuration object */
> +#define TASK_SEGMENTS   (NUM_TASK_PF_SEGMENTS + NUM_TASK_VF_SEGMENTS)
> +#define TASK_SEGMENT_VF (NUM_TASK_PF_SEGMENTS)
> +
> +struct ecore_tid_seg {
> +       u32 count;
> +       u8 type;
> +       bool has_fl_mem;
> +};
> +
> +struct ecore_conn_type_cfg {
> +       u32 cid_count;
> +       u32 cids_per_vf;
> +       struct ecore_tid_seg tid_seg[TASK_SEGMENTS];
> +};
> +
> +/* ILT Client configuration,
> + * Per connection type (protocol) resources (cids, tis, vf cids etc.)
> + * 1 - for connection context (CDUC) and for each task context we need two
> + * values, for regular task context and for force load memory
> + */
> +#define ILT_CLI_PF_BLOCKS      (1 + NUM_TASK_PF_SEGMENTS * 2)
> +#define ILT_CLI_VF_BLOCKS      (1 + NUM_TASK_VF_SEGMENTS * 2)
> +#define CDUC_BLK               (0)
> +#define SRQ_BLK                        (0)
> +#define CDUT_SEG_BLK(n)                (1 + (u8)(n))
> +#define CDUT_FL_SEG_BLK(n, X)  (1 + (n) + NUM_TASK_##X##_SEGMENTS)
> +
> +struct ilt_cfg_pair {
> +       u32 reg;
> +       u32 val;
> +};
> +
> +struct ecore_ilt_cli_blk {
> +       u32 total_size;         /* 0 means not active */
> +       u32 real_size_in_page;
> +       u32 start_line;
> +       u32 dynamic_line_offset;
> +       u32 dynamic_line_cnt;
> +};
> +
> +struct ecore_ilt_client_cfg {
> +       bool active;
> +
> +       /* ILT boundaries */
> +       struct ilt_cfg_pair first;
> +       struct ilt_cfg_pair last;
> +       struct ilt_cfg_pair p_size;
> +
> +       /* ILT client blocks for PF */
> +       struct ecore_ilt_cli_blk pf_blks[ILT_CLI_PF_BLOCKS];
> +       u32 pf_total_lines;
> +
> +       /* ILT client blocks for VFs */
> +       struct ecore_ilt_cli_blk vf_blks[ILT_CLI_VF_BLOCKS];
> +       u32 vf_total_lines;
> +};
> +
> +#define MAP_WORD_SIZE          sizeof(unsigned long)
> +#define BITS_PER_MAP_WORD      (MAP_WORD_SIZE * 8)
> +
> +struct ecore_cid_acquired_map {
> +       u32 start_cid;
> +       u32 max_count;
> +       u32 *cid_map;
> +};
> +
> +struct ecore_src_t2 {
> +       struct phys_mem_desc    *dma_mem;
> +       u32                     num_pages;
> +       u64                     first_free;
> +       u64                     last_free;
> +};
> +
> +struct ecore_cxt_mngr {
> +       /* Per protocl configuration */
> +       struct ecore_conn_type_cfg      conn_cfg[MAX_CONN_TYPES];
> +
> +       /* computed ILT structure */
> +       struct ecore_ilt_client_cfg     clients[MAX_ILT_CLIENTS];
> +
> +       /* Task type sizes */
> +       u32                             task_type_size[NUM_TASK_TYPES];
> +
> +       /* total number of VFs for this hwfn -
> +        * ALL VFs are symmetric in terms of HW resources
> +        */
> +       u32                             vf_count;
> +       u32                             first_vf_in_pf;
> +
> +       /* Acquired CIDs */
> +       struct ecore_cid_acquired_map acquired[MAX_CONN_TYPES];
> +       struct ecore_cid_acquired_map *acquired_vf[MAX_CONN_TYPES];
> +
> +       /* ILT  shadow table */
> +       struct phys_mem_desc            *ilt_shadow;
> +       u32                             ilt_shadow_size;
> +       u32                             pf_start_line;
> +
> +       /* Mutex for a dynamic ILT allocation */
> +       osal_mutex_t mutex;
> +
> +       /* SRC T2 */
> +       struct ecore_src_t2             src_t2;
> +
> +       /* The infrastructure originally was very generic and context/task
> +        * oriented - per connection-type we would set how many of those
> +        * are needed, and later when determining how much memory we're
> +        * needing for a given block we'd iterate over all the relevant
> +        * connection-types.
> +        * But since then we've had some additional resources, some of which
> +        * require memory which is indepent of the general context/task
> +        * scheme. We add those here explicitly per-feature.
> +        */
> +
> +       /* total number of SRQ's for this hwfn */
> +       u32                             srq_count;
> +
> +       /* Maximal number of L2 steering filters */
> +       u32                             arfs_count;
> +
> +       /* TODO - VF arfs filters ? */
> +
> +       u8                              task_type_id;
> +       u16                             task_ctx_size;
> +       u16                             conn_ctx_size;
> +};
>  #endif /* _ECORE_CID_ */
> diff --git a/drivers/net/qede/base/ecore_hsi_func_common.h b/drivers/net/qede/base/ecore_hsi_func_common.h
> new file mode 100644
> index 000000000..2cd175163
> --- /dev/null
> +++ b/drivers/net/qede/base/ecore_hsi_func_common.h
> @@ -0,0 +1,17 @@
> +#ifndef _HSI_FUNC_COMMON_H
> +#define _HSI_FUNC_COMMON_H
> +
> +/* Physical memory descriptor */
> +struct phys_mem_desc {
> +       dma_addr_t phys_addr;
> +       void *virt_addr;
> +       u32 size; /* In bytes */
> +};
> +
> +/* Virtual memory descriptor */
> +struct virt_mem_desc {
> +       void *ptr;
> +       u32 size; /* In bytes */
> +};
> +
> +#endif
> diff --git a/drivers/net/qede/base/ecore_init_fw_funcs.h b/drivers/net/qede/base/ecore_init_fw_funcs.h
> index 912451662..a393d088f 100644
> --- a/drivers/net/qede/base/ecore_init_fw_funcs.h
> +++ b/drivers/net/qede/base/ecore_init_fw_funcs.h
> @@ -9,13 +9,6 @@
>  #include "ecore_hsi_common.h"
>  #include "ecore_hsi_eth.h"
>
> -/* Physical memory descriptor */
> -struct phys_mem_desc {
> -       dma_addr_t phys_addr;
> -       void *virt_addr;
> -       u32 size; /* In bytes */
> -};
> -
>  /* Returns the VOQ based on port and TC */
>  #define VOQ(port, tc, max_phys_tcs_per_port) \
>         ((tc) == PURE_LB_TC ? NUM_OF_PHYS_TCS * MAX_NUM_PORTS_BB + (port) : \
> --
> 2.18.0
>

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

* [dpdk-dev] [PATCH v3 0/4] net/qede: add FW debug data collection support
  2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 0/4] net/qede: add FW debug data collection support Rasesh Mody
@ 2020-07-07 20:18   ` Rasesh Mody
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 " Rasesh Mody
                       ` (4 more replies)
  2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
                     ` (3 subsequent siblings)
  4 siblings, 5 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-07-07 20:18 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev

Hi Jerin, Ferruh,

This patch-set adds an ability to collect FW and HW Debug Data/Dump
(referred to as FW/HW Dump) to QEDE PMD. The dump is collected either
when PMD detects an error or when a DPDK application asks PMD to
collect it upon detection of application error. This FW/HW Dump
needs to be saved to a file and sent to Marvell for analysis.

Please apply to dpdk-next-net-mrvl and dpdk-next-net trees.

v3:
Fixed gcc-10 compilation issue.

v2:
Addressed checkpatch issues and updated supported features.

Thanks!
-Rasesh

Rasesh Mody (4):
  net/qede/base: re-arrange few structures for DDC
  net/qede/base: add changes for debug data collection
  net/qede: add infrastructure for debug data collection
  net/qede: add support for get register operation

 doc/guides/nics/features/qede.ini             |    1 +
 drivers/net/qede/Makefile                     |    5 +-
 drivers/net/qede/base/bcm_osal.c              |   31 +
 drivers/net/qede/base/bcm_osal.h              |   18 +-
 drivers/net/qede/base/common_hsi.h            |    1 +
 drivers/net/qede/base/ecore.h                 |   54 +-
 drivers/net/qede/base/ecore_cxt.c             |  200 +-
 drivers/net/qede/base/ecore_cxt.h             |  140 +-
 drivers/net/qede/base/ecore_dev.c             |   26 +-
 drivers/net/qede/base/ecore_hsi_common.h      |  184 +-
 drivers/net/qede/base/ecore_hsi_debug_tools.h |    2 +-
 drivers/net/qede/base/ecore_hsi_func_common.h |   17 +
 drivers/net/qede/base/ecore_init_fw_funcs.h   |    7 -
 drivers/net/qede/base/ecore_mcp.c             |  211 +
 drivers/net/qede/base/ecore_mcp_api.h         |   37 +
 drivers/net/qede/base/ecore_status.h          |    2 +
 drivers/net/qede/base/reg_addr.h              |  846 ++
 drivers/net/qede/qede_debug.c                 | 8120 +++++++++++++++++
 drivers/net/qede/qede_debug.h                 |  759 ++
 drivers/net/qede/qede_ethdev.c                |    2 +-
 drivers/net/qede/qede_ethdev.h                |   25 +
 drivers/net/qede/qede_if.h                    |   45 +
 drivers/net/qede/qede_main.c                  |   42 +-
 drivers/net/qede/qede_regs.c                  |  271 +
 24 files changed, 10883 insertions(+), 163 deletions(-)
 create mode 100644 drivers/net/qede/base/ecore_hsi_func_common.h
 create mode 100644 drivers/net/qede/qede_debug.c
 create mode 100644 drivers/net/qede/qede_debug.h
 create mode 100644 drivers/net/qede/qede_regs.c

-- 
2.18.0


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

* [dpdk-dev] [PATCH v3 1/4] net/qede/base: re-arrange few structures for DDC
  2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 0/4] net/qede: add FW debug data collection support Rasesh Mody
  2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 " Rasesh Mody
@ 2020-07-07 20:18   ` Rasesh Mody
  2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 2/4] net/qede/base: add changes for debug data collection Rasesh Mody
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-07-07 20:18 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

This patch rearranges some of the base driver structures which will be
also used by debug data collection (DDC) implementation. It adds a new
file ecore_hsi_func_common.h with Physical, Virtual memory descriptors.

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/qede/base/ecore.h                 |   2 +
 drivers/net/qede/base/ecore_cxt.c             | 140 ++----------------
 drivers/net/qede/base/ecore_cxt.h             | 135 ++++++++++++++++-
 drivers/net/qede/base/ecore_dev.c             |  13 +-
 drivers/net/qede/base/ecore_hsi_func_common.h |  17 +++
 drivers/net/qede/base/ecore_init_fw_funcs.h   |   7 -
 6 files changed, 172 insertions(+), 142 deletions(-)
 create mode 100644 drivers/net/qede/base/ecore_hsi_func_common.h

diff --git a/drivers/net/qede/base/ecore.h b/drivers/net/qede/base/ecore.h
index 498bb6f09..dc5fe4d80 100644
--- a/drivers/net/qede/base/ecore.h
+++ b/drivers/net/qede/base/ecore.h
@@ -24,6 +24,7 @@
 #include "ecore_hsi_debug_tools.h"
 #include "ecore_hsi_init_func.h"
 #include "ecore_hsi_init_tool.h"
+#include "ecore_hsi_func_common.h"
 #include "ecore_proto_if.h"
 #include "mcp_public.h"
 
@@ -671,6 +672,7 @@ struct ecore_hwfn {
 
 	struct dbg_tools_data		dbg_info;
 	void				*dbg_user_info;
+	struct virt_mem_desc		dbg_arrays[MAX_BIN_DBG_BUFFER_TYPE];
 
 	struct z_stream_s		*stream;
 
diff --git a/drivers/net/qede/base/ecore_cxt.c b/drivers/net/qede/base/ecore_cxt.c
index dda47ea67..23f37b1bf 100644
--- a/drivers/net/qede/base/ecore_cxt.c
+++ b/drivers/net/qede/base/ecore_cxt.c
@@ -20,12 +20,6 @@
 #include "ecore_sriov.h"
 #include "ecore_mcp.h"
 
-/* Max number of connection types in HW (DQ/CDU etc.) */
-#define MAX_CONN_TYPES		PROTOCOLID_COMMON
-#define NUM_TASK_TYPES		2
-#define NUM_TASK_PF_SEGMENTS	4
-#define NUM_TASK_VF_SEGMENTS	1
-
 /* Doorbell-Queue constants */
 #define DQ_RANGE_SHIFT	4
 #define DQ_RANGE_ALIGN	(1 << DQ_RANGE_SHIFT)
@@ -90,128 +84,6 @@ struct src_ent {
 /* Alignment is inherent to the type1_task_context structure */
 #define TYPE1_TASK_CXT_SIZE(p_hwfn) sizeof(union type1_task_context)
 
-/* PF per protocl configuration object */
-#define TASK_SEGMENTS   (NUM_TASK_PF_SEGMENTS + NUM_TASK_VF_SEGMENTS)
-#define TASK_SEGMENT_VF (NUM_TASK_PF_SEGMENTS)
-
-struct ecore_tid_seg {
-	u32 count;
-	u8 type;
-	bool has_fl_mem;
-};
-
-struct ecore_conn_type_cfg {
-	u32 cid_count;
-	u32 cids_per_vf;
-	struct ecore_tid_seg tid_seg[TASK_SEGMENTS];
-};
-
-/* ILT Client configuration,
- * Per connection type (protocol) resources (cids, tis, vf cids etc.)
- * 1 - for connection context (CDUC) and for each task context we need two
- * values, for regular task context and for force load memory
- */
-#define ILT_CLI_PF_BLOCKS	(1 + NUM_TASK_PF_SEGMENTS * 2)
-#define ILT_CLI_VF_BLOCKS	(1 + NUM_TASK_VF_SEGMENTS * 2)
-#define CDUC_BLK		(0)
-#define SRQ_BLK			(0)
-#define CDUT_SEG_BLK(n)		(1 + (u8)(n))
-#define CDUT_FL_SEG_BLK(n, X)	(1 + (n) + NUM_TASK_##X##_SEGMENTS)
-
-struct ilt_cfg_pair {
-	u32 reg;
-	u32 val;
-};
-
-struct ecore_ilt_cli_blk {
-	u32 total_size;		/* 0 means not active */
-	u32 real_size_in_page;
-	u32 start_line;
-	u32 dynamic_line_offset;
-	u32 dynamic_line_cnt;
-};
-
-struct ecore_ilt_client_cfg {
-	bool active;
-
-	/* ILT boundaries */
-	struct ilt_cfg_pair first;
-	struct ilt_cfg_pair last;
-	struct ilt_cfg_pair p_size;
-
-	/* ILT client blocks for PF */
-	struct ecore_ilt_cli_blk pf_blks[ILT_CLI_PF_BLOCKS];
-	u32 pf_total_lines;
-
-	/* ILT client blocks for VFs */
-	struct ecore_ilt_cli_blk vf_blks[ILT_CLI_VF_BLOCKS];
-	u32 vf_total_lines;
-};
-
-#define MAP_WORD_SIZE		sizeof(unsigned long)
-#define BITS_PER_MAP_WORD	(MAP_WORD_SIZE * 8)
-
-struct ecore_cid_acquired_map {
-	u32 start_cid;
-	u32 max_count;
-	u32 *cid_map;
-};
-
-struct ecore_src_t2 {
-	struct phys_mem_desc	*dma_mem;
-	u32			num_pages;
-	u64			first_free;
-	u64			last_free;
-};
-
-struct ecore_cxt_mngr {
-	/* Per protocl configuration */
-	struct ecore_conn_type_cfg conn_cfg[MAX_CONN_TYPES];
-
-	/* computed ILT structure */
-	struct ecore_ilt_client_cfg clients[ILT_CLI_MAX];
-
-	/* Task type sizes */
-	u32 task_type_size[NUM_TASK_TYPES];
-
-	/* total number of VFs for this hwfn -
-	 * ALL VFs are symmetric in terms of HW resources
-	 */
-	u32 vf_count;
-
-	/* Acquired CIDs */
-	struct ecore_cid_acquired_map acquired[MAX_CONN_TYPES];
-	struct ecore_cid_acquired_map *acquired_vf[MAX_CONN_TYPES];
-
-	/* ILT  shadow table */
-	struct phys_mem_desc		*ilt_shadow;
-	u32 pf_start_line;
-
-	/* Mutex for a dynamic ILT allocation */
-	osal_mutex_t mutex;
-
-	/* SRC T2 */
-	struct ecore_src_t2		src_t2;
-
-	/* The infrastructure originally was very generic and context/task
-	 * oriented - per connection-type we would set how many of those
-	 * are needed, and later when determining how much memory we're
-	 * needing for a given block we'd iterate over all the relevant
-	 * connection-types.
-	 * But since then we've had some additional resources, some of which
-	 * require memory which is indepent of the general context/task
-	 * scheme. We add those here explicitly per-feature.
-	 */
-
-	/* total number of SRQ's for this hwfn */
-	u32				srq_count;
-
-	/* Maximal number of L2 steering filters */
-	u32				arfs_count;
-
-	/* TODO - VF arfs filters ? */
-};
-
 static OSAL_INLINE bool tm_cid_proto(enum protocol_type type)
 {
 	return type == PROTOCOLID_TOE;
@@ -945,7 +817,7 @@ static enum _ecore_status_t ecore_cxt_src_t2_alloc(struct ecore_hwfn *p_hwfn)
 }
 
 #define for_each_ilt_valid_client(pos, clients)		\
-	for (pos = 0; pos < ILT_CLI_MAX; pos++)		\
+	for (pos = 0; pos < MAX_ILT_CLIENTS; pos++)		\
 		if (!clients[pos].active) {		\
 			continue;			\
 		} else					\
@@ -1238,7 +1110,7 @@ enum _ecore_status_t ecore_cxt_mngr_alloc(struct ecore_hwfn *p_hwfn)
 	clients[ILT_CLI_TSDM].p_size.reg = ILT_CFG_REG(TSDM, P_SIZE);
 
 	/* default ILT page size for all clients is 64K */
-	for (i = 0; i < ILT_CLI_MAX; i++)
+	for (i = 0; i < MAX_ILT_CLIENTS; i++)
 		p_mngr->clients[i].p_size.val = ILT_DEFAULT_HW_P_SIZE;
 
 	/* due to removal of ISCSI/FCoE files union type0_task_context
@@ -2306,3 +2178,11 @@ ecore_cxt_free_ilt_range(struct ecore_hwfn *p_hwfn,
 
 	return ECORE_SUCCESS;
 }
+
+static u16 ecore_blk_calculate_pages(struct ecore_ilt_cli_blk *p_blk)
+{
+	if (p_blk->real_size_in_page == 0)
+		return 0;
+
+	return DIV_ROUND_UP(p_blk->total_size, p_blk->real_size_in_page);
+}
diff --git a/drivers/net/qede/base/ecore_cxt.h b/drivers/net/qede/base/ecore_cxt.h
index 55f08027d..7b91b953e 100644
--- a/drivers/net/qede/base/ecore_cxt.h
+++ b/drivers/net/qede/base/ecore_cxt.h
@@ -31,7 +31,7 @@ enum ilt_clients {
 	ILT_CLI_TSDM,
 	ILT_CLI_RGFS,
 	ILT_CLI_TGFS,
-	ILT_CLI_MAX
+	MAX_ILT_CLIENTS
 };
 
 u32 ecore_cxt_get_proto_cid_count(struct ecore_hwfn *p_hwfn,
@@ -212,4 +212,137 @@ enum _ecore_status_t ecore_cxt_free_proto_ilt(struct ecore_hwfn *p_hwfn,
 #define ECORE_CTX_WORKING_MEM 0
 #define ECORE_CTX_FL_MEM 1
 
+/* Max number of connection types in HW (DQ/CDU etc.) */
+#define MAX_CONN_TYPES		PROTOCOLID_COMMON
+#define NUM_TASK_TYPES		2
+#define NUM_TASK_PF_SEGMENTS	4
+#define NUM_TASK_VF_SEGMENTS	1
+
+/* PF per protocl configuration object */
+#define TASK_SEGMENTS   (NUM_TASK_PF_SEGMENTS + NUM_TASK_VF_SEGMENTS)
+#define TASK_SEGMENT_VF (NUM_TASK_PF_SEGMENTS)
+
+struct ecore_tid_seg {
+	u32 count;
+	u8 type;
+	bool has_fl_mem;
+};
+
+struct ecore_conn_type_cfg {
+	u32 cid_count;
+	u32 cids_per_vf;
+	struct ecore_tid_seg tid_seg[TASK_SEGMENTS];
+};
+
+/* ILT Client configuration,
+ * Per connection type (protocol) resources (cids, tis, vf cids etc.)
+ * 1 - for connection context (CDUC) and for each task context we need two
+ * values, for regular task context and for force load memory
+ */
+#define ILT_CLI_PF_BLOCKS	(1 + NUM_TASK_PF_SEGMENTS * 2)
+#define ILT_CLI_VF_BLOCKS	(1 + NUM_TASK_VF_SEGMENTS * 2)
+#define CDUC_BLK		(0)
+#define SRQ_BLK			(0)
+#define CDUT_SEG_BLK(n)		(1 + (u8)(n))
+#define CDUT_FL_SEG_BLK(n, X)	(1 + (n) + NUM_TASK_##X##_SEGMENTS)
+
+struct ilt_cfg_pair {
+	u32 reg;
+	u32 val;
+};
+
+struct ecore_ilt_cli_blk {
+	u32 total_size;		/* 0 means not active */
+	u32 real_size_in_page;
+	u32 start_line;
+	u32 dynamic_line_offset;
+	u32 dynamic_line_cnt;
+};
+
+struct ecore_ilt_client_cfg {
+	bool active;
+
+	/* ILT boundaries */
+	struct ilt_cfg_pair first;
+	struct ilt_cfg_pair last;
+	struct ilt_cfg_pair p_size;
+
+	/* ILT client blocks for PF */
+	struct ecore_ilt_cli_blk pf_blks[ILT_CLI_PF_BLOCKS];
+	u32 pf_total_lines;
+
+	/* ILT client blocks for VFs */
+	struct ecore_ilt_cli_blk vf_blks[ILT_CLI_VF_BLOCKS];
+	u32 vf_total_lines;
+};
+
+#define MAP_WORD_SIZE		sizeof(unsigned long)
+#define BITS_PER_MAP_WORD	(MAP_WORD_SIZE * 8)
+
+struct ecore_cid_acquired_map {
+	u32 start_cid;
+	u32 max_count;
+	u32 *cid_map;
+};
+
+struct ecore_src_t2 {
+	struct phys_mem_desc	*dma_mem;
+	u32			num_pages;
+	u64			first_free;
+	u64			last_free;
+};
+
+struct ecore_cxt_mngr {
+	/* Per protocl configuration */
+	struct ecore_conn_type_cfg	conn_cfg[MAX_CONN_TYPES];
+
+	/* computed ILT structure */
+	struct ecore_ilt_client_cfg	clients[MAX_ILT_CLIENTS];
+
+	/* Task type sizes */
+	u32				task_type_size[NUM_TASK_TYPES];
+
+	/* total number of VFs for this hwfn -
+	 * ALL VFs are symmetric in terms of HW resources
+	 */
+	u32				vf_count;
+	u32				first_vf_in_pf;
+
+	/* Acquired CIDs */
+	struct ecore_cid_acquired_map acquired[MAX_CONN_TYPES];
+	struct ecore_cid_acquired_map *acquired_vf[MAX_CONN_TYPES];
+
+	/* ILT  shadow table */
+	struct phys_mem_desc		*ilt_shadow;
+	u32				ilt_shadow_size;
+	u32				pf_start_line;
+
+	/* Mutex for a dynamic ILT allocation */
+	osal_mutex_t mutex;
+
+	/* SRC T2 */
+	struct ecore_src_t2		src_t2;
+
+	/* The infrastructure originally was very generic and context/task
+	 * oriented - per connection-type we would set how many of those
+	 * are needed, and later when determining how much memory we're
+	 * needing for a given block we'd iterate over all the relevant
+	 * connection-types.
+	 * But since then we've had some additional resources, some of which
+	 * require memory which is indepent of the general context/task
+	 * scheme. We add those here explicitly per-feature.
+	 */
+
+	/* total number of SRQ's for this hwfn */
+	u32				srq_count;
+
+	/* Maximal number of L2 steering filters */
+	u32				arfs_count;
+
+	/* TODO - VF arfs filters ? */
+
+	u8				task_type_id;
+	u16				task_ctx_size;
+	u16				conn_ctx_size;
+};
 #endif /* _ECORE_CID_ */
diff --git a/drivers/net/qede/base/ecore_dev.c b/drivers/net/qede/base/ecore_dev.c
index e18c2fa89..814d9ced6 100644
--- a/drivers/net/qede/base/ecore_dev.c
+++ b/drivers/net/qede/base/ecore_dev.c
@@ -2358,6 +2358,7 @@ static enum _ecore_status_t ecore_alloc_qm_data(struct ecore_hwfn *p_hwfn)
 enum _ecore_status_t ecore_resc_alloc(struct ecore_dev *p_dev)
 {
 	enum _ecore_status_t rc = ECORE_SUCCESS;
+	enum dbg_status debug_status = DBG_STATUS_OK;
 	int i;
 
 	if (IS_VF(p_dev)) {
@@ -2512,17 +2513,21 @@ enum _ecore_status_t ecore_resc_alloc(struct ecore_dev *p_dev)
 			goto alloc_err;
 		}
 
-		rc = OSAL_DBG_ALLOC_USER_DATA(p_hwfn, &p_hwfn->dbg_user_info);
-		if (rc) {
+		debug_status = OSAL_DBG_ALLOC_USER_DATA(p_hwfn,
+							&p_hwfn->dbg_user_info);
+		if (debug_status) {
 			DP_NOTICE(p_hwfn, false,
 				  "Failed to allocate dbg user info structure\n");
+			rc = (enum _ecore_status_t)debug_status;
 			goto alloc_err;
 		}
 
-		rc = OSAL_DBG_ALLOC_USER_DATA(p_hwfn, &p_hwfn->dbg_user_info);
-		if (rc) {
+		debug_status = OSAL_DBG_ALLOC_USER_DATA(p_hwfn,
+							&p_hwfn->dbg_user_info);
+		if (debug_status) {
 			DP_NOTICE(p_hwfn, false,
 				  "Failed to allocate dbg user info structure\n");
+			rc = (enum _ecore_status_t)debug_status;
 			goto alloc_err;
 		}
 	} /* hwfn loop */
diff --git a/drivers/net/qede/base/ecore_hsi_func_common.h b/drivers/net/qede/base/ecore_hsi_func_common.h
new file mode 100644
index 000000000..2cd175163
--- /dev/null
+++ b/drivers/net/qede/base/ecore_hsi_func_common.h
@@ -0,0 +1,17 @@
+#ifndef _HSI_FUNC_COMMON_H
+#define _HSI_FUNC_COMMON_H
+
+/* Physical memory descriptor */
+struct phys_mem_desc {
+	dma_addr_t phys_addr;
+	void *virt_addr;
+	u32 size; /* In bytes */
+};
+
+/* Virtual memory descriptor */
+struct virt_mem_desc {
+	void *ptr;
+	u32 size; /* In bytes */
+};
+
+#endif
diff --git a/drivers/net/qede/base/ecore_init_fw_funcs.h b/drivers/net/qede/base/ecore_init_fw_funcs.h
index 912451662..a393d088f 100644
--- a/drivers/net/qede/base/ecore_init_fw_funcs.h
+++ b/drivers/net/qede/base/ecore_init_fw_funcs.h
@@ -9,13 +9,6 @@
 #include "ecore_hsi_common.h"
 #include "ecore_hsi_eth.h"
 
-/* Physical memory descriptor */
-struct phys_mem_desc {
-	dma_addr_t phys_addr;
-	void *virt_addr;
-	u32 size; /* In bytes */
-};
-
 /* Returns the VOQ based on port and TC */
 #define VOQ(port, tc, max_phys_tcs_per_port) \
 	((tc) == PURE_LB_TC ? NUM_OF_PHYS_TCS * MAX_NUM_PORTS_BB + (port) : \
-- 
2.18.0


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

* [dpdk-dev] [PATCH v3 2/4] net/qede/base: add changes for debug data collection
  2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 0/4] net/qede: add FW debug data collection support Rasesh Mody
  2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 " Rasesh Mody
  2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
@ 2020-07-07 20:18   ` Rasesh Mody
  2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 3/4] net/qede: add infrastructure " Rasesh Mody
  2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 4/4] net/qede: add support for get register operation Rasesh Mody
  4 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-07-07 20:18 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

This patch adds base driver APIs required for debug data collection.
It adds support for dumping internal lookup tables(ilt), reading nvram
image, register definitions.

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/qede/base/bcm_osal.c              |   6 +
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/qede/base/common_hsi.h            |   1 +
 drivers/net/qede/base/ecore.h                 |  52 +-
 drivers/net/qede/base/ecore_cxt.c             |  60 ++
 drivers/net/qede/base/ecore_cxt.h             |   5 +
 drivers/net/qede/base/ecore_dev.c             |  13 +
 drivers/net/qede/base/ecore_hsi_common.h      | 184 +++-
 drivers/net/qede/base/ecore_hsi_debug_tools.h |   2 +-
 drivers/net/qede/base/ecore_mcp.c             | 211 +++++
 drivers/net/qede/base/ecore_mcp_api.h         |  37 +
 drivers/net/qede/base/ecore_status.h          |   2 +
 drivers/net/qede/base/reg_addr.h              | 846 ++++++++++++++++++
 drivers/net/qede/qede_ethdev.c                |   1 -
 drivers/net/qede/qede_main.c                  |   3 +-
 15 files changed, 1414 insertions(+), 17 deletions(-)

diff --git a/drivers/net/qede/base/bcm_osal.c b/drivers/net/qede/base/bcm_osal.c
index 54e5e4f98..45557fe3c 100644
--- a/drivers/net/qede/base/bcm_osal.c
+++ b/drivers/net/qede/base/bcm_osal.c
@@ -289,3 +289,9 @@ u32 qede_crc32(u32 crc, u8 *ptr, u32 length)
 	}
 	return crc;
 }
+
+void qed_set_platform_str(struct ecore_hwfn *p_hwfn,
+			  char *buf_str, u32 buf_size)
+{
+	snprintf(buf_str, buf_size, "%s.", rte_version());
+}
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index 88a2500a5..6ea3e7dda 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -8,6 +8,7 @@
 #define __BCM_OSAL_H
 
 #include <stdbool.h>
+#include <time.h>
 #include <rte_bitops.h>
 #include <rte_byteorder.h>
 #include <rte_spinlock.h>
@@ -19,6 +20,7 @@
 #include <rte_debug.h>
 #include <rte_ether.h>
 #include <rte_io.h>
+#include <rte_version.h>
 
 /* Forward declaration */
 struct ecore_dev;
@@ -450,7 +452,11 @@ u32 qede_crc32(u32 crc, u8 *ptr, u32 length);
 
 #define OSAL_DIV_S64(a, b)	((a) / (b))
 #define OSAL_LLDP_RX_TLVS(p_hwfn, tlv_buf, tlv_size) nothing
-#define OSAL_GET_EPOCH(p_hwfn)	0
+void qed_set_platform_str(struct ecore_hwfn *p_hwfn,
+			  char *buf_str, u32 buf_size);
+#define OSAL_SET_PLATFORM_STR(p_hwfn, buf_str, buf_size) \
+	qed_set_platform_str(p_hwfn, buf_str, buf_size)
+#define OSAL_GET_EPOCH(p_hwfn) ((u32)time(NULL))
 #define OSAL_DBG_ALLOC_USER_DATA(p_hwfn, user_data_ptr) (0)
 #define OSAL_DB_REC_OCCURRED(p_hwfn) nothing
 
diff --git a/drivers/net/qede/base/common_hsi.h b/drivers/net/qede/base/common_hsi.h
index e230fe5ac..1a02d460b 100644
--- a/drivers/net/qede/base/common_hsi.h
+++ b/drivers/net/qede/base/common_hsi.h
@@ -145,6 +145,7 @@
 #define NUM_OF_CONNECTION_TYPES (8)
 #define NUM_OF_TASK_TYPES       (8)
 #define NUM_OF_LCIDS            (320)
+#define NUM_OF_LTIDS            (320)
 
 /* Global PXP windows (GTT) */
 #define NUM_OF_GTT          19
diff --git a/drivers/net/qede/base/ecore.h b/drivers/net/qede/base/ecore.h
index dc5fe4d80..63bd7466a 100644
--- a/drivers/net/qede/base/ecore.h
+++ b/drivers/net/qede/base/ecore.h
@@ -576,6 +576,12 @@ enum BAR_ID {
 	BAR_ID_1	/* Used for doorbells */
 };
 
+struct ecore_nvm_image_info {
+	u32				num_images;
+	struct bist_nvm_image_att	*image_att;
+	bool				valid;
+};
+
 struct ecore_hwfn {
 	struct ecore_dev		*p_dev;
 	u8				my_id;		/* ID inside the PF */
@@ -701,6 +707,9 @@ struct ecore_hwfn {
 	 */
 	bool b_en_pacing;
 
+	/* Nvm images number and attributes */
+	struct ecore_nvm_image_info     nvm_info;
+
 	struct phys_mem_desc            *fw_overlay_mem;
 
 	/* @DPDK */
@@ -714,26 +723,34 @@ enum ecore_mf_mode {
 	ECORE_MF_UFP,
 };
 
-/* @DPDK */
-struct ecore_dbg_feature {
-	u8				*dump_buf;
-	u32				buf_size;
-	u32				dumped_dwords;
+enum ecore_dev_type {
+	ECORE_DEV_TYPE_BB,
+	ECORE_DEV_TYPE_AH,
 };
 
-enum qed_dbg_features {
-	DBG_FEATURE_BUS,
+/* @DPDK */
+enum ecore_dbg_features {
 	DBG_FEATURE_GRC,
 	DBG_FEATURE_IDLE_CHK,
 	DBG_FEATURE_MCP_TRACE,
 	DBG_FEATURE_REG_FIFO,
+	DBG_FEATURE_IGU_FIFO,
 	DBG_FEATURE_PROTECTION_OVERRIDE,
+	DBG_FEATURE_FW_ASSERTS,
+	DBG_FEATURE_ILT,
 	DBG_FEATURE_NUM
 };
 
-enum ecore_dev_type {
-	ECORE_DEV_TYPE_BB,
-	ECORE_DEV_TYPE_AH,
+struct ecore_dbg_feature {
+	u8				*dump_buf;
+	u32				buf_size;
+	u32				dumped_dwords;
+};
+
+struct ecore_dbg_params {
+	struct ecore_dbg_feature features[DBG_FEATURE_NUM];
+	u8 engine_for_debug;
+	bool print_data;
 };
 
 struct ecore_dev {
@@ -914,10 +931,12 @@ struct ecore_dev {
 	void				*firmware;
 	u64				fw_len;
 #endif
+	bool				disable_ilt_dump;
 
 	/* @DPDK */
 	struct ecore_dbg_feature	dbg_features[DBG_FEATURE_NUM];
-	u8				engine_for_debug;
+	struct ecore_dbg_params		dbg_params;
+	osal_mutex_t			dbg_lock;
 };
 
 enum ecore_hsi_def_type {
@@ -1067,6 +1086,17 @@ enum _ecore_status_t ecore_all_ppfids_wr(struct ecore_hwfn *p_hwfn,
 enum _ecore_status_t ecore_llh_dump_ppfid(struct ecore_dev *p_dev, u8 ppfid);
 enum _ecore_status_t ecore_llh_dump_all(struct ecore_dev *p_dev);
 
+/**
+ * @brief ecore_set_platform_str - Set the debug dump platform string.
+ * Write the ecore version and device's string to the given buffer.
+ *
+ * @param p_hwfn
+ * @param buf_str
+ * @param buf_size
+ */
+void ecore_set_platform_str(struct ecore_hwfn *p_hwfn,
+			    char *buf_str, u32 buf_size);
+
 #define TSTORM_QZONE_START	PXP_VF_BAR0_START_SDM_ZONE_A
 
 #define MSTORM_QZONE_START(dev) \
diff --git a/drivers/net/qede/base/ecore_cxt.c b/drivers/net/qede/base/ecore_cxt.c
index 23f37b1bf..d3025724b 100644
--- a/drivers/net/qede/base/ecore_cxt.c
+++ b/drivers/net/qede/base/ecore_cxt.c
@@ -2186,3 +2186,63 @@ static u16 ecore_blk_calculate_pages(struct ecore_ilt_cli_blk *p_blk)
 
 	return DIV_ROUND_UP(p_blk->total_size, p_blk->real_size_in_page);
 }
+
+u16 ecore_get_cdut_num_pf_init_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 i, pages = 0;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_PF_SEGMENTS; i++) {
+		p_blk = &p_cli->pf_blks[CDUT_FL_SEG_BLK(i, PF)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
+
+u16 ecore_get_cdut_num_vf_init_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 i, pages = 0;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_VF_SEGMENTS; i++) {
+		p_blk = &p_cli->vf_blks[CDUT_FL_SEG_BLK(i, VF)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
+
+u16 ecore_get_cdut_num_pf_work_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 i, pages = 0;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_PF_SEGMENTS; i++) {
+		p_blk = &p_cli->pf_blks[CDUT_SEG_BLK(i)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
+
+u16 ecore_get_cdut_num_vf_work_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 pages = 0, i;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_VF_SEGMENTS; i++) {
+		p_blk = &p_cli->vf_blks[CDUT_SEG_BLK(i)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
diff --git a/drivers/net/qede/base/ecore_cxt.h b/drivers/net/qede/base/ecore_cxt.h
index 7b91b953e..80fe39ac0 100644
--- a/drivers/net/qede/base/ecore_cxt.h
+++ b/drivers/net/qede/base/ecore_cxt.h
@@ -345,4 +345,9 @@ struct ecore_cxt_mngr {
 	u16				task_ctx_size;
 	u16				conn_ctx_size;
 };
+
+u16 ecore_get_cdut_num_pf_init_pages(struct ecore_hwfn *p_hwfn);
+u16 ecore_get_cdut_num_vf_init_pages(struct ecore_hwfn *p_hwfn);
+u16 ecore_get_cdut_num_pf_work_pages(struct ecore_hwfn *p_hwfn);
+u16 ecore_get_cdut_num_vf_work_pages(struct ecore_hwfn *p_hwfn);
 #endif /* _ECORE_CID_ */
diff --git a/drivers/net/qede/base/ecore_dev.c b/drivers/net/qede/base/ecore_dev.c
index 814d9ced6..35a8394de 100644
--- a/drivers/net/qede/base/ecore_dev.c
+++ b/drivers/net/qede/base/ecore_dev.c
@@ -6798,6 +6798,19 @@ void ecore_set_fw_mac_addr(__le16 *fw_msb,
 	((u8 *)fw_lsb)[1] = mac[4];
 }
 
+void ecore_set_platform_str(struct ecore_hwfn *p_hwfn,
+			    char *buf_str, u32 buf_size)
+{
+	u32 len;
+
+	OSAL_SNPRINTF(buf_str, buf_size, "Ecore %d.%d.%d.%d. ",
+		      ECORE_MAJOR_VERSION, ECORE_MINOR_VERSION,
+		      ECORE_REVISION_VERSION, ECORE_ENGINEERING_VERSION);
+
+	len = OSAL_STRLEN(buf_str);
+	OSAL_SET_PLATFORM_STR(p_hwfn, &buf_str[len], buf_size - len);
+}
+
 bool ecore_is_mf_fip_special(struct ecore_dev *p_dev)
 {
 	return !!OSAL_GET_BIT(ECORE_MF_FIP_SPECIAL, &p_dev->mf_bits);
diff --git a/drivers/net/qede/base/ecore_hsi_common.h b/drivers/net/qede/base/ecore_hsi_common.h
index 23cfcdeff..578c798a9 100644
--- a/drivers/net/qede/base/ecore_hsi_common.h
+++ b/drivers/net/qede/base/ecore_hsi_common.h
@@ -10,6 +10,7 @@
 /* Add include to common target */
 /********************************/
 #include "common_hsi.h"
+#include "mcp_public.h"
 
 
 /*
@@ -2229,7 +2230,40 @@ struct fw_info_location {
 };
 
 
-
+/* DMAE parameters */
+struct ecore_dmae_params {
+	u32 flags;
+/* If QED_DMAE_PARAMS_RW_REPL_SRC flag is set and the
+ * source is a block of length DMAE_MAX_RW_SIZE and the
+ * destination is larger, the source block will be duplicated as
+ * many times as required to fill the destination block. This is
+ * used mostly to write a zeroed buffer to destination address
+ * using DMA
+ */
+#define ECORE_DMAE_PARAMS_RW_REPL_SRC_MASK        0x1
+#define ECORE_DMAE_PARAMS_RW_REPL_SRC_SHIFT       0
+#define ECORE_DMAE_PARAMS_SRC_VF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_SRC_VF_VALID_SHIFT      1
+#define ECORE_DMAE_PARAMS_DST_VF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_DST_VF_VALID_SHIFT      2
+#define ECORE_DMAE_PARAMS_COMPLETION_DST_MASK     0x1
+#define ECORE_DMAE_PARAMS_COMPLETION_DST_SHIFT    3
+#define ECORE_DMAE_PARAMS_PORT_VALID_MASK         0x1
+#define ECORE_DMAE_PARAMS_PORT_VALID_SHIFT        4
+#define ECORE_DMAE_PARAMS_SRC_PF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_SRC_PF_VALID_SHIFT      5
+#define ECORE_DMAE_PARAMS_DST_PF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_DST_PF_VALID_SHIFT      6
+#define ECORE_DMAE_PARAMS_RESERVED_MASK           0x1FFFFFF
+#define ECORE_DMAE_PARAMS_RESERVED_SHIFT          7
+	u8 src_vfid;
+	u8 dst_vfid;
+	u8 port_id;
+	u8 src_pfid;
+	u8 dst_pfid;
+	u8 reserved1;
+	__le16 reserved2;
+};
 
 /*
  * IGU cleanup command
@@ -2543,4 +2577,152 @@ struct ystorm_core_conn_ag_ctx {
 	__le32 reg3 /* reg3 */;
 };
 
+/*********/
+/* DEBUG */
+/*********/
+
+#define MFW_TRACE_SIGNATURE	0x25071946
+
+/* The trace in the buffer */
+#define MFW_TRACE_EVENTID_MASK		0x00ffff
+#define MFW_TRACE_PRM_SIZE_MASK		0x0f0000
+#define MFW_TRACE_PRM_SIZE_OFFSET	16
+#define MFW_TRACE_ENTRY_SIZE		3
+
+struct mcp_trace {
+	u32	signature;	/* Help to identify that the trace is valid */
+	u32	size;		/* the size of the trace buffer in bytes*/
+	u32	curr_level;	/* 2 - all will be written to the buffer
+				 * 1 - debug trace will not be written
+				 * 0 - just errors will be written to the buffer
+				 */
+	/* a bit per module, 1 means mask it off, 0 means add it to the trace
+	 * buffer
+	 */
+	u32	modules_mask[2];
+
+	/* Warning: the following pointers are assumed to be 32bits as they are
+	 * used only in the MFW
+	 */
+	/* The next trace will be written to this offset */
+	u32	trace_prod;
+	/* The oldest valid trace starts at this offset (usually very close
+	 * after the current producer)
+	 */
+	u32	trace_oldest;
+};
+
+enum spad_sections {
+	SPAD_SECTION_TRACE,
+	SPAD_SECTION_NVM_CFG,
+	SPAD_SECTION_PUBLIC,
+	SPAD_SECTION_PRIVATE,
+	SPAD_SECTION_MAX
+};
+
+#define MCP_TRACE_SIZE          2048    /* 2kb */
+
+/* This section is located at a fixed location in the beginning of the
+ * scratchpad, to ensure that the MCP trace is not run over during MFW upgrade.
+ * All the rest of data has a floating location which differs from version to
+ * version, and is pointed by the mcp_meta_data below.
+ * Moreover, the spad_layout section is part of the MFW firmware, and is loaded
+ * with it from nvram in order to clear this portion.
+ */
+struct static_init {
+	u32 num_sections;
+	offsize_t sections[SPAD_SECTION_MAX];
+#define SECTION(_sec_) (*((offsize_t *)(STRUCT_OFFSET(sections[_sec_]))))
+
+	struct mcp_trace trace;
+#define MCP_TRACE_P ((struct mcp_trace *)(STRUCT_OFFSET(trace)))
+	u8 trace_buffer[MCP_TRACE_SIZE];
+#define MCP_TRACE_BUF ((u8 *)(STRUCT_OFFSET(trace_buffer)))
+	/* running_mfw has the same definition as in nvm_map.h.
+	 * This bit indicate both the running dir, and the running bundle.
+	 * It is set once when the LIM is loaded.
+	 */
+	u32 running_mfw;
+#define RUNNING_MFW (*((u32 *)(STRUCT_OFFSET(running_mfw))))
+	u32 build_time;
+#define MFW_BUILD_TIME (*((u32 *)(STRUCT_OFFSET(build_time))))
+	u32 reset_type;
+#define RESET_TYPE (*((u32 *)(STRUCT_OFFSET(reset_type))))
+	u32 mfw_secure_mode;
+#define MFW_SECURE_MODE (*((u32 *)(STRUCT_OFFSET(mfw_secure_mode))))
+	u16 pme_status_pf_bitmap;
+#define PME_STATUS_PF_BITMAP (*((u16 *)(STRUCT_OFFSET(pme_status_pf_bitmap))))
+	u16 pme_enable_pf_bitmap;
+#define PME_ENABLE_PF_BITMAP (*((u16 *)(STRUCT_OFFSET(pme_enable_pf_bitmap))))
+	u32 mim_nvm_addr;
+	u32 mim_start_addr;
+	u32 ah_pcie_link_params;
+#define AH_PCIE_LINK_PARAMS_LINK_SPEED_MASK     (0x000000ff)
+#define AH_PCIE_LINK_PARAMS_LINK_SPEED_SHIFT    (0)
+#define AH_PCIE_LINK_PARAMS_LINK_WIDTH_MASK     (0x0000ff00)
+#define AH_PCIE_LINK_PARAMS_LINK_WIDTH_SHIFT    (8)
+#define AH_PCIE_LINK_PARAMS_ASPM_MODE_MASK      (0x00ff0000)
+#define AH_PCIE_LINK_PARAMS_ASPM_MODE_SHIFT     (16)
+#define AH_PCIE_LINK_PARAMS_ASPM_CAP_MASK       (0xff000000)
+#define AH_PCIE_LINK_PARAMS_ASPM_CAP_SHIFT      (24)
+#define AH_PCIE_LINK_PARAMS (*((u32 *)(STRUCT_OFFSET(ah_pcie_link_params))))
+
+	u32 rsrv_persist[5];	/* Persist reserved for MFW upgrades */
+};
+
+#define NVM_MAGIC_VALUE		0x669955aa
+
+enum nvm_image_type {
+	NVM_TYPE_TIM1 = 0x01,
+	NVM_TYPE_TIM2 = 0x02,
+	NVM_TYPE_MIM1 = 0x03,
+	NVM_TYPE_MIM2 = 0x04,
+	NVM_TYPE_MBA = 0x05,
+	NVM_TYPE_MODULES_PN = 0x06,
+	NVM_TYPE_VPD = 0x07,
+	NVM_TYPE_MFW_TRACE1 = 0x08,
+	NVM_TYPE_MFW_TRACE2 = 0x09,
+	NVM_TYPE_NVM_CFG1 = 0x0a,
+	NVM_TYPE_L2B = 0x0b,
+	NVM_TYPE_DIR1 = 0x0c,
+	NVM_TYPE_EAGLE_FW1 = 0x0d,
+	NVM_TYPE_FALCON_FW1 = 0x0e,
+	NVM_TYPE_PCIE_FW1 = 0x0f,
+	NVM_TYPE_HW_SET = 0x10,
+	NVM_TYPE_LIM = 0x11,
+	NVM_TYPE_AVS_FW1 = 0x12,
+	NVM_TYPE_DIR2 = 0x13,
+	NVM_TYPE_CCM = 0x14,
+	NVM_TYPE_EAGLE_FW2 = 0x15,
+	NVM_TYPE_FALCON_FW2 = 0x16,
+	NVM_TYPE_PCIE_FW2 = 0x17,
+	NVM_TYPE_AVS_FW2 = 0x18,
+	NVM_TYPE_INIT_HW = 0x19,
+	NVM_TYPE_DEFAULT_CFG = 0x1a,
+	NVM_TYPE_MDUMP = 0x1b,
+	NVM_TYPE_META = 0x1c,
+	NVM_TYPE_ISCSI_CFG = 0x1d,
+	NVM_TYPE_FCOE_CFG = 0x1f,
+	NVM_TYPE_ETH_PHY_FW1 = 0x20,
+	NVM_TYPE_ETH_PHY_FW2 = 0x21,
+	NVM_TYPE_BDN = 0x22,
+	NVM_TYPE_8485X_PHY_FW = 0x23,
+	NVM_TYPE_PUB_KEY = 0x24,
+	NVM_TYPE_RECOVERY = 0x25,
+	NVM_TYPE_PLDM = 0x26,
+	NVM_TYPE_UPK1 = 0x27,
+	NVM_TYPE_UPK2 = 0x28,
+	NVM_TYPE_MASTER_KC = 0x29,
+	NVM_TYPE_BACKUP_KC = 0x2a,
+	NVM_TYPE_HW_DUMP = 0x2b,
+	NVM_TYPE_HW_DUMP_OUT = 0x2c,
+	NVM_TYPE_BIN_NVM_META = 0x30,
+	NVM_TYPE_ROM_TEST = 0xf0,
+	NVM_TYPE_88X33X0_PHY_FW = 0x31,
+	NVM_TYPE_88X33X0_PHY_SLAVE_FW = 0x32,
+	NVM_TYPE_MAX,
+};
+
+#define DIR_ID_1    (0)
+
 #endif /* __ECORE_HSI_COMMON__ */
diff --git a/drivers/net/qede/base/ecore_hsi_debug_tools.h b/drivers/net/qede/base/ecore_hsi_debug_tools.h
index eb72e93cf..c5ef67f84 100644
--- a/drivers/net/qede/base/ecore_hsi_debug_tools.h
+++ b/drivers/net/qede/base/ecore_hsi_debug_tools.h
@@ -245,6 +245,7 @@ struct dbg_mode_hdr {
  * Attention register
  */
 struct dbg_attn_reg {
+	struct dbg_mode_hdr mode /* Mode header */;
 /* The offset of this registers attentions within the blocks attentions list
  * (a value in the range 0..number of block attentions-1)
  */
@@ -1049,5 +1050,4 @@ struct dbg_tools_data {
 };
 
 
-
 #endif /* __ECORE_HSI_DEBUG_TOOLS__ */
diff --git a/drivers/net/qede/base/ecore_mcp.c b/drivers/net/qede/base/ecore_mcp.c
index 0a9e26805..cab089d81 100644
--- a/drivers/net/qede/base/ecore_mcp.c
+++ b/drivers/net/qede/base/ecore_mcp.c
@@ -3621,6 +3621,217 @@ enum _ecore_status_t ecore_mcp_bist_nvm_test_get_image_att(
 	return rc;
 }
 
+enum _ecore_status_t
+ecore_mcp_bist_nvm_get_num_images(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt, u32 *num_images)
+{
+	u32 drv_mb_param = 0, rsp;
+	enum _ecore_status_t rc = ECORE_SUCCESS;
+
+	SET_MFW_FIELD(drv_mb_param, DRV_MB_PARAM_BIST_TEST_INDEX,
+		      DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES);
+
+	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
+			   drv_mb_param, &rsp, num_images);
+	if (rc != ECORE_SUCCESS)
+		return rc;
+
+	if (rsp == FW_MSG_CODE_UNSUPPORTED)
+		rc = ECORE_NOTIMPL;
+	else if (rsp != FW_MSG_CODE_OK)
+		rc = ECORE_UNKNOWN_ERROR;
+
+	return rc;
+}
+
+enum _ecore_status_t
+ecore_mcp_bist_nvm_get_image_att(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 struct bist_nvm_image_att *p_image_att,
+				 u32 image_index)
+{
+	u32 buf_size, nvm_offset = 0, resp, param;
+	enum _ecore_status_t rc;
+
+	SET_MFW_FIELD(nvm_offset, DRV_MB_PARAM_BIST_TEST_INDEX,
+		      DRV_MB_PARAM_BIST_NVM_TEST_IMAGE_BY_INDEX);
+	SET_MFW_FIELD(nvm_offset, DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX,
+		      image_index);
+	rc = ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
+				  nvm_offset, &resp, &param, &buf_size,
+				  (u32 *)p_image_att);
+	if (rc != ECORE_SUCCESS)
+		return rc;
+
+	if (resp == FW_MSG_CODE_UNSUPPORTED)
+		rc = ECORE_NOTIMPL;
+	else if ((resp != FW_MSG_CODE_OK) || (p_image_att->return_code != 1))
+		rc = ECORE_UNKNOWN_ERROR;
+
+	return rc;
+}
+
+enum _ecore_status_t ecore_mcp_nvm_info_populate(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_nvm_image_info nvm_info;
+	struct ecore_ptt *p_ptt;
+	enum _ecore_status_t rc;
+	u32 i;
+
+	if (p_hwfn->nvm_info.valid)
+		return ECORE_SUCCESS;
+
+#ifndef ASIC_ONLY
+	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev) ||
+	    CHIP_REV_IS_TEDIBEAR(p_hwfn->p_dev))
+		return ECORE_SUCCESS;
+#endif
+
+	p_ptt = ecore_ptt_acquire(p_hwfn);
+	if (!p_ptt) {
+		DP_ERR(p_hwfn, "failed to acquire ptt\n");
+		return ECORE_BUSY;
+	}
+
+	/* Acquire from MFW the amount of available images */
+	OSAL_MEM_ZERO(&nvm_info, sizeof(nvm_info));
+	rc = ecore_mcp_bist_nvm_get_num_images(p_hwfn, p_ptt,
+					       &nvm_info.num_images);
+	if (rc == ECORE_NOTIMPL) {
+		DP_INFO(p_hwfn, "DRV_MSG_CODE_BIST_TEST is not supported\n");
+		goto out;
+	} else if ((rc != ECORE_SUCCESS) || (nvm_info.num_images == 0)) {
+		DP_ERR(p_hwfn, "Failed getting number of images\n");
+		goto err0;
+	}
+
+	nvm_info.image_att = OSAL_ALLOC(p_hwfn->p_dev, GFP_KERNEL,
+					 nvm_info.num_images *
+					 sizeof(struct bist_nvm_image_att));
+	if (!nvm_info.image_att) {
+		rc = ECORE_NOMEM;
+		goto err0;
+	}
+
+	/* Iterate over images and get their attributes */
+	for (i = 0; i < nvm_info.num_images; i++) {
+		rc = ecore_mcp_bist_nvm_get_image_att(p_hwfn, p_ptt,
+						      &nvm_info.image_att[i],
+						      i);
+		if (rc != ECORE_SUCCESS) {
+			DP_ERR(p_hwfn,
+			       "Failed getting image index %d attributes\n",
+			       i);
+			goto err1;
+		}
+
+		DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "image index %d, size %x\n", i,
+			   nvm_info.image_att[i].len);
+	}
+out:
+	/* Update hwfn's nvm_info */
+	if (nvm_info.num_images) {
+		p_hwfn->nvm_info.num_images = nvm_info.num_images;
+		if (p_hwfn->nvm_info.image_att)
+			OSAL_FREE(p_hwfn->p_dev, p_hwfn->nvm_info.image_att);
+		p_hwfn->nvm_info.image_att = nvm_info.image_att;
+		p_hwfn->nvm_info.valid = true;
+	}
+
+	ecore_ptt_release(p_hwfn, p_ptt);
+	return ECORE_SUCCESS;
+
+err1:
+	OSAL_FREE(p_hwfn->p_dev, nvm_info.image_att);
+err0:
+	ecore_ptt_release(p_hwfn, p_ptt);
+	return rc;
+}
+
+enum _ecore_status_t
+ecore_mcp_get_nvm_image_att(struct ecore_hwfn *p_hwfn,
+			    enum ecore_nvm_images image_id,
+			    struct ecore_nvm_image_att *p_image_att)
+{
+	enum nvm_image_type type;
+	u32 i;
+
+	/* Translate image_id into MFW definitions */
+	switch (image_id) {
+	case ECORE_NVM_IMAGE_ISCSI_CFG:
+		type = NVM_TYPE_ISCSI_CFG;
+		break;
+	case ECORE_NVM_IMAGE_FCOE_CFG:
+		type = NVM_TYPE_FCOE_CFG;
+		break;
+	case ECORE_NVM_IMAGE_MDUMP:
+		type = NVM_TYPE_MDUMP;
+		break;
+	case ECORE_NVM_IMAGE_NVM_CFG1:
+		type = NVM_TYPE_NVM_CFG1;
+		break;
+	case ECORE_NVM_IMAGE_DEFAULT_CFG:
+		type = NVM_TYPE_DEFAULT_CFG;
+		break;
+	case ECORE_NVM_IMAGE_NVM_META:
+		type = NVM_TYPE_META;
+		break;
+	default:
+		DP_NOTICE(p_hwfn, false, "Unknown request of image_id %08x\n",
+			  image_id);
+		return ECORE_INVAL;
+	}
+
+	ecore_mcp_nvm_info_populate(p_hwfn);
+	for (i = 0; i < p_hwfn->nvm_info.num_images; i++) {
+		if (type == p_hwfn->nvm_info.image_att[i].image_type)
+			break;
+	}
+	if (i == p_hwfn->nvm_info.num_images) {
+		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
+			   "Failed to find nvram image of type %08x\n",
+			   image_id);
+		return ECORE_NOENT;
+	}
+
+	p_image_att->start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr;
+	p_image_att->length = p_hwfn->nvm_info.image_att[i].len;
+
+	return ECORE_SUCCESS;
+}
+
+enum _ecore_status_t ecore_mcp_get_nvm_image(struct ecore_hwfn *p_hwfn,
+					     enum ecore_nvm_images image_id,
+					     u8 *p_buffer, u32 buffer_len)
+{
+	struct ecore_nvm_image_att image_att;
+	enum _ecore_status_t rc;
+
+	OSAL_MEM_ZERO(p_buffer, buffer_len);
+
+	rc = ecore_mcp_get_nvm_image_att(p_hwfn, image_id, &image_att);
+	if (rc != ECORE_SUCCESS)
+		return rc;
+
+	/* Validate sizes - both the image's and the supplied buffer's */
+	if (image_att.length <= 4) {
+		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
+			   "Image [%d] is too small - only %d bytes\n",
+			   image_id, image_att.length);
+		return ECORE_INVAL;
+	}
+
+	if (image_att.length > buffer_len) {
+		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
+			   "Image [%d] is too big - %08x bytes where only %08x are available\n",
+			   image_id, image_att.length, buffer_len);
+		return ECORE_NOMEM;
+	}
+
+	return ecore_mcp_nvm_read(p_hwfn->p_dev, image_att.start_addr,
+				  (u8 *)p_buffer, image_att.length);
+}
+
 enum _ecore_status_t
 ecore_mcp_get_temperature_info(struct ecore_hwfn *p_hwfn,
 			       struct ecore_ptt *p_ptt,
diff --git a/drivers/net/qede/base/ecore_mcp_api.h b/drivers/net/qede/base/ecore_mcp_api.h
index dc889ab8e..53c130be7 100644
--- a/drivers/net/qede/base/ecore_mcp_api.h
+++ b/drivers/net/qede/base/ecore_mcp_api.h
@@ -121,6 +121,10 @@ struct ecore_mcp_function_info {
 enum ecore_nvm_images {
 	ECORE_NVM_IMAGE_ISCSI_CFG,
 	ECORE_NVM_IMAGE_FCOE_CFG,
+	ECORE_NVM_IMAGE_MDUMP,
+	ECORE_NVM_IMAGE_NVM_CFG1,
+	ECORE_NVM_IMAGE_DEFAULT_CFG,
+	ECORE_NVM_IMAGE_NVM_META,
 };
 #endif
 
@@ -970,6 +974,39 @@ enum _ecore_status_t ecore_mcp_phy_read(struct ecore_dev *p_dev, u32 cmd,
 enum _ecore_status_t ecore_mcp_nvm_read(struct ecore_dev *p_dev, u32 addr,
 			   u8 *p_buf, u32 len);
 
+struct ecore_nvm_image_att {
+	u32 start_addr;
+	u32 length;
+};
+
+/**
+ * @brief Allows reading a whole nvram image
+ *
+ * @param p_hwfn
+ * @param image_id - image to get attributes for
+ * @param p_image_att - image attributes structure into which to fill data
+ *
+ * @return enum _ecore_status_t - ECORE_SUCCESS - operation was successful.
+ */
+enum _ecore_status_t
+ecore_mcp_get_nvm_image_att(struct ecore_hwfn *p_hwfn,
+			    enum ecore_nvm_images image_id,
+			    struct ecore_nvm_image_att *p_image_att);
+
+/**
+ * @brief Allows reading a whole nvram image
+ *
+ * @param p_hwfn
+ * @param image_id - image requested for reading
+ * @param p_buffer - allocated buffer into which to fill data
+ * @param buffer_len - length of the allocated buffer.
+ *
+ * @return ECORE_SUCCESS iff p_buffer now contains the nvram image.
+ */
+enum _ecore_status_t ecore_mcp_get_nvm_image(struct ecore_hwfn *p_hwfn,
+					     enum ecore_nvm_images image_id,
+					     u8 *p_buffer, u32 buffer_len);
+
 /**
  * @brief - Sends an NVM write command request to the MFW with
  *          payload.
diff --git a/drivers/net/qede/base/ecore_status.h b/drivers/net/qede/base/ecore_status.h
index b893f1d41..01cf9fd31 100644
--- a/drivers/net/qede/base/ecore_status.h
+++ b/drivers/net/qede/base/ecore_status.h
@@ -8,6 +8,8 @@
 #define __ECORE_STATUS_H__
 
 enum _ecore_status_t {
+	ECORE_NOENT = -15,
+	ECORE_CONN_REFUSED = -14,
 	ECORE_CONN_RESET = -13,
 	ECORE_UNKNOWN_ERROR  = -12,
 	ECORE_NORESOURCES	 = -11,
diff --git a/drivers/net/qede/base/reg_addr.h b/drivers/net/qede/base/reg_addr.h
index 91d889dc8..c84d3865f 100644
--- a/drivers/net/qede/base/reg_addr.h
+++ b/drivers/net/qede/base/reg_addr.h
@@ -1245,3 +1245,849 @@
 #define DORQ_REG_VF_USAGE_CNT_LIM 0x1009ccUL
 #define PGLUE_B_REG_SR_IOV_DISABLED_REQUEST 0x2aa06cUL
 #define PGLUE_B_REG_SR_IOV_DISABLED_REQUEST_CLR 0x2aa070UL
+
+#define PSWRQ2_REG_ILT_MEMORY_SIZE_BB 15200
+#define PSWRQ2_REG_ILT_MEMORY_SIZE_K2 22000
+#define TSEM_REG_DBG_GPRE_VECT 0x1701410UL
+#define MSEM_REG_DBG_GPRE_VECT 0x1801410UL
+#define USEM_REG_DBG_GPRE_VECT 0x1901410UL
+#define XSEM_REG_DBG_GPRE_VECT 0x1401410UL
+#define YSEM_REG_DBG_GPRE_VECT 0x1501410UL
+#define PSEM_REG_DBG_GPRE_VECT 0x1601410UL
+#define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE 0x000748UL
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_WRITE_DISABLE (0x1UL << 0)
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_WRITE_DISABLE_SHIFT 0
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_READ_DISABLE (0x1UL << 1)
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_READ_DISABLE_SHIFT 1
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_INTERRUPT_DISABLE (0x1UL << 2)
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_INTERRUPT_DISABLE_SHIFT 2
+#define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE 0x00074cUL
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_STORE_DATA_DISABLE (0x1UL << 0)
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_STORE_DATA_DISABLE_SHIFT 0
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_LOAD_DATA_DISABLE (0x1UL << 1)
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_LOAD_DATA_DISABLE_SHIFT 1
+#define NWS_REG_NWS_CMU_K2 0x720000UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_7_0_K2 0x000680UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_15_8_K2 0x000684UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_7_0_K2 0x0006c0UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_11_8_K2 0x0006c4UL
+#define MS_REG_MS_CMU_K2 0x6a4000UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X132_K2 0x000210UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X133_K2 0x000214UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X130_K2 0x000208UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X131_K2 0x00020cUL
+#define PHY_PCIE_REG_PHY0_K2 0x620000UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2 0x000210UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2 0x000214UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2 0x000208UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2 0x00020cUL
+#define PHY_PCIE_REG_PHY1_K2 0x624000UL
+#define PCIE_REG_DBG_REPEAT_THRESHOLD_COUNT_K2 0x054364UL
+#define PCIE_REG_DBG_FW_TRIGGER_ENABLE_K2 0x05436cUL
+#define RDIF_REG_DEBUG_ERROR_INFO 0x300400UL
+#define RDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define RDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define TDIF_REG_DEBUG_ERROR_INFO 0x310400UL
+#define TDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define TDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define SEM_FAST_REG_VFC_STATUS 0x000b4cUL
+  #define SEM_FAST_REG_VFC_STATUS_RESPONSE_READY (0x1UL << 0)
+  #define SEM_FAST_REG_VFC_STATUS_RESPONSE_READY_SHIFT 0
+  #define SEM_FAST_REG_VFC_STATUS_VFC_BUSY (0x1UL << 1)
+  #define SEM_FAST_REG_VFC_STATUS_VFC_BUSY_SHIFT 1
+  #define SEM_FAST_REG_VFC_STATUS_SENDING_CMD_ON_GOING (0x1UL << 2)
+  #define SEM_FAST_REG_VFC_STATUS_SENDING_CMD_ON_GOING_SHIFT 2
+#define RSS_REG_RSS_RAM_DATA_SIZE 4
+#define BRB_REG_BIG_RAM_DATA_SIZE 64
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_1 0x0084c0UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_2 0x0084e4UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_3 0x008508UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_4 0x00852cUL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_5 0x008550UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_6 0x008574UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_7 0x008598UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_NIG 0x0085bcUL
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_PXP 0x0085e0UL
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_MCP_OUT_0 0x008628UL
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR 0x008748UL
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_SYS_KILL 0x008604UL
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO31_SHIFT 31
+#define DBG_REG_FULL_BUFFER_THR 0x01045cUL
+#define MISC_REG_AEU_MASK_ATTN_MCP 0x008498UL
+#define MISC_REG_AEU_SYS_KILL_BEHAVIOR 0x008800UL
+#define MISC_REG_AEU_GENERAL_MASK 0x008828UL
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_PXP_CLOSE_MASK (0x1UL << 0)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_PXP_CLOSE_MASK_SHIFT 0
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_NIG_CLOSE_MASK (0x1UL << 1)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_NIG_CLOSE_MASK_SHIFT 1
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_SYS_KILL_MASK (0x1UL << 2)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_SYS_KILL_MASK_SHIFT 2
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_GLB_UNC_ERR_MASK (0x1UL << 3)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_GLB_UNC_ERR_MASK_SHIFT 3
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 7f5a34bcb..b5d6c7c43 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -7,7 +7,6 @@
 #include "qede_ethdev.h"
 #include <rte_string_fns.h>
 #include <rte_alarm.h>
-#include <rte_version.h>
 #include <rte_kvargs.h>
 
 static const struct qed_eth_ops *qed_ops;
diff --git a/drivers/net/qede/qede_main.c b/drivers/net/qede/qede_main.c
index 02f70beb3..51aa639c6 100644
--- a/drivers/net/qede/qede_main.c
+++ b/drivers/net/qede/qede_main.c
@@ -5,7 +5,6 @@
  */
 
 #include <limits.h>
-#include <time.h>
 #include <rte_alarm.h>
 #include <rte_string_fns.h>
 
@@ -66,7 +65,7 @@ qed_probe(struct ecore_dev *edev, struct rte_pci_device *pci_dev,
 	hw_prepare_params.initiate_pf_flr = true;
 	hw_prepare_params.allow_mdump = false;
 	hw_prepare_params.b_en_pacing = false;
-	hw_prepare_params.epoch = (u32)time(NULL);
+	hw_prepare_params.epoch = OSAL_GET_EPOCH(ECORE_LEADING_HWFN(edev));
 	rc = ecore_hw_prepare(edev, &hw_prepare_params);
 	if (rc) {
 		DP_ERR(edev, "hw prepare failed\n");
-- 
2.18.0


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

* [dpdk-dev] [PATCH v3 3/4] net/qede: add infrastructure for debug data collection
  2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 0/4] net/qede: add FW debug data collection support Rasesh Mody
                     ` (2 preceding siblings ...)
  2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 2/4] net/qede/base: add changes for debug data collection Rasesh Mody
@ 2020-07-07 20:18   ` Rasesh Mody
  2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 4/4] net/qede: add support for get register operation Rasesh Mody
  4 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-07-07 20:18 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

The patch adds QEDE PMD ops and APIs to calculate the size and collect
the debug dump for various firmware components. The patch adds new files
qede_debug.[ch] that has all the firmware debug data collection
infrastructure changes.

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/qede/Makefile        |    4 +-
 drivers/net/qede/base/bcm_osal.h |    5 +-
 drivers/net/qede/qede_debug.c    | 8120 ++++++++++++++++++++++++++++++
 drivers/net/qede/qede_debug.h    |  759 +++
 drivers/net/qede/qede_if.h       |   45 +
 drivers/net/qede/qede_main.c     |   39 +-
 6 files changed, 8968 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/qede/qede_debug.c
 create mode 100644 drivers/net/qede/qede_debug.h

diff --git a/drivers/net/qede/Makefile b/drivers/net/qede/Makefile
index 5810b4d49..3b00338ff 100644
--- a/drivers/net/qede/Makefile
+++ b/drivers/net/qede/Makefile
@@ -11,7 +11,6 @@ include $(RTE_SDK)/mk/rte.vars.mk
 LIB = librte_pmd_qede.a
 
 CFLAGS += -O3
-CFLAGS += $(WERROR_FLAGS)
 LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
 LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs
 LDLIBS += -lrte_bus_pci
@@ -37,7 +36,6 @@ CFLAGS_BASE_DRIVER += -Wno-missing-prototypes
 
 ifneq ($(CONFIG_RTE_TOOLCHAIN_ICC),y)
 CFLAGS_BASE_DRIVER += -Wno-unused-value
-CFLAGS_BASE_DRIVER += -Wno-format-nonliteral
 ifeq ($(OS_TYPE),Linux)
 ifeq ($(shell clang -Wno-shift-negative-value -Werror -E - < /dev/null > /dev/null 2>&1; echo $$?),0)
 CFLAGS_BASE_DRIVER += -Wno-shift-negative-value
@@ -48,6 +46,7 @@ endif
 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
 ifeq ($(shell test $(GCC_VERSION) -ge 44 && echo 1), 1)
 CFLAGS_BASE_DRIVER += -Wno-unused-but-set-variable
+CFLAGS += -Wno-format-nonliteral
 endif
 CFLAGS_BASE_DRIVER += -Wno-missing-declarations
 ifeq ($(shell test $(GCC_VERSION) -ge 46 && echo 1), 1)
@@ -104,5 +103,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_ethdev.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_main.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_rxtx.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_filter.c
+SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_debug.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index 6ea3e7dda..b4b94231b 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -457,7 +457,10 @@ void qed_set_platform_str(struct ecore_hwfn *p_hwfn,
 #define OSAL_SET_PLATFORM_STR(p_hwfn, buf_str, buf_size) \
 	qed_set_platform_str(p_hwfn, buf_str, buf_size)
 #define OSAL_GET_EPOCH(p_hwfn) ((u32)time(NULL))
-#define OSAL_DBG_ALLOC_USER_DATA(p_hwfn, user_data_ptr) (0)
+enum dbg_status	qed_dbg_alloc_user_data(struct ecore_hwfn *p_hwfn,
+					void **user_data_ptr);
+#define OSAL_DBG_ALLOC_USER_DATA(p_hwfn, user_data_ptr) \
+	qed_dbg_alloc_user_data(p_hwfn, user_data_ptr)
 #define OSAL_DB_REC_OCCURRED(p_hwfn) nothing
 
 #endif /* __BCM_OSAL_H */
diff --git a/drivers/net/qede/qede_debug.c b/drivers/net/qede/qede_debug.c
new file mode 100644
index 000000000..dd54e50be
--- /dev/null
+++ b/drivers/net/qede/qede_debug.c
@@ -0,0 +1,8120 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Marvell Semiconductor Inc.
+ * All rights reserved.
+ * www.marvell.com
+ */
+
+#include <rte_common.h>
+#include "base/bcm_osal.h"
+#include "base/ecore.h"
+#include "base/ecore_cxt.h"
+#include "base/ecore_hsi_common.h"
+#include "base/ecore_hw.h"
+#include "base/ecore_mcp.h"
+#include "base/reg_addr.h"
+#include "qede_debug.h"
+
+/* Memory groups enum */
+enum mem_groups {
+	MEM_GROUP_PXP_MEM,
+	MEM_GROUP_DMAE_MEM,
+	MEM_GROUP_CM_MEM,
+	MEM_GROUP_QM_MEM,
+	MEM_GROUP_DORQ_MEM,
+	MEM_GROUP_BRB_RAM,
+	MEM_GROUP_BRB_MEM,
+	MEM_GROUP_PRS_MEM,
+	MEM_GROUP_SDM_MEM,
+	MEM_GROUP_PBUF,
+	MEM_GROUP_IOR,
+	MEM_GROUP_RAM,
+	MEM_GROUP_BTB_RAM,
+	MEM_GROUP_RDIF_CTX,
+	MEM_GROUP_TDIF_CTX,
+	MEM_GROUP_CFC_MEM,
+	MEM_GROUP_CONN_CFC_MEM,
+	MEM_GROUP_CAU_PI,
+	MEM_GROUP_CAU_MEM,
+	MEM_GROUP_CAU_MEM_EXT,
+	MEM_GROUP_PXP_ILT,
+	MEM_GROUP_MULD_MEM,
+	MEM_GROUP_BTB_MEM,
+	MEM_GROUP_IGU_MEM,
+	MEM_GROUP_IGU_MSIX,
+	MEM_GROUP_CAU_SB,
+	MEM_GROUP_BMB_RAM,
+	MEM_GROUP_BMB_MEM,
+	MEM_GROUP_TM_MEM,
+	MEM_GROUP_TASK_CFC_MEM,
+	MEM_GROUPS_NUM
+};
+
+/* Memory groups names */
+static const char * const s_mem_group_names[] = {
+	"PXP_MEM",
+	"DMAE_MEM",
+	"CM_MEM",
+	"QM_MEM",
+	"DORQ_MEM",
+	"BRB_RAM",
+	"BRB_MEM",
+	"PRS_MEM",
+	"SDM_MEM",
+	"PBUF",
+	"IOR",
+	"RAM",
+	"BTB_RAM",
+	"RDIF_CTX",
+	"TDIF_CTX",
+	"CFC_MEM",
+	"CONN_CFC_MEM",
+	"CAU_PI",
+	"CAU_MEM",
+	"CAU_MEM_EXT",
+	"PXP_ILT",
+	"MULD_MEM",
+	"BTB_MEM",
+	"IGU_MEM",
+	"IGU_MSIX",
+	"CAU_SB",
+	"BMB_RAM",
+	"BMB_MEM",
+	"TM_MEM",
+	"TASK_CFC_MEM",
+};
+
+/* Idle check conditions */
+
+static u32 cond5(const u32 *r, const u32 *imm)
+{
+	return ((r[0] & imm[0]) != imm[1]) && ((r[1] & imm[2]) != imm[3]);
+}
+
+static u32 cond7(const u32 *r, const u32 *imm)
+{
+	return ((r[0] >> imm[0]) & imm[1]) != imm[2];
+}
+
+static u32 cond6(const u32 *r, const u32 *imm)
+{
+	return (r[0] & imm[0]) != imm[1];
+}
+
+static u32 cond9(const u32 *r, const u32 *imm)
+{
+	return ((r[0] & imm[0]) >> imm[1]) !=
+		(((r[0] & imm[2]) >> imm[3]) | ((r[1] & imm[4]) << imm[5]));
+}
+
+static u32 cond10(const u32 *r, const u32 *imm)
+{
+	return ((r[0] & imm[0]) >> imm[1]) != (r[0] & imm[2]);
+}
+
+static u32 cond4(const u32 *r, const u32 *imm)
+{
+	return (r[0] & ~imm[0]) != imm[1];
+}
+
+static u32 cond0(const u32 *r, const u32 *imm)
+{
+	return (r[0] & ~r[1]) != imm[0];
+}
+
+static u32 cond1(const u32 *r, const u32 *imm)
+{
+	return r[0] != imm[0];
+}
+
+static u32 cond11(const u32 *r, const u32 *imm)
+{
+	return r[0] != r[1] && r[2] == imm[0];
+}
+
+static u32 cond12(const u32 *r, const u32 *imm)
+{
+	return r[0] != r[1] && r[2] > imm[0];
+}
+
+static u32 cond3(const u32 *r, const __rte_unused u32 *imm)
+{
+	return r[0] != r[1];
+}
+
+static u32 cond13(const u32 *r, const u32 *imm)
+{
+	return r[0] & imm[0];
+}
+
+static u32 cond8(const u32 *r, const u32 *imm)
+{
+	return r[0] < (r[1] - imm[0]);
+}
+
+static u32 cond2(const u32 *r, const u32 *imm)
+{
+	return r[0] > imm[0];
+}
+
+/* Array of Idle Check conditions */
+static u32(*cond_arr[]) (const u32 *r, const u32 *imm) = {
+	cond0,
+	cond1,
+	cond2,
+	cond3,
+	cond4,
+	cond5,
+	cond6,
+	cond7,
+	cond8,
+	cond9,
+	cond10,
+	cond11,
+	cond12,
+	cond13,
+};
+
+#define NUM_PHYS_BLOCKS 84
+
+#define NUM_DBG_RESET_REGS 8
+
+/******************************* Data Types **********************************/
+
+enum hw_types {
+	HW_TYPE_ASIC,
+	PLATFORM_RESERVED,
+	PLATFORM_RESERVED2,
+	PLATFORM_RESERVED3,
+	PLATFORM_RESERVED4,
+	MAX_HW_TYPES
+};
+
+/* CM context types */
+enum cm_ctx_types {
+	CM_CTX_CONN_AG,
+	CM_CTX_CONN_ST,
+	CM_CTX_TASK_AG,
+	CM_CTX_TASK_ST,
+	NUM_CM_CTX_TYPES
+};
+
+/* Debug bus frame modes */
+enum dbg_bus_frame_modes {
+	DBG_BUS_FRAME_MODE_4ST = 0,	/* 4 Storm dwords (no HW) */
+	DBG_BUS_FRAME_MODE_2ST_2HW = 1,	/* 2 Storm dwords, 2 HW dwords */
+	DBG_BUS_FRAME_MODE_1ST_3HW = 2,	/* 1 Storm dwords, 3 HW dwords */
+	DBG_BUS_FRAME_MODE_4HW = 3,	/* 4 HW dwords (no Storms) */
+	DBG_BUS_FRAME_MODE_8HW = 4,	/* 8 HW dwords (no Storms) */
+	DBG_BUS_NUM_FRAME_MODES
+};
+
+/* Chip constant definitions */
+struct chip_defs {
+	const char *name;
+	u32 num_ilt_pages;
+};
+
+/* HW type constant definitions */
+struct hw_type_defs {
+	const char *name;
+	u32 delay_factor;
+	u32 dmae_thresh;
+	u32 log_thresh;
+};
+
+/* RBC reset definitions */
+struct rbc_reset_defs {
+	u32 reset_reg_addr;
+	u32 reset_val[MAX_CHIP_IDS];
+};
+
+/* Storm constant definitions.
+ * Addresses are in bytes, sizes are in quad-regs.
+ */
+struct storm_defs {
+	char letter;
+	enum block_id sem_block_id;
+	enum dbg_bus_clients dbg_client_id[MAX_CHIP_IDS];
+	bool has_vfc;
+	u32 sem_fast_mem_addr;
+	u32 sem_frame_mode_addr;
+	u32 sem_slow_enable_addr;
+	u32 sem_slow_mode_addr;
+	u32 sem_slow_mode1_conf_addr;
+	u32 sem_sync_dbg_empty_addr;
+	u32 sem_gpre_vect_addr;
+	u32 cm_ctx_wr_addr;
+	u32 cm_ctx_rd_addr[NUM_CM_CTX_TYPES];
+	u32 cm_ctx_lid_sizes[MAX_CHIP_IDS][NUM_CM_CTX_TYPES];
+};
+
+/* Debug Bus Constraint operation constant definitions */
+struct dbg_bus_constraint_op_defs {
+	u8 hw_op_val;
+	bool is_cyclic;
+};
+
+/* Storm Mode definitions */
+struct storm_mode_defs {
+	const char *name;
+	bool is_fast_dbg;
+	u8 id_in_hw;
+	u32 src_disable_reg_addr;
+	u32 src_enable_val;
+	bool exists[MAX_CHIP_IDS];
+};
+
+struct grc_param_defs {
+	u32 default_val[MAX_CHIP_IDS];
+	u32 min;
+	u32 max;
+	bool is_preset;
+	bool is_persistent;
+	u32 exclude_all_preset_val;
+	u32 crash_preset_val[MAX_CHIP_IDS];
+};
+
+/* Address is in 128b units. Width is in bits. */
+struct rss_mem_defs {
+	const char *mem_name;
+	const char *type_name;
+	u32 addr;
+	u32 entry_width;
+	u32 num_entries[MAX_CHIP_IDS];
+};
+
+struct vfc_ram_defs {
+	const char *mem_name;
+	const char *type_name;
+	u32 base_row;
+	u32 num_rows;
+};
+
+struct big_ram_defs {
+	const char *instance_name;
+	enum mem_groups mem_group_id;
+	enum mem_groups ram_mem_group_id;
+	enum dbg_grc_params grc_param;
+	u32 addr_reg_addr;
+	u32 data_reg_addr;
+	u32 is_256b_reg_addr;
+	u32 is_256b_bit_offset[MAX_CHIP_IDS];
+	u32 ram_size[MAX_CHIP_IDS]; /* In dwords */
+};
+
+struct phy_defs {
+	const char *phy_name;
+
+	/* PHY base GRC address */
+	u32 base_addr;
+
+	/* Relative address of indirect TBUS address register (bits 0..7) */
+	u32 tbus_addr_lo_addr;
+
+	/* Relative address of indirect TBUS address register (bits 8..10) */
+	u32 tbus_addr_hi_addr;
+
+	/* Relative address of indirect TBUS data register (bits 0..7) */
+	u32 tbus_data_lo_addr;
+
+	/* Relative address of indirect TBUS data register (bits 8..11) */
+	u32 tbus_data_hi_addr;
+};
+
+/* Split type definitions */
+struct split_type_defs {
+	const char *name;
+};
+
+/******************************** Constants **********************************/
+
+#define BYTES_IN_DWORD			sizeof(u32)
+/* In the macros below, size and offset are specified in bits */
+#define CEIL_DWORDS(size)		DIV_ROUND_UP(size, 32)
+#define FIELD_BIT_OFFSET(type, field)	type ## _ ## field ## _ ## OFFSET
+#define FIELD_BIT_SIZE(type, field)	type ## _ ## field ## _ ## SIZE
+#define FIELD_DWORD_OFFSET(type, field) \
+	 (int)(FIELD_BIT_OFFSET(type, field) / 32)
+#define FIELD_DWORD_SHIFT(type, field)	(FIELD_BIT_OFFSET(type, field) % 32)
+#define FIELD_BIT_MASK(type, field) \
+	(((1 << FIELD_BIT_SIZE(type, field)) - 1) << \
+	 FIELD_DWORD_SHIFT(type, field))
+
+#define SET_VAR_FIELD(var, type, field, val) \
+	do { \
+		var[FIELD_DWORD_OFFSET(type, field)] &=	\
+		(~FIELD_BIT_MASK(type, field));	\
+		var[FIELD_DWORD_OFFSET(type, field)] |= \
+		(val) << FIELD_DWORD_SHIFT(type, field); \
+	} while (0)
+
+#define ARR_REG_WR(dev, ptt, addr, arr, arr_size) \
+	do { \
+		for (i = 0; i < (arr_size); i++) \
+			ecore_wr(dev, ptt, addr,	(arr)[i]); \
+	} while (0)
+
+#define DWORDS_TO_BYTES(dwords)		((dwords) * BYTES_IN_DWORD)
+#define BYTES_TO_DWORDS(bytes)		((bytes) / BYTES_IN_DWORD)
+
+/* extra lines include a signature line + optional latency events line */
+#define NUM_EXTRA_DBG_LINES(block) \
+	(GET_FIELD((block)->flags, DBG_BLOCK_CHIP_HAS_LATENCY_EVENTS) ? 2 : 1)
+#define NUM_DBG_LINES(block) \
+	((block)->num_of_dbg_bus_lines + NUM_EXTRA_DBG_LINES(block))
+
+#define USE_DMAE			true
+#define PROTECT_WIDE_BUS		true
+
+#define RAM_LINES_TO_DWORDS(lines)	((lines) * 2)
+#define RAM_LINES_TO_BYTES(lines) \
+	DWORDS_TO_BYTES(RAM_LINES_TO_DWORDS(lines))
+
+#define REG_DUMP_LEN_SHIFT		24
+#define MEM_DUMP_ENTRY_SIZE_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_dump_mem))
+
+#define IDLE_CHK_RULE_SIZE_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_rule))
+
+#define IDLE_CHK_RESULT_HDR_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_result_hdr))
+
+#define IDLE_CHK_RESULT_REG_HDR_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_result_reg_hdr))
+
+#define PAGE_MEM_DESC_SIZE_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct phys_mem_desc))
+
+#define IDLE_CHK_MAX_ENTRIES_SIZE	32
+
+/* The sizes and offsets below are specified in bits */
+#define VFC_CAM_CMD_STRUCT_SIZE		64
+#define VFC_CAM_CMD_ROW_OFFSET		48
+#define VFC_CAM_CMD_ROW_SIZE		9
+#define VFC_CAM_ADDR_STRUCT_SIZE	16
+#define VFC_CAM_ADDR_OP_OFFSET		0
+#define VFC_CAM_ADDR_OP_SIZE		4
+#define VFC_CAM_RESP_STRUCT_SIZE	256
+#define VFC_RAM_ADDR_STRUCT_SIZE	16
+#define VFC_RAM_ADDR_OP_OFFSET		0
+#define VFC_RAM_ADDR_OP_SIZE		2
+#define VFC_RAM_ADDR_ROW_OFFSET		2
+#define VFC_RAM_ADDR_ROW_SIZE		10
+#define VFC_RAM_RESP_STRUCT_SIZE	256
+
+#define VFC_CAM_CMD_DWORDS		CEIL_DWORDS(VFC_CAM_CMD_STRUCT_SIZE)
+#define VFC_CAM_ADDR_DWORDS		CEIL_DWORDS(VFC_CAM_ADDR_STRUCT_SIZE)
+#define VFC_CAM_RESP_DWORDS		CEIL_DWORDS(VFC_CAM_RESP_STRUCT_SIZE)
+#define VFC_RAM_CMD_DWORDS		VFC_CAM_CMD_DWORDS
+#define VFC_RAM_ADDR_DWORDS		CEIL_DWORDS(VFC_RAM_ADDR_STRUCT_SIZE)
+#define VFC_RAM_RESP_DWORDS		CEIL_DWORDS(VFC_RAM_RESP_STRUCT_SIZE)
+
+#define NUM_VFC_RAM_TYPES		4
+
+#define VFC_CAM_NUM_ROWS		512
+
+#define VFC_OPCODE_CAM_RD		14
+#define VFC_OPCODE_RAM_RD		0
+
+#define NUM_RSS_MEM_TYPES		5
+
+#define NUM_BIG_RAM_TYPES		3
+#define BIG_RAM_NAME_LEN		3
+
+#define NUM_PHY_TBUS_ADDRESSES		2048
+#define PHY_DUMP_SIZE_DWORDS		(NUM_PHY_TBUS_ADDRESSES / 2)
+
+#define RESET_REG_UNRESET_OFFSET	4
+
+#define STALL_DELAY_MS			500
+
+#define STATIC_DEBUG_LINE_DWORDS	9
+
+#define NUM_COMMON_GLOBAL_PARAMS	11
+
+#define MAX_RECURSION_DEPTH		10
+
+#define FW_IMG_MAIN			1
+
+#define REG_FIFO_ELEMENT_DWORDS		2
+#define REG_FIFO_DEPTH_ELEMENTS		32
+#define REG_FIFO_DEPTH_DWORDS \
+	(REG_FIFO_ELEMENT_DWORDS * REG_FIFO_DEPTH_ELEMENTS)
+
+#define IGU_FIFO_ELEMENT_DWORDS		4
+#define IGU_FIFO_DEPTH_ELEMENTS		64
+#define IGU_FIFO_DEPTH_DWORDS \
+	(IGU_FIFO_ELEMENT_DWORDS * IGU_FIFO_DEPTH_ELEMENTS)
+
+#define PROTECTION_OVERRIDE_ELEMENT_DWORDS	2
+#define PROTECTION_OVERRIDE_DEPTH_ELEMENTS	20
+#define PROTECTION_OVERRIDE_DEPTH_DWORDS \
+	(PROTECTION_OVERRIDE_DEPTH_ELEMENTS * \
+	 PROTECTION_OVERRIDE_ELEMENT_DWORDS)
+
+#define MCP_SPAD_TRACE_OFFSIZE_ADDR \
+	(MCP_REG_SCRATCH + \
+	 offsetof(struct static_init, sections[SPAD_SECTION_TRACE]))
+
+#define MAX_SW_PLTAFORM_STR_SIZE	64
+
+#define EMPTY_FW_VERSION_STR		"???_???_???_???"
+#define EMPTY_FW_IMAGE_STR		"???????????????"
+
+/***************************** Constant Arrays *******************************/
+
+/* Chip constant definitions array */
+static struct chip_defs s_chip_defs[MAX_CHIP_IDS] = {
+	{"bb", PSWRQ2_REG_ILT_MEMORY_SIZE_BB / 2},
+	{"ah", PSWRQ2_REG_ILT_MEMORY_SIZE_K2 / 2}
+};
+
+/* Storm constant definitions array */
+static struct storm_defs s_storm_defs[] = {
+	/* Tstorm */
+	{'T', BLOCK_TSEM,
+		{DBG_BUS_CLIENT_RBCT, DBG_BUS_CLIENT_RBCT},
+		true,
+		TSEM_REG_FAST_MEMORY,
+		TSEM_REG_DBG_FRAME_MODE, TSEM_REG_SLOW_DBG_ACTIVE,
+		TSEM_REG_SLOW_DBG_MODE, TSEM_REG_DBG_MODE1_CFG,
+		TSEM_REG_SYNC_DBG_EMPTY, TSEM_REG_DBG_GPRE_VECT,
+		TCM_REG_CTX_RBC_ACCS,
+		{TCM_REG_AGG_CON_CTX, TCM_REG_SM_CON_CTX, TCM_REG_AGG_TASK_CTX,
+		 TCM_REG_SM_TASK_CTX},
+		{{4, 16, 2, 4}, {4, 16, 2, 4} } /* {bb} {k2} */
+	},
+
+	/* Mstorm */
+	{'M', BLOCK_MSEM,
+		{DBG_BUS_CLIENT_RBCT, DBG_BUS_CLIENT_RBCM},
+		false,
+		MSEM_REG_FAST_MEMORY,
+		MSEM_REG_DBG_FRAME_MODE,
+		MSEM_REG_SLOW_DBG_ACTIVE,
+		MSEM_REG_SLOW_DBG_MODE,
+		MSEM_REG_DBG_MODE1_CFG,
+		MSEM_REG_SYNC_DBG_EMPTY,
+		MSEM_REG_DBG_GPRE_VECT,
+		MCM_REG_CTX_RBC_ACCS,
+		{MCM_REG_AGG_CON_CTX, MCM_REG_SM_CON_CTX, MCM_REG_AGG_TASK_CTX,
+		 MCM_REG_SM_TASK_CTX },
+		{{1, 10, 2, 7}, {1, 10, 2, 7} } /* {bb} {k2}*/
+	},
+
+	/* Ustorm */
+	{'U', BLOCK_USEM,
+		{DBG_BUS_CLIENT_RBCU, DBG_BUS_CLIENT_RBCU},
+		false,
+		USEM_REG_FAST_MEMORY,
+		USEM_REG_DBG_FRAME_MODE,
+		USEM_REG_SLOW_DBG_ACTIVE,
+		USEM_REG_SLOW_DBG_MODE,
+		USEM_REG_DBG_MODE1_CFG,
+		USEM_REG_SYNC_DBG_EMPTY,
+		USEM_REG_DBG_GPRE_VECT,
+		UCM_REG_CTX_RBC_ACCS,
+		{UCM_REG_AGG_CON_CTX, UCM_REG_SM_CON_CTX, UCM_REG_AGG_TASK_CTX,
+		 UCM_REG_SM_TASK_CTX},
+		{{2, 13, 3, 3}, {2, 13, 3, 3} } /* {bb} {k2} */
+	},
+
+	/* Xstorm */
+	{'X', BLOCK_XSEM,
+		{DBG_BUS_CLIENT_RBCX, DBG_BUS_CLIENT_RBCX},
+		false,
+		XSEM_REG_FAST_MEMORY,
+		XSEM_REG_DBG_FRAME_MODE,
+		XSEM_REG_SLOW_DBG_ACTIVE,
+		XSEM_REG_SLOW_DBG_MODE,
+		XSEM_REG_DBG_MODE1_CFG,
+		XSEM_REG_SYNC_DBG_EMPTY,
+		XSEM_REG_DBG_GPRE_VECT,
+		XCM_REG_CTX_RBC_ACCS,
+		{XCM_REG_AGG_CON_CTX, XCM_REG_SM_CON_CTX, 0, 0},
+		{{9, 15, 0, 0}, {9, 15,	0, 0} } /* {bb} {k2} */
+	},
+
+	/* Ystorm */
+	{'Y', BLOCK_YSEM,
+		{DBG_BUS_CLIENT_RBCX, DBG_BUS_CLIENT_RBCY},
+		false,
+		YSEM_REG_FAST_MEMORY,
+		YSEM_REG_DBG_FRAME_MODE,
+		YSEM_REG_SLOW_DBG_ACTIVE,
+		YSEM_REG_SLOW_DBG_MODE,
+		YSEM_REG_DBG_MODE1_CFG,
+		YSEM_REG_SYNC_DBG_EMPTY,
+		YSEM_REG_DBG_GPRE_VECT,
+		YCM_REG_CTX_RBC_ACCS,
+		{YCM_REG_AGG_CON_CTX, YCM_REG_SM_CON_CTX, YCM_REG_AGG_TASK_CTX,
+		 YCM_REG_SM_TASK_CTX},
+		{{2, 3, 2, 12}, {2, 3, 2, 12} } /* {bb} {k2} */
+	},
+
+	/* Pstorm */
+	{'P', BLOCK_PSEM,
+		{DBG_BUS_CLIENT_RBCS, DBG_BUS_CLIENT_RBCS},
+		true,
+		PSEM_REG_FAST_MEMORY,
+		PSEM_REG_DBG_FRAME_MODE,
+		PSEM_REG_SLOW_DBG_ACTIVE,
+		PSEM_REG_SLOW_DBG_MODE,
+		PSEM_REG_DBG_MODE1_CFG,
+		PSEM_REG_SYNC_DBG_EMPTY,
+		PSEM_REG_DBG_GPRE_VECT,
+		PCM_REG_CTX_RBC_ACCS,
+		{0, PCM_REG_SM_CON_CTX, 0, 0},
+		{{0, 10, 0, 0}, {0, 10, 0, 0} } /* {bb} {k2} */
+	},
+};
+
+static struct hw_type_defs s_hw_type_defs[] = {
+	/* HW_TYPE_ASIC */
+	{"asic", 1, 256, 32768},
+	{"reserved", 0, 0, 0},
+	{"reserved2", 0, 0, 0},
+	{"reserved3", 0, 0, 0}
+};
+
+static struct grc_param_defs s_grc_param_defs[] = {
+	/* DBG_GRC_PARAM_DUMP_TSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_MSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_USTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_XSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_YSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_REGS */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_RAM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PBUF */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_IOR */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_VFC */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_CM_CTX */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_ILT */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_RSS */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_CAU */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_QM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_MCP */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_DORQ */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_CFC */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_IGU */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_BRB */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_BTB */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_BMB */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_RESERVED1 */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_MULD */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PRS */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_DMAE */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_TM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_SDM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_DIF */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_STATIC */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_UNSTALL */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_RESERVED2 */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_MCP_TRACE_META_SIZE */
+	{{0, 0}, 1, 0xffffffff, false, true, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_EXCLUDE_ALL */
+	{{0, 0}, 0, 1, true, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_CRASH */
+	{{0, 0}, 0, 1, true, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_PARITY_SAFE */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_CM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PHY */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_NO_MCP */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_NO_FW_VER */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_RESERVED3 */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_MCP_HW_DUMP */
+	{{0, 1}, 0, 1, false, false, 0, {0, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_ILT_CDUC */
+	{{1, 1}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_ILT_CDUT */
+	{{1, 1}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_CAU_EXT */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} }
+};
+
+static struct rss_mem_defs s_rss_mem_defs[] = {
+	{"rss_mem_cid", "rss_cid", 0, 32,
+	 {256, 320} },
+
+	{"rss_mem_key_msb", "rss_key", 1024, 256,
+	 {128, 208} },
+
+	{"rss_mem_key_lsb", "rss_key", 2048, 64,
+	 {128, 208} },
+
+	{"rss_mem_info", "rss_info", 3072, 16,
+	 {128, 208} },
+
+	{"rss_mem_ind", "rss_ind", 4096, 16,
+	 {16384, 26624} }
+};
+
+static struct vfc_ram_defs s_vfc_ram_defs[] = {
+	{"vfc_ram_tt1", "vfc_ram", 0, 512},
+	{"vfc_ram_mtt2", "vfc_ram", 512, 128},
+	{"vfc_ram_stt2", "vfc_ram", 640, 32},
+	{"vfc_ram_ro_vect", "vfc_ram", 672, 32}
+};
+
+static struct big_ram_defs s_big_ram_defs[] = {
+	{"BRB", MEM_GROUP_BRB_MEM, MEM_GROUP_BRB_RAM, DBG_GRC_PARAM_DUMP_BRB,
+	 BRB_REG_BIG_RAM_ADDRESS, BRB_REG_BIG_RAM_DATA,
+	 MISC_REG_BLOCK_256B_EN, {0, 0},
+	 {153600, 180224} },
+
+	{"BTB", MEM_GROUP_BTB_MEM, MEM_GROUP_BTB_RAM, DBG_GRC_PARAM_DUMP_BTB,
+	 BTB_REG_BIG_RAM_ADDRESS, BTB_REG_BIG_RAM_DATA,
+	 MISC_REG_BLOCK_256B_EN, {0, 1},
+	 {92160, 117760} },
+
+	{"BMB", MEM_GROUP_BMB_MEM, MEM_GROUP_BMB_RAM, DBG_GRC_PARAM_DUMP_BMB,
+	 BMB_REG_BIG_RAM_ADDRESS, BMB_REG_BIG_RAM_DATA,
+	 MISCS_REG_BLOCK_256B_EN, {0, 0},
+	 {36864, 36864} }
+};
+
+static struct rbc_reset_defs s_rbc_reset_defs[] = {
+	{MISCS_REG_RESET_PL_HV,
+	 {0x0, 0x400} },
+	{MISC_REG_RESET_PL_PDA_VMAIN_1,
+	 {0x4404040, 0x4404040} },
+	{MISC_REG_RESET_PL_PDA_VMAIN_2,
+	 {0x7, 0x7c00007} },
+	{MISC_REG_RESET_PL_PDA_VAUX,
+	 {0x2, 0x2} },
+};
+
+static struct phy_defs s_phy_defs[] = {
+	{"nw_phy", NWS_REG_NWS_CMU_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_7_0_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_15_8_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_7_0_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_11_8_K2},
+	{"sgmii_phy", MS_REG_MS_CMU_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X132_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X133_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X130_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X131_K2},
+	{"pcie_phy0", PHY_PCIE_REG_PHY0_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2},
+	{"pcie_phy1", PHY_PCIE_REG_PHY1_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2},
+};
+
+static struct split_type_defs s_split_type_defs[] = {
+	/* SPLIT_TYPE_NONE */
+	{"eng"},
+
+	/* SPLIT_TYPE_PORT */
+	{"port"},
+
+	/* SPLIT_TYPE_PF */
+	{"pf"},
+
+	/* SPLIT_TYPE_PORT_PF */
+	{"port"},
+
+	/* SPLIT_TYPE_VF */
+	{"vf"}
+};
+
+/******************************** Variables *********************************/
+
+/**
+ * The version of the calling app
+ */
+static u32 s_app_ver;
+
+/**************************** Private Functions ******************************/
+
+/* Reads and returns a single dword from the specified unaligned buffer */
+static u32 qed_read_unaligned_dword(u8 *buf)
+{
+	u32 dword;
+
+	memcpy((u8 *)&dword, buf, sizeof(dword));
+	return dword;
+}
+
+/* Sets the value of the specified GRC param */
+static void qed_grc_set_param(struct ecore_hwfn *p_hwfn,
+			      enum dbg_grc_params grc_param, u32 val)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	dev_data->grc.param_val[grc_param] = val;
+}
+
+/* Returns the value of the specified GRC param */
+static u32 qed_grc_get_param(struct ecore_hwfn *p_hwfn,
+			     enum dbg_grc_params grc_param)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	return dev_data->grc.param_val[grc_param];
+}
+
+/* Initializes the GRC parameters */
+static void qed_dbg_grc_init_params(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	if (!dev_data->grc.params_initialized) {
+		qed_dbg_grc_set_params_default(p_hwfn);
+		dev_data->grc.params_initialized = 1;
+	}
+}
+
+/* Sets pointer and size for the specified binary buffer type */
+static void qed_set_dbg_bin_buf(struct ecore_hwfn *p_hwfn,
+				enum bin_dbg_buffer_type buf_type,
+				const u32 *ptr, u32 size)
+{
+	struct virt_mem_desc *buf = &p_hwfn->dbg_arrays[buf_type];
+
+	buf->ptr = (void *)(osal_uintptr_t)ptr;
+	buf->size = size;
+}
+
+/* Initializes debug data for the specified device */
+static enum dbg_status qed_dbg_dev_init(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 num_pfs = 0, max_pfs_per_port = 0;
+
+	if (dev_data->initialized)
+		return DBG_STATUS_OK;
+
+	/* Set chip */
+	if (ECORE_IS_K2(p_hwfn->p_dev)) {
+		dev_data->chip_id = CHIP_K2;
+		dev_data->mode_enable[MODE_K2] = 1;
+		dev_data->num_vfs = MAX_NUM_VFS_K2;
+		num_pfs = MAX_NUM_PFS_K2;
+		max_pfs_per_port = MAX_NUM_PFS_K2 / 2;
+	} else if (ECORE_IS_BB_B0(p_hwfn->p_dev)) {
+		dev_data->chip_id = CHIP_BB;
+		dev_data->mode_enable[MODE_BB] = 1;
+		dev_data->num_vfs = MAX_NUM_VFS_BB;
+		num_pfs = MAX_NUM_PFS_BB;
+		max_pfs_per_port = MAX_NUM_PFS_BB;
+	} else {
+		return DBG_STATUS_UNKNOWN_CHIP;
+	}
+
+	/* Set HW type */
+	dev_data->hw_type = HW_TYPE_ASIC;
+	dev_data->mode_enable[MODE_ASIC] = 1;
+
+	/* Set port mode */
+	switch (p_hwfn->p_dev->num_ports_in_engine) {
+	case 1:
+		dev_data->mode_enable[MODE_PORTS_PER_ENG_1] = 1;
+		break;
+	case 2:
+		dev_data->mode_enable[MODE_PORTS_PER_ENG_2] = 1;
+		break;
+	case 4:
+		dev_data->mode_enable[MODE_PORTS_PER_ENG_4] = 1;
+		break;
+	}
+
+	/* Set 100G mode */
+	if (ECORE_IS_CMT(p_hwfn->p_dev))
+		dev_data->mode_enable[MODE_100G] = 1;
+
+	/* Set number of ports */
+	if (dev_data->mode_enable[MODE_PORTS_PER_ENG_1] ||
+	    dev_data->mode_enable[MODE_100G])
+		dev_data->num_ports = 1;
+	else if (dev_data->mode_enable[MODE_PORTS_PER_ENG_2])
+		dev_data->num_ports = 2;
+	else if (dev_data->mode_enable[MODE_PORTS_PER_ENG_4])
+		dev_data->num_ports = 4;
+
+	/* Set number of PFs per port */
+	dev_data->num_pfs_per_port = OSAL_MIN_T(u32,
+						num_pfs / dev_data->num_ports,
+						max_pfs_per_port);
+
+	/* Initializes the GRC parameters */
+	qed_dbg_grc_init_params(p_hwfn);
+
+	dev_data->use_dmae = true;
+	dev_data->initialized = 1;
+
+	return DBG_STATUS_OK;
+}
+
+static const struct dbg_block *get_dbg_block(struct ecore_hwfn *p_hwfn,
+					     enum block_id block_id)
+{
+	const struct dbg_block *dbg_block;
+
+	dbg_block = p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS].ptr;
+	return dbg_block + block_id;
+}
+
+static const struct dbg_block_chip *qed_get_dbg_block_per_chip(struct ecore_hwfn
+							       *p_hwfn,
+							       enum block_id
+							       block_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	return (const struct dbg_block_chip *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS_CHIP_DATA].ptr +
+	    block_id * MAX_CHIP_IDS + dev_data->chip_id;
+}
+
+static const struct dbg_reset_reg *qed_get_dbg_reset_reg(struct ecore_hwfn
+							 *p_hwfn,
+							 u8 reset_reg_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	return (const struct dbg_reset_reg *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_RESET_REGS].ptr +
+	    reset_reg_id * MAX_CHIP_IDS + dev_data->chip_id;
+}
+
+/* Reads the FW info structure for the specified Storm from the chip,
+ * and writes it to the specified fw_info pointer.
+ */
+static void qed_read_storm_fw_info(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   u8 storm_id, struct fw_info *fw_info)
+{
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	struct fw_info_location fw_info_location;
+	u32 addr, i, *dest;
+
+	memset(&fw_info_location, 0, sizeof(fw_info_location));
+	memset(fw_info, 0, sizeof(*fw_info));
+
+	/* Read first the address that points to fw_info location.
+	 * The address is located in the last line of the Storm RAM.
+	 */
+	addr = storm->sem_fast_mem_addr + SEM_FAST_REG_INT_RAM +
+	    DWORDS_TO_BYTES(SEM_FAST_REG_INT_RAM_SIZE) -
+	    sizeof(fw_info_location);
+
+	dest = (u32 *)&fw_info_location;
+
+	for (i = 0; i < BYTES_TO_DWORDS(sizeof(fw_info_location));
+	     i++, addr += BYTES_IN_DWORD)
+		dest[i] = ecore_rd(p_hwfn, p_ptt, addr);
+
+	/* Read FW version info from Storm RAM */
+	if (fw_info_location.size > 0 && fw_info_location.size <=
+	    sizeof(*fw_info)) {
+		addr = fw_info_location.grc_addr;
+		dest = (u32 *)fw_info;
+		for (i = 0; i < BYTES_TO_DWORDS(fw_info_location.size);
+		     i++, addr += BYTES_IN_DWORD)
+			dest[i] = ecore_rd(p_hwfn, p_ptt, addr);
+	}
+}
+
+/* Dumps the specified string to the specified buffer.
+ * Returns the dumped size in bytes.
+ */
+static u32 qed_dump_str(char *dump_buf, bool dump, const char *str)
+{
+	if (dump)
+		strcpy(dump_buf, str);
+
+	return (u32)strlen(str) + 1;
+}
+
+/* Dumps zeros to align the specified buffer to dwords.
+ * Returns the dumped size in bytes.
+ */
+static u32 qed_dump_align(char *dump_buf, bool dump, u32 byte_offset)
+{
+	u8 offset_in_dword, align_size;
+
+	offset_in_dword = (u8)(byte_offset & 0x3);
+	align_size = offset_in_dword ? BYTES_IN_DWORD - offset_in_dword : 0;
+
+	if (dump && align_size)
+		memset(dump_buf, 0, align_size);
+
+	return align_size;
+}
+
+/* Writes the specified string param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_str_param(u32 *dump_buf,
+			      bool dump,
+			      const char *param_name, const char *param_val)
+{
+	char *char_buf = (char *)dump_buf;
+	u32 offset = 0;
+
+	/* Dump param name */
+	offset += qed_dump_str(char_buf + offset, dump, param_name);
+
+	/* Indicate a string param value */
+	if (dump)
+		*(char_buf + offset) = 1;
+	offset++;
+
+	/* Dump param value */
+	offset += qed_dump_str(char_buf + offset, dump, param_val);
+
+	/* Align buffer to next dword */
+	offset += qed_dump_align(char_buf + offset, dump, offset);
+
+	return BYTES_TO_DWORDS(offset);
+}
+
+/* Writes the specified numeric param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_num_param(u32 *dump_buf,
+			      bool dump, const char *param_name, u32 param_val)
+{
+	char *char_buf = (char *)dump_buf;
+	u32 offset = 0;
+
+	/* Dump param name */
+	offset += qed_dump_str(char_buf + offset, dump, param_name);
+
+	/* Indicate a numeric param value */
+	if (dump)
+		*(char_buf + offset) = 0;
+	offset++;
+
+	/* Align buffer to next dword */
+	offset += qed_dump_align(char_buf + offset, dump, offset);
+
+	/* Dump param value (and change offset from bytes to dwords) */
+	offset = BYTES_TO_DWORDS(offset);
+	if (dump)
+		*(dump_buf + offset) = param_val;
+	offset++;
+
+	return offset;
+}
+
+/* Reads the FW version and writes it as a param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_fw_ver_param(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf, bool dump)
+{
+	char fw_ver_str[16] = EMPTY_FW_VERSION_STR;
+	char fw_img_str[16] = EMPTY_FW_IMAGE_STR;
+	struct fw_info fw_info = { {0}, {0} };
+	u32 offset = 0;
+
+	if (dump && !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_FW_VER)) {
+		/* Read FW info from chip */
+		qed_read_fw_info(p_hwfn, p_ptt, &fw_info);
+
+		/* Create FW version/image strings */
+		if (snprintf(fw_ver_str, sizeof(fw_ver_str),
+			     "%d_%d_%d_%d", fw_info.ver.num.major,
+			     fw_info.ver.num.minor, fw_info.ver.num.rev,
+			     fw_info.ver.num.eng) < 0)
+			DP_NOTICE(p_hwfn, false,
+				  "Unexpected debug error: invalid FW version string\n");
+		switch (fw_info.ver.image_id) {
+		case FW_IMG_MAIN:
+			strcpy(fw_img_str, "main");
+			break;
+		default:
+			strcpy(fw_img_str, "unknown");
+			break;
+		}
+	}
+
+	/* Dump FW version, image and timestamp */
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "fw-version", fw_ver_str);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "fw-image", fw_img_str);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "fw-timestamp", fw_info.ver.timestamp);
+
+	return offset;
+}
+
+/* Reads the MFW version and writes it as a param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_mfw_ver_param(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  u32 *dump_buf, bool dump)
+{
+	char mfw_ver_str[16] = EMPTY_FW_VERSION_STR;
+
+	if (dump &&
+	    !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_FW_VER)) {
+		u32 global_section_offsize, global_section_addr, mfw_ver;
+		u32 public_data_addr, global_section_offsize_addr;
+
+		/* Find MCP public data GRC address. Needs to be ORed with
+		 * MCP_REG_SCRATCH due to a HW bug.
+		 */
+		public_data_addr = ecore_rd(p_hwfn,
+					  p_ptt,
+					  MISC_REG_SHARED_MEM_ADDR) |
+				   MCP_REG_SCRATCH;
+
+		/* Find MCP public global section offset */
+		global_section_offsize_addr = public_data_addr +
+					      offsetof(struct mcp_public_data,
+						       sections) +
+					      sizeof(offsize_t) * PUBLIC_GLOBAL;
+		global_section_offsize = ecore_rd(p_hwfn, p_ptt,
+						global_section_offsize_addr);
+		global_section_addr =
+			MCP_REG_SCRATCH +
+			(global_section_offsize & OFFSIZE_OFFSET_MASK) * 4;
+
+		/* Read MFW version from MCP public global section */
+		mfw_ver = ecore_rd(p_hwfn, p_ptt,
+				 global_section_addr +
+				 offsetof(struct public_global, mfw_ver));
+
+		/* Dump MFW version param */
+		if (snprintf(mfw_ver_str, sizeof(mfw_ver_str), "%d_%d_%d_%d",
+			     (u8)(mfw_ver >> 24), (u8)(mfw_ver >> 16),
+			     (u8)(mfw_ver >> 8), (u8)mfw_ver) < 0)
+			DP_NOTICE(p_hwfn, false,
+				  "Unexpected debug error: invalid MFW version string\n");
+	}
+
+	return qed_dump_str_param(dump_buf, dump, "mfw-version", mfw_ver_str);
+}
+
+/* Reads the chip revision from the chip and writes it as a param to the
+ * specified buffer. Returns the dumped size in dwords.
+ */
+static u32 qed_dump_chip_revision_param(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	char param_str[3] = "??";
+
+	if (dev_data->hw_type == HW_TYPE_ASIC) {
+		u32 chip_rev, chip_metal;
+
+		chip_rev = ecore_rd(p_hwfn, p_ptt, MISCS_REG_CHIP_REV);
+		chip_metal = ecore_rd(p_hwfn, p_ptt, MISCS_REG_CHIP_METAL);
+
+		param_str[0] = 'a' + (u8)chip_rev;
+		param_str[1] = '0' + (u8)chip_metal;
+	}
+
+	return qed_dump_str_param(dump_buf, dump, "chip-revision", param_str);
+}
+
+/* Writes a section header to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_section_hdr(u32 *dump_buf,
+				bool dump, const char *name, u32 num_params)
+{
+	return qed_dump_num_param(dump_buf, dump, name, num_params);
+}
+
+/* Writes the common global params to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_common_global_params(struct ecore_hwfn *p_hwfn,
+					 struct ecore_ptt *p_ptt,
+					 u32 *dump_buf,
+					 bool dump,
+					 u8 num_specific_global_params)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	char sw_platform_str[MAX_SW_PLTAFORM_STR_SIZE];
+	u32 offset = 0;
+	u8 num_params;
+
+	/* Fill platform string */
+	ecore_set_platform_str(p_hwfn, sw_platform_str,
+			       MAX_SW_PLTAFORM_STR_SIZE);
+
+	/* Dump global params section header */
+	num_params = NUM_COMMON_GLOBAL_PARAMS + num_specific_global_params +
+		(dev_data->chip_id == CHIP_BB ? 1 : 0);
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "global_params", num_params);
+
+	/* Store params */
+	offset += qed_dump_fw_ver_param(p_hwfn, p_ptt, dump_buf + offset, dump);
+	offset += qed_dump_mfw_ver_param(p_hwfn,
+					 p_ptt, dump_buf + offset, dump);
+	offset += qed_dump_chip_revision_param(p_hwfn,
+					       p_ptt, dump_buf + offset, dump);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "tools-version", TOOLS_VERSION);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump,
+				     "chip",
+				     s_chip_defs[dev_data->chip_id].name);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump,
+				     "platform",
+				     s_hw_type_defs[dev_data->hw_type].name);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "sw-platform", sw_platform_str);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "pci-func", p_hwfn->abs_pf_id);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "epoch", OSAL_GET_EPOCH(p_hwfn));
+	if (dev_data->chip_id == CHIP_BB)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "path",
+					     ECORE_PATH_ID(p_hwfn));
+
+	return offset;
+}
+
+/* Writes the "last" section (including CRC) to the specified buffer at the
+ * given offset. Returns the dumped size in dwords.
+ */
+static u32 qed_dump_last_section(u32 *dump_buf, u32 offset, bool dump)
+{
+	u32 start_offset = offset;
+
+	/* Dump CRC section header */
+	offset += qed_dump_section_hdr(dump_buf + offset, dump, "last", 0);
+
+	/* Calculate CRC32 and add it to the dword after the "last" section */
+	if (dump)
+		*(dump_buf + offset) = ~OSAL_CRC32(0xffffffff,
+					      (u8 *)dump_buf,
+					      DWORDS_TO_BYTES(offset));
+
+	offset++;
+
+	return offset - start_offset;
+}
+
+/* Update blocks reset state  */
+static void qed_update_blocks_reset_state(struct ecore_hwfn *p_hwfn,
+					  struct ecore_ptt *p_ptt)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 reg_val[NUM_DBG_RESET_REGS] = { 0 };
+	u8 rst_reg_id;
+	u32 blk_id;
+
+	/* Read reset registers */
+	for (rst_reg_id = 0; rst_reg_id < NUM_DBG_RESET_REGS; rst_reg_id++) {
+		const struct dbg_reset_reg *rst_reg;
+		bool rst_reg_removed;
+		u32 rst_reg_addr;
+
+		rst_reg = qed_get_dbg_reset_reg(p_hwfn, rst_reg_id);
+		rst_reg_removed = GET_FIELD(rst_reg->data,
+					    DBG_RESET_REG_IS_REMOVED);
+		rst_reg_addr = DWORDS_TO_BYTES(GET_FIELD(rst_reg->data,
+							 DBG_RESET_REG_ADDR));
+
+		if (!rst_reg_removed)
+			reg_val[rst_reg_id] = ecore_rd(p_hwfn, p_ptt,
+						     rst_reg_addr);
+	}
+
+	/* Check if blocks are in reset */
+	for (blk_id = 0; blk_id < NUM_PHYS_BLOCKS; blk_id++) {
+		const struct dbg_block_chip *blk;
+		bool has_rst_reg;
+		bool is_removed;
+
+		blk = qed_get_dbg_block_per_chip(p_hwfn, (enum block_id)blk_id);
+		is_removed = GET_FIELD(blk->flags, DBG_BLOCK_CHIP_IS_REMOVED);
+		has_rst_reg = GET_FIELD(blk->flags,
+					DBG_BLOCK_CHIP_HAS_RESET_REG);
+
+		if (!is_removed && has_rst_reg)
+			dev_data->block_in_reset[blk_id] =
+			    !(reg_val[blk->reset_reg_id] &
+			      OSAL_BIT(blk->reset_reg_bit_offset));
+	}
+}
+
+/* is_mode_match recursive function */
+static bool qed_is_mode_match_rec(struct ecore_hwfn *p_hwfn,
+				  u16 *modes_buf_offset, u8 rec_depth)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	const u8 *dbg_array;
+	bool arg1, arg2;
+	u8 tree_val;
+
+	if (rec_depth > MAX_RECURSION_DEPTH) {
+		DP_NOTICE(p_hwfn, false,
+			  "Unexpected error: is_mode_match_rec exceeded the max recursion depth. This is probably due to a corrupt init/debug buffer.\n");
+		return false;
+	}
+
+	/* Get next element from modes tree buffer */
+	dbg_array = p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr;
+	tree_val = dbg_array[(*modes_buf_offset)++];
+
+	switch (tree_val) {
+	case INIT_MODE_OP_NOT:
+		return !qed_is_mode_match_rec(p_hwfn,
+					      modes_buf_offset, rec_depth + 1);
+	case INIT_MODE_OP_OR:
+	case INIT_MODE_OP_AND:
+		arg1 = qed_is_mode_match_rec(p_hwfn,
+					     modes_buf_offset, rec_depth + 1);
+		arg2 = qed_is_mode_match_rec(p_hwfn,
+					     modes_buf_offset, rec_depth + 1);
+		return (tree_val == INIT_MODE_OP_OR) ? (arg1 ||
+							arg2) : (arg1 && arg2);
+	default:
+		return dev_data->mode_enable[tree_val - MAX_INIT_MODE_OPS] > 0;
+	}
+}
+
+/* Returns true if the mode (specified using modes_buf_offset) is enabled */
+static bool qed_is_mode_match(struct ecore_hwfn *p_hwfn, u16 *modes_buf_offset)
+{
+	return qed_is_mode_match_rec(p_hwfn, modes_buf_offset, 0);
+}
+
+/* Enable / disable the Debug block */
+static void qed_bus_enable_dbg_block(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt, bool enable)
+{
+	ecore_wr(p_hwfn, p_ptt, DBG_REG_DBG_BLOCK_ON, enable ? 1 : 0);
+}
+
+/* Resets the Debug block */
+static void qed_bus_reset_dbg_block(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt)
+{
+	u32 reset_reg_addr, old_reset_reg_val, new_reset_reg_val;
+	const struct dbg_reset_reg *reset_reg;
+	const struct dbg_block_chip *block;
+
+	block = qed_get_dbg_block_per_chip(p_hwfn, BLOCK_DBG);
+	reset_reg = qed_get_dbg_reset_reg(p_hwfn, block->reset_reg_id);
+	reset_reg_addr =
+	    DWORDS_TO_BYTES(GET_FIELD(reset_reg->data, DBG_RESET_REG_ADDR));
+
+	old_reset_reg_val = ecore_rd(p_hwfn, p_ptt, reset_reg_addr);
+	new_reset_reg_val =
+	    old_reset_reg_val & ~OSAL_BIT(block->reset_reg_bit_offset);
+
+	ecore_wr(p_hwfn, p_ptt, reset_reg_addr, new_reset_reg_val);
+	ecore_wr(p_hwfn, p_ptt, reset_reg_addr, old_reset_reg_val);
+}
+
+/* Enable / disable Debug Bus clients according to the specified mask
+ * (1 = enable, 0 = disable).
+ */
+static void qed_bus_enable_clients(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt, u32 client_mask)
+{
+	ecore_wr(p_hwfn, p_ptt, DBG_REG_CLIENT_ENABLE, client_mask);
+}
+
+static void qed_bus_config_dbg_line(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    enum block_id block_id,
+				    u8 line_id,
+				    u8 enable_mask,
+				    u8 right_shift,
+				    u8 force_valid_mask, u8 force_frame_mask)
+{
+	const struct dbg_block_chip *block =
+		qed_get_dbg_block_per_chip(p_hwfn, block_id);
+
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_select_reg_addr),
+		 line_id);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_dword_enable_reg_addr),
+		 enable_mask);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_shift_reg_addr),
+		 right_shift);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_force_valid_reg_addr),
+		 force_valid_mask);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_force_frame_reg_addr),
+		 force_frame_mask);
+}
+
+/* Disable debug bus in all blocks */
+static void qed_bus_disable_blocks(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_id;
+
+	/* Disable all blocks */
+	for (block_id = 0; block_id < MAX_BLOCK_ID; block_id++) {
+		const struct dbg_block_chip *block_per_chip =
+		    qed_get_dbg_block_per_chip(p_hwfn,
+					       (enum block_id)block_id);
+
+		if (GET_FIELD(block_per_chip->flags,
+			      DBG_BLOCK_CHIP_IS_REMOVED) ||
+		    dev_data->block_in_reset[block_id])
+			continue;
+
+		/* Disable debug bus */
+		if (GET_FIELD(block_per_chip->flags,
+			      DBG_BLOCK_CHIP_HAS_DBG_BUS)) {
+			u32 dbg_en_addr =
+				block_per_chip->dbg_dword_enable_reg_addr;
+			u16 modes_buf_offset =
+			    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+				      DBG_MODE_HDR_MODES_BUF_OFFSET);
+			bool eval_mode =
+			    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+
+			if (!eval_mode ||
+			    qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				ecore_wr(p_hwfn, p_ptt,
+				       DWORDS_TO_BYTES(dbg_en_addr),
+				       0);
+		}
+	}
+}
+
+/* Returns true if the specified entity (indicated by GRC param) should be
+ * included in the dump, false otherwise.
+ */
+static bool qed_grc_is_included(struct ecore_hwfn *p_hwfn,
+				enum dbg_grc_params grc_param)
+{
+	return qed_grc_get_param(p_hwfn, grc_param) > 0;
+}
+
+/* Returns the storm_id that matches the specified Storm letter,
+ * or MAX_DBG_STORMS if invalid storm letter.
+ */
+static enum dbg_storms qed_get_id_from_letter(char storm_letter)
+{
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++)
+		if (s_storm_defs[storm_id].letter == storm_letter)
+			return (enum dbg_storms)storm_id;
+
+	return MAX_DBG_STORMS;
+}
+
+/* Returns true of the specified Storm should be included in the dump, false
+ * otherwise.
+ */
+static bool qed_grc_is_storm_included(struct ecore_hwfn *p_hwfn,
+				      enum dbg_storms storm)
+{
+	return qed_grc_get_param(p_hwfn, (enum dbg_grc_params)storm) > 0;
+}
+
+/* Returns true if the specified memory should be included in the dump, false
+ * otherwise.
+ */
+static bool qed_grc_is_mem_included(struct ecore_hwfn *p_hwfn,
+				    enum block_id block_id, u8 mem_group_id)
+{
+	const struct dbg_block *block;
+	u8 i;
+
+	block = get_dbg_block(p_hwfn, block_id);
+
+	/* If the block is associated with a Storm, check Storm match */
+	if (block->associated_storm_letter) {
+		enum dbg_storms associated_storm_id =
+		    qed_get_id_from_letter(block->associated_storm_letter);
+
+		if (associated_storm_id == MAX_DBG_STORMS ||
+		    !qed_grc_is_storm_included(p_hwfn, associated_storm_id))
+			return false;
+	}
+
+	for (i = 0; i < NUM_BIG_RAM_TYPES; i++) {
+		struct big_ram_defs *big_ram = &s_big_ram_defs[i];
+
+		if (mem_group_id == big_ram->mem_group_id ||
+		    mem_group_id == big_ram->ram_mem_group_id)
+			return qed_grc_is_included(p_hwfn, big_ram->grc_param);
+	}
+
+	switch (mem_group_id) {
+	case MEM_GROUP_PXP_ILT:
+	case MEM_GROUP_PXP_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PXP);
+	case MEM_GROUP_RAM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_RAM);
+	case MEM_GROUP_PBUF:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PBUF);
+	case MEM_GROUP_CAU_MEM:
+	case MEM_GROUP_CAU_SB:
+	case MEM_GROUP_CAU_PI:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CAU);
+	case MEM_GROUP_CAU_MEM_EXT:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CAU_EXT);
+	case MEM_GROUP_QM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_QM);
+	case MEM_GROUP_CFC_MEM:
+	case MEM_GROUP_CONN_CFC_MEM:
+	case MEM_GROUP_TASK_CFC_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CFC) ||
+		       qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM_CTX);
+	case MEM_GROUP_DORQ_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DORQ);
+	case MEM_GROUP_IGU_MEM:
+	case MEM_GROUP_IGU_MSIX:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_IGU);
+	case MEM_GROUP_MULD_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MULD);
+	case MEM_GROUP_PRS_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PRS);
+	case MEM_GROUP_DMAE_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DMAE);
+	case MEM_GROUP_TM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_TM);
+	case MEM_GROUP_SDM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_SDM);
+	case MEM_GROUP_TDIF_CTX:
+	case MEM_GROUP_RDIF_CTX:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DIF);
+	case MEM_GROUP_CM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM);
+	case MEM_GROUP_IOR:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_IOR);
+	default:
+		return true;
+	}
+}
+
+/* Stalls all Storms */
+static void qed_grc_stall_storms(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt, bool stall)
+{
+	u32 reg_addr;
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		if (!qed_grc_is_storm_included(p_hwfn,
+					       (enum dbg_storms)storm_id))
+			continue;
+
+		reg_addr = s_storm_defs[storm_id].sem_fast_mem_addr +
+		    SEM_FAST_REG_STALL_0;
+		ecore_wr(p_hwfn, p_ptt, reg_addr, stall ? 1 : 0);
+	}
+
+	OSAL_MSLEEP(STALL_DELAY_MS);
+}
+
+/* Takes all blocks out of reset. If rbc_only is true, only RBC clients are
+ * taken out of reset.
+ */
+static void qed_grc_unreset_blocks(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt, bool rbc_only)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 chip_id = dev_data->chip_id;
+	u32 i;
+
+	/* Take RBCs out of reset */
+	for (i = 0; i < OSAL_ARRAY_SIZE(s_rbc_reset_defs); i++)
+		if (s_rbc_reset_defs[i].reset_val[dev_data->chip_id])
+			ecore_wr(p_hwfn,
+			       p_ptt,
+			       s_rbc_reset_defs[i].reset_reg_addr +
+			       RESET_REG_UNRESET_OFFSET,
+			       s_rbc_reset_defs[i].reset_val[chip_id]);
+
+	if (!rbc_only) {
+		u32 reg_val[NUM_DBG_RESET_REGS] = { 0 };
+		u8 reset_reg_id;
+		u32 block_id;
+
+		/* Fill reset regs values */
+		for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
+			bool is_removed, has_reset_reg, unreset_before_dump;
+			const struct dbg_block_chip *block;
+
+			block = qed_get_dbg_block_per_chip(p_hwfn,
+							   (enum block_id)
+							   block_id);
+			is_removed =
+			    GET_FIELD(block->flags, DBG_BLOCK_CHIP_IS_REMOVED);
+			has_reset_reg =
+			    GET_FIELD(block->flags,
+				      DBG_BLOCK_CHIP_HAS_RESET_REG);
+			unreset_before_dump =
+			    GET_FIELD(block->flags,
+				      DBG_BLOCK_CHIP_UNRESET_BEFORE_DUMP);
+
+			if (!is_removed && has_reset_reg && unreset_before_dump)
+				reg_val[block->reset_reg_id] |=
+				    OSAL_BIT(block->reset_reg_bit_offset);
+		}
+
+		/* Write reset registers */
+		for (reset_reg_id = 0; reset_reg_id < NUM_DBG_RESET_REGS;
+		     reset_reg_id++) {
+			const struct dbg_reset_reg *reset_reg;
+			u32 reset_reg_addr;
+
+			reset_reg = qed_get_dbg_reset_reg(p_hwfn, reset_reg_id);
+
+			if (GET_FIELD
+			    (reset_reg->data, DBG_RESET_REG_IS_REMOVED))
+				continue;
+
+			if (reg_val[reset_reg_id]) {
+				reset_reg_addr =
+				    GET_FIELD(reset_reg->data,
+					      DBG_RESET_REG_ADDR);
+				ecore_wr(p_hwfn,
+				       p_ptt,
+				       DWORDS_TO_BYTES(reset_reg_addr) +
+				       RESET_REG_UNRESET_OFFSET,
+				       reg_val[reset_reg_id]);
+			}
+		}
+	}
+}
+
+/* Returns the attention block data of the specified block */
+static const struct dbg_attn_block_type_data *
+qed_get_block_attn_data(struct ecore_hwfn *p_hwfn,
+			enum block_id block_id, enum dbg_attn_type attn_type)
+{
+	const struct dbg_attn_block *base_attn_block_arr =
+	    (const struct dbg_attn_block *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr;
+
+	return &base_attn_block_arr[block_id].per_type_data[attn_type];
+}
+
+/* Returns the attention registers of the specified block */
+static const struct dbg_attn_reg *
+qed_get_block_attn_regs(struct ecore_hwfn *p_hwfn,
+			enum block_id block_id, enum dbg_attn_type attn_type,
+			u8 *num_attn_regs)
+{
+	const struct dbg_attn_block_type_data *block_type_data =
+	    qed_get_block_attn_data(p_hwfn, block_id, attn_type);
+
+	*num_attn_regs = block_type_data->num_regs;
+
+	return (const struct dbg_attn_reg *)
+		p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr +
+		block_type_data->regs_offset;
+}
+
+/* For each block, clear the status of all parities */
+static void qed_grc_clear_all_prty(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	const struct dbg_attn_reg *attn_reg_arr;
+	u8 reg_idx, num_attn_regs;
+	u32 block_id;
+
+	for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
+		if (dev_data->block_in_reset[block_id])
+			continue;
+
+		attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
+						       (enum block_id)block_id,
+						       ATTN_TYPE_PARITY,
+						       &num_attn_regs);
+
+		for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
+			const struct dbg_attn_reg *reg_data =
+				&attn_reg_arr[reg_idx];
+			u16 modes_buf_offset;
+			bool eval_mode;
+
+			/* Check mode */
+			eval_mode = GET_FIELD(reg_data->mode.data,
+					      DBG_MODE_HDR_EVAL_MODE) > 0;
+			modes_buf_offset =
+				GET_FIELD(reg_data->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+
+			/* If Mode match: clear parity status */
+			if (!eval_mode ||
+			    qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				ecore_rd(p_hwfn, p_ptt,
+				    DWORDS_TO_BYTES(reg_data->sts_clr_address));
+		}
+	}
+}
+
+/* Dumps GRC registers section header. Returns the dumped size in dwords.
+ * the following parameters are dumped:
+ * - count: no. of dumped entries
+ * - split_type: split type
+ * - split_id: split ID (dumped only if split_id != SPLIT_TYPE_NONE)
+ * - reg_type_name: register type name (dumped only if reg_type_name != NULL)
+ */
+static u32 qed_grc_dump_regs_hdr(u32 *dump_buf,
+				 bool dump,
+				 u32 num_reg_entries,
+				 enum init_split_types split_type,
+				 u8 split_id, const char *reg_type_name)
+{
+	u8 num_params = 2 +
+	    (split_type != SPLIT_TYPE_NONE ? 1 : 0) + (reg_type_name ? 1 : 0);
+	u32 offset = 0;
+
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "grc_regs", num_params);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "count", num_reg_entries);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "split",
+				     s_split_type_defs[split_type].name);
+	if (split_type != SPLIT_TYPE_NONE)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "id", split_id);
+	if (reg_type_name)
+		offset += qed_dump_str_param(dump_buf + offset,
+					     dump, "type", reg_type_name);
+
+	return offset;
+}
+
+/* Reads the specified registers into the specified buffer.
+ * The addr and len arguments are specified in dwords.
+ */
+void qed_read_regs(struct ecore_hwfn *p_hwfn,
+		   struct ecore_ptt *p_ptt, u32 *buf, u32 addr, u32 len)
+{
+	u32 i;
+
+	for (i = 0; i < len; i++)
+		buf[i] = ecore_rd(p_hwfn, p_ptt, DWORDS_TO_BYTES(addr + i));
+}
+
+/* Dumps the GRC registers in the specified address range.
+ * Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_addr_range(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   u32 *dump_buf,
+				   bool dump, u32 addr, u32 len, bool wide_bus,
+				   enum init_split_types split_type,
+				   u8 split_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 port_id = 0, pf_id = 0, vf_id = 0, fid = 0;
+	bool read_using_dmae = false;
+	u32 thresh;
+
+	if (!dump)
+		return len;
+
+	switch (split_type) {
+	case SPLIT_TYPE_PORT:
+		port_id = split_id;
+		break;
+	case SPLIT_TYPE_PF:
+		pf_id = split_id;
+		break;
+	case SPLIT_TYPE_PORT_PF:
+		port_id = split_id / dev_data->num_pfs_per_port;
+		pf_id = port_id + dev_data->num_ports *
+		    (split_id % dev_data->num_pfs_per_port);
+		break;
+	case SPLIT_TYPE_VF:
+		vf_id = split_id;
+		break;
+	default:
+		break;
+	}
+
+	/* Try reading using DMAE */
+	if (dev_data->use_dmae && split_type != SPLIT_TYPE_VF &&
+	    (len >= s_hw_type_defs[dev_data->hw_type].dmae_thresh ||
+	     (PROTECT_WIDE_BUS && wide_bus))) {
+		struct dmae_params dmae_params;
+
+		/* Set DMAE params */
+		memset(&dmae_params, 0, sizeof(dmae_params));
+		SET_FIELD(dmae_params.flags, DMAE_PARAMS_COMPLETION_DST, 1);
+		switch (split_type) {
+		case SPLIT_TYPE_PORT:
+			SET_FIELD(dmae_params.flags, DMAE_PARAMS_PORT_VALID,
+				  1);
+			dmae_params.port_id = port_id;
+			break;
+		case SPLIT_TYPE_PF:
+			SET_FIELD(dmae_params.flags,
+				  DMAE_PARAMS_SRC_PF_VALID, 1);
+			dmae_params.src_pf_id = pf_id;
+			break;
+		case SPLIT_TYPE_PORT_PF:
+			SET_FIELD(dmae_params.flags, DMAE_PARAMS_PORT_VALID,
+				  1);
+			SET_FIELD(dmae_params.flags,
+				  DMAE_PARAMS_SRC_PF_VALID, 1);
+			dmae_params.port_id = port_id;
+			dmae_params.src_pf_id = pf_id;
+			break;
+		default:
+			break;
+		}
+
+		/* Execute DMAE command */
+		read_using_dmae = !ecore_dmae_grc2host(p_hwfn,
+						     p_ptt,
+						     DWORDS_TO_BYTES(addr),
+						     (u64)(uintptr_t)(dump_buf),
+						     len, &dmae_params);
+		if (!read_using_dmae) {
+			dev_data->use_dmae = 0;
+			DP_VERBOSE(p_hwfn->p_dev,
+				   ECORE_MSG_DEBUG,
+				   "Failed reading from chip using DMAE, using GRC instead\n");
+		}
+	}
+
+	if (read_using_dmae)
+		goto print_log;
+
+	/* If not read using DMAE, read using GRC */
+
+	/* Set pretend */
+	if (split_type != dev_data->pretend.split_type ||
+	    split_id != dev_data->pretend.split_id) {
+		switch (split_type) {
+		case SPLIT_TYPE_PORT:
+			ecore_port_pretend(p_hwfn, p_ptt, port_id);
+			break;
+		case SPLIT_TYPE_PF:
+			fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
+					  pf_id);
+			ecore_fid_pretend(p_hwfn, p_ptt, fid);
+			break;
+		case SPLIT_TYPE_PORT_PF:
+			fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
+					  pf_id);
+			ecore_port_fid_pretend(p_hwfn, p_ptt, port_id, fid);
+			break;
+		case SPLIT_TYPE_VF:
+			fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_VFVALID, 1)
+			      | FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_VFID,
+					  vf_id);
+			ecore_fid_pretend(p_hwfn, p_ptt, fid);
+			break;
+		default:
+			break;
+		}
+
+		dev_data->pretend.split_type = (u8)split_type;
+		dev_data->pretend.split_id = split_id;
+	}
+
+	/* Read registers using GRC */
+	qed_read_regs(p_hwfn, p_ptt, dump_buf, addr, len);
+
+print_log:
+	/* Print log */
+	dev_data->num_regs_read += len;
+	thresh = s_hw_type_defs[dev_data->hw_type].log_thresh;
+	if ((dev_data->num_regs_read / thresh) >
+	    ((dev_data->num_regs_read - len) / thresh))
+		DP_VERBOSE(p_hwfn->p_dev,
+			   ECORE_MSG_DEBUG,
+			   "Dumped %d registers...\n", dev_data->num_regs_read);
+
+	return len;
+}
+
+/* Dumps GRC registers sequence header. Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_reg_entry_hdr(u32 *dump_buf,
+				      bool dump, u32 addr, u32 len)
+{
+	if (dump)
+		*dump_buf = addr | (len << REG_DUMP_LEN_SHIFT);
+
+	return 1;
+}
+
+/* Dumps GRC registers sequence. Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_reg_entry(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  u32 *dump_buf,
+				  bool dump, u32 addr, u32 len, bool wide_bus,
+				  enum init_split_types split_type, u8 split_id)
+{
+	u32 offset = 0;
+
+	offset += qed_grc_dump_reg_entry_hdr(dump_buf, dump, addr, len);
+	offset += qed_grc_dump_addr_range(p_hwfn,
+					  p_ptt,
+					  dump_buf + offset,
+					  dump, addr, len, wide_bus,
+					  split_type, split_id);
+
+	return offset;
+}
+
+/* Dumps GRC registers sequence with skip cycle.
+ * Returns the dumped size in dwords.
+ * - addr:	start GRC address in dwords
+ * - total_len:	total no. of dwords to dump
+ * - read_len:	no. consecutive dwords to read
+ * - skip_len:	no. of dwords to skip (and fill with zeros)
+ */
+static u32 qed_grc_dump_reg_entry_skip(struct ecore_hwfn *p_hwfn,
+				       struct ecore_ptt *p_ptt,
+				       u32 *dump_buf,
+				       bool dump,
+				       u32 addr,
+				       u32 total_len,
+				       u32 read_len, u32 skip_len)
+{
+	u32 offset = 0, reg_offset = 0;
+
+	offset += qed_grc_dump_reg_entry_hdr(dump_buf, dump, addr, total_len);
+
+	if (!dump)
+		return offset + total_len;
+
+	while (reg_offset < total_len) {
+		u32 curr_len = OSAL_MIN_T(u32, read_len,
+					  total_len - reg_offset);
+
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  dump,  addr, curr_len, false,
+						  SPLIT_TYPE_NONE, 0);
+		reg_offset += curr_len;
+		addr += curr_len;
+
+		if (reg_offset < total_len) {
+			curr_len = OSAL_MIN_T(u32, skip_len,
+					      total_len - skip_len);
+			memset(dump_buf + offset, 0, DWORDS_TO_BYTES(curr_len));
+			offset += curr_len;
+			reg_offset += curr_len;
+			addr += curr_len;
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC registers entries. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_regs_entries(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     struct virt_mem_desc input_regs_arr,
+				     u32 *dump_buf,
+				     bool dump,
+				     enum init_split_types split_type,
+				     u8 split_id,
+				     bool block_enable[MAX_BLOCK_ID],
+				     u32 *num_dumped_reg_entries)
+{
+	u32 i, offset = 0, input_offset = 0;
+	bool mode_match = true;
+
+	*num_dumped_reg_entries = 0;
+
+	while (input_offset < BYTES_TO_DWORDS(input_regs_arr.size)) {
+		const struct dbg_dump_cond_hdr *cond_hdr =
+		    (const struct dbg_dump_cond_hdr *)
+		    input_regs_arr.ptr + input_offset++;
+		u16 modes_buf_offset;
+		bool eval_mode;
+
+		/* Check mode/block */
+		eval_mode = GET_FIELD(cond_hdr->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		if (eval_mode) {
+			modes_buf_offset =
+				GET_FIELD(cond_hdr->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			mode_match = qed_is_mode_match(p_hwfn,
+						       &modes_buf_offset);
+		}
+
+		if (!mode_match || !block_enable[cond_hdr->block_id]) {
+			input_offset += cond_hdr->data_size;
+			continue;
+		}
+
+		for (i = 0; i < cond_hdr->data_size; i++, input_offset++) {
+			const struct dbg_dump_reg *reg =
+			    (const struct dbg_dump_reg *)
+			    input_regs_arr.ptr + input_offset;
+			u32 addr, len;
+			bool wide_bus;
+
+			addr = GET_FIELD(reg->data, DBG_DUMP_REG_ADDRESS);
+			len = GET_FIELD(reg->data, DBG_DUMP_REG_LENGTH);
+			wide_bus = GET_FIELD(reg->data, DBG_DUMP_REG_WIDE_BUS);
+			offset += qed_grc_dump_reg_entry(p_hwfn,
+							 p_ptt,
+							 dump_buf + offset,
+							 dump,
+							 addr,
+							 len,
+							 wide_bus,
+							 split_type, split_id);
+			(*num_dumped_reg_entries)++;
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC registers entries. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_split_data(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   struct virt_mem_desc input_regs_arr,
+				   u32 *dump_buf,
+				   bool dump,
+				   bool block_enable[MAX_BLOCK_ID],
+				   enum init_split_types split_type,
+				   u8 split_id, const char *reg_type_name)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	enum init_split_types hdr_split_type = split_type;
+	u32 num_dumped_reg_entries, offset;
+	u8 hdr_split_id = split_id;
+
+	/* In PORT_PF split type, print a port split header */
+	if (split_type == SPLIT_TYPE_PORT_PF) {
+		hdr_split_type = SPLIT_TYPE_PORT;
+		hdr_split_id = split_id / dev_data->num_pfs_per_port;
+	}
+
+	/* Calculate register dump header size (and skip it for now) */
+	offset = qed_grc_dump_regs_hdr(dump_buf,
+				       false,
+				       0,
+				       hdr_split_type,
+				       hdr_split_id, reg_type_name);
+
+	/* Dump registers */
+	offset += qed_grc_dump_regs_entries(p_hwfn,
+					    p_ptt,
+					    input_regs_arr,
+					    dump_buf + offset,
+					    dump,
+					    split_type,
+					    split_id,
+					    block_enable,
+					    &num_dumped_reg_entries);
+
+	/* Write register dump header */
+	if (dump && num_dumped_reg_entries > 0)
+		qed_grc_dump_regs_hdr(dump_buf,
+				      dump,
+				      num_dumped_reg_entries,
+				      hdr_split_type,
+				      hdr_split_id, reg_type_name);
+
+	return num_dumped_reg_entries > 0 ? offset : 0;
+}
+
+/* Dumps registers according to the input registers array. Returns the dumped
+ * size in dwords.
+ */
+static u32 qed_grc_dump_registers(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  u32 *dump_buf,
+				  bool dump,
+				  bool block_enable[MAX_BLOCK_ID],
+				  const char *reg_type_name)
+{
+	struct virt_mem_desc *dbg_buf =
+	    &p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG];
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 offset = 0, input_offset = 0;
+
+	while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
+		const struct dbg_dump_split_hdr *split_hdr;
+		struct virt_mem_desc curr_input_regs_arr;
+		enum init_split_types split_type;
+		u16 split_count = 0;
+		u32 split_data_size;
+		u8 split_id;
+
+		split_hdr =
+		    (const struct dbg_dump_split_hdr *)
+		    dbg_buf->ptr + input_offset++;
+		split_type =
+		    GET_FIELD(split_hdr->hdr,
+			      DBG_DUMP_SPLIT_HDR_SPLIT_TYPE_ID);
+		split_data_size = GET_FIELD(split_hdr->hdr,
+					    DBG_DUMP_SPLIT_HDR_DATA_SIZE);
+		curr_input_regs_arr.ptr =
+		    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG].ptr +
+		    input_offset;
+		curr_input_regs_arr.size = DWORDS_TO_BYTES(split_data_size);
+
+		switch (split_type) {
+		case SPLIT_TYPE_NONE:
+			split_count = 1;
+			break;
+		case SPLIT_TYPE_PORT:
+			split_count = dev_data->num_ports;
+			break;
+		case SPLIT_TYPE_PF:
+		case SPLIT_TYPE_PORT_PF:
+			split_count = dev_data->num_ports *
+			    dev_data->num_pfs_per_port;
+			break;
+		case SPLIT_TYPE_VF:
+			split_count = dev_data->num_vfs;
+			break;
+		default:
+			return 0;
+		}
+
+		for (split_id = 0; split_id < split_count; split_id++)
+			offset += qed_grc_dump_split_data(p_hwfn, p_ptt,
+							  curr_input_regs_arr,
+							  dump_buf + offset,
+							  dump, block_enable,
+							  split_type,
+							  split_id,
+							  reg_type_name);
+
+		input_offset += split_data_size;
+	}
+
+	/* Cancel pretends (pretend to original PF) */
+	if (dump) {
+		ecore_fid_pretend(p_hwfn, p_ptt,
+				FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
+					    p_hwfn->rel_pf_id));
+		dev_data->pretend.split_type = SPLIT_TYPE_NONE;
+		dev_data->pretend.split_id = 0;
+	}
+
+	return offset;
+}
+
+/* Dump reset registers. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_reset_regs(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   u32 *dump_buf, bool dump)
+{
+	u32 offset = 0, num_regs = 0;
+	u8 reset_reg_id;
+
+	/* Calculate header size */
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					false,
+					0, SPLIT_TYPE_NONE, 0, "RESET_REGS");
+
+	/* Write reset registers */
+	for (reset_reg_id = 0; reset_reg_id < NUM_DBG_RESET_REGS;
+	     reset_reg_id++) {
+		const struct dbg_reset_reg *reset_reg;
+		u32 reset_reg_addr;
+
+		reset_reg = qed_get_dbg_reset_reg(p_hwfn, reset_reg_id);
+
+		if (GET_FIELD(reset_reg->data, DBG_RESET_REG_IS_REMOVED))
+			continue;
+
+		reset_reg_addr = GET_FIELD(reset_reg->data, DBG_RESET_REG_ADDR);
+		offset += qed_grc_dump_reg_entry(p_hwfn,
+						 p_ptt,
+						 dump_buf + offset,
+						 dump,
+						 reset_reg_addr,
+						 1, false, SPLIT_TYPE_NONE, 0);
+		num_regs++;
+	}
+
+	/* Write header */
+	if (dump)
+		qed_grc_dump_regs_hdr(dump_buf,
+				      true, num_regs, SPLIT_TYPE_NONE,
+				      0, "RESET_REGS");
+
+	return offset;
+}
+
+/* Dump registers that are modified during GRC Dump and therefore must be
+ * dumped first. Returns the dumped size in dwords.
+ */
+static u32 qed_grc_dump_modified_regs(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_id, offset = 0, stall_regs_offset;
+	const struct dbg_attn_reg *attn_reg_arr;
+	u8 storm_id, reg_idx, num_attn_regs;
+	u32 num_reg_entries = 0;
+
+	/* Write empty header for attention registers */
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					false,
+					0, SPLIT_TYPE_NONE, 0, "ATTN_REGS");
+
+	/* Write parity registers */
+	for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
+		if (dev_data->block_in_reset[block_id] && dump)
+			continue;
+
+		attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
+						       (enum block_id)block_id,
+						       ATTN_TYPE_PARITY,
+						       &num_attn_regs);
+
+		for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
+			const struct dbg_attn_reg *reg_data =
+				&attn_reg_arr[reg_idx];
+			u16 modes_buf_offset;
+			bool eval_mode;
+			u32 addr;
+
+			/* Check mode */
+			eval_mode = GET_FIELD(reg_data->mode.data,
+					      DBG_MODE_HDR_EVAL_MODE) > 0;
+			modes_buf_offset =
+				GET_FIELD(reg_data->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			if (eval_mode &&
+			    !qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				continue;
+
+			/* Mode match: read & dump registers */
+			addr = reg_data->mask_address;
+			offset += qed_grc_dump_reg_entry(p_hwfn,
+							 p_ptt,
+							 dump_buf + offset,
+							 dump,
+							 addr,
+							 1, false,
+							 SPLIT_TYPE_NONE, 0);
+			addr = GET_FIELD(reg_data->data,
+					 DBG_ATTN_REG_STS_ADDRESS);
+			offset += qed_grc_dump_reg_entry(p_hwfn,
+							 p_ptt,
+							 dump_buf + offset,
+							 dump,
+							 addr,
+							 1, false,
+							 SPLIT_TYPE_NONE, 0);
+			num_reg_entries += 2;
+		}
+	}
+
+	/* Overwrite header for attention registers */
+	if (dump)
+		qed_grc_dump_regs_hdr(dump_buf,
+				      true,
+				      num_reg_entries,
+				      SPLIT_TYPE_NONE, 0, "ATTN_REGS");
+
+	/* Write empty header for stall registers */
+	stall_regs_offset = offset;
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					false, 0, SPLIT_TYPE_NONE, 0, "REGS");
+
+	/* Write Storm stall status registers */
+	for (storm_id = 0, num_reg_entries = 0; storm_id < MAX_DBG_STORMS;
+	     storm_id++) {
+		struct storm_defs *storm = &s_storm_defs[storm_id];
+		u32 addr;
+
+		if (dev_data->block_in_reset[storm->sem_block_id] && dump)
+			continue;
+
+		addr =
+		    BYTES_TO_DWORDS(storm->sem_fast_mem_addr +
+				    SEM_FAST_REG_STALLED);
+		offset += qed_grc_dump_reg_entry(p_hwfn,
+						 p_ptt,
+						 dump_buf + offset,
+						 dump,
+						 addr,
+						 1,
+						 false, SPLIT_TYPE_NONE, 0);
+		num_reg_entries++;
+	}
+
+	/* Overwrite header for stall registers */
+	if (dump)
+		qed_grc_dump_regs_hdr(dump_buf + stall_regs_offset,
+				      true,
+				      num_reg_entries,
+				      SPLIT_TYPE_NONE, 0, "REGS");
+
+	return offset;
+}
+
+/* Dumps registers that can't be represented in the debug arrays */
+static u32 qed_grc_dump_special_regs(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     u32 *dump_buf, bool dump)
+{
+	u32 offset = 0, addr;
+
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					dump, 2, SPLIT_TYPE_NONE, 0, "REGS");
+
+	/* Dump R/TDIF_REG_DEBUG_ERROR_INFO_SIZE (every 8'th register should be
+	 * skipped).
+	 */
+	addr = BYTES_TO_DWORDS(RDIF_REG_DEBUG_ERROR_INFO);
+	offset += qed_grc_dump_reg_entry_skip(p_hwfn,
+					      p_ptt,
+					      dump_buf + offset,
+					      dump,
+					      addr,
+					      RDIF_REG_DEBUG_ERROR_INFO_SIZE,
+					      7,
+					      1);
+	addr = BYTES_TO_DWORDS(TDIF_REG_DEBUG_ERROR_INFO);
+	offset +=
+	    qed_grc_dump_reg_entry_skip(p_hwfn,
+					p_ptt,
+					dump_buf + offset,
+					dump,
+					addr,
+					TDIF_REG_DEBUG_ERROR_INFO_SIZE,
+					7,
+					1);
+
+	return offset;
+}
+
+/* Dumps a GRC memory header (section and params). Returns the dumped size in
+ * dwords. The following parameters are dumped:
+ * - name:	   dumped only if it's not NULL.
+ * - addr:	   in dwords, dumped only if name is NULL.
+ * - len:	   in dwords, always dumped.
+ * - width:	   dumped if it's not zero.
+ * - packed:	   dumped only if it's not false.
+ * - mem_group:	   always dumped.
+ * - is_storm:	   true only if the memory is related to a Storm.
+ * - storm_letter: valid only if is_storm is true.
+ *
+ */
+static u32 qed_grc_dump_mem_hdr(struct ecore_hwfn *p_hwfn,
+				u32 *dump_buf,
+				bool dump,
+				const char *name,
+				u32 addr,
+				u32 len,
+				u32 bit_width,
+				bool packed,
+				const char *mem_group, char storm_letter)
+{
+	u8 num_params = 3;
+	u32 offset = 0;
+	char buf[64];
+
+	if (!len)
+		DP_NOTICE(p_hwfn, false,
+			  "Unexpected GRC Dump error: dumped memory size must be non-zero\n");
+
+	if (bit_width)
+		num_params++;
+	if (packed)
+		num_params++;
+
+	/* Dump section header */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "grc_mem", num_params);
+
+	if (name) {
+		/* Dump name */
+		if (storm_letter) {
+			strcpy(buf, "?STORM_");
+			buf[0] = storm_letter;
+			strcpy(buf + strlen(buf), name);
+		} else {
+			strcpy(buf, name);
+		}
+
+		offset += qed_dump_str_param(dump_buf + offset,
+					     dump, "name", buf);
+	} else {
+		/* Dump address */
+		u32 addr_in_bytes = DWORDS_TO_BYTES(addr);
+
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "addr", addr_in_bytes);
+	}
+
+	/* Dump len */
+	offset += qed_dump_num_param(dump_buf + offset, dump, "len", len);
+
+	/* Dump bit width */
+	if (bit_width)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "width", bit_width);
+
+	/* Dump packed */
+	if (packed)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "packed", 1);
+
+	/* Dump reg type */
+	if (storm_letter) {
+		strcpy(buf, "?STORM_");
+		buf[0] = storm_letter;
+		strcpy(buf + strlen(buf), mem_group);
+	} else {
+		strcpy(buf, mem_group);
+	}
+
+	offset += qed_dump_str_param(dump_buf + offset, dump, "type", buf);
+
+	return offset;
+}
+
+/* Dumps a single GRC memory. If name is NULL, the memory is stored by address.
+ * Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_mem(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt,
+			    u32 *dump_buf,
+			    bool dump,
+			    const char *name,
+			    u32 addr,
+			    u32 len,
+			    bool wide_bus,
+			    u32 bit_width,
+			    bool packed,
+			    const char *mem_group, char storm_letter)
+{
+	u32 offset = 0;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       name,
+				       addr,
+				       len,
+				       bit_width,
+				       packed, mem_group, storm_letter);
+	offset += qed_grc_dump_addr_range(p_hwfn,
+					  p_ptt,
+					  dump_buf + offset,
+					  dump, addr, len, wide_bus,
+					  SPLIT_TYPE_NONE, 0);
+
+	return offset;
+}
+
+/* Dumps GRC memories entries. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_mem_entries(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    struct virt_mem_desc input_mems_arr,
+				    u32 *dump_buf, bool dump)
+{
+	u32 i, offset = 0, input_offset = 0;
+	bool mode_match = true;
+
+	while (input_offset < BYTES_TO_DWORDS(input_mems_arr.size)) {
+		const struct dbg_dump_cond_hdr *cond_hdr;
+		u16 modes_buf_offset;
+		u32 num_entries;
+		bool eval_mode;
+
+		cond_hdr =
+		    (const struct dbg_dump_cond_hdr *)input_mems_arr.ptr +
+		    input_offset++;
+		num_entries = cond_hdr->data_size / MEM_DUMP_ENTRY_SIZE_DWORDS;
+
+		/* Check required mode */
+		eval_mode = GET_FIELD(cond_hdr->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		if (eval_mode) {
+			modes_buf_offset =
+				GET_FIELD(cond_hdr->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			mode_match = qed_is_mode_match(p_hwfn,
+						       &modes_buf_offset);
+		}
+
+		if (!mode_match) {
+			input_offset += cond_hdr->data_size;
+			continue;
+		}
+
+		for (i = 0; i < num_entries;
+		     i++, input_offset += MEM_DUMP_ENTRY_SIZE_DWORDS) {
+			const struct dbg_dump_mem *mem =
+			    (const struct dbg_dump_mem *)((u32 *)
+							  input_mems_arr.ptr
+							  + input_offset);
+			const struct dbg_block *block;
+			char storm_letter = 0;
+			u32 mem_addr, mem_len;
+			bool mem_wide_bus;
+			u8 mem_group_id;
+
+			mem_group_id = GET_FIELD(mem->dword0,
+						 DBG_DUMP_MEM_MEM_GROUP_ID);
+			if (mem_group_id >= MEM_GROUPS_NUM) {
+				DP_NOTICE(p_hwfn, false, "Invalid mem_group_id\n");
+				return 0;
+			}
+
+			if (!qed_grc_is_mem_included(p_hwfn,
+						     (enum block_id)
+						     cond_hdr->block_id,
+						     mem_group_id))
+				continue;
+
+			mem_addr = GET_FIELD(mem->dword0, DBG_DUMP_MEM_ADDRESS);
+			mem_len = GET_FIELD(mem->dword1, DBG_DUMP_MEM_LENGTH);
+			mem_wide_bus = GET_FIELD(mem->dword1,
+						 DBG_DUMP_MEM_WIDE_BUS);
+
+			block = get_dbg_block(p_hwfn,
+					      cond_hdr->block_id);
+
+			/* If memory is associated with Storm,
+			 * update storm details
+			 */
+			if (block->associated_storm_letter)
+				storm_letter = block->associated_storm_letter;
+
+			/* Dump memory */
+			offset += qed_grc_dump_mem(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						NULL,
+						mem_addr,
+						mem_len,
+						mem_wide_bus,
+						0,
+						false,
+						s_mem_group_names[mem_group_id],
+						storm_letter);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC memories according to the input array dump_mem.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_grc_dump_memories(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf, bool dump)
+{
+	struct virt_mem_desc *dbg_buf =
+	    &p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_MEM];
+	u32 offset = 0, input_offset = 0;
+
+	while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
+		const struct dbg_dump_split_hdr *split_hdr;
+		struct virt_mem_desc curr_input_mems_arr;
+		enum init_split_types split_type;
+		u32 split_data_size;
+
+		split_hdr =
+		    (const struct dbg_dump_split_hdr *)dbg_buf->ptr +
+		    input_offset++;
+		split_type = GET_FIELD(split_hdr->hdr,
+				       DBG_DUMP_SPLIT_HDR_SPLIT_TYPE_ID);
+		split_data_size = GET_FIELD(split_hdr->hdr,
+					    DBG_DUMP_SPLIT_HDR_DATA_SIZE);
+		curr_input_mems_arr.ptr = (u32 *)dbg_buf->ptr + input_offset;
+		curr_input_mems_arr.size = DWORDS_TO_BYTES(split_data_size);
+
+		if (split_type == SPLIT_TYPE_NONE)
+			offset += qed_grc_dump_mem_entries(p_hwfn,
+							   p_ptt,
+							   curr_input_mems_arr,
+							   dump_buf + offset,
+							   dump);
+		else
+			DP_NOTICE(p_hwfn, false,
+				  "Dumping split memories is currently not supported\n");
+
+		input_offset += split_data_size;
+	}
+
+	return offset;
+}
+
+/* Dumps GRC context data for the specified Storm.
+ * Returns the dumped size in dwords.
+ * The lid_size argument is specified in quad-regs.
+ */
+static u32 qed_grc_dump_ctx_data(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf,
+				 bool dump,
+				 const char *name,
+				 u32 num_lids,
+				 enum cm_ctx_types ctx_type, u8 storm_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	u32 i, lid, lid_size, total_size;
+	u32 rd_reg_addr, offset = 0;
+
+	/* Convert quad-regs to dwords */
+	lid_size = storm->cm_ctx_lid_sizes[dev_data->chip_id][ctx_type] * 4;
+
+	if (!lid_size)
+		return 0;
+
+	total_size = num_lids * lid_size;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       name,
+				       0,
+				       total_size,
+				       lid_size * 32,
+				       false, name, storm->letter);
+
+	if (!dump)
+		return offset + total_size;
+
+	rd_reg_addr = BYTES_TO_DWORDS(storm->cm_ctx_rd_addr[ctx_type]);
+
+	/* Dump context data */
+	for (lid = 0; lid < num_lids; lid++) {
+		for (i = 0; i < lid_size; i++) {
+			ecore_wr(p_hwfn,
+			       p_ptt, storm->cm_ctx_wr_addr, (i << 9) | lid);
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  rd_reg_addr,
+							  1,
+							  false,
+							  SPLIT_TYPE_NONE, 0);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC contexts. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_ctx(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	u32 offset = 0;
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		if (!qed_grc_is_storm_included(p_hwfn,
+					       (enum dbg_storms)storm_id))
+			continue;
+
+		/* Dump Conn AG context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"CONN_AG_CTX",
+						NUM_OF_LCIDS,
+						CM_CTX_CONN_AG, storm_id);
+
+		/* Dump Conn ST context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"CONN_ST_CTX",
+						NUM_OF_LCIDS,
+						CM_CTX_CONN_ST, storm_id);
+
+		/* Dump Task AG context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"TASK_AG_CTX",
+						NUM_OF_LTIDS,
+						CM_CTX_TASK_AG, storm_id);
+
+		/* Dump Task ST context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"TASK_ST_CTX",
+						NUM_OF_LTIDS,
+						CM_CTX_TASK_ST, storm_id);
+	}
+
+	return offset;
+}
+
+#define VFC_STATUS_RESP_READY_BIT	0
+#define VFC_STATUS_BUSY_BIT		1
+#define VFC_STATUS_SENDING_CMD_BIT	2
+
+#define VFC_POLLING_DELAY_MS	1
+#define VFC_POLLING_COUNT		20
+
+/* Reads data from VFC. Returns the number of dwords read (0 on error).
+ * Sizes are specified in dwords.
+ */
+static u32 qed_grc_dump_read_from_vfc(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      struct storm_defs *storm,
+				      u32 *cmd_data,
+				      u32 cmd_size,
+				      u32 *addr_data,
+				      u32 addr_size,
+				      u32 resp_size, u32 *dump_buf)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 vfc_status, polling_ms, polling_count = 0, i;
+	u32 reg_addr, sem_base;
+	bool is_ready = false;
+
+	sem_base = storm->sem_fast_mem_addr;
+	polling_ms = VFC_POLLING_DELAY_MS *
+	    s_hw_type_defs[dev_data->hw_type].delay_factor;
+
+	/* Write VFC command */
+	ARR_REG_WR(p_hwfn,
+		   p_ptt,
+		   sem_base + SEM_FAST_REG_VFC_DATA_WR,
+		   cmd_data, cmd_size);
+
+	/* Write VFC address */
+	ARR_REG_WR(p_hwfn,
+		   p_ptt,
+		   sem_base + SEM_FAST_REG_VFC_ADDR,
+		   addr_data, addr_size);
+
+	/* Read response */
+	for (i = 0; i < resp_size; i++) {
+		/* Poll until ready */
+		do {
+			reg_addr = sem_base + SEM_FAST_REG_VFC_STATUS;
+			qed_grc_dump_addr_range(p_hwfn,
+						p_ptt,
+						&vfc_status,
+						true,
+						BYTES_TO_DWORDS(reg_addr),
+						1,
+						false, SPLIT_TYPE_NONE, 0);
+			is_ready = vfc_status &
+				   OSAL_BIT(VFC_STATUS_RESP_READY_BIT);
+
+			if (!is_ready) {
+				if (polling_count++ == VFC_POLLING_COUNT)
+					return 0;
+
+				OSAL_MSLEEP(polling_ms);
+			}
+		} while (!is_ready);
+
+		reg_addr = sem_base + SEM_FAST_REG_VFC_DATA_RD;
+		qed_grc_dump_addr_range(p_hwfn,
+					p_ptt,
+					dump_buf + i,
+					true,
+					BYTES_TO_DWORDS(reg_addr),
+					1, false, SPLIT_TYPE_NONE, 0);
+	}
+
+	return resp_size;
+}
+
+/* Dump VFC CAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_vfc_cam(struct ecore_hwfn *p_hwfn,
+				struct ecore_ptt *p_ptt,
+				u32 *dump_buf, bool dump, u8 storm_id)
+{
+	u32 total_size = VFC_CAM_NUM_ROWS * VFC_CAM_RESP_DWORDS;
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	u32 cam_addr[VFC_CAM_ADDR_DWORDS] = { 0 };
+	u32 cam_cmd[VFC_CAM_CMD_DWORDS] = { 0 };
+	u32 row, offset = 0;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       "vfc_cam",
+				       0,
+				       total_size,
+				       256,
+				       false, "vfc_cam", storm->letter);
+
+	if (!dump)
+		return offset + total_size;
+
+	/* Prepare CAM address */
+	SET_VAR_FIELD(cam_addr, VFC_CAM_ADDR, OP, VFC_OPCODE_CAM_RD);
+
+	/* Read VFC CAM data */
+	for (row = 0; row < VFC_CAM_NUM_ROWS; row++) {
+		SET_VAR_FIELD(cam_cmd, VFC_CAM_CMD, ROW, row);
+		offset += qed_grc_dump_read_from_vfc(p_hwfn,
+						     p_ptt,
+						     storm,
+						     cam_cmd,
+						     VFC_CAM_CMD_DWORDS,
+						     cam_addr,
+						     VFC_CAM_ADDR_DWORDS,
+						     VFC_CAM_RESP_DWORDS,
+						     dump_buf + offset);
+	}
+
+	return offset;
+}
+
+/* Dump VFC RAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_vfc_ram(struct ecore_hwfn *p_hwfn,
+				struct ecore_ptt *p_ptt,
+				u32 *dump_buf,
+				bool dump,
+				u8 storm_id, struct vfc_ram_defs *ram_defs)
+{
+	u32 total_size = ram_defs->num_rows * VFC_RAM_RESP_DWORDS;
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	u32 ram_addr[VFC_RAM_ADDR_DWORDS] = { 0 };
+	u32 ram_cmd[VFC_RAM_CMD_DWORDS] = { 0 };
+	u32 row, offset = 0;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       ram_defs->mem_name,
+				       0,
+				       total_size,
+				       256,
+				       false,
+				       ram_defs->type_name,
+				       storm->letter);
+
+	if (!dump)
+		return offset + total_size;
+
+	/* Prepare RAM address */
+	SET_VAR_FIELD(ram_addr, VFC_RAM_ADDR, OP, VFC_OPCODE_RAM_RD);
+
+	/* Read VFC RAM data */
+	for (row = ram_defs->base_row;
+	     row < ram_defs->base_row + ram_defs->num_rows; row++) {
+		SET_VAR_FIELD(ram_addr, VFC_RAM_ADDR, ROW, row);
+		offset += qed_grc_dump_read_from_vfc(p_hwfn,
+						     p_ptt,
+						     storm,
+						     ram_cmd,
+						     VFC_RAM_CMD_DWORDS,
+						     ram_addr,
+						     VFC_RAM_ADDR_DWORDS,
+						     VFC_RAM_RESP_DWORDS,
+						     dump_buf + offset);
+	}
+
+	return offset;
+}
+
+/* Dumps GRC VFC data. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_vfc(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	u8 storm_id, i;
+	u32 offset = 0;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		if (!qed_grc_is_storm_included(p_hwfn,
+					       (enum dbg_storms)storm_id) ||
+		    !s_storm_defs[storm_id].has_vfc)
+			continue;
+
+		/* Read CAM */
+		offset += qed_grc_dump_vfc_cam(p_hwfn,
+					       p_ptt,
+					       dump_buf + offset,
+					       dump, storm_id);
+
+		/* Read RAM */
+		for (i = 0; i < NUM_VFC_RAM_TYPES; i++)
+			offset += qed_grc_dump_vfc_ram(p_hwfn,
+						       p_ptt,
+						       dump_buf + offset,
+						       dump,
+						       storm_id,
+						       &s_vfc_ram_defs[i]);
+	}
+
+	return offset;
+}
+
+/* Dumps GRC RSS data. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_rss(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 offset = 0;
+	u8 rss_mem_id;
+
+	for (rss_mem_id = 0; rss_mem_id < NUM_RSS_MEM_TYPES; rss_mem_id++) {
+		u32 rss_addr, num_entries, total_dwords;
+		struct rss_mem_defs *rss_defs;
+		u32 addr, num_dwords_to_read;
+		bool packed;
+
+		rss_defs = &s_rss_mem_defs[rss_mem_id];
+		rss_addr = rss_defs->addr;
+		num_entries = rss_defs->num_entries[dev_data->chip_id];
+		total_dwords = (num_entries * rss_defs->entry_width) / 32;
+		packed = (rss_defs->entry_width == 16);
+
+		offset += qed_grc_dump_mem_hdr(p_hwfn,
+					       dump_buf + offset,
+					       dump,
+					       rss_defs->mem_name,
+					       0,
+					       total_dwords,
+					       rss_defs->entry_width,
+					       packed,
+					       rss_defs->type_name, 0);
+
+		/* Dump RSS data */
+		if (!dump) {
+			offset += total_dwords;
+			continue;
+		}
+
+		addr = BYTES_TO_DWORDS(RSS_REG_RSS_RAM_DATA);
+		while (total_dwords) {
+			num_dwords_to_read = OSAL_MIN_T(u32,
+						      RSS_REG_RSS_RAM_DATA_SIZE,
+						      total_dwords);
+			ecore_wr(p_hwfn, p_ptt, RSS_REG_RSS_RAM_ADDR, rss_addr);
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  addr,
+							  num_dwords_to_read,
+							  false,
+							  SPLIT_TYPE_NONE, 0);
+			total_dwords -= num_dwords_to_read;
+			rss_addr++;
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC Big RAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_big_ram(struct ecore_hwfn *p_hwfn,
+				struct ecore_ptt *p_ptt,
+				u32 *dump_buf, bool dump, u8 big_ram_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_size, ram_size, offset = 0, reg_val, i;
+	char mem_name[12] = "???_BIG_RAM";
+	char type_name[8] = "???_RAM";
+	struct big_ram_defs *big_ram;
+
+	big_ram = &s_big_ram_defs[big_ram_id];
+	ram_size = big_ram->ram_size[dev_data->chip_id];
+
+	reg_val = ecore_rd(p_hwfn, p_ptt, big_ram->is_256b_reg_addr);
+	block_size = reg_val &
+		     OSAL_BIT(big_ram->is_256b_bit_offset[dev_data->chip_id]) ?
+								     256 : 128;
+
+	strncpy(type_name, big_ram->instance_name, BIG_RAM_NAME_LEN);
+	strncpy(mem_name, big_ram->instance_name, BIG_RAM_NAME_LEN);
+
+	/* Dump memory header */
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       mem_name,
+				       0,
+				       ram_size,
+				       block_size * 8,
+				       false, type_name, 0);
+
+	/* Read and dump Big RAM data */
+	if (!dump)
+		return offset + ram_size;
+
+	/* Dump Big RAM */
+	for (i = 0; i < DIV_ROUND_UP(ram_size, BRB_REG_BIG_RAM_DATA_SIZE);
+	     i++) {
+		u32 addr, len;
+
+		ecore_wr(p_hwfn, p_ptt, big_ram->addr_reg_addr, i);
+		addr = BYTES_TO_DWORDS(big_ram->data_reg_addr);
+		len = BRB_REG_BIG_RAM_DATA_SIZE;
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  dump,
+						  addr,
+						  len,
+						  false, SPLIT_TYPE_NONE, 0);
+	}
+
+	return offset;
+}
+
+/* Dumps MCP scratchpad. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_mcp(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	bool block_enable[MAX_BLOCK_ID] = { 0 };
+	u32 offset = 0, addr;
+	bool halted = false;
+
+	/* Halt MCP */
+	if (dump && !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP)) {
+		halted = !ecore_mcp_halt(p_hwfn, p_ptt);
+		if (!halted)
+			DP_NOTICE(p_hwfn, false, "MCP halt failed!\n");
+	}
+
+	/* Dump MCP scratchpad */
+	offset += qed_grc_dump_mem(p_hwfn,
+				   p_ptt,
+				   dump_buf + offset,
+				   dump,
+				   NULL,
+				   BYTES_TO_DWORDS(MCP_REG_SCRATCH),
+				   MCP_REG_SCRATCH_SIZE,
+				   false, 0, false, "MCP", 0);
+
+	/* Dump MCP cpu_reg_file */
+	offset += qed_grc_dump_mem(p_hwfn,
+				   p_ptt,
+				   dump_buf + offset,
+				   dump,
+				   NULL,
+				   BYTES_TO_DWORDS(MCP_REG_CPU_REG_FILE),
+				   MCP_REG_CPU_REG_FILE_SIZE,
+				   false, 0, false, "MCP", 0);
+
+	/* Dump MCP registers */
+	block_enable[BLOCK_MCP] = true;
+	offset += qed_grc_dump_registers(p_hwfn,
+					 p_ptt,
+					 dump_buf + offset,
+					 dump, block_enable, "MCP");
+
+	/* Dump required non-MCP registers */
+	offset += qed_grc_dump_regs_hdr(dump_buf + offset,
+					dump, 1, SPLIT_TYPE_NONE, 0,
+					"MCP");
+	addr = BYTES_TO_DWORDS(MISC_REG_SHARED_MEM_ADDR);
+	offset += qed_grc_dump_reg_entry(p_hwfn,
+					 p_ptt,
+					 dump_buf + offset,
+					 dump,
+					 addr,
+					 1,
+					 false, SPLIT_TYPE_NONE, 0);
+
+	/* Release MCP */
+	if (halted && ecore_mcp_resume(p_hwfn, p_ptt))
+		DP_NOTICE(p_hwfn, false, "Failed to resume MCP after halt!\n");
+
+	return offset;
+}
+
+/* Dumps the tbus indirect memory for all PHYs.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_grc_dump_phy(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	u32 offset = 0, tbus_lo_offset, tbus_hi_offset;
+	char mem_name[32];
+	u8 phy_id;
+
+	for (phy_id = 0; phy_id < OSAL_ARRAY_SIZE(s_phy_defs); phy_id++) {
+		u32 addr_lo_addr, addr_hi_addr, data_lo_addr, data_hi_addr;
+		struct phy_defs *phy_defs;
+		u8 *bytes_buf;
+
+		phy_defs = &s_phy_defs[phy_id];
+		addr_lo_addr = phy_defs->base_addr +
+			       phy_defs->tbus_addr_lo_addr;
+		addr_hi_addr = phy_defs->base_addr +
+			       phy_defs->tbus_addr_hi_addr;
+		data_lo_addr = phy_defs->base_addr +
+			       phy_defs->tbus_data_lo_addr;
+		data_hi_addr = phy_defs->base_addr +
+			       phy_defs->tbus_data_hi_addr;
+
+		if (snprintf(mem_name, sizeof(mem_name), "tbus_%s",
+			     phy_defs->phy_name) < 0)
+			DP_NOTICE(p_hwfn, false,
+				  "Unexpected debug error: invalid PHY memory name\n");
+
+		offset += qed_grc_dump_mem_hdr(p_hwfn,
+					       dump_buf + offset,
+					       dump,
+					       mem_name,
+					       0,
+					       PHY_DUMP_SIZE_DWORDS,
+					       16, true, mem_name, 0);
+
+		if (!dump) {
+			offset += PHY_DUMP_SIZE_DWORDS;
+			continue;
+		}
+
+		bytes_buf = (u8 *)(dump_buf + offset);
+		for (tbus_hi_offset = 0;
+		     tbus_hi_offset < (NUM_PHY_TBUS_ADDRESSES >> 8);
+		     tbus_hi_offset++) {
+			ecore_wr(p_hwfn, p_ptt, addr_hi_addr, tbus_hi_offset);
+			for (tbus_lo_offset = 0; tbus_lo_offset < 256;
+			     tbus_lo_offset++) {
+				ecore_wr(p_hwfn,
+				       p_ptt, addr_lo_addr, tbus_lo_offset);
+				*(bytes_buf++) = (u8)ecore_rd(p_hwfn,
+							    p_ptt,
+							    data_lo_addr);
+				*(bytes_buf++) = (u8)ecore_rd(p_hwfn,
+							    p_ptt,
+							    data_hi_addr);
+			}
+		}
+
+		offset += PHY_DUMP_SIZE_DWORDS;
+	}
+
+	return offset;
+}
+
+static enum dbg_status qed_find_nvram_image(struct ecore_hwfn *p_hwfn,
+					    struct ecore_ptt *p_ptt,
+					    u32 image_type,
+					    u32 *nvram_offset_bytes,
+					    u32 *nvram_size_bytes);
+
+static enum dbg_status qed_nvram_read(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 nvram_offset_bytes,
+				      u32 nvram_size_bytes, u32 *ret_buf);
+
+/* Dumps the MCP HW dump from NVRAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_mcp_hw_dump(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    u32 *dump_buf, bool dump)
+{
+	u32 hw_dump_offset_bytes = 0, hw_dump_size_bytes = 0;
+	u32 hw_dump_size_dwords = 0, offset = 0;
+	enum dbg_status status;
+
+	/* Read HW dump image from NVRAM */
+	status = qed_find_nvram_image(p_hwfn,
+				      p_ptt,
+				      NVM_TYPE_HW_DUMP_OUT,
+				      &hw_dump_offset_bytes,
+				      &hw_dump_size_bytes);
+	if (status != DBG_STATUS_OK)
+		return 0;
+
+	hw_dump_size_dwords = BYTES_TO_DWORDS(hw_dump_size_bytes);
+
+	/* Dump HW dump image section */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "mcp_hw_dump", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", hw_dump_size_dwords);
+
+	/* Read MCP HW dump image into dump buffer */
+	if (dump && hw_dump_size_dwords) {
+		status = qed_nvram_read(p_hwfn,
+					p_ptt,
+					hw_dump_offset_bytes,
+					hw_dump_size_bytes, dump_buf + offset);
+		if (status != DBG_STATUS_OK) {
+			DP_NOTICE(p_hwfn, false,
+				  "Failed to read MCP HW Dump image from NVRAM\n");
+			return 0;
+		}
+	}
+	offset += hw_dump_size_dwords;
+
+	return offset;
+}
+
+/* Dumps Static Debug data. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_static_debug(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_id, line_id, offset = 0, addr, len;
+
+	/* Don't dump static debug if a debug bus recording is in progress */
+	if (dump && ecore_rd(p_hwfn, p_ptt, DBG_REG_DBG_BLOCK_ON))
+		return 0;
+
+	if (dump) {
+		/* Disable debug bus in all blocks */
+		qed_bus_disable_blocks(p_hwfn, p_ptt);
+
+		qed_bus_reset_dbg_block(p_hwfn, p_ptt);
+		ecore_wr(p_hwfn,
+		       p_ptt, DBG_REG_FRAMING_MODE, DBG_BUS_FRAME_MODE_8HW);
+		ecore_wr(p_hwfn,
+		       p_ptt, DBG_REG_DEBUG_TARGET, DBG_BUS_TARGET_ID_INT_BUF);
+		ecore_wr(p_hwfn, p_ptt, DBG_REG_FULL_MODE, 1);
+		qed_bus_enable_dbg_block(p_hwfn, p_ptt, true);
+	}
+
+	/* Dump all static debug lines for each relevant block */
+	for (block_id = 0; block_id < MAX_BLOCK_ID; block_id++) {
+		const struct dbg_block_chip *block_per_chip;
+		const struct dbg_block *block;
+		bool is_removed, has_dbg_bus;
+		u16 modes_buf_offset;
+		u32 block_dwords;
+
+		block_per_chip =
+		    qed_get_dbg_block_per_chip(p_hwfn, (enum block_id)block_id);
+		is_removed = GET_FIELD(block_per_chip->flags,
+				       DBG_BLOCK_CHIP_IS_REMOVED);
+		has_dbg_bus = GET_FIELD(block_per_chip->flags,
+					DBG_BLOCK_CHIP_HAS_DBG_BUS);
+
+		/* read+clear for NWS parity is not working, skip NWS block */
+		if (block_id == BLOCK_NWS)
+			continue;
+
+		if (!is_removed && has_dbg_bus &&
+		    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+			      DBG_MODE_HDR_EVAL_MODE) > 0) {
+			modes_buf_offset =
+			    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+				      DBG_MODE_HDR_MODES_BUF_OFFSET);
+			if (!qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				has_dbg_bus = false;
+		}
+
+		if (is_removed || !has_dbg_bus)
+			continue;
+
+		block_dwords = NUM_DBG_LINES(block_per_chip) *
+			       STATIC_DEBUG_LINE_DWORDS;
+
+		/* Dump static section params */
+		block = get_dbg_block(p_hwfn, (enum block_id)block_id);
+		offset += qed_grc_dump_mem_hdr(p_hwfn,
+					       dump_buf + offset,
+					       dump,
+					       (const char *)block->name,
+					       0,
+					       block_dwords,
+					       32, false, "STATIC", 0);
+
+		if (!dump) {
+			offset += block_dwords;
+			continue;
+		}
+
+		/* If all lines are invalid - dump zeros */
+		if (dev_data->block_in_reset[block_id]) {
+			memset(dump_buf + offset, 0,
+			       DWORDS_TO_BYTES(block_dwords));
+			offset += block_dwords;
+			continue;
+		}
+
+		/* Enable block's client */
+		qed_bus_enable_clients(p_hwfn,
+				       p_ptt,
+				       OSAL_BIT(block_per_chip->dbg_client_id));
+
+		addr = BYTES_TO_DWORDS(DBG_REG_CALENDAR_OUT_DATA);
+		len = STATIC_DEBUG_LINE_DWORDS;
+		for (line_id = 0; line_id < (u32)NUM_DBG_LINES(block_per_chip);
+		     line_id++) {
+			/* Configure debug line ID */
+			qed_bus_config_dbg_line(p_hwfn,
+						p_ptt,
+						(enum block_id)block_id,
+						(u8)line_id, 0xf, 0, 0, 0);
+
+			/* Read debug line info */
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  addr,
+							  len,
+							  true, SPLIT_TYPE_NONE,
+							  0);
+		}
+
+		/* Disable block's client and debug output */
+		qed_bus_enable_clients(p_hwfn, p_ptt, 0);
+		qed_bus_config_dbg_line(p_hwfn, p_ptt,
+					(enum block_id)block_id, 0, 0, 0, 0, 0);
+	}
+
+	if (dump) {
+		qed_bus_enable_dbg_block(p_hwfn, p_ptt, false);
+		qed_bus_enable_clients(p_hwfn, p_ptt, 0);
+	}
+
+	return offset;
+}
+
+/* Performs GRC Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static enum dbg_status qed_grc_dump(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    u32 *dump_buf,
+				    bool dump, u32 *num_dumped_dwords)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 dwords_read, offset = 0;
+	bool parities_masked = false;
+	u8 i;
+
+	*num_dumped_dwords = 0;
+	dev_data->num_regs_read = 0;
+
+	/* Update reset state */
+	if (dump)
+		qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 4);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "grc-dump");
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "num-lcids",
+				     NUM_OF_LCIDS);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "num-ltids",
+				     NUM_OF_LTIDS);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "num-ports", dev_data->num_ports);
+
+	/* Dump reset registers (dumped before taking blocks out of reset ) */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS))
+		offset += qed_grc_dump_reset_regs(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset, dump);
+
+	/* Take all blocks out of reset (using reset registers) */
+	if (dump) {
+		qed_grc_unreset_blocks(p_hwfn, p_ptt, false);
+		qed_update_blocks_reset_state(p_hwfn, p_ptt);
+	}
+
+	/* Disable all parities using MFW command */
+	if (dump &&
+	    !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP)) {
+		parities_masked = !ecore_mcp_mask_parities(p_hwfn, p_ptt, 1);
+		if (!parities_masked) {
+			DP_NOTICE(p_hwfn, false,
+				  "Failed to mask parities using MFW\n");
+			if (qed_grc_get_param
+			    (p_hwfn, DBG_GRC_PARAM_PARITY_SAFE))
+				return DBG_STATUS_MCP_COULD_NOT_MASK_PRTY;
+		}
+	}
+
+	/* Dump modified registers (dumped before modifying them) */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS))
+		offset += qed_grc_dump_modified_regs(p_hwfn,
+						     p_ptt,
+						     dump_buf + offset, dump);
+
+	/* Stall storms */
+	if (dump &&
+	    (qed_grc_is_included(p_hwfn,
+				 DBG_GRC_PARAM_DUMP_IOR) ||
+	     qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_VFC)))
+		qed_grc_stall_storms(p_hwfn, p_ptt, true);
+
+	/* Dump all regs  */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS)) {
+		bool block_enable[MAX_BLOCK_ID];
+
+		/* Dump all blocks except MCP */
+		for (i = 0; i < MAX_BLOCK_ID; i++)
+			block_enable[i] = true;
+		block_enable[BLOCK_MCP] = false;
+		offset += qed_grc_dump_registers(p_hwfn,
+						 p_ptt,
+						 dump_buf +
+						 offset,
+						 dump,
+						 block_enable, NULL);
+
+		/* Dump special registers */
+		offset += qed_grc_dump_special_regs(p_hwfn,
+						    p_ptt,
+						    dump_buf + offset, dump);
+	}
+
+	/* Dump memories */
+	offset += qed_grc_dump_memories(p_hwfn, p_ptt, dump_buf + offset, dump);
+
+	/* Dump MCP */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MCP))
+		offset += qed_grc_dump_mcp(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump context */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM_CTX))
+		offset += qed_grc_dump_ctx(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump RSS memories */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_RSS))
+		offset += qed_grc_dump_rss(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump Big RAM */
+	for (i = 0; i < NUM_BIG_RAM_TYPES; i++)
+		if (qed_grc_is_included(p_hwfn, s_big_ram_defs[i].grc_param))
+			offset += qed_grc_dump_big_ram(p_hwfn,
+						       p_ptt,
+						       dump_buf + offset,
+						       dump, i);
+
+	/* Dump VFC */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_VFC)) {
+		dwords_read = qed_grc_dump_vfc(p_hwfn,
+					       p_ptt, dump_buf + offset, dump);
+		offset += dwords_read;
+		if (!dwords_read)
+			return DBG_STATUS_VFC_READ_ERROR;
+	}
+
+	/* Dump PHY tbus */
+	if (qed_grc_is_included(p_hwfn,
+				DBG_GRC_PARAM_DUMP_PHY) && dev_data->chip_id ==
+	    CHIP_K2 && dev_data->hw_type == HW_TYPE_ASIC)
+		offset += qed_grc_dump_phy(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump MCP HW Dump */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MCP_HW_DUMP) &&
+	    !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP) && 1)
+		offset += qed_grc_dump_mcp_hw_dump(p_hwfn,
+						   p_ptt,
+						   dump_buf + offset, dump);
+
+	/* Dump static debug data (only if not during debug bus recording) */
+	if (qed_grc_is_included(p_hwfn,
+				DBG_GRC_PARAM_DUMP_STATIC) &&
+	    (!dump || dev_data->bus.state == DBG_BUS_STATE_IDLE))
+		offset += qed_grc_dump_static_debug(p_hwfn,
+						    p_ptt,
+						    dump_buf + offset, dump);
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	if (dump) {
+		/* Unstall storms */
+		if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_UNSTALL))
+			qed_grc_stall_storms(p_hwfn, p_ptt, false);
+
+		/* Clear parity status */
+		qed_grc_clear_all_prty(p_hwfn, p_ptt);
+
+		/* Enable all parities using MFW command */
+		if (parities_masked)
+			ecore_mcp_mask_parities(p_hwfn, p_ptt, 0);
+	}
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Writes the specified failing Idle Check rule to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_idle_chk_dump_failure(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     u32 *
+				     dump_buf,
+				     bool dump,
+				     u16 rule_id,
+				     const struct dbg_idle_chk_rule *rule,
+				     u16 fail_entry_id, u32 *cond_reg_values)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	const struct dbg_idle_chk_cond_reg *cond_regs;
+	const struct dbg_idle_chk_info_reg *info_regs;
+	u32 i, next_reg_offset = 0, offset = 0;
+	struct dbg_idle_chk_result_hdr *hdr;
+	const union dbg_idle_chk_reg *regs;
+	u8 reg_id;
+
+	hdr = (struct dbg_idle_chk_result_hdr *)dump_buf;
+	regs = (const union dbg_idle_chk_reg *)
+		p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr +
+		rule->reg_offset;
+	cond_regs = &regs[0].cond_reg;
+	info_regs = &regs[rule->num_cond_regs].info_reg;
+
+	/* Dump rule data */
+	if (dump) {
+		memset(hdr, 0, sizeof(*hdr));
+		hdr->rule_id = rule_id;
+		hdr->mem_entry_id = fail_entry_id;
+		hdr->severity = rule->severity;
+		hdr->num_dumped_cond_regs = rule->num_cond_regs;
+	}
+
+	offset += IDLE_CHK_RESULT_HDR_DWORDS;
+
+	/* Dump condition register values */
+	for (reg_id = 0; reg_id < rule->num_cond_regs; reg_id++) {
+		const struct dbg_idle_chk_cond_reg *reg = &cond_regs[reg_id];
+		struct dbg_idle_chk_result_reg_hdr *reg_hdr;
+
+		reg_hdr =
+		    (struct dbg_idle_chk_result_reg_hdr *)(dump_buf + offset);
+
+		/* Write register header */
+		if (!dump) {
+			offset += IDLE_CHK_RESULT_REG_HDR_DWORDS +
+			    reg->entry_size;
+			continue;
+		}
+
+		offset += IDLE_CHK_RESULT_REG_HDR_DWORDS;
+		memset(reg_hdr, 0, sizeof(*reg_hdr));
+		reg_hdr->start_entry = reg->start_entry;
+		reg_hdr->size = reg->entry_size;
+		SET_FIELD(reg_hdr->data,
+			  DBG_IDLE_CHK_RESULT_REG_HDR_IS_MEM,
+			  reg->num_entries > 1 || reg->start_entry > 0 ? 1 : 0);
+		SET_FIELD(reg_hdr->data,
+			  DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID, reg_id);
+
+		/* Write register values */
+		for (i = 0; i < reg_hdr->size; i++, next_reg_offset++, offset++)
+			dump_buf[offset] = cond_reg_values[next_reg_offset];
+	}
+
+	/* Dump info register values */
+	for (reg_id = 0; reg_id < rule->num_info_regs; reg_id++) {
+		const struct dbg_idle_chk_info_reg *reg = &info_regs[reg_id];
+		u32 block_id;
+
+		/* Check if register's block is in reset */
+		if (!dump) {
+			offset += IDLE_CHK_RESULT_REG_HDR_DWORDS + reg->size;
+			continue;
+		}
+
+		block_id = GET_FIELD(reg->data, DBG_IDLE_CHK_INFO_REG_BLOCK_ID);
+		if (block_id >= MAX_BLOCK_ID) {
+			DP_NOTICE(p_hwfn, false, "Invalid block_id\n");
+			return 0;
+		}
+
+		if (!dev_data->block_in_reset[block_id]) {
+			struct dbg_idle_chk_result_reg_hdr *reg_hdr;
+			bool wide_bus, eval_mode, mode_match = true;
+			u16 modes_buf_offset;
+			u32 addr;
+
+			reg_hdr = (struct dbg_idle_chk_result_reg_hdr *)
+				  (dump_buf + offset);
+
+			/* Check mode */
+			eval_mode = GET_FIELD(reg->mode.data,
+					      DBG_MODE_HDR_EVAL_MODE) > 0;
+			if (eval_mode) {
+				modes_buf_offset =
+				    GET_FIELD(reg->mode.data,
+					      DBG_MODE_HDR_MODES_BUF_OFFSET);
+				mode_match =
+					qed_is_mode_match(p_hwfn,
+							  &modes_buf_offset);
+			}
+
+			if (!mode_match)
+				continue;
+
+			addr = GET_FIELD(reg->data,
+					 DBG_IDLE_CHK_INFO_REG_ADDRESS);
+			wide_bus = GET_FIELD(reg->data,
+					     DBG_IDLE_CHK_INFO_REG_WIDE_BUS);
+
+			/* Write register header */
+			offset += IDLE_CHK_RESULT_REG_HDR_DWORDS;
+			hdr->num_dumped_info_regs++;
+			memset(reg_hdr, 0, sizeof(*reg_hdr));
+			reg_hdr->size = reg->size;
+			SET_FIELD(reg_hdr->data,
+				  DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID,
+				  rule->num_cond_regs + reg_id);
+
+			/* Write register values */
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  addr,
+							  reg->size, wide_bus,
+							  SPLIT_TYPE_NONE, 0);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps idle check rule entries. Returns the dumped size in dwords. */
+static u32
+qed_idle_chk_dump_rule_entries(struct ecore_hwfn *p_hwfn,
+			       struct ecore_ptt *p_ptt,
+			       u32 *dump_buf, bool dump,
+			       const struct dbg_idle_chk_rule *input_rules,
+			       u32 num_input_rules, u32 *num_failing_rules)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 cond_reg_values[IDLE_CHK_MAX_ENTRIES_SIZE];
+	u32 i, offset = 0;
+	u16 entry_id;
+	u8 reg_id;
+
+	*num_failing_rules = 0;
+
+	for (i = 0; i < num_input_rules; i++) {
+		const struct dbg_idle_chk_cond_reg *cond_regs;
+		const struct dbg_idle_chk_rule *rule;
+		const union dbg_idle_chk_reg *regs;
+		u16 num_reg_entries = 1;
+		bool check_rule = true;
+		const u32 *imm_values;
+
+		rule = &input_rules[i];
+		regs = (const union dbg_idle_chk_reg *)
+			p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr +
+			rule->reg_offset;
+		cond_regs = &regs[0].cond_reg;
+		imm_values =
+		    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_IMMS].ptr +
+		    rule->imm_offset;
+
+		/* Check if all condition register blocks are out of reset, and
+		 * find maximal number of entries (all condition registers that
+		 * are memories must have the same size, which is > 1).
+		 */
+		for (reg_id = 0; reg_id < rule->num_cond_regs && check_rule;
+		     reg_id++) {
+			u32 block_id =
+				GET_FIELD(cond_regs[reg_id].data,
+					  DBG_IDLE_CHK_COND_REG_BLOCK_ID);
+
+			if (block_id >= MAX_BLOCK_ID) {
+				DP_NOTICE(p_hwfn, false, "Invalid block_id\n");
+				return 0;
+			}
+
+			check_rule = !dev_data->block_in_reset[block_id];
+			if (cond_regs[reg_id].num_entries > num_reg_entries)
+				num_reg_entries = cond_regs[reg_id].num_entries;
+		}
+
+		if (!check_rule && dump)
+			continue;
+
+		if (!dump) {
+			u32 entry_dump_size =
+				qed_idle_chk_dump_failure(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  false,
+							  rule->rule_id,
+							  rule,
+							  0,
+							  NULL);
+
+			offset += num_reg_entries * entry_dump_size;
+			(*num_failing_rules) += num_reg_entries;
+			continue;
+		}
+
+		/* Go over all register entries (number of entries is the same
+		 * for all condition registers).
+		 */
+		for (entry_id = 0; entry_id < num_reg_entries; entry_id++) {
+			u32 next_reg_offset = 0;
+
+			/* Read current entry of all condition registers */
+			for (reg_id = 0; reg_id < rule->num_cond_regs;
+			     reg_id++) {
+				const struct dbg_idle_chk_cond_reg *reg =
+					&cond_regs[reg_id];
+				u32 padded_entry_size, addr;
+				bool wide_bus;
+
+				/* Find GRC address (if it's a memory, the
+				 * address of the specific entry is calculated).
+				 */
+				addr = GET_FIELD(reg->data,
+						 DBG_IDLE_CHK_COND_REG_ADDRESS);
+				wide_bus =
+				    GET_FIELD(reg->data,
+					      DBG_IDLE_CHK_COND_REG_WIDE_BUS);
+				if (reg->num_entries > 1 ||
+				    reg->start_entry > 0) {
+					padded_entry_size =
+					   reg->entry_size > 1 ?
+					   OSAL_ROUNDUP_POW_OF_TWO(reg->entry_size) :
+					   1;
+					addr += (reg->start_entry + entry_id) *
+						padded_entry_size;
+				}
+
+				/* Read registers */
+				if (next_reg_offset + reg->entry_size >=
+				    IDLE_CHK_MAX_ENTRIES_SIZE) {
+					DP_NOTICE(p_hwfn, false,
+						  "idle check registers entry is too large\n");
+					return 0;
+				}
+
+				next_reg_offset +=
+				    qed_grc_dump_addr_range(p_hwfn, p_ptt,
+							    cond_reg_values +
+							    next_reg_offset,
+							    dump, addr,
+							    reg->entry_size,
+							    wide_bus,
+							    SPLIT_TYPE_NONE, 0);
+			}
+
+			/* Call rule condition function.
+			 * If returns true, it's a failure.
+			 */
+			if ((*cond_arr[rule->cond_id]) (cond_reg_values,
+							imm_values)) {
+				offset += qed_idle_chk_dump_failure(p_hwfn,
+							p_ptt,
+							dump_buf + offset,
+							dump,
+							rule->rule_id,
+							rule,
+							entry_id,
+							cond_reg_values);
+				(*num_failing_rules)++;
+			}
+		}
+	}
+
+	return offset;
+}
+
+/* Performs Idle Check Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+			     struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	struct virt_mem_desc *dbg_buf =
+	    &p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_RULES];
+	u32 num_failing_rules_offset, offset = 0,
+	    input_offset = 0, num_failing_rules = 0;
+
+	/* Dump global params  - 1 must match below amount of params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "idle-chk");
+
+	/* Dump idle check section header with a single parameter */
+	offset += qed_dump_section_hdr(dump_buf + offset, dump, "idle_chk", 1);
+	num_failing_rules_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "num_rules", 0);
+
+	while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
+		const struct dbg_idle_chk_cond_hdr *cond_hdr =
+		    (const struct dbg_idle_chk_cond_hdr *)dbg_buf->ptr +
+		    input_offset++;
+		bool eval_mode, mode_match = true;
+		u32 curr_failing_rules;
+		u16 modes_buf_offset;
+
+		/* Check mode */
+		eval_mode = GET_FIELD(cond_hdr->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		if (eval_mode) {
+			modes_buf_offset =
+				GET_FIELD(cond_hdr->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			mode_match = qed_is_mode_match(p_hwfn,
+						       &modes_buf_offset);
+		}
+
+		if (mode_match) {
+			const struct dbg_idle_chk_rule *rule =
+			    (const struct dbg_idle_chk_rule *)((u32 *)
+							       dbg_buf->ptr
+							       + input_offset);
+			u32 num_input_rules =
+				cond_hdr->data_size / IDLE_CHK_RULE_SIZE_DWORDS;
+			offset +=
+			    qed_idle_chk_dump_rule_entries(p_hwfn,
+							   p_ptt,
+							   dump_buf +
+							   offset,
+							   dump,
+							   rule,
+							   num_input_rules,
+							   &curr_failing_rules);
+			num_failing_rules += curr_failing_rules;
+		}
+
+		input_offset += cond_hdr->data_size;
+	}
+
+	/* Overwrite num_rules parameter */
+	if (dump)
+		qed_dump_num_param(dump_buf + num_failing_rules_offset,
+				   dump, "num_rules", num_failing_rules);
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	return offset;
+}
+
+/* Finds the meta data image in NVRAM */
+static enum dbg_status qed_find_nvram_image(struct ecore_hwfn *p_hwfn,
+					    struct ecore_ptt *p_ptt,
+					    u32 image_type,
+					    u32 *nvram_offset_bytes,
+					    u32 *nvram_size_bytes)
+{
+	u32 ret_mcp_resp, ret_mcp_param, ret_txn_size;
+	struct mcp_file_att file_att;
+	int nvm_result;
+
+	/* Call NVRAM get file command */
+	nvm_result = ecore_mcp_nvm_rd_cmd(p_hwfn,
+					p_ptt,
+					DRV_MSG_CODE_NVM_GET_FILE_ATT,
+					image_type,
+					&ret_mcp_resp,
+					&ret_mcp_param,
+					&ret_txn_size, (u32 *)&file_att);
+
+	/* Check response */
+	if (nvm_result ||
+	    (ret_mcp_resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_NVM_OK)
+		return DBG_STATUS_NVRAM_GET_IMAGE_FAILED;
+
+	/* Update return values */
+	*nvram_offset_bytes = file_att.nvm_start_addr;
+	*nvram_size_bytes = file_att.len;
+
+	DP_VERBOSE(p_hwfn->p_dev,
+		   ECORE_MSG_DEBUG,
+		   "find_nvram_image: found NVRAM image of type %d in NVRAM offset %d bytes with size %d bytes\n",
+		   image_type, *nvram_offset_bytes, *nvram_size_bytes);
+
+	/* Check alignment */
+	if (*nvram_size_bytes & 0x3)
+		return DBG_STATUS_NON_ALIGNED_NVRAM_IMAGE;
+
+	return DBG_STATUS_OK;
+}
+
+/* Reads data from NVRAM */
+static enum dbg_status qed_nvram_read(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 nvram_offset_bytes,
+				      u32 nvram_size_bytes, u32 *ret_buf)
+{
+	u32 ret_mcp_resp, ret_mcp_param, ret_read_size, bytes_to_copy;
+	s32 bytes_left = nvram_size_bytes;
+	u32 read_offset = 0, param = 0;
+
+	DP_NOTICE(p_hwfn->p_dev, false,
+		   "nvram_read: reading image of size %d bytes from NVRAM\n",
+		   nvram_size_bytes);
+
+	do {
+		bytes_to_copy =
+		    (bytes_left >
+		     MCP_DRV_NVM_BUF_LEN) ? MCP_DRV_NVM_BUF_LEN : bytes_left;
+
+		/* Call NVRAM read command */
+		SET_MFW_FIELD(param,
+			      DRV_MB_PARAM_NVM_OFFSET,
+			      nvram_offset_bytes + read_offset);
+		SET_MFW_FIELD(param, DRV_MB_PARAM_NVM_LEN, bytes_to_copy);
+		if (ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt,
+					 DRV_MSG_CODE_NVM_READ_NVRAM, param,
+					 &ret_mcp_resp,
+					 &ret_mcp_param, &ret_read_size,
+					 (u32 *)((u8 *)ret_buf +
+						 read_offset))) {
+			DP_NOTICE(p_hwfn->p_dev, false, "rc = DBG_STATUS_NVRAM_READ_FAILED\n");
+			return DBG_STATUS_NVRAM_READ_FAILED;
+		}
+
+		/* Check response */
+		if ((ret_mcp_resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_NVM_OK) {
+			DP_NOTICE(p_hwfn->p_dev, false, "rc = DBG_STATUS_NVRAM_READ_FAILED\n");
+			return DBG_STATUS_NVRAM_READ_FAILED;
+		}
+
+		/* Update read offset */
+		read_offset += ret_read_size;
+		bytes_left -= ret_read_size;
+	} while (bytes_left > 0);
+
+	return DBG_STATUS_OK;
+}
+
+/* Get info on the MCP Trace data in the scratchpad:
+ * - trace_data_grc_addr (OUT): trace data GRC address in bytes
+ * - trace_data_size (OUT): trace data size in bytes (without the header)
+ */
+static enum dbg_status qed_mcp_trace_get_data_info(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *trace_data_grc_addr,
+						   u32 *trace_data_size)
+{
+	u32 spad_trace_offsize, signature;
+
+	/* Read trace section offsize structure from MCP scratchpad */
+	spad_trace_offsize = ecore_rd(p_hwfn, p_ptt,
+				      MCP_SPAD_TRACE_OFFSIZE_ADDR);
+
+	/* Extract trace section address from offsize (in scratchpad) */
+	*trace_data_grc_addr =
+		MCP_REG_SCRATCH + SECTION_OFFSET(spad_trace_offsize);
+
+	/* Read signature from MCP trace section */
+	signature = ecore_rd(p_hwfn, p_ptt,
+			   *trace_data_grc_addr +
+			   offsetof(struct mcp_trace, signature));
+
+	if (signature != MFW_TRACE_SIGNATURE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Read trace size from MCP trace section */
+	*trace_data_size = ecore_rd(p_hwfn,
+				  p_ptt,
+				  *trace_data_grc_addr +
+				  offsetof(struct mcp_trace, size));
+
+	return DBG_STATUS_OK;
+}
+
+/* Reads MCP trace meta data image from NVRAM
+ * - running_bundle_id (OUT): running bundle ID (invalid when loaded from file)
+ * - trace_meta_offset (OUT): trace meta offset in NVRAM in bytes (invalid when
+ *			      loaded from file).
+ * - trace_meta_size (OUT):   size in bytes of the trace meta data.
+ */
+static enum dbg_status qed_mcp_trace_get_meta_info(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 trace_data_size_bytes,
+						   u32 *running_bundle_id,
+						   u32 *trace_meta_offset,
+						   u32 *trace_meta_size)
+{
+	u32 spad_trace_offsize, nvram_image_type, running_mfw_addr;
+
+	/* Read MCP trace section offsize structure from MCP scratchpad */
+	spad_trace_offsize = ecore_rd(p_hwfn, p_ptt,
+				      MCP_SPAD_TRACE_OFFSIZE_ADDR);
+
+	/* Find running bundle ID */
+	running_mfw_addr =
+		MCP_REG_SCRATCH + SECTION_OFFSET(spad_trace_offsize) +
+		SECTION_SIZE(spad_trace_offsize) + trace_data_size_bytes;
+	*running_bundle_id = ecore_rd(p_hwfn, p_ptt, running_mfw_addr);
+	if (*running_bundle_id > 1)
+		return DBG_STATUS_INVALID_NVRAM_BUNDLE;
+
+	/* Find image in NVRAM */
+	nvram_image_type =
+	    (*running_bundle_id ==
+	     DIR_ID_1) ? NVM_TYPE_MFW_TRACE1 : NVM_TYPE_MFW_TRACE2;
+	return qed_find_nvram_image(p_hwfn,
+				    p_ptt,
+				    nvram_image_type,
+				    trace_meta_offset, trace_meta_size);
+}
+
+/* Reads the MCP Trace meta data from NVRAM into the specified buffer */
+static enum dbg_status qed_mcp_trace_read_meta(struct ecore_hwfn *p_hwfn,
+					       struct ecore_ptt *p_ptt,
+					       u32 nvram_offset_in_bytes,
+					       u32 size_in_bytes, u32 *buf)
+{
+	u8 modules_num, module_len, i, *byte_buf = (u8 *)buf;
+	enum dbg_status status;
+	u32 signature;
+
+	/* Read meta data from NVRAM */
+	status = qed_nvram_read(p_hwfn,
+				p_ptt,
+				nvram_offset_in_bytes, size_in_bytes, buf);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Extract and check first signature */
+	signature = qed_read_unaligned_dword(byte_buf);
+	byte_buf += sizeof(signature);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Extract number of modules */
+	modules_num = *(byte_buf++);
+
+	/* Skip all modules */
+	for (i = 0; i < modules_num; i++) {
+		module_len = *(byte_buf++);
+		byte_buf += module_len;
+	}
+
+	/* Extract and check second signature */
+	signature = qed_read_unaligned_dword(byte_buf);
+	byte_buf += sizeof(signature);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	return DBG_STATUS_OK;
+}
+
+/* Dump MCP Trace */
+static enum dbg_status qed_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+					  struct ecore_ptt *p_ptt,
+					  u32 *dump_buf,
+					  bool dump, u32 *num_dumped_dwords)
+{
+	u32 trace_data_grc_addr, trace_data_size_bytes, trace_data_size_dwords;
+	u32 trace_meta_size_dwords = 0, running_bundle_id, offset = 0;
+	u32 trace_meta_offset_bytes = 0, trace_meta_size_bytes = 0;
+	enum dbg_status status;
+	int halted = 0;
+	bool use_mfw;
+
+	*num_dumped_dwords = 0;
+
+	use_mfw = !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP);
+
+	/* Get trace data info */
+	status = qed_mcp_trace_get_data_info(p_hwfn,
+					     p_ptt,
+					     &trace_data_grc_addr,
+					     &trace_data_size_bytes);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "mcp-trace");
+
+	/* Halt MCP while reading from scratchpad so the read data will be
+	 * consistent. if halt fails, MCP trace is taken anyway, with a small
+	 * risk that it may be corrupt.
+	 */
+	if (dump && use_mfw) {
+		halted = !ecore_mcp_halt(p_hwfn, p_ptt);
+		if (!halted)
+			DP_NOTICE(p_hwfn, false, "MCP halt failed!\n");
+	}
+
+	/* Find trace data size */
+	trace_data_size_dwords =
+	    DIV_ROUND_UP(trace_data_size_bytes + sizeof(struct mcp_trace),
+			 BYTES_IN_DWORD);
+
+	/* Dump trace data section header and param */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "mcp_trace_data", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", trace_data_size_dwords);
+
+	/* Read trace data from scratchpad into dump buffer */
+	offset += qed_grc_dump_addr_range(p_hwfn,
+					  p_ptt,
+					  dump_buf + offset,
+					  dump,
+					  BYTES_TO_DWORDS(trace_data_grc_addr),
+					  trace_data_size_dwords, false,
+					  SPLIT_TYPE_NONE, 0);
+
+	/* Resume MCP (only if halt succeeded) */
+	if (halted && ecore_mcp_resume(p_hwfn, p_ptt))
+		DP_NOTICE(p_hwfn, false, "Failed to resume MCP after halt!\n");
+
+	/* Dump trace meta section header */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "mcp_trace_meta", 1);
+
+	/* If MCP Trace meta size parameter was set, use it.
+	 * Otherwise, read trace meta.
+	 * trace_meta_size_bytes is dword-aligned.
+	 */
+	trace_meta_size_bytes =
+		qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_MCP_TRACE_META_SIZE);
+	if ((!trace_meta_size_bytes || dump) && use_mfw)
+		status = qed_mcp_trace_get_meta_info(p_hwfn,
+						     p_ptt,
+						     trace_data_size_bytes,
+						     &running_bundle_id,
+						     &trace_meta_offset_bytes,
+						     &trace_meta_size_bytes);
+	if (status == DBG_STATUS_OK)
+		trace_meta_size_dwords = BYTES_TO_DWORDS(trace_meta_size_bytes);
+
+	/* Dump trace meta size param */
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", trace_meta_size_dwords);
+
+	/* Read trace meta image into dump buffer */
+	if (dump && trace_meta_size_dwords)
+		status = qed_mcp_trace_read_meta(p_hwfn,
+						 p_ptt,
+						 trace_meta_offset_bytes,
+						 trace_meta_size_bytes,
+						 dump_buf + offset);
+	if (status == DBG_STATUS_OK)
+		offset += trace_meta_size_dwords;
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	/* If no mcp access, indicate that the dump doesn't contain the meta
+	 * data from NVRAM.
+	 */
+	return use_mfw ? status : DBG_STATUS_NVRAM_GET_IMAGE_FAILED;
+}
+
+/* Dump GRC FIFO */
+static enum dbg_status qed_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
+					 struct ecore_ptt *p_ptt,
+					 u32 *dump_buf,
+					 bool dump, u32 *num_dumped_dwords)
+{
+	u32 dwords_read, size_param_offset, offset = 0, addr, len;
+	bool fifo_has_data;
+
+	*num_dumped_dwords = 0;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "reg-fifo");
+
+	/* Dump fifo data section header and param. The size param is 0 for
+	 * now, and is overwritten after reading the FIFO.
+	 */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "reg_fifo_data", 1);
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+
+	if (!dump) {
+		/* FIFO max size is REG_FIFO_DEPTH_DWORDS. There is no way to
+		 * test how much data is available, except for reading it.
+		 */
+		offset += REG_FIFO_DEPTH_DWORDS;
+		goto out;
+	}
+
+	fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+			       GRC_REG_TRACE_FIFO_VALID_DATA) > 0;
+
+	/* Pull available data from fifo. Use DMAE since this is widebus memory
+	 * and must be accessed atomically. Test for dwords_read not passing
+	 * buffer size since more entries could be added to the buffer as we are
+	 * emptying it.
+	 */
+	addr = BYTES_TO_DWORDS(GRC_REG_TRACE_FIFO);
+	len = REG_FIFO_ELEMENT_DWORDS;
+	for (dwords_read = 0;
+	     fifo_has_data && dwords_read < REG_FIFO_DEPTH_DWORDS;
+	     dwords_read += REG_FIFO_ELEMENT_DWORDS) {
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  true,
+						  addr,
+						  len,
+						  true, SPLIT_TYPE_NONE,
+						  0);
+		fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+				       GRC_REG_TRACE_FIFO_VALID_DATA) > 0;
+	}
+
+	qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
+			   dwords_read);
+out:
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Dump IGU FIFO */
+static enum dbg_status qed_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
+					 struct ecore_ptt *p_ptt,
+					 u32 *dump_buf,
+					 bool dump, u32 *num_dumped_dwords)
+{
+	u32 dwords_read, size_param_offset, offset = 0, addr, len;
+	bool fifo_has_data;
+
+	*num_dumped_dwords = 0;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "igu-fifo");
+
+	/* Dump fifo data section header and param. The size param is 0 for
+	 * now, and is overwritten after reading the FIFO.
+	 */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "igu_fifo_data", 1);
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+
+	if (!dump) {
+		/* FIFO max size is IGU_FIFO_DEPTH_DWORDS. There is no way to
+		 * test how much data is available, except for reading it.
+		 */
+		offset += IGU_FIFO_DEPTH_DWORDS;
+		goto out;
+	}
+
+	fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+			       IGU_REG_ERROR_HANDLING_DATA_VALID) > 0;
+
+	/* Pull available data from fifo. Use DMAE since this is widebus memory
+	 * and must be accessed atomically. Test for dwords_read not passing
+	 * buffer size since more entries could be added to the buffer as we are
+	 * emptying it.
+	 */
+	addr = BYTES_TO_DWORDS(IGU_REG_ERROR_HANDLING_MEMORY);
+	len = IGU_FIFO_ELEMENT_DWORDS;
+	for (dwords_read = 0;
+	     fifo_has_data && dwords_read < IGU_FIFO_DEPTH_DWORDS;
+	     dwords_read += IGU_FIFO_ELEMENT_DWORDS) {
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  true,
+						  addr,
+						  len,
+						  true, SPLIT_TYPE_NONE,
+						  0);
+		fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+				       IGU_REG_ERROR_HANDLING_DATA_VALID) > 0;
+	}
+
+	qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
+			   dwords_read);
+out:
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Protection Override dump */
+static enum dbg_status qed_protection_override_dump(struct ecore_hwfn *p_hwfn,
+						    struct ecore_ptt *p_ptt,
+						    u32 *dump_buf,
+						    bool dump,
+						    u32 *num_dumped_dwords)
+{
+	u32 size_param_offset, override_window_dwords, offset = 0, addr;
+
+	*num_dumped_dwords = 0;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "protection-override");
+
+	/* Dump data section header and param. The size param is 0 for now,
+	 * and is overwritten after reading the data.
+	 */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "protection_override_data", 1);
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+
+	if (!dump) {
+		offset += PROTECTION_OVERRIDE_DEPTH_DWORDS;
+		goto out;
+	}
+
+	/* Add override window info to buffer */
+	override_window_dwords =
+		ecore_rd(p_hwfn, p_ptt, GRC_REG_NUMBER_VALID_OVERRIDE_WINDOW) *
+		PROTECTION_OVERRIDE_ELEMENT_DWORDS;
+	if (override_window_dwords) {
+		addr = BYTES_TO_DWORDS(GRC_REG_PROTECTION_OVERRIDE_WINDOW);
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  true,
+						  addr,
+						  override_window_dwords,
+						  true, SPLIT_TYPE_NONE, 0);
+		qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
+				   override_window_dwords);
+	}
+out:
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Performs FW Asserts Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
+			       struct ecore_ptt *p_ptt, u32 *dump_buf,
+			       bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	struct fw_asserts_ram_section *asserts;
+	char storm_letter_str[2] = "?";
+	struct fw_info fw_info;
+	u32 offset = 0;
+	u8 storm_id;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "fw-asserts");
+
+	/* Find Storm dump size */
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		u32 fw_asserts_section_addr, next_list_idx_addr, next_list_idx;
+		struct storm_defs *storm = &s_storm_defs[storm_id];
+		u32 last_list_idx, addr;
+
+		if (dev_data->block_in_reset[storm->sem_block_id])
+			continue;
+
+		/* Read FW info for the current Storm */
+		qed_read_storm_fw_info(p_hwfn, p_ptt, storm_id, &fw_info);
+
+		asserts = &fw_info.fw_asserts_section;
+
+		/* Dump FW Asserts section header and params */
+		storm_letter_str[0] = storm->letter;
+		offset += qed_dump_section_hdr(dump_buf + offset,
+					       dump, "fw_asserts", 2);
+		offset += qed_dump_str_param(dump_buf + offset,
+					     dump, "storm", storm_letter_str);
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump,
+					     "size",
+					     asserts->list_element_dword_size);
+
+		/* Read and dump FW Asserts data */
+		if (!dump) {
+			offset += asserts->list_element_dword_size;
+			continue;
+		}
+
+		fw_asserts_section_addr = storm->sem_fast_mem_addr +
+			SEM_FAST_REG_INT_RAM +
+			RAM_LINES_TO_BYTES(asserts->section_ram_line_offset);
+		next_list_idx_addr = fw_asserts_section_addr +
+			DWORDS_TO_BYTES(asserts->list_next_index_dword_offset);
+		next_list_idx = ecore_rd(p_hwfn, p_ptt, next_list_idx_addr);
+		last_list_idx = (next_list_idx > 0 ?
+				 next_list_idx :
+				 asserts->list_num_elements) - 1;
+		addr = BYTES_TO_DWORDS(fw_asserts_section_addr) +
+		       asserts->list_dword_offset +
+		       last_list_idx * asserts->list_element_dword_size;
+		offset +=
+		    qed_grc_dump_addr_range(p_hwfn, p_ptt,
+					    dump_buf + offset,
+					    dump, addr,
+					    asserts->list_element_dword_size,
+						  false, SPLIT_TYPE_NONE, 0);
+	}
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	return offset;
+}
+
+/* Dumps the specified ILT pages to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_ilt_dump_pages_range(u32 *dump_buf,
+				    bool dump,
+				    u32 start_page_id,
+				    u32 num_pages,
+				    struct phys_mem_desc *ilt_pages,
+				    bool dump_page_ids)
+{
+	u32 page_id, end_page_id, offset = 0;
+
+	if (num_pages == 0)
+		return offset;
+
+	end_page_id = start_page_id + num_pages - 1;
+
+	for (page_id = start_page_id; page_id <= end_page_id; page_id++) {
+		struct phys_mem_desc *mem_desc = &ilt_pages[page_id];
+
+		/**
+		 *
+		 * if (page_id >= ->p_cxt_mngr->ilt_shadow_size)
+		 *     break;
+		 */
+
+		if (!ilt_pages[page_id].virt_addr)
+			continue;
+
+		if (dump_page_ids) {
+			/* Copy page ID to dump buffer */
+			if (dump)
+				*(dump_buf + offset) = page_id;
+			offset++;
+		} else {
+			/* Copy page memory to dump buffer */
+			if (dump)
+				memcpy(dump_buf + offset,
+				       mem_desc->virt_addr, mem_desc->size);
+			offset += BYTES_TO_DWORDS(mem_desc->size);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps a section containing the dumped ILT pages.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_ilt_dump_pages_section(struct ecore_hwfn *p_hwfn,
+				      u32 *dump_buf,
+				      bool dump,
+				      u32 valid_conn_pf_pages,
+				      u32 valid_conn_vf_pages,
+				      struct phys_mem_desc *ilt_pages,
+				      bool dump_page_ids)
+{
+	struct ecore_ilt_client_cfg *clients = p_hwfn->p_cxt_mngr->clients;
+	u32 pf_start_line, start_page_id, offset = 0;
+	u32 cdut_pf_init_pages, cdut_vf_init_pages;
+	u32 cdut_pf_work_pages, cdut_vf_work_pages;
+	u32 base_data_offset, size_param_offset;
+	u32 cdut_pf_pages, cdut_vf_pages;
+	const char *section_name;
+	u8 i;
+
+	section_name = dump_page_ids ? "ilt_page_ids" : "ilt_page_mem";
+	cdut_pf_init_pages = ecore_get_cdut_num_pf_init_pages(p_hwfn);
+	cdut_vf_init_pages = ecore_get_cdut_num_vf_init_pages(p_hwfn);
+	cdut_pf_work_pages = ecore_get_cdut_num_pf_work_pages(p_hwfn);
+	cdut_vf_work_pages = ecore_get_cdut_num_vf_work_pages(p_hwfn);
+	cdut_pf_pages = cdut_pf_init_pages + cdut_pf_work_pages;
+	cdut_vf_pages = cdut_vf_init_pages + cdut_vf_work_pages;
+	pf_start_line = p_hwfn->p_cxt_mngr->pf_start_line;
+
+	offset +=
+	    qed_dump_section_hdr(dump_buf + offset, dump, section_name, 1);
+
+	/* Dump size parameter (0 for now, overwritten with real size later) */
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+	base_data_offset = offset;
+
+	/* CDUC pages are ordered as follows:
+	 * - PF pages - valid section (included in PF connection type mapping)
+	 * - PF pages - invalid section (not dumped)
+	 * - For each VF in the PF:
+	 *   - VF pages - valid section (included in VF connection type mapping)
+	 *   - VF pages - invalid section (not dumped)
+	 */
+	if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_DUMP_ILT_CDUC)) {
+		/* Dump connection PF pages */
+		start_page_id = clients[ILT_CLI_CDUC].first.val - pf_start_line;
+		offset += qed_ilt_dump_pages_range(dump_buf + offset,
+						   dump,
+						   start_page_id,
+						   valid_conn_pf_pages,
+						   ilt_pages, dump_page_ids);
+
+		/* Dump connection VF pages */
+		start_page_id += clients[ILT_CLI_CDUC].pf_total_lines;
+		for (i = 0; i < p_hwfn->p_cxt_mngr->vf_count;
+		     i++, start_page_id += clients[ILT_CLI_CDUC].vf_total_lines)
+			offset += qed_ilt_dump_pages_range(dump_buf + offset,
+							   dump,
+							   start_page_id,
+							   valid_conn_vf_pages,
+							   ilt_pages,
+							   dump_page_ids);
+	}
+
+	/* CDUT pages are ordered as follows:
+	 * - PF init pages (not dumped)
+	 * - PF work pages
+	 * - For each VF in the PF:
+	 *   - VF init pages (not dumped)
+	 *   - VF work pages
+	 */
+	if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_DUMP_ILT_CDUT)) {
+		/* Dump task PF pages */
+		start_page_id = clients[ILT_CLI_CDUT].first.val +
+		    cdut_pf_init_pages - pf_start_line;
+		offset += qed_ilt_dump_pages_range(dump_buf + offset,
+						   dump,
+						   start_page_id,
+						   cdut_pf_work_pages,
+						   ilt_pages, dump_page_ids);
+
+		/* Dump task VF pages */
+		start_page_id = clients[ILT_CLI_CDUT].first.val +
+		    cdut_pf_pages + cdut_vf_init_pages - pf_start_line;
+		for (i = 0; i < p_hwfn->p_cxt_mngr->vf_count;
+		     i++, start_page_id += cdut_vf_pages)
+			offset += qed_ilt_dump_pages_range(dump_buf + offset,
+							   dump,
+							   start_page_id,
+							   cdut_vf_work_pages,
+							   ilt_pages,
+							   dump_page_ids);
+	}
+
+	/* Overwrite size param */
+	if (dump)
+		qed_dump_num_param(dump_buf + size_param_offset,
+				   dump, "size", offset - base_data_offset);
+
+	return offset;
+}
+
+/* Performs ILT Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_ilt_dump(struct ecore_hwfn *p_hwfn,
+			struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	struct ecore_ilt_client_cfg *clients = p_hwfn->p_cxt_mngr->clients;
+	u32 valid_conn_vf_cids, valid_conn_vf_pages, offset = 0;
+	u32 valid_conn_pf_cids, valid_conn_pf_pages, num_pages;
+	u32 num_cids_per_page, conn_ctx_size;
+	u32 cduc_page_size, cdut_page_size;
+	struct phys_mem_desc *ilt_pages;
+	u8 conn_type;
+
+	cduc_page_size = 1 <<
+	    (clients[ILT_CLI_CDUC].p_size.val + PXP_ILT_PAGE_SIZE_NUM_BITS_MIN);
+	cdut_page_size = 1 <<
+	    (clients[ILT_CLI_CDUT].p_size.val + PXP_ILT_PAGE_SIZE_NUM_BITS_MIN);
+	conn_ctx_size = p_hwfn->p_cxt_mngr->conn_ctx_size;
+	num_cids_per_page = (int)(cduc_page_size / conn_ctx_size);
+	ilt_pages = p_hwfn->p_cxt_mngr->ilt_shadow;
+
+	/* Dump global params - 22 must match number of params below */
+	offset += qed_dump_common_global_params(p_hwfn, p_ptt,
+						dump_buf + offset, dump, 22);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "ilt-dump");
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-page-size", cduc_page_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-first-page-id",
+				     clients[ILT_CLI_CDUC].first.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-last-page-id",
+				     clients[ILT_CLI_CDUC].last.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-num-pf-pages",
+				     clients
+				     [ILT_CLI_CDUC].pf_total_lines);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-num-vf-pages",
+				     clients
+				     [ILT_CLI_CDUC].vf_total_lines);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "max-conn-ctx-size",
+				     conn_ctx_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-page-size", cdut_page_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-first-page-id",
+				     clients[ILT_CLI_CDUT].first.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-last-page-id",
+				     clients[ILT_CLI_CDUT].last.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-pf-init-pages",
+				     ecore_get_cdut_num_pf_init_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-vf-init-pages",
+				     ecore_get_cdut_num_vf_init_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-pf-work-pages",
+				     ecore_get_cdut_num_pf_work_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-vf-work-pages",
+				     ecore_get_cdut_num_vf_work_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "max-task-ctx-size",
+				     p_hwfn->p_cxt_mngr->task_ctx_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "task-type-id",
+				     p_hwfn->p_cxt_mngr->task_type_id);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "first-vf-id-in-pf",
+				     p_hwfn->p_cxt_mngr->first_vf_in_pf);
+	offset += /* 18 */ qed_dump_num_param(dump_buf + offset,
+					      dump,
+					      "num-vfs-in-pf",
+					      p_hwfn->p_cxt_mngr->vf_count);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "ptr-size-bytes", sizeof(void *));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "pf-start-line",
+				     p_hwfn->p_cxt_mngr->pf_start_line);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "page-mem-desc-size-dwords",
+				     PAGE_MEM_DESC_SIZE_DWORDS);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "ilt-shadow-size",
+				     p_hwfn->p_cxt_mngr->ilt_shadow_size);
+	/* Additional/Less parameters require matching of number in call to
+	 * dump_common_global_params()
+	 */
+
+	/* Dump section containing number of PF CIDs per connection type */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "num_pf_cids_per_conn_type", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", NUM_OF_CONNECTION_TYPES);
+	for (conn_type = 0, valid_conn_pf_cids = 0;
+	     conn_type < NUM_OF_CONNECTION_TYPES; conn_type++, offset++) {
+		u32 num_pf_cids =
+		    p_hwfn->p_cxt_mngr->conn_cfg[conn_type].cid_count;
+
+		if (dump)
+			*(dump_buf + offset) = num_pf_cids;
+		valid_conn_pf_cids += num_pf_cids;
+	}
+
+	/* Dump section containing number of VF CIDs per connection type */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "num_vf_cids_per_conn_type", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", NUM_OF_CONNECTION_TYPES);
+	for (conn_type = 0, valid_conn_vf_cids = 0;
+	     conn_type < NUM_OF_CONNECTION_TYPES; conn_type++, offset++) {
+		u32 num_vf_cids =
+		    p_hwfn->p_cxt_mngr->conn_cfg[conn_type].cids_per_vf;
+
+		if (dump)
+			*(dump_buf + offset) = num_vf_cids;
+		valid_conn_vf_cids += num_vf_cids;
+	}
+
+	/* Dump section containing physical memory descs for each ILT page */
+	num_pages = p_hwfn->p_cxt_mngr->ilt_shadow_size;
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "ilt_page_desc", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "size",
+				     num_pages * PAGE_MEM_DESC_SIZE_DWORDS);
+
+	/* Copy memory descriptors to dump buffer */
+	if (dump) {
+		u32 page_id;
+
+		for (page_id = 0; page_id < num_pages;
+		     page_id++, offset += PAGE_MEM_DESC_SIZE_DWORDS)
+			memcpy(dump_buf + offset,
+			       &ilt_pages[page_id],
+			       DWORDS_TO_BYTES(PAGE_MEM_DESC_SIZE_DWORDS));
+	} else {
+		offset += num_pages * PAGE_MEM_DESC_SIZE_DWORDS;
+	}
+
+	valid_conn_pf_pages = DIV_ROUND_UP(valid_conn_pf_cids,
+					   num_cids_per_page);
+	valid_conn_vf_pages = DIV_ROUND_UP(valid_conn_vf_cids,
+					   num_cids_per_page);
+
+	/* Dump ILT pages IDs */
+	offset += qed_ilt_dump_pages_section(p_hwfn,
+					     dump_buf + offset,
+					     dump,
+					     valid_conn_pf_pages,
+					     valid_conn_vf_pages,
+					     ilt_pages, true);
+
+	/* Dump ILT pages memory */
+	offset += qed_ilt_dump_pages_section(p_hwfn,
+					     dump_buf + offset,
+					     dump,
+					     valid_conn_pf_pages,
+					     valid_conn_vf_pages,
+					     ilt_pages, false);
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	return offset;
+}
+
+/***************************** Public Functions *******************************/
+
+enum dbg_status qed_dbg_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+				    const u8 * const bin_ptr)
+{
+	struct bin_buffer_hdr *buf_hdrs =
+			(struct bin_buffer_hdr *)(osal_uintptr_t)bin_ptr;
+	u8 buf_id;
+
+	/* Convert binary data to debug arrays */
+	for (buf_id = 0; buf_id < MAX_BIN_DBG_BUFFER_TYPE; buf_id++)
+		qed_set_dbg_bin_buf(p_hwfn,
+				    buf_id,
+				    (const u32 *)(bin_ptr +
+						  buf_hdrs[buf_id].offset),
+						  buf_hdrs[buf_id].length);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_set_app_ver(u32 ver)
+{
+	if (ver < TOOLS_VERSION)
+		return DBG_STATUS_UNSUPPORTED_APP_VERSION;
+
+	s_app_ver = ver;
+
+	return DBG_STATUS_OK;
+}
+
+bool qed_read_fw_info(struct ecore_hwfn *p_hwfn,
+		      struct ecore_ptt *p_ptt, struct fw_info *fw_info)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		struct storm_defs *storm = &s_storm_defs[storm_id];
+
+		/* Skip Storm if it's in reset */
+		if (dev_data->block_in_reset[storm->sem_block_id])
+			continue;
+
+		/* Read FW info for the current Storm */
+		qed_read_storm_fw_info(p_hwfn, p_ptt, storm_id, fw_info);
+
+		return true;
+	}
+
+	return false;
+}
+
+enum dbg_status qed_dbg_grc_config(struct ecore_hwfn *p_hwfn,
+				   enum dbg_grc_params grc_param, u32 val)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	enum dbg_status status;
+	int i;
+
+	DP_VERBOSE(p_hwfn->p_dev,
+		   ECORE_MSG_DEBUG,
+		   "dbg_grc_config: paramId = %d, val = %d\n", grc_param, val);
+
+	status = qed_dbg_dev_init(p_hwfn);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Initializes the GRC parameters (if not initialized). Needed in order
+	 * to set the default parameter values for the first time.
+	 */
+	qed_dbg_grc_init_params(p_hwfn);
+
+	if (grc_param >= MAX_DBG_GRC_PARAMS)
+		return DBG_STATUS_INVALID_ARGS;
+	if (val < s_grc_param_defs[grc_param].min ||
+	    val > s_grc_param_defs[grc_param].max)
+		return DBG_STATUS_INVALID_ARGS;
+
+	if (s_grc_param_defs[grc_param].is_preset) {
+		/* Preset param */
+
+		/* Disabling a preset is not allowed. Call
+		 * dbg_grc_set_params_default instead.
+		 */
+		if (!val)
+			return DBG_STATUS_INVALID_ARGS;
+
+		/* Update all params with the preset values */
+		for (i = 0; i < MAX_DBG_GRC_PARAMS; i++) {
+			struct grc_param_defs *defs = &s_grc_param_defs[i];
+			u32 preset_val;
+			/* Skip persistent params */
+			if (defs->is_persistent)
+				continue;
+
+			/* Find preset value */
+			if (grc_param == DBG_GRC_PARAM_EXCLUDE_ALL)
+				preset_val =
+				    defs->exclude_all_preset_val;
+			else if (grc_param == DBG_GRC_PARAM_CRASH)
+				preset_val =
+				    defs->crash_preset_val[dev_data->chip_id];
+			else
+				return DBG_STATUS_INVALID_ARGS;
+
+			qed_grc_set_param(p_hwfn, i, preset_val);
+		}
+	} else {
+		/* Regular param - set its value */
+		qed_grc_set_param(p_hwfn, grc_param, val);
+	}
+
+	return DBG_STATUS_OK;
+}
+
+/* Assign default GRC param values */
+void qed_dbg_grc_set_params_default(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 i;
+
+	for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
+		if (!s_grc_param_defs[i].is_persistent)
+			dev_data->grc.param_val[i] =
+			    s_grc_param_defs[i].default_val[dev_data->chip_id];
+}
+
+enum dbg_status qed_dbg_grc_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_MEM].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	return qed_grc_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_grc_dump(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf,
+				 u32 buf_size_in_dwords,
+				 u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_grc_get_dump_buf_size(p_hwfn,
+					       p_ptt,
+					       &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* GRC Dump */
+	status = qed_grc_dump(p_hwfn, p_ptt, dump_buf, true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_idle_chk_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	struct idle_chk_data *idle_chk = &dev_data->idle_chk;
+	enum dbg_status status;
+
+	*buf_size = 0;
+
+	status = qed_dbg_dev_init(p_hwfn);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_IMMS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_RULES].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	if (!idle_chk->buf_size_set) {
+		idle_chk->buf_size = qed_idle_chk_dump(p_hwfn,
+						       p_ptt, NULL, false);
+		idle_chk->buf_size_set = true;
+	}
+
+	*buf_size = idle_chk->buf_size;
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_idle_chk_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_grc_unreset_blocks(p_hwfn, p_ptt, true);
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	/* Idle Check Dump */
+	*num_dumped_dwords = qed_idle_chk_dump(p_hwfn, p_ptt, dump_buf, true);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_mcp_trace_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						    struct ecore_ptt *p_ptt,
+						    u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_mcp_trace_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+				       struct ecore_ptt *p_ptt,
+				       u32 *dump_buf,
+				       u32 buf_size_in_dwords,
+				       u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	status =
+		qed_dbg_mcp_trace_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK && status !=
+	    DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
+		return status;
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	/* Perform dump */
+	status = qed_mcp_trace_dump(p_hwfn,
+				    p_ptt, dump_buf, true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_reg_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_reg_fifo_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_reg_fifo_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	status = qed_reg_fifo_dump(p_hwfn,
+				   p_ptt, dump_buf, true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_igu_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_igu_fifo_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_igu_fifo_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	status = qed_igu_fifo_dump(p_hwfn,
+				   p_ptt, dump_buf, true, num_dumped_dwords);
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status
+qed_dbg_protection_override_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_protection_override_dump(p_hwfn,
+					    p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_protection_override_dump(struct ecore_hwfn *p_hwfn,
+						 struct ecore_ptt *p_ptt,
+						 u32 *dump_buf,
+						 u32 buf_size_in_dwords,
+						 u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords, *p_size = &needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status =
+		qed_dbg_protection_override_get_dump_buf_size(p_hwfn,
+							      p_ptt,
+							      p_size);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	status = qed_protection_override_dump(p_hwfn,
+					      p_ptt,
+					      dump_buf,
+					      true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_fw_asserts_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						     struct ecore_ptt *p_ptt,
+						     u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	*buf_size = qed_fw_asserts_dump(p_hwfn, p_ptt, NULL, false);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf,
+					u32 buf_size_in_dwords,
+					u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords, *p_size = &needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status =
+		qed_dbg_fw_asserts_get_dump_buf_size(p_hwfn,
+						     p_ptt,
+						     p_size);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	*num_dumped_dwords = qed_fw_asserts_dump(p_hwfn, p_ptt, dump_buf, true);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status qed_dbg_ilt_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						     struct ecore_ptt *p_ptt,
+						     u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	*buf_size = qed_ilt_dump(p_hwfn, p_ptt, NULL, false);
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status qed_dbg_ilt_dump(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf,
+					u32 buf_size_in_dwords,
+					u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_ilt_get_dump_buf_size(p_hwfn,
+					       p_ptt,
+					       &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	*num_dumped_dwords = qed_ilt_dump(p_hwfn, p_ptt, dump_buf, true);
+
+	/* Reveret GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_read_attn(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  enum block_id block_id,
+				  enum dbg_attn_type attn_type,
+				  bool clear_status,
+				  struct dbg_attn_block_result *results)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+	u8 reg_idx, num_attn_regs, num_result_regs = 0;
+	const struct dbg_attn_reg *attn_reg_arr;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
+					       block_id,
+					       attn_type, &num_attn_regs);
+
+	for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
+		const struct dbg_attn_reg *reg_data = &attn_reg_arr[reg_idx];
+		struct dbg_attn_reg_result *reg_result;
+		u32 sts_addr, sts_val;
+		u16 modes_buf_offset;
+		bool eval_mode;
+
+		/* Check mode */
+		eval_mode = GET_FIELD(reg_data->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		modes_buf_offset = GET_FIELD(reg_data->mode.data,
+					     DBG_MODE_HDR_MODES_BUF_OFFSET);
+		if (eval_mode && !qed_is_mode_match(p_hwfn, &modes_buf_offset))
+			continue;
+
+		/* Mode match - read attention status register */
+		sts_addr = DWORDS_TO_BYTES(clear_status ?
+					   reg_data->sts_clr_address :
+					   GET_FIELD(reg_data->data,
+						     DBG_ATTN_REG_STS_ADDRESS));
+		sts_val = ecore_rd(p_hwfn, p_ptt, sts_addr);
+		if (!sts_val)
+			continue;
+
+		/* Non-zero attention status - add to results */
+		reg_result = &results->reg_results[num_result_regs];
+		SET_FIELD(reg_result->data,
+			  DBG_ATTN_REG_RESULT_STS_ADDRESS, sts_addr);
+		SET_FIELD(reg_result->data,
+			  DBG_ATTN_REG_RESULT_NUM_REG_ATTN,
+			  GET_FIELD(reg_data->data, DBG_ATTN_REG_NUM_REG_ATTN));
+		reg_result->block_attn_offset = reg_data->block_attn_offset;
+		reg_result->sts_val = sts_val;
+		reg_result->mask_val = ecore_rd(p_hwfn,
+					      p_ptt,
+					      DWORDS_TO_BYTES
+					      (reg_data->mask_address));
+		num_result_regs++;
+	}
+
+	results->block_id = (u8)block_id;
+	results->names_offset =
+	    qed_get_block_attn_data(p_hwfn, block_id, attn_type)->names_offset;
+	SET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_ATTN_TYPE, attn_type);
+	SET_FIELD(results->data,
+		  DBG_ATTN_BLOCK_RESULT_NUM_REGS, num_result_regs);
+
+	return DBG_STATUS_OK;
+}
+
+/******************************* Data Types **********************************/
+
+/* REG fifo element */
+struct reg_fifo_element {
+	u64 data;
+#define REG_FIFO_ELEMENT_ADDRESS_SHIFT		0
+#define REG_FIFO_ELEMENT_ADDRESS_MASK		0x7fffff
+#define REG_FIFO_ELEMENT_ACCESS_SHIFT		23
+#define REG_FIFO_ELEMENT_ACCESS_MASK		0x1
+#define REG_FIFO_ELEMENT_PF_SHIFT		24
+#define REG_FIFO_ELEMENT_PF_MASK		0xf
+#define REG_FIFO_ELEMENT_VF_SHIFT		28
+#define REG_FIFO_ELEMENT_VF_MASK		0xff
+#define REG_FIFO_ELEMENT_PORT_SHIFT		36
+#define REG_FIFO_ELEMENT_PORT_MASK		0x3
+#define REG_FIFO_ELEMENT_PRIVILEGE_SHIFT	38
+#define REG_FIFO_ELEMENT_PRIVILEGE_MASK		0x3
+#define REG_FIFO_ELEMENT_PROTECTION_SHIFT	40
+#define REG_FIFO_ELEMENT_PROTECTION_MASK	0x7
+#define REG_FIFO_ELEMENT_MASTER_SHIFT		43
+#define REG_FIFO_ELEMENT_MASTER_MASK		0xf
+#define REG_FIFO_ELEMENT_ERROR_SHIFT		47
+#define REG_FIFO_ELEMENT_ERROR_MASK		0x1f
+};
+
+/* REG fifo error element */
+struct reg_fifo_err {
+	u32 err_code;
+	const char *err_msg;
+};
+
+/* IGU fifo element */
+struct igu_fifo_element {
+	u32 dword0;
+#define IGU_FIFO_ELEMENT_DWORD0_FID_SHIFT		0
+#define IGU_FIFO_ELEMENT_DWORD0_FID_MASK		0xff
+#define IGU_FIFO_ELEMENT_DWORD0_IS_PF_SHIFT		8
+#define IGU_FIFO_ELEMENT_DWORD0_IS_PF_MASK		0x1
+#define IGU_FIFO_ELEMENT_DWORD0_SOURCE_SHIFT		9
+#define IGU_FIFO_ELEMENT_DWORD0_SOURCE_MASK		0xf
+#define IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE_SHIFT		13
+#define IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE_MASK		0xf
+#define IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR_SHIFT		17
+#define IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR_MASK		0x7fff
+	u32 dword1;
+	u32 dword2;
+#define IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD_SHIFT	0
+#define IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD_MASK		0x1
+#define IGU_FIFO_ELEMENT_DWORD12_WR_DATA_SHIFT		1
+#define IGU_FIFO_ELEMENT_DWORD12_WR_DATA_MASK		0xffffffff
+	u32 reserved;
+};
+
+struct igu_fifo_wr_data {
+	u32 data;
+#define IGU_FIFO_WR_DATA_PROD_CONS_SHIFT		0
+#define IGU_FIFO_WR_DATA_PROD_CONS_MASK			0xffffff
+#define IGU_FIFO_WR_DATA_UPDATE_FLAG_SHIFT		24
+#define IGU_FIFO_WR_DATA_UPDATE_FLAG_MASK		0x1
+#define IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB_SHIFT	25
+#define IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB_MASK		0x3
+#define IGU_FIFO_WR_DATA_SEGMENT_SHIFT			27
+#define IGU_FIFO_WR_DATA_SEGMENT_MASK			0x1
+#define IGU_FIFO_WR_DATA_TIMER_MASK_SHIFT		28
+#define IGU_FIFO_WR_DATA_TIMER_MASK_MASK		0x1
+#define IGU_FIFO_WR_DATA_CMD_TYPE_SHIFT			31
+#define IGU_FIFO_WR_DATA_CMD_TYPE_MASK			0x1
+};
+
+struct igu_fifo_cleanup_wr_data {
+	u32 data;
+#define IGU_FIFO_CLEANUP_WR_DATA_RESERVED_SHIFT		0
+#define IGU_FIFO_CLEANUP_WR_DATA_RESERVED_MASK		0x7ffffff
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL_SHIFT	27
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL_MASK	0x1
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE_SHIFT	28
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE_MASK	0x7
+#define IGU_FIFO_CLEANUP_WR_DATA_CMD_TYPE_SHIFT		31
+#define IGU_FIFO_CLEANUP_WR_DATA_CMD_TYPE_MASK		0x1
+};
+
+/* Protection override element */
+struct protection_override_element {
+	u64 data;
+#define PROTECTION_OVERRIDE_ELEMENT_ADDRESS_SHIFT		0
+#define PROTECTION_OVERRIDE_ELEMENT_ADDRESS_MASK		0x7fffff
+#define PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE_SHIFT		23
+#define PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE_MASK		0xffffff
+#define PROTECTION_OVERRIDE_ELEMENT_READ_SHIFT			47
+#define PROTECTION_OVERRIDE_ELEMENT_READ_MASK			0x1
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_SHIFT			48
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_MASK			0x1
+#define PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION_SHIFT	49
+#define PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION_MASK	0x7
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION_SHIFT	52
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION_MASK	0x7
+};
+
+enum igu_fifo_sources {
+	IGU_SRC_PXP0,
+	IGU_SRC_PXP1,
+	IGU_SRC_PXP2,
+	IGU_SRC_PXP3,
+	IGU_SRC_PXP4,
+	IGU_SRC_PXP5,
+	IGU_SRC_PXP6,
+	IGU_SRC_PXP7,
+	IGU_SRC_CAU,
+	IGU_SRC_ATTN,
+	IGU_SRC_GRC
+};
+
+enum igu_fifo_addr_types {
+	IGU_ADDR_TYPE_MSIX_MEM,
+	IGU_ADDR_TYPE_WRITE_PBA,
+	IGU_ADDR_TYPE_WRITE_INT_ACK,
+	IGU_ADDR_TYPE_WRITE_ATTN_BITS,
+	IGU_ADDR_TYPE_READ_INT,
+	IGU_ADDR_TYPE_WRITE_PROD_UPDATE,
+	IGU_ADDR_TYPE_RESERVED
+};
+
+struct igu_fifo_addr_data {
+	u16 start_addr;
+	u16 end_addr;
+	const char *desc;
+	const char *vf_desc;
+	enum igu_fifo_addr_types type;
+};
+
+/******************************** Constants **********************************/
+
+#define MAX_MSG_LEN				1024
+
+#define MCP_TRACE_MAX_MODULE_LEN		8
+#define MCP_TRACE_FORMAT_MAX_PARAMS		3
+#define MCP_TRACE_FORMAT_PARAM_WIDTH \
+	(MCP_TRACE_FORMAT_P2_SIZE_OFFSET - MCP_TRACE_FORMAT_P1_SIZE_OFFSET)
+
+#define REG_FIFO_ELEMENT_ADDR_FACTOR		4
+#define REG_FIFO_ELEMENT_IS_PF_VF_VAL		127
+
+#define PROTECTION_OVERRIDE_ELEMENT_ADDR_FACTOR	4
+
+/***************************** Constant Arrays *******************************/
+
+/* Status string array */
+static const char * const s_status_str[] = {
+	/* DBG_STATUS_OK */
+	"Operation completed successfully",
+
+	/* DBG_STATUS_APP_VERSION_NOT_SET */
+	"Debug application version wasn't set",
+
+	/* DBG_STATUS_UNSUPPORTED_APP_VERSION */
+	"Unsupported debug application version",
+
+	/* DBG_STATUS_DBG_BLOCK_NOT_RESET */
+	"The debug block wasn't reset since the last recording",
+
+	/* DBG_STATUS_INVALID_ARGS */
+	"Invalid arguments",
+
+	/* DBG_STATUS_OUTPUT_ALREADY_SET */
+	"The debug output was already set",
+
+	/* DBG_STATUS_INVALID_PCI_BUF_SIZE */
+	"Invalid PCI buffer size",
+
+	/* DBG_STATUS_PCI_BUF_ALLOC_FAILED */
+	"PCI buffer allocation failed",
+
+	/* DBG_STATUS_PCI_BUF_NOT_ALLOCATED */
+	"A PCI buffer wasn't allocated",
+
+	/* DBG_STATUS_INVALID_FILTER_TRIGGER_DWORDS */
+	"The filter/trigger constraint dword offsets are not enabled for recording",
+
+
+	/* DBG_STATUS_VFC_READ_ERROR */
+	"Error reading from VFC",
+
+	/* DBG_STATUS_STORM_ALREADY_ENABLED */
+	"The Storm was already enabled",
+
+	/* DBG_STATUS_STORM_NOT_ENABLED */
+	"The specified Storm wasn't enabled",
+
+	/* DBG_STATUS_BLOCK_ALREADY_ENABLED */
+	"The block was already enabled",
+
+	/* DBG_STATUS_BLOCK_NOT_ENABLED */
+	"The specified block wasn't enabled",
+
+	/* DBG_STATUS_NO_INPUT_ENABLED */
+	"No input was enabled for recording",
+
+	/* DBG_STATUS_NO_FILTER_TRIGGER_256B */
+	"Filters and triggers are not allowed in E4 256-bit mode",
+
+	/* DBG_STATUS_FILTER_ALREADY_ENABLED */
+	"The filter was already enabled",
+
+	/* DBG_STATUS_TRIGGER_ALREADY_ENABLED */
+	"The trigger was already enabled",
+
+	/* DBG_STATUS_TRIGGER_NOT_ENABLED */
+	"The trigger wasn't enabled",
+
+	/* DBG_STATUS_CANT_ADD_CONSTRAINT */
+	"A constraint can be added only after a filter was enabled or a trigger state was added",
+
+	/* DBG_STATUS_TOO_MANY_TRIGGER_STATES */
+	"Cannot add more than 3 trigger states",
+
+	/* DBG_STATUS_TOO_MANY_CONSTRAINTS */
+	"Cannot add more than 4 constraints per filter or trigger state",
+
+	/* DBG_STATUS_RECORDING_NOT_STARTED */
+	"The recording wasn't started",
+
+	/* DBG_STATUS_DATA_DID_NOT_TRIGGER */
+	"A trigger was configured, but it didn't trigger",
+
+	/* DBG_STATUS_NO_DATA_RECORDED */
+	"No data was recorded",
+
+	/* DBG_STATUS_DUMP_BUF_TOO_SMALL */
+	"Dump buffer is too small",
+
+	/* DBG_STATUS_DUMP_NOT_CHUNK_ALIGNED */
+	"Dumped data is not aligned to chunks",
+
+	/* DBG_STATUS_UNKNOWN_CHIP */
+	"Unknown chip",
+
+	/* DBG_STATUS_VIRT_MEM_ALLOC_FAILED */
+	"Failed allocating virtual memory",
+
+	/* DBG_STATUS_BLOCK_IN_RESET */
+	"The input block is in reset",
+
+	/* DBG_STATUS_INVALID_TRACE_SIGNATURE */
+	"Invalid MCP trace signature found in NVRAM",
+
+	/* DBG_STATUS_INVALID_NVRAM_BUNDLE */
+	"Invalid bundle ID found in NVRAM",
+
+	/* DBG_STATUS_NVRAM_GET_IMAGE_FAILED */
+	"Failed getting NVRAM image",
+
+	/* DBG_STATUS_NON_ALIGNED_NVRAM_IMAGE */
+	"NVRAM image is not dword-aligned",
+
+	/* DBG_STATUS_NVRAM_READ_FAILED */
+	"Failed reading from NVRAM",
+
+	/* DBG_STATUS_IDLE_CHK_PARSE_FAILED */
+	"Idle check parsing failed",
+
+	/* DBG_STATUS_MCP_TRACE_BAD_DATA */
+	"MCP Trace data is corrupt",
+
+	/* DBG_STATUS_MCP_TRACE_NO_META */
+	"Dump doesn't contain meta data - it must be provided in image file",
+
+	/* DBG_STATUS_MCP_COULD_NOT_HALT */
+	"Failed to halt MCP",
+
+	/* DBG_STATUS_MCP_COULD_NOT_RESUME */
+	"Failed to resume MCP after halt",
+
+	/* DBG_STATUS_RESERVED0 */
+	"",
+
+	/* DBG_STATUS_SEMI_FIFO_NOT_EMPTY */
+	"Failed to empty SEMI sync FIFO",
+
+	/* DBG_STATUS_IGU_FIFO_BAD_DATA */
+	"IGU FIFO data is corrupt",
+
+	/* DBG_STATUS_MCP_COULD_NOT_MASK_PRTY */
+	"MCP failed to mask parities",
+
+	/* DBG_STATUS_FW_ASSERTS_PARSE_FAILED */
+	"FW Asserts parsing failed",
+
+	/* DBG_STATUS_REG_FIFO_BAD_DATA */
+	"GRC FIFO data is corrupt",
+
+	/* DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA */
+	"Protection Override data is corrupt",
+
+	/* DBG_STATUS_DBG_ARRAY_NOT_SET */
+	"Debug arrays were not set (when using binary files, dbg_set_bin_ptr must be called)",
+
+	/* DBG_STATUS_RESERVED1 */
+	"",
+
+	/* DBG_STATUS_NON_MATCHING_LINES */
+	"Non-matching debug lines - in E4, all lines must be of the same type (either 128b or 256b)",
+
+	/* DBG_STATUS_INSUFFICIENT_HW_IDS */
+	"Insufficient HW IDs. Try to record less Storms/blocks",
+
+	/* DBG_STATUS_DBG_BUS_IN_USE */
+	"The debug bus is in use",
+
+	/* DBG_STATUS_INVALID_STORM_DBG_MODE */
+	"The storm debug mode is not supported in the current chip",
+
+	/* DBG_STATUS_OTHER_ENGINE_BB_ONLY */
+	"Other engine is supported only in BB",
+
+	/* DBG_STATUS_FILTER_SINGLE_HW_ID */
+	"The configured filter mode requires a single Storm/block input",
+
+	/* DBG_STATUS_TRIGGER_SINGLE_HW_ID */
+	"The configured filter mode requires that all the constraints of a single trigger state will be defined on a single Storm/block input",
+
+	/* DBG_STATUS_MISSING_TRIGGER_STATE_STORM */
+	"When triggering on Storm data, the Storm to trigger on must be specified"
+};
+
+/* Idle check severity names array */
+static const char * const s_idle_chk_severity_str[] = {
+	"Error",
+	"Error if no traffic",
+	"Warning"
+};
+
+/* MCP Trace level names array */
+static const char * const s_mcp_trace_level_str[] = {
+	"ERROR",
+	"TRACE",
+	"DEBUG"
+};
+
+/* Access type names array */
+static const char * const s_access_strs[] = {
+	"read",
+	"write"
+};
+
+/* Privilege type names array */
+static const char * const s_privilege_strs[] = {
+	"VF",
+	"PDA",
+	"HV",
+	"UA"
+};
+
+/* Protection type names array */
+static const char * const s_protection_strs[] = {
+	"(default)",
+	"(default)",
+	"(default)",
+	"(default)",
+	"override VF",
+	"override PDA",
+	"override HV",
+	"override UA"
+};
+
+/* Master type names array */
+static const char * const s_master_strs[] = {
+	"???",
+	"pxp",
+	"mcp",
+	"msdm",
+	"psdm",
+	"ysdm",
+	"usdm",
+	"tsdm",
+	"xsdm",
+	"dbu",
+	"dmae",
+	"jdap",
+	"???",
+	"???",
+	"???",
+	"???"
+};
+
+/* REG FIFO error messages array */
+static struct reg_fifo_err s_reg_fifo_errors[] = {
+	{1, "grc timeout"},
+	{2, "address doesn't belong to any block"},
+	{4, "reserved address in block or write to read-only address"},
+	{8, "privilege/protection mismatch"},
+	{16, "path isolation error"},
+	{17, "RSL error"}
+};
+
+/* IGU FIFO sources array */
+static const char * const s_igu_fifo_source_strs[] = {
+	"TSTORM",
+	"MSTORM",
+	"USTORM",
+	"XSTORM",
+	"YSTORM",
+	"PSTORM",
+	"PCIE",
+	"NIG_QM_PBF",
+	"CAU",
+	"ATTN",
+	"GRC",
+};
+
+/* IGU FIFO error messages */
+static const char * const s_igu_fifo_error_strs[] = {
+	"no error",
+	"length error",
+	"function disabled",
+	"VF sent command to attention address",
+	"host sent prod update command",
+	"read of during interrupt register while in MIMD mode",
+	"access to PXP BAR reserved address",
+	"producer update command to attention index",
+	"unknown error",
+	"SB index not valid",
+	"SB relative index and FID not found",
+	"FID not match",
+	"command with error flag asserted (PCI error or CAU discard)",
+	"VF sent cleanup and RF cleanup is disabled",
+	"cleanup command on type bigger than 4"
+};
+
+/* IGU FIFO address data */
+static const struct igu_fifo_addr_data s_igu_fifo_addr_data[] = {
+	{0x0, 0x101, "MSI-X Memory", NULL,
+	 IGU_ADDR_TYPE_MSIX_MEM},
+	{0x102, 0x1ff, "reserved", NULL,
+	 IGU_ADDR_TYPE_RESERVED},
+	{0x200, 0x200, "Write PBA[0:63]", NULL,
+	 IGU_ADDR_TYPE_WRITE_PBA},
+	{0x201, 0x201, "Write PBA[64:127]", "reserved",
+	 IGU_ADDR_TYPE_WRITE_PBA},
+	{0x202, 0x202, "Write PBA[128]", "reserved",
+	 IGU_ADDR_TYPE_WRITE_PBA},
+	{0x203, 0x3ff, "reserved", NULL,
+	 IGU_ADDR_TYPE_RESERVED},
+	{0x400, 0x5ef, "Write interrupt acknowledgment", NULL,
+	 IGU_ADDR_TYPE_WRITE_INT_ACK},
+	{0x5f0, 0x5f0, "Attention bits update", NULL,
+	 IGU_ADDR_TYPE_WRITE_ATTN_BITS},
+	{0x5f1, 0x5f1, "Attention bits set", NULL,
+	 IGU_ADDR_TYPE_WRITE_ATTN_BITS},
+	{0x5f2, 0x5f2, "Attention bits clear", NULL,
+	 IGU_ADDR_TYPE_WRITE_ATTN_BITS},
+	{0x5f3, 0x5f3, "Read interrupt 0:63 with mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f4, 0x5f4, "Read interrupt 0:31 with mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f5, 0x5f5, "Read interrupt 32:63 with mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f6, 0x5f6, "Read interrupt 0:63 without mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f7, 0x5ff, "reserved", NULL,
+	 IGU_ADDR_TYPE_RESERVED},
+	{0x600, 0x7ff, "Producer update", NULL,
+	 IGU_ADDR_TYPE_WRITE_PROD_UPDATE}
+};
+
+/******************************** Variables **********************************/
+
+/* Temporary buffer, used for print size calculations */
+static char s_temp_buf[MAX_MSG_LEN];
+
+/**************************** Private Functions ******************************/
+
+static u32 qed_cyclic_add(u32 a, u32 b, u32 size)
+{
+	return (a + b) % size;
+}
+
+static u32 qed_cyclic_sub(u32 a, u32 b, u32 size)
+{
+	return (size + a - b) % size;
+}
+
+/* Reads the specified number of bytes from the specified cyclic buffer (up to 4
+ * bytes) and returns them as a dword value. the specified buffer offset is
+ * updated.
+ */
+static u32 qed_read_from_cyclic_buf(void *buf,
+				    u32 *offset,
+				    u32 buf_size, u8 num_bytes_to_read)
+{
+	u8 i, *val_ptr, *bytes_buf = (u8 *)buf;
+	u32 val = 0;
+
+	val_ptr = (u8 *)&val;
+
+	/* Assume running on a LITTLE ENDIAN and the buffer is network order
+	 * (BIG ENDIAN), as high order bytes are placed in lower memory address.
+	 */
+	for (i = 0; i < num_bytes_to_read; i++) {
+		val_ptr[i] = bytes_buf[*offset];
+		*offset = qed_cyclic_add(*offset, 1, buf_size);
+	}
+
+	return val;
+}
+
+/* Reads and returns the next byte from the specified buffer.
+ * The specified buffer offset is updated.
+ */
+static u8 qed_read_byte_from_buf(void *buf, u32 *offset)
+{
+	return ((u8 *)buf)[(*offset)++];
+}
+
+/* Reads and returns the next dword from the specified buffer.
+ * The specified buffer offset is updated.
+ */
+static u32 qed_read_dword_from_buf(void *buf, u32 *offset)
+{
+	u32 dword_val = *(u32 *)&((u8 *)buf)[*offset];
+
+	*offset += 4;
+
+	return dword_val;
+}
+
+/* Reads the next string from the specified buffer, and copies it to the
+ * specified pointer. The specified buffer offset is updated.
+ */
+static void qed_read_str_from_buf(void *buf, u32 *offset, u32 size, char *dest)
+{
+	const char *source_str = &((const char *)buf)[*offset];
+
+	OSAL_STRNCPY(dest, source_str, size);
+	dest[size - 1] = '\0';
+	*offset += size;
+}
+
+/* Returns a pointer to the specified offset (in bytes) of the specified buffer.
+ * If the specified buffer in NULL, a temporary buffer pointer is returned.
+ */
+static char *qed_get_buf_ptr(void *buf, u32 offset)
+{
+	return buf ? (char *)buf + offset : s_temp_buf;
+}
+
+/* Reads a param from the specified buffer. Returns the number of dwords read.
+ * If the returned str_param is NULL, the param is numeric and its value is
+ * returned in num_param.
+ * Otheriwise, the param is a string and its pointer is returned in str_param.
+ */
+static u32 qed_read_param(u32 *dump_buf,
+			  const char **param_name,
+			  const char **param_str_val, u32 *param_num_val)
+{
+	char *char_buf = (char *)dump_buf;
+	size_t offset = 0;
+
+	/* Extract param name */
+	*param_name = char_buf;
+	offset += strlen(*param_name) + 1;
+
+	/* Check param type */
+	if (*(char_buf + offset++)) {
+		/* String param */
+		*param_str_val = char_buf + offset;
+		*param_num_val = 0;
+		offset += strlen(*param_str_val) + 1;
+		if (offset & 0x3)
+			offset += (4 - (offset & 0x3));
+	} else {
+		/* Numeric param */
+		*param_str_val = NULL;
+		if (offset & 0x3)
+			offset += (4 - (offset & 0x3));
+		*param_num_val = *(u32 *)(char_buf + offset);
+		offset += 4;
+	}
+
+	return (u32)offset / 4;
+}
+
+/* Reads a section header from the specified buffer.
+ * Returns the number of dwords read.
+ */
+static u32 qed_read_section_hdr(u32 *dump_buf,
+				const char **section_name,
+				u32 *num_section_params)
+{
+	const char *param_str_val;
+
+	return qed_read_param(dump_buf,
+			      section_name, &param_str_val, num_section_params);
+}
+
+/* Reads section params from the specified buffer and prints them to the results
+ * buffer. Returns the number of dwords read.
+ */
+static u32 qed_print_section_params(u32 *dump_buf,
+				    u32 num_section_params,
+				    char *results_buf, u32 *num_chars_printed)
+{
+	u32 i, dump_offset = 0, results_offset = 0;
+
+	for (i = 0; i < num_section_params; i++) {
+		const char *param_name, *param_str_val;
+		u32 param_num_val = 0;
+
+		dump_offset += qed_read_param(dump_buf + dump_offset,
+					      &param_name,
+					      &param_str_val, &param_num_val);
+
+		if (param_str_val) {
+			results_offset +=
+				sprintf(qed_get_buf_ptr(results_buf,
+							results_offset),
+					"%s: %s\n", param_name, param_str_val);
+		} else if (strcmp(param_name, "fw-timestamp")) {
+			results_offset +=
+				sprintf(qed_get_buf_ptr(results_buf,
+							results_offset),
+					"%s: %d\n", param_name, param_num_val);
+		}
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf, results_offset),
+				  "\n");
+
+	*num_chars_printed = results_offset;
+
+	return dump_offset;
+}
+
+/* Returns the block name that matches the specified block ID,
+ * or NULL if not found.
+ */
+static const char *qed_dbg_get_block_name(struct ecore_hwfn *p_hwfn,
+					  enum block_id block_id)
+{
+	const struct dbg_block_user *block =
+	    (const struct dbg_block_user *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS_USER_DATA].ptr + block_id;
+
+	return (const char *)block->name;
+}
+
+static struct dbg_tools_user_data *qed_dbg_get_user_data(struct ecore_hwfn
+							 *p_hwfn)
+{
+	return (struct dbg_tools_user_data *)p_hwfn->dbg_user_info;
+}
+
+/* Parses the idle check rules and returns the number of characters printed.
+ * In case of parsing error, returns 0.
+ */
+static u32 qed_parse_idle_chk_dump_rules(struct ecore_hwfn *p_hwfn,
+					 u32 *dump_buf,
+					 u32 *dump_buf_end,
+					 u32 num_rules,
+					 bool print_fw_idle_chk,
+					 char *results_buf,
+					 u32 *num_errors, u32 *num_warnings)
+{
+	/* Offset in results_buf in bytes */
+	u32 results_offset = 0;
+
+	u32 rule_idx;
+	u16 i, j;
+
+	*num_errors = 0;
+	*num_warnings = 0;
+
+	/* Go over dumped results */
+	for (rule_idx = 0; rule_idx < num_rules && dump_buf < dump_buf_end;
+	     rule_idx++) {
+		const struct dbg_idle_chk_rule_parsing_data *rule_parsing_data;
+		struct dbg_idle_chk_result_hdr *hdr;
+		const char *parsing_str, *lsi_msg;
+		u32 parsing_str_offset;
+		bool has_fw_msg;
+		u8 curr_reg_id;
+
+		hdr = (struct dbg_idle_chk_result_hdr *)dump_buf;
+		rule_parsing_data =
+		    (const struct dbg_idle_chk_rule_parsing_data *)
+		    p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_PARSING_DATA].ptr +
+		    hdr->rule_id;
+		parsing_str_offset =
+		    GET_FIELD(rule_parsing_data->data,
+			      DBG_IDLE_CHK_RULE_PARSING_DATA_STR_OFFSET);
+		has_fw_msg =
+		    GET_FIELD(rule_parsing_data->data,
+			      DBG_IDLE_CHK_RULE_PARSING_DATA_HAS_FW_MSG) > 0;
+		parsing_str = (const char *)
+		    p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr +
+		    parsing_str_offset;
+		lsi_msg = parsing_str;
+		curr_reg_id = 0;
+
+		if (hdr->severity >= MAX_DBG_IDLE_CHK_SEVERITY_TYPES)
+			return 0;
+
+		/* Skip rule header */
+		dump_buf += BYTES_TO_DWORDS(sizeof(*hdr));
+
+		/* Update errors/warnings count */
+		if (hdr->severity == IDLE_CHK_SEVERITY_ERROR ||
+		    hdr->severity == IDLE_CHK_SEVERITY_ERROR_NO_TRAFFIC)
+			(*num_errors)++;
+		else
+			(*num_warnings)++;
+
+		/* Print rule severity */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset), "%s: ",
+			    s_idle_chk_severity_str[hdr->severity]);
+
+		/* Print rule message */
+		if (has_fw_msg)
+			parsing_str += strlen(parsing_str) + 1;
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset), "%s.",
+			    has_fw_msg &&
+			    print_fw_idle_chk ? parsing_str : lsi_msg);
+		parsing_str += strlen(parsing_str) + 1;
+
+		/* Print register values */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset), " Registers:");
+		for (i = 0;
+		     i < hdr->num_dumped_cond_regs + hdr->num_dumped_info_regs;
+		     i++) {
+			struct dbg_idle_chk_result_reg_hdr *reg_hdr;
+			bool is_mem;
+			u8 reg_id;
+
+			reg_hdr =
+				(struct dbg_idle_chk_result_reg_hdr *)dump_buf;
+			is_mem = GET_FIELD(reg_hdr->data,
+					   DBG_IDLE_CHK_RESULT_REG_HDR_IS_MEM);
+			reg_id = GET_FIELD(reg_hdr->data,
+					   DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID);
+
+			/* Skip reg header */
+			dump_buf += BYTES_TO_DWORDS(sizeof(*reg_hdr));
+
+			/* Skip register names until the required reg_id is
+			 * reached.
+			 */
+			while (reg_id > curr_reg_id) {
+				curr_reg_id++;
+				parsing_str += strlen(parsing_str) + 1;
+			}
+
+			results_offset +=
+			    sprintf(qed_get_buf_ptr(results_buf,
+						    results_offset), " %s",
+				    parsing_str);
+			if (i < hdr->num_dumped_cond_regs && is_mem)
+				results_offset +=
+				    sprintf(qed_get_buf_ptr(results_buf,
+							    results_offset),
+					    "[%d]", hdr->mem_entry_id +
+					    reg_hdr->start_entry);
+			results_offset +=
+			    sprintf(qed_get_buf_ptr(results_buf,
+						    results_offset), "=");
+			for (j = 0; j < reg_hdr->size; j++, dump_buf++) {
+				results_offset +=
+				    sprintf(qed_get_buf_ptr(results_buf,
+							    results_offset),
+					    "0x%x", *dump_buf);
+				if (j < reg_hdr->size - 1)
+					results_offset +=
+					    sprintf(qed_get_buf_ptr
+						    (results_buf,
+						     results_offset), ",");
+			}
+		}
+
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf, results_offset), "\n");
+	}
+
+	/* Check if end of dump buffer was exceeded */
+	if (dump_buf > dump_buf_end)
+		return 0;
+
+	return results_offset;
+}
+
+/* Parses an idle check dump buffer.
+ * If result_buf is not NULL, the idle check results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+					       u32 *dump_buf,
+					       u32 num_dumped_dwords,
+					       char *results_buf,
+					       u32 *parsed_results_bytes,
+					       u32 *num_errors,
+					       u32 *num_warnings)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 *dump_buf_end = dump_buf + num_dumped_dwords;
+	u32 num_section_params = 0, num_rules;
+
+	/* Offset in results_buf in bytes */
+	u32 results_offset = 0;
+
+	*parsed_results_bytes = 0;
+	*num_errors = 0;
+	*num_warnings = 0;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_PARSING_DATA].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read idle_chk section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "idle_chk") || num_section_params != 1)
+		return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &num_rules);
+	if (strcmp(param_name, "num_rules"))
+		return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+
+	if (num_rules) {
+		u32 rules_print_size;
+
+		/* Print FW output */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "FW_IDLE_CHECK:\n");
+		rules_print_size =
+			qed_parse_idle_chk_dump_rules(p_hwfn,
+						      dump_buf,
+						      dump_buf_end,
+						      num_rules,
+						      true,
+						      results_buf ?
+						      results_buf +
+						      results_offset :
+						      NULL,
+						      num_errors,
+						      num_warnings);
+		results_offset += rules_print_size;
+		if (!rules_print_size)
+			return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+
+		/* Print LSI output */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nLSI_IDLE_CHECK:\n");
+		rules_print_size =
+			qed_parse_idle_chk_dump_rules(p_hwfn,
+						      dump_buf,
+						      dump_buf_end,
+						      num_rules,
+						      false,
+						      results_buf ?
+						      results_buf +
+						      results_offset :
+						      NULL,
+						      num_errors,
+						      num_warnings);
+		results_offset += rules_print_size;
+		if (!rules_print_size)
+			return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+	}
+
+	/* Print errors/warnings count */
+	if (*num_errors)
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nIdle Check failed!!! (with %d errors and %d warnings)\n",
+			    *num_errors, *num_warnings);
+	else if (*num_warnings)
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nIdle Check completed successfully (with %d warnings)\n",
+			    *num_warnings);
+	else
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nIdle Check completed successfully\n");
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+/* Allocates and fills MCP Trace meta data based on the specified meta data
+ * dump buffer.
+ * Returns debug status code.
+ */
+static enum dbg_status
+qed_mcp_trace_alloc_meta_data(struct ecore_hwfn *p_hwfn,
+			      const u32 *meta_buf)
+{
+	struct dbg_tools_user_data *dev_user_data;
+	u32 offset = 0, signature, i;
+	struct mcp_trace_meta *meta;
+	u8 *meta_buf_bytes = (u8 *)(osal_uintptr_t)meta_buf;
+
+	dev_user_data = qed_dbg_get_user_data(p_hwfn);
+	meta = &dev_user_data->mcp_trace_meta;
+
+	/* Free the previous meta before loading a new one. */
+	if (meta->is_allocated)
+		qed_mcp_trace_free_meta_data(p_hwfn);
+
+	OSAL_MEMSET(meta, 0, sizeof(*meta));
+
+	/* Read first signature */
+	signature = qed_read_dword_from_buf(meta_buf_bytes, &offset);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Read no. of modules and allocate memory for their pointers */
+	meta->modules_num = qed_read_byte_from_buf(meta_buf_bytes, &offset);
+	meta->modules = (char **)OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
+				    meta->modules_num * sizeof(char *));
+	if (!meta->modules)
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	/* Allocate and read all module strings */
+	for (i = 0; i < meta->modules_num; i++) {
+		u8 module_len = qed_read_byte_from_buf(meta_buf_bytes, &offset);
+
+		*(meta->modules + i) = (char *)OSAL_ZALLOC(p_hwfn->p_dev,
+							   GFP_KERNEL,
+							   module_len);
+		if (!(*(meta->modules + i))) {
+			/* Update number of modules to be released */
+			meta->modules_num = i ? i - 1 : 0;
+			return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+		}
+
+		qed_read_str_from_buf(meta_buf_bytes, &offset, module_len,
+				      *(meta->modules + i));
+		if (module_len > MCP_TRACE_MAX_MODULE_LEN)
+			(*(meta->modules + i))[MCP_TRACE_MAX_MODULE_LEN] = '\0';
+	}
+
+	/* Read second signature */
+	signature = qed_read_dword_from_buf(meta_buf_bytes, &offset);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Read number of formats and allocate memory for all formats */
+	meta->formats_num = qed_read_dword_from_buf(meta_buf_bytes, &offset);
+	meta->formats =
+		(struct mcp_trace_format *)OSAL_ZALLOC(p_hwfn->p_dev,
+						       GFP_KERNEL,
+						       meta->formats_num *
+					       sizeof(struct mcp_trace_format));
+	if (!meta->formats)
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	/* Allocate and read all strings */
+	for (i = 0; i < meta->formats_num; i++) {
+		struct mcp_trace_format *format_ptr = &meta->formats[i];
+		u8 format_len;
+
+		format_ptr->data = qed_read_dword_from_buf(meta_buf_bytes,
+							   &offset);
+		format_len = GET_MFW_FIELD(format_ptr->data,
+					   MCP_TRACE_FORMAT_LEN);
+		format_ptr->format_str = (char *)OSAL_ZALLOC(p_hwfn->p_dev,
+							     GFP_KERNEL,
+							     format_len);
+		if (!format_ptr->format_str) {
+			/* Update number of modules to be released */
+			meta->formats_num = i ? i - 1 : 0;
+			return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+		}
+
+		qed_read_str_from_buf(meta_buf_bytes,
+				      &offset,
+				      format_len, format_ptr->format_str);
+	}
+
+	meta->is_allocated = true;
+	return DBG_STATUS_OK;
+}
+
+/* Parses an MCP trace buffer. If result_buf is not NULL, the MCP Trace results
+ * are printed to it. The parsing status is returned.
+ * Arguments:
+ * trace_buf - MCP trace cyclic buffer
+ * trace_buf_size - MCP trace cyclic buffer size in bytes
+ * data_offset - offset in bytes of the data to parse in the MCP trace cyclic
+ *		 buffer.
+ * data_size - size in bytes of data to parse.
+ * parsed_buf - destination buffer for parsed data.
+ * parsed_results_bytes - size of parsed data in bytes.
+ */
+static enum dbg_status qed_parse_mcp_trace_buf(struct ecore_hwfn *p_hwfn,
+					       u8 *trace_buf,
+					       u32 trace_buf_size,
+					       u32 data_offset,
+					       u32 data_size,
+					       char *parsed_buf,
+					       u32 *parsed_results_bytes)
+{
+	struct dbg_tools_user_data *dev_user_data;
+	struct mcp_trace_meta *meta;
+	u32 param_mask, param_shift;
+	enum dbg_status status;
+
+	dev_user_data = qed_dbg_get_user_data(p_hwfn);
+	meta = &dev_user_data->mcp_trace_meta;
+	*parsed_results_bytes = 0;
+
+	if (!meta->is_allocated)
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+	status = DBG_STATUS_OK;
+
+	while (data_size) {
+		struct mcp_trace_format *format_ptr;
+		u8 format_level, format_module;
+		u32 params[3] = { 0, 0, 0 };
+		u32 header, format_idx, i;
+
+		if (data_size < MFW_TRACE_ENTRY_SIZE)
+			return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+		header = qed_read_from_cyclic_buf(trace_buf,
+						  &data_offset,
+						  trace_buf_size,
+						  MFW_TRACE_ENTRY_SIZE);
+		data_size -= MFW_TRACE_ENTRY_SIZE;
+		format_idx = header & MFW_TRACE_EVENTID_MASK;
+
+		/* Skip message if its index doesn't exist in the meta data */
+		if (format_idx >= meta->formats_num) {
+			u8 format_size = (u8)GET_MFW_FIELD(header,
+							   MFW_TRACE_PRM_SIZE);
+
+			if (data_size < format_size)
+				return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+			data_offset = qed_cyclic_add(data_offset,
+						     format_size,
+						     trace_buf_size);
+			data_size -= format_size;
+			continue;
+		}
+
+		format_ptr =
+			(struct mcp_trace_format *)&meta->formats[format_idx];
+
+		for (i = 0,
+		     param_mask = MCP_TRACE_FORMAT_P1_SIZE_MASK, param_shift =
+		     MCP_TRACE_FORMAT_P1_SIZE_OFFSET;
+		     i < MCP_TRACE_FORMAT_MAX_PARAMS;
+		     i++, param_mask <<= MCP_TRACE_FORMAT_PARAM_WIDTH,
+		     param_shift += MCP_TRACE_FORMAT_PARAM_WIDTH) {
+			/* Extract param size (0..3) */
+			u8 param_size = (u8)((format_ptr->data & param_mask) >>
+					     param_shift);
+
+			/* If the param size is zero, there are no other
+			 * parameters.
+			 */
+			if (!param_size)
+				break;
+
+			/* Size is encoded using 2 bits, where 3 is used to
+			 * encode 4.
+			 */
+			if (param_size == 3)
+				param_size = 4;
+
+			if (data_size < param_size)
+				return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+			params[i] = qed_read_from_cyclic_buf(trace_buf,
+							     &data_offset,
+							     trace_buf_size,
+							     param_size);
+			data_size -= param_size;
+		}
+
+		format_level = (u8)GET_MFW_FIELD(format_ptr->data,
+						 MCP_TRACE_FORMAT_LEVEL);
+		format_module = (u8)GET_MFW_FIELD(format_ptr->data,
+						  MCP_TRACE_FORMAT_MODULE);
+		if (format_level >= OSAL_ARRAY_SIZE(s_mcp_trace_level_str))
+			return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+		/* Print current message to results buffer */
+		*parsed_results_bytes +=
+			OSAL_SPRINTF(qed_get_buf_ptr(parsed_buf,
+						*parsed_results_bytes),
+				"%s %-8s: ",
+				s_mcp_trace_level_str[format_level],
+				meta->modules[format_module]);
+		*parsed_results_bytes +=
+		    sprintf(qed_get_buf_ptr(parsed_buf, *parsed_results_bytes),
+			    format_ptr->format_str,
+			    params[0], params[1], params[2]);
+	}
+
+	/* Add string NULL terminator */
+	(*parsed_results_bytes)++;
+
+	return status;
+}
+
+/* Parses an MCP Trace dump buffer.
+ * If result_buf is not NULL, the MCP Trace results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+						u32 *dump_buf,
+						char *results_buf,
+						u32 *parsed_results_bytes,
+						bool free_meta_data)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 data_size, trace_data_dwords, trace_meta_dwords;
+	u32 offset, results_offset, results_buf_bytes;
+	u32 param_num_val, num_section_params;
+	struct mcp_trace *trace;
+	enum dbg_status status;
+	const u32 *meta_buf;
+	u8 *trace_buf;
+
+	*parsed_results_bytes = 0;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read trace_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "mcp_trace_data") || num_section_params != 1)
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	trace_data_dwords = param_num_val;
+
+	/* Prepare trace info */
+	trace = (struct mcp_trace *)dump_buf;
+	if (trace->signature != MFW_TRACE_SIGNATURE || !trace->size)
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+	trace_buf = (u8 *)dump_buf + sizeof(*trace);
+	offset = trace->trace_oldest;
+	data_size = qed_cyclic_sub(trace->trace_prod, offset, trace->size);
+	dump_buf += trace_data_dwords;
+
+	/* Read meta_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "mcp_trace_meta"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	trace_meta_dwords = param_num_val;
+
+	/* Choose meta data buffer */
+	if (!trace_meta_dwords) {
+		/* Dump doesn't include meta data */
+		struct dbg_tools_user_data *dev_user_data =
+			qed_dbg_get_user_data(p_hwfn);
+
+		if (!dev_user_data->mcp_trace_user_meta_buf)
+			return DBG_STATUS_MCP_TRACE_NO_META;
+
+		meta_buf = dev_user_data->mcp_trace_user_meta_buf;
+	} else {
+		/* Dump includes meta data */
+		meta_buf = dump_buf;
+	}
+
+	/* Allocate meta data memory */
+	status = qed_mcp_trace_alloc_meta_data(p_hwfn, meta_buf);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	status = qed_parse_mcp_trace_buf(p_hwfn,
+					 trace_buf,
+					 trace->size,
+					 offset,
+					 data_size,
+					 results_buf ?
+					 results_buf + results_offset :
+					 NULL,
+					 &results_buf_bytes);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (free_meta_data)
+		qed_mcp_trace_free_meta_data(p_hwfn);
+
+	*parsed_results_bytes = results_offset + results_buf_bytes;
+
+	return DBG_STATUS_OK;
+}
+
+/* Parses a Reg FIFO dump buffer.
+ * If result_buf is not NULL, the Reg FIFO results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_reg_fifo_dump(u32 *dump_buf,
+					       char *results_buf,
+					       u32 *parsed_results_bytes)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 param_num_val, num_section_params, num_elements;
+	struct reg_fifo_element *elements;
+	u8 i, j, err_code, vf_val;
+	u32 results_offset = 0;
+	char vf_str[4];
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read reg_fifo_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "reg_fifo_data"))
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+	if (param_num_val % REG_FIFO_ELEMENT_DWORDS)
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+	num_elements = param_num_val / REG_FIFO_ELEMENT_DWORDS;
+	elements = (struct reg_fifo_element *)dump_buf;
+
+	/* Decode elements */
+	for (i = 0; i < num_elements; i++) {
+		const char *err_msg = NULL;
+
+		/* Discover if element belongs to a VF or a PF */
+		vf_val = GET_FIELD(elements[i].data, REG_FIFO_ELEMENT_VF);
+		if (vf_val == REG_FIFO_ELEMENT_IS_PF_VF_VAL)
+			sprintf(vf_str, "%s", "N/A");
+		else
+			sprintf(vf_str, "%d", vf_val);
+
+		/* Find error message */
+		err_code = GET_FIELD(elements[i].data, REG_FIFO_ELEMENT_ERROR);
+		for (j = 0; j < OSAL_ARRAY_SIZE(s_reg_fifo_errors) && !err_msg;
+		     j++)
+			if (err_code == s_reg_fifo_errors[j].err_code)
+				err_msg = s_reg_fifo_errors[j].err_msg;
+
+		/* Add parsed element to parsed buffer */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "raw: 0x%016lx, address: 0x%07x, access: %-5s, pf: %2d, vf: %s, port: %d, privilege: %-3s, protection: %-12s, master: %-4s, error: %s\n",
+			    elements[i].data,
+			    (u32)GET_FIELD(elements[i].data,
+					   REG_FIFO_ELEMENT_ADDRESS) *
+			    REG_FIFO_ELEMENT_ADDR_FACTOR,
+			    s_access_strs[GET_FIELD(elements[i].data,
+						    REG_FIFO_ELEMENT_ACCESS)],
+			    (u32)GET_FIELD(elements[i].data,
+					   REG_FIFO_ELEMENT_PF),
+			    vf_str,
+			    (u32)GET_FIELD(elements[i].data,
+					   REG_FIFO_ELEMENT_PORT),
+			    s_privilege_strs[GET_FIELD(elements[i].data,
+						REG_FIFO_ELEMENT_PRIVILEGE)],
+			    s_protection_strs[GET_FIELD(elements[i].data,
+						REG_FIFO_ELEMENT_PROTECTION)],
+			    s_master_strs[GET_FIELD(elements[i].data,
+						    REG_FIFO_ELEMENT_MASTER)],
+			    err_msg ? err_msg : "unknown error code");
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						  results_offset),
+				  "fifo contained %d elements", num_elements);
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status qed_parse_igu_fifo_element(struct igu_fifo_element
+						  *element, char
+						  *results_buf,
+						  u32 *results_offset)
+{
+	const struct igu_fifo_addr_data *found_addr = NULL;
+	u8 source, err_type, i, is_cleanup;
+	char parsed_addr_data[32];
+	char parsed_wr_data[256];
+	u32 wr_data, prod_cons;
+	bool is_wr_cmd, is_pf;
+	u16 cmd_addr;
+	u64 dword12;
+
+	/* Dword12 (dword index 1 and 2) contains bits 32..95 of the
+	 * FIFO element.
+	 */
+	dword12 = ((u64)element->dword2 << 32) | element->dword1;
+	is_wr_cmd = GET_FIELD(dword12, IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD);
+	is_pf = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_IS_PF);
+	cmd_addr = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR);
+	source = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_SOURCE);
+	err_type = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE);
+
+	if (source >= OSAL_ARRAY_SIZE(s_igu_fifo_source_strs))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	if (err_type >= OSAL_ARRAY_SIZE(s_igu_fifo_error_strs))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+
+	/* Find address data */
+	for (i = 0; i < OSAL_ARRAY_SIZE(s_igu_fifo_addr_data) && !found_addr;
+	     i++) {
+		const struct igu_fifo_addr_data *curr_addr =
+			&s_igu_fifo_addr_data[i];
+
+		if (cmd_addr >= curr_addr->start_addr && cmd_addr <=
+		    curr_addr->end_addr)
+			found_addr = curr_addr;
+	}
+
+	if (!found_addr)
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+
+	/* Prepare parsed address data */
+	switch (found_addr->type) {
+	case IGU_ADDR_TYPE_MSIX_MEM:
+		sprintf(parsed_addr_data, " vector_num = 0x%x", cmd_addr / 2);
+		break;
+	case IGU_ADDR_TYPE_WRITE_INT_ACK:
+	case IGU_ADDR_TYPE_WRITE_PROD_UPDATE:
+		sprintf(parsed_addr_data,
+			" SB = 0x%x", cmd_addr - found_addr->start_addr);
+		break;
+	default:
+		parsed_addr_data[0] = '\0';
+	}
+
+	if (!is_wr_cmd) {
+		parsed_wr_data[0] = '\0';
+		goto out;
+	}
+
+	/* Prepare parsed write data */
+	wr_data = GET_FIELD(dword12, IGU_FIFO_ELEMENT_DWORD12_WR_DATA);
+	prod_cons = GET_FIELD(wr_data, IGU_FIFO_WR_DATA_PROD_CONS);
+	is_cleanup = GET_FIELD(wr_data, IGU_FIFO_WR_DATA_CMD_TYPE);
+
+	if (source == IGU_SRC_ATTN) {
+		sprintf(parsed_wr_data, "prod: 0x%x, ", prod_cons);
+	} else {
+		if (is_cleanup) {
+			u8 cleanup_val, cleanup_type;
+
+			cleanup_val =
+				GET_FIELD(wr_data,
+					  IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL);
+			cleanup_type =
+			    GET_FIELD(wr_data,
+				      IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE);
+
+			sprintf(parsed_wr_data,
+				"cmd_type: cleanup, cleanup_val: %s, cleanup_type : %d, ",
+				cleanup_val ? "set" : "clear",
+				cleanup_type);
+		} else {
+			u8 update_flag, en_dis_int_for_sb, segment;
+			u8 timer_mask;
+
+			update_flag = GET_FIELD(wr_data,
+						IGU_FIFO_WR_DATA_UPDATE_FLAG);
+			en_dis_int_for_sb =
+				GET_FIELD(wr_data,
+					  IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB);
+			segment = GET_FIELD(wr_data,
+					    IGU_FIFO_WR_DATA_SEGMENT);
+			timer_mask = GET_FIELD(wr_data,
+					       IGU_FIFO_WR_DATA_TIMER_MASK);
+
+			sprintf(parsed_wr_data,
+				"cmd_type: prod/cons update, prod/cons: 0x%x, update_flag: %s, en_dis_int_for_sb : %s, segment : %s, timer_mask = %d, ",
+				prod_cons,
+				update_flag ? "update" : "nop",
+				en_dis_int_for_sb ?
+				(en_dis_int_for_sb == 1 ? "disable" : "nop") :
+				"enable",
+				segment ? "attn" : "regular",
+				timer_mask);
+		}
+	}
+out:
+	/* Add parsed element to parsed buffer */
+	*results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						   *results_offset),
+				   "raw: 0x%01x%08x%08x, %s: %d, source : %s, type : %s, cmd_addr : 0x%x(%s%s), %serror: %s\n",
+				   element->dword2, element->dword1,
+				   element->dword0,
+				   is_pf ? "pf" : "vf",
+				   GET_FIELD(element->dword0,
+					     IGU_FIFO_ELEMENT_DWORD0_FID),
+				   s_igu_fifo_source_strs[source],
+				   is_wr_cmd ? "wr" : "rd",
+				   cmd_addr,
+				   (!is_pf && found_addr->vf_desc)
+				   ? found_addr->vf_desc
+				   : found_addr->desc,
+				   parsed_addr_data,
+				   parsed_wr_data,
+				   s_igu_fifo_error_strs[err_type]);
+
+	return DBG_STATUS_OK;
+}
+
+/* Parses an IGU FIFO dump buffer.
+ * If result_buf is not NULL, the IGU FIFO results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_igu_fifo_dump(u32 *dump_buf,
+					       char *results_buf,
+					       u32 *parsed_results_bytes)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 param_num_val, num_section_params, num_elements;
+	struct igu_fifo_element *elements;
+	enum dbg_status status;
+	u32 results_offset = 0;
+	u8 i;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read igu_fifo_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "igu_fifo_data"))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	if (param_num_val % IGU_FIFO_ELEMENT_DWORDS)
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	num_elements = param_num_val / IGU_FIFO_ELEMENT_DWORDS;
+	elements = (struct igu_fifo_element *)dump_buf;
+
+	/* Decode elements */
+	for (i = 0; i < num_elements; i++) {
+		status = qed_parse_igu_fifo_element(&elements[i],
+						    results_buf,
+						    &results_offset);
+		if (status != DBG_STATUS_OK)
+			return status;
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						  results_offset),
+				  "fifo contained %d elements", num_elements);
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status
+qed_parse_protection_override_dump(u32 *dump_buf,
+				   char *results_buf,
+				   u32 *parsed_results_bytes)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 param_num_val, num_section_params, num_elements;
+	struct protection_override_element *elements;
+	u32 results_offset = 0;
+	u8 i;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read protection_override_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "protection_override_data"))
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+	if (param_num_val % PROTECTION_OVERRIDE_ELEMENT_DWORDS)
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+	num_elements = param_num_val / PROTECTION_OVERRIDE_ELEMENT_DWORDS;
+	elements = (struct protection_override_element *)dump_buf;
+
+	/* Decode elements */
+	for (i = 0; i < num_elements; i++) {
+		u32 address = GET_FIELD(elements[i].data,
+					PROTECTION_OVERRIDE_ELEMENT_ADDRESS) *
+			      PROTECTION_OVERRIDE_ELEMENT_ADDR_FACTOR;
+
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "window %2d, address: 0x%07x, size: %7d regs, read: %d, write: %d, read protection: %-12s, write protection: %-12s\n",
+			    i, address,
+			    (u32)GET_FIELD(elements[i].data,
+				      PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE),
+			    (u32)GET_FIELD(elements[i].data,
+				      PROTECTION_OVERRIDE_ELEMENT_READ),
+			    (u32)GET_FIELD(elements[i].data,
+				      PROTECTION_OVERRIDE_ELEMENT_WRITE),
+			    s_protection_strs[GET_FIELD(elements[i].data,
+				PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION)],
+			    s_protection_strs[GET_FIELD(elements[i].data,
+				PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION)]);
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						  results_offset),
+				  "protection override contained %d elements",
+				  num_elements);
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+/* Parses a FW Asserts dump buffer.
+ * If result_buf is not NULL, the FW Asserts results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_fw_asserts_dump(u32 *dump_buf,
+						 char *results_buf,
+						 u32 *parsed_results_bytes)
+{
+	u32 num_section_params, param_num_val, i, results_offset = 0;
+	const char *param_name, *param_str_val, *section_name;
+	bool last_section_found = false;
+
+	*parsed_results_bytes = 0;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	while (!last_section_found) {
+		dump_buf += qed_read_section_hdr(dump_buf,
+						 &section_name,
+						 &num_section_params);
+		if (!strcmp(section_name, "fw_asserts")) {
+			/* Extract params */
+			const char *storm_letter = NULL;
+			u32 storm_dump_size = 0;
+
+			for (i = 0; i < num_section_params; i++) {
+				dump_buf += qed_read_param(dump_buf,
+							   &param_name,
+							   &param_str_val,
+							   &param_num_val);
+				if (!strcmp(param_name, "storm"))
+					storm_letter = param_str_val;
+				else if (!strcmp(param_name, "size"))
+					storm_dump_size = param_num_val;
+				else
+					return
+					    DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+			}
+
+			if (!storm_letter || !storm_dump_size)
+				return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+
+			/* Print data */
+			results_offset +=
+			    sprintf(qed_get_buf_ptr(results_buf,
+						    results_offset),
+				    "\n%sSTORM_ASSERT: size=%d\n",
+				    storm_letter, storm_dump_size);
+			for (i = 0; i < storm_dump_size; i++, dump_buf++)
+				results_offset +=
+				    sprintf(qed_get_buf_ptr(results_buf,
+							    results_offset),
+					    "%08x\n", *dump_buf);
+		} else if (!strcmp(section_name, "last")) {
+			last_section_found = true;
+		} else {
+			return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+		}
+	}
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+/***************************** Public Functions *******************************/
+
+enum dbg_status qed_dbg_user_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+					 const u8 * const bin_ptr)
+{
+	struct bin_buffer_hdr *buf_hdrs =
+			(struct bin_buffer_hdr *)(osal_uintptr_t)bin_ptr;
+	u8 buf_id;
+
+	/* Convert binary data to debug arrays */
+	for (buf_id = 0; buf_id < MAX_BIN_DBG_BUFFER_TYPE; buf_id++)
+		qed_set_dbg_bin_buf(p_hwfn,
+				    (enum bin_dbg_buffer_type)buf_id,
+				    (const u32 *)(bin_ptr +
+						  buf_hdrs[buf_id].offset),
+						  buf_hdrs[buf_id].length);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_alloc_user_data(__rte_unused struct ecore_hwfn *p_hwfn,
+					void **user_data_ptr)
+{
+	*user_data_ptr = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
+				     sizeof(struct dbg_tools_user_data));
+	if (!(*user_data_ptr))
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	return DBG_STATUS_OK;
+}
+
+const char *qed_dbg_get_status_str(enum dbg_status status)
+{
+	return (status <
+		MAX_DBG_STATUS) ? s_status_str[status] : "Invalid debug status";
+}
+
+enum dbg_status qed_get_idle_chk_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32 num_dumped_dwords,
+						  u32 *results_buf_size)
+{
+	u32 num_errors, num_warnings;
+
+	return qed_parse_idle_chk_dump(p_hwfn,
+				       dump_buf,
+				       num_dumped_dwords,
+				       NULL,
+				       results_buf_size,
+				       &num_errors, &num_warnings);
+}
+
+enum dbg_status qed_print_idle_chk_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf,
+					   u32 *num_errors,
+					   u32 *num_warnings)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_idle_chk_dump(p_hwfn,
+				       dump_buf,
+				       num_dumped_dwords,
+				       results_buf,
+				       &parsed_buf_size,
+				       num_errors, num_warnings);
+}
+
+void qed_dbg_mcp_trace_set_meta_data(struct ecore_hwfn *p_hwfn,
+				     const u32 *meta_buf)
+{
+	struct dbg_tools_user_data *dev_user_data =
+		qed_dbg_get_user_data(p_hwfn);
+
+	dev_user_data->mcp_trace_user_meta_buf = meta_buf;
+}
+
+enum dbg_status
+qed_get_mcp_trace_results_buf_size(struct ecore_hwfn *p_hwfn,
+				   u32 *dump_buf,
+				   __rte_unused u32 num_dumped_dwords,
+				   u32 *results_buf_size)
+{
+	return qed_parse_mcp_trace_dump(p_hwfn,
+					dump_buf, NULL, results_buf_size, true);
+}
+
+enum dbg_status qed_print_mcp_trace_results(struct ecore_hwfn *p_hwfn,
+					    u32 *dump_buf,
+					    __rte_unused u32 num_dumped_dwords,
+					    char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_mcp_trace_dump(p_hwfn,
+					dump_buf,
+					results_buf, &parsed_buf_size, true);
+}
+
+enum dbg_status qed_print_mcp_trace_results_cont(struct ecore_hwfn *p_hwfn,
+						 u32 *dump_buf,
+						 char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_mcp_trace_dump(p_hwfn, dump_buf, results_buf,
+					&parsed_buf_size, false);
+}
+
+enum dbg_status qed_print_mcp_trace_line(struct ecore_hwfn *p_hwfn,
+					 u8 *dump_buf,
+					 u32 num_dumped_bytes,
+					 char *results_buf)
+{
+	u32 parsed_results_bytes;
+
+	return qed_parse_mcp_trace_buf(p_hwfn,
+				       dump_buf,
+				       num_dumped_bytes,
+				       0,
+				       num_dumped_bytes,
+				       results_buf, &parsed_results_bytes);
+}
+
+/* Frees the specified MCP Trace meta data */
+void qed_mcp_trace_free_meta_data(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_user_data *dev_user_data;
+	struct mcp_trace_meta *meta;
+	u32 i;
+
+	dev_user_data = qed_dbg_get_user_data(p_hwfn);
+	meta = &dev_user_data->mcp_trace_meta;
+	if (!meta->is_allocated)
+		return;
+
+	/* Release modules */
+	if (meta->modules) {
+		for (i = 0; i < meta->modules_num; i++)
+			OSAL_FREE(p_hwfn, meta->modules[i]);
+		OSAL_FREE(p_hwfn, meta->modules);
+	}
+
+	/* Release formats */
+	if (meta->formats) {
+		for (i = 0; i < meta->formats_num; i++)
+			OSAL_FREE(p_hwfn, meta->formats[i].format_str);
+		OSAL_FREE(p_hwfn, meta->formats);
+	}
+
+	meta->is_allocated = false;
+}
+
+enum dbg_status
+qed_get_reg_fifo_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
+				  u32 *dump_buf,
+				  __rte_unused u32 num_dumped_dwords,
+				  u32 *results_buf_size)
+{
+	return qed_parse_reg_fifo_dump(dump_buf, NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_reg_fifo_results(__rte_unused struct ecore_hwfn *p_hwfn,
+			   u32 *dump_buf,
+			   __rte_unused u32 num_dumped_dwords,
+			   char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_reg_fifo_dump(dump_buf, results_buf, &parsed_buf_size);
+}
+
+enum dbg_status
+qed_get_igu_fifo_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
+				  u32 *dump_buf,
+				  __rte_unused u32 num_dumped_dwords,
+				  u32 *results_buf_size)
+{
+	return qed_parse_igu_fifo_dump(dump_buf, NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_igu_fifo_results(__rte_unused struct ecore_hwfn *p_hwfn,
+			   u32 *dump_buf,
+			   __rte_unused u32 num_dumped_dwords,
+			   char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_igu_fifo_dump(dump_buf, results_buf, &parsed_buf_size);
+}
+
+enum dbg_status
+qed_get_protection_override_results_buf_size(__rte_unused
+					     struct ecore_hwfn *p_hwfn,
+					     u32 *dump_buf,
+					     __rte_unused u32 num_dumped_dwords,
+					     u32 *results_buf_size)
+{
+	return qed_parse_protection_override_dump(dump_buf,
+						  NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_protection_override_results(__rte_unused struct ecore_hwfn *p_hwfn,
+				      u32 *dump_buf,
+				      __rte_unused u32 num_dumped_dwords,
+				      char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_protection_override_dump(dump_buf,
+						  results_buf,
+						  &parsed_buf_size);
+}
+
+enum dbg_status
+qed_get_fw_asserts_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
+				    u32 *dump_buf,
+				    __rte_unused u32 num_dumped_dwords,
+				    u32 *results_buf_size)
+{
+	return qed_parse_fw_asserts_dump(dump_buf, NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_fw_asserts_results(__rte_unused struct ecore_hwfn *p_hwfn,
+			     u32 *dump_buf,
+			     __rte_unused u32 num_dumped_dwords,
+			     char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_fw_asserts_dump(dump_buf,
+					 results_buf, &parsed_buf_size);
+}
+
+enum dbg_status qed_dbg_parse_attn(struct ecore_hwfn *p_hwfn,
+				   struct dbg_attn_block_result *results)
+{
+	const u32 *block_attn_name_offsets;
+	const char *attn_name_base;
+	const char *block_name;
+	enum dbg_attn_type attn_type;
+	u8 num_regs, i, j;
+
+	num_regs = GET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_NUM_REGS);
+	attn_type = GET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_ATTN_TYPE);
+	block_name = qed_dbg_get_block_name(p_hwfn, results->block_id);
+	if (!block_name)
+		return DBG_STATUS_INVALID_ARGS;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_INDEXES].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_NAME_OFFSETS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	block_attn_name_offsets =
+	    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_NAME_OFFSETS].ptr +
+	    results->names_offset;
+
+	attn_name_base = p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr;
+
+	/* Go over registers with a non-zero attention status */
+	for (i = 0; i < num_regs; i++) {
+		struct dbg_attn_bit_mapping *bit_mapping;
+		struct dbg_attn_reg_result *reg_result;
+		u8 num_reg_attn, bit_idx = 0;
+
+		reg_result = &results->reg_results[i];
+		num_reg_attn = GET_FIELD(reg_result->data,
+					 DBG_ATTN_REG_RESULT_NUM_REG_ATTN);
+		bit_mapping = (struct dbg_attn_bit_mapping *)
+		    p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_INDEXES].ptr +
+		    reg_result->block_attn_offset;
+
+		/* Go over attention status bits */
+		for (j = 0; j < num_reg_attn; j++, bit_idx++) {
+			u16 attn_idx_val = GET_FIELD(bit_mapping[j].data,
+						     DBG_ATTN_BIT_MAPPING_VAL);
+			const char *attn_name, *attn_type_str, *masked_str;
+			u32 attn_name_offset;
+			u32 sts_addr;
+
+			/* Check if bit mask should be advanced (due to unused
+			 * bits).
+			 */
+			if (GET_FIELD(bit_mapping[j].data,
+				      DBG_ATTN_BIT_MAPPING_IS_UNUSED_BIT_CNT)) {
+				bit_idx += (u8)attn_idx_val;
+				continue;
+			}
+
+			/* Check current bit index */
+			if (!(reg_result->sts_val & OSAL_BIT(bit_idx)))
+				continue;
+
+			/* An attention bit with value=1 was found
+			 * Find attention name
+			 */
+			attn_name_offset =
+				block_attn_name_offsets[attn_idx_val];
+			attn_name = attn_name_base + attn_name_offset;
+			attn_type_str =
+				(attn_type ==
+				 ATTN_TYPE_INTERRUPT ? "Interrupt" :
+				 "Parity");
+			masked_str = reg_result->mask_val & OSAL_BIT(bit_idx) ?
+				     " [masked]" : "";
+			sts_addr = GET_FIELD(reg_result->data,
+					     DBG_ATTN_REG_RESULT_STS_ADDRESS);
+			DP_NOTICE(p_hwfn, false,
+				  "%s (%s) : %s [address 0x%08x, bit %d]%s\n",
+				  block_name, attn_type_str, attn_name,
+				  sts_addr * 4, bit_idx, masked_str);
+		}
+	}
+
+	return DBG_STATUS_OK;
+}
+
+/* Wrapper for unifying the idle_chk and mcp_trace api */
+static enum dbg_status
+qed_print_idle_chk_results_wrapper(struct ecore_hwfn *p_hwfn,
+				   u32 *dump_buf,
+				   u32 num_dumped_dwords,
+				   char *results_buf)
+{
+	u32 num_errors, num_warnnings;
+
+	return qed_print_idle_chk_results(p_hwfn, dump_buf, num_dumped_dwords,
+					  results_buf, &num_errors,
+					  &num_warnnings);
+}
+
+/* Feature meta data lookup table */
+static struct {
+	const char *name;
+	enum dbg_status (*get_size)(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt, u32 *size);
+	enum dbg_status (*perform_dump)(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt, u32 *dump_buf,
+					u32 buf_size, u32 *dumped_dwords);
+	enum dbg_status (*print_results)(struct ecore_hwfn *p_hwfn,
+					 u32 *dump_buf, u32 num_dumped_dwords,
+					 char *results_buf);
+	enum dbg_status (*results_buf_size)(struct ecore_hwfn *p_hwfn,
+					    u32 *dump_buf,
+					    u32 num_dumped_dwords,
+					    u32 *results_buf_size);
+} qed_features_lookup[] = {
+	{
+	"grc", qed_dbg_grc_get_dump_buf_size,
+		    qed_dbg_grc_dump, NULL, NULL}, {
+	"idle_chk",
+		    qed_dbg_idle_chk_get_dump_buf_size,
+		    qed_dbg_idle_chk_dump,
+		    qed_print_idle_chk_results_wrapper,
+		    qed_get_idle_chk_results_buf_size}, {
+	"mcp_trace",
+		    qed_dbg_mcp_trace_get_dump_buf_size,
+		    qed_dbg_mcp_trace_dump, qed_print_mcp_trace_results,
+		    qed_get_mcp_trace_results_buf_size}, {
+	"reg_fifo",
+		    qed_dbg_reg_fifo_get_dump_buf_size,
+		    qed_dbg_reg_fifo_dump, qed_print_reg_fifo_results,
+		    qed_get_reg_fifo_results_buf_size}, {
+	"igu_fifo",
+		    qed_dbg_igu_fifo_get_dump_buf_size,
+		    qed_dbg_igu_fifo_dump, qed_print_igu_fifo_results,
+		    qed_get_igu_fifo_results_buf_size}, {
+	"protection_override",
+		    qed_dbg_protection_override_get_dump_buf_size,
+		    qed_dbg_protection_override_dump,
+		    qed_print_protection_override_results,
+		    qed_get_protection_override_results_buf_size}, {
+	"fw_asserts",
+		    qed_dbg_fw_asserts_get_dump_buf_size,
+		    qed_dbg_fw_asserts_dump,
+		    qed_print_fw_asserts_results,
+		    qed_get_fw_asserts_results_buf_size}, {
+	"ilt",
+		    qed_dbg_ilt_get_dump_buf_size,
+		    qed_dbg_ilt_dump, NULL, NULL},};
+
+#define QED_RESULTS_BUF_MIN_SIZE 16
+/* Generic function for decoding debug feature info */
+static enum dbg_status format_feature(struct ecore_hwfn *p_hwfn,
+				      enum ecore_dbg_features feature_idx)
+{
+	struct ecore_dbg_feature *feature =
+	    &p_hwfn->p_dev->dbg_params.features[feature_idx];
+	u32 text_size_bytes, null_char_pos, i;
+	enum dbg_status rc;
+	char *text_buf;
+
+	/* Check if feature supports formatting capability */
+	if (!qed_features_lookup[feature_idx].results_buf_size)
+		return DBG_STATUS_OK;
+
+	/* Obtain size of formatted output */
+	rc = qed_features_lookup[feature_idx].results_buf_size(p_hwfn,
+						(u32 *)feature->dump_buf,
+						feature->dumped_dwords,
+						&text_size_bytes);
+	if (rc != DBG_STATUS_OK)
+		return rc;
+
+	/* Make sure that the allocated size is a multiple of dword (4 bytes) */
+	null_char_pos = text_size_bytes - 1;
+	text_size_bytes = (text_size_bytes + 3) & ~0x3;
+
+	if (text_size_bytes < QED_RESULTS_BUF_MIN_SIZE) {
+		DP_NOTICE(p_hwfn->p_dev, false,
+			  "formatted size of feature was too small %d. Aborting\n",
+			  text_size_bytes);
+		return DBG_STATUS_INVALID_ARGS;
+	}
+
+	/* Allocate temp text buf */
+	text_buf = OSAL_VZALLOC(p_hwfn, text_size_bytes);
+	if (!text_buf) {
+		DP_NOTICE(p_hwfn->p_dev, false,
+			  "failed to allocate text buffer. Aborting\n");
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+	}
+
+	/* Decode feature opcodes to string on temp buf */
+	rc = qed_features_lookup[feature_idx].print_results(p_hwfn,
+						(u32 *)feature->dump_buf,
+						feature->dumped_dwords,
+						text_buf);
+	if (rc != DBG_STATUS_OK) {
+		OSAL_VFREE(p_hwfn, text_buf);
+		return rc;
+	}
+
+	/* Replace the original null character with a '\n' character.
+	 * The bytes that were added as a result of the dword alignment are also
+	 * padded with '\n' characters.
+	 */
+	for (i = null_char_pos; i < text_size_bytes; i++)
+		text_buf[i] = '\n';
+
+
+	/* Free the old dump_buf and point the dump_buf to the newly allocagted
+	 * and formatted text buffer.
+	 */
+	OSAL_VFREE(p_hwfn, feature->dump_buf);
+	feature->dump_buf = (u8 *)text_buf;
+	feature->buf_size = text_size_bytes;
+	feature->dumped_dwords = text_size_bytes / 4;
+	return rc;
+}
+
+#define MAX_DBG_FEATURE_SIZE_DWORDS	0x3FFFFFFF
+
+/* Generic function for performing the dump of a debug feature. */
+static enum dbg_status qed_dbg_dump(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    enum ecore_dbg_features feature_idx)
+{
+	struct ecore_dbg_feature *feature =
+	    &p_hwfn->p_dev->dbg_params.features[feature_idx];
+	u32 buf_size_dwords;
+	enum dbg_status rc;
+
+	DP_NOTICE(p_hwfn->p_dev, false, "Collecting a debug feature [\"%s\"]\n",
+		  qed_features_lookup[feature_idx].name);
+
+	/* Dump_buf was already allocated need to free (this can happen if dump
+	 * was called but file was never read).
+	 * We can't use the buffer as is since size may have changed.
+	 */
+	if (feature->dump_buf) {
+		OSAL_VFREE(p_hwfn, feature->dump_buf);
+		feature->dump_buf = NULL;
+	}
+
+	/* Get buffer size from hsi, allocate accordingly, and perform the
+	 * dump.
+	 */
+	rc = qed_features_lookup[feature_idx].get_size(p_hwfn, p_ptt,
+						       &buf_size_dwords);
+	if (rc != DBG_STATUS_OK && rc != DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
+		return rc;
+
+	if (buf_size_dwords > MAX_DBG_FEATURE_SIZE_DWORDS) {
+		feature->buf_size = 0;
+		DP_NOTICE(p_hwfn->p_dev, false,
+			  "Debug feature [\"%s\"] size (0x%x dwords) exceeds maximum size (0x%x dwords)\n",
+			  qed_features_lookup[feature_idx].name,
+			  buf_size_dwords, MAX_DBG_FEATURE_SIZE_DWORDS);
+
+		return DBG_STATUS_OK;
+	}
+
+	feature->buf_size = buf_size_dwords * sizeof(u32);
+	feature->dump_buf = OSAL_ZALLOC(p_hwfn, GFP_KERNEL, feature->buf_size);
+	if (!feature->dump_buf)
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	rc = qed_features_lookup[feature_idx].perform_dump(p_hwfn, p_ptt,
+					(u32 *)feature->dump_buf,
+					feature->buf_size / sizeof(u32),
+					&feature->dumped_dwords);
+
+	/* If mcp is stuck we get DBG_STATUS_NVRAM_GET_IMAGE_FAILED error.
+	 * In this case the buffer holds valid binary data, but we wont able
+	 * to parse it (since parsing relies on data in NVRAM which is only
+	 * accessible when MFW is responsive). skip the formatting but return
+	 * success so that binary data is provided.
+	 */
+	if (rc == DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
+		return DBG_STATUS_OK;
+
+	if (rc != DBG_STATUS_OK)
+		return rc;
+
+	/* Format output */
+	rc = format_feature(p_hwfn, feature_idx);
+	return rc;
+}
+
+int qed_dbg_grc(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_GRC, num_dumped_bytes);
+}
+
+int qed_dbg_grc_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_GRC);
+}
+
+int
+qed_dbg_idle_chk(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_IDLE_CHK,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_idle_chk_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_IDLE_CHK);
+}
+
+int
+qed_dbg_reg_fifo(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_REG_FIFO,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_reg_fifo_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_REG_FIFO);
+}
+
+int
+qed_dbg_igu_fifo(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_IGU_FIFO,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_igu_fifo_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_IGU_FIFO);
+}
+
+static int qed_dbg_nvm_image_length(struct ecore_hwfn *p_hwfn,
+				    enum ecore_nvm_images image_id, u32 *length)
+{
+	struct ecore_nvm_image_att image_att;
+	int rc;
+
+	*length = 0;
+	rc = ecore_mcp_get_nvm_image_att(p_hwfn, image_id, &image_att);
+	if (rc)
+		return rc;
+
+	*length = image_att.length;
+
+	return rc;
+}
+
+int qed_dbg_protection_override(struct ecore_dev *edev, void *buffer,
+				u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_PROTECTION_OVERRIDE,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_protection_override_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_PROTECTION_OVERRIDE);
+}
+
+int qed_dbg_fw_asserts(struct ecore_dev *edev, void *buffer,
+		       u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_FW_ASSERTS,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_fw_asserts_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_FW_ASSERTS);
+}
+
+int qed_dbg_ilt(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_ILT, num_dumped_bytes);
+}
+
+int qed_dbg_ilt_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_ILT);
+}
+
+int qed_dbg_mcp_trace(struct ecore_dev *edev, void *buffer,
+		      u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_MCP_TRACE,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_mcp_trace_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_MCP_TRACE);
+}
+
+/* Defines the amount of bytes allocated for recording the length of debug
+ * feature buffer.
+ */
+#define REGDUMP_HEADER_SIZE			sizeof(u32)
+#define REGDUMP_HEADER_SIZE_SHIFT		0
+#define REGDUMP_HEADER_SIZE_MASK		0xffffff
+#define REGDUMP_HEADER_FEATURE_SHIFT		24
+#define REGDUMP_HEADER_FEATURE_MASK		0x3f
+#define REGDUMP_HEADER_OMIT_ENGINE_SHIFT	30
+#define REGDUMP_HEADER_OMIT_ENGINE_MASK		0x1
+#define REGDUMP_HEADER_ENGINE_SHIFT		31
+#define REGDUMP_HEADER_ENGINE_MASK		0x1
+#define REGDUMP_MAX_SIZE			0x1000000
+#define ILT_DUMP_MAX_SIZE			(1024 * 1024 * 15)
+
+enum debug_print_features {
+	OLD_MODE = 0,
+	IDLE_CHK = 1,
+	GRC_DUMP = 2,
+	MCP_TRACE = 3,
+	REG_FIFO = 4,
+	PROTECTION_OVERRIDE = 5,
+	IGU_FIFO = 6,
+	PHY = 7,
+	FW_ASSERTS = 8,
+	NVM_CFG1 = 9,
+	DEFAULT_CFG = 10,
+	NVM_META = 11,
+	MDUMP = 12,
+	ILT_DUMP = 13,
+};
+
+static u32 qed_calc_regdump_header(struct ecore_dev *edev,
+				   enum debug_print_features feature,
+				   int engine, u32 feature_size, u8 omit_engine)
+{
+	u32 res = 0;
+
+	SET_FIELD(res, REGDUMP_HEADER_SIZE, feature_size);
+	if (res != feature_size)
+		DP_NOTICE(edev, false,
+			  "Feature %d is too large (size 0x%x) and will corrupt the dump\n",
+			  feature, feature_size);
+
+	SET_FIELD(res, REGDUMP_HEADER_FEATURE, feature);
+	SET_FIELD(res, REGDUMP_HEADER_OMIT_ENGINE, omit_engine);
+	SET_FIELD(res, REGDUMP_HEADER_ENGINE, engine);
+
+	return res;
+}
+
+int qed_dbg_all_data(struct ecore_dev *edev, void *buffer)
+{
+	u8 cur_engine, omit_engine = 0, org_engine;
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	int grc_params[MAX_DBG_GRC_PARAMS], i;
+	u32 offset = 0, feature_size;
+	int rc;
+
+	for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
+		grc_params[i] = dev_data->grc.param_val[i];
+
+	if (!ECORE_IS_CMT(edev))
+		omit_engine = 1;
+
+	OSAL_MUTEX_ACQUIRE(&edev->dbg_lock);
+
+	org_engine = qed_get_debug_engine(edev);
+	for (cur_engine = 0; cur_engine < edev->num_hwfns; cur_engine++) {
+		/* Collect idle_chks and grcDump for each hw function */
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+			   "obtaining idle_chk and grcdump for current engine\n");
+		qed_set_debug_engine(edev, cur_engine);
+
+		/* First idle_chk */
+		rc = qed_dbg_idle_chk(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, IDLE_CHK, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_idle_chk failed. rc = %d\n", rc);
+		}
+
+		/* Second idle_chk */
+		rc = qed_dbg_idle_chk(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, IDLE_CHK, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_idle_chk failed. rc = %d\n", rc);
+		}
+
+		/* reg_fifo dump */
+		rc = qed_dbg_reg_fifo(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, REG_FIFO, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_reg_fifo failed. rc = %d\n", rc);
+		}
+
+		/* igu_fifo dump */
+		rc = qed_dbg_igu_fifo(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, IGU_FIFO, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_igu_fifo failed. rc = %d", rc);
+		}
+
+		/* protection_override dump */
+		rc = qed_dbg_protection_override(edev, (u8 *)buffer + offset +
+						 REGDUMP_HEADER_SIZE,
+						 &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, PROTECTION_OVERRIDE,
+						    cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev,
+			       "qed_dbg_protection_override failed. rc = %d\n",
+			       rc);
+		}
+
+		/* fw_asserts dump */
+		rc = qed_dbg_fw_asserts(edev, (u8 *)buffer + offset +
+					REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, FW_ASSERTS,
+						    cur_engine, feature_size,
+						    omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_fw_asserts failed. rc = %d\n",
+			       rc);
+		}
+
+		/* GRC dump - must be last because when mcp stuck it will
+		 * clutter idle_chk, reg_fifo, ...
+		 */
+		for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
+			dev_data->grc.param_val[i] = grc_params[i];
+
+		rc = qed_dbg_grc(edev, (u8 *)buffer + offset +
+				 REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, GRC_DUMP,
+						    cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_grc failed. rc = %d", rc);
+		}
+	}
+
+	qed_set_debug_engine(edev, org_engine);
+
+	/* mcp_trace */
+	rc = qed_dbg_mcp_trace(edev, (u8 *)buffer + offset +
+			       REGDUMP_HEADER_SIZE, &feature_size);
+	if (!rc) {
+		*(u32 *)((u8 *)buffer + offset) =
+		    qed_calc_regdump_header(edev, MCP_TRACE, cur_engine,
+					    feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+	} else {
+		DP_ERR(edev, "qed_dbg_mcp_trace failed. rc = %d\n", rc);
+	}
+
+	OSAL_MUTEX_RELEASE(&edev->dbg_lock);
+
+	return 0;
+}
+
+int qed_dbg_all_data_size(struct ecore_dev *edev)
+{
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	u32 regs_len = 0, image_len = 0, ilt_len = 0, total_ilt_len = 0;
+	u8 cur_engine, org_engine;
+
+	edev->disable_ilt_dump = false;
+	org_engine = qed_get_debug_engine(edev);
+	for (cur_engine = 0; cur_engine < edev->num_hwfns; cur_engine++) {
+		/* Engine specific */
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+			   "calculating idle_chk and grcdump register length for current engine\n");
+		qed_set_debug_engine(edev, cur_engine);
+		regs_len += REGDUMP_HEADER_SIZE + qed_dbg_idle_chk_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_idle_chk_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_grc_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_reg_fifo_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_igu_fifo_size(edev) +
+			    REGDUMP_HEADER_SIZE +
+			    qed_dbg_protection_override_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_fw_asserts_size(edev);
+
+		ilt_len = REGDUMP_HEADER_SIZE + qed_dbg_ilt_size(edev);
+		if (ilt_len < ILT_DUMP_MAX_SIZE) {
+			total_ilt_len += ilt_len;
+			regs_len += ilt_len;
+		}
+	}
+
+	qed_set_debug_engine(edev, org_engine);
+
+	/* Engine common */
+	regs_len += REGDUMP_HEADER_SIZE + qed_dbg_mcp_trace_size(edev);
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_NVM_CFG1, &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_DEFAULT_CFG,
+				 &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_NVM_META, &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_MDUMP, &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+
+	if (regs_len > REGDUMP_MAX_SIZE) {
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+			   "Dump exceeds max size 0x%x, disable ILT dump\n",
+			   REGDUMP_MAX_SIZE);
+		edev->disable_ilt_dump = true;
+		regs_len -= total_ilt_len;
+	}
+
+	return regs_len;
+}
+
+int qed_dbg_feature(struct ecore_dev *edev, void *buffer,
+		    enum ecore_dbg_features feature, u32 *num_dumped_bytes)
+{
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	struct ecore_dbg_feature *qed_feature =
+		&edev->dbg_params.features[feature];
+	enum dbg_status dbg_rc;
+	struct ecore_ptt *p_ptt;
+	int rc = 0;
+
+	/* Acquire ptt */
+	p_ptt = ecore_ptt_acquire(p_hwfn);
+	if (!p_ptt)
+		return -EINVAL;
+
+	/* Get dump */
+	dbg_rc = qed_dbg_dump(p_hwfn, p_ptt, feature);
+	if (dbg_rc != DBG_STATUS_OK) {
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG, "%s\n",
+			   qed_dbg_get_status_str(dbg_rc));
+		*num_dumped_bytes = 0;
+		rc = -EINVAL;
+		goto out;
+	}
+
+	DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+		   "copying debug feature to external buffer\n");
+	memcpy(buffer, qed_feature->dump_buf, qed_feature->buf_size);
+	*num_dumped_bytes = edev->dbg_params.features[feature].dumped_dwords *
+			    4;
+
+out:
+	ecore_ptt_release(p_hwfn, p_ptt);
+	return rc;
+}
+
+int
+qed_dbg_feature_size(struct ecore_dev *edev, enum ecore_dbg_features feature)
+{
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	struct ecore_dbg_feature *qed_feature = &edev->dbg_features[feature];
+	struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
+	u32 buf_size_dwords;
+	enum dbg_status rc;
+
+	if (!p_ptt)
+		return -EINVAL;
+
+	rc = qed_features_lookup[feature].get_size(p_hwfn, p_ptt,
+						   &buf_size_dwords);
+	if (rc != DBG_STATUS_OK)
+		buf_size_dwords = 0;
+
+	/* Feature will not be dumped if it exceeds maximum size */
+	if (buf_size_dwords > MAX_DBG_FEATURE_SIZE_DWORDS)
+		buf_size_dwords = 0;
+
+	ecore_ptt_release(p_hwfn, p_ptt);
+	qed_feature->buf_size = buf_size_dwords * sizeof(u32);
+	return qed_feature->buf_size;
+}
+
+u8 qed_get_debug_engine(struct ecore_dev *edev)
+{
+	return edev->dbg_params.engine_for_debug;
+}
+
+void qed_set_debug_engine(struct ecore_dev *edev, int engine_number)
+{
+	DP_VERBOSE(edev, ECORE_MSG_DEBUG, "set debug engine to %d\n",
+		   engine_number);
+	edev->dbg_params.engine_for_debug = engine_number;
+}
+
+void qed_dbg_pf_init(struct ecore_dev *edev)
+{
+	const u8 *dbg_values = NULL;
+	int i;
+
+	PMD_INIT_FUNC_TRACE(edev);
+
+	OSAL_MUTEX_INIT(&edev->dbg_lock);
+
+	/* Sync ver with debugbus qed code */
+	qed_dbg_set_app_ver(TOOLS_VERSION);
+
+	/* Debug values are after init values.
+	 * The offset is the first dword of the file.
+	 */
+	/* TBD: change hardcoded value to offset from FW file */
+	dbg_values = (const u8 *)edev->firmware + 1337296;
+
+	for_each_hwfn(edev, i) {
+		qed_dbg_set_bin_ptr(&edev->hwfns[i], dbg_values);
+		qed_dbg_user_set_bin_ptr(&edev->hwfns[i], dbg_values);
+	}
+
+	/* Set the hwfn to be 0 as default */
+	edev->dbg_params.engine_for_debug = 0;
+}
+
+void qed_dbg_pf_exit(struct ecore_dev *edev)
+{
+	struct ecore_dbg_feature *feature = NULL;
+	enum ecore_dbg_features feature_idx;
+
+	PMD_INIT_FUNC_TRACE(edev);
+
+	/* debug features' buffers may be allocated if debug feature was used
+	 * but dump wasn't called
+	 */
+	for (feature_idx = 0; feature_idx < DBG_FEATURE_NUM; feature_idx++) {
+		feature = &edev->dbg_features[feature_idx];
+		if (feature->dump_buf) {
+			OSAL_VFREE(edev, feature->dump_buf);
+			feature->dump_buf = NULL;
+		}
+	}
+
+	OSAL_MUTEX_DEALLOC(&edev->dbg_lock);
+}
diff --git a/drivers/net/qede/qede_debug.h b/drivers/net/qede/qede_debug.h
new file mode 100644
index 000000000..93e1bd710
--- /dev/null
+++ b/drivers/net/qede/qede_debug.h
@@ -0,0 +1,759 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Marvell Semiconductor Inc.
+ * All rights reserved.
+ * www.marvell.com
+ */
+
+#ifndef _QED_DEBUG_H
+#define _QED_DEBUG_H
+
+/* Forward Declaration */
+struct ecore_dev;
+enum ecore_dbg_features;
+
+int qed_dbg_grc(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes);
+int qed_dbg_grc_size(struct ecore_dev *edev);
+int qed_dbg_idle_chk(struct ecore_dev *edev, void *buffer,
+		     u32 *num_dumped_bytes);
+int qed_dbg_idle_chk_size(struct ecore_dev *edev);
+int qed_dbg_reg_fifo(struct ecore_dev *edev, void *buffer,
+		     u32 *num_dumped_bytes);
+int qed_dbg_reg_fifo_size(struct ecore_dev *edev);
+int qed_dbg_igu_fifo(struct ecore_dev *edev, void *buffer,
+		     u32 *num_dumped_bytes);
+int qed_dbg_igu_fifo_size(struct ecore_dev *edev);
+int qed_dbg_protection_override(struct ecore_dev *edev, void *buffer,
+				u32 *num_dumped_bytes);
+int qed_dbg_protection_override_size(struct ecore_dev *edev);
+int qed_dbg_fw_asserts(struct ecore_dev *edev, void *buffer,
+		       u32 *num_dumped_bytes);
+int qed_dbg_fw_asserts_size(struct ecore_dev *edev);
+int qed_dbg_ilt(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes);
+int qed_dbg_ilt_size(struct ecore_dev *edev);
+int qed_dbg_mcp_trace(struct ecore_dev *edev, void *buffer,
+		      u32 *num_dumped_bytes);
+int qed_dbg_mcp_trace_size(struct ecore_dev *edev);
+int qed_dbg_all_data(struct ecore_dev *edev, void *buffer);
+int qed_dbg_all_data_size(struct ecore_dev *edev);
+u8 qed_get_debug_engine(struct ecore_dev *edev);
+void qed_set_debug_engine(struct ecore_dev *edev, int engine_number);
+int qed_dbg_feature(struct ecore_dev *edev, void *buffer,
+		    enum ecore_dbg_features feature, u32 *num_dumped_bytes);
+int
+qed_dbg_feature_size(struct ecore_dev *edev, enum ecore_dbg_features feature);
+
+void qed_dbg_pf_init(struct ecore_dev *edev);
+void qed_dbg_pf_exit(struct ecore_dev *edev);
+
+/***************************** Public Functions *******************************/
+
+/**
+ * @brief qed_dbg_set_bin_ptr - Sets a pointer to the binary data with debug
+ *	arrays.
+ *
+ * @param p_hwfn -	    HW device data
+ * @param bin_ptr - a pointer to the binary data with debug arrays.
+ */
+enum dbg_status qed_dbg_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+				    const u8 * const bin_ptr);
+
+/**
+ * @brief qed_dbg_set_app_ver - Sets the version of the calling app.
+ *
+ * The application should call this function with the TOOLS_VERSION
+ * it compiles with. Must be called before all other debug functions.
+ *
+ * @return error if one of the following holds:
+ *      - the specified app version is not supported
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_set_app_ver(u32 ver);
+
+/**
+ * @brief qed_read_regs - Reads registers into a buffer (using GRC).
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf - Destination buffer.
+ * @param addr - Source GRC address in dwords.
+ * @param len - Number of registers to read.
+ */
+void qed_read_regs(struct ecore_hwfn *p_hwfn,
+		   struct ecore_ptt *p_ptt, u32 *buf, u32 addr, u32 len);
+
+/**
+ * @brief qed_read_fw_info - Reads FW info from the chip.
+ *
+ * The FW info contains FW-related information, such as the FW version,
+ * FW image (main/L2B/kuku), FW timestamp, etc.
+ * The FW info is read from the internal RAM of the first Storm that is not in
+ * reset.
+ *
+ * @param p_hwfn -	    HW device data
+ * @param p_ptt -	    Ptt window used for writing the registers.
+ * @param fw_info -	Out: a pointer to write the FW info into.
+ *
+ * @return true if the FW info was read successfully from one of the Storms,
+ * or false if all Storms are in reset.
+ */
+bool qed_read_fw_info(struct ecore_hwfn *p_hwfn,
+		      struct ecore_ptt *p_ptt, struct fw_info *fw_info);
+/**
+ * @brief qed_dbg_grc_config - Sets the value of a GRC parameter.
+ *
+ * @param p_hwfn -	HW device data
+ * @param grc_param -	GRC parameter
+ * @param val -		Value to set.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- grc_param is invalid
+ *	- val is outside the allowed boundaries
+ */
+enum dbg_status qed_dbg_grc_config(struct ecore_hwfn *p_hwfn,
+				   enum dbg_grc_params grc_param, u32 val);
+
+/**
+ * @brief qed_dbg_grc_set_params_default - Reverts all GRC parameters to their
+ *	default value.
+ *
+ * @param p_hwfn		- HW device data
+ */
+void qed_dbg_grc_set_params_default(struct ecore_hwfn *p_hwfn);
+/**
+ * @brief qed_dbg_grc_get_dump_buf_size - Returns the required buffer size for
+ *	GRC Dump.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for the GRC Dump
+ *	data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_grc_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size);
+
+/**
+ * @brief qed_dbg_grc_dump - Dumps GRC data into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the collected GRC data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified dump buffer is too small
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_grc_dump(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf,
+				 u32 buf_size_in_dwords,
+				 u32 *num_dumped_dwords);
+/**
+ * @brief qed_dbg_idle_chk_get_dump_buf_size - Returns the required buffer size
+ *	for idle check results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for the idle check
+ *	data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_idle_chk_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size);
+
+/**
+ * @brief qed_dbg_idle_chk_dump - Performs idle check and writes the results
+ *	into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the idle check data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_mcp_trace_get_dump_buf_size - Returns the required buffer size
+ *	for mcp trace results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for mcp trace data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the trace data in MCP scratchpad contain an invalid signature
+ *	- the bundle ID in NVRAM is invalid
+ *	- the trace meta data cannot be found (in NVRAM or image file)
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_mcp_trace_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						    struct ecore_ptt *p_ptt,
+						    u32 *buf_size);
+
+/**
+ * @brief qed_dbg_mcp_trace_dump - Performs mcp trace and writes the results
+ *	into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the mcp trace data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- the trace data in MCP scratchpad contain an invalid signature
+ *	- the bundle ID in NVRAM is invalid
+ *	- the trace meta data cannot be found (in NVRAM or image file)
+ *	- the trace meta data cannot be read (from NVRAM or image file)
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+				       struct ecore_ptt *p_ptt,
+				       u32 *dump_buf,
+				       u32 buf_size_in_dwords,
+				       u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_reg_fifo_get_dump_buf_size - Returns the required buffer size
+ *	for grc trace fifo results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for reg fifo data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_reg_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size);
+
+/**
+ * @brief qed_dbg_reg_fifo_dump - Reads the reg fifo and writes the results into
+ *	the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the reg fifo data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- DMAE transaction failed
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_igu_fifo_get_dump_buf_size - Returns the required buffer size
+ *	for the IGU fifo results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for the IGU fifo
+ *	data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_igu_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size);
+
+/**
+ * @brief qed_dbg_igu_fifo_dump - Reads the IGU fifo and writes the results into
+ *	the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the IGU fifo data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- DMAE transaction failed
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_protection_override_get_dump_buf_size - Returns the required
+ *	buffer size for protection override window results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for protection
+ *	override data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status
+qed_dbg_protection_override_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size);
+/**
+ * @brief qed_dbg_protection_override_dump - Reads protection override window
+ *	entries and writes the results into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the protection override data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- DMAE transaction failed
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_protection_override_dump(struct ecore_hwfn *p_hwfn,
+						 struct ecore_ptt *p_ptt,
+						 u32 *dump_buf,
+						 u32 buf_size_in_dwords,
+						 u32 *num_dumped_dwords);
+/**
+ * @brief qed_dbg_fw_asserts_get_dump_buf_size - Returns the required buffer
+ *	size for FW Asserts results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for FW Asserts data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_fw_asserts_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						     struct ecore_ptt *p_ptt,
+						     u32 *buf_size);
+/**
+ * @brief qed_dbg_fw_asserts_dump - Reads the FW Asserts and writes the results
+ *	into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the FW Asserts data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf,
+					u32 buf_size_in_dwords,
+					u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_read_attn - Reads the attention registers of the specified
+ * block and type, and writes the results into the specified buffer.
+ *
+ * @param p_hwfn -	 HW device data
+ * @param p_ptt -	 Ptt window used for writing the registers.
+ * @param block -	 Block ID.
+ * @param attn_type -	 Attention type.
+ * @param clear_status - Indicates if the attention status should be cleared.
+ * @param results -	 OUT: Pointer to write the read results into
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_read_attn(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  enum block_id block,
+				  enum dbg_attn_type attn_type,
+				  bool clear_status,
+				  struct dbg_attn_block_result *results);
+
+/**
+ * @brief qed_dbg_print_attn - Prints attention registers values in the
+ *	specified results struct.
+ *
+ * @param p_hwfn
+ * @param results - Pointer to the attention read results
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_print_attn(struct ecore_hwfn *p_hwfn,
+				   struct dbg_attn_block_result *results);
+
+/******************************* Data Types **********************************/
+
+struct mcp_trace_format {
+	u32 data;
+#define MCP_TRACE_FORMAT_MODULE_MASK	0x0000ffff
+#define MCP_TRACE_FORMAT_MODULE_OFFSET	0
+#define MCP_TRACE_FORMAT_LEVEL_MASK	0x00030000
+#define MCP_TRACE_FORMAT_LEVEL_OFFSET	16
+#define MCP_TRACE_FORMAT_P1_SIZE_MASK	0x000c0000
+#define MCP_TRACE_FORMAT_P1_SIZE_OFFSET 18
+#define MCP_TRACE_FORMAT_P2_SIZE_MASK	0x00300000
+#define MCP_TRACE_FORMAT_P2_SIZE_OFFSET 20
+#define MCP_TRACE_FORMAT_P3_SIZE_MASK	0x00c00000
+#define MCP_TRACE_FORMAT_P3_SIZE_OFFSET 22
+#define MCP_TRACE_FORMAT_LEN_MASK	0xff000000
+#define MCP_TRACE_FORMAT_LEN_OFFSET	24
+
+	char *format_str;
+};
+
+/* MCP Trace Meta data structure */
+struct mcp_trace_meta {
+	u32 modules_num;
+	char **modules;
+	u32 formats_num;
+	struct mcp_trace_format *formats;
+	bool is_allocated;
+};
+
+/* Debug Tools user data */
+struct dbg_tools_user_data {
+	struct mcp_trace_meta mcp_trace_meta;
+	const u32 *mcp_trace_user_meta_buf;
+};
+
+/******************************** Constants **********************************/
+
+#define MAX_NAME_LEN	16
+
+/***************************** Public Functions *******************************/
+
+/**
+ * @brief qed_dbg_user_set_bin_ptr - Sets a pointer to the binary data with
+ *	debug arrays.
+ *
+ * @param p_hwfn - HW device data
+ * @param bin_ptr - a pointer to the binary data with debug arrays.
+ */
+enum dbg_status qed_dbg_user_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+					 const u8 * const bin_ptr);
+
+/**
+ * @brief qed_dbg_alloc_user_data - Allocates user debug data.
+ *
+ * @param p_hwfn -		 HW device data
+ * @param user_data_ptr - OUT: a pointer to the allocated memory.
+ */
+enum dbg_status qed_dbg_alloc_user_data(struct ecore_hwfn *p_hwfn,
+					void **user_data_ptr);
+
+/**
+ * @brief qed_dbg_get_status_str - Returns a string for the specified status.
+ *
+ * @param status - a debug status code.
+ *
+ * @return a string for the specified status
+ */
+const char *qed_dbg_get_status_str(enum dbg_status status);
+
+/**
+ * @brief qed_get_idle_chk_results_buf_size - Returns the required buffer size
+ *	for idle check results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - idle check dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_idle_chk_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32  num_dumped_dwords,
+						  u32 *results_buf_size);
+/**
+ * @brief qed_print_idle_chk_results - Prints idle check results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - idle check dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the idle check results.
+ * @param num_errors - OUT: number of errors found in idle check.
+ * @param num_warnings - OUT: number of warnings found in idle check.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_idle_chk_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf,
+					   u32 *num_errors,
+					   u32 *num_warnings);
+
+/**
+ * @brief qed_dbg_mcp_trace_set_meta_data - Sets the MCP Trace meta data.
+ *
+ * Needed in case the MCP Trace dump doesn't contain the meta data (e.g. due to
+ * no NVRAM access).
+ *
+ * @param data - pointer to MCP Trace meta data
+ * @param size - size of MCP Trace meta data in dwords
+ */
+void qed_dbg_mcp_trace_set_meta_data(struct ecore_hwfn *p_hwfn,
+				     const u32 *meta_buf);
+
+/**
+ * @brief qed_get_mcp_trace_results_buf_size - Returns the required buffer size
+ *	for MCP Trace results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - MCP Trace dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_mcp_trace_results_buf_size(struct ecore_hwfn *p_hwfn,
+						   u32 *dump_buf,
+						   u32 num_dumped_dwords,
+						   u32 *results_buf_size);
+
+/**
+ * @brief qed_print_mcp_trace_results - Prints MCP Trace results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - mcp trace dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the mcp trace results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_mcp_trace_results(struct ecore_hwfn *p_hwfn,
+					    u32 *dump_buf,
+					    u32 num_dumped_dwords,
+					    char *results_buf);
+
+/**
+ * @brief qed_print_mcp_trace_results_cont - Prints MCP Trace results, and
+ * keeps the MCP trace meta data allocated, to support continuous MCP Trace
+ * parsing. After the continuous parsing ends, mcp_trace_free_meta_data should
+ * be called to free the meta data.
+ *
+ * @param p_hwfn -	      HW device data
+ * @param dump_buf -	      mcp trace dump buffer, starting from the header.
+ * @param results_buf -	      buffer for printing the mcp trace results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_mcp_trace_results_cont(struct ecore_hwfn *p_hwfn,
+						 u32 *dump_buf,
+						 char *results_buf);
+
+/**
+ * @brief print_mcp_trace_line - Prints MCP Trace results for a single line
+ *
+ * @param p_hwfn -	      HW device data
+ * @param dump_buf -	      mcp trace dump buffer, starting from the header.
+ * @param num_dumped_bytes -  number of bytes that were dumped.
+ * @param results_buf -	      buffer for printing the mcp trace results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_mcp_trace_line(struct ecore_hwfn *p_hwfn,
+					 u8 *dump_buf,
+					 u32 num_dumped_bytes,
+					 char *results_buf);
+
+/**
+ * @brief mcp_trace_free_meta_data - Frees the MCP Trace meta data.
+ * Should be called after continuous MCP Trace parsing.
+ *
+ * @param p_hwfn - HW device data
+ */
+void qed_mcp_trace_free_meta_data(struct ecore_hwfn *p_hwfn);
+
+/**
+ * @brief qed_get_reg_fifo_results_buf_size - Returns the required buffer size
+ *	for reg_fifo results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - reg fifo dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_reg_fifo_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32 num_dumped_dwords,
+						  u32 *results_buf_size);
+
+/**
+ * @brief qed_print_reg_fifo_results - Prints reg fifo results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - reg fifo dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the reg fifo results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_reg_fifo_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf);
+
+/**
+ * @brief qed_get_igu_fifo_results_buf_size - Returns the required buffer size
+ *	for igu_fifo results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - IGU fifo dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_igu_fifo_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32 num_dumped_dwords,
+						  u32 *results_buf_size);
+
+/**
+ * @brief qed_print_igu_fifo_results - Prints IGU fifo results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - IGU fifo dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the IGU fifo results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_igu_fifo_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf);
+
+/**
+ * @brief qed_get_protection_override_results_buf_size - Returns the required
+ *	buffer size for protection override results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - protection override dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status
+qed_get_protection_override_results_buf_size(struct ecore_hwfn *p_hwfn,
+					     u32 *dump_buf,
+					     u32 num_dumped_dwords,
+					     u32 *results_buf_size);
+
+/**
+ * @brief qed_print_protection_override_results - Prints protection override
+ *	results.
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - protection override dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the reg fifo results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_protection_override_results(struct ecore_hwfn *p_hwfn,
+						      u32 *dump_buf,
+						      u32 num_dumped_dwords,
+						      char *results_buf);
+
+/**
+ * @brief qed_get_fw_asserts_results_buf_size - Returns the required buffer size
+ *	for FW Asserts results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - FW Asserts dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_fw_asserts_results_buf_size(struct ecore_hwfn *p_hwfn,
+						    u32 *dump_buf,
+						    u32 num_dumped_dwords,
+						    u32 *results_buf_size);
+
+/**
+ * @brief qed_print_fw_asserts_results - Prints FW Asserts results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - FW Asserts dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the FW Asserts results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_fw_asserts_results(struct ecore_hwfn *p_hwfn,
+					     u32 *dump_buf,
+					     u32 num_dumped_dwords,
+					     char *results_buf);
+
+/**
+ * @brief qed_dbg_parse_attn - Parses and prints attention registers values in
+ * the specified results struct.
+ *
+ * @param p_hwfn -  HW device data
+ * @param results - Pointer to the attention read results
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_parse_attn(struct ecore_hwfn *p_hwfn,
+				   struct dbg_attn_block_result *results);
+
+#endif
diff --git a/drivers/net/qede/qede_if.h b/drivers/net/qede/qede_if.h
index 858cd51d5..c5ae3fb2e 100644
--- a/drivers/net/qede/qede_if.h
+++ b/drivers/net/qede/qede_if.h
@@ -189,6 +189,51 @@ struct qed_common_ops {
 			      uint32_t dp_module, uint8_t dp_level);
 
 	int (*send_drv_state)(struct ecore_dev *edev, bool active);
+
+	/* ###############  DEBUG *************************/
+
+	int     (*dbg_grc)(struct ecore_dev       *edev,
+			   void		 *buffer,
+			   u32		  *num_dumped_bytes);
+	int     (*dbg_grc_size)(struct ecore_dev *edev);
+
+	int     (*dbg_idle_chk)(struct ecore_dev  *edev,
+				void	    *buffer,
+				u32	     *num_dumped_bytes);
+	int     (*dbg_idle_chk_size)(struct ecore_dev *edev);
+
+	int     (*dbg_reg_fifo)(struct ecore_dev  *edev,
+				void	    *buffer,
+				u32	     *num_dumped_bytes);
+	int     (*dbg_reg_fifo_size)(struct ecore_dev *edev);
+
+	int     (*dbg_mcp_trace)(struct ecore_dev *edev,
+				 void	   *buffer,
+				 u32	    *num_dumped_bytes);
+	int     (*dbg_mcp_trace_size)(struct ecore_dev *edev);
+
+	int	(*dbg_protection_override)(struct ecore_dev *edev, void *buffer,
+					   u32 *num_dumped_bytes);
+	int     (*dbg_protection_override_size)(struct ecore_dev *edev);
+
+	int	(*dbg_igu_fifo_size)(struct ecore_dev *edev);
+	int	(*dbg_igu_fifo)(struct ecore_dev *edev, void *buffer,
+				u32 *num_dumped_bytes);
+
+	int	(*dbg_fw_asserts)(struct ecore_dev *edev, void *buffer,
+				  u32 *num_dumped_bytes);
+
+	int	(*dbg_fw_asserts_size)(struct ecore_dev *edev);
+
+	int	(*dbg_ilt)(struct ecore_dev *edev, void *buffer,
+			   u32 *num_dumped_bytes);
+
+	int	(*dbg_ilt_size)(struct ecore_dev *edev);
+
+	u8      (*dbg_get_debug_engine)(struct ecore_dev *edev);
+	void    (*dbg_set_debug_engine)(struct ecore_dev  *edev,
+					int	     engine_number);
+
 };
 
 /* Externs */
diff --git a/drivers/net/qede/qede_main.c b/drivers/net/qede/qede_main.c
index 51aa639c6..987a6f1e1 100644
--- a/drivers/net/qede/qede_main.c
+++ b/drivers/net/qede/qede_main.c
@@ -9,6 +9,8 @@
 #include <rte_string_fns.h>
 
 #include "qede_ethdev.h"
+/* ######### DEBUG ###########*/
+#include "qede_debug.h"
 
 /* Alarm timeout. */
 #define QEDE_ALARM_TIMEOUT_US 100000
@@ -276,10 +278,15 @@ static int qed_slowpath_start(struct ecore_dev *edev,
 	qed_start_iov_task(edev);
 
 #ifdef CONFIG_ECORE_BINARY_FW
-	if (IS_PF(edev))
+	if (IS_PF(edev)) {
 		data = (const uint8_t *)edev->firmware + sizeof(u32);
+
+		/* ############### DEBUG ################## */
+		qed_dbg_pf_init(edev);
+	}
 #endif
 
+
 	/* Start the slowpath */
 	memset(&hw_init_params, 0, sizeof(hw_init_params));
 	hw_init_params.b_hw_start = true;
@@ -779,6 +786,36 @@ const struct qed_common_ops qed_common_ops_pass = {
 	INIT_STRUCT_FIELD(slowpath_stop, &qed_slowpath_stop),
 	INIT_STRUCT_FIELD(remove, &qed_remove),
 	INIT_STRUCT_FIELD(send_drv_state, &qed_send_drv_state),
+	/* ############### DEBUG ####################*/
+
+	INIT_STRUCT_FIELD(dbg_get_debug_engine, &qed_get_debug_engine),
+	INIT_STRUCT_FIELD(dbg_set_debug_engine, &qed_set_debug_engine),
+
+	INIT_STRUCT_FIELD(dbg_protection_override,
+			  &qed_dbg_protection_override),
+	INIT_STRUCT_FIELD(dbg_protection_override_size,
+			  &qed_dbg_protection_override_size),
+
+	INIT_STRUCT_FIELD(dbg_grc, &qed_dbg_grc),
+	INIT_STRUCT_FIELD(dbg_grc_size, &qed_dbg_grc_size),
+
+	INIT_STRUCT_FIELD(dbg_idle_chk, &qed_dbg_idle_chk),
+	INIT_STRUCT_FIELD(dbg_idle_chk_size, &qed_dbg_idle_chk_size),
+
+	INIT_STRUCT_FIELD(dbg_mcp_trace, &qed_dbg_mcp_trace),
+	INIT_STRUCT_FIELD(dbg_mcp_trace_size, &qed_dbg_mcp_trace_size),
+
+	INIT_STRUCT_FIELD(dbg_fw_asserts, &qed_dbg_fw_asserts),
+	INIT_STRUCT_FIELD(dbg_fw_asserts_size, &qed_dbg_fw_asserts_size),
+
+	INIT_STRUCT_FIELD(dbg_ilt, &qed_dbg_ilt),
+	INIT_STRUCT_FIELD(dbg_ilt_size, &qed_dbg_ilt_size),
+
+	INIT_STRUCT_FIELD(dbg_reg_fifo_size, &qed_dbg_reg_fifo_size),
+	INIT_STRUCT_FIELD(dbg_reg_fifo, &qed_dbg_reg_fifo),
+
+	INIT_STRUCT_FIELD(dbg_igu_fifo_size, &qed_dbg_igu_fifo_size),
+	INIT_STRUCT_FIELD(dbg_igu_fifo, &qed_dbg_igu_fifo),
 };
 
 const struct qed_eth_ops qed_eth_ops_pass = {
-- 
2.18.0


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

* [dpdk-dev] [PATCH v3 4/4] net/qede: add support for get register operation
  2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 0/4] net/qede: add FW debug data collection support Rasesh Mody
                     ` (3 preceding siblings ...)
  2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 3/4] net/qede: add infrastructure " Rasesh Mody
@ 2020-07-07 20:18   ` Rasesh Mody
  4 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-07-07 20:18 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

Add support for .get_reg eth_dev ops which will be used to collect the
firmware debug data.

PMD on detecting on some HW errors will collect the FW/HW Dump to a
buffer and then it will save it to a file implemented in
qede_save_fw_dump().

Dump file location and name:
Location: <RTE_SDK> or DPDK root
Name: qede_pmd_dump_mm-dd-yy_hh-mm-ss.bin

DPDK applications can initiate a debug data collection by invoking DPDK
library’s rte_eth_dev_get_reg_info() API. This API invokes .get_reg()
interface in the PMD.

PMD implementation of .get_reg() collects the FW/HW Dump, saves it to
data field of rte_dev_reg_info and passes it to the application. It’s
the responsibility of the application to save the FW/HW Dump to a file.
We recommendation using the file name format used by qede_save_fw_dump().

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 doc/guides/nics/features/qede.ini |   1 +
 drivers/net/qede/Makefile         |   1 +
 drivers/net/qede/base/bcm_osal.c  |  25 +++
 drivers/net/qede/base/bcm_osal.h  |   5 +
 drivers/net/qede/qede_ethdev.c    |   1 +
 drivers/net/qede/qede_ethdev.h    |  25 +++
 drivers/net/qede/qede_regs.c      | 271 ++++++++++++++++++++++++++++++
 7 files changed, 329 insertions(+)
 create mode 100644 drivers/net/qede/qede_regs.c

diff --git a/doc/guides/nics/features/qede.ini b/doc/guides/nics/features/qede.ini
index 20c90e626..f8716523e 100644
--- a/doc/guides/nics/features/qede.ini
+++ b/doc/guides/nics/features/qede.ini
@@ -31,6 +31,7 @@ Packet type parsing  = Y
 Basic stats          = Y
 Extended stats       = Y
 Stats per queue      = Y
+Registers dump       = Y
 Multiprocess aware   = Y
 Linux UIO            = Y
 Linux VFIO           = Y
diff --git a/drivers/net/qede/Makefile b/drivers/net/qede/Makefile
index 3b00338ff..0e8a67b0d 100644
--- a/drivers/net/qede/Makefile
+++ b/drivers/net/qede/Makefile
@@ -104,5 +104,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_main.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_rxtx.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_filter.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_debug.c
+SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_regs.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/qede/base/bcm_osal.c b/drivers/net/qede/base/bcm_osal.c
index 45557fe3c..65837b53d 100644
--- a/drivers/net/qede/base/bcm_osal.c
+++ b/drivers/net/qede/base/bcm_osal.c
@@ -246,6 +246,28 @@ qede_get_mcp_proto_stats(struct ecore_dev *edev,
 	}
 }
 
+static void qede_hw_err_handler(void *dev, enum ecore_hw_err_type err_type)
+{
+	struct ecore_dev *edev = dev;
+
+	switch (err_type) {
+	case ECORE_HW_ERR_FAN_FAIL:
+		break;
+
+	case ECORE_HW_ERR_MFW_RESP_FAIL:
+	case ECORE_HW_ERR_HW_ATTN:
+	case ECORE_HW_ERR_DMAE_FAIL:
+	case ECORE_HW_ERR_RAMROD_FAIL:
+	case ECORE_HW_ERR_FW_ASSERT:
+		OSAL_SAVE_FW_DUMP(0); /* Using port 0 as default port_id */
+		break;
+
+	default:
+		DP_NOTICE(edev, false, "Unknown HW error [%d]\n", err_type);
+		return;
+	}
+}
+
 void
 qede_hw_err_notify(struct ecore_hwfn *p_hwfn, enum ecore_hw_err_type err_type)
 {
@@ -275,6 +297,9 @@ qede_hw_err_notify(struct ecore_hwfn *p_hwfn, enum ecore_hw_err_type err_type)
 	}
 
 	DP_ERR(p_hwfn, "HW error occurred [%s]\n", err_str);
+
+	qede_hw_err_handler(p_hwfn->p_dev, err_type);
+
 	ecore_int_attn_clr_enable(p_hwfn->p_dev, true);
 }
 
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index b4b94231b..5d4df5907 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -371,6 +371,11 @@ void qede_hw_err_notify(struct ecore_hwfn *p_hwfn,
 
 /* TODO: */
 #define OSAL_SCHEDULE_RECOVERY_HANDLER(hwfn) nothing
+
+int qede_save_fw_dump(uint8_t port_id);
+
+#define OSAL_SAVE_FW_DUMP(port_id) qede_save_fw_dump(port_id)
+
 #define OSAL_HW_ERROR_OCCURRED(hwfn, err_type) \
 	qede_hw_err_notify(hwfn, err_type)
 
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index b5d6c7c43..e5a2581dd 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -2426,6 +2426,7 @@ static const struct eth_dev_ops qede_eth_dev_ops = {
 	.udp_tunnel_port_add = qede_udp_dst_port_add,
 	.udp_tunnel_port_del = qede_udp_dst_port_del,
 	.fw_version_get = qede_fw_version_get,
+	.get_reg = qede_get_regs,
 };
 
 static const struct eth_dev_ops qede_eth_vf_dev_ops = {
diff --git a/drivers/net/qede/qede_ethdev.h b/drivers/net/qede/qede_ethdev.h
index b988a73f2..76c5dae3b 100644
--- a/drivers/net/qede/qede_ethdev.h
+++ b/drivers/net/qede/qede_ethdev.h
@@ -214,6 +214,8 @@ struct qede_tunn_params {
 	uint16_t udp_port;
 };
 
+#define QEDE_FW_DUMP_FILE_SIZE 128
+
 /*
  *  Structure to store private data for each port.
  */
@@ -252,6 +254,7 @@ struct qede_dev {
 	char drv_ver[QEDE_PMD_DRV_VER_STR_SIZE];
 	bool vport_started;
 	int vlan_offload_mask;
+	char dump_file[QEDE_FW_DUMP_FILE_SIZE];
 	void *ethdev;
 };
 
@@ -313,4 +316,26 @@ void qede_config_accept_any_vlan(struct qede_dev *qdev, bool flg);
 int qede_ucast_filter(struct rte_eth_dev *eth_dev,
 		      struct ecore_filter_ucast *ucast,
 		      bool add);
+
+#define REGDUMP_HEADER_SIZE sizeof(u32)
+#define REGDUMP_HEADER_FEATURE_SHIFT 24
+#define REGDUMP_HEADER_ENGINE_SHIFT 31
+#define REGDUMP_HEADER_OMIT_ENGINE_SHIFT 30
+
+enum debug_print_features {
+	OLD_MODE = 0,
+	IDLE_CHK = 1,
+	GRC_DUMP = 2,
+	MCP_TRACE = 3,
+	REG_FIFO = 4,
+	PROTECTION_OVERRIDE = 5,
+	IGU_FIFO = 6,
+	PHY = 7,
+	FW_ASSERTS = 8,
+};
+
+int qede_get_regs_len(struct qede_dev *qdev);
+int qede_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs);
+void qede_config_rx_mode(struct rte_eth_dev *eth_dev);
+void qed_dbg_dump(struct rte_eth_dev *eth_dev);
 #endif /* _QEDE_ETHDEV_H_ */
diff --git a/drivers/net/qede/qede_regs.c b/drivers/net/qede/qede_regs.c
new file mode 100644
index 000000000..4409d2180
--- /dev/null
+++ b/drivers/net/qede/qede_regs.c
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Marvell Semiconductor Inc.
+ * All rights reserved.
+ * www.marvell.com
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <time.h>
+#include <rte_ethdev.h>
+#include "base/bcm_osal.h"
+#include "qede_ethdev.h"
+
+int
+qede_get_regs_len(struct qede_dev *qdev)
+{
+	struct ecore_dev *edev = &qdev->edev;
+	int cur_engine, num_of_hwfns, regs_len = 0;
+	uint8_t org_engine;
+
+	if (IS_VF(edev))
+		return 0;
+
+	if (qdev->ops && qdev->ops->common) {
+		num_of_hwfns = qdev->dev_info.common.num_hwfns;
+		org_engine = qdev->ops->common->dbg_get_debug_engine(edev);
+		for (cur_engine = 0; cur_engine < num_of_hwfns; cur_engine++) {
+			/* compute requierd buffer size for idle_chks and
+			 * grcDump for each hw function
+			 */
+			DP_NOTICE(edev, false,
+				"Calculating idle_chk and grcdump register length for current engine\n");
+			qdev->ops->common->dbg_set_debug_engine(edev,
+								cur_engine);
+			regs_len += REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_idle_chk_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_idle_chk_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_grc_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_reg_fifo_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_protection_override_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_igu_fifo_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_fw_asserts_size(edev);
+		}
+		/* compute requierd buffer size for mcp trace and add it to the
+		 * total requierd buffer size
+		 */
+		regs_len += REGDUMP_HEADER_SIZE +
+			    qdev->ops->common->dbg_mcp_trace_size(edev);
+
+		qdev->ops->common->dbg_set_debug_engine(edev, org_engine);
+	}
+	DP_NOTICE(edev, false, "Total length = %u\n", regs_len);
+
+	return regs_len;
+}
+
+static uint32_t
+qede_calc_regdump_header(enum debug_print_features feature, int engine,
+			 uint32_t feature_size, uint8_t omit_engine)
+{
+	/* insert the engine, feature and mode inside the header and
+	 * combine it with feature size
+	 */
+	return (feature_size | (feature << REGDUMP_HEADER_FEATURE_SHIFT) |
+		(omit_engine << REGDUMP_HEADER_OMIT_ENGINE_SHIFT) |
+		(engine << REGDUMP_HEADER_ENGINE_SHIFT));
+}
+
+int qede_get_regs(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs)
+{
+	struct qede_dev *qdev = eth_dev->data->dev_private;
+	struct ecore_dev *edev = &qdev->edev;
+	uint32_t *buffer = regs->data;
+	int cur_engine, num_of_hwfns;
+	/* '1' tells the parser to omit the engine number in the output files */
+	uint8_t omit_engine = 0;
+	uint8_t org_engine;
+	uint32_t feature_size;
+	uint32_t offset = 0;
+
+	if (IS_VF(edev))
+		return -ENOTSUP;
+
+	if (buffer == NULL) {
+		regs->length = qede_get_regs_len(qdev);
+		regs->width =  sizeof(uint32_t);
+		DP_INFO(edev, "Length %u\n", regs->length);
+		return 0;
+	}
+
+	memset(buffer, 0, regs->length);
+	num_of_hwfns = qdev->dev_info.common.num_hwfns;
+	if (num_of_hwfns == 1)
+		omit_engine = 1;
+
+	OSAL_MUTEX_ACQUIRE(&edev->dbg_lock);
+
+	org_engine = qdev->ops->common->dbg_get_debug_engine(edev);
+	for (cur_engine = 0; cur_engine < num_of_hwfns; cur_engine++) {
+		/* collect idle_chks and grcDump for each hw function */
+		DP_NOTICE(edev, false, "obtaining idle_chk and grcdump for current engine\n");
+		qdev->ops->common->dbg_set_debug_engine(edev, cur_engine);
+
+		/* first idle_chk */
+		qdev->ops->common->dbg_idle_chk(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(IDLE_CHK, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Idle Check1 feature_size %u\n",
+			  feature_size);
+
+		/* second idle_chk */
+		qdev->ops->common->dbg_idle_chk(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(IDLE_CHK, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Idle Check2 feature_size %u\n",
+			  feature_size);
+
+		/* reg_fifo dump */
+		qdev->ops->common->dbg_reg_fifo(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(REG_FIFO, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Reg fifo feature_size %u\n",
+			  feature_size);
+
+		/* igu_fifo dump */
+		qdev->ops->common->dbg_igu_fifo(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(IGU_FIFO, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "IGU fifo feature_size %u\n",
+			  feature_size);
+
+		/* protection_override dump */
+		qdev->ops->common->dbg_protection_override(edev,
+							   (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+		       qede_calc_regdump_header(PROTECTION_OVERRIDE, cur_engine,
+						feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Protection override feature_size %u\n",
+			  feature_size);
+
+		/* fw_asserts dump */
+		qdev->ops->common->dbg_fw_asserts(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(FW_ASSERTS, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "FW assert feature_size %u\n",
+			  feature_size);
+
+		/* grc dump */
+		qdev->ops->common->dbg_grc(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(GRC_DUMP, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "GRC dump feature_size %u\n",
+			  feature_size);
+	}
+
+	/* mcp_trace */
+	qdev->ops->common->dbg_mcp_trace(edev, (uint8_t *)buffer +
+		offset + REGDUMP_HEADER_SIZE, &feature_size);
+	*(uint32_t *)((uint8_t *)buffer + offset) =
+		qede_calc_regdump_header(MCP_TRACE, cur_engine, feature_size,
+					 omit_engine);
+	offset += (feature_size + REGDUMP_HEADER_SIZE);
+	DP_NOTICE(edev, false, "MCP trace feature_size %u\n", feature_size);
+
+	qdev->ops->common->dbg_set_debug_engine(edev, org_engine);
+
+	OSAL_MUTEX_RELEASE(&edev->dbg_lock);
+
+	return 0;
+}
+
+static void
+qede_set_fw_dump_file_name(struct qede_dev *qdev)
+{
+	time_t ltime;
+	struct tm *tm;
+
+	ltime = time(NULL);
+	tm = localtime(&ltime);
+	snprintf(qdev->dump_file, QEDE_FW_DUMP_FILE_SIZE,
+		 "qede_pmd_dump_%02d-%02d-%02d_%02d-%02d-%02d.bin",
+		 tm->tm_mon + 1, (int)tm->tm_mday, 1900 + tm->tm_year,
+		 tm->tm_hour, tm->tm_min, tm->tm_sec);
+}
+
+static int
+qede_write_fwdump(const char *dump_file, void *dump, size_t len)
+{
+	int err = 0;
+	FILE *f;
+	size_t bytes;
+
+	f = fopen(dump_file, "wb+");
+
+	if (!f) {
+		fprintf(stderr, "Can't open file %s: %s\n",
+			dump_file, strerror(errno));
+		return 1;
+	}
+	bytes = fwrite(dump, 1, len, f);
+	if (bytes != len) {
+		fprintf(stderr, "Can not write all of dump data bytes=%ld len=%ld\n",
+			bytes, len);
+		err = 1;
+	}
+
+	if (fclose(f)) {
+		fprintf(stderr, "Can't close file %s: %s\n",
+			dump_file, strerror(errno));
+		err = 1;
+	}
+
+	return err;
+}
+
+int
+qede_save_fw_dump(uint8_t port_id)
+{
+	struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id];
+	struct rte_dev_reg_info regs;
+	struct qede_dev *qdev = eth_dev->data->dev_private;
+	struct ecore_dev *edev = &qdev->edev;
+	int rc = 0;
+
+	if (!rte_eth_dev_is_valid_port(port_id)) {
+		DP_ERR(edev, "port %u invalid port ID", port_id);
+		return -ENODEV;
+	}
+
+	memset(&regs, 0, sizeof(regs));
+	regs.length = qede_get_regs_len(qdev);
+	regs.data = OSAL_ZALLOC(eth_dev, GFP_KERNEL, regs.length);
+	if (regs.data) {
+		qede_get_regs(eth_dev, &regs);
+		qede_set_fw_dump_file_name(qdev);
+		rc = qede_write_fwdump(qdev->dump_file, regs.data, regs.length);
+		if (!rc)
+			DP_NOTICE(edev, false, "FW dump written to %s file\n",
+				  qdev->dump_file);
+		OSAL_FREE(edev, regs.data);
+	}
+
+	return rc;
+}
-- 
2.18.0


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

* [dpdk-dev] [PATCH v4 0/4] net/qede: add FW debug data collection support
  2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 " Rasesh Mody
@ 2020-07-07 21:16     ` Rasesh Mody
  2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 " Rasesh Mody
                         ` (4 more replies)
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
                       ` (3 subsequent siblings)
  4 siblings, 5 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-07-07 21:16 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev

Hi Jerin, Ferruh,

This patch-set adds an ability to collect FW and HW Debug Data/Dump
(referred to as FW/HW Dump) to QEDE PMD. The dump is collected either
when PMD detects an error or when a DPDK application asks PMD to
collect it upon detection of application error. This FW/HW Dump
needs to be saved to a file and sent to Marvell for analysis.

Please apply to dpdk-next-net-mrvl and dpdk-next-net trees.

v4:
Rectify all genuine spelling typos, remaining are false positive.

v3:
Fixed gcc-10 compilation issue.

v2:
Addressed checkpatch issues and updated supported features.

Thanks!
-Rasesh

Rasesh Mody (4):
  net/qede/base: re-arrange few structures for DDC
  net/qede/base: add changes for debug data collection
  net/qede: add infrastructure for debug data collection
  net/qede: add support for get register operation

 doc/guides/nics/features/qede.ini             |    1 +
 drivers/net/qede/Makefile                     |    5 +-
 drivers/net/qede/base/bcm_osal.c              |   31 +
 drivers/net/qede/base/bcm_osal.h              |   18 +-
 drivers/net/qede/base/common_hsi.h            |    1 +
 drivers/net/qede/base/ecore.h                 |   54 +-
 drivers/net/qede/base/ecore_cxt.c             |  200 +-
 drivers/net/qede/base/ecore_cxt.h             |  140 +-
 drivers/net/qede/base/ecore_dev.c             |   26 +-
 drivers/net/qede/base/ecore_hsi_common.h      |  184 +-
 drivers/net/qede/base/ecore_hsi_debug_tools.h |    2 +-
 drivers/net/qede/base/ecore_hsi_func_common.h |   17 +
 drivers/net/qede/base/ecore_init_fw_funcs.h   |    7 -
 drivers/net/qede/base/ecore_mcp.c             |  211 +
 drivers/net/qede/base/ecore_mcp_api.h         |   37 +
 drivers/net/qede/base/ecore_status.h          |    2 +
 drivers/net/qede/base/reg_addr.h              |  846 ++
 drivers/net/qede/qede_debug.c                 | 8120 +++++++++++++++++
 drivers/net/qede/qede_debug.h                 |  759 ++
 drivers/net/qede/qede_ethdev.c                |    2 +-
 drivers/net/qede/qede_ethdev.h                |   25 +
 drivers/net/qede/qede_if.h                    |   45 +
 drivers/net/qede/qede_main.c                  |   42 +-
 drivers/net/qede/qede_regs.c                  |  271 +
 24 files changed, 10883 insertions(+), 163 deletions(-)
 create mode 100644 drivers/net/qede/base/ecore_hsi_func_common.h
 create mode 100644 drivers/net/qede/qede_debug.c
 create mode 100644 drivers/net/qede/qede_debug.h
 create mode 100644 drivers/net/qede/qede_regs.c

-- 
2.18.0


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

* [dpdk-dev] [PATCH v4 1/4] net/qede/base: re-arrange few structures for DDC
  2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 " Rasesh Mody
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 " Rasesh Mody
@ 2020-07-07 21:16     ` Rasesh Mody
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 2/4] net/qede/base: add changes for debug data collection Rasesh Mody
                       ` (2 subsequent siblings)
  4 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-07-07 21:16 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

This patch rearranges some of the base driver structures which will be
also used by debug data collection (DDC) implementation. It adds a new
file ecore_hsi_func_common.h with Physical, Virtual memory descriptors.

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/qede/base/ecore.h                 |   2 +
 drivers/net/qede/base/ecore_cxt.c             | 140 ++----------------
 drivers/net/qede/base/ecore_cxt.h             | 135 ++++++++++++++++-
 drivers/net/qede/base/ecore_dev.c             |  13 +-
 drivers/net/qede/base/ecore_hsi_func_common.h |  17 +++
 drivers/net/qede/base/ecore_init_fw_funcs.h   |   7 -
 6 files changed, 172 insertions(+), 142 deletions(-)
 create mode 100644 drivers/net/qede/base/ecore_hsi_func_common.h

diff --git a/drivers/net/qede/base/ecore.h b/drivers/net/qede/base/ecore.h
index 498bb6f09..dc5fe4d80 100644
--- a/drivers/net/qede/base/ecore.h
+++ b/drivers/net/qede/base/ecore.h
@@ -24,6 +24,7 @@
 #include "ecore_hsi_debug_tools.h"
 #include "ecore_hsi_init_func.h"
 #include "ecore_hsi_init_tool.h"
+#include "ecore_hsi_func_common.h"
 #include "ecore_proto_if.h"
 #include "mcp_public.h"
 
@@ -671,6 +672,7 @@ struct ecore_hwfn {
 
 	struct dbg_tools_data		dbg_info;
 	void				*dbg_user_info;
+	struct virt_mem_desc		dbg_arrays[MAX_BIN_DBG_BUFFER_TYPE];
 
 	struct z_stream_s		*stream;
 
diff --git a/drivers/net/qede/base/ecore_cxt.c b/drivers/net/qede/base/ecore_cxt.c
index dda47ea67..23f37b1bf 100644
--- a/drivers/net/qede/base/ecore_cxt.c
+++ b/drivers/net/qede/base/ecore_cxt.c
@@ -20,12 +20,6 @@
 #include "ecore_sriov.h"
 #include "ecore_mcp.h"
 
-/* Max number of connection types in HW (DQ/CDU etc.) */
-#define MAX_CONN_TYPES		PROTOCOLID_COMMON
-#define NUM_TASK_TYPES		2
-#define NUM_TASK_PF_SEGMENTS	4
-#define NUM_TASK_VF_SEGMENTS	1
-
 /* Doorbell-Queue constants */
 #define DQ_RANGE_SHIFT	4
 #define DQ_RANGE_ALIGN	(1 << DQ_RANGE_SHIFT)
@@ -90,128 +84,6 @@ struct src_ent {
 /* Alignment is inherent to the type1_task_context structure */
 #define TYPE1_TASK_CXT_SIZE(p_hwfn) sizeof(union type1_task_context)
 
-/* PF per protocl configuration object */
-#define TASK_SEGMENTS   (NUM_TASK_PF_SEGMENTS + NUM_TASK_VF_SEGMENTS)
-#define TASK_SEGMENT_VF (NUM_TASK_PF_SEGMENTS)
-
-struct ecore_tid_seg {
-	u32 count;
-	u8 type;
-	bool has_fl_mem;
-};
-
-struct ecore_conn_type_cfg {
-	u32 cid_count;
-	u32 cids_per_vf;
-	struct ecore_tid_seg tid_seg[TASK_SEGMENTS];
-};
-
-/* ILT Client configuration,
- * Per connection type (protocol) resources (cids, tis, vf cids etc.)
- * 1 - for connection context (CDUC) and for each task context we need two
- * values, for regular task context and for force load memory
- */
-#define ILT_CLI_PF_BLOCKS	(1 + NUM_TASK_PF_SEGMENTS * 2)
-#define ILT_CLI_VF_BLOCKS	(1 + NUM_TASK_VF_SEGMENTS * 2)
-#define CDUC_BLK		(0)
-#define SRQ_BLK			(0)
-#define CDUT_SEG_BLK(n)		(1 + (u8)(n))
-#define CDUT_FL_SEG_BLK(n, X)	(1 + (n) + NUM_TASK_##X##_SEGMENTS)
-
-struct ilt_cfg_pair {
-	u32 reg;
-	u32 val;
-};
-
-struct ecore_ilt_cli_blk {
-	u32 total_size;		/* 0 means not active */
-	u32 real_size_in_page;
-	u32 start_line;
-	u32 dynamic_line_offset;
-	u32 dynamic_line_cnt;
-};
-
-struct ecore_ilt_client_cfg {
-	bool active;
-
-	/* ILT boundaries */
-	struct ilt_cfg_pair first;
-	struct ilt_cfg_pair last;
-	struct ilt_cfg_pair p_size;
-
-	/* ILT client blocks for PF */
-	struct ecore_ilt_cli_blk pf_blks[ILT_CLI_PF_BLOCKS];
-	u32 pf_total_lines;
-
-	/* ILT client blocks for VFs */
-	struct ecore_ilt_cli_blk vf_blks[ILT_CLI_VF_BLOCKS];
-	u32 vf_total_lines;
-};
-
-#define MAP_WORD_SIZE		sizeof(unsigned long)
-#define BITS_PER_MAP_WORD	(MAP_WORD_SIZE * 8)
-
-struct ecore_cid_acquired_map {
-	u32 start_cid;
-	u32 max_count;
-	u32 *cid_map;
-};
-
-struct ecore_src_t2 {
-	struct phys_mem_desc	*dma_mem;
-	u32			num_pages;
-	u64			first_free;
-	u64			last_free;
-};
-
-struct ecore_cxt_mngr {
-	/* Per protocl configuration */
-	struct ecore_conn_type_cfg conn_cfg[MAX_CONN_TYPES];
-
-	/* computed ILT structure */
-	struct ecore_ilt_client_cfg clients[ILT_CLI_MAX];
-
-	/* Task type sizes */
-	u32 task_type_size[NUM_TASK_TYPES];
-
-	/* total number of VFs for this hwfn -
-	 * ALL VFs are symmetric in terms of HW resources
-	 */
-	u32 vf_count;
-
-	/* Acquired CIDs */
-	struct ecore_cid_acquired_map acquired[MAX_CONN_TYPES];
-	struct ecore_cid_acquired_map *acquired_vf[MAX_CONN_TYPES];
-
-	/* ILT  shadow table */
-	struct phys_mem_desc		*ilt_shadow;
-	u32 pf_start_line;
-
-	/* Mutex for a dynamic ILT allocation */
-	osal_mutex_t mutex;
-
-	/* SRC T2 */
-	struct ecore_src_t2		src_t2;
-
-	/* The infrastructure originally was very generic and context/task
-	 * oriented - per connection-type we would set how many of those
-	 * are needed, and later when determining how much memory we're
-	 * needing for a given block we'd iterate over all the relevant
-	 * connection-types.
-	 * But since then we've had some additional resources, some of which
-	 * require memory which is indepent of the general context/task
-	 * scheme. We add those here explicitly per-feature.
-	 */
-
-	/* total number of SRQ's for this hwfn */
-	u32				srq_count;
-
-	/* Maximal number of L2 steering filters */
-	u32				arfs_count;
-
-	/* TODO - VF arfs filters ? */
-};
-
 static OSAL_INLINE bool tm_cid_proto(enum protocol_type type)
 {
 	return type == PROTOCOLID_TOE;
@@ -945,7 +817,7 @@ static enum _ecore_status_t ecore_cxt_src_t2_alloc(struct ecore_hwfn *p_hwfn)
 }
 
 #define for_each_ilt_valid_client(pos, clients)		\
-	for (pos = 0; pos < ILT_CLI_MAX; pos++)		\
+	for (pos = 0; pos < MAX_ILT_CLIENTS; pos++)		\
 		if (!clients[pos].active) {		\
 			continue;			\
 		} else					\
@@ -1238,7 +1110,7 @@ enum _ecore_status_t ecore_cxt_mngr_alloc(struct ecore_hwfn *p_hwfn)
 	clients[ILT_CLI_TSDM].p_size.reg = ILT_CFG_REG(TSDM, P_SIZE);
 
 	/* default ILT page size for all clients is 64K */
-	for (i = 0; i < ILT_CLI_MAX; i++)
+	for (i = 0; i < MAX_ILT_CLIENTS; i++)
 		p_mngr->clients[i].p_size.val = ILT_DEFAULT_HW_P_SIZE;
 
 	/* due to removal of ISCSI/FCoE files union type0_task_context
@@ -2306,3 +2178,11 @@ ecore_cxt_free_ilt_range(struct ecore_hwfn *p_hwfn,
 
 	return ECORE_SUCCESS;
 }
+
+static u16 ecore_blk_calculate_pages(struct ecore_ilt_cli_blk *p_blk)
+{
+	if (p_blk->real_size_in_page == 0)
+		return 0;
+
+	return DIV_ROUND_UP(p_blk->total_size, p_blk->real_size_in_page);
+}
diff --git a/drivers/net/qede/base/ecore_cxt.h b/drivers/net/qede/base/ecore_cxt.h
index 55f08027d..7b91b953e 100644
--- a/drivers/net/qede/base/ecore_cxt.h
+++ b/drivers/net/qede/base/ecore_cxt.h
@@ -31,7 +31,7 @@ enum ilt_clients {
 	ILT_CLI_TSDM,
 	ILT_CLI_RGFS,
 	ILT_CLI_TGFS,
-	ILT_CLI_MAX
+	MAX_ILT_CLIENTS
 };
 
 u32 ecore_cxt_get_proto_cid_count(struct ecore_hwfn *p_hwfn,
@@ -212,4 +212,137 @@ enum _ecore_status_t ecore_cxt_free_proto_ilt(struct ecore_hwfn *p_hwfn,
 #define ECORE_CTX_WORKING_MEM 0
 #define ECORE_CTX_FL_MEM 1
 
+/* Max number of connection types in HW (DQ/CDU etc.) */
+#define MAX_CONN_TYPES		PROTOCOLID_COMMON
+#define NUM_TASK_TYPES		2
+#define NUM_TASK_PF_SEGMENTS	4
+#define NUM_TASK_VF_SEGMENTS	1
+
+/* PF per protocol configuration object */
+#define TASK_SEGMENTS   (NUM_TASK_PF_SEGMENTS + NUM_TASK_VF_SEGMENTS)
+#define TASK_SEGMENT_VF (NUM_TASK_PF_SEGMENTS)
+
+struct ecore_tid_seg {
+	u32 count;
+	u8 type;
+	bool has_fl_mem;
+};
+
+struct ecore_conn_type_cfg {
+	u32 cid_count;
+	u32 cids_per_vf;
+	struct ecore_tid_seg tid_seg[TASK_SEGMENTS];
+};
+
+/* ILT Client configuration,
+ * Per connection type (protocol) resources (cids, tis, vf cids etc.)
+ * 1 - for connection context (CDUC) and for each task context we need two
+ * values, for regular task context and for force load memory
+ */
+#define ILT_CLI_PF_BLOCKS	(1 + NUM_TASK_PF_SEGMENTS * 2)
+#define ILT_CLI_VF_BLOCKS	(1 + NUM_TASK_VF_SEGMENTS * 2)
+#define CDUC_BLK		(0)
+#define SRQ_BLK			(0)
+#define CDUT_SEG_BLK(n)		(1 + (u8)(n))
+#define CDUT_FL_SEG_BLK(n, X)	(1 + (n) + NUM_TASK_##X##_SEGMENTS)
+
+struct ilt_cfg_pair {
+	u32 reg;
+	u32 val;
+};
+
+struct ecore_ilt_cli_blk {
+	u32 total_size;		/* 0 means not active */
+	u32 real_size_in_page;
+	u32 start_line;
+	u32 dynamic_line_offset;
+	u32 dynamic_line_cnt;
+};
+
+struct ecore_ilt_client_cfg {
+	bool active;
+
+	/* ILT boundaries */
+	struct ilt_cfg_pair first;
+	struct ilt_cfg_pair last;
+	struct ilt_cfg_pair p_size;
+
+	/* ILT client blocks for PF */
+	struct ecore_ilt_cli_blk pf_blks[ILT_CLI_PF_BLOCKS];
+	u32 pf_total_lines;
+
+	/* ILT client blocks for VFs */
+	struct ecore_ilt_cli_blk vf_blks[ILT_CLI_VF_BLOCKS];
+	u32 vf_total_lines;
+};
+
+#define MAP_WORD_SIZE		sizeof(unsigned long)
+#define BITS_PER_MAP_WORD	(MAP_WORD_SIZE * 8)
+
+struct ecore_cid_acquired_map {
+	u32 start_cid;
+	u32 max_count;
+	u32 *cid_map;
+};
+
+struct ecore_src_t2 {
+	struct phys_mem_desc	*dma_mem;
+	u32			num_pages;
+	u64			first_free;
+	u64			last_free;
+};
+
+struct ecore_cxt_mngr {
+	/* Per protocol configuration */
+	struct ecore_conn_type_cfg	conn_cfg[MAX_CONN_TYPES];
+
+	/* computed ILT structure */
+	struct ecore_ilt_client_cfg	clients[MAX_ILT_CLIENTS];
+
+	/* Task type sizes */
+	u32				task_type_size[NUM_TASK_TYPES];
+
+	/* total number of VFs for this hwfn -
+	 * ALL VFs are symmetric in terms of HW resources
+	 */
+	u32				vf_count;
+	u32				first_vf_in_pf;
+
+	/* Acquired CIDs */
+	struct ecore_cid_acquired_map acquired[MAX_CONN_TYPES];
+	struct ecore_cid_acquired_map *acquired_vf[MAX_CONN_TYPES];
+
+	/* ILT  shadow table */
+	struct phys_mem_desc		*ilt_shadow;
+	u32				ilt_shadow_size;
+	u32				pf_start_line;
+
+	/* Mutex for a dynamic ILT allocation */
+	osal_mutex_t mutex;
+
+	/* SRC T2 */
+	struct ecore_src_t2		src_t2;
+
+	/* The infrastructure originally was very generic and context/task
+	 * oriented - per connection-type we would set how many of those
+	 * are needed, and later when determining how much memory we're
+	 * needing for a given block we'd iterate over all the relevant
+	 * connection-types.
+	 * But since then we've had some additional resources, some of which
+	 * require memory which is independent of the general context/task
+	 * scheme. We add those here explicitly per-feature.
+	 */
+
+	/* total number of SRQ's for this hwfn */
+	u32				srq_count;
+
+	/* Maximal number of L2 steering filters */
+	u32				arfs_count;
+
+	/* TODO - VF arfs filters ? */
+
+	u8				task_type_id;
+	u16				task_ctx_size;
+	u16				conn_ctx_size;
+};
 #endif /* _ECORE_CID_ */
diff --git a/drivers/net/qede/base/ecore_dev.c b/drivers/net/qede/base/ecore_dev.c
index e18c2fa89..814d9ced6 100644
--- a/drivers/net/qede/base/ecore_dev.c
+++ b/drivers/net/qede/base/ecore_dev.c
@@ -2358,6 +2358,7 @@ static enum _ecore_status_t ecore_alloc_qm_data(struct ecore_hwfn *p_hwfn)
 enum _ecore_status_t ecore_resc_alloc(struct ecore_dev *p_dev)
 {
 	enum _ecore_status_t rc = ECORE_SUCCESS;
+	enum dbg_status debug_status = DBG_STATUS_OK;
 	int i;
 
 	if (IS_VF(p_dev)) {
@@ -2512,17 +2513,21 @@ enum _ecore_status_t ecore_resc_alloc(struct ecore_dev *p_dev)
 			goto alloc_err;
 		}
 
-		rc = OSAL_DBG_ALLOC_USER_DATA(p_hwfn, &p_hwfn->dbg_user_info);
-		if (rc) {
+		debug_status = OSAL_DBG_ALLOC_USER_DATA(p_hwfn,
+							&p_hwfn->dbg_user_info);
+		if (debug_status) {
 			DP_NOTICE(p_hwfn, false,
 				  "Failed to allocate dbg user info structure\n");
+			rc = (enum _ecore_status_t)debug_status;
 			goto alloc_err;
 		}
 
-		rc = OSAL_DBG_ALLOC_USER_DATA(p_hwfn, &p_hwfn->dbg_user_info);
-		if (rc) {
+		debug_status = OSAL_DBG_ALLOC_USER_DATA(p_hwfn,
+							&p_hwfn->dbg_user_info);
+		if (debug_status) {
 			DP_NOTICE(p_hwfn, false,
 				  "Failed to allocate dbg user info structure\n");
+			rc = (enum _ecore_status_t)debug_status;
 			goto alloc_err;
 		}
 	} /* hwfn loop */
diff --git a/drivers/net/qede/base/ecore_hsi_func_common.h b/drivers/net/qede/base/ecore_hsi_func_common.h
new file mode 100644
index 000000000..2cd175163
--- /dev/null
+++ b/drivers/net/qede/base/ecore_hsi_func_common.h
@@ -0,0 +1,17 @@
+#ifndef _HSI_FUNC_COMMON_H
+#define _HSI_FUNC_COMMON_H
+
+/* Physical memory descriptor */
+struct phys_mem_desc {
+	dma_addr_t phys_addr;
+	void *virt_addr;
+	u32 size; /* In bytes */
+};
+
+/* Virtual memory descriptor */
+struct virt_mem_desc {
+	void *ptr;
+	u32 size; /* In bytes */
+};
+
+#endif
diff --git a/drivers/net/qede/base/ecore_init_fw_funcs.h b/drivers/net/qede/base/ecore_init_fw_funcs.h
index 912451662..a393d088f 100644
--- a/drivers/net/qede/base/ecore_init_fw_funcs.h
+++ b/drivers/net/qede/base/ecore_init_fw_funcs.h
@@ -9,13 +9,6 @@
 #include "ecore_hsi_common.h"
 #include "ecore_hsi_eth.h"
 
-/* Physical memory descriptor */
-struct phys_mem_desc {
-	dma_addr_t phys_addr;
-	void *virt_addr;
-	u32 size; /* In bytes */
-};
-
 /* Returns the VOQ based on port and TC */
 #define VOQ(port, tc, max_phys_tcs_per_port) \
 	((tc) == PURE_LB_TC ? NUM_OF_PHYS_TCS * MAX_NUM_PORTS_BB + (port) : \
-- 
2.18.0


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

* [dpdk-dev] [PATCH v4 2/4] net/qede/base: add changes for debug data collection
  2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 " Rasesh Mody
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 " Rasesh Mody
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
@ 2020-07-07 21:16     ` Rasesh Mody
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 3/4] net/qede: add infrastructure " Rasesh Mody
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 4/4] net/qede: add support for get register operation Rasesh Mody
  4 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-07-07 21:16 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

This patch adds base driver APIs required for debug data collection.
It adds support for dumping internal lookup tables(ilt), reading nvram
image, register definitions.

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/qede/base/bcm_osal.c              |   6 +
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/qede/base/common_hsi.h            |   1 +
 drivers/net/qede/base/ecore.h                 |  52 +-
 drivers/net/qede/base/ecore_cxt.c             |  60 ++
 drivers/net/qede/base/ecore_cxt.h             |   5 +
 drivers/net/qede/base/ecore_dev.c             |  13 +
 drivers/net/qede/base/ecore_hsi_common.h      | 184 +++-
 drivers/net/qede/base/ecore_hsi_debug_tools.h |   2 +-
 drivers/net/qede/base/ecore_mcp.c             | 211 +++++
 drivers/net/qede/base/ecore_mcp_api.h         |  37 +
 drivers/net/qede/base/ecore_status.h          |   2 +
 drivers/net/qede/base/reg_addr.h              | 846 ++++++++++++++++++
 drivers/net/qede/qede_ethdev.c                |   1 -
 drivers/net/qede/qede_main.c                  |   3 +-
 15 files changed, 1414 insertions(+), 17 deletions(-)

diff --git a/drivers/net/qede/base/bcm_osal.c b/drivers/net/qede/base/bcm_osal.c
index 54e5e4f98..45557fe3c 100644
--- a/drivers/net/qede/base/bcm_osal.c
+++ b/drivers/net/qede/base/bcm_osal.c
@@ -289,3 +289,9 @@ u32 qede_crc32(u32 crc, u8 *ptr, u32 length)
 	}
 	return crc;
 }
+
+void qed_set_platform_str(struct ecore_hwfn *p_hwfn,
+			  char *buf_str, u32 buf_size)
+{
+	snprintf(buf_str, buf_size, "%s.", rte_version());
+}
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index 88a2500a5..6ea3e7dda 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -8,6 +8,7 @@
 #define __BCM_OSAL_H
 
 #include <stdbool.h>
+#include <time.h>
 #include <rte_bitops.h>
 #include <rte_byteorder.h>
 #include <rte_spinlock.h>
@@ -19,6 +20,7 @@
 #include <rte_debug.h>
 #include <rte_ether.h>
 #include <rte_io.h>
+#include <rte_version.h>
 
 /* Forward declaration */
 struct ecore_dev;
@@ -450,7 +452,11 @@ u32 qede_crc32(u32 crc, u8 *ptr, u32 length);
 
 #define OSAL_DIV_S64(a, b)	((a) / (b))
 #define OSAL_LLDP_RX_TLVS(p_hwfn, tlv_buf, tlv_size) nothing
-#define OSAL_GET_EPOCH(p_hwfn)	0
+void qed_set_platform_str(struct ecore_hwfn *p_hwfn,
+			  char *buf_str, u32 buf_size);
+#define OSAL_SET_PLATFORM_STR(p_hwfn, buf_str, buf_size) \
+	qed_set_platform_str(p_hwfn, buf_str, buf_size)
+#define OSAL_GET_EPOCH(p_hwfn) ((u32)time(NULL))
 #define OSAL_DBG_ALLOC_USER_DATA(p_hwfn, user_data_ptr) (0)
 #define OSAL_DB_REC_OCCURRED(p_hwfn) nothing
 
diff --git a/drivers/net/qede/base/common_hsi.h b/drivers/net/qede/base/common_hsi.h
index e230fe5ac..1a02d460b 100644
--- a/drivers/net/qede/base/common_hsi.h
+++ b/drivers/net/qede/base/common_hsi.h
@@ -145,6 +145,7 @@
 #define NUM_OF_CONNECTION_TYPES (8)
 #define NUM_OF_TASK_TYPES       (8)
 #define NUM_OF_LCIDS            (320)
+#define NUM_OF_LTIDS            (320)
 
 /* Global PXP windows (GTT) */
 #define NUM_OF_GTT          19
diff --git a/drivers/net/qede/base/ecore.h b/drivers/net/qede/base/ecore.h
index dc5fe4d80..63bd7466a 100644
--- a/drivers/net/qede/base/ecore.h
+++ b/drivers/net/qede/base/ecore.h
@@ -576,6 +576,12 @@ enum BAR_ID {
 	BAR_ID_1	/* Used for doorbells */
 };
 
+struct ecore_nvm_image_info {
+	u32				num_images;
+	struct bist_nvm_image_att	*image_att;
+	bool				valid;
+};
+
 struct ecore_hwfn {
 	struct ecore_dev		*p_dev;
 	u8				my_id;		/* ID inside the PF */
@@ -701,6 +707,9 @@ struct ecore_hwfn {
 	 */
 	bool b_en_pacing;
 
+	/* Nvm images number and attributes */
+	struct ecore_nvm_image_info     nvm_info;
+
 	struct phys_mem_desc            *fw_overlay_mem;
 
 	/* @DPDK */
@@ -714,26 +723,34 @@ enum ecore_mf_mode {
 	ECORE_MF_UFP,
 };
 
-/* @DPDK */
-struct ecore_dbg_feature {
-	u8				*dump_buf;
-	u32				buf_size;
-	u32				dumped_dwords;
+enum ecore_dev_type {
+	ECORE_DEV_TYPE_BB,
+	ECORE_DEV_TYPE_AH,
 };
 
-enum qed_dbg_features {
-	DBG_FEATURE_BUS,
+/* @DPDK */
+enum ecore_dbg_features {
 	DBG_FEATURE_GRC,
 	DBG_FEATURE_IDLE_CHK,
 	DBG_FEATURE_MCP_TRACE,
 	DBG_FEATURE_REG_FIFO,
+	DBG_FEATURE_IGU_FIFO,
 	DBG_FEATURE_PROTECTION_OVERRIDE,
+	DBG_FEATURE_FW_ASSERTS,
+	DBG_FEATURE_ILT,
 	DBG_FEATURE_NUM
 };
 
-enum ecore_dev_type {
-	ECORE_DEV_TYPE_BB,
-	ECORE_DEV_TYPE_AH,
+struct ecore_dbg_feature {
+	u8				*dump_buf;
+	u32				buf_size;
+	u32				dumped_dwords;
+};
+
+struct ecore_dbg_params {
+	struct ecore_dbg_feature features[DBG_FEATURE_NUM];
+	u8 engine_for_debug;
+	bool print_data;
 };
 
 struct ecore_dev {
@@ -914,10 +931,12 @@ struct ecore_dev {
 	void				*firmware;
 	u64				fw_len;
 #endif
+	bool				disable_ilt_dump;
 
 	/* @DPDK */
 	struct ecore_dbg_feature	dbg_features[DBG_FEATURE_NUM];
-	u8				engine_for_debug;
+	struct ecore_dbg_params		dbg_params;
+	osal_mutex_t			dbg_lock;
 };
 
 enum ecore_hsi_def_type {
@@ -1067,6 +1086,17 @@ enum _ecore_status_t ecore_all_ppfids_wr(struct ecore_hwfn *p_hwfn,
 enum _ecore_status_t ecore_llh_dump_ppfid(struct ecore_dev *p_dev, u8 ppfid);
 enum _ecore_status_t ecore_llh_dump_all(struct ecore_dev *p_dev);
 
+/**
+ * @brief ecore_set_platform_str - Set the debug dump platform string.
+ * Write the ecore version and device's string to the given buffer.
+ *
+ * @param p_hwfn
+ * @param buf_str
+ * @param buf_size
+ */
+void ecore_set_platform_str(struct ecore_hwfn *p_hwfn,
+			    char *buf_str, u32 buf_size);
+
 #define TSTORM_QZONE_START	PXP_VF_BAR0_START_SDM_ZONE_A
 
 #define MSTORM_QZONE_START(dev) \
diff --git a/drivers/net/qede/base/ecore_cxt.c b/drivers/net/qede/base/ecore_cxt.c
index 23f37b1bf..d3025724b 100644
--- a/drivers/net/qede/base/ecore_cxt.c
+++ b/drivers/net/qede/base/ecore_cxt.c
@@ -2186,3 +2186,63 @@ static u16 ecore_blk_calculate_pages(struct ecore_ilt_cli_blk *p_blk)
 
 	return DIV_ROUND_UP(p_blk->total_size, p_blk->real_size_in_page);
 }
+
+u16 ecore_get_cdut_num_pf_init_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 i, pages = 0;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_PF_SEGMENTS; i++) {
+		p_blk = &p_cli->pf_blks[CDUT_FL_SEG_BLK(i, PF)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
+
+u16 ecore_get_cdut_num_vf_init_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 i, pages = 0;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_VF_SEGMENTS; i++) {
+		p_blk = &p_cli->vf_blks[CDUT_FL_SEG_BLK(i, VF)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
+
+u16 ecore_get_cdut_num_pf_work_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 i, pages = 0;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_PF_SEGMENTS; i++) {
+		p_blk = &p_cli->pf_blks[CDUT_SEG_BLK(i)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
+
+u16 ecore_get_cdut_num_vf_work_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 pages = 0, i;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_VF_SEGMENTS; i++) {
+		p_blk = &p_cli->vf_blks[CDUT_SEG_BLK(i)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
diff --git a/drivers/net/qede/base/ecore_cxt.h b/drivers/net/qede/base/ecore_cxt.h
index 7b91b953e..80fe39ac0 100644
--- a/drivers/net/qede/base/ecore_cxt.h
+++ b/drivers/net/qede/base/ecore_cxt.h
@@ -345,4 +345,9 @@ struct ecore_cxt_mngr {
 	u16				task_ctx_size;
 	u16				conn_ctx_size;
 };
+
+u16 ecore_get_cdut_num_pf_init_pages(struct ecore_hwfn *p_hwfn);
+u16 ecore_get_cdut_num_vf_init_pages(struct ecore_hwfn *p_hwfn);
+u16 ecore_get_cdut_num_pf_work_pages(struct ecore_hwfn *p_hwfn);
+u16 ecore_get_cdut_num_vf_work_pages(struct ecore_hwfn *p_hwfn);
 #endif /* _ECORE_CID_ */
diff --git a/drivers/net/qede/base/ecore_dev.c b/drivers/net/qede/base/ecore_dev.c
index 814d9ced6..35a8394de 100644
--- a/drivers/net/qede/base/ecore_dev.c
+++ b/drivers/net/qede/base/ecore_dev.c
@@ -6798,6 +6798,19 @@ void ecore_set_fw_mac_addr(__le16 *fw_msb,
 	((u8 *)fw_lsb)[1] = mac[4];
 }
 
+void ecore_set_platform_str(struct ecore_hwfn *p_hwfn,
+			    char *buf_str, u32 buf_size)
+{
+	u32 len;
+
+	OSAL_SNPRINTF(buf_str, buf_size, "Ecore %d.%d.%d.%d. ",
+		      ECORE_MAJOR_VERSION, ECORE_MINOR_VERSION,
+		      ECORE_REVISION_VERSION, ECORE_ENGINEERING_VERSION);
+
+	len = OSAL_STRLEN(buf_str);
+	OSAL_SET_PLATFORM_STR(p_hwfn, &buf_str[len], buf_size - len);
+}
+
 bool ecore_is_mf_fip_special(struct ecore_dev *p_dev)
 {
 	return !!OSAL_GET_BIT(ECORE_MF_FIP_SPECIAL, &p_dev->mf_bits);
diff --git a/drivers/net/qede/base/ecore_hsi_common.h b/drivers/net/qede/base/ecore_hsi_common.h
index 23cfcdeff..578c798a9 100644
--- a/drivers/net/qede/base/ecore_hsi_common.h
+++ b/drivers/net/qede/base/ecore_hsi_common.h
@@ -10,6 +10,7 @@
 /* Add include to common target */
 /********************************/
 #include "common_hsi.h"
+#include "mcp_public.h"
 
 
 /*
@@ -2229,7 +2230,40 @@ struct fw_info_location {
 };
 
 
-
+/* DMAE parameters */
+struct ecore_dmae_params {
+	u32 flags;
+/* If QED_DMAE_PARAMS_RW_REPL_SRC flag is set and the
+ * source is a block of length DMAE_MAX_RW_SIZE and the
+ * destination is larger, the source block will be duplicated as
+ * many times as required to fill the destination block. This is
+ * used mostly to write a zeroed buffer to destination address
+ * using DMA
+ */
+#define ECORE_DMAE_PARAMS_RW_REPL_SRC_MASK        0x1
+#define ECORE_DMAE_PARAMS_RW_REPL_SRC_SHIFT       0
+#define ECORE_DMAE_PARAMS_SRC_VF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_SRC_VF_VALID_SHIFT      1
+#define ECORE_DMAE_PARAMS_DST_VF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_DST_VF_VALID_SHIFT      2
+#define ECORE_DMAE_PARAMS_COMPLETION_DST_MASK     0x1
+#define ECORE_DMAE_PARAMS_COMPLETION_DST_SHIFT    3
+#define ECORE_DMAE_PARAMS_PORT_VALID_MASK         0x1
+#define ECORE_DMAE_PARAMS_PORT_VALID_SHIFT        4
+#define ECORE_DMAE_PARAMS_SRC_PF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_SRC_PF_VALID_SHIFT      5
+#define ECORE_DMAE_PARAMS_DST_PF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_DST_PF_VALID_SHIFT      6
+#define ECORE_DMAE_PARAMS_RESERVED_MASK           0x1FFFFFF
+#define ECORE_DMAE_PARAMS_RESERVED_SHIFT          7
+	u8 src_vfid;
+	u8 dst_vfid;
+	u8 port_id;
+	u8 src_pfid;
+	u8 dst_pfid;
+	u8 reserved1;
+	__le16 reserved2;
+};
 
 /*
  * IGU cleanup command
@@ -2543,4 +2577,152 @@ struct ystorm_core_conn_ag_ctx {
 	__le32 reg3 /* reg3 */;
 };
 
+/*********/
+/* DEBUG */
+/*********/
+
+#define MFW_TRACE_SIGNATURE	0x25071946
+
+/* The trace in the buffer */
+#define MFW_TRACE_EVENTID_MASK		0x00ffff
+#define MFW_TRACE_PRM_SIZE_MASK		0x0f0000
+#define MFW_TRACE_PRM_SIZE_OFFSET	16
+#define MFW_TRACE_ENTRY_SIZE		3
+
+struct mcp_trace {
+	u32	signature;	/* Help to identify that the trace is valid */
+	u32	size;		/* the size of the trace buffer in bytes*/
+	u32	curr_level;	/* 2 - all will be written to the buffer
+				 * 1 - debug trace will not be written
+				 * 0 - just errors will be written to the buffer
+				 */
+	/* a bit per module, 1 means mask it off, 0 means add it to the trace
+	 * buffer
+	 */
+	u32	modules_mask[2];
+
+	/* Warning: the following pointers are assumed to be 32bits as they are
+	 * used only in the MFW
+	 */
+	/* The next trace will be written to this offset */
+	u32	trace_prod;
+	/* The oldest valid trace starts at this offset (usually very close
+	 * after the current producer)
+	 */
+	u32	trace_oldest;
+};
+
+enum spad_sections {
+	SPAD_SECTION_TRACE,
+	SPAD_SECTION_NVM_CFG,
+	SPAD_SECTION_PUBLIC,
+	SPAD_SECTION_PRIVATE,
+	SPAD_SECTION_MAX
+};
+
+#define MCP_TRACE_SIZE          2048    /* 2kb */
+
+/* This section is located at a fixed location in the beginning of the
+ * scratchpad, to ensure that the MCP trace is not run over during MFW upgrade.
+ * All the rest of data has a floating location which differs from version to
+ * version, and is pointed by the mcp_meta_data below.
+ * Moreover, the spad_layout section is part of the MFW firmware, and is loaded
+ * with it from nvram in order to clear this portion.
+ */
+struct static_init {
+	u32 num_sections;
+	offsize_t sections[SPAD_SECTION_MAX];
+#define SECTION(_sec_) (*((offsize_t *)(STRUCT_OFFSET(sections[_sec_]))))
+
+	struct mcp_trace trace;
+#define MCP_TRACE_P ((struct mcp_trace *)(STRUCT_OFFSET(trace)))
+	u8 trace_buffer[MCP_TRACE_SIZE];
+#define MCP_TRACE_BUF ((u8 *)(STRUCT_OFFSET(trace_buffer)))
+	/* running_mfw has the same definition as in nvm_map.h.
+	 * This bit indicate both the running dir, and the running bundle.
+	 * It is set once when the LIM is loaded.
+	 */
+	u32 running_mfw;
+#define RUNNING_MFW (*((u32 *)(STRUCT_OFFSET(running_mfw))))
+	u32 build_time;
+#define MFW_BUILD_TIME (*((u32 *)(STRUCT_OFFSET(build_time))))
+	u32 reset_type;
+#define RESET_TYPE (*((u32 *)(STRUCT_OFFSET(reset_type))))
+	u32 mfw_secure_mode;
+#define MFW_SECURE_MODE (*((u32 *)(STRUCT_OFFSET(mfw_secure_mode))))
+	u16 pme_status_pf_bitmap;
+#define PME_STATUS_PF_BITMAP (*((u16 *)(STRUCT_OFFSET(pme_status_pf_bitmap))))
+	u16 pme_enable_pf_bitmap;
+#define PME_ENABLE_PF_BITMAP (*((u16 *)(STRUCT_OFFSET(pme_enable_pf_bitmap))))
+	u32 mim_nvm_addr;
+	u32 mim_start_addr;
+	u32 ah_pcie_link_params;
+#define AH_PCIE_LINK_PARAMS_LINK_SPEED_MASK     (0x000000ff)
+#define AH_PCIE_LINK_PARAMS_LINK_SPEED_SHIFT    (0)
+#define AH_PCIE_LINK_PARAMS_LINK_WIDTH_MASK     (0x0000ff00)
+#define AH_PCIE_LINK_PARAMS_LINK_WIDTH_SHIFT    (8)
+#define AH_PCIE_LINK_PARAMS_ASPM_MODE_MASK      (0x00ff0000)
+#define AH_PCIE_LINK_PARAMS_ASPM_MODE_SHIFT     (16)
+#define AH_PCIE_LINK_PARAMS_ASPM_CAP_MASK       (0xff000000)
+#define AH_PCIE_LINK_PARAMS_ASPM_CAP_SHIFT      (24)
+#define AH_PCIE_LINK_PARAMS (*((u32 *)(STRUCT_OFFSET(ah_pcie_link_params))))
+
+	u32 rsrv_persist[5];	/* Persist reserved for MFW upgrades */
+};
+
+#define NVM_MAGIC_VALUE		0x669955aa
+
+enum nvm_image_type {
+	NVM_TYPE_TIM1 = 0x01,
+	NVM_TYPE_TIM2 = 0x02,
+	NVM_TYPE_MIM1 = 0x03,
+	NVM_TYPE_MIM2 = 0x04,
+	NVM_TYPE_MBA = 0x05,
+	NVM_TYPE_MODULES_PN = 0x06,
+	NVM_TYPE_VPD = 0x07,
+	NVM_TYPE_MFW_TRACE1 = 0x08,
+	NVM_TYPE_MFW_TRACE2 = 0x09,
+	NVM_TYPE_NVM_CFG1 = 0x0a,
+	NVM_TYPE_L2B = 0x0b,
+	NVM_TYPE_DIR1 = 0x0c,
+	NVM_TYPE_EAGLE_FW1 = 0x0d,
+	NVM_TYPE_FALCON_FW1 = 0x0e,
+	NVM_TYPE_PCIE_FW1 = 0x0f,
+	NVM_TYPE_HW_SET = 0x10,
+	NVM_TYPE_LIM = 0x11,
+	NVM_TYPE_AVS_FW1 = 0x12,
+	NVM_TYPE_DIR2 = 0x13,
+	NVM_TYPE_CCM = 0x14,
+	NVM_TYPE_EAGLE_FW2 = 0x15,
+	NVM_TYPE_FALCON_FW2 = 0x16,
+	NVM_TYPE_PCIE_FW2 = 0x17,
+	NVM_TYPE_AVS_FW2 = 0x18,
+	NVM_TYPE_INIT_HW = 0x19,
+	NVM_TYPE_DEFAULT_CFG = 0x1a,
+	NVM_TYPE_MDUMP = 0x1b,
+	NVM_TYPE_META = 0x1c,
+	NVM_TYPE_ISCSI_CFG = 0x1d,
+	NVM_TYPE_FCOE_CFG = 0x1f,
+	NVM_TYPE_ETH_PHY_FW1 = 0x20,
+	NVM_TYPE_ETH_PHY_FW2 = 0x21,
+	NVM_TYPE_BDN = 0x22,
+	NVM_TYPE_8485X_PHY_FW = 0x23,
+	NVM_TYPE_PUB_KEY = 0x24,
+	NVM_TYPE_RECOVERY = 0x25,
+	NVM_TYPE_PLDM = 0x26,
+	NVM_TYPE_UPK1 = 0x27,
+	NVM_TYPE_UPK2 = 0x28,
+	NVM_TYPE_MASTER_KC = 0x29,
+	NVM_TYPE_BACKUP_KC = 0x2a,
+	NVM_TYPE_HW_DUMP = 0x2b,
+	NVM_TYPE_HW_DUMP_OUT = 0x2c,
+	NVM_TYPE_BIN_NVM_META = 0x30,
+	NVM_TYPE_ROM_TEST = 0xf0,
+	NVM_TYPE_88X33X0_PHY_FW = 0x31,
+	NVM_TYPE_88X33X0_PHY_SLAVE_FW = 0x32,
+	NVM_TYPE_MAX,
+};
+
+#define DIR_ID_1    (0)
+
 #endif /* __ECORE_HSI_COMMON__ */
diff --git a/drivers/net/qede/base/ecore_hsi_debug_tools.h b/drivers/net/qede/base/ecore_hsi_debug_tools.h
index eb72e93cf..c5ef67f84 100644
--- a/drivers/net/qede/base/ecore_hsi_debug_tools.h
+++ b/drivers/net/qede/base/ecore_hsi_debug_tools.h
@@ -245,6 +245,7 @@ struct dbg_mode_hdr {
  * Attention register
  */
 struct dbg_attn_reg {
+	struct dbg_mode_hdr mode /* Mode header */;
 /* The offset of this registers attentions within the blocks attentions list
  * (a value in the range 0..number of block attentions-1)
  */
@@ -1049,5 +1050,4 @@ struct dbg_tools_data {
 };
 
 
-
 #endif /* __ECORE_HSI_DEBUG_TOOLS__ */
diff --git a/drivers/net/qede/base/ecore_mcp.c b/drivers/net/qede/base/ecore_mcp.c
index 0a9e26805..cab089d81 100644
--- a/drivers/net/qede/base/ecore_mcp.c
+++ b/drivers/net/qede/base/ecore_mcp.c
@@ -3621,6 +3621,217 @@ enum _ecore_status_t ecore_mcp_bist_nvm_test_get_image_att(
 	return rc;
 }
 
+enum _ecore_status_t
+ecore_mcp_bist_nvm_get_num_images(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt, u32 *num_images)
+{
+	u32 drv_mb_param = 0, rsp;
+	enum _ecore_status_t rc = ECORE_SUCCESS;
+
+	SET_MFW_FIELD(drv_mb_param, DRV_MB_PARAM_BIST_TEST_INDEX,
+		      DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES);
+
+	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
+			   drv_mb_param, &rsp, num_images);
+	if (rc != ECORE_SUCCESS)
+		return rc;
+
+	if (rsp == FW_MSG_CODE_UNSUPPORTED)
+		rc = ECORE_NOTIMPL;
+	else if (rsp != FW_MSG_CODE_OK)
+		rc = ECORE_UNKNOWN_ERROR;
+
+	return rc;
+}
+
+enum _ecore_status_t
+ecore_mcp_bist_nvm_get_image_att(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 struct bist_nvm_image_att *p_image_att,
+				 u32 image_index)
+{
+	u32 buf_size, nvm_offset = 0, resp, param;
+	enum _ecore_status_t rc;
+
+	SET_MFW_FIELD(nvm_offset, DRV_MB_PARAM_BIST_TEST_INDEX,
+		      DRV_MB_PARAM_BIST_NVM_TEST_IMAGE_BY_INDEX);
+	SET_MFW_FIELD(nvm_offset, DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX,
+		      image_index);
+	rc = ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
+				  nvm_offset, &resp, &param, &buf_size,
+				  (u32 *)p_image_att);
+	if (rc != ECORE_SUCCESS)
+		return rc;
+
+	if (resp == FW_MSG_CODE_UNSUPPORTED)
+		rc = ECORE_NOTIMPL;
+	else if ((resp != FW_MSG_CODE_OK) || (p_image_att->return_code != 1))
+		rc = ECORE_UNKNOWN_ERROR;
+
+	return rc;
+}
+
+enum _ecore_status_t ecore_mcp_nvm_info_populate(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_nvm_image_info nvm_info;
+	struct ecore_ptt *p_ptt;
+	enum _ecore_status_t rc;
+	u32 i;
+
+	if (p_hwfn->nvm_info.valid)
+		return ECORE_SUCCESS;
+
+#ifndef ASIC_ONLY
+	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev) ||
+	    CHIP_REV_IS_TEDIBEAR(p_hwfn->p_dev))
+		return ECORE_SUCCESS;
+#endif
+
+	p_ptt = ecore_ptt_acquire(p_hwfn);
+	if (!p_ptt) {
+		DP_ERR(p_hwfn, "failed to acquire ptt\n");
+		return ECORE_BUSY;
+	}
+
+	/* Acquire from MFW the amount of available images */
+	OSAL_MEM_ZERO(&nvm_info, sizeof(nvm_info));
+	rc = ecore_mcp_bist_nvm_get_num_images(p_hwfn, p_ptt,
+					       &nvm_info.num_images);
+	if (rc == ECORE_NOTIMPL) {
+		DP_INFO(p_hwfn, "DRV_MSG_CODE_BIST_TEST is not supported\n");
+		goto out;
+	} else if ((rc != ECORE_SUCCESS) || (nvm_info.num_images == 0)) {
+		DP_ERR(p_hwfn, "Failed getting number of images\n");
+		goto err0;
+	}
+
+	nvm_info.image_att = OSAL_ALLOC(p_hwfn->p_dev, GFP_KERNEL,
+					 nvm_info.num_images *
+					 sizeof(struct bist_nvm_image_att));
+	if (!nvm_info.image_att) {
+		rc = ECORE_NOMEM;
+		goto err0;
+	}
+
+	/* Iterate over images and get their attributes */
+	for (i = 0; i < nvm_info.num_images; i++) {
+		rc = ecore_mcp_bist_nvm_get_image_att(p_hwfn, p_ptt,
+						      &nvm_info.image_att[i],
+						      i);
+		if (rc != ECORE_SUCCESS) {
+			DP_ERR(p_hwfn,
+			       "Failed getting image index %d attributes\n",
+			       i);
+			goto err1;
+		}
+
+		DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "image index %d, size %x\n", i,
+			   nvm_info.image_att[i].len);
+	}
+out:
+	/* Update hwfn's nvm_info */
+	if (nvm_info.num_images) {
+		p_hwfn->nvm_info.num_images = nvm_info.num_images;
+		if (p_hwfn->nvm_info.image_att)
+			OSAL_FREE(p_hwfn->p_dev, p_hwfn->nvm_info.image_att);
+		p_hwfn->nvm_info.image_att = nvm_info.image_att;
+		p_hwfn->nvm_info.valid = true;
+	}
+
+	ecore_ptt_release(p_hwfn, p_ptt);
+	return ECORE_SUCCESS;
+
+err1:
+	OSAL_FREE(p_hwfn->p_dev, nvm_info.image_att);
+err0:
+	ecore_ptt_release(p_hwfn, p_ptt);
+	return rc;
+}
+
+enum _ecore_status_t
+ecore_mcp_get_nvm_image_att(struct ecore_hwfn *p_hwfn,
+			    enum ecore_nvm_images image_id,
+			    struct ecore_nvm_image_att *p_image_att)
+{
+	enum nvm_image_type type;
+	u32 i;
+
+	/* Translate image_id into MFW definitions */
+	switch (image_id) {
+	case ECORE_NVM_IMAGE_ISCSI_CFG:
+		type = NVM_TYPE_ISCSI_CFG;
+		break;
+	case ECORE_NVM_IMAGE_FCOE_CFG:
+		type = NVM_TYPE_FCOE_CFG;
+		break;
+	case ECORE_NVM_IMAGE_MDUMP:
+		type = NVM_TYPE_MDUMP;
+		break;
+	case ECORE_NVM_IMAGE_NVM_CFG1:
+		type = NVM_TYPE_NVM_CFG1;
+		break;
+	case ECORE_NVM_IMAGE_DEFAULT_CFG:
+		type = NVM_TYPE_DEFAULT_CFG;
+		break;
+	case ECORE_NVM_IMAGE_NVM_META:
+		type = NVM_TYPE_META;
+		break;
+	default:
+		DP_NOTICE(p_hwfn, false, "Unknown request of image_id %08x\n",
+			  image_id);
+		return ECORE_INVAL;
+	}
+
+	ecore_mcp_nvm_info_populate(p_hwfn);
+	for (i = 0; i < p_hwfn->nvm_info.num_images; i++) {
+		if (type == p_hwfn->nvm_info.image_att[i].image_type)
+			break;
+	}
+	if (i == p_hwfn->nvm_info.num_images) {
+		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
+			   "Failed to find nvram image of type %08x\n",
+			   image_id);
+		return ECORE_NOENT;
+	}
+
+	p_image_att->start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr;
+	p_image_att->length = p_hwfn->nvm_info.image_att[i].len;
+
+	return ECORE_SUCCESS;
+}
+
+enum _ecore_status_t ecore_mcp_get_nvm_image(struct ecore_hwfn *p_hwfn,
+					     enum ecore_nvm_images image_id,
+					     u8 *p_buffer, u32 buffer_len)
+{
+	struct ecore_nvm_image_att image_att;
+	enum _ecore_status_t rc;
+
+	OSAL_MEM_ZERO(p_buffer, buffer_len);
+
+	rc = ecore_mcp_get_nvm_image_att(p_hwfn, image_id, &image_att);
+	if (rc != ECORE_SUCCESS)
+		return rc;
+
+	/* Validate sizes - both the image's and the supplied buffer's */
+	if (image_att.length <= 4) {
+		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
+			   "Image [%d] is too small - only %d bytes\n",
+			   image_id, image_att.length);
+		return ECORE_INVAL;
+	}
+
+	if (image_att.length > buffer_len) {
+		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
+			   "Image [%d] is too big - %08x bytes where only %08x are available\n",
+			   image_id, image_att.length, buffer_len);
+		return ECORE_NOMEM;
+	}
+
+	return ecore_mcp_nvm_read(p_hwfn->p_dev, image_att.start_addr,
+				  (u8 *)p_buffer, image_att.length);
+}
+
 enum _ecore_status_t
 ecore_mcp_get_temperature_info(struct ecore_hwfn *p_hwfn,
 			       struct ecore_ptt *p_ptt,
diff --git a/drivers/net/qede/base/ecore_mcp_api.h b/drivers/net/qede/base/ecore_mcp_api.h
index dc889ab8e..53c130be7 100644
--- a/drivers/net/qede/base/ecore_mcp_api.h
+++ b/drivers/net/qede/base/ecore_mcp_api.h
@@ -121,6 +121,10 @@ struct ecore_mcp_function_info {
 enum ecore_nvm_images {
 	ECORE_NVM_IMAGE_ISCSI_CFG,
 	ECORE_NVM_IMAGE_FCOE_CFG,
+	ECORE_NVM_IMAGE_MDUMP,
+	ECORE_NVM_IMAGE_NVM_CFG1,
+	ECORE_NVM_IMAGE_DEFAULT_CFG,
+	ECORE_NVM_IMAGE_NVM_META,
 };
 #endif
 
@@ -970,6 +974,39 @@ enum _ecore_status_t ecore_mcp_phy_read(struct ecore_dev *p_dev, u32 cmd,
 enum _ecore_status_t ecore_mcp_nvm_read(struct ecore_dev *p_dev, u32 addr,
 			   u8 *p_buf, u32 len);
 
+struct ecore_nvm_image_att {
+	u32 start_addr;
+	u32 length;
+};
+
+/**
+ * @brief Allows reading a whole nvram image
+ *
+ * @param p_hwfn
+ * @param image_id - image to get attributes for
+ * @param p_image_att - image attributes structure into which to fill data
+ *
+ * @return enum _ecore_status_t - ECORE_SUCCESS - operation was successful.
+ */
+enum _ecore_status_t
+ecore_mcp_get_nvm_image_att(struct ecore_hwfn *p_hwfn,
+			    enum ecore_nvm_images image_id,
+			    struct ecore_nvm_image_att *p_image_att);
+
+/**
+ * @brief Allows reading a whole nvram image
+ *
+ * @param p_hwfn
+ * @param image_id - image requested for reading
+ * @param p_buffer - allocated buffer into which to fill data
+ * @param buffer_len - length of the allocated buffer.
+ *
+ * @return ECORE_SUCCESS if p_buffer now contains the nvram image.
+ */
+enum _ecore_status_t ecore_mcp_get_nvm_image(struct ecore_hwfn *p_hwfn,
+					     enum ecore_nvm_images image_id,
+					     u8 *p_buffer, u32 buffer_len);
+
 /**
  * @brief - Sends an NVM write command request to the MFW with
  *          payload.
diff --git a/drivers/net/qede/base/ecore_status.h b/drivers/net/qede/base/ecore_status.h
index b893f1d41..01cf9fd31 100644
--- a/drivers/net/qede/base/ecore_status.h
+++ b/drivers/net/qede/base/ecore_status.h
@@ -8,6 +8,8 @@
 #define __ECORE_STATUS_H__
 
 enum _ecore_status_t {
+	ECORE_NOENT = -15,
+	ECORE_CONN_REFUSED = -14,
 	ECORE_CONN_RESET = -13,
 	ECORE_UNKNOWN_ERROR  = -12,
 	ECORE_NORESOURCES	 = -11,
diff --git a/drivers/net/qede/base/reg_addr.h b/drivers/net/qede/base/reg_addr.h
index 91d889dc8..c84d3865f 100644
--- a/drivers/net/qede/base/reg_addr.h
+++ b/drivers/net/qede/base/reg_addr.h
@@ -1245,3 +1245,849 @@
 #define DORQ_REG_VF_USAGE_CNT_LIM 0x1009ccUL
 #define PGLUE_B_REG_SR_IOV_DISABLED_REQUEST 0x2aa06cUL
 #define PGLUE_B_REG_SR_IOV_DISABLED_REQUEST_CLR 0x2aa070UL
+
+#define PSWRQ2_REG_ILT_MEMORY_SIZE_BB 15200
+#define PSWRQ2_REG_ILT_MEMORY_SIZE_K2 22000
+#define TSEM_REG_DBG_GPRE_VECT 0x1701410UL
+#define MSEM_REG_DBG_GPRE_VECT 0x1801410UL
+#define USEM_REG_DBG_GPRE_VECT 0x1901410UL
+#define XSEM_REG_DBG_GPRE_VECT 0x1401410UL
+#define YSEM_REG_DBG_GPRE_VECT 0x1501410UL
+#define PSEM_REG_DBG_GPRE_VECT 0x1601410UL
+#define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE 0x000748UL
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_WRITE_DISABLE (0x1UL << 0)
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_WRITE_DISABLE_SHIFT 0
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_READ_DISABLE (0x1UL << 1)
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_READ_DISABLE_SHIFT 1
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_INTERRUPT_DISABLE (0x1UL << 2)
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_INTERRUPT_DISABLE_SHIFT 2
+#define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE 0x00074cUL
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_STORE_DATA_DISABLE (0x1UL << 0)
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_STORE_DATA_DISABLE_SHIFT 0
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_LOAD_DATA_DISABLE (0x1UL << 1)
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_LOAD_DATA_DISABLE_SHIFT 1
+#define NWS_REG_NWS_CMU_K2 0x720000UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_7_0_K2 0x000680UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_15_8_K2 0x000684UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_7_0_K2 0x0006c0UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_11_8_K2 0x0006c4UL
+#define MS_REG_MS_CMU_K2 0x6a4000UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X132_K2 0x000210UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X133_K2 0x000214UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X130_K2 0x000208UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X131_K2 0x00020cUL
+#define PHY_PCIE_REG_PHY0_K2 0x620000UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2 0x000210UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2 0x000214UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2 0x000208UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2 0x00020cUL
+#define PHY_PCIE_REG_PHY1_K2 0x624000UL
+#define PCIE_REG_DBG_REPEAT_THRESHOLD_COUNT_K2 0x054364UL
+#define PCIE_REG_DBG_FW_TRIGGER_ENABLE_K2 0x05436cUL
+#define RDIF_REG_DEBUG_ERROR_INFO 0x300400UL
+#define RDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define RDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define TDIF_REG_DEBUG_ERROR_INFO 0x310400UL
+#define TDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define TDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define SEM_FAST_REG_VFC_STATUS 0x000b4cUL
+  #define SEM_FAST_REG_VFC_STATUS_RESPONSE_READY (0x1UL << 0)
+  #define SEM_FAST_REG_VFC_STATUS_RESPONSE_READY_SHIFT 0
+  #define SEM_FAST_REG_VFC_STATUS_VFC_BUSY (0x1UL << 1)
+  #define SEM_FAST_REG_VFC_STATUS_VFC_BUSY_SHIFT 1
+  #define SEM_FAST_REG_VFC_STATUS_SENDING_CMD_ON_GOING (0x1UL << 2)
+  #define SEM_FAST_REG_VFC_STATUS_SENDING_CMD_ON_GOING_SHIFT 2
+#define RSS_REG_RSS_RAM_DATA_SIZE 4
+#define BRB_REG_BIG_RAM_DATA_SIZE 64
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_1 0x0084c0UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_2 0x0084e4UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_3 0x008508UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_4 0x00852cUL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_5 0x008550UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_6 0x008574UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_7 0x008598UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_NIG 0x0085bcUL
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_PXP 0x0085e0UL
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_MCP_OUT_0 0x008628UL
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR 0x008748UL
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_SYS_KILL 0x008604UL
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO31_SHIFT 31
+#define DBG_REG_FULL_BUFFER_THR 0x01045cUL
+#define MISC_REG_AEU_MASK_ATTN_MCP 0x008498UL
+#define MISC_REG_AEU_SYS_KILL_BEHAVIOR 0x008800UL
+#define MISC_REG_AEU_GENERAL_MASK 0x008828UL
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_PXP_CLOSE_MASK (0x1UL << 0)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_PXP_CLOSE_MASK_SHIFT 0
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_NIG_CLOSE_MASK (0x1UL << 1)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_NIG_CLOSE_MASK_SHIFT 1
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_SYS_KILL_MASK (0x1UL << 2)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_SYS_KILL_MASK_SHIFT 2
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_GLB_UNC_ERR_MASK (0x1UL << 3)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_GLB_UNC_ERR_MASK_SHIFT 3
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 7f5a34bcb..b5d6c7c43 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -7,7 +7,6 @@
 #include "qede_ethdev.h"
 #include <rte_string_fns.h>
 #include <rte_alarm.h>
-#include <rte_version.h>
 #include <rte_kvargs.h>
 
 static const struct qed_eth_ops *qed_ops;
diff --git a/drivers/net/qede/qede_main.c b/drivers/net/qede/qede_main.c
index 02f70beb3..51aa639c6 100644
--- a/drivers/net/qede/qede_main.c
+++ b/drivers/net/qede/qede_main.c
@@ -5,7 +5,6 @@
  */
 
 #include <limits.h>
-#include <time.h>
 #include <rte_alarm.h>
 #include <rte_string_fns.h>
 
@@ -66,7 +65,7 @@ qed_probe(struct ecore_dev *edev, struct rte_pci_device *pci_dev,
 	hw_prepare_params.initiate_pf_flr = true;
 	hw_prepare_params.allow_mdump = false;
 	hw_prepare_params.b_en_pacing = false;
-	hw_prepare_params.epoch = (u32)time(NULL);
+	hw_prepare_params.epoch = OSAL_GET_EPOCH(ECORE_LEADING_HWFN(edev));
 	rc = ecore_hw_prepare(edev, &hw_prepare_params);
 	if (rc) {
 		DP_ERR(edev, "hw prepare failed\n");
-- 
2.18.0


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

* [dpdk-dev] [PATCH v4 3/4] net/qede: add infrastructure for debug data collection
  2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 " Rasesh Mody
                       ` (2 preceding siblings ...)
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 2/4] net/qede/base: add changes for debug data collection Rasesh Mody
@ 2020-07-07 21:16     ` Rasesh Mody
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 4/4] net/qede: add support for get register operation Rasesh Mody
  4 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-07-07 21:16 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

The patch adds QEDE PMD ops and APIs to calculate the size and collect
the debug dump for various firmware components. The patch adds new files
qede_debug.[ch] that has all the firmware debug data collection
infrastructure changes.

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/qede/Makefile        |    4 +-
 drivers/net/qede/base/bcm_osal.h |    5 +-
 drivers/net/qede/qede_debug.c    | 8120 ++++++++++++++++++++++++++++++
 drivers/net/qede/qede_debug.h    |  759 +++
 drivers/net/qede/qede_if.h       |   45 +
 drivers/net/qede/qede_main.c     |   39 +-
 6 files changed, 8968 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/qede/qede_debug.c
 create mode 100644 drivers/net/qede/qede_debug.h

diff --git a/drivers/net/qede/Makefile b/drivers/net/qede/Makefile
index 5810b4d49..3b00338ff 100644
--- a/drivers/net/qede/Makefile
+++ b/drivers/net/qede/Makefile
@@ -11,7 +11,6 @@ include $(RTE_SDK)/mk/rte.vars.mk
 LIB = librte_pmd_qede.a
 
 CFLAGS += -O3
-CFLAGS += $(WERROR_FLAGS)
 LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
 LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs
 LDLIBS += -lrte_bus_pci
@@ -37,7 +36,6 @@ CFLAGS_BASE_DRIVER += -Wno-missing-prototypes
 
 ifneq ($(CONFIG_RTE_TOOLCHAIN_ICC),y)
 CFLAGS_BASE_DRIVER += -Wno-unused-value
-CFLAGS_BASE_DRIVER += -Wno-format-nonliteral
 ifeq ($(OS_TYPE),Linux)
 ifeq ($(shell clang -Wno-shift-negative-value -Werror -E - < /dev/null > /dev/null 2>&1; echo $$?),0)
 CFLAGS_BASE_DRIVER += -Wno-shift-negative-value
@@ -48,6 +46,7 @@ endif
 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
 ifeq ($(shell test $(GCC_VERSION) -ge 44 && echo 1), 1)
 CFLAGS_BASE_DRIVER += -Wno-unused-but-set-variable
+CFLAGS += -Wno-format-nonliteral
 endif
 CFLAGS_BASE_DRIVER += -Wno-missing-declarations
 ifeq ($(shell test $(GCC_VERSION) -ge 46 && echo 1), 1)
@@ -104,5 +103,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_ethdev.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_main.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_rxtx.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_filter.c
+SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_debug.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index 6ea3e7dda..b4b94231b 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -457,7 +457,10 @@ void qed_set_platform_str(struct ecore_hwfn *p_hwfn,
 #define OSAL_SET_PLATFORM_STR(p_hwfn, buf_str, buf_size) \
 	qed_set_platform_str(p_hwfn, buf_str, buf_size)
 #define OSAL_GET_EPOCH(p_hwfn) ((u32)time(NULL))
-#define OSAL_DBG_ALLOC_USER_DATA(p_hwfn, user_data_ptr) (0)
+enum dbg_status	qed_dbg_alloc_user_data(struct ecore_hwfn *p_hwfn,
+					void **user_data_ptr);
+#define OSAL_DBG_ALLOC_USER_DATA(p_hwfn, user_data_ptr) \
+	qed_dbg_alloc_user_data(p_hwfn, user_data_ptr)
 #define OSAL_DB_REC_OCCURRED(p_hwfn) nothing
 
 #endif /* __BCM_OSAL_H */
diff --git a/drivers/net/qede/qede_debug.c b/drivers/net/qede/qede_debug.c
new file mode 100644
index 000000000..dd54e50be
--- /dev/null
+++ b/drivers/net/qede/qede_debug.c
@@ -0,0 +1,8120 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Marvell Semiconductor Inc.
+ * All rights reserved.
+ * www.marvell.com
+ */
+
+#include <rte_common.h>
+#include "base/bcm_osal.h"
+#include "base/ecore.h"
+#include "base/ecore_cxt.h"
+#include "base/ecore_hsi_common.h"
+#include "base/ecore_hw.h"
+#include "base/ecore_mcp.h"
+#include "base/reg_addr.h"
+#include "qede_debug.h"
+
+/* Memory groups enum */
+enum mem_groups {
+	MEM_GROUP_PXP_MEM,
+	MEM_GROUP_DMAE_MEM,
+	MEM_GROUP_CM_MEM,
+	MEM_GROUP_QM_MEM,
+	MEM_GROUP_DORQ_MEM,
+	MEM_GROUP_BRB_RAM,
+	MEM_GROUP_BRB_MEM,
+	MEM_GROUP_PRS_MEM,
+	MEM_GROUP_SDM_MEM,
+	MEM_GROUP_PBUF,
+	MEM_GROUP_IOR,
+	MEM_GROUP_RAM,
+	MEM_GROUP_BTB_RAM,
+	MEM_GROUP_RDIF_CTX,
+	MEM_GROUP_TDIF_CTX,
+	MEM_GROUP_CFC_MEM,
+	MEM_GROUP_CONN_CFC_MEM,
+	MEM_GROUP_CAU_PI,
+	MEM_GROUP_CAU_MEM,
+	MEM_GROUP_CAU_MEM_EXT,
+	MEM_GROUP_PXP_ILT,
+	MEM_GROUP_MULD_MEM,
+	MEM_GROUP_BTB_MEM,
+	MEM_GROUP_IGU_MEM,
+	MEM_GROUP_IGU_MSIX,
+	MEM_GROUP_CAU_SB,
+	MEM_GROUP_BMB_RAM,
+	MEM_GROUP_BMB_MEM,
+	MEM_GROUP_TM_MEM,
+	MEM_GROUP_TASK_CFC_MEM,
+	MEM_GROUPS_NUM
+};
+
+/* Memory groups names */
+static const char * const s_mem_group_names[] = {
+	"PXP_MEM",
+	"DMAE_MEM",
+	"CM_MEM",
+	"QM_MEM",
+	"DORQ_MEM",
+	"BRB_RAM",
+	"BRB_MEM",
+	"PRS_MEM",
+	"SDM_MEM",
+	"PBUF",
+	"IOR",
+	"RAM",
+	"BTB_RAM",
+	"RDIF_CTX",
+	"TDIF_CTX",
+	"CFC_MEM",
+	"CONN_CFC_MEM",
+	"CAU_PI",
+	"CAU_MEM",
+	"CAU_MEM_EXT",
+	"PXP_ILT",
+	"MULD_MEM",
+	"BTB_MEM",
+	"IGU_MEM",
+	"IGU_MSIX",
+	"CAU_SB",
+	"BMB_RAM",
+	"BMB_MEM",
+	"TM_MEM",
+	"TASK_CFC_MEM",
+};
+
+/* Idle check conditions */
+
+static u32 cond5(const u32 *r, const u32 *imm)
+{
+	return ((r[0] & imm[0]) != imm[1]) && ((r[1] & imm[2]) != imm[3]);
+}
+
+static u32 cond7(const u32 *r, const u32 *imm)
+{
+	return ((r[0] >> imm[0]) & imm[1]) != imm[2];
+}
+
+static u32 cond6(const u32 *r, const u32 *imm)
+{
+	return (r[0] & imm[0]) != imm[1];
+}
+
+static u32 cond9(const u32 *r, const u32 *imm)
+{
+	return ((r[0] & imm[0]) >> imm[1]) !=
+		(((r[0] & imm[2]) >> imm[3]) | ((r[1] & imm[4]) << imm[5]));
+}
+
+static u32 cond10(const u32 *r, const u32 *imm)
+{
+	return ((r[0] & imm[0]) >> imm[1]) != (r[0] & imm[2]);
+}
+
+static u32 cond4(const u32 *r, const u32 *imm)
+{
+	return (r[0] & ~imm[0]) != imm[1];
+}
+
+static u32 cond0(const u32 *r, const u32 *imm)
+{
+	return (r[0] & ~r[1]) != imm[0];
+}
+
+static u32 cond1(const u32 *r, const u32 *imm)
+{
+	return r[0] != imm[0];
+}
+
+static u32 cond11(const u32 *r, const u32 *imm)
+{
+	return r[0] != r[1] && r[2] == imm[0];
+}
+
+static u32 cond12(const u32 *r, const u32 *imm)
+{
+	return r[0] != r[1] && r[2] > imm[0];
+}
+
+static u32 cond3(const u32 *r, const __rte_unused u32 *imm)
+{
+	return r[0] != r[1];
+}
+
+static u32 cond13(const u32 *r, const u32 *imm)
+{
+	return r[0] & imm[0];
+}
+
+static u32 cond8(const u32 *r, const u32 *imm)
+{
+	return r[0] < (r[1] - imm[0]);
+}
+
+static u32 cond2(const u32 *r, const u32 *imm)
+{
+	return r[0] > imm[0];
+}
+
+/* Array of Idle Check conditions */
+static u32(*cond_arr[]) (const u32 *r, const u32 *imm) = {
+	cond0,
+	cond1,
+	cond2,
+	cond3,
+	cond4,
+	cond5,
+	cond6,
+	cond7,
+	cond8,
+	cond9,
+	cond10,
+	cond11,
+	cond12,
+	cond13,
+};
+
+#define NUM_PHYS_BLOCKS 84
+
+#define NUM_DBG_RESET_REGS 8
+
+/******************************* Data Types **********************************/
+
+enum hw_types {
+	HW_TYPE_ASIC,
+	PLATFORM_RESERVED,
+	PLATFORM_RESERVED2,
+	PLATFORM_RESERVED3,
+	PLATFORM_RESERVED4,
+	MAX_HW_TYPES
+};
+
+/* CM context types */
+enum cm_ctx_types {
+	CM_CTX_CONN_AG,
+	CM_CTX_CONN_ST,
+	CM_CTX_TASK_AG,
+	CM_CTX_TASK_ST,
+	NUM_CM_CTX_TYPES
+};
+
+/* Debug bus frame modes */
+enum dbg_bus_frame_modes {
+	DBG_BUS_FRAME_MODE_4ST = 0,	/* 4 Storm dwords (no HW) */
+	DBG_BUS_FRAME_MODE_2ST_2HW = 1,	/* 2 Storm dwords, 2 HW dwords */
+	DBG_BUS_FRAME_MODE_1ST_3HW = 2,	/* 1 Storm dwords, 3 HW dwords */
+	DBG_BUS_FRAME_MODE_4HW = 3,	/* 4 HW dwords (no Storms) */
+	DBG_BUS_FRAME_MODE_8HW = 4,	/* 8 HW dwords (no Storms) */
+	DBG_BUS_NUM_FRAME_MODES
+};
+
+/* Chip constant definitions */
+struct chip_defs {
+	const char *name;
+	u32 num_ilt_pages;
+};
+
+/* HW type constant definitions */
+struct hw_type_defs {
+	const char *name;
+	u32 delay_factor;
+	u32 dmae_thresh;
+	u32 log_thresh;
+};
+
+/* RBC reset definitions */
+struct rbc_reset_defs {
+	u32 reset_reg_addr;
+	u32 reset_val[MAX_CHIP_IDS];
+};
+
+/* Storm constant definitions.
+ * Addresses are in bytes, sizes are in quad-regs.
+ */
+struct storm_defs {
+	char letter;
+	enum block_id sem_block_id;
+	enum dbg_bus_clients dbg_client_id[MAX_CHIP_IDS];
+	bool has_vfc;
+	u32 sem_fast_mem_addr;
+	u32 sem_frame_mode_addr;
+	u32 sem_slow_enable_addr;
+	u32 sem_slow_mode_addr;
+	u32 sem_slow_mode1_conf_addr;
+	u32 sem_sync_dbg_empty_addr;
+	u32 sem_gpre_vect_addr;
+	u32 cm_ctx_wr_addr;
+	u32 cm_ctx_rd_addr[NUM_CM_CTX_TYPES];
+	u32 cm_ctx_lid_sizes[MAX_CHIP_IDS][NUM_CM_CTX_TYPES];
+};
+
+/* Debug Bus Constraint operation constant definitions */
+struct dbg_bus_constraint_op_defs {
+	u8 hw_op_val;
+	bool is_cyclic;
+};
+
+/* Storm Mode definitions */
+struct storm_mode_defs {
+	const char *name;
+	bool is_fast_dbg;
+	u8 id_in_hw;
+	u32 src_disable_reg_addr;
+	u32 src_enable_val;
+	bool exists[MAX_CHIP_IDS];
+};
+
+struct grc_param_defs {
+	u32 default_val[MAX_CHIP_IDS];
+	u32 min;
+	u32 max;
+	bool is_preset;
+	bool is_persistent;
+	u32 exclude_all_preset_val;
+	u32 crash_preset_val[MAX_CHIP_IDS];
+};
+
+/* Address is in 128b units. Width is in bits. */
+struct rss_mem_defs {
+	const char *mem_name;
+	const char *type_name;
+	u32 addr;
+	u32 entry_width;
+	u32 num_entries[MAX_CHIP_IDS];
+};
+
+struct vfc_ram_defs {
+	const char *mem_name;
+	const char *type_name;
+	u32 base_row;
+	u32 num_rows;
+};
+
+struct big_ram_defs {
+	const char *instance_name;
+	enum mem_groups mem_group_id;
+	enum mem_groups ram_mem_group_id;
+	enum dbg_grc_params grc_param;
+	u32 addr_reg_addr;
+	u32 data_reg_addr;
+	u32 is_256b_reg_addr;
+	u32 is_256b_bit_offset[MAX_CHIP_IDS];
+	u32 ram_size[MAX_CHIP_IDS]; /* In dwords */
+};
+
+struct phy_defs {
+	const char *phy_name;
+
+	/* PHY base GRC address */
+	u32 base_addr;
+
+	/* Relative address of indirect TBUS address register (bits 0..7) */
+	u32 tbus_addr_lo_addr;
+
+	/* Relative address of indirect TBUS address register (bits 8..10) */
+	u32 tbus_addr_hi_addr;
+
+	/* Relative address of indirect TBUS data register (bits 0..7) */
+	u32 tbus_data_lo_addr;
+
+	/* Relative address of indirect TBUS data register (bits 8..11) */
+	u32 tbus_data_hi_addr;
+};
+
+/* Split type definitions */
+struct split_type_defs {
+	const char *name;
+};
+
+/******************************** Constants **********************************/
+
+#define BYTES_IN_DWORD			sizeof(u32)
+/* In the macros below, size and offset are specified in bits */
+#define CEIL_DWORDS(size)		DIV_ROUND_UP(size, 32)
+#define FIELD_BIT_OFFSET(type, field)	type ## _ ## field ## _ ## OFFSET
+#define FIELD_BIT_SIZE(type, field)	type ## _ ## field ## _ ## SIZE
+#define FIELD_DWORD_OFFSET(type, field) \
+	 (int)(FIELD_BIT_OFFSET(type, field) / 32)
+#define FIELD_DWORD_SHIFT(type, field)	(FIELD_BIT_OFFSET(type, field) % 32)
+#define FIELD_BIT_MASK(type, field) \
+	(((1 << FIELD_BIT_SIZE(type, field)) - 1) << \
+	 FIELD_DWORD_SHIFT(type, field))
+
+#define SET_VAR_FIELD(var, type, field, val) \
+	do { \
+		var[FIELD_DWORD_OFFSET(type, field)] &=	\
+		(~FIELD_BIT_MASK(type, field));	\
+		var[FIELD_DWORD_OFFSET(type, field)] |= \
+		(val) << FIELD_DWORD_SHIFT(type, field); \
+	} while (0)
+
+#define ARR_REG_WR(dev, ptt, addr, arr, arr_size) \
+	do { \
+		for (i = 0; i < (arr_size); i++) \
+			ecore_wr(dev, ptt, addr,	(arr)[i]); \
+	} while (0)
+
+#define DWORDS_TO_BYTES(dwords)		((dwords) * BYTES_IN_DWORD)
+#define BYTES_TO_DWORDS(bytes)		((bytes) / BYTES_IN_DWORD)
+
+/* extra lines include a signature line + optional latency events line */
+#define NUM_EXTRA_DBG_LINES(block) \
+	(GET_FIELD((block)->flags, DBG_BLOCK_CHIP_HAS_LATENCY_EVENTS) ? 2 : 1)
+#define NUM_DBG_LINES(block) \
+	((block)->num_of_dbg_bus_lines + NUM_EXTRA_DBG_LINES(block))
+
+#define USE_DMAE			true
+#define PROTECT_WIDE_BUS		true
+
+#define RAM_LINES_TO_DWORDS(lines)	((lines) * 2)
+#define RAM_LINES_TO_BYTES(lines) \
+	DWORDS_TO_BYTES(RAM_LINES_TO_DWORDS(lines))
+
+#define REG_DUMP_LEN_SHIFT		24
+#define MEM_DUMP_ENTRY_SIZE_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_dump_mem))
+
+#define IDLE_CHK_RULE_SIZE_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_rule))
+
+#define IDLE_CHK_RESULT_HDR_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_result_hdr))
+
+#define IDLE_CHK_RESULT_REG_HDR_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_result_reg_hdr))
+
+#define PAGE_MEM_DESC_SIZE_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct phys_mem_desc))
+
+#define IDLE_CHK_MAX_ENTRIES_SIZE	32
+
+/* The sizes and offsets below are specified in bits */
+#define VFC_CAM_CMD_STRUCT_SIZE		64
+#define VFC_CAM_CMD_ROW_OFFSET		48
+#define VFC_CAM_CMD_ROW_SIZE		9
+#define VFC_CAM_ADDR_STRUCT_SIZE	16
+#define VFC_CAM_ADDR_OP_OFFSET		0
+#define VFC_CAM_ADDR_OP_SIZE		4
+#define VFC_CAM_RESP_STRUCT_SIZE	256
+#define VFC_RAM_ADDR_STRUCT_SIZE	16
+#define VFC_RAM_ADDR_OP_OFFSET		0
+#define VFC_RAM_ADDR_OP_SIZE		2
+#define VFC_RAM_ADDR_ROW_OFFSET		2
+#define VFC_RAM_ADDR_ROW_SIZE		10
+#define VFC_RAM_RESP_STRUCT_SIZE	256
+
+#define VFC_CAM_CMD_DWORDS		CEIL_DWORDS(VFC_CAM_CMD_STRUCT_SIZE)
+#define VFC_CAM_ADDR_DWORDS		CEIL_DWORDS(VFC_CAM_ADDR_STRUCT_SIZE)
+#define VFC_CAM_RESP_DWORDS		CEIL_DWORDS(VFC_CAM_RESP_STRUCT_SIZE)
+#define VFC_RAM_CMD_DWORDS		VFC_CAM_CMD_DWORDS
+#define VFC_RAM_ADDR_DWORDS		CEIL_DWORDS(VFC_RAM_ADDR_STRUCT_SIZE)
+#define VFC_RAM_RESP_DWORDS		CEIL_DWORDS(VFC_RAM_RESP_STRUCT_SIZE)
+
+#define NUM_VFC_RAM_TYPES		4
+
+#define VFC_CAM_NUM_ROWS		512
+
+#define VFC_OPCODE_CAM_RD		14
+#define VFC_OPCODE_RAM_RD		0
+
+#define NUM_RSS_MEM_TYPES		5
+
+#define NUM_BIG_RAM_TYPES		3
+#define BIG_RAM_NAME_LEN		3
+
+#define NUM_PHY_TBUS_ADDRESSES		2048
+#define PHY_DUMP_SIZE_DWORDS		(NUM_PHY_TBUS_ADDRESSES / 2)
+
+#define RESET_REG_UNRESET_OFFSET	4
+
+#define STALL_DELAY_MS			500
+
+#define STATIC_DEBUG_LINE_DWORDS	9
+
+#define NUM_COMMON_GLOBAL_PARAMS	11
+
+#define MAX_RECURSION_DEPTH		10
+
+#define FW_IMG_MAIN			1
+
+#define REG_FIFO_ELEMENT_DWORDS		2
+#define REG_FIFO_DEPTH_ELEMENTS		32
+#define REG_FIFO_DEPTH_DWORDS \
+	(REG_FIFO_ELEMENT_DWORDS * REG_FIFO_DEPTH_ELEMENTS)
+
+#define IGU_FIFO_ELEMENT_DWORDS		4
+#define IGU_FIFO_DEPTH_ELEMENTS		64
+#define IGU_FIFO_DEPTH_DWORDS \
+	(IGU_FIFO_ELEMENT_DWORDS * IGU_FIFO_DEPTH_ELEMENTS)
+
+#define PROTECTION_OVERRIDE_ELEMENT_DWORDS	2
+#define PROTECTION_OVERRIDE_DEPTH_ELEMENTS	20
+#define PROTECTION_OVERRIDE_DEPTH_DWORDS \
+	(PROTECTION_OVERRIDE_DEPTH_ELEMENTS * \
+	 PROTECTION_OVERRIDE_ELEMENT_DWORDS)
+
+#define MCP_SPAD_TRACE_OFFSIZE_ADDR \
+	(MCP_REG_SCRATCH + \
+	 offsetof(struct static_init, sections[SPAD_SECTION_TRACE]))
+
+#define MAX_SW_PLTAFORM_STR_SIZE	64
+
+#define EMPTY_FW_VERSION_STR		"???_???_???_???"
+#define EMPTY_FW_IMAGE_STR		"???????????????"
+
+/***************************** Constant Arrays *******************************/
+
+/* Chip constant definitions array */
+static struct chip_defs s_chip_defs[MAX_CHIP_IDS] = {
+	{"bb", PSWRQ2_REG_ILT_MEMORY_SIZE_BB / 2},
+	{"ah", PSWRQ2_REG_ILT_MEMORY_SIZE_K2 / 2}
+};
+
+/* Storm constant definitions array */
+static struct storm_defs s_storm_defs[] = {
+	/* Tstorm */
+	{'T', BLOCK_TSEM,
+		{DBG_BUS_CLIENT_RBCT, DBG_BUS_CLIENT_RBCT},
+		true,
+		TSEM_REG_FAST_MEMORY,
+		TSEM_REG_DBG_FRAME_MODE, TSEM_REG_SLOW_DBG_ACTIVE,
+		TSEM_REG_SLOW_DBG_MODE, TSEM_REG_DBG_MODE1_CFG,
+		TSEM_REG_SYNC_DBG_EMPTY, TSEM_REG_DBG_GPRE_VECT,
+		TCM_REG_CTX_RBC_ACCS,
+		{TCM_REG_AGG_CON_CTX, TCM_REG_SM_CON_CTX, TCM_REG_AGG_TASK_CTX,
+		 TCM_REG_SM_TASK_CTX},
+		{{4, 16, 2, 4}, {4, 16, 2, 4} } /* {bb} {k2} */
+	},
+
+	/* Mstorm */
+	{'M', BLOCK_MSEM,
+		{DBG_BUS_CLIENT_RBCT, DBG_BUS_CLIENT_RBCM},
+		false,
+		MSEM_REG_FAST_MEMORY,
+		MSEM_REG_DBG_FRAME_MODE,
+		MSEM_REG_SLOW_DBG_ACTIVE,
+		MSEM_REG_SLOW_DBG_MODE,
+		MSEM_REG_DBG_MODE1_CFG,
+		MSEM_REG_SYNC_DBG_EMPTY,
+		MSEM_REG_DBG_GPRE_VECT,
+		MCM_REG_CTX_RBC_ACCS,
+		{MCM_REG_AGG_CON_CTX, MCM_REG_SM_CON_CTX, MCM_REG_AGG_TASK_CTX,
+		 MCM_REG_SM_TASK_CTX },
+		{{1, 10, 2, 7}, {1, 10, 2, 7} } /* {bb} {k2}*/
+	},
+
+	/* Ustorm */
+	{'U', BLOCK_USEM,
+		{DBG_BUS_CLIENT_RBCU, DBG_BUS_CLIENT_RBCU},
+		false,
+		USEM_REG_FAST_MEMORY,
+		USEM_REG_DBG_FRAME_MODE,
+		USEM_REG_SLOW_DBG_ACTIVE,
+		USEM_REG_SLOW_DBG_MODE,
+		USEM_REG_DBG_MODE1_CFG,
+		USEM_REG_SYNC_DBG_EMPTY,
+		USEM_REG_DBG_GPRE_VECT,
+		UCM_REG_CTX_RBC_ACCS,
+		{UCM_REG_AGG_CON_CTX, UCM_REG_SM_CON_CTX, UCM_REG_AGG_TASK_CTX,
+		 UCM_REG_SM_TASK_CTX},
+		{{2, 13, 3, 3}, {2, 13, 3, 3} } /* {bb} {k2} */
+	},
+
+	/* Xstorm */
+	{'X', BLOCK_XSEM,
+		{DBG_BUS_CLIENT_RBCX, DBG_BUS_CLIENT_RBCX},
+		false,
+		XSEM_REG_FAST_MEMORY,
+		XSEM_REG_DBG_FRAME_MODE,
+		XSEM_REG_SLOW_DBG_ACTIVE,
+		XSEM_REG_SLOW_DBG_MODE,
+		XSEM_REG_DBG_MODE1_CFG,
+		XSEM_REG_SYNC_DBG_EMPTY,
+		XSEM_REG_DBG_GPRE_VECT,
+		XCM_REG_CTX_RBC_ACCS,
+		{XCM_REG_AGG_CON_CTX, XCM_REG_SM_CON_CTX, 0, 0},
+		{{9, 15, 0, 0}, {9, 15,	0, 0} } /* {bb} {k2} */
+	},
+
+	/* Ystorm */
+	{'Y', BLOCK_YSEM,
+		{DBG_BUS_CLIENT_RBCX, DBG_BUS_CLIENT_RBCY},
+		false,
+		YSEM_REG_FAST_MEMORY,
+		YSEM_REG_DBG_FRAME_MODE,
+		YSEM_REG_SLOW_DBG_ACTIVE,
+		YSEM_REG_SLOW_DBG_MODE,
+		YSEM_REG_DBG_MODE1_CFG,
+		YSEM_REG_SYNC_DBG_EMPTY,
+		YSEM_REG_DBG_GPRE_VECT,
+		YCM_REG_CTX_RBC_ACCS,
+		{YCM_REG_AGG_CON_CTX, YCM_REG_SM_CON_CTX, YCM_REG_AGG_TASK_CTX,
+		 YCM_REG_SM_TASK_CTX},
+		{{2, 3, 2, 12}, {2, 3, 2, 12} } /* {bb} {k2} */
+	},
+
+	/* Pstorm */
+	{'P', BLOCK_PSEM,
+		{DBG_BUS_CLIENT_RBCS, DBG_BUS_CLIENT_RBCS},
+		true,
+		PSEM_REG_FAST_MEMORY,
+		PSEM_REG_DBG_FRAME_MODE,
+		PSEM_REG_SLOW_DBG_ACTIVE,
+		PSEM_REG_SLOW_DBG_MODE,
+		PSEM_REG_DBG_MODE1_CFG,
+		PSEM_REG_SYNC_DBG_EMPTY,
+		PSEM_REG_DBG_GPRE_VECT,
+		PCM_REG_CTX_RBC_ACCS,
+		{0, PCM_REG_SM_CON_CTX, 0, 0},
+		{{0, 10, 0, 0}, {0, 10, 0, 0} } /* {bb} {k2} */
+	},
+};
+
+static struct hw_type_defs s_hw_type_defs[] = {
+	/* HW_TYPE_ASIC */
+	{"asic", 1, 256, 32768},
+	{"reserved", 0, 0, 0},
+	{"reserved2", 0, 0, 0},
+	{"reserved3", 0, 0, 0}
+};
+
+static struct grc_param_defs s_grc_param_defs[] = {
+	/* DBG_GRC_PARAM_DUMP_TSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_MSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_USTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_XSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_YSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_REGS */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_RAM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PBUF */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_IOR */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_VFC */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_CM_CTX */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_ILT */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_RSS */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_CAU */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_QM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_MCP */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_DORQ */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_CFC */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_IGU */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_BRB */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_BTB */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_BMB */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_RESERVED1 */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_MULD */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PRS */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_DMAE */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_TM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_SDM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_DIF */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_STATIC */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_UNSTALL */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_RESERVED2 */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_MCP_TRACE_META_SIZE */
+	{{0, 0}, 1, 0xffffffff, false, true, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_EXCLUDE_ALL */
+	{{0, 0}, 0, 1, true, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_CRASH */
+	{{0, 0}, 0, 1, true, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_PARITY_SAFE */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_CM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PHY */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_NO_MCP */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_NO_FW_VER */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_RESERVED3 */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_MCP_HW_DUMP */
+	{{0, 1}, 0, 1, false, false, 0, {0, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_ILT_CDUC */
+	{{1, 1}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_ILT_CDUT */
+	{{1, 1}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_CAU_EXT */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} }
+};
+
+static struct rss_mem_defs s_rss_mem_defs[] = {
+	{"rss_mem_cid", "rss_cid", 0, 32,
+	 {256, 320} },
+
+	{"rss_mem_key_msb", "rss_key", 1024, 256,
+	 {128, 208} },
+
+	{"rss_mem_key_lsb", "rss_key", 2048, 64,
+	 {128, 208} },
+
+	{"rss_mem_info", "rss_info", 3072, 16,
+	 {128, 208} },
+
+	{"rss_mem_ind", "rss_ind", 4096, 16,
+	 {16384, 26624} }
+};
+
+static struct vfc_ram_defs s_vfc_ram_defs[] = {
+	{"vfc_ram_tt1", "vfc_ram", 0, 512},
+	{"vfc_ram_mtt2", "vfc_ram", 512, 128},
+	{"vfc_ram_stt2", "vfc_ram", 640, 32},
+	{"vfc_ram_ro_vect", "vfc_ram", 672, 32}
+};
+
+static struct big_ram_defs s_big_ram_defs[] = {
+	{"BRB", MEM_GROUP_BRB_MEM, MEM_GROUP_BRB_RAM, DBG_GRC_PARAM_DUMP_BRB,
+	 BRB_REG_BIG_RAM_ADDRESS, BRB_REG_BIG_RAM_DATA,
+	 MISC_REG_BLOCK_256B_EN, {0, 0},
+	 {153600, 180224} },
+
+	{"BTB", MEM_GROUP_BTB_MEM, MEM_GROUP_BTB_RAM, DBG_GRC_PARAM_DUMP_BTB,
+	 BTB_REG_BIG_RAM_ADDRESS, BTB_REG_BIG_RAM_DATA,
+	 MISC_REG_BLOCK_256B_EN, {0, 1},
+	 {92160, 117760} },
+
+	{"BMB", MEM_GROUP_BMB_MEM, MEM_GROUP_BMB_RAM, DBG_GRC_PARAM_DUMP_BMB,
+	 BMB_REG_BIG_RAM_ADDRESS, BMB_REG_BIG_RAM_DATA,
+	 MISCS_REG_BLOCK_256B_EN, {0, 0},
+	 {36864, 36864} }
+};
+
+static struct rbc_reset_defs s_rbc_reset_defs[] = {
+	{MISCS_REG_RESET_PL_HV,
+	 {0x0, 0x400} },
+	{MISC_REG_RESET_PL_PDA_VMAIN_1,
+	 {0x4404040, 0x4404040} },
+	{MISC_REG_RESET_PL_PDA_VMAIN_2,
+	 {0x7, 0x7c00007} },
+	{MISC_REG_RESET_PL_PDA_VAUX,
+	 {0x2, 0x2} },
+};
+
+static struct phy_defs s_phy_defs[] = {
+	{"nw_phy", NWS_REG_NWS_CMU_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_7_0_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_15_8_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_7_0_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_11_8_K2},
+	{"sgmii_phy", MS_REG_MS_CMU_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X132_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X133_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X130_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X131_K2},
+	{"pcie_phy0", PHY_PCIE_REG_PHY0_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2},
+	{"pcie_phy1", PHY_PCIE_REG_PHY1_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2},
+};
+
+static struct split_type_defs s_split_type_defs[] = {
+	/* SPLIT_TYPE_NONE */
+	{"eng"},
+
+	/* SPLIT_TYPE_PORT */
+	{"port"},
+
+	/* SPLIT_TYPE_PF */
+	{"pf"},
+
+	/* SPLIT_TYPE_PORT_PF */
+	{"port"},
+
+	/* SPLIT_TYPE_VF */
+	{"vf"}
+};
+
+/******************************** Variables *********************************/
+
+/**
+ * The version of the calling app
+ */
+static u32 s_app_ver;
+
+/**************************** Private Functions ******************************/
+
+/* Reads and returns a single dword from the specified unaligned buffer */
+static u32 qed_read_unaligned_dword(u8 *buf)
+{
+	u32 dword;
+
+	memcpy((u8 *)&dword, buf, sizeof(dword));
+	return dword;
+}
+
+/* Sets the value of the specified GRC param */
+static void qed_grc_set_param(struct ecore_hwfn *p_hwfn,
+			      enum dbg_grc_params grc_param, u32 val)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	dev_data->grc.param_val[grc_param] = val;
+}
+
+/* Returns the value of the specified GRC param */
+static u32 qed_grc_get_param(struct ecore_hwfn *p_hwfn,
+			     enum dbg_grc_params grc_param)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	return dev_data->grc.param_val[grc_param];
+}
+
+/* Initializes the GRC parameters */
+static void qed_dbg_grc_init_params(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	if (!dev_data->grc.params_initialized) {
+		qed_dbg_grc_set_params_default(p_hwfn);
+		dev_data->grc.params_initialized = 1;
+	}
+}
+
+/* Sets pointer and size for the specified binary buffer type */
+static void qed_set_dbg_bin_buf(struct ecore_hwfn *p_hwfn,
+				enum bin_dbg_buffer_type buf_type,
+				const u32 *ptr, u32 size)
+{
+	struct virt_mem_desc *buf = &p_hwfn->dbg_arrays[buf_type];
+
+	buf->ptr = (void *)(osal_uintptr_t)ptr;
+	buf->size = size;
+}
+
+/* Initializes debug data for the specified device */
+static enum dbg_status qed_dbg_dev_init(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 num_pfs = 0, max_pfs_per_port = 0;
+
+	if (dev_data->initialized)
+		return DBG_STATUS_OK;
+
+	/* Set chip */
+	if (ECORE_IS_K2(p_hwfn->p_dev)) {
+		dev_data->chip_id = CHIP_K2;
+		dev_data->mode_enable[MODE_K2] = 1;
+		dev_data->num_vfs = MAX_NUM_VFS_K2;
+		num_pfs = MAX_NUM_PFS_K2;
+		max_pfs_per_port = MAX_NUM_PFS_K2 / 2;
+	} else if (ECORE_IS_BB_B0(p_hwfn->p_dev)) {
+		dev_data->chip_id = CHIP_BB;
+		dev_data->mode_enable[MODE_BB] = 1;
+		dev_data->num_vfs = MAX_NUM_VFS_BB;
+		num_pfs = MAX_NUM_PFS_BB;
+		max_pfs_per_port = MAX_NUM_PFS_BB;
+	} else {
+		return DBG_STATUS_UNKNOWN_CHIP;
+	}
+
+	/* Set HW type */
+	dev_data->hw_type = HW_TYPE_ASIC;
+	dev_data->mode_enable[MODE_ASIC] = 1;
+
+	/* Set port mode */
+	switch (p_hwfn->p_dev->num_ports_in_engine) {
+	case 1:
+		dev_data->mode_enable[MODE_PORTS_PER_ENG_1] = 1;
+		break;
+	case 2:
+		dev_data->mode_enable[MODE_PORTS_PER_ENG_2] = 1;
+		break;
+	case 4:
+		dev_data->mode_enable[MODE_PORTS_PER_ENG_4] = 1;
+		break;
+	}
+
+	/* Set 100G mode */
+	if (ECORE_IS_CMT(p_hwfn->p_dev))
+		dev_data->mode_enable[MODE_100G] = 1;
+
+	/* Set number of ports */
+	if (dev_data->mode_enable[MODE_PORTS_PER_ENG_1] ||
+	    dev_data->mode_enable[MODE_100G])
+		dev_data->num_ports = 1;
+	else if (dev_data->mode_enable[MODE_PORTS_PER_ENG_2])
+		dev_data->num_ports = 2;
+	else if (dev_data->mode_enable[MODE_PORTS_PER_ENG_4])
+		dev_data->num_ports = 4;
+
+	/* Set number of PFs per port */
+	dev_data->num_pfs_per_port = OSAL_MIN_T(u32,
+						num_pfs / dev_data->num_ports,
+						max_pfs_per_port);
+
+	/* Initializes the GRC parameters */
+	qed_dbg_grc_init_params(p_hwfn);
+
+	dev_data->use_dmae = true;
+	dev_data->initialized = 1;
+
+	return DBG_STATUS_OK;
+}
+
+static const struct dbg_block *get_dbg_block(struct ecore_hwfn *p_hwfn,
+					     enum block_id block_id)
+{
+	const struct dbg_block *dbg_block;
+
+	dbg_block = p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS].ptr;
+	return dbg_block + block_id;
+}
+
+static const struct dbg_block_chip *qed_get_dbg_block_per_chip(struct ecore_hwfn
+							       *p_hwfn,
+							       enum block_id
+							       block_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	return (const struct dbg_block_chip *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS_CHIP_DATA].ptr +
+	    block_id * MAX_CHIP_IDS + dev_data->chip_id;
+}
+
+static const struct dbg_reset_reg *qed_get_dbg_reset_reg(struct ecore_hwfn
+							 *p_hwfn,
+							 u8 reset_reg_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	return (const struct dbg_reset_reg *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_RESET_REGS].ptr +
+	    reset_reg_id * MAX_CHIP_IDS + dev_data->chip_id;
+}
+
+/* Reads the FW info structure for the specified Storm from the chip,
+ * and writes it to the specified fw_info pointer.
+ */
+static void qed_read_storm_fw_info(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   u8 storm_id, struct fw_info *fw_info)
+{
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	struct fw_info_location fw_info_location;
+	u32 addr, i, *dest;
+
+	memset(&fw_info_location, 0, sizeof(fw_info_location));
+	memset(fw_info, 0, sizeof(*fw_info));
+
+	/* Read first the address that points to fw_info location.
+	 * The address is located in the last line of the Storm RAM.
+	 */
+	addr = storm->sem_fast_mem_addr + SEM_FAST_REG_INT_RAM +
+	    DWORDS_TO_BYTES(SEM_FAST_REG_INT_RAM_SIZE) -
+	    sizeof(fw_info_location);
+
+	dest = (u32 *)&fw_info_location;
+
+	for (i = 0; i < BYTES_TO_DWORDS(sizeof(fw_info_location));
+	     i++, addr += BYTES_IN_DWORD)
+		dest[i] = ecore_rd(p_hwfn, p_ptt, addr);
+
+	/* Read FW version info from Storm RAM */
+	if (fw_info_location.size > 0 && fw_info_location.size <=
+	    sizeof(*fw_info)) {
+		addr = fw_info_location.grc_addr;
+		dest = (u32 *)fw_info;
+		for (i = 0; i < BYTES_TO_DWORDS(fw_info_location.size);
+		     i++, addr += BYTES_IN_DWORD)
+			dest[i] = ecore_rd(p_hwfn, p_ptt, addr);
+	}
+}
+
+/* Dumps the specified string to the specified buffer.
+ * Returns the dumped size in bytes.
+ */
+static u32 qed_dump_str(char *dump_buf, bool dump, const char *str)
+{
+	if (dump)
+		strcpy(dump_buf, str);
+
+	return (u32)strlen(str) + 1;
+}
+
+/* Dumps zeros to align the specified buffer to dwords.
+ * Returns the dumped size in bytes.
+ */
+static u32 qed_dump_align(char *dump_buf, bool dump, u32 byte_offset)
+{
+	u8 offset_in_dword, align_size;
+
+	offset_in_dword = (u8)(byte_offset & 0x3);
+	align_size = offset_in_dword ? BYTES_IN_DWORD - offset_in_dword : 0;
+
+	if (dump && align_size)
+		memset(dump_buf, 0, align_size);
+
+	return align_size;
+}
+
+/* Writes the specified string param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_str_param(u32 *dump_buf,
+			      bool dump,
+			      const char *param_name, const char *param_val)
+{
+	char *char_buf = (char *)dump_buf;
+	u32 offset = 0;
+
+	/* Dump param name */
+	offset += qed_dump_str(char_buf + offset, dump, param_name);
+
+	/* Indicate a string param value */
+	if (dump)
+		*(char_buf + offset) = 1;
+	offset++;
+
+	/* Dump param value */
+	offset += qed_dump_str(char_buf + offset, dump, param_val);
+
+	/* Align buffer to next dword */
+	offset += qed_dump_align(char_buf + offset, dump, offset);
+
+	return BYTES_TO_DWORDS(offset);
+}
+
+/* Writes the specified numeric param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_num_param(u32 *dump_buf,
+			      bool dump, const char *param_name, u32 param_val)
+{
+	char *char_buf = (char *)dump_buf;
+	u32 offset = 0;
+
+	/* Dump param name */
+	offset += qed_dump_str(char_buf + offset, dump, param_name);
+
+	/* Indicate a numeric param value */
+	if (dump)
+		*(char_buf + offset) = 0;
+	offset++;
+
+	/* Align buffer to next dword */
+	offset += qed_dump_align(char_buf + offset, dump, offset);
+
+	/* Dump param value (and change offset from bytes to dwords) */
+	offset = BYTES_TO_DWORDS(offset);
+	if (dump)
+		*(dump_buf + offset) = param_val;
+	offset++;
+
+	return offset;
+}
+
+/* Reads the FW version and writes it as a param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_fw_ver_param(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf, bool dump)
+{
+	char fw_ver_str[16] = EMPTY_FW_VERSION_STR;
+	char fw_img_str[16] = EMPTY_FW_IMAGE_STR;
+	struct fw_info fw_info = { {0}, {0} };
+	u32 offset = 0;
+
+	if (dump && !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_FW_VER)) {
+		/* Read FW info from chip */
+		qed_read_fw_info(p_hwfn, p_ptt, &fw_info);
+
+		/* Create FW version/image strings */
+		if (snprintf(fw_ver_str, sizeof(fw_ver_str),
+			     "%d_%d_%d_%d", fw_info.ver.num.major,
+			     fw_info.ver.num.minor, fw_info.ver.num.rev,
+			     fw_info.ver.num.eng) < 0)
+			DP_NOTICE(p_hwfn, false,
+				  "Unexpected debug error: invalid FW version string\n");
+		switch (fw_info.ver.image_id) {
+		case FW_IMG_MAIN:
+			strcpy(fw_img_str, "main");
+			break;
+		default:
+			strcpy(fw_img_str, "unknown");
+			break;
+		}
+	}
+
+	/* Dump FW version, image and timestamp */
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "fw-version", fw_ver_str);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "fw-image", fw_img_str);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "fw-timestamp", fw_info.ver.timestamp);
+
+	return offset;
+}
+
+/* Reads the MFW version and writes it as a param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_mfw_ver_param(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  u32 *dump_buf, bool dump)
+{
+	char mfw_ver_str[16] = EMPTY_FW_VERSION_STR;
+
+	if (dump &&
+	    !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_FW_VER)) {
+		u32 global_section_offsize, global_section_addr, mfw_ver;
+		u32 public_data_addr, global_section_offsize_addr;
+
+		/* Find MCP public data GRC address. Needs to be ORed with
+		 * MCP_REG_SCRATCH due to a HW bug.
+		 */
+		public_data_addr = ecore_rd(p_hwfn,
+					  p_ptt,
+					  MISC_REG_SHARED_MEM_ADDR) |
+				   MCP_REG_SCRATCH;
+
+		/* Find MCP public global section offset */
+		global_section_offsize_addr = public_data_addr +
+					      offsetof(struct mcp_public_data,
+						       sections) +
+					      sizeof(offsize_t) * PUBLIC_GLOBAL;
+		global_section_offsize = ecore_rd(p_hwfn, p_ptt,
+						global_section_offsize_addr);
+		global_section_addr =
+			MCP_REG_SCRATCH +
+			(global_section_offsize & OFFSIZE_OFFSET_MASK) * 4;
+
+		/* Read MFW version from MCP public global section */
+		mfw_ver = ecore_rd(p_hwfn, p_ptt,
+				 global_section_addr +
+				 offsetof(struct public_global, mfw_ver));
+
+		/* Dump MFW version param */
+		if (snprintf(mfw_ver_str, sizeof(mfw_ver_str), "%d_%d_%d_%d",
+			     (u8)(mfw_ver >> 24), (u8)(mfw_ver >> 16),
+			     (u8)(mfw_ver >> 8), (u8)mfw_ver) < 0)
+			DP_NOTICE(p_hwfn, false,
+				  "Unexpected debug error: invalid MFW version string\n");
+	}
+
+	return qed_dump_str_param(dump_buf, dump, "mfw-version", mfw_ver_str);
+}
+
+/* Reads the chip revision from the chip and writes it as a param to the
+ * specified buffer. Returns the dumped size in dwords.
+ */
+static u32 qed_dump_chip_revision_param(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	char param_str[3] = "??";
+
+	if (dev_data->hw_type == HW_TYPE_ASIC) {
+		u32 chip_rev, chip_metal;
+
+		chip_rev = ecore_rd(p_hwfn, p_ptt, MISCS_REG_CHIP_REV);
+		chip_metal = ecore_rd(p_hwfn, p_ptt, MISCS_REG_CHIP_METAL);
+
+		param_str[0] = 'a' + (u8)chip_rev;
+		param_str[1] = '0' + (u8)chip_metal;
+	}
+
+	return qed_dump_str_param(dump_buf, dump, "chip-revision", param_str);
+}
+
+/* Writes a section header to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_section_hdr(u32 *dump_buf,
+				bool dump, const char *name, u32 num_params)
+{
+	return qed_dump_num_param(dump_buf, dump, name, num_params);
+}
+
+/* Writes the common global params to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_common_global_params(struct ecore_hwfn *p_hwfn,
+					 struct ecore_ptt *p_ptt,
+					 u32 *dump_buf,
+					 bool dump,
+					 u8 num_specific_global_params)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	char sw_platform_str[MAX_SW_PLTAFORM_STR_SIZE];
+	u32 offset = 0;
+	u8 num_params;
+
+	/* Fill platform string */
+	ecore_set_platform_str(p_hwfn, sw_platform_str,
+			       MAX_SW_PLTAFORM_STR_SIZE);
+
+	/* Dump global params section header */
+	num_params = NUM_COMMON_GLOBAL_PARAMS + num_specific_global_params +
+		(dev_data->chip_id == CHIP_BB ? 1 : 0);
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "global_params", num_params);
+
+	/* Store params */
+	offset += qed_dump_fw_ver_param(p_hwfn, p_ptt, dump_buf + offset, dump);
+	offset += qed_dump_mfw_ver_param(p_hwfn,
+					 p_ptt, dump_buf + offset, dump);
+	offset += qed_dump_chip_revision_param(p_hwfn,
+					       p_ptt, dump_buf + offset, dump);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "tools-version", TOOLS_VERSION);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump,
+				     "chip",
+				     s_chip_defs[dev_data->chip_id].name);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump,
+				     "platform",
+				     s_hw_type_defs[dev_data->hw_type].name);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "sw-platform", sw_platform_str);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "pci-func", p_hwfn->abs_pf_id);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "epoch", OSAL_GET_EPOCH(p_hwfn));
+	if (dev_data->chip_id == CHIP_BB)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "path",
+					     ECORE_PATH_ID(p_hwfn));
+
+	return offset;
+}
+
+/* Writes the "last" section (including CRC) to the specified buffer at the
+ * given offset. Returns the dumped size in dwords.
+ */
+static u32 qed_dump_last_section(u32 *dump_buf, u32 offset, bool dump)
+{
+	u32 start_offset = offset;
+
+	/* Dump CRC section header */
+	offset += qed_dump_section_hdr(dump_buf + offset, dump, "last", 0);
+
+	/* Calculate CRC32 and add it to the dword after the "last" section */
+	if (dump)
+		*(dump_buf + offset) = ~OSAL_CRC32(0xffffffff,
+					      (u8 *)dump_buf,
+					      DWORDS_TO_BYTES(offset));
+
+	offset++;
+
+	return offset - start_offset;
+}
+
+/* Update blocks reset state  */
+static void qed_update_blocks_reset_state(struct ecore_hwfn *p_hwfn,
+					  struct ecore_ptt *p_ptt)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 reg_val[NUM_DBG_RESET_REGS] = { 0 };
+	u8 rst_reg_id;
+	u32 blk_id;
+
+	/* Read reset registers */
+	for (rst_reg_id = 0; rst_reg_id < NUM_DBG_RESET_REGS; rst_reg_id++) {
+		const struct dbg_reset_reg *rst_reg;
+		bool rst_reg_removed;
+		u32 rst_reg_addr;
+
+		rst_reg = qed_get_dbg_reset_reg(p_hwfn, rst_reg_id);
+		rst_reg_removed = GET_FIELD(rst_reg->data,
+					    DBG_RESET_REG_IS_REMOVED);
+		rst_reg_addr = DWORDS_TO_BYTES(GET_FIELD(rst_reg->data,
+							 DBG_RESET_REG_ADDR));
+
+		if (!rst_reg_removed)
+			reg_val[rst_reg_id] = ecore_rd(p_hwfn, p_ptt,
+						     rst_reg_addr);
+	}
+
+	/* Check if blocks are in reset */
+	for (blk_id = 0; blk_id < NUM_PHYS_BLOCKS; blk_id++) {
+		const struct dbg_block_chip *blk;
+		bool has_rst_reg;
+		bool is_removed;
+
+		blk = qed_get_dbg_block_per_chip(p_hwfn, (enum block_id)blk_id);
+		is_removed = GET_FIELD(blk->flags, DBG_BLOCK_CHIP_IS_REMOVED);
+		has_rst_reg = GET_FIELD(blk->flags,
+					DBG_BLOCK_CHIP_HAS_RESET_REG);
+
+		if (!is_removed && has_rst_reg)
+			dev_data->block_in_reset[blk_id] =
+			    !(reg_val[blk->reset_reg_id] &
+			      OSAL_BIT(blk->reset_reg_bit_offset));
+	}
+}
+
+/* is_mode_match recursive function */
+static bool qed_is_mode_match_rec(struct ecore_hwfn *p_hwfn,
+				  u16 *modes_buf_offset, u8 rec_depth)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	const u8 *dbg_array;
+	bool arg1, arg2;
+	u8 tree_val;
+
+	if (rec_depth > MAX_RECURSION_DEPTH) {
+		DP_NOTICE(p_hwfn, false,
+			  "Unexpected error: is_mode_match_rec exceeded the max recursion depth. This is probably due to a corrupt init/debug buffer.\n");
+		return false;
+	}
+
+	/* Get next element from modes tree buffer */
+	dbg_array = p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr;
+	tree_val = dbg_array[(*modes_buf_offset)++];
+
+	switch (tree_val) {
+	case INIT_MODE_OP_NOT:
+		return !qed_is_mode_match_rec(p_hwfn,
+					      modes_buf_offset, rec_depth + 1);
+	case INIT_MODE_OP_OR:
+	case INIT_MODE_OP_AND:
+		arg1 = qed_is_mode_match_rec(p_hwfn,
+					     modes_buf_offset, rec_depth + 1);
+		arg2 = qed_is_mode_match_rec(p_hwfn,
+					     modes_buf_offset, rec_depth + 1);
+		return (tree_val == INIT_MODE_OP_OR) ? (arg1 ||
+							arg2) : (arg1 && arg2);
+	default:
+		return dev_data->mode_enable[tree_val - MAX_INIT_MODE_OPS] > 0;
+	}
+}
+
+/* Returns true if the mode (specified using modes_buf_offset) is enabled */
+static bool qed_is_mode_match(struct ecore_hwfn *p_hwfn, u16 *modes_buf_offset)
+{
+	return qed_is_mode_match_rec(p_hwfn, modes_buf_offset, 0);
+}
+
+/* Enable / disable the Debug block */
+static void qed_bus_enable_dbg_block(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt, bool enable)
+{
+	ecore_wr(p_hwfn, p_ptt, DBG_REG_DBG_BLOCK_ON, enable ? 1 : 0);
+}
+
+/* Resets the Debug block */
+static void qed_bus_reset_dbg_block(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt)
+{
+	u32 reset_reg_addr, old_reset_reg_val, new_reset_reg_val;
+	const struct dbg_reset_reg *reset_reg;
+	const struct dbg_block_chip *block;
+
+	block = qed_get_dbg_block_per_chip(p_hwfn, BLOCK_DBG);
+	reset_reg = qed_get_dbg_reset_reg(p_hwfn, block->reset_reg_id);
+	reset_reg_addr =
+	    DWORDS_TO_BYTES(GET_FIELD(reset_reg->data, DBG_RESET_REG_ADDR));
+
+	old_reset_reg_val = ecore_rd(p_hwfn, p_ptt, reset_reg_addr);
+	new_reset_reg_val =
+	    old_reset_reg_val & ~OSAL_BIT(block->reset_reg_bit_offset);
+
+	ecore_wr(p_hwfn, p_ptt, reset_reg_addr, new_reset_reg_val);
+	ecore_wr(p_hwfn, p_ptt, reset_reg_addr, old_reset_reg_val);
+}
+
+/* Enable / disable Debug Bus clients according to the specified mask
+ * (1 = enable, 0 = disable).
+ */
+static void qed_bus_enable_clients(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt, u32 client_mask)
+{
+	ecore_wr(p_hwfn, p_ptt, DBG_REG_CLIENT_ENABLE, client_mask);
+}
+
+static void qed_bus_config_dbg_line(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    enum block_id block_id,
+				    u8 line_id,
+				    u8 enable_mask,
+				    u8 right_shift,
+				    u8 force_valid_mask, u8 force_frame_mask)
+{
+	const struct dbg_block_chip *block =
+		qed_get_dbg_block_per_chip(p_hwfn, block_id);
+
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_select_reg_addr),
+		 line_id);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_dword_enable_reg_addr),
+		 enable_mask);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_shift_reg_addr),
+		 right_shift);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_force_valid_reg_addr),
+		 force_valid_mask);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_force_frame_reg_addr),
+		 force_frame_mask);
+}
+
+/* Disable debug bus in all blocks */
+static void qed_bus_disable_blocks(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_id;
+
+	/* Disable all blocks */
+	for (block_id = 0; block_id < MAX_BLOCK_ID; block_id++) {
+		const struct dbg_block_chip *block_per_chip =
+		    qed_get_dbg_block_per_chip(p_hwfn,
+					       (enum block_id)block_id);
+
+		if (GET_FIELD(block_per_chip->flags,
+			      DBG_BLOCK_CHIP_IS_REMOVED) ||
+		    dev_data->block_in_reset[block_id])
+			continue;
+
+		/* Disable debug bus */
+		if (GET_FIELD(block_per_chip->flags,
+			      DBG_BLOCK_CHIP_HAS_DBG_BUS)) {
+			u32 dbg_en_addr =
+				block_per_chip->dbg_dword_enable_reg_addr;
+			u16 modes_buf_offset =
+			    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+				      DBG_MODE_HDR_MODES_BUF_OFFSET);
+			bool eval_mode =
+			    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+
+			if (!eval_mode ||
+			    qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				ecore_wr(p_hwfn, p_ptt,
+				       DWORDS_TO_BYTES(dbg_en_addr),
+				       0);
+		}
+	}
+}
+
+/* Returns true if the specified entity (indicated by GRC param) should be
+ * included in the dump, false otherwise.
+ */
+static bool qed_grc_is_included(struct ecore_hwfn *p_hwfn,
+				enum dbg_grc_params grc_param)
+{
+	return qed_grc_get_param(p_hwfn, grc_param) > 0;
+}
+
+/* Returns the storm_id that matches the specified Storm letter,
+ * or MAX_DBG_STORMS if invalid storm letter.
+ */
+static enum dbg_storms qed_get_id_from_letter(char storm_letter)
+{
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++)
+		if (s_storm_defs[storm_id].letter == storm_letter)
+			return (enum dbg_storms)storm_id;
+
+	return MAX_DBG_STORMS;
+}
+
+/* Returns true of the specified Storm should be included in the dump, false
+ * otherwise.
+ */
+static bool qed_grc_is_storm_included(struct ecore_hwfn *p_hwfn,
+				      enum dbg_storms storm)
+{
+	return qed_grc_get_param(p_hwfn, (enum dbg_grc_params)storm) > 0;
+}
+
+/* Returns true if the specified memory should be included in the dump, false
+ * otherwise.
+ */
+static bool qed_grc_is_mem_included(struct ecore_hwfn *p_hwfn,
+				    enum block_id block_id, u8 mem_group_id)
+{
+	const struct dbg_block *block;
+	u8 i;
+
+	block = get_dbg_block(p_hwfn, block_id);
+
+	/* If the block is associated with a Storm, check Storm match */
+	if (block->associated_storm_letter) {
+		enum dbg_storms associated_storm_id =
+		    qed_get_id_from_letter(block->associated_storm_letter);
+
+		if (associated_storm_id == MAX_DBG_STORMS ||
+		    !qed_grc_is_storm_included(p_hwfn, associated_storm_id))
+			return false;
+	}
+
+	for (i = 0; i < NUM_BIG_RAM_TYPES; i++) {
+		struct big_ram_defs *big_ram = &s_big_ram_defs[i];
+
+		if (mem_group_id == big_ram->mem_group_id ||
+		    mem_group_id == big_ram->ram_mem_group_id)
+			return qed_grc_is_included(p_hwfn, big_ram->grc_param);
+	}
+
+	switch (mem_group_id) {
+	case MEM_GROUP_PXP_ILT:
+	case MEM_GROUP_PXP_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PXP);
+	case MEM_GROUP_RAM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_RAM);
+	case MEM_GROUP_PBUF:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PBUF);
+	case MEM_GROUP_CAU_MEM:
+	case MEM_GROUP_CAU_SB:
+	case MEM_GROUP_CAU_PI:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CAU);
+	case MEM_GROUP_CAU_MEM_EXT:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CAU_EXT);
+	case MEM_GROUP_QM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_QM);
+	case MEM_GROUP_CFC_MEM:
+	case MEM_GROUP_CONN_CFC_MEM:
+	case MEM_GROUP_TASK_CFC_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CFC) ||
+		       qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM_CTX);
+	case MEM_GROUP_DORQ_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DORQ);
+	case MEM_GROUP_IGU_MEM:
+	case MEM_GROUP_IGU_MSIX:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_IGU);
+	case MEM_GROUP_MULD_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MULD);
+	case MEM_GROUP_PRS_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PRS);
+	case MEM_GROUP_DMAE_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DMAE);
+	case MEM_GROUP_TM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_TM);
+	case MEM_GROUP_SDM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_SDM);
+	case MEM_GROUP_TDIF_CTX:
+	case MEM_GROUP_RDIF_CTX:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DIF);
+	case MEM_GROUP_CM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM);
+	case MEM_GROUP_IOR:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_IOR);
+	default:
+		return true;
+	}
+}
+
+/* Stalls all Storms */
+static void qed_grc_stall_storms(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt, bool stall)
+{
+	u32 reg_addr;
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		if (!qed_grc_is_storm_included(p_hwfn,
+					       (enum dbg_storms)storm_id))
+			continue;
+
+		reg_addr = s_storm_defs[storm_id].sem_fast_mem_addr +
+		    SEM_FAST_REG_STALL_0;
+		ecore_wr(p_hwfn, p_ptt, reg_addr, stall ? 1 : 0);
+	}
+
+	OSAL_MSLEEP(STALL_DELAY_MS);
+}
+
+/* Takes all blocks out of reset. If rbc_only is true, only RBC clients are
+ * taken out of reset.
+ */
+static void qed_grc_unreset_blocks(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt, bool rbc_only)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 chip_id = dev_data->chip_id;
+	u32 i;
+
+	/* Take RBCs out of reset */
+	for (i = 0; i < OSAL_ARRAY_SIZE(s_rbc_reset_defs); i++)
+		if (s_rbc_reset_defs[i].reset_val[dev_data->chip_id])
+			ecore_wr(p_hwfn,
+			       p_ptt,
+			       s_rbc_reset_defs[i].reset_reg_addr +
+			       RESET_REG_UNRESET_OFFSET,
+			       s_rbc_reset_defs[i].reset_val[chip_id]);
+
+	if (!rbc_only) {
+		u32 reg_val[NUM_DBG_RESET_REGS] = { 0 };
+		u8 reset_reg_id;
+		u32 block_id;
+
+		/* Fill reset regs values */
+		for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
+			bool is_removed, has_reset_reg, unreset_before_dump;
+			const struct dbg_block_chip *block;
+
+			block = qed_get_dbg_block_per_chip(p_hwfn,
+							   (enum block_id)
+							   block_id);
+			is_removed =
+			    GET_FIELD(block->flags, DBG_BLOCK_CHIP_IS_REMOVED);
+			has_reset_reg =
+			    GET_FIELD(block->flags,
+				      DBG_BLOCK_CHIP_HAS_RESET_REG);
+			unreset_before_dump =
+			    GET_FIELD(block->flags,
+				      DBG_BLOCK_CHIP_UNRESET_BEFORE_DUMP);
+
+			if (!is_removed && has_reset_reg && unreset_before_dump)
+				reg_val[block->reset_reg_id] |=
+				    OSAL_BIT(block->reset_reg_bit_offset);
+		}
+
+		/* Write reset registers */
+		for (reset_reg_id = 0; reset_reg_id < NUM_DBG_RESET_REGS;
+		     reset_reg_id++) {
+			const struct dbg_reset_reg *reset_reg;
+			u32 reset_reg_addr;
+
+			reset_reg = qed_get_dbg_reset_reg(p_hwfn, reset_reg_id);
+
+			if (GET_FIELD
+			    (reset_reg->data, DBG_RESET_REG_IS_REMOVED))
+				continue;
+
+			if (reg_val[reset_reg_id]) {
+				reset_reg_addr =
+				    GET_FIELD(reset_reg->data,
+					      DBG_RESET_REG_ADDR);
+				ecore_wr(p_hwfn,
+				       p_ptt,
+				       DWORDS_TO_BYTES(reset_reg_addr) +
+				       RESET_REG_UNRESET_OFFSET,
+				       reg_val[reset_reg_id]);
+			}
+		}
+	}
+}
+
+/* Returns the attention block data of the specified block */
+static const struct dbg_attn_block_type_data *
+qed_get_block_attn_data(struct ecore_hwfn *p_hwfn,
+			enum block_id block_id, enum dbg_attn_type attn_type)
+{
+	const struct dbg_attn_block *base_attn_block_arr =
+	    (const struct dbg_attn_block *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr;
+
+	return &base_attn_block_arr[block_id].per_type_data[attn_type];
+}
+
+/* Returns the attention registers of the specified block */
+static const struct dbg_attn_reg *
+qed_get_block_attn_regs(struct ecore_hwfn *p_hwfn,
+			enum block_id block_id, enum dbg_attn_type attn_type,
+			u8 *num_attn_regs)
+{
+	const struct dbg_attn_block_type_data *block_type_data =
+	    qed_get_block_attn_data(p_hwfn, block_id, attn_type);
+
+	*num_attn_regs = block_type_data->num_regs;
+
+	return (const struct dbg_attn_reg *)
+		p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr +
+		block_type_data->regs_offset;
+}
+
+/* For each block, clear the status of all parities */
+static void qed_grc_clear_all_prty(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	const struct dbg_attn_reg *attn_reg_arr;
+	u8 reg_idx, num_attn_regs;
+	u32 block_id;
+
+	for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
+		if (dev_data->block_in_reset[block_id])
+			continue;
+
+		attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
+						       (enum block_id)block_id,
+						       ATTN_TYPE_PARITY,
+						       &num_attn_regs);
+
+		for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
+			const struct dbg_attn_reg *reg_data =
+				&attn_reg_arr[reg_idx];
+			u16 modes_buf_offset;
+			bool eval_mode;
+
+			/* Check mode */
+			eval_mode = GET_FIELD(reg_data->mode.data,
+					      DBG_MODE_HDR_EVAL_MODE) > 0;
+			modes_buf_offset =
+				GET_FIELD(reg_data->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+
+			/* If Mode match: clear parity status */
+			if (!eval_mode ||
+			    qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				ecore_rd(p_hwfn, p_ptt,
+				    DWORDS_TO_BYTES(reg_data->sts_clr_address));
+		}
+	}
+}
+
+/* Dumps GRC registers section header. Returns the dumped size in dwords.
+ * the following parameters are dumped:
+ * - count: no. of dumped entries
+ * - split_type: split type
+ * - split_id: split ID (dumped only if split_id != SPLIT_TYPE_NONE)
+ * - reg_type_name: register type name (dumped only if reg_type_name != NULL)
+ */
+static u32 qed_grc_dump_regs_hdr(u32 *dump_buf,
+				 bool dump,
+				 u32 num_reg_entries,
+				 enum init_split_types split_type,
+				 u8 split_id, const char *reg_type_name)
+{
+	u8 num_params = 2 +
+	    (split_type != SPLIT_TYPE_NONE ? 1 : 0) + (reg_type_name ? 1 : 0);
+	u32 offset = 0;
+
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "grc_regs", num_params);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "count", num_reg_entries);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "split",
+				     s_split_type_defs[split_type].name);
+	if (split_type != SPLIT_TYPE_NONE)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "id", split_id);
+	if (reg_type_name)
+		offset += qed_dump_str_param(dump_buf + offset,
+					     dump, "type", reg_type_name);
+
+	return offset;
+}
+
+/* Reads the specified registers into the specified buffer.
+ * The addr and len arguments are specified in dwords.
+ */
+void qed_read_regs(struct ecore_hwfn *p_hwfn,
+		   struct ecore_ptt *p_ptt, u32 *buf, u32 addr, u32 len)
+{
+	u32 i;
+
+	for (i = 0; i < len; i++)
+		buf[i] = ecore_rd(p_hwfn, p_ptt, DWORDS_TO_BYTES(addr + i));
+}
+
+/* Dumps the GRC registers in the specified address range.
+ * Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_addr_range(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   u32 *dump_buf,
+				   bool dump, u32 addr, u32 len, bool wide_bus,
+				   enum init_split_types split_type,
+				   u8 split_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 port_id = 0, pf_id = 0, vf_id = 0, fid = 0;
+	bool read_using_dmae = false;
+	u32 thresh;
+
+	if (!dump)
+		return len;
+
+	switch (split_type) {
+	case SPLIT_TYPE_PORT:
+		port_id = split_id;
+		break;
+	case SPLIT_TYPE_PF:
+		pf_id = split_id;
+		break;
+	case SPLIT_TYPE_PORT_PF:
+		port_id = split_id / dev_data->num_pfs_per_port;
+		pf_id = port_id + dev_data->num_ports *
+		    (split_id % dev_data->num_pfs_per_port);
+		break;
+	case SPLIT_TYPE_VF:
+		vf_id = split_id;
+		break;
+	default:
+		break;
+	}
+
+	/* Try reading using DMAE */
+	if (dev_data->use_dmae && split_type != SPLIT_TYPE_VF &&
+	    (len >= s_hw_type_defs[dev_data->hw_type].dmae_thresh ||
+	     (PROTECT_WIDE_BUS && wide_bus))) {
+		struct dmae_params dmae_params;
+
+		/* Set DMAE params */
+		memset(&dmae_params, 0, sizeof(dmae_params));
+		SET_FIELD(dmae_params.flags, DMAE_PARAMS_COMPLETION_DST, 1);
+		switch (split_type) {
+		case SPLIT_TYPE_PORT:
+			SET_FIELD(dmae_params.flags, DMAE_PARAMS_PORT_VALID,
+				  1);
+			dmae_params.port_id = port_id;
+			break;
+		case SPLIT_TYPE_PF:
+			SET_FIELD(dmae_params.flags,
+				  DMAE_PARAMS_SRC_PF_VALID, 1);
+			dmae_params.src_pf_id = pf_id;
+			break;
+		case SPLIT_TYPE_PORT_PF:
+			SET_FIELD(dmae_params.flags, DMAE_PARAMS_PORT_VALID,
+				  1);
+			SET_FIELD(dmae_params.flags,
+				  DMAE_PARAMS_SRC_PF_VALID, 1);
+			dmae_params.port_id = port_id;
+			dmae_params.src_pf_id = pf_id;
+			break;
+		default:
+			break;
+		}
+
+		/* Execute DMAE command */
+		read_using_dmae = !ecore_dmae_grc2host(p_hwfn,
+						     p_ptt,
+						     DWORDS_TO_BYTES(addr),
+						     (u64)(uintptr_t)(dump_buf),
+						     len, &dmae_params);
+		if (!read_using_dmae) {
+			dev_data->use_dmae = 0;
+			DP_VERBOSE(p_hwfn->p_dev,
+				   ECORE_MSG_DEBUG,
+				   "Failed reading from chip using DMAE, using GRC instead\n");
+		}
+	}
+
+	if (read_using_dmae)
+		goto print_log;
+
+	/* If not read using DMAE, read using GRC */
+
+	/* Set pretend */
+	if (split_type != dev_data->pretend.split_type ||
+	    split_id != dev_data->pretend.split_id) {
+		switch (split_type) {
+		case SPLIT_TYPE_PORT:
+			ecore_port_pretend(p_hwfn, p_ptt, port_id);
+			break;
+		case SPLIT_TYPE_PF:
+			fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
+					  pf_id);
+			ecore_fid_pretend(p_hwfn, p_ptt, fid);
+			break;
+		case SPLIT_TYPE_PORT_PF:
+			fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
+					  pf_id);
+			ecore_port_fid_pretend(p_hwfn, p_ptt, port_id, fid);
+			break;
+		case SPLIT_TYPE_VF:
+			fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_VFVALID, 1)
+			      | FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_VFID,
+					  vf_id);
+			ecore_fid_pretend(p_hwfn, p_ptt, fid);
+			break;
+		default:
+			break;
+		}
+
+		dev_data->pretend.split_type = (u8)split_type;
+		dev_data->pretend.split_id = split_id;
+	}
+
+	/* Read registers using GRC */
+	qed_read_regs(p_hwfn, p_ptt, dump_buf, addr, len);
+
+print_log:
+	/* Print log */
+	dev_data->num_regs_read += len;
+	thresh = s_hw_type_defs[dev_data->hw_type].log_thresh;
+	if ((dev_data->num_regs_read / thresh) >
+	    ((dev_data->num_regs_read - len) / thresh))
+		DP_VERBOSE(p_hwfn->p_dev,
+			   ECORE_MSG_DEBUG,
+			   "Dumped %d registers...\n", dev_data->num_regs_read);
+
+	return len;
+}
+
+/* Dumps GRC registers sequence header. Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_reg_entry_hdr(u32 *dump_buf,
+				      bool dump, u32 addr, u32 len)
+{
+	if (dump)
+		*dump_buf = addr | (len << REG_DUMP_LEN_SHIFT);
+
+	return 1;
+}
+
+/* Dumps GRC registers sequence. Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_reg_entry(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  u32 *dump_buf,
+				  bool dump, u32 addr, u32 len, bool wide_bus,
+				  enum init_split_types split_type, u8 split_id)
+{
+	u32 offset = 0;
+
+	offset += qed_grc_dump_reg_entry_hdr(dump_buf, dump, addr, len);
+	offset += qed_grc_dump_addr_range(p_hwfn,
+					  p_ptt,
+					  dump_buf + offset,
+					  dump, addr, len, wide_bus,
+					  split_type, split_id);
+
+	return offset;
+}
+
+/* Dumps GRC registers sequence with skip cycle.
+ * Returns the dumped size in dwords.
+ * - addr:	start GRC address in dwords
+ * - total_len:	total no. of dwords to dump
+ * - read_len:	no. consecutive dwords to read
+ * - skip_len:	no. of dwords to skip (and fill with zeros)
+ */
+static u32 qed_grc_dump_reg_entry_skip(struct ecore_hwfn *p_hwfn,
+				       struct ecore_ptt *p_ptt,
+				       u32 *dump_buf,
+				       bool dump,
+				       u32 addr,
+				       u32 total_len,
+				       u32 read_len, u32 skip_len)
+{
+	u32 offset = 0, reg_offset = 0;
+
+	offset += qed_grc_dump_reg_entry_hdr(dump_buf, dump, addr, total_len);
+
+	if (!dump)
+		return offset + total_len;
+
+	while (reg_offset < total_len) {
+		u32 curr_len = OSAL_MIN_T(u32, read_len,
+					  total_len - reg_offset);
+
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  dump,  addr, curr_len, false,
+						  SPLIT_TYPE_NONE, 0);
+		reg_offset += curr_len;
+		addr += curr_len;
+
+		if (reg_offset < total_len) {
+			curr_len = OSAL_MIN_T(u32, skip_len,
+					      total_len - skip_len);
+			memset(dump_buf + offset, 0, DWORDS_TO_BYTES(curr_len));
+			offset += curr_len;
+			reg_offset += curr_len;
+			addr += curr_len;
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC registers entries. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_regs_entries(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     struct virt_mem_desc input_regs_arr,
+				     u32 *dump_buf,
+				     bool dump,
+				     enum init_split_types split_type,
+				     u8 split_id,
+				     bool block_enable[MAX_BLOCK_ID],
+				     u32 *num_dumped_reg_entries)
+{
+	u32 i, offset = 0, input_offset = 0;
+	bool mode_match = true;
+
+	*num_dumped_reg_entries = 0;
+
+	while (input_offset < BYTES_TO_DWORDS(input_regs_arr.size)) {
+		const struct dbg_dump_cond_hdr *cond_hdr =
+		    (const struct dbg_dump_cond_hdr *)
+		    input_regs_arr.ptr + input_offset++;
+		u16 modes_buf_offset;
+		bool eval_mode;
+
+		/* Check mode/block */
+		eval_mode = GET_FIELD(cond_hdr->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		if (eval_mode) {
+			modes_buf_offset =
+				GET_FIELD(cond_hdr->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			mode_match = qed_is_mode_match(p_hwfn,
+						       &modes_buf_offset);
+		}
+
+		if (!mode_match || !block_enable[cond_hdr->block_id]) {
+			input_offset += cond_hdr->data_size;
+			continue;
+		}
+
+		for (i = 0; i < cond_hdr->data_size; i++, input_offset++) {
+			const struct dbg_dump_reg *reg =
+			    (const struct dbg_dump_reg *)
+			    input_regs_arr.ptr + input_offset;
+			u32 addr, len;
+			bool wide_bus;
+
+			addr = GET_FIELD(reg->data, DBG_DUMP_REG_ADDRESS);
+			len = GET_FIELD(reg->data, DBG_DUMP_REG_LENGTH);
+			wide_bus = GET_FIELD(reg->data, DBG_DUMP_REG_WIDE_BUS);
+			offset += qed_grc_dump_reg_entry(p_hwfn,
+							 p_ptt,
+							 dump_buf + offset,
+							 dump,
+							 addr,
+							 len,
+							 wide_bus,
+							 split_type, split_id);
+			(*num_dumped_reg_entries)++;
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC registers entries. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_split_data(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   struct virt_mem_desc input_regs_arr,
+				   u32 *dump_buf,
+				   bool dump,
+				   bool block_enable[MAX_BLOCK_ID],
+				   enum init_split_types split_type,
+				   u8 split_id, const char *reg_type_name)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	enum init_split_types hdr_split_type = split_type;
+	u32 num_dumped_reg_entries, offset;
+	u8 hdr_split_id = split_id;
+
+	/* In PORT_PF split type, print a port split header */
+	if (split_type == SPLIT_TYPE_PORT_PF) {
+		hdr_split_type = SPLIT_TYPE_PORT;
+		hdr_split_id = split_id / dev_data->num_pfs_per_port;
+	}
+
+	/* Calculate register dump header size (and skip it for now) */
+	offset = qed_grc_dump_regs_hdr(dump_buf,
+				       false,
+				       0,
+				       hdr_split_type,
+				       hdr_split_id, reg_type_name);
+
+	/* Dump registers */
+	offset += qed_grc_dump_regs_entries(p_hwfn,
+					    p_ptt,
+					    input_regs_arr,
+					    dump_buf + offset,
+					    dump,
+					    split_type,
+					    split_id,
+					    block_enable,
+					    &num_dumped_reg_entries);
+
+	/* Write register dump header */
+	if (dump && num_dumped_reg_entries > 0)
+		qed_grc_dump_regs_hdr(dump_buf,
+				      dump,
+				      num_dumped_reg_entries,
+				      hdr_split_type,
+				      hdr_split_id, reg_type_name);
+
+	return num_dumped_reg_entries > 0 ? offset : 0;
+}
+
+/* Dumps registers according to the input registers array. Returns the dumped
+ * size in dwords.
+ */
+static u32 qed_grc_dump_registers(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  u32 *dump_buf,
+				  bool dump,
+				  bool block_enable[MAX_BLOCK_ID],
+				  const char *reg_type_name)
+{
+	struct virt_mem_desc *dbg_buf =
+	    &p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG];
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 offset = 0, input_offset = 0;
+
+	while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
+		const struct dbg_dump_split_hdr *split_hdr;
+		struct virt_mem_desc curr_input_regs_arr;
+		enum init_split_types split_type;
+		u16 split_count = 0;
+		u32 split_data_size;
+		u8 split_id;
+
+		split_hdr =
+		    (const struct dbg_dump_split_hdr *)
+		    dbg_buf->ptr + input_offset++;
+		split_type =
+		    GET_FIELD(split_hdr->hdr,
+			      DBG_DUMP_SPLIT_HDR_SPLIT_TYPE_ID);
+		split_data_size = GET_FIELD(split_hdr->hdr,
+					    DBG_DUMP_SPLIT_HDR_DATA_SIZE);
+		curr_input_regs_arr.ptr =
+		    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG].ptr +
+		    input_offset;
+		curr_input_regs_arr.size = DWORDS_TO_BYTES(split_data_size);
+
+		switch (split_type) {
+		case SPLIT_TYPE_NONE:
+			split_count = 1;
+			break;
+		case SPLIT_TYPE_PORT:
+			split_count = dev_data->num_ports;
+			break;
+		case SPLIT_TYPE_PF:
+		case SPLIT_TYPE_PORT_PF:
+			split_count = dev_data->num_ports *
+			    dev_data->num_pfs_per_port;
+			break;
+		case SPLIT_TYPE_VF:
+			split_count = dev_data->num_vfs;
+			break;
+		default:
+			return 0;
+		}
+
+		for (split_id = 0; split_id < split_count; split_id++)
+			offset += qed_grc_dump_split_data(p_hwfn, p_ptt,
+							  curr_input_regs_arr,
+							  dump_buf + offset,
+							  dump, block_enable,
+							  split_type,
+							  split_id,
+							  reg_type_name);
+
+		input_offset += split_data_size;
+	}
+
+	/* Cancel pretends (pretend to original PF) */
+	if (dump) {
+		ecore_fid_pretend(p_hwfn, p_ptt,
+				FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
+					    p_hwfn->rel_pf_id));
+		dev_data->pretend.split_type = SPLIT_TYPE_NONE;
+		dev_data->pretend.split_id = 0;
+	}
+
+	return offset;
+}
+
+/* Dump reset registers. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_reset_regs(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   u32 *dump_buf, bool dump)
+{
+	u32 offset = 0, num_regs = 0;
+	u8 reset_reg_id;
+
+	/* Calculate header size */
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					false,
+					0, SPLIT_TYPE_NONE, 0, "RESET_REGS");
+
+	/* Write reset registers */
+	for (reset_reg_id = 0; reset_reg_id < NUM_DBG_RESET_REGS;
+	     reset_reg_id++) {
+		const struct dbg_reset_reg *reset_reg;
+		u32 reset_reg_addr;
+
+		reset_reg = qed_get_dbg_reset_reg(p_hwfn, reset_reg_id);
+
+		if (GET_FIELD(reset_reg->data, DBG_RESET_REG_IS_REMOVED))
+			continue;
+
+		reset_reg_addr = GET_FIELD(reset_reg->data, DBG_RESET_REG_ADDR);
+		offset += qed_grc_dump_reg_entry(p_hwfn,
+						 p_ptt,
+						 dump_buf + offset,
+						 dump,
+						 reset_reg_addr,
+						 1, false, SPLIT_TYPE_NONE, 0);
+		num_regs++;
+	}
+
+	/* Write header */
+	if (dump)
+		qed_grc_dump_regs_hdr(dump_buf,
+				      true, num_regs, SPLIT_TYPE_NONE,
+				      0, "RESET_REGS");
+
+	return offset;
+}
+
+/* Dump registers that are modified during GRC Dump and therefore must be
+ * dumped first. Returns the dumped size in dwords.
+ */
+static u32 qed_grc_dump_modified_regs(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_id, offset = 0, stall_regs_offset;
+	const struct dbg_attn_reg *attn_reg_arr;
+	u8 storm_id, reg_idx, num_attn_regs;
+	u32 num_reg_entries = 0;
+
+	/* Write empty header for attention registers */
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					false,
+					0, SPLIT_TYPE_NONE, 0, "ATTN_REGS");
+
+	/* Write parity registers */
+	for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
+		if (dev_data->block_in_reset[block_id] && dump)
+			continue;
+
+		attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
+						       (enum block_id)block_id,
+						       ATTN_TYPE_PARITY,
+						       &num_attn_regs);
+
+		for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
+			const struct dbg_attn_reg *reg_data =
+				&attn_reg_arr[reg_idx];
+			u16 modes_buf_offset;
+			bool eval_mode;
+			u32 addr;
+
+			/* Check mode */
+			eval_mode = GET_FIELD(reg_data->mode.data,
+					      DBG_MODE_HDR_EVAL_MODE) > 0;
+			modes_buf_offset =
+				GET_FIELD(reg_data->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			if (eval_mode &&
+			    !qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				continue;
+
+			/* Mode match: read & dump registers */
+			addr = reg_data->mask_address;
+			offset += qed_grc_dump_reg_entry(p_hwfn,
+							 p_ptt,
+							 dump_buf + offset,
+							 dump,
+							 addr,
+							 1, false,
+							 SPLIT_TYPE_NONE, 0);
+			addr = GET_FIELD(reg_data->data,
+					 DBG_ATTN_REG_STS_ADDRESS);
+			offset += qed_grc_dump_reg_entry(p_hwfn,
+							 p_ptt,
+							 dump_buf + offset,
+							 dump,
+							 addr,
+							 1, false,
+							 SPLIT_TYPE_NONE, 0);
+			num_reg_entries += 2;
+		}
+	}
+
+	/* Overwrite header for attention registers */
+	if (dump)
+		qed_grc_dump_regs_hdr(dump_buf,
+				      true,
+				      num_reg_entries,
+				      SPLIT_TYPE_NONE, 0, "ATTN_REGS");
+
+	/* Write empty header for stall registers */
+	stall_regs_offset = offset;
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					false, 0, SPLIT_TYPE_NONE, 0, "REGS");
+
+	/* Write Storm stall status registers */
+	for (storm_id = 0, num_reg_entries = 0; storm_id < MAX_DBG_STORMS;
+	     storm_id++) {
+		struct storm_defs *storm = &s_storm_defs[storm_id];
+		u32 addr;
+
+		if (dev_data->block_in_reset[storm->sem_block_id] && dump)
+			continue;
+
+		addr =
+		    BYTES_TO_DWORDS(storm->sem_fast_mem_addr +
+				    SEM_FAST_REG_STALLED);
+		offset += qed_grc_dump_reg_entry(p_hwfn,
+						 p_ptt,
+						 dump_buf + offset,
+						 dump,
+						 addr,
+						 1,
+						 false, SPLIT_TYPE_NONE, 0);
+		num_reg_entries++;
+	}
+
+	/* Overwrite header for stall registers */
+	if (dump)
+		qed_grc_dump_regs_hdr(dump_buf + stall_regs_offset,
+				      true,
+				      num_reg_entries,
+				      SPLIT_TYPE_NONE, 0, "REGS");
+
+	return offset;
+}
+
+/* Dumps registers that can't be represented in the debug arrays */
+static u32 qed_grc_dump_special_regs(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     u32 *dump_buf, bool dump)
+{
+	u32 offset = 0, addr;
+
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					dump, 2, SPLIT_TYPE_NONE, 0, "REGS");
+
+	/* Dump R/TDIF_REG_DEBUG_ERROR_INFO_SIZE (every 8'th register should be
+	 * skipped).
+	 */
+	addr = BYTES_TO_DWORDS(RDIF_REG_DEBUG_ERROR_INFO);
+	offset += qed_grc_dump_reg_entry_skip(p_hwfn,
+					      p_ptt,
+					      dump_buf + offset,
+					      dump,
+					      addr,
+					      RDIF_REG_DEBUG_ERROR_INFO_SIZE,
+					      7,
+					      1);
+	addr = BYTES_TO_DWORDS(TDIF_REG_DEBUG_ERROR_INFO);
+	offset +=
+	    qed_grc_dump_reg_entry_skip(p_hwfn,
+					p_ptt,
+					dump_buf + offset,
+					dump,
+					addr,
+					TDIF_REG_DEBUG_ERROR_INFO_SIZE,
+					7,
+					1);
+
+	return offset;
+}
+
+/* Dumps a GRC memory header (section and params). Returns the dumped size in
+ * dwords. The following parameters are dumped:
+ * - name:	   dumped only if it's not NULL.
+ * - addr:	   in dwords, dumped only if name is NULL.
+ * - len:	   in dwords, always dumped.
+ * - width:	   dumped if it's not zero.
+ * - packed:	   dumped only if it's not false.
+ * - mem_group:	   always dumped.
+ * - is_storm:	   true only if the memory is related to a Storm.
+ * - storm_letter: valid only if is_storm is true.
+ *
+ */
+static u32 qed_grc_dump_mem_hdr(struct ecore_hwfn *p_hwfn,
+				u32 *dump_buf,
+				bool dump,
+				const char *name,
+				u32 addr,
+				u32 len,
+				u32 bit_width,
+				bool packed,
+				const char *mem_group, char storm_letter)
+{
+	u8 num_params = 3;
+	u32 offset = 0;
+	char buf[64];
+
+	if (!len)
+		DP_NOTICE(p_hwfn, false,
+			  "Unexpected GRC Dump error: dumped memory size must be non-zero\n");
+
+	if (bit_width)
+		num_params++;
+	if (packed)
+		num_params++;
+
+	/* Dump section header */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "grc_mem", num_params);
+
+	if (name) {
+		/* Dump name */
+		if (storm_letter) {
+			strcpy(buf, "?STORM_");
+			buf[0] = storm_letter;
+			strcpy(buf + strlen(buf), name);
+		} else {
+			strcpy(buf, name);
+		}
+
+		offset += qed_dump_str_param(dump_buf + offset,
+					     dump, "name", buf);
+	} else {
+		/* Dump address */
+		u32 addr_in_bytes = DWORDS_TO_BYTES(addr);
+
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "addr", addr_in_bytes);
+	}
+
+	/* Dump len */
+	offset += qed_dump_num_param(dump_buf + offset, dump, "len", len);
+
+	/* Dump bit width */
+	if (bit_width)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "width", bit_width);
+
+	/* Dump packed */
+	if (packed)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "packed", 1);
+
+	/* Dump reg type */
+	if (storm_letter) {
+		strcpy(buf, "?STORM_");
+		buf[0] = storm_letter;
+		strcpy(buf + strlen(buf), mem_group);
+	} else {
+		strcpy(buf, mem_group);
+	}
+
+	offset += qed_dump_str_param(dump_buf + offset, dump, "type", buf);
+
+	return offset;
+}
+
+/* Dumps a single GRC memory. If name is NULL, the memory is stored by address.
+ * Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_mem(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt,
+			    u32 *dump_buf,
+			    bool dump,
+			    const char *name,
+			    u32 addr,
+			    u32 len,
+			    bool wide_bus,
+			    u32 bit_width,
+			    bool packed,
+			    const char *mem_group, char storm_letter)
+{
+	u32 offset = 0;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       name,
+				       addr,
+				       len,
+				       bit_width,
+				       packed, mem_group, storm_letter);
+	offset += qed_grc_dump_addr_range(p_hwfn,
+					  p_ptt,
+					  dump_buf + offset,
+					  dump, addr, len, wide_bus,
+					  SPLIT_TYPE_NONE, 0);
+
+	return offset;
+}
+
+/* Dumps GRC memories entries. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_mem_entries(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    struct virt_mem_desc input_mems_arr,
+				    u32 *dump_buf, bool dump)
+{
+	u32 i, offset = 0, input_offset = 0;
+	bool mode_match = true;
+
+	while (input_offset < BYTES_TO_DWORDS(input_mems_arr.size)) {
+		const struct dbg_dump_cond_hdr *cond_hdr;
+		u16 modes_buf_offset;
+		u32 num_entries;
+		bool eval_mode;
+
+		cond_hdr =
+		    (const struct dbg_dump_cond_hdr *)input_mems_arr.ptr +
+		    input_offset++;
+		num_entries = cond_hdr->data_size / MEM_DUMP_ENTRY_SIZE_DWORDS;
+
+		/* Check required mode */
+		eval_mode = GET_FIELD(cond_hdr->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		if (eval_mode) {
+			modes_buf_offset =
+				GET_FIELD(cond_hdr->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			mode_match = qed_is_mode_match(p_hwfn,
+						       &modes_buf_offset);
+		}
+
+		if (!mode_match) {
+			input_offset += cond_hdr->data_size;
+			continue;
+		}
+
+		for (i = 0; i < num_entries;
+		     i++, input_offset += MEM_DUMP_ENTRY_SIZE_DWORDS) {
+			const struct dbg_dump_mem *mem =
+			    (const struct dbg_dump_mem *)((u32 *)
+							  input_mems_arr.ptr
+							  + input_offset);
+			const struct dbg_block *block;
+			char storm_letter = 0;
+			u32 mem_addr, mem_len;
+			bool mem_wide_bus;
+			u8 mem_group_id;
+
+			mem_group_id = GET_FIELD(mem->dword0,
+						 DBG_DUMP_MEM_MEM_GROUP_ID);
+			if (mem_group_id >= MEM_GROUPS_NUM) {
+				DP_NOTICE(p_hwfn, false, "Invalid mem_group_id\n");
+				return 0;
+			}
+
+			if (!qed_grc_is_mem_included(p_hwfn,
+						     (enum block_id)
+						     cond_hdr->block_id,
+						     mem_group_id))
+				continue;
+
+			mem_addr = GET_FIELD(mem->dword0, DBG_DUMP_MEM_ADDRESS);
+			mem_len = GET_FIELD(mem->dword1, DBG_DUMP_MEM_LENGTH);
+			mem_wide_bus = GET_FIELD(mem->dword1,
+						 DBG_DUMP_MEM_WIDE_BUS);
+
+			block = get_dbg_block(p_hwfn,
+					      cond_hdr->block_id);
+
+			/* If memory is associated with Storm,
+			 * update storm details
+			 */
+			if (block->associated_storm_letter)
+				storm_letter = block->associated_storm_letter;
+
+			/* Dump memory */
+			offset += qed_grc_dump_mem(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						NULL,
+						mem_addr,
+						mem_len,
+						mem_wide_bus,
+						0,
+						false,
+						s_mem_group_names[mem_group_id],
+						storm_letter);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC memories according to the input array dump_mem.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_grc_dump_memories(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf, bool dump)
+{
+	struct virt_mem_desc *dbg_buf =
+	    &p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_MEM];
+	u32 offset = 0, input_offset = 0;
+
+	while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
+		const struct dbg_dump_split_hdr *split_hdr;
+		struct virt_mem_desc curr_input_mems_arr;
+		enum init_split_types split_type;
+		u32 split_data_size;
+
+		split_hdr =
+		    (const struct dbg_dump_split_hdr *)dbg_buf->ptr +
+		    input_offset++;
+		split_type = GET_FIELD(split_hdr->hdr,
+				       DBG_DUMP_SPLIT_HDR_SPLIT_TYPE_ID);
+		split_data_size = GET_FIELD(split_hdr->hdr,
+					    DBG_DUMP_SPLIT_HDR_DATA_SIZE);
+		curr_input_mems_arr.ptr = (u32 *)dbg_buf->ptr + input_offset;
+		curr_input_mems_arr.size = DWORDS_TO_BYTES(split_data_size);
+
+		if (split_type == SPLIT_TYPE_NONE)
+			offset += qed_grc_dump_mem_entries(p_hwfn,
+							   p_ptt,
+							   curr_input_mems_arr,
+							   dump_buf + offset,
+							   dump);
+		else
+			DP_NOTICE(p_hwfn, false,
+				  "Dumping split memories is currently not supported\n");
+
+		input_offset += split_data_size;
+	}
+
+	return offset;
+}
+
+/* Dumps GRC context data for the specified Storm.
+ * Returns the dumped size in dwords.
+ * The lid_size argument is specified in quad-regs.
+ */
+static u32 qed_grc_dump_ctx_data(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf,
+				 bool dump,
+				 const char *name,
+				 u32 num_lids,
+				 enum cm_ctx_types ctx_type, u8 storm_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	u32 i, lid, lid_size, total_size;
+	u32 rd_reg_addr, offset = 0;
+
+	/* Convert quad-regs to dwords */
+	lid_size = storm->cm_ctx_lid_sizes[dev_data->chip_id][ctx_type] * 4;
+
+	if (!lid_size)
+		return 0;
+
+	total_size = num_lids * lid_size;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       name,
+				       0,
+				       total_size,
+				       lid_size * 32,
+				       false, name, storm->letter);
+
+	if (!dump)
+		return offset + total_size;
+
+	rd_reg_addr = BYTES_TO_DWORDS(storm->cm_ctx_rd_addr[ctx_type]);
+
+	/* Dump context data */
+	for (lid = 0; lid < num_lids; lid++) {
+		for (i = 0; i < lid_size; i++) {
+			ecore_wr(p_hwfn,
+			       p_ptt, storm->cm_ctx_wr_addr, (i << 9) | lid);
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  rd_reg_addr,
+							  1,
+							  false,
+							  SPLIT_TYPE_NONE, 0);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC contexts. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_ctx(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	u32 offset = 0;
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		if (!qed_grc_is_storm_included(p_hwfn,
+					       (enum dbg_storms)storm_id))
+			continue;
+
+		/* Dump Conn AG context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"CONN_AG_CTX",
+						NUM_OF_LCIDS,
+						CM_CTX_CONN_AG, storm_id);
+
+		/* Dump Conn ST context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"CONN_ST_CTX",
+						NUM_OF_LCIDS,
+						CM_CTX_CONN_ST, storm_id);
+
+		/* Dump Task AG context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"TASK_AG_CTX",
+						NUM_OF_LTIDS,
+						CM_CTX_TASK_AG, storm_id);
+
+		/* Dump Task ST context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"TASK_ST_CTX",
+						NUM_OF_LTIDS,
+						CM_CTX_TASK_ST, storm_id);
+	}
+
+	return offset;
+}
+
+#define VFC_STATUS_RESP_READY_BIT	0
+#define VFC_STATUS_BUSY_BIT		1
+#define VFC_STATUS_SENDING_CMD_BIT	2
+
+#define VFC_POLLING_DELAY_MS	1
+#define VFC_POLLING_COUNT		20
+
+/* Reads data from VFC. Returns the number of dwords read (0 on error).
+ * Sizes are specified in dwords.
+ */
+static u32 qed_grc_dump_read_from_vfc(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      struct storm_defs *storm,
+				      u32 *cmd_data,
+				      u32 cmd_size,
+				      u32 *addr_data,
+				      u32 addr_size,
+				      u32 resp_size, u32 *dump_buf)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 vfc_status, polling_ms, polling_count = 0, i;
+	u32 reg_addr, sem_base;
+	bool is_ready = false;
+
+	sem_base = storm->sem_fast_mem_addr;
+	polling_ms = VFC_POLLING_DELAY_MS *
+	    s_hw_type_defs[dev_data->hw_type].delay_factor;
+
+	/* Write VFC command */
+	ARR_REG_WR(p_hwfn,
+		   p_ptt,
+		   sem_base + SEM_FAST_REG_VFC_DATA_WR,
+		   cmd_data, cmd_size);
+
+	/* Write VFC address */
+	ARR_REG_WR(p_hwfn,
+		   p_ptt,
+		   sem_base + SEM_FAST_REG_VFC_ADDR,
+		   addr_data, addr_size);
+
+	/* Read response */
+	for (i = 0; i < resp_size; i++) {
+		/* Poll until ready */
+		do {
+			reg_addr = sem_base + SEM_FAST_REG_VFC_STATUS;
+			qed_grc_dump_addr_range(p_hwfn,
+						p_ptt,
+						&vfc_status,
+						true,
+						BYTES_TO_DWORDS(reg_addr),
+						1,
+						false, SPLIT_TYPE_NONE, 0);
+			is_ready = vfc_status &
+				   OSAL_BIT(VFC_STATUS_RESP_READY_BIT);
+
+			if (!is_ready) {
+				if (polling_count++ == VFC_POLLING_COUNT)
+					return 0;
+
+				OSAL_MSLEEP(polling_ms);
+			}
+		} while (!is_ready);
+
+		reg_addr = sem_base + SEM_FAST_REG_VFC_DATA_RD;
+		qed_grc_dump_addr_range(p_hwfn,
+					p_ptt,
+					dump_buf + i,
+					true,
+					BYTES_TO_DWORDS(reg_addr),
+					1, false, SPLIT_TYPE_NONE, 0);
+	}
+
+	return resp_size;
+}
+
+/* Dump VFC CAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_vfc_cam(struct ecore_hwfn *p_hwfn,
+				struct ecore_ptt *p_ptt,
+				u32 *dump_buf, bool dump, u8 storm_id)
+{
+	u32 total_size = VFC_CAM_NUM_ROWS * VFC_CAM_RESP_DWORDS;
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	u32 cam_addr[VFC_CAM_ADDR_DWORDS] = { 0 };
+	u32 cam_cmd[VFC_CAM_CMD_DWORDS] = { 0 };
+	u32 row, offset = 0;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       "vfc_cam",
+				       0,
+				       total_size,
+				       256,
+				       false, "vfc_cam", storm->letter);
+
+	if (!dump)
+		return offset + total_size;
+
+	/* Prepare CAM address */
+	SET_VAR_FIELD(cam_addr, VFC_CAM_ADDR, OP, VFC_OPCODE_CAM_RD);
+
+	/* Read VFC CAM data */
+	for (row = 0; row < VFC_CAM_NUM_ROWS; row++) {
+		SET_VAR_FIELD(cam_cmd, VFC_CAM_CMD, ROW, row);
+		offset += qed_grc_dump_read_from_vfc(p_hwfn,
+						     p_ptt,
+						     storm,
+						     cam_cmd,
+						     VFC_CAM_CMD_DWORDS,
+						     cam_addr,
+						     VFC_CAM_ADDR_DWORDS,
+						     VFC_CAM_RESP_DWORDS,
+						     dump_buf + offset);
+	}
+
+	return offset;
+}
+
+/* Dump VFC RAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_vfc_ram(struct ecore_hwfn *p_hwfn,
+				struct ecore_ptt *p_ptt,
+				u32 *dump_buf,
+				bool dump,
+				u8 storm_id, struct vfc_ram_defs *ram_defs)
+{
+	u32 total_size = ram_defs->num_rows * VFC_RAM_RESP_DWORDS;
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	u32 ram_addr[VFC_RAM_ADDR_DWORDS] = { 0 };
+	u32 ram_cmd[VFC_RAM_CMD_DWORDS] = { 0 };
+	u32 row, offset = 0;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       ram_defs->mem_name,
+				       0,
+				       total_size,
+				       256,
+				       false,
+				       ram_defs->type_name,
+				       storm->letter);
+
+	if (!dump)
+		return offset + total_size;
+
+	/* Prepare RAM address */
+	SET_VAR_FIELD(ram_addr, VFC_RAM_ADDR, OP, VFC_OPCODE_RAM_RD);
+
+	/* Read VFC RAM data */
+	for (row = ram_defs->base_row;
+	     row < ram_defs->base_row + ram_defs->num_rows; row++) {
+		SET_VAR_FIELD(ram_addr, VFC_RAM_ADDR, ROW, row);
+		offset += qed_grc_dump_read_from_vfc(p_hwfn,
+						     p_ptt,
+						     storm,
+						     ram_cmd,
+						     VFC_RAM_CMD_DWORDS,
+						     ram_addr,
+						     VFC_RAM_ADDR_DWORDS,
+						     VFC_RAM_RESP_DWORDS,
+						     dump_buf + offset);
+	}
+
+	return offset;
+}
+
+/* Dumps GRC VFC data. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_vfc(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	u8 storm_id, i;
+	u32 offset = 0;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		if (!qed_grc_is_storm_included(p_hwfn,
+					       (enum dbg_storms)storm_id) ||
+		    !s_storm_defs[storm_id].has_vfc)
+			continue;
+
+		/* Read CAM */
+		offset += qed_grc_dump_vfc_cam(p_hwfn,
+					       p_ptt,
+					       dump_buf + offset,
+					       dump, storm_id);
+
+		/* Read RAM */
+		for (i = 0; i < NUM_VFC_RAM_TYPES; i++)
+			offset += qed_grc_dump_vfc_ram(p_hwfn,
+						       p_ptt,
+						       dump_buf + offset,
+						       dump,
+						       storm_id,
+						       &s_vfc_ram_defs[i]);
+	}
+
+	return offset;
+}
+
+/* Dumps GRC RSS data. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_rss(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 offset = 0;
+	u8 rss_mem_id;
+
+	for (rss_mem_id = 0; rss_mem_id < NUM_RSS_MEM_TYPES; rss_mem_id++) {
+		u32 rss_addr, num_entries, total_dwords;
+		struct rss_mem_defs *rss_defs;
+		u32 addr, num_dwords_to_read;
+		bool packed;
+
+		rss_defs = &s_rss_mem_defs[rss_mem_id];
+		rss_addr = rss_defs->addr;
+		num_entries = rss_defs->num_entries[dev_data->chip_id];
+		total_dwords = (num_entries * rss_defs->entry_width) / 32;
+		packed = (rss_defs->entry_width == 16);
+
+		offset += qed_grc_dump_mem_hdr(p_hwfn,
+					       dump_buf + offset,
+					       dump,
+					       rss_defs->mem_name,
+					       0,
+					       total_dwords,
+					       rss_defs->entry_width,
+					       packed,
+					       rss_defs->type_name, 0);
+
+		/* Dump RSS data */
+		if (!dump) {
+			offset += total_dwords;
+			continue;
+		}
+
+		addr = BYTES_TO_DWORDS(RSS_REG_RSS_RAM_DATA);
+		while (total_dwords) {
+			num_dwords_to_read = OSAL_MIN_T(u32,
+						      RSS_REG_RSS_RAM_DATA_SIZE,
+						      total_dwords);
+			ecore_wr(p_hwfn, p_ptt, RSS_REG_RSS_RAM_ADDR, rss_addr);
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  addr,
+							  num_dwords_to_read,
+							  false,
+							  SPLIT_TYPE_NONE, 0);
+			total_dwords -= num_dwords_to_read;
+			rss_addr++;
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC Big RAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_big_ram(struct ecore_hwfn *p_hwfn,
+				struct ecore_ptt *p_ptt,
+				u32 *dump_buf, bool dump, u8 big_ram_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_size, ram_size, offset = 0, reg_val, i;
+	char mem_name[12] = "???_BIG_RAM";
+	char type_name[8] = "???_RAM";
+	struct big_ram_defs *big_ram;
+
+	big_ram = &s_big_ram_defs[big_ram_id];
+	ram_size = big_ram->ram_size[dev_data->chip_id];
+
+	reg_val = ecore_rd(p_hwfn, p_ptt, big_ram->is_256b_reg_addr);
+	block_size = reg_val &
+		     OSAL_BIT(big_ram->is_256b_bit_offset[dev_data->chip_id]) ?
+								     256 : 128;
+
+	strncpy(type_name, big_ram->instance_name, BIG_RAM_NAME_LEN);
+	strncpy(mem_name, big_ram->instance_name, BIG_RAM_NAME_LEN);
+
+	/* Dump memory header */
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       mem_name,
+				       0,
+				       ram_size,
+				       block_size * 8,
+				       false, type_name, 0);
+
+	/* Read and dump Big RAM data */
+	if (!dump)
+		return offset + ram_size;
+
+	/* Dump Big RAM */
+	for (i = 0; i < DIV_ROUND_UP(ram_size, BRB_REG_BIG_RAM_DATA_SIZE);
+	     i++) {
+		u32 addr, len;
+
+		ecore_wr(p_hwfn, p_ptt, big_ram->addr_reg_addr, i);
+		addr = BYTES_TO_DWORDS(big_ram->data_reg_addr);
+		len = BRB_REG_BIG_RAM_DATA_SIZE;
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  dump,
+						  addr,
+						  len,
+						  false, SPLIT_TYPE_NONE, 0);
+	}
+
+	return offset;
+}
+
+/* Dumps MCP scratchpad. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_mcp(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	bool block_enable[MAX_BLOCK_ID] = { 0 };
+	u32 offset = 0, addr;
+	bool halted = false;
+
+	/* Halt MCP */
+	if (dump && !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP)) {
+		halted = !ecore_mcp_halt(p_hwfn, p_ptt);
+		if (!halted)
+			DP_NOTICE(p_hwfn, false, "MCP halt failed!\n");
+	}
+
+	/* Dump MCP scratchpad */
+	offset += qed_grc_dump_mem(p_hwfn,
+				   p_ptt,
+				   dump_buf + offset,
+				   dump,
+				   NULL,
+				   BYTES_TO_DWORDS(MCP_REG_SCRATCH),
+				   MCP_REG_SCRATCH_SIZE,
+				   false, 0, false, "MCP", 0);
+
+	/* Dump MCP cpu_reg_file */
+	offset += qed_grc_dump_mem(p_hwfn,
+				   p_ptt,
+				   dump_buf + offset,
+				   dump,
+				   NULL,
+				   BYTES_TO_DWORDS(MCP_REG_CPU_REG_FILE),
+				   MCP_REG_CPU_REG_FILE_SIZE,
+				   false, 0, false, "MCP", 0);
+
+	/* Dump MCP registers */
+	block_enable[BLOCK_MCP] = true;
+	offset += qed_grc_dump_registers(p_hwfn,
+					 p_ptt,
+					 dump_buf + offset,
+					 dump, block_enable, "MCP");
+
+	/* Dump required non-MCP registers */
+	offset += qed_grc_dump_regs_hdr(dump_buf + offset,
+					dump, 1, SPLIT_TYPE_NONE, 0,
+					"MCP");
+	addr = BYTES_TO_DWORDS(MISC_REG_SHARED_MEM_ADDR);
+	offset += qed_grc_dump_reg_entry(p_hwfn,
+					 p_ptt,
+					 dump_buf + offset,
+					 dump,
+					 addr,
+					 1,
+					 false, SPLIT_TYPE_NONE, 0);
+
+	/* Release MCP */
+	if (halted && ecore_mcp_resume(p_hwfn, p_ptt))
+		DP_NOTICE(p_hwfn, false, "Failed to resume MCP after halt!\n");
+
+	return offset;
+}
+
+/* Dumps the tbus indirect memory for all PHYs.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_grc_dump_phy(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	u32 offset = 0, tbus_lo_offset, tbus_hi_offset;
+	char mem_name[32];
+	u8 phy_id;
+
+	for (phy_id = 0; phy_id < OSAL_ARRAY_SIZE(s_phy_defs); phy_id++) {
+		u32 addr_lo_addr, addr_hi_addr, data_lo_addr, data_hi_addr;
+		struct phy_defs *phy_defs;
+		u8 *bytes_buf;
+
+		phy_defs = &s_phy_defs[phy_id];
+		addr_lo_addr = phy_defs->base_addr +
+			       phy_defs->tbus_addr_lo_addr;
+		addr_hi_addr = phy_defs->base_addr +
+			       phy_defs->tbus_addr_hi_addr;
+		data_lo_addr = phy_defs->base_addr +
+			       phy_defs->tbus_data_lo_addr;
+		data_hi_addr = phy_defs->base_addr +
+			       phy_defs->tbus_data_hi_addr;
+
+		if (snprintf(mem_name, sizeof(mem_name), "tbus_%s",
+			     phy_defs->phy_name) < 0)
+			DP_NOTICE(p_hwfn, false,
+				  "Unexpected debug error: invalid PHY memory name\n");
+
+		offset += qed_grc_dump_mem_hdr(p_hwfn,
+					       dump_buf + offset,
+					       dump,
+					       mem_name,
+					       0,
+					       PHY_DUMP_SIZE_DWORDS,
+					       16, true, mem_name, 0);
+
+		if (!dump) {
+			offset += PHY_DUMP_SIZE_DWORDS;
+			continue;
+		}
+
+		bytes_buf = (u8 *)(dump_buf + offset);
+		for (tbus_hi_offset = 0;
+		     tbus_hi_offset < (NUM_PHY_TBUS_ADDRESSES >> 8);
+		     tbus_hi_offset++) {
+			ecore_wr(p_hwfn, p_ptt, addr_hi_addr, tbus_hi_offset);
+			for (tbus_lo_offset = 0; tbus_lo_offset < 256;
+			     tbus_lo_offset++) {
+				ecore_wr(p_hwfn,
+				       p_ptt, addr_lo_addr, tbus_lo_offset);
+				*(bytes_buf++) = (u8)ecore_rd(p_hwfn,
+							    p_ptt,
+							    data_lo_addr);
+				*(bytes_buf++) = (u8)ecore_rd(p_hwfn,
+							    p_ptt,
+							    data_hi_addr);
+			}
+		}
+
+		offset += PHY_DUMP_SIZE_DWORDS;
+	}
+
+	return offset;
+}
+
+static enum dbg_status qed_find_nvram_image(struct ecore_hwfn *p_hwfn,
+					    struct ecore_ptt *p_ptt,
+					    u32 image_type,
+					    u32 *nvram_offset_bytes,
+					    u32 *nvram_size_bytes);
+
+static enum dbg_status qed_nvram_read(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 nvram_offset_bytes,
+				      u32 nvram_size_bytes, u32 *ret_buf);
+
+/* Dumps the MCP HW dump from NVRAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_mcp_hw_dump(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    u32 *dump_buf, bool dump)
+{
+	u32 hw_dump_offset_bytes = 0, hw_dump_size_bytes = 0;
+	u32 hw_dump_size_dwords = 0, offset = 0;
+	enum dbg_status status;
+
+	/* Read HW dump image from NVRAM */
+	status = qed_find_nvram_image(p_hwfn,
+				      p_ptt,
+				      NVM_TYPE_HW_DUMP_OUT,
+				      &hw_dump_offset_bytes,
+				      &hw_dump_size_bytes);
+	if (status != DBG_STATUS_OK)
+		return 0;
+
+	hw_dump_size_dwords = BYTES_TO_DWORDS(hw_dump_size_bytes);
+
+	/* Dump HW dump image section */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "mcp_hw_dump", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", hw_dump_size_dwords);
+
+	/* Read MCP HW dump image into dump buffer */
+	if (dump && hw_dump_size_dwords) {
+		status = qed_nvram_read(p_hwfn,
+					p_ptt,
+					hw_dump_offset_bytes,
+					hw_dump_size_bytes, dump_buf + offset);
+		if (status != DBG_STATUS_OK) {
+			DP_NOTICE(p_hwfn, false,
+				  "Failed to read MCP HW Dump image from NVRAM\n");
+			return 0;
+		}
+	}
+	offset += hw_dump_size_dwords;
+
+	return offset;
+}
+
+/* Dumps Static Debug data. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_static_debug(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_id, line_id, offset = 0, addr, len;
+
+	/* Don't dump static debug if a debug bus recording is in progress */
+	if (dump && ecore_rd(p_hwfn, p_ptt, DBG_REG_DBG_BLOCK_ON))
+		return 0;
+
+	if (dump) {
+		/* Disable debug bus in all blocks */
+		qed_bus_disable_blocks(p_hwfn, p_ptt);
+
+		qed_bus_reset_dbg_block(p_hwfn, p_ptt);
+		ecore_wr(p_hwfn,
+		       p_ptt, DBG_REG_FRAMING_MODE, DBG_BUS_FRAME_MODE_8HW);
+		ecore_wr(p_hwfn,
+		       p_ptt, DBG_REG_DEBUG_TARGET, DBG_BUS_TARGET_ID_INT_BUF);
+		ecore_wr(p_hwfn, p_ptt, DBG_REG_FULL_MODE, 1);
+		qed_bus_enable_dbg_block(p_hwfn, p_ptt, true);
+	}
+
+	/* Dump all static debug lines for each relevant block */
+	for (block_id = 0; block_id < MAX_BLOCK_ID; block_id++) {
+		const struct dbg_block_chip *block_per_chip;
+		const struct dbg_block *block;
+		bool is_removed, has_dbg_bus;
+		u16 modes_buf_offset;
+		u32 block_dwords;
+
+		block_per_chip =
+		    qed_get_dbg_block_per_chip(p_hwfn, (enum block_id)block_id);
+		is_removed = GET_FIELD(block_per_chip->flags,
+				       DBG_BLOCK_CHIP_IS_REMOVED);
+		has_dbg_bus = GET_FIELD(block_per_chip->flags,
+					DBG_BLOCK_CHIP_HAS_DBG_BUS);
+
+		/* read+clear for NWS parity is not working, skip NWS block */
+		if (block_id == BLOCK_NWS)
+			continue;
+
+		if (!is_removed && has_dbg_bus &&
+		    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+			      DBG_MODE_HDR_EVAL_MODE) > 0) {
+			modes_buf_offset =
+			    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+				      DBG_MODE_HDR_MODES_BUF_OFFSET);
+			if (!qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				has_dbg_bus = false;
+		}
+
+		if (is_removed || !has_dbg_bus)
+			continue;
+
+		block_dwords = NUM_DBG_LINES(block_per_chip) *
+			       STATIC_DEBUG_LINE_DWORDS;
+
+		/* Dump static section params */
+		block = get_dbg_block(p_hwfn, (enum block_id)block_id);
+		offset += qed_grc_dump_mem_hdr(p_hwfn,
+					       dump_buf + offset,
+					       dump,
+					       (const char *)block->name,
+					       0,
+					       block_dwords,
+					       32, false, "STATIC", 0);
+
+		if (!dump) {
+			offset += block_dwords;
+			continue;
+		}
+
+		/* If all lines are invalid - dump zeros */
+		if (dev_data->block_in_reset[block_id]) {
+			memset(dump_buf + offset, 0,
+			       DWORDS_TO_BYTES(block_dwords));
+			offset += block_dwords;
+			continue;
+		}
+
+		/* Enable block's client */
+		qed_bus_enable_clients(p_hwfn,
+				       p_ptt,
+				       OSAL_BIT(block_per_chip->dbg_client_id));
+
+		addr = BYTES_TO_DWORDS(DBG_REG_CALENDAR_OUT_DATA);
+		len = STATIC_DEBUG_LINE_DWORDS;
+		for (line_id = 0; line_id < (u32)NUM_DBG_LINES(block_per_chip);
+		     line_id++) {
+			/* Configure debug line ID */
+			qed_bus_config_dbg_line(p_hwfn,
+						p_ptt,
+						(enum block_id)block_id,
+						(u8)line_id, 0xf, 0, 0, 0);
+
+			/* Read debug line info */
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  addr,
+							  len,
+							  true, SPLIT_TYPE_NONE,
+							  0);
+		}
+
+		/* Disable block's client and debug output */
+		qed_bus_enable_clients(p_hwfn, p_ptt, 0);
+		qed_bus_config_dbg_line(p_hwfn, p_ptt,
+					(enum block_id)block_id, 0, 0, 0, 0, 0);
+	}
+
+	if (dump) {
+		qed_bus_enable_dbg_block(p_hwfn, p_ptt, false);
+		qed_bus_enable_clients(p_hwfn, p_ptt, 0);
+	}
+
+	return offset;
+}
+
+/* Performs GRC Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static enum dbg_status qed_grc_dump(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    u32 *dump_buf,
+				    bool dump, u32 *num_dumped_dwords)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 dwords_read, offset = 0;
+	bool parities_masked = false;
+	u8 i;
+
+	*num_dumped_dwords = 0;
+	dev_data->num_regs_read = 0;
+
+	/* Update reset state */
+	if (dump)
+		qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 4);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "grc-dump");
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "num-lcids",
+				     NUM_OF_LCIDS);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "num-ltids",
+				     NUM_OF_LTIDS);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "num-ports", dev_data->num_ports);
+
+	/* Dump reset registers (dumped before taking blocks out of reset ) */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS))
+		offset += qed_grc_dump_reset_regs(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset, dump);
+
+	/* Take all blocks out of reset (using reset registers) */
+	if (dump) {
+		qed_grc_unreset_blocks(p_hwfn, p_ptt, false);
+		qed_update_blocks_reset_state(p_hwfn, p_ptt);
+	}
+
+	/* Disable all parities using MFW command */
+	if (dump &&
+	    !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP)) {
+		parities_masked = !ecore_mcp_mask_parities(p_hwfn, p_ptt, 1);
+		if (!parities_masked) {
+			DP_NOTICE(p_hwfn, false,
+				  "Failed to mask parities using MFW\n");
+			if (qed_grc_get_param
+			    (p_hwfn, DBG_GRC_PARAM_PARITY_SAFE))
+				return DBG_STATUS_MCP_COULD_NOT_MASK_PRTY;
+		}
+	}
+
+	/* Dump modified registers (dumped before modifying them) */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS))
+		offset += qed_grc_dump_modified_regs(p_hwfn,
+						     p_ptt,
+						     dump_buf + offset, dump);
+
+	/* Stall storms */
+	if (dump &&
+	    (qed_grc_is_included(p_hwfn,
+				 DBG_GRC_PARAM_DUMP_IOR) ||
+	     qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_VFC)))
+		qed_grc_stall_storms(p_hwfn, p_ptt, true);
+
+	/* Dump all regs  */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS)) {
+		bool block_enable[MAX_BLOCK_ID];
+
+		/* Dump all blocks except MCP */
+		for (i = 0; i < MAX_BLOCK_ID; i++)
+			block_enable[i] = true;
+		block_enable[BLOCK_MCP] = false;
+		offset += qed_grc_dump_registers(p_hwfn,
+						 p_ptt,
+						 dump_buf +
+						 offset,
+						 dump,
+						 block_enable, NULL);
+
+		/* Dump special registers */
+		offset += qed_grc_dump_special_regs(p_hwfn,
+						    p_ptt,
+						    dump_buf + offset, dump);
+	}
+
+	/* Dump memories */
+	offset += qed_grc_dump_memories(p_hwfn, p_ptt, dump_buf + offset, dump);
+
+	/* Dump MCP */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MCP))
+		offset += qed_grc_dump_mcp(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump context */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM_CTX))
+		offset += qed_grc_dump_ctx(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump RSS memories */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_RSS))
+		offset += qed_grc_dump_rss(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump Big RAM */
+	for (i = 0; i < NUM_BIG_RAM_TYPES; i++)
+		if (qed_grc_is_included(p_hwfn, s_big_ram_defs[i].grc_param))
+			offset += qed_grc_dump_big_ram(p_hwfn,
+						       p_ptt,
+						       dump_buf + offset,
+						       dump, i);
+
+	/* Dump VFC */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_VFC)) {
+		dwords_read = qed_grc_dump_vfc(p_hwfn,
+					       p_ptt, dump_buf + offset, dump);
+		offset += dwords_read;
+		if (!dwords_read)
+			return DBG_STATUS_VFC_READ_ERROR;
+	}
+
+	/* Dump PHY tbus */
+	if (qed_grc_is_included(p_hwfn,
+				DBG_GRC_PARAM_DUMP_PHY) && dev_data->chip_id ==
+	    CHIP_K2 && dev_data->hw_type == HW_TYPE_ASIC)
+		offset += qed_grc_dump_phy(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump MCP HW Dump */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MCP_HW_DUMP) &&
+	    !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP) && 1)
+		offset += qed_grc_dump_mcp_hw_dump(p_hwfn,
+						   p_ptt,
+						   dump_buf + offset, dump);
+
+	/* Dump static debug data (only if not during debug bus recording) */
+	if (qed_grc_is_included(p_hwfn,
+				DBG_GRC_PARAM_DUMP_STATIC) &&
+	    (!dump || dev_data->bus.state == DBG_BUS_STATE_IDLE))
+		offset += qed_grc_dump_static_debug(p_hwfn,
+						    p_ptt,
+						    dump_buf + offset, dump);
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	if (dump) {
+		/* Unstall storms */
+		if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_UNSTALL))
+			qed_grc_stall_storms(p_hwfn, p_ptt, false);
+
+		/* Clear parity status */
+		qed_grc_clear_all_prty(p_hwfn, p_ptt);
+
+		/* Enable all parities using MFW command */
+		if (parities_masked)
+			ecore_mcp_mask_parities(p_hwfn, p_ptt, 0);
+	}
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Writes the specified failing Idle Check rule to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_idle_chk_dump_failure(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     u32 *
+				     dump_buf,
+				     bool dump,
+				     u16 rule_id,
+				     const struct dbg_idle_chk_rule *rule,
+				     u16 fail_entry_id, u32 *cond_reg_values)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	const struct dbg_idle_chk_cond_reg *cond_regs;
+	const struct dbg_idle_chk_info_reg *info_regs;
+	u32 i, next_reg_offset = 0, offset = 0;
+	struct dbg_idle_chk_result_hdr *hdr;
+	const union dbg_idle_chk_reg *regs;
+	u8 reg_id;
+
+	hdr = (struct dbg_idle_chk_result_hdr *)dump_buf;
+	regs = (const union dbg_idle_chk_reg *)
+		p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr +
+		rule->reg_offset;
+	cond_regs = &regs[0].cond_reg;
+	info_regs = &regs[rule->num_cond_regs].info_reg;
+
+	/* Dump rule data */
+	if (dump) {
+		memset(hdr, 0, sizeof(*hdr));
+		hdr->rule_id = rule_id;
+		hdr->mem_entry_id = fail_entry_id;
+		hdr->severity = rule->severity;
+		hdr->num_dumped_cond_regs = rule->num_cond_regs;
+	}
+
+	offset += IDLE_CHK_RESULT_HDR_DWORDS;
+
+	/* Dump condition register values */
+	for (reg_id = 0; reg_id < rule->num_cond_regs; reg_id++) {
+		const struct dbg_idle_chk_cond_reg *reg = &cond_regs[reg_id];
+		struct dbg_idle_chk_result_reg_hdr *reg_hdr;
+
+		reg_hdr =
+		    (struct dbg_idle_chk_result_reg_hdr *)(dump_buf + offset);
+
+		/* Write register header */
+		if (!dump) {
+			offset += IDLE_CHK_RESULT_REG_HDR_DWORDS +
+			    reg->entry_size;
+			continue;
+		}
+
+		offset += IDLE_CHK_RESULT_REG_HDR_DWORDS;
+		memset(reg_hdr, 0, sizeof(*reg_hdr));
+		reg_hdr->start_entry = reg->start_entry;
+		reg_hdr->size = reg->entry_size;
+		SET_FIELD(reg_hdr->data,
+			  DBG_IDLE_CHK_RESULT_REG_HDR_IS_MEM,
+			  reg->num_entries > 1 || reg->start_entry > 0 ? 1 : 0);
+		SET_FIELD(reg_hdr->data,
+			  DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID, reg_id);
+
+		/* Write register values */
+		for (i = 0; i < reg_hdr->size; i++, next_reg_offset++, offset++)
+			dump_buf[offset] = cond_reg_values[next_reg_offset];
+	}
+
+	/* Dump info register values */
+	for (reg_id = 0; reg_id < rule->num_info_regs; reg_id++) {
+		const struct dbg_idle_chk_info_reg *reg = &info_regs[reg_id];
+		u32 block_id;
+
+		/* Check if register's block is in reset */
+		if (!dump) {
+			offset += IDLE_CHK_RESULT_REG_HDR_DWORDS + reg->size;
+			continue;
+		}
+
+		block_id = GET_FIELD(reg->data, DBG_IDLE_CHK_INFO_REG_BLOCK_ID);
+		if (block_id >= MAX_BLOCK_ID) {
+			DP_NOTICE(p_hwfn, false, "Invalid block_id\n");
+			return 0;
+		}
+
+		if (!dev_data->block_in_reset[block_id]) {
+			struct dbg_idle_chk_result_reg_hdr *reg_hdr;
+			bool wide_bus, eval_mode, mode_match = true;
+			u16 modes_buf_offset;
+			u32 addr;
+
+			reg_hdr = (struct dbg_idle_chk_result_reg_hdr *)
+				  (dump_buf + offset);
+
+			/* Check mode */
+			eval_mode = GET_FIELD(reg->mode.data,
+					      DBG_MODE_HDR_EVAL_MODE) > 0;
+			if (eval_mode) {
+				modes_buf_offset =
+				    GET_FIELD(reg->mode.data,
+					      DBG_MODE_HDR_MODES_BUF_OFFSET);
+				mode_match =
+					qed_is_mode_match(p_hwfn,
+							  &modes_buf_offset);
+			}
+
+			if (!mode_match)
+				continue;
+
+			addr = GET_FIELD(reg->data,
+					 DBG_IDLE_CHK_INFO_REG_ADDRESS);
+			wide_bus = GET_FIELD(reg->data,
+					     DBG_IDLE_CHK_INFO_REG_WIDE_BUS);
+
+			/* Write register header */
+			offset += IDLE_CHK_RESULT_REG_HDR_DWORDS;
+			hdr->num_dumped_info_regs++;
+			memset(reg_hdr, 0, sizeof(*reg_hdr));
+			reg_hdr->size = reg->size;
+			SET_FIELD(reg_hdr->data,
+				  DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID,
+				  rule->num_cond_regs + reg_id);
+
+			/* Write register values */
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  addr,
+							  reg->size, wide_bus,
+							  SPLIT_TYPE_NONE, 0);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps idle check rule entries. Returns the dumped size in dwords. */
+static u32
+qed_idle_chk_dump_rule_entries(struct ecore_hwfn *p_hwfn,
+			       struct ecore_ptt *p_ptt,
+			       u32 *dump_buf, bool dump,
+			       const struct dbg_idle_chk_rule *input_rules,
+			       u32 num_input_rules, u32 *num_failing_rules)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 cond_reg_values[IDLE_CHK_MAX_ENTRIES_SIZE];
+	u32 i, offset = 0;
+	u16 entry_id;
+	u8 reg_id;
+
+	*num_failing_rules = 0;
+
+	for (i = 0; i < num_input_rules; i++) {
+		const struct dbg_idle_chk_cond_reg *cond_regs;
+		const struct dbg_idle_chk_rule *rule;
+		const union dbg_idle_chk_reg *regs;
+		u16 num_reg_entries = 1;
+		bool check_rule = true;
+		const u32 *imm_values;
+
+		rule = &input_rules[i];
+		regs = (const union dbg_idle_chk_reg *)
+			p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr +
+			rule->reg_offset;
+		cond_regs = &regs[0].cond_reg;
+		imm_values =
+		    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_IMMS].ptr +
+		    rule->imm_offset;
+
+		/* Check if all condition register blocks are out of reset, and
+		 * find maximal number of entries (all condition registers that
+		 * are memories must have the same size, which is > 1).
+		 */
+		for (reg_id = 0; reg_id < rule->num_cond_regs && check_rule;
+		     reg_id++) {
+			u32 block_id =
+				GET_FIELD(cond_regs[reg_id].data,
+					  DBG_IDLE_CHK_COND_REG_BLOCK_ID);
+
+			if (block_id >= MAX_BLOCK_ID) {
+				DP_NOTICE(p_hwfn, false, "Invalid block_id\n");
+				return 0;
+			}
+
+			check_rule = !dev_data->block_in_reset[block_id];
+			if (cond_regs[reg_id].num_entries > num_reg_entries)
+				num_reg_entries = cond_regs[reg_id].num_entries;
+		}
+
+		if (!check_rule && dump)
+			continue;
+
+		if (!dump) {
+			u32 entry_dump_size =
+				qed_idle_chk_dump_failure(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  false,
+							  rule->rule_id,
+							  rule,
+							  0,
+							  NULL);
+
+			offset += num_reg_entries * entry_dump_size;
+			(*num_failing_rules) += num_reg_entries;
+			continue;
+		}
+
+		/* Go over all register entries (number of entries is the same
+		 * for all condition registers).
+		 */
+		for (entry_id = 0; entry_id < num_reg_entries; entry_id++) {
+			u32 next_reg_offset = 0;
+
+			/* Read current entry of all condition registers */
+			for (reg_id = 0; reg_id < rule->num_cond_regs;
+			     reg_id++) {
+				const struct dbg_idle_chk_cond_reg *reg =
+					&cond_regs[reg_id];
+				u32 padded_entry_size, addr;
+				bool wide_bus;
+
+				/* Find GRC address (if it's a memory, the
+				 * address of the specific entry is calculated).
+				 */
+				addr = GET_FIELD(reg->data,
+						 DBG_IDLE_CHK_COND_REG_ADDRESS);
+				wide_bus =
+				    GET_FIELD(reg->data,
+					      DBG_IDLE_CHK_COND_REG_WIDE_BUS);
+				if (reg->num_entries > 1 ||
+				    reg->start_entry > 0) {
+					padded_entry_size =
+					   reg->entry_size > 1 ?
+					   OSAL_ROUNDUP_POW_OF_TWO(reg->entry_size) :
+					   1;
+					addr += (reg->start_entry + entry_id) *
+						padded_entry_size;
+				}
+
+				/* Read registers */
+				if (next_reg_offset + reg->entry_size >=
+				    IDLE_CHK_MAX_ENTRIES_SIZE) {
+					DP_NOTICE(p_hwfn, false,
+						  "idle check registers entry is too large\n");
+					return 0;
+				}
+
+				next_reg_offset +=
+				    qed_grc_dump_addr_range(p_hwfn, p_ptt,
+							    cond_reg_values +
+							    next_reg_offset,
+							    dump, addr,
+							    reg->entry_size,
+							    wide_bus,
+							    SPLIT_TYPE_NONE, 0);
+			}
+
+			/* Call rule condition function.
+			 * If returns true, it's a failure.
+			 */
+			if ((*cond_arr[rule->cond_id]) (cond_reg_values,
+							imm_values)) {
+				offset += qed_idle_chk_dump_failure(p_hwfn,
+							p_ptt,
+							dump_buf + offset,
+							dump,
+							rule->rule_id,
+							rule,
+							entry_id,
+							cond_reg_values);
+				(*num_failing_rules)++;
+			}
+		}
+	}
+
+	return offset;
+}
+
+/* Performs Idle Check Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+			     struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	struct virt_mem_desc *dbg_buf =
+	    &p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_RULES];
+	u32 num_failing_rules_offset, offset = 0,
+	    input_offset = 0, num_failing_rules = 0;
+
+	/* Dump global params  - 1 must match below amount of params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "idle-chk");
+
+	/* Dump idle check section header with a single parameter */
+	offset += qed_dump_section_hdr(dump_buf + offset, dump, "idle_chk", 1);
+	num_failing_rules_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "num_rules", 0);
+
+	while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
+		const struct dbg_idle_chk_cond_hdr *cond_hdr =
+		    (const struct dbg_idle_chk_cond_hdr *)dbg_buf->ptr +
+		    input_offset++;
+		bool eval_mode, mode_match = true;
+		u32 curr_failing_rules;
+		u16 modes_buf_offset;
+
+		/* Check mode */
+		eval_mode = GET_FIELD(cond_hdr->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		if (eval_mode) {
+			modes_buf_offset =
+				GET_FIELD(cond_hdr->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			mode_match = qed_is_mode_match(p_hwfn,
+						       &modes_buf_offset);
+		}
+
+		if (mode_match) {
+			const struct dbg_idle_chk_rule *rule =
+			    (const struct dbg_idle_chk_rule *)((u32 *)
+							       dbg_buf->ptr
+							       + input_offset);
+			u32 num_input_rules =
+				cond_hdr->data_size / IDLE_CHK_RULE_SIZE_DWORDS;
+			offset +=
+			    qed_idle_chk_dump_rule_entries(p_hwfn,
+							   p_ptt,
+							   dump_buf +
+							   offset,
+							   dump,
+							   rule,
+							   num_input_rules,
+							   &curr_failing_rules);
+			num_failing_rules += curr_failing_rules;
+		}
+
+		input_offset += cond_hdr->data_size;
+	}
+
+	/* Overwrite num_rules parameter */
+	if (dump)
+		qed_dump_num_param(dump_buf + num_failing_rules_offset,
+				   dump, "num_rules", num_failing_rules);
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	return offset;
+}
+
+/* Finds the meta data image in NVRAM */
+static enum dbg_status qed_find_nvram_image(struct ecore_hwfn *p_hwfn,
+					    struct ecore_ptt *p_ptt,
+					    u32 image_type,
+					    u32 *nvram_offset_bytes,
+					    u32 *nvram_size_bytes)
+{
+	u32 ret_mcp_resp, ret_mcp_param, ret_txn_size;
+	struct mcp_file_att file_att;
+	int nvm_result;
+
+	/* Call NVRAM get file command */
+	nvm_result = ecore_mcp_nvm_rd_cmd(p_hwfn,
+					p_ptt,
+					DRV_MSG_CODE_NVM_GET_FILE_ATT,
+					image_type,
+					&ret_mcp_resp,
+					&ret_mcp_param,
+					&ret_txn_size, (u32 *)&file_att);
+
+	/* Check response */
+	if (nvm_result ||
+	    (ret_mcp_resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_NVM_OK)
+		return DBG_STATUS_NVRAM_GET_IMAGE_FAILED;
+
+	/* Update return values */
+	*nvram_offset_bytes = file_att.nvm_start_addr;
+	*nvram_size_bytes = file_att.len;
+
+	DP_VERBOSE(p_hwfn->p_dev,
+		   ECORE_MSG_DEBUG,
+		   "find_nvram_image: found NVRAM image of type %d in NVRAM offset %d bytes with size %d bytes\n",
+		   image_type, *nvram_offset_bytes, *nvram_size_bytes);
+
+	/* Check alignment */
+	if (*nvram_size_bytes & 0x3)
+		return DBG_STATUS_NON_ALIGNED_NVRAM_IMAGE;
+
+	return DBG_STATUS_OK;
+}
+
+/* Reads data from NVRAM */
+static enum dbg_status qed_nvram_read(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 nvram_offset_bytes,
+				      u32 nvram_size_bytes, u32 *ret_buf)
+{
+	u32 ret_mcp_resp, ret_mcp_param, ret_read_size, bytes_to_copy;
+	s32 bytes_left = nvram_size_bytes;
+	u32 read_offset = 0, param = 0;
+
+	DP_NOTICE(p_hwfn->p_dev, false,
+		   "nvram_read: reading image of size %d bytes from NVRAM\n",
+		   nvram_size_bytes);
+
+	do {
+		bytes_to_copy =
+		    (bytes_left >
+		     MCP_DRV_NVM_BUF_LEN) ? MCP_DRV_NVM_BUF_LEN : bytes_left;
+
+		/* Call NVRAM read command */
+		SET_MFW_FIELD(param,
+			      DRV_MB_PARAM_NVM_OFFSET,
+			      nvram_offset_bytes + read_offset);
+		SET_MFW_FIELD(param, DRV_MB_PARAM_NVM_LEN, bytes_to_copy);
+		if (ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt,
+					 DRV_MSG_CODE_NVM_READ_NVRAM, param,
+					 &ret_mcp_resp,
+					 &ret_mcp_param, &ret_read_size,
+					 (u32 *)((u8 *)ret_buf +
+						 read_offset))) {
+			DP_NOTICE(p_hwfn->p_dev, false, "rc = DBG_STATUS_NVRAM_READ_FAILED\n");
+			return DBG_STATUS_NVRAM_READ_FAILED;
+		}
+
+		/* Check response */
+		if ((ret_mcp_resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_NVM_OK) {
+			DP_NOTICE(p_hwfn->p_dev, false, "rc = DBG_STATUS_NVRAM_READ_FAILED\n");
+			return DBG_STATUS_NVRAM_READ_FAILED;
+		}
+
+		/* Update read offset */
+		read_offset += ret_read_size;
+		bytes_left -= ret_read_size;
+	} while (bytes_left > 0);
+
+	return DBG_STATUS_OK;
+}
+
+/* Get info on the MCP Trace data in the scratchpad:
+ * - trace_data_grc_addr (OUT): trace data GRC address in bytes
+ * - trace_data_size (OUT): trace data size in bytes (without the header)
+ */
+static enum dbg_status qed_mcp_trace_get_data_info(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *trace_data_grc_addr,
+						   u32 *trace_data_size)
+{
+	u32 spad_trace_offsize, signature;
+
+	/* Read trace section offsize structure from MCP scratchpad */
+	spad_trace_offsize = ecore_rd(p_hwfn, p_ptt,
+				      MCP_SPAD_TRACE_OFFSIZE_ADDR);
+
+	/* Extract trace section address from offsize (in scratchpad) */
+	*trace_data_grc_addr =
+		MCP_REG_SCRATCH + SECTION_OFFSET(spad_trace_offsize);
+
+	/* Read signature from MCP trace section */
+	signature = ecore_rd(p_hwfn, p_ptt,
+			   *trace_data_grc_addr +
+			   offsetof(struct mcp_trace, signature));
+
+	if (signature != MFW_TRACE_SIGNATURE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Read trace size from MCP trace section */
+	*trace_data_size = ecore_rd(p_hwfn,
+				  p_ptt,
+				  *trace_data_grc_addr +
+				  offsetof(struct mcp_trace, size));
+
+	return DBG_STATUS_OK;
+}
+
+/* Reads MCP trace meta data image from NVRAM
+ * - running_bundle_id (OUT): running bundle ID (invalid when loaded from file)
+ * - trace_meta_offset (OUT): trace meta offset in NVRAM in bytes (invalid when
+ *			      loaded from file).
+ * - trace_meta_size (OUT):   size in bytes of the trace meta data.
+ */
+static enum dbg_status qed_mcp_trace_get_meta_info(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 trace_data_size_bytes,
+						   u32 *running_bundle_id,
+						   u32 *trace_meta_offset,
+						   u32 *trace_meta_size)
+{
+	u32 spad_trace_offsize, nvram_image_type, running_mfw_addr;
+
+	/* Read MCP trace section offsize structure from MCP scratchpad */
+	spad_trace_offsize = ecore_rd(p_hwfn, p_ptt,
+				      MCP_SPAD_TRACE_OFFSIZE_ADDR);
+
+	/* Find running bundle ID */
+	running_mfw_addr =
+		MCP_REG_SCRATCH + SECTION_OFFSET(spad_trace_offsize) +
+		SECTION_SIZE(spad_trace_offsize) + trace_data_size_bytes;
+	*running_bundle_id = ecore_rd(p_hwfn, p_ptt, running_mfw_addr);
+	if (*running_bundle_id > 1)
+		return DBG_STATUS_INVALID_NVRAM_BUNDLE;
+
+	/* Find image in NVRAM */
+	nvram_image_type =
+	    (*running_bundle_id ==
+	     DIR_ID_1) ? NVM_TYPE_MFW_TRACE1 : NVM_TYPE_MFW_TRACE2;
+	return qed_find_nvram_image(p_hwfn,
+				    p_ptt,
+				    nvram_image_type,
+				    trace_meta_offset, trace_meta_size);
+}
+
+/* Reads the MCP Trace meta data from NVRAM into the specified buffer */
+static enum dbg_status qed_mcp_trace_read_meta(struct ecore_hwfn *p_hwfn,
+					       struct ecore_ptt *p_ptt,
+					       u32 nvram_offset_in_bytes,
+					       u32 size_in_bytes, u32 *buf)
+{
+	u8 modules_num, module_len, i, *byte_buf = (u8 *)buf;
+	enum dbg_status status;
+	u32 signature;
+
+	/* Read meta data from NVRAM */
+	status = qed_nvram_read(p_hwfn,
+				p_ptt,
+				nvram_offset_in_bytes, size_in_bytes, buf);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Extract and check first signature */
+	signature = qed_read_unaligned_dword(byte_buf);
+	byte_buf += sizeof(signature);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Extract number of modules */
+	modules_num = *(byte_buf++);
+
+	/* Skip all modules */
+	for (i = 0; i < modules_num; i++) {
+		module_len = *(byte_buf++);
+		byte_buf += module_len;
+	}
+
+	/* Extract and check second signature */
+	signature = qed_read_unaligned_dword(byte_buf);
+	byte_buf += sizeof(signature);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	return DBG_STATUS_OK;
+}
+
+/* Dump MCP Trace */
+static enum dbg_status qed_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+					  struct ecore_ptt *p_ptt,
+					  u32 *dump_buf,
+					  bool dump, u32 *num_dumped_dwords)
+{
+	u32 trace_data_grc_addr, trace_data_size_bytes, trace_data_size_dwords;
+	u32 trace_meta_size_dwords = 0, running_bundle_id, offset = 0;
+	u32 trace_meta_offset_bytes = 0, trace_meta_size_bytes = 0;
+	enum dbg_status status;
+	int halted = 0;
+	bool use_mfw;
+
+	*num_dumped_dwords = 0;
+
+	use_mfw = !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP);
+
+	/* Get trace data info */
+	status = qed_mcp_trace_get_data_info(p_hwfn,
+					     p_ptt,
+					     &trace_data_grc_addr,
+					     &trace_data_size_bytes);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "mcp-trace");
+
+	/* Halt MCP while reading from scratchpad so the read data will be
+	 * consistent. if halt fails, MCP trace is taken anyway, with a small
+	 * risk that it may be corrupt.
+	 */
+	if (dump && use_mfw) {
+		halted = !ecore_mcp_halt(p_hwfn, p_ptt);
+		if (!halted)
+			DP_NOTICE(p_hwfn, false, "MCP halt failed!\n");
+	}
+
+	/* Find trace data size */
+	trace_data_size_dwords =
+	    DIV_ROUND_UP(trace_data_size_bytes + sizeof(struct mcp_trace),
+			 BYTES_IN_DWORD);
+
+	/* Dump trace data section header and param */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "mcp_trace_data", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", trace_data_size_dwords);
+
+	/* Read trace data from scratchpad into dump buffer */
+	offset += qed_grc_dump_addr_range(p_hwfn,
+					  p_ptt,
+					  dump_buf + offset,
+					  dump,
+					  BYTES_TO_DWORDS(trace_data_grc_addr),
+					  trace_data_size_dwords, false,
+					  SPLIT_TYPE_NONE, 0);
+
+	/* Resume MCP (only if halt succeeded) */
+	if (halted && ecore_mcp_resume(p_hwfn, p_ptt))
+		DP_NOTICE(p_hwfn, false, "Failed to resume MCP after halt!\n");
+
+	/* Dump trace meta section header */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "mcp_trace_meta", 1);
+
+	/* If MCP Trace meta size parameter was set, use it.
+	 * Otherwise, read trace meta.
+	 * trace_meta_size_bytes is dword-aligned.
+	 */
+	trace_meta_size_bytes =
+		qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_MCP_TRACE_META_SIZE);
+	if ((!trace_meta_size_bytes || dump) && use_mfw)
+		status = qed_mcp_trace_get_meta_info(p_hwfn,
+						     p_ptt,
+						     trace_data_size_bytes,
+						     &running_bundle_id,
+						     &trace_meta_offset_bytes,
+						     &trace_meta_size_bytes);
+	if (status == DBG_STATUS_OK)
+		trace_meta_size_dwords = BYTES_TO_DWORDS(trace_meta_size_bytes);
+
+	/* Dump trace meta size param */
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", trace_meta_size_dwords);
+
+	/* Read trace meta image into dump buffer */
+	if (dump && trace_meta_size_dwords)
+		status = qed_mcp_trace_read_meta(p_hwfn,
+						 p_ptt,
+						 trace_meta_offset_bytes,
+						 trace_meta_size_bytes,
+						 dump_buf + offset);
+	if (status == DBG_STATUS_OK)
+		offset += trace_meta_size_dwords;
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	/* If no mcp access, indicate that the dump doesn't contain the meta
+	 * data from NVRAM.
+	 */
+	return use_mfw ? status : DBG_STATUS_NVRAM_GET_IMAGE_FAILED;
+}
+
+/* Dump GRC FIFO */
+static enum dbg_status qed_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
+					 struct ecore_ptt *p_ptt,
+					 u32 *dump_buf,
+					 bool dump, u32 *num_dumped_dwords)
+{
+	u32 dwords_read, size_param_offset, offset = 0, addr, len;
+	bool fifo_has_data;
+
+	*num_dumped_dwords = 0;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "reg-fifo");
+
+	/* Dump fifo data section header and param. The size param is 0 for
+	 * now, and is overwritten after reading the FIFO.
+	 */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "reg_fifo_data", 1);
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+
+	if (!dump) {
+		/* FIFO max size is REG_FIFO_DEPTH_DWORDS. There is no way to
+		 * test how much data is available, except for reading it.
+		 */
+		offset += REG_FIFO_DEPTH_DWORDS;
+		goto out;
+	}
+
+	fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+			       GRC_REG_TRACE_FIFO_VALID_DATA) > 0;
+
+	/* Pull available data from fifo. Use DMAE since this is widebus memory
+	 * and must be accessed atomically. Test for dwords_read not passing
+	 * buffer size since more entries could be added to the buffer as we are
+	 * emptying it.
+	 */
+	addr = BYTES_TO_DWORDS(GRC_REG_TRACE_FIFO);
+	len = REG_FIFO_ELEMENT_DWORDS;
+	for (dwords_read = 0;
+	     fifo_has_data && dwords_read < REG_FIFO_DEPTH_DWORDS;
+	     dwords_read += REG_FIFO_ELEMENT_DWORDS) {
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  true,
+						  addr,
+						  len,
+						  true, SPLIT_TYPE_NONE,
+						  0);
+		fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+				       GRC_REG_TRACE_FIFO_VALID_DATA) > 0;
+	}
+
+	qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
+			   dwords_read);
+out:
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Dump IGU FIFO */
+static enum dbg_status qed_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
+					 struct ecore_ptt *p_ptt,
+					 u32 *dump_buf,
+					 bool dump, u32 *num_dumped_dwords)
+{
+	u32 dwords_read, size_param_offset, offset = 0, addr, len;
+	bool fifo_has_data;
+
+	*num_dumped_dwords = 0;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "igu-fifo");
+
+	/* Dump fifo data section header and param. The size param is 0 for
+	 * now, and is overwritten after reading the FIFO.
+	 */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "igu_fifo_data", 1);
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+
+	if (!dump) {
+		/* FIFO max size is IGU_FIFO_DEPTH_DWORDS. There is no way to
+		 * test how much data is available, except for reading it.
+		 */
+		offset += IGU_FIFO_DEPTH_DWORDS;
+		goto out;
+	}
+
+	fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+			       IGU_REG_ERROR_HANDLING_DATA_VALID) > 0;
+
+	/* Pull available data from fifo. Use DMAE since this is widebus memory
+	 * and must be accessed atomically. Test for dwords_read not passing
+	 * buffer size since more entries could be added to the buffer as we are
+	 * emptying it.
+	 */
+	addr = BYTES_TO_DWORDS(IGU_REG_ERROR_HANDLING_MEMORY);
+	len = IGU_FIFO_ELEMENT_DWORDS;
+	for (dwords_read = 0;
+	     fifo_has_data && dwords_read < IGU_FIFO_DEPTH_DWORDS;
+	     dwords_read += IGU_FIFO_ELEMENT_DWORDS) {
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  true,
+						  addr,
+						  len,
+						  true, SPLIT_TYPE_NONE,
+						  0);
+		fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+				       IGU_REG_ERROR_HANDLING_DATA_VALID) > 0;
+	}
+
+	qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
+			   dwords_read);
+out:
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Protection Override dump */
+static enum dbg_status qed_protection_override_dump(struct ecore_hwfn *p_hwfn,
+						    struct ecore_ptt *p_ptt,
+						    u32 *dump_buf,
+						    bool dump,
+						    u32 *num_dumped_dwords)
+{
+	u32 size_param_offset, override_window_dwords, offset = 0, addr;
+
+	*num_dumped_dwords = 0;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "protection-override");
+
+	/* Dump data section header and param. The size param is 0 for now,
+	 * and is overwritten after reading the data.
+	 */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "protection_override_data", 1);
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+
+	if (!dump) {
+		offset += PROTECTION_OVERRIDE_DEPTH_DWORDS;
+		goto out;
+	}
+
+	/* Add override window info to buffer */
+	override_window_dwords =
+		ecore_rd(p_hwfn, p_ptt, GRC_REG_NUMBER_VALID_OVERRIDE_WINDOW) *
+		PROTECTION_OVERRIDE_ELEMENT_DWORDS;
+	if (override_window_dwords) {
+		addr = BYTES_TO_DWORDS(GRC_REG_PROTECTION_OVERRIDE_WINDOW);
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  true,
+						  addr,
+						  override_window_dwords,
+						  true, SPLIT_TYPE_NONE, 0);
+		qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
+				   override_window_dwords);
+	}
+out:
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Performs FW Asserts Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
+			       struct ecore_ptt *p_ptt, u32 *dump_buf,
+			       bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	struct fw_asserts_ram_section *asserts;
+	char storm_letter_str[2] = "?";
+	struct fw_info fw_info;
+	u32 offset = 0;
+	u8 storm_id;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "fw-asserts");
+
+	/* Find Storm dump size */
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		u32 fw_asserts_section_addr, next_list_idx_addr, next_list_idx;
+		struct storm_defs *storm = &s_storm_defs[storm_id];
+		u32 last_list_idx, addr;
+
+		if (dev_data->block_in_reset[storm->sem_block_id])
+			continue;
+
+		/* Read FW info for the current Storm */
+		qed_read_storm_fw_info(p_hwfn, p_ptt, storm_id, &fw_info);
+
+		asserts = &fw_info.fw_asserts_section;
+
+		/* Dump FW Asserts section header and params */
+		storm_letter_str[0] = storm->letter;
+		offset += qed_dump_section_hdr(dump_buf + offset,
+					       dump, "fw_asserts", 2);
+		offset += qed_dump_str_param(dump_buf + offset,
+					     dump, "storm", storm_letter_str);
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump,
+					     "size",
+					     asserts->list_element_dword_size);
+
+		/* Read and dump FW Asserts data */
+		if (!dump) {
+			offset += asserts->list_element_dword_size;
+			continue;
+		}
+
+		fw_asserts_section_addr = storm->sem_fast_mem_addr +
+			SEM_FAST_REG_INT_RAM +
+			RAM_LINES_TO_BYTES(asserts->section_ram_line_offset);
+		next_list_idx_addr = fw_asserts_section_addr +
+			DWORDS_TO_BYTES(asserts->list_next_index_dword_offset);
+		next_list_idx = ecore_rd(p_hwfn, p_ptt, next_list_idx_addr);
+		last_list_idx = (next_list_idx > 0 ?
+				 next_list_idx :
+				 asserts->list_num_elements) - 1;
+		addr = BYTES_TO_DWORDS(fw_asserts_section_addr) +
+		       asserts->list_dword_offset +
+		       last_list_idx * asserts->list_element_dword_size;
+		offset +=
+		    qed_grc_dump_addr_range(p_hwfn, p_ptt,
+					    dump_buf + offset,
+					    dump, addr,
+					    asserts->list_element_dword_size,
+						  false, SPLIT_TYPE_NONE, 0);
+	}
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	return offset;
+}
+
+/* Dumps the specified ILT pages to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_ilt_dump_pages_range(u32 *dump_buf,
+				    bool dump,
+				    u32 start_page_id,
+				    u32 num_pages,
+				    struct phys_mem_desc *ilt_pages,
+				    bool dump_page_ids)
+{
+	u32 page_id, end_page_id, offset = 0;
+
+	if (num_pages == 0)
+		return offset;
+
+	end_page_id = start_page_id + num_pages - 1;
+
+	for (page_id = start_page_id; page_id <= end_page_id; page_id++) {
+		struct phys_mem_desc *mem_desc = &ilt_pages[page_id];
+
+		/**
+		 *
+		 * if (page_id >= ->p_cxt_mngr->ilt_shadow_size)
+		 *     break;
+		 */
+
+		if (!ilt_pages[page_id].virt_addr)
+			continue;
+
+		if (dump_page_ids) {
+			/* Copy page ID to dump buffer */
+			if (dump)
+				*(dump_buf + offset) = page_id;
+			offset++;
+		} else {
+			/* Copy page memory to dump buffer */
+			if (dump)
+				memcpy(dump_buf + offset,
+				       mem_desc->virt_addr, mem_desc->size);
+			offset += BYTES_TO_DWORDS(mem_desc->size);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps a section containing the dumped ILT pages.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_ilt_dump_pages_section(struct ecore_hwfn *p_hwfn,
+				      u32 *dump_buf,
+				      bool dump,
+				      u32 valid_conn_pf_pages,
+				      u32 valid_conn_vf_pages,
+				      struct phys_mem_desc *ilt_pages,
+				      bool dump_page_ids)
+{
+	struct ecore_ilt_client_cfg *clients = p_hwfn->p_cxt_mngr->clients;
+	u32 pf_start_line, start_page_id, offset = 0;
+	u32 cdut_pf_init_pages, cdut_vf_init_pages;
+	u32 cdut_pf_work_pages, cdut_vf_work_pages;
+	u32 base_data_offset, size_param_offset;
+	u32 cdut_pf_pages, cdut_vf_pages;
+	const char *section_name;
+	u8 i;
+
+	section_name = dump_page_ids ? "ilt_page_ids" : "ilt_page_mem";
+	cdut_pf_init_pages = ecore_get_cdut_num_pf_init_pages(p_hwfn);
+	cdut_vf_init_pages = ecore_get_cdut_num_vf_init_pages(p_hwfn);
+	cdut_pf_work_pages = ecore_get_cdut_num_pf_work_pages(p_hwfn);
+	cdut_vf_work_pages = ecore_get_cdut_num_vf_work_pages(p_hwfn);
+	cdut_pf_pages = cdut_pf_init_pages + cdut_pf_work_pages;
+	cdut_vf_pages = cdut_vf_init_pages + cdut_vf_work_pages;
+	pf_start_line = p_hwfn->p_cxt_mngr->pf_start_line;
+
+	offset +=
+	    qed_dump_section_hdr(dump_buf + offset, dump, section_name, 1);
+
+	/* Dump size parameter (0 for now, overwritten with real size later) */
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+	base_data_offset = offset;
+
+	/* CDUC pages are ordered as follows:
+	 * - PF pages - valid section (included in PF connection type mapping)
+	 * - PF pages - invalid section (not dumped)
+	 * - For each VF in the PF:
+	 *   - VF pages - valid section (included in VF connection type mapping)
+	 *   - VF pages - invalid section (not dumped)
+	 */
+	if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_DUMP_ILT_CDUC)) {
+		/* Dump connection PF pages */
+		start_page_id = clients[ILT_CLI_CDUC].first.val - pf_start_line;
+		offset += qed_ilt_dump_pages_range(dump_buf + offset,
+						   dump,
+						   start_page_id,
+						   valid_conn_pf_pages,
+						   ilt_pages, dump_page_ids);
+
+		/* Dump connection VF pages */
+		start_page_id += clients[ILT_CLI_CDUC].pf_total_lines;
+		for (i = 0; i < p_hwfn->p_cxt_mngr->vf_count;
+		     i++, start_page_id += clients[ILT_CLI_CDUC].vf_total_lines)
+			offset += qed_ilt_dump_pages_range(dump_buf + offset,
+							   dump,
+							   start_page_id,
+							   valid_conn_vf_pages,
+							   ilt_pages,
+							   dump_page_ids);
+	}
+
+	/* CDUT pages are ordered as follows:
+	 * - PF init pages (not dumped)
+	 * - PF work pages
+	 * - For each VF in the PF:
+	 *   - VF init pages (not dumped)
+	 *   - VF work pages
+	 */
+	if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_DUMP_ILT_CDUT)) {
+		/* Dump task PF pages */
+		start_page_id = clients[ILT_CLI_CDUT].first.val +
+		    cdut_pf_init_pages - pf_start_line;
+		offset += qed_ilt_dump_pages_range(dump_buf + offset,
+						   dump,
+						   start_page_id,
+						   cdut_pf_work_pages,
+						   ilt_pages, dump_page_ids);
+
+		/* Dump task VF pages */
+		start_page_id = clients[ILT_CLI_CDUT].first.val +
+		    cdut_pf_pages + cdut_vf_init_pages - pf_start_line;
+		for (i = 0; i < p_hwfn->p_cxt_mngr->vf_count;
+		     i++, start_page_id += cdut_vf_pages)
+			offset += qed_ilt_dump_pages_range(dump_buf + offset,
+							   dump,
+							   start_page_id,
+							   cdut_vf_work_pages,
+							   ilt_pages,
+							   dump_page_ids);
+	}
+
+	/* Overwrite size param */
+	if (dump)
+		qed_dump_num_param(dump_buf + size_param_offset,
+				   dump, "size", offset - base_data_offset);
+
+	return offset;
+}
+
+/* Performs ILT Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_ilt_dump(struct ecore_hwfn *p_hwfn,
+			struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	struct ecore_ilt_client_cfg *clients = p_hwfn->p_cxt_mngr->clients;
+	u32 valid_conn_vf_cids, valid_conn_vf_pages, offset = 0;
+	u32 valid_conn_pf_cids, valid_conn_pf_pages, num_pages;
+	u32 num_cids_per_page, conn_ctx_size;
+	u32 cduc_page_size, cdut_page_size;
+	struct phys_mem_desc *ilt_pages;
+	u8 conn_type;
+
+	cduc_page_size = 1 <<
+	    (clients[ILT_CLI_CDUC].p_size.val + PXP_ILT_PAGE_SIZE_NUM_BITS_MIN);
+	cdut_page_size = 1 <<
+	    (clients[ILT_CLI_CDUT].p_size.val + PXP_ILT_PAGE_SIZE_NUM_BITS_MIN);
+	conn_ctx_size = p_hwfn->p_cxt_mngr->conn_ctx_size;
+	num_cids_per_page = (int)(cduc_page_size / conn_ctx_size);
+	ilt_pages = p_hwfn->p_cxt_mngr->ilt_shadow;
+
+	/* Dump global params - 22 must match number of params below */
+	offset += qed_dump_common_global_params(p_hwfn, p_ptt,
+						dump_buf + offset, dump, 22);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "ilt-dump");
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-page-size", cduc_page_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-first-page-id",
+				     clients[ILT_CLI_CDUC].first.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-last-page-id",
+				     clients[ILT_CLI_CDUC].last.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-num-pf-pages",
+				     clients
+				     [ILT_CLI_CDUC].pf_total_lines);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-num-vf-pages",
+				     clients
+				     [ILT_CLI_CDUC].vf_total_lines);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "max-conn-ctx-size",
+				     conn_ctx_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-page-size", cdut_page_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-first-page-id",
+				     clients[ILT_CLI_CDUT].first.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-last-page-id",
+				     clients[ILT_CLI_CDUT].last.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-pf-init-pages",
+				     ecore_get_cdut_num_pf_init_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-vf-init-pages",
+				     ecore_get_cdut_num_vf_init_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-pf-work-pages",
+				     ecore_get_cdut_num_pf_work_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-vf-work-pages",
+				     ecore_get_cdut_num_vf_work_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "max-task-ctx-size",
+				     p_hwfn->p_cxt_mngr->task_ctx_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "task-type-id",
+				     p_hwfn->p_cxt_mngr->task_type_id);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "first-vf-id-in-pf",
+				     p_hwfn->p_cxt_mngr->first_vf_in_pf);
+	offset += /* 18 */ qed_dump_num_param(dump_buf + offset,
+					      dump,
+					      "num-vfs-in-pf",
+					      p_hwfn->p_cxt_mngr->vf_count);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "ptr-size-bytes", sizeof(void *));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "pf-start-line",
+				     p_hwfn->p_cxt_mngr->pf_start_line);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "page-mem-desc-size-dwords",
+				     PAGE_MEM_DESC_SIZE_DWORDS);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "ilt-shadow-size",
+				     p_hwfn->p_cxt_mngr->ilt_shadow_size);
+	/* Additional/Less parameters require matching of number in call to
+	 * dump_common_global_params()
+	 */
+
+	/* Dump section containing number of PF CIDs per connection type */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "num_pf_cids_per_conn_type", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", NUM_OF_CONNECTION_TYPES);
+	for (conn_type = 0, valid_conn_pf_cids = 0;
+	     conn_type < NUM_OF_CONNECTION_TYPES; conn_type++, offset++) {
+		u32 num_pf_cids =
+		    p_hwfn->p_cxt_mngr->conn_cfg[conn_type].cid_count;
+
+		if (dump)
+			*(dump_buf + offset) = num_pf_cids;
+		valid_conn_pf_cids += num_pf_cids;
+	}
+
+	/* Dump section containing number of VF CIDs per connection type */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "num_vf_cids_per_conn_type", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", NUM_OF_CONNECTION_TYPES);
+	for (conn_type = 0, valid_conn_vf_cids = 0;
+	     conn_type < NUM_OF_CONNECTION_TYPES; conn_type++, offset++) {
+		u32 num_vf_cids =
+		    p_hwfn->p_cxt_mngr->conn_cfg[conn_type].cids_per_vf;
+
+		if (dump)
+			*(dump_buf + offset) = num_vf_cids;
+		valid_conn_vf_cids += num_vf_cids;
+	}
+
+	/* Dump section containing physical memory descs for each ILT page */
+	num_pages = p_hwfn->p_cxt_mngr->ilt_shadow_size;
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "ilt_page_desc", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "size",
+				     num_pages * PAGE_MEM_DESC_SIZE_DWORDS);
+
+	/* Copy memory descriptors to dump buffer */
+	if (dump) {
+		u32 page_id;
+
+		for (page_id = 0; page_id < num_pages;
+		     page_id++, offset += PAGE_MEM_DESC_SIZE_DWORDS)
+			memcpy(dump_buf + offset,
+			       &ilt_pages[page_id],
+			       DWORDS_TO_BYTES(PAGE_MEM_DESC_SIZE_DWORDS));
+	} else {
+		offset += num_pages * PAGE_MEM_DESC_SIZE_DWORDS;
+	}
+
+	valid_conn_pf_pages = DIV_ROUND_UP(valid_conn_pf_cids,
+					   num_cids_per_page);
+	valid_conn_vf_pages = DIV_ROUND_UP(valid_conn_vf_cids,
+					   num_cids_per_page);
+
+	/* Dump ILT pages IDs */
+	offset += qed_ilt_dump_pages_section(p_hwfn,
+					     dump_buf + offset,
+					     dump,
+					     valid_conn_pf_pages,
+					     valid_conn_vf_pages,
+					     ilt_pages, true);
+
+	/* Dump ILT pages memory */
+	offset += qed_ilt_dump_pages_section(p_hwfn,
+					     dump_buf + offset,
+					     dump,
+					     valid_conn_pf_pages,
+					     valid_conn_vf_pages,
+					     ilt_pages, false);
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	return offset;
+}
+
+/***************************** Public Functions *******************************/
+
+enum dbg_status qed_dbg_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+				    const u8 * const bin_ptr)
+{
+	struct bin_buffer_hdr *buf_hdrs =
+			(struct bin_buffer_hdr *)(osal_uintptr_t)bin_ptr;
+	u8 buf_id;
+
+	/* Convert binary data to debug arrays */
+	for (buf_id = 0; buf_id < MAX_BIN_DBG_BUFFER_TYPE; buf_id++)
+		qed_set_dbg_bin_buf(p_hwfn,
+				    buf_id,
+				    (const u32 *)(bin_ptr +
+						  buf_hdrs[buf_id].offset),
+						  buf_hdrs[buf_id].length);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_set_app_ver(u32 ver)
+{
+	if (ver < TOOLS_VERSION)
+		return DBG_STATUS_UNSUPPORTED_APP_VERSION;
+
+	s_app_ver = ver;
+
+	return DBG_STATUS_OK;
+}
+
+bool qed_read_fw_info(struct ecore_hwfn *p_hwfn,
+		      struct ecore_ptt *p_ptt, struct fw_info *fw_info)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		struct storm_defs *storm = &s_storm_defs[storm_id];
+
+		/* Skip Storm if it's in reset */
+		if (dev_data->block_in_reset[storm->sem_block_id])
+			continue;
+
+		/* Read FW info for the current Storm */
+		qed_read_storm_fw_info(p_hwfn, p_ptt, storm_id, fw_info);
+
+		return true;
+	}
+
+	return false;
+}
+
+enum dbg_status qed_dbg_grc_config(struct ecore_hwfn *p_hwfn,
+				   enum dbg_grc_params grc_param, u32 val)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	enum dbg_status status;
+	int i;
+
+	DP_VERBOSE(p_hwfn->p_dev,
+		   ECORE_MSG_DEBUG,
+		   "dbg_grc_config: paramId = %d, val = %d\n", grc_param, val);
+
+	status = qed_dbg_dev_init(p_hwfn);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Initializes the GRC parameters (if not initialized). Needed in order
+	 * to set the default parameter values for the first time.
+	 */
+	qed_dbg_grc_init_params(p_hwfn);
+
+	if (grc_param >= MAX_DBG_GRC_PARAMS)
+		return DBG_STATUS_INVALID_ARGS;
+	if (val < s_grc_param_defs[grc_param].min ||
+	    val > s_grc_param_defs[grc_param].max)
+		return DBG_STATUS_INVALID_ARGS;
+
+	if (s_grc_param_defs[grc_param].is_preset) {
+		/* Preset param */
+
+		/* Disabling a preset is not allowed. Call
+		 * dbg_grc_set_params_default instead.
+		 */
+		if (!val)
+			return DBG_STATUS_INVALID_ARGS;
+
+		/* Update all params with the preset values */
+		for (i = 0; i < MAX_DBG_GRC_PARAMS; i++) {
+			struct grc_param_defs *defs = &s_grc_param_defs[i];
+			u32 preset_val;
+			/* Skip persistent params */
+			if (defs->is_persistent)
+				continue;
+
+			/* Find preset value */
+			if (grc_param == DBG_GRC_PARAM_EXCLUDE_ALL)
+				preset_val =
+				    defs->exclude_all_preset_val;
+			else if (grc_param == DBG_GRC_PARAM_CRASH)
+				preset_val =
+				    defs->crash_preset_val[dev_data->chip_id];
+			else
+				return DBG_STATUS_INVALID_ARGS;
+
+			qed_grc_set_param(p_hwfn, i, preset_val);
+		}
+	} else {
+		/* Regular param - set its value */
+		qed_grc_set_param(p_hwfn, grc_param, val);
+	}
+
+	return DBG_STATUS_OK;
+}
+
+/* Assign default GRC param values */
+void qed_dbg_grc_set_params_default(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 i;
+
+	for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
+		if (!s_grc_param_defs[i].is_persistent)
+			dev_data->grc.param_val[i] =
+			    s_grc_param_defs[i].default_val[dev_data->chip_id];
+}
+
+enum dbg_status qed_dbg_grc_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_MEM].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	return qed_grc_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_grc_dump(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf,
+				 u32 buf_size_in_dwords,
+				 u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_grc_get_dump_buf_size(p_hwfn,
+					       p_ptt,
+					       &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* GRC Dump */
+	status = qed_grc_dump(p_hwfn, p_ptt, dump_buf, true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_idle_chk_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	struct idle_chk_data *idle_chk = &dev_data->idle_chk;
+	enum dbg_status status;
+
+	*buf_size = 0;
+
+	status = qed_dbg_dev_init(p_hwfn);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_IMMS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_RULES].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	if (!idle_chk->buf_size_set) {
+		idle_chk->buf_size = qed_idle_chk_dump(p_hwfn,
+						       p_ptt, NULL, false);
+		idle_chk->buf_size_set = true;
+	}
+
+	*buf_size = idle_chk->buf_size;
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_idle_chk_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_grc_unreset_blocks(p_hwfn, p_ptt, true);
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	/* Idle Check Dump */
+	*num_dumped_dwords = qed_idle_chk_dump(p_hwfn, p_ptt, dump_buf, true);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_mcp_trace_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						    struct ecore_ptt *p_ptt,
+						    u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_mcp_trace_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+				       struct ecore_ptt *p_ptt,
+				       u32 *dump_buf,
+				       u32 buf_size_in_dwords,
+				       u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	status =
+		qed_dbg_mcp_trace_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK && status !=
+	    DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
+		return status;
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	/* Perform dump */
+	status = qed_mcp_trace_dump(p_hwfn,
+				    p_ptt, dump_buf, true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_reg_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_reg_fifo_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_reg_fifo_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	status = qed_reg_fifo_dump(p_hwfn,
+				   p_ptt, dump_buf, true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_igu_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_igu_fifo_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_igu_fifo_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	status = qed_igu_fifo_dump(p_hwfn,
+				   p_ptt, dump_buf, true, num_dumped_dwords);
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status
+qed_dbg_protection_override_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_protection_override_dump(p_hwfn,
+					    p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_protection_override_dump(struct ecore_hwfn *p_hwfn,
+						 struct ecore_ptt *p_ptt,
+						 u32 *dump_buf,
+						 u32 buf_size_in_dwords,
+						 u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords, *p_size = &needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status =
+		qed_dbg_protection_override_get_dump_buf_size(p_hwfn,
+							      p_ptt,
+							      p_size);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	status = qed_protection_override_dump(p_hwfn,
+					      p_ptt,
+					      dump_buf,
+					      true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_fw_asserts_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						     struct ecore_ptt *p_ptt,
+						     u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	*buf_size = qed_fw_asserts_dump(p_hwfn, p_ptt, NULL, false);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf,
+					u32 buf_size_in_dwords,
+					u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords, *p_size = &needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status =
+		qed_dbg_fw_asserts_get_dump_buf_size(p_hwfn,
+						     p_ptt,
+						     p_size);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	*num_dumped_dwords = qed_fw_asserts_dump(p_hwfn, p_ptt, dump_buf, true);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status qed_dbg_ilt_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						     struct ecore_ptt *p_ptt,
+						     u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	*buf_size = qed_ilt_dump(p_hwfn, p_ptt, NULL, false);
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status qed_dbg_ilt_dump(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf,
+					u32 buf_size_in_dwords,
+					u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_ilt_get_dump_buf_size(p_hwfn,
+					       p_ptt,
+					       &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	*num_dumped_dwords = qed_ilt_dump(p_hwfn, p_ptt, dump_buf, true);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_read_attn(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  enum block_id block_id,
+				  enum dbg_attn_type attn_type,
+				  bool clear_status,
+				  struct dbg_attn_block_result *results)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+	u8 reg_idx, num_attn_regs, num_result_regs = 0;
+	const struct dbg_attn_reg *attn_reg_arr;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
+					       block_id,
+					       attn_type, &num_attn_regs);
+
+	for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
+		const struct dbg_attn_reg *reg_data = &attn_reg_arr[reg_idx];
+		struct dbg_attn_reg_result *reg_result;
+		u32 sts_addr, sts_val;
+		u16 modes_buf_offset;
+		bool eval_mode;
+
+		/* Check mode */
+		eval_mode = GET_FIELD(reg_data->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		modes_buf_offset = GET_FIELD(reg_data->mode.data,
+					     DBG_MODE_HDR_MODES_BUF_OFFSET);
+		if (eval_mode && !qed_is_mode_match(p_hwfn, &modes_buf_offset))
+			continue;
+
+		/* Mode match - read attention status register */
+		sts_addr = DWORDS_TO_BYTES(clear_status ?
+					   reg_data->sts_clr_address :
+					   GET_FIELD(reg_data->data,
+						     DBG_ATTN_REG_STS_ADDRESS));
+		sts_val = ecore_rd(p_hwfn, p_ptt, sts_addr);
+		if (!sts_val)
+			continue;
+
+		/* Non-zero attention status - add to results */
+		reg_result = &results->reg_results[num_result_regs];
+		SET_FIELD(reg_result->data,
+			  DBG_ATTN_REG_RESULT_STS_ADDRESS, sts_addr);
+		SET_FIELD(reg_result->data,
+			  DBG_ATTN_REG_RESULT_NUM_REG_ATTN,
+			  GET_FIELD(reg_data->data, DBG_ATTN_REG_NUM_REG_ATTN));
+		reg_result->block_attn_offset = reg_data->block_attn_offset;
+		reg_result->sts_val = sts_val;
+		reg_result->mask_val = ecore_rd(p_hwfn,
+					      p_ptt,
+					      DWORDS_TO_BYTES
+					      (reg_data->mask_address));
+		num_result_regs++;
+	}
+
+	results->block_id = (u8)block_id;
+	results->names_offset =
+	    qed_get_block_attn_data(p_hwfn, block_id, attn_type)->names_offset;
+	SET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_ATTN_TYPE, attn_type);
+	SET_FIELD(results->data,
+		  DBG_ATTN_BLOCK_RESULT_NUM_REGS, num_result_regs);
+
+	return DBG_STATUS_OK;
+}
+
+/******************************* Data Types **********************************/
+
+/* REG fifo element */
+struct reg_fifo_element {
+	u64 data;
+#define REG_FIFO_ELEMENT_ADDRESS_SHIFT		0
+#define REG_FIFO_ELEMENT_ADDRESS_MASK		0x7fffff
+#define REG_FIFO_ELEMENT_ACCESS_SHIFT		23
+#define REG_FIFO_ELEMENT_ACCESS_MASK		0x1
+#define REG_FIFO_ELEMENT_PF_SHIFT		24
+#define REG_FIFO_ELEMENT_PF_MASK		0xf
+#define REG_FIFO_ELEMENT_VF_SHIFT		28
+#define REG_FIFO_ELEMENT_VF_MASK		0xff
+#define REG_FIFO_ELEMENT_PORT_SHIFT		36
+#define REG_FIFO_ELEMENT_PORT_MASK		0x3
+#define REG_FIFO_ELEMENT_PRIVILEGE_SHIFT	38
+#define REG_FIFO_ELEMENT_PRIVILEGE_MASK		0x3
+#define REG_FIFO_ELEMENT_PROTECTION_SHIFT	40
+#define REG_FIFO_ELEMENT_PROTECTION_MASK	0x7
+#define REG_FIFO_ELEMENT_MASTER_SHIFT		43
+#define REG_FIFO_ELEMENT_MASTER_MASK		0xf
+#define REG_FIFO_ELEMENT_ERROR_SHIFT		47
+#define REG_FIFO_ELEMENT_ERROR_MASK		0x1f
+};
+
+/* REG fifo error element */
+struct reg_fifo_err {
+	u32 err_code;
+	const char *err_msg;
+};
+
+/* IGU fifo element */
+struct igu_fifo_element {
+	u32 dword0;
+#define IGU_FIFO_ELEMENT_DWORD0_FID_SHIFT		0
+#define IGU_FIFO_ELEMENT_DWORD0_FID_MASK		0xff
+#define IGU_FIFO_ELEMENT_DWORD0_IS_PF_SHIFT		8
+#define IGU_FIFO_ELEMENT_DWORD0_IS_PF_MASK		0x1
+#define IGU_FIFO_ELEMENT_DWORD0_SOURCE_SHIFT		9
+#define IGU_FIFO_ELEMENT_DWORD0_SOURCE_MASK		0xf
+#define IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE_SHIFT		13
+#define IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE_MASK		0xf
+#define IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR_SHIFT		17
+#define IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR_MASK		0x7fff
+	u32 dword1;
+	u32 dword2;
+#define IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD_SHIFT	0
+#define IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD_MASK		0x1
+#define IGU_FIFO_ELEMENT_DWORD12_WR_DATA_SHIFT		1
+#define IGU_FIFO_ELEMENT_DWORD12_WR_DATA_MASK		0xffffffff
+	u32 reserved;
+};
+
+struct igu_fifo_wr_data {
+	u32 data;
+#define IGU_FIFO_WR_DATA_PROD_CONS_SHIFT		0
+#define IGU_FIFO_WR_DATA_PROD_CONS_MASK			0xffffff
+#define IGU_FIFO_WR_DATA_UPDATE_FLAG_SHIFT		24
+#define IGU_FIFO_WR_DATA_UPDATE_FLAG_MASK		0x1
+#define IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB_SHIFT	25
+#define IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB_MASK		0x3
+#define IGU_FIFO_WR_DATA_SEGMENT_SHIFT			27
+#define IGU_FIFO_WR_DATA_SEGMENT_MASK			0x1
+#define IGU_FIFO_WR_DATA_TIMER_MASK_SHIFT		28
+#define IGU_FIFO_WR_DATA_TIMER_MASK_MASK		0x1
+#define IGU_FIFO_WR_DATA_CMD_TYPE_SHIFT			31
+#define IGU_FIFO_WR_DATA_CMD_TYPE_MASK			0x1
+};
+
+struct igu_fifo_cleanup_wr_data {
+	u32 data;
+#define IGU_FIFO_CLEANUP_WR_DATA_RESERVED_SHIFT		0
+#define IGU_FIFO_CLEANUP_WR_DATA_RESERVED_MASK		0x7ffffff
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL_SHIFT	27
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL_MASK	0x1
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE_SHIFT	28
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE_MASK	0x7
+#define IGU_FIFO_CLEANUP_WR_DATA_CMD_TYPE_SHIFT		31
+#define IGU_FIFO_CLEANUP_WR_DATA_CMD_TYPE_MASK		0x1
+};
+
+/* Protection override element */
+struct protection_override_element {
+	u64 data;
+#define PROTECTION_OVERRIDE_ELEMENT_ADDRESS_SHIFT		0
+#define PROTECTION_OVERRIDE_ELEMENT_ADDRESS_MASK		0x7fffff
+#define PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE_SHIFT		23
+#define PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE_MASK		0xffffff
+#define PROTECTION_OVERRIDE_ELEMENT_READ_SHIFT			47
+#define PROTECTION_OVERRIDE_ELEMENT_READ_MASK			0x1
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_SHIFT			48
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_MASK			0x1
+#define PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION_SHIFT	49
+#define PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION_MASK	0x7
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION_SHIFT	52
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION_MASK	0x7
+};
+
+enum igu_fifo_sources {
+	IGU_SRC_PXP0,
+	IGU_SRC_PXP1,
+	IGU_SRC_PXP2,
+	IGU_SRC_PXP3,
+	IGU_SRC_PXP4,
+	IGU_SRC_PXP5,
+	IGU_SRC_PXP6,
+	IGU_SRC_PXP7,
+	IGU_SRC_CAU,
+	IGU_SRC_ATTN,
+	IGU_SRC_GRC
+};
+
+enum igu_fifo_addr_types {
+	IGU_ADDR_TYPE_MSIX_MEM,
+	IGU_ADDR_TYPE_WRITE_PBA,
+	IGU_ADDR_TYPE_WRITE_INT_ACK,
+	IGU_ADDR_TYPE_WRITE_ATTN_BITS,
+	IGU_ADDR_TYPE_READ_INT,
+	IGU_ADDR_TYPE_WRITE_PROD_UPDATE,
+	IGU_ADDR_TYPE_RESERVED
+};
+
+struct igu_fifo_addr_data {
+	u16 start_addr;
+	u16 end_addr;
+	const char *desc;
+	const char *vf_desc;
+	enum igu_fifo_addr_types type;
+};
+
+/******************************** Constants **********************************/
+
+#define MAX_MSG_LEN				1024
+
+#define MCP_TRACE_MAX_MODULE_LEN		8
+#define MCP_TRACE_FORMAT_MAX_PARAMS		3
+#define MCP_TRACE_FORMAT_PARAM_WIDTH \
+	(MCP_TRACE_FORMAT_P2_SIZE_OFFSET - MCP_TRACE_FORMAT_P1_SIZE_OFFSET)
+
+#define REG_FIFO_ELEMENT_ADDR_FACTOR		4
+#define REG_FIFO_ELEMENT_IS_PF_VF_VAL		127
+
+#define PROTECTION_OVERRIDE_ELEMENT_ADDR_FACTOR	4
+
+/***************************** Constant Arrays *******************************/
+
+/* Status string array */
+static const char * const s_status_str[] = {
+	/* DBG_STATUS_OK */
+	"Operation completed successfully",
+
+	/* DBG_STATUS_APP_VERSION_NOT_SET */
+	"Debug application version wasn't set",
+
+	/* DBG_STATUS_UNSUPPORTED_APP_VERSION */
+	"Unsupported debug application version",
+
+	/* DBG_STATUS_DBG_BLOCK_NOT_RESET */
+	"The debug block wasn't reset since the last recording",
+
+	/* DBG_STATUS_INVALID_ARGS */
+	"Invalid arguments",
+
+	/* DBG_STATUS_OUTPUT_ALREADY_SET */
+	"The debug output was already set",
+
+	/* DBG_STATUS_INVALID_PCI_BUF_SIZE */
+	"Invalid PCI buffer size",
+
+	/* DBG_STATUS_PCI_BUF_ALLOC_FAILED */
+	"PCI buffer allocation failed",
+
+	/* DBG_STATUS_PCI_BUF_NOT_ALLOCATED */
+	"A PCI buffer wasn't allocated",
+
+	/* DBG_STATUS_INVALID_FILTER_TRIGGER_DWORDS */
+	"The filter/trigger constraint dword offsets are not enabled for recording",
+
+
+	/* DBG_STATUS_VFC_READ_ERROR */
+	"Error reading from VFC",
+
+	/* DBG_STATUS_STORM_ALREADY_ENABLED */
+	"The Storm was already enabled",
+
+	/* DBG_STATUS_STORM_NOT_ENABLED */
+	"The specified Storm wasn't enabled",
+
+	/* DBG_STATUS_BLOCK_ALREADY_ENABLED */
+	"The block was already enabled",
+
+	/* DBG_STATUS_BLOCK_NOT_ENABLED */
+	"The specified block wasn't enabled",
+
+	/* DBG_STATUS_NO_INPUT_ENABLED */
+	"No input was enabled for recording",
+
+	/* DBG_STATUS_NO_FILTER_TRIGGER_256B */
+	"Filters and triggers are not allowed in E4 256-bit mode",
+
+	/* DBG_STATUS_FILTER_ALREADY_ENABLED */
+	"The filter was already enabled",
+
+	/* DBG_STATUS_TRIGGER_ALREADY_ENABLED */
+	"The trigger was already enabled",
+
+	/* DBG_STATUS_TRIGGER_NOT_ENABLED */
+	"The trigger wasn't enabled",
+
+	/* DBG_STATUS_CANT_ADD_CONSTRAINT */
+	"A constraint can be added only after a filter was enabled or a trigger state was added",
+
+	/* DBG_STATUS_TOO_MANY_TRIGGER_STATES */
+	"Cannot add more than 3 trigger states",
+
+	/* DBG_STATUS_TOO_MANY_CONSTRAINTS */
+	"Cannot add more than 4 constraints per filter or trigger state",
+
+	/* DBG_STATUS_RECORDING_NOT_STARTED */
+	"The recording wasn't started",
+
+	/* DBG_STATUS_DATA_DID_NOT_TRIGGER */
+	"A trigger was configured, but it didn't trigger",
+
+	/* DBG_STATUS_NO_DATA_RECORDED */
+	"No data was recorded",
+
+	/* DBG_STATUS_DUMP_BUF_TOO_SMALL */
+	"Dump buffer is too small",
+
+	/* DBG_STATUS_DUMP_NOT_CHUNK_ALIGNED */
+	"Dumped data is not aligned to chunks",
+
+	/* DBG_STATUS_UNKNOWN_CHIP */
+	"Unknown chip",
+
+	/* DBG_STATUS_VIRT_MEM_ALLOC_FAILED */
+	"Failed allocating virtual memory",
+
+	/* DBG_STATUS_BLOCK_IN_RESET */
+	"The input block is in reset",
+
+	/* DBG_STATUS_INVALID_TRACE_SIGNATURE */
+	"Invalid MCP trace signature found in NVRAM",
+
+	/* DBG_STATUS_INVALID_NVRAM_BUNDLE */
+	"Invalid bundle ID found in NVRAM",
+
+	/* DBG_STATUS_NVRAM_GET_IMAGE_FAILED */
+	"Failed getting NVRAM image",
+
+	/* DBG_STATUS_NON_ALIGNED_NVRAM_IMAGE */
+	"NVRAM image is not dword-aligned",
+
+	/* DBG_STATUS_NVRAM_READ_FAILED */
+	"Failed reading from NVRAM",
+
+	/* DBG_STATUS_IDLE_CHK_PARSE_FAILED */
+	"Idle check parsing failed",
+
+	/* DBG_STATUS_MCP_TRACE_BAD_DATA */
+	"MCP Trace data is corrupt",
+
+	/* DBG_STATUS_MCP_TRACE_NO_META */
+	"Dump doesn't contain meta data - it must be provided in image file",
+
+	/* DBG_STATUS_MCP_COULD_NOT_HALT */
+	"Failed to halt MCP",
+
+	/* DBG_STATUS_MCP_COULD_NOT_RESUME */
+	"Failed to resume MCP after halt",
+
+	/* DBG_STATUS_RESERVED0 */
+	"",
+
+	/* DBG_STATUS_SEMI_FIFO_NOT_EMPTY */
+	"Failed to empty SEMI sync FIFO",
+
+	/* DBG_STATUS_IGU_FIFO_BAD_DATA */
+	"IGU FIFO data is corrupt",
+
+	/* DBG_STATUS_MCP_COULD_NOT_MASK_PRTY */
+	"MCP failed to mask parities",
+
+	/* DBG_STATUS_FW_ASSERTS_PARSE_FAILED */
+	"FW Asserts parsing failed",
+
+	/* DBG_STATUS_REG_FIFO_BAD_DATA */
+	"GRC FIFO data is corrupt",
+
+	/* DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA */
+	"Protection Override data is corrupt",
+
+	/* DBG_STATUS_DBG_ARRAY_NOT_SET */
+	"Debug arrays were not set (when using binary files, dbg_set_bin_ptr must be called)",
+
+	/* DBG_STATUS_RESERVED1 */
+	"",
+
+	/* DBG_STATUS_NON_MATCHING_LINES */
+	"Non-matching debug lines - in E4, all lines must be of the same type (either 128b or 256b)",
+
+	/* DBG_STATUS_INSUFFICIENT_HW_IDS */
+	"Insufficient HW IDs. Try to record less Storms/blocks",
+
+	/* DBG_STATUS_DBG_BUS_IN_USE */
+	"The debug bus is in use",
+
+	/* DBG_STATUS_INVALID_STORM_DBG_MODE */
+	"The storm debug mode is not supported in the current chip",
+
+	/* DBG_STATUS_OTHER_ENGINE_BB_ONLY */
+	"Other engine is supported only in BB",
+
+	/* DBG_STATUS_FILTER_SINGLE_HW_ID */
+	"The configured filter mode requires a single Storm/block input",
+
+	/* DBG_STATUS_TRIGGER_SINGLE_HW_ID */
+	"The configured filter mode requires that all the constraints of a single trigger state will be defined on a single Storm/block input",
+
+	/* DBG_STATUS_MISSING_TRIGGER_STATE_STORM */
+	"When triggering on Storm data, the Storm to trigger on must be specified"
+};
+
+/* Idle check severity names array */
+static const char * const s_idle_chk_severity_str[] = {
+	"Error",
+	"Error if no traffic",
+	"Warning"
+};
+
+/* MCP Trace level names array */
+static const char * const s_mcp_trace_level_str[] = {
+	"ERROR",
+	"TRACE",
+	"DEBUG"
+};
+
+/* Access type names array */
+static const char * const s_access_strs[] = {
+	"read",
+	"write"
+};
+
+/* Privilege type names array */
+static const char * const s_privilege_strs[] = {
+	"VF",
+	"PDA",
+	"HV",
+	"UA"
+};
+
+/* Protection type names array */
+static const char * const s_protection_strs[] = {
+	"(default)",
+	"(default)",
+	"(default)",
+	"(default)",
+	"override VF",
+	"override PDA",
+	"override HV",
+	"override UA"
+};
+
+/* Master type names array */
+static const char * const s_master_strs[] = {
+	"???",
+	"pxp",
+	"mcp",
+	"msdm",
+	"psdm",
+	"ysdm",
+	"usdm",
+	"tsdm",
+	"xsdm",
+	"dbu",
+	"dmae",
+	"jdap",
+	"???",
+	"???",
+	"???",
+	"???"
+};
+
+/* REG FIFO error messages array */
+static struct reg_fifo_err s_reg_fifo_errors[] = {
+	{1, "grc timeout"},
+	{2, "address doesn't belong to any block"},
+	{4, "reserved address in block or write to read-only address"},
+	{8, "privilege/protection mismatch"},
+	{16, "path isolation error"},
+	{17, "RSL error"}
+};
+
+/* IGU FIFO sources array */
+static const char * const s_igu_fifo_source_strs[] = {
+	"TSTORM",
+	"MSTORM",
+	"USTORM",
+	"XSTORM",
+	"YSTORM",
+	"PSTORM",
+	"PCIE",
+	"NIG_QM_PBF",
+	"CAU",
+	"ATTN",
+	"GRC",
+};
+
+/* IGU FIFO error messages */
+static const char * const s_igu_fifo_error_strs[] = {
+	"no error",
+	"length error",
+	"function disabled",
+	"VF sent command to attention address",
+	"host sent prod update command",
+	"read of during interrupt register while in MIMD mode",
+	"access to PXP BAR reserved address",
+	"producer update command to attention index",
+	"unknown error",
+	"SB index not valid",
+	"SB relative index and FID not found",
+	"FID not match",
+	"command with error flag asserted (PCI error or CAU discard)",
+	"VF sent cleanup and RF cleanup is disabled",
+	"cleanup command on type bigger than 4"
+};
+
+/* IGU FIFO address data */
+static const struct igu_fifo_addr_data s_igu_fifo_addr_data[] = {
+	{0x0, 0x101, "MSI-X Memory", NULL,
+	 IGU_ADDR_TYPE_MSIX_MEM},
+	{0x102, 0x1ff, "reserved", NULL,
+	 IGU_ADDR_TYPE_RESERVED},
+	{0x200, 0x200, "Write PBA[0:63]", NULL,
+	 IGU_ADDR_TYPE_WRITE_PBA},
+	{0x201, 0x201, "Write PBA[64:127]", "reserved",
+	 IGU_ADDR_TYPE_WRITE_PBA},
+	{0x202, 0x202, "Write PBA[128]", "reserved",
+	 IGU_ADDR_TYPE_WRITE_PBA},
+	{0x203, 0x3ff, "reserved", NULL,
+	 IGU_ADDR_TYPE_RESERVED},
+	{0x400, 0x5ef, "Write interrupt acknowledgment", NULL,
+	 IGU_ADDR_TYPE_WRITE_INT_ACK},
+	{0x5f0, 0x5f0, "Attention bits update", NULL,
+	 IGU_ADDR_TYPE_WRITE_ATTN_BITS},
+	{0x5f1, 0x5f1, "Attention bits set", NULL,
+	 IGU_ADDR_TYPE_WRITE_ATTN_BITS},
+	{0x5f2, 0x5f2, "Attention bits clear", NULL,
+	 IGU_ADDR_TYPE_WRITE_ATTN_BITS},
+	{0x5f3, 0x5f3, "Read interrupt 0:63 with mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f4, 0x5f4, "Read interrupt 0:31 with mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f5, 0x5f5, "Read interrupt 32:63 with mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f6, 0x5f6, "Read interrupt 0:63 without mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f7, 0x5ff, "reserved", NULL,
+	 IGU_ADDR_TYPE_RESERVED},
+	{0x600, 0x7ff, "Producer update", NULL,
+	 IGU_ADDR_TYPE_WRITE_PROD_UPDATE}
+};
+
+/******************************** Variables **********************************/
+
+/* Temporary buffer, used for print size calculations */
+static char s_temp_buf[MAX_MSG_LEN];
+
+/**************************** Private Functions ******************************/
+
+static u32 qed_cyclic_add(u32 a, u32 b, u32 size)
+{
+	return (a + b) % size;
+}
+
+static u32 qed_cyclic_sub(u32 a, u32 b, u32 size)
+{
+	return (size + a - b) % size;
+}
+
+/* Reads the specified number of bytes from the specified cyclic buffer (up to 4
+ * bytes) and returns them as a dword value. the specified buffer offset is
+ * updated.
+ */
+static u32 qed_read_from_cyclic_buf(void *buf,
+				    u32 *offset,
+				    u32 buf_size, u8 num_bytes_to_read)
+{
+	u8 i, *val_ptr, *bytes_buf = (u8 *)buf;
+	u32 val = 0;
+
+	val_ptr = (u8 *)&val;
+
+	/* Assume running on a LITTLE ENDIAN and the buffer is network order
+	 * (BIG ENDIAN), as high order bytes are placed in lower memory address.
+	 */
+	for (i = 0; i < num_bytes_to_read; i++) {
+		val_ptr[i] = bytes_buf[*offset];
+		*offset = qed_cyclic_add(*offset, 1, buf_size);
+	}
+
+	return val;
+}
+
+/* Reads and returns the next byte from the specified buffer.
+ * The specified buffer offset is updated.
+ */
+static u8 qed_read_byte_from_buf(void *buf, u32 *offset)
+{
+	return ((u8 *)buf)[(*offset)++];
+}
+
+/* Reads and returns the next dword from the specified buffer.
+ * The specified buffer offset is updated.
+ */
+static u32 qed_read_dword_from_buf(void *buf, u32 *offset)
+{
+	u32 dword_val = *(u32 *)&((u8 *)buf)[*offset];
+
+	*offset += 4;
+
+	return dword_val;
+}
+
+/* Reads the next string from the specified buffer, and copies it to the
+ * specified pointer. The specified buffer offset is updated.
+ */
+static void qed_read_str_from_buf(void *buf, u32 *offset, u32 size, char *dest)
+{
+	const char *source_str = &((const char *)buf)[*offset];
+
+	OSAL_STRNCPY(dest, source_str, size);
+	dest[size - 1] = '\0';
+	*offset += size;
+}
+
+/* Returns a pointer to the specified offset (in bytes) of the specified buffer.
+ * If the specified buffer in NULL, a temporary buffer pointer is returned.
+ */
+static char *qed_get_buf_ptr(void *buf, u32 offset)
+{
+	return buf ? (char *)buf + offset : s_temp_buf;
+}
+
+/* Reads a param from the specified buffer. Returns the number of dwords read.
+ * If the returned str_param is NULL, the param is numeric and its value is
+ * returned in num_param.
+ * Otheriwise, the param is a string and its pointer is returned in str_param.
+ */
+static u32 qed_read_param(u32 *dump_buf,
+			  const char **param_name,
+			  const char **param_str_val, u32 *param_num_val)
+{
+	char *char_buf = (char *)dump_buf;
+	size_t offset = 0;
+
+	/* Extract param name */
+	*param_name = char_buf;
+	offset += strlen(*param_name) + 1;
+
+	/* Check param type */
+	if (*(char_buf + offset++)) {
+		/* String param */
+		*param_str_val = char_buf + offset;
+		*param_num_val = 0;
+		offset += strlen(*param_str_val) + 1;
+		if (offset & 0x3)
+			offset += (4 - (offset & 0x3));
+	} else {
+		/* Numeric param */
+		*param_str_val = NULL;
+		if (offset & 0x3)
+			offset += (4 - (offset & 0x3));
+		*param_num_val = *(u32 *)(char_buf + offset);
+		offset += 4;
+	}
+
+	return (u32)offset / 4;
+}
+
+/* Reads a section header from the specified buffer.
+ * Returns the number of dwords read.
+ */
+static u32 qed_read_section_hdr(u32 *dump_buf,
+				const char **section_name,
+				u32 *num_section_params)
+{
+	const char *param_str_val;
+
+	return qed_read_param(dump_buf,
+			      section_name, &param_str_val, num_section_params);
+}
+
+/* Reads section params from the specified buffer and prints them to the results
+ * buffer. Returns the number of dwords read.
+ */
+static u32 qed_print_section_params(u32 *dump_buf,
+				    u32 num_section_params,
+				    char *results_buf, u32 *num_chars_printed)
+{
+	u32 i, dump_offset = 0, results_offset = 0;
+
+	for (i = 0; i < num_section_params; i++) {
+		const char *param_name, *param_str_val;
+		u32 param_num_val = 0;
+
+		dump_offset += qed_read_param(dump_buf + dump_offset,
+					      &param_name,
+					      &param_str_val, &param_num_val);
+
+		if (param_str_val) {
+			results_offset +=
+				sprintf(qed_get_buf_ptr(results_buf,
+							results_offset),
+					"%s: %s\n", param_name, param_str_val);
+		} else if (strcmp(param_name, "fw-timestamp")) {
+			results_offset +=
+				sprintf(qed_get_buf_ptr(results_buf,
+							results_offset),
+					"%s: %d\n", param_name, param_num_val);
+		}
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf, results_offset),
+				  "\n");
+
+	*num_chars_printed = results_offset;
+
+	return dump_offset;
+}
+
+/* Returns the block name that matches the specified block ID,
+ * or NULL if not found.
+ */
+static const char *qed_dbg_get_block_name(struct ecore_hwfn *p_hwfn,
+					  enum block_id block_id)
+{
+	const struct dbg_block_user *block =
+	    (const struct dbg_block_user *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS_USER_DATA].ptr + block_id;
+
+	return (const char *)block->name;
+}
+
+static struct dbg_tools_user_data *qed_dbg_get_user_data(struct ecore_hwfn
+							 *p_hwfn)
+{
+	return (struct dbg_tools_user_data *)p_hwfn->dbg_user_info;
+}
+
+/* Parses the idle check rules and returns the number of characters printed.
+ * In case of parsing error, returns 0.
+ */
+static u32 qed_parse_idle_chk_dump_rules(struct ecore_hwfn *p_hwfn,
+					 u32 *dump_buf,
+					 u32 *dump_buf_end,
+					 u32 num_rules,
+					 bool print_fw_idle_chk,
+					 char *results_buf,
+					 u32 *num_errors, u32 *num_warnings)
+{
+	/* Offset in results_buf in bytes */
+	u32 results_offset = 0;
+
+	u32 rule_idx;
+	u16 i, j;
+
+	*num_errors = 0;
+	*num_warnings = 0;
+
+	/* Go over dumped results */
+	for (rule_idx = 0; rule_idx < num_rules && dump_buf < dump_buf_end;
+	     rule_idx++) {
+		const struct dbg_idle_chk_rule_parsing_data *rule_parsing_data;
+		struct dbg_idle_chk_result_hdr *hdr;
+		const char *parsing_str, *lsi_msg;
+		u32 parsing_str_offset;
+		bool has_fw_msg;
+		u8 curr_reg_id;
+
+		hdr = (struct dbg_idle_chk_result_hdr *)dump_buf;
+		rule_parsing_data =
+		    (const struct dbg_idle_chk_rule_parsing_data *)
+		    p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_PARSING_DATA].ptr +
+		    hdr->rule_id;
+		parsing_str_offset =
+		    GET_FIELD(rule_parsing_data->data,
+			      DBG_IDLE_CHK_RULE_PARSING_DATA_STR_OFFSET);
+		has_fw_msg =
+		    GET_FIELD(rule_parsing_data->data,
+			      DBG_IDLE_CHK_RULE_PARSING_DATA_HAS_FW_MSG) > 0;
+		parsing_str = (const char *)
+		    p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr +
+		    parsing_str_offset;
+		lsi_msg = parsing_str;
+		curr_reg_id = 0;
+
+		if (hdr->severity >= MAX_DBG_IDLE_CHK_SEVERITY_TYPES)
+			return 0;
+
+		/* Skip rule header */
+		dump_buf += BYTES_TO_DWORDS(sizeof(*hdr));
+
+		/* Update errors/warnings count */
+		if (hdr->severity == IDLE_CHK_SEVERITY_ERROR ||
+		    hdr->severity == IDLE_CHK_SEVERITY_ERROR_NO_TRAFFIC)
+			(*num_errors)++;
+		else
+			(*num_warnings)++;
+
+		/* Print rule severity */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset), "%s: ",
+			    s_idle_chk_severity_str[hdr->severity]);
+
+		/* Print rule message */
+		if (has_fw_msg)
+			parsing_str += strlen(parsing_str) + 1;
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset), "%s.",
+			    has_fw_msg &&
+			    print_fw_idle_chk ? parsing_str : lsi_msg);
+		parsing_str += strlen(parsing_str) + 1;
+
+		/* Print register values */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset), " Registers:");
+		for (i = 0;
+		     i < hdr->num_dumped_cond_regs + hdr->num_dumped_info_regs;
+		     i++) {
+			struct dbg_idle_chk_result_reg_hdr *reg_hdr;
+			bool is_mem;
+			u8 reg_id;
+
+			reg_hdr =
+				(struct dbg_idle_chk_result_reg_hdr *)dump_buf;
+			is_mem = GET_FIELD(reg_hdr->data,
+					   DBG_IDLE_CHK_RESULT_REG_HDR_IS_MEM);
+			reg_id = GET_FIELD(reg_hdr->data,
+					   DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID);
+
+			/* Skip reg header */
+			dump_buf += BYTES_TO_DWORDS(sizeof(*reg_hdr));
+
+			/* Skip register names until the required reg_id is
+			 * reached.
+			 */
+			while (reg_id > curr_reg_id) {
+				curr_reg_id++;
+				parsing_str += strlen(parsing_str) + 1;
+			}
+
+			results_offset +=
+			    sprintf(qed_get_buf_ptr(results_buf,
+						    results_offset), " %s",
+				    parsing_str);
+			if (i < hdr->num_dumped_cond_regs && is_mem)
+				results_offset +=
+				    sprintf(qed_get_buf_ptr(results_buf,
+							    results_offset),
+					    "[%d]", hdr->mem_entry_id +
+					    reg_hdr->start_entry);
+			results_offset +=
+			    sprintf(qed_get_buf_ptr(results_buf,
+						    results_offset), "=");
+			for (j = 0; j < reg_hdr->size; j++, dump_buf++) {
+				results_offset +=
+				    sprintf(qed_get_buf_ptr(results_buf,
+							    results_offset),
+					    "0x%x", *dump_buf);
+				if (j < reg_hdr->size - 1)
+					results_offset +=
+					    sprintf(qed_get_buf_ptr
+						    (results_buf,
+						     results_offset), ",");
+			}
+		}
+
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf, results_offset), "\n");
+	}
+
+	/* Check if end of dump buffer was exceeded */
+	if (dump_buf > dump_buf_end)
+		return 0;
+
+	return results_offset;
+}
+
+/* Parses an idle check dump buffer.
+ * If result_buf is not NULL, the idle check results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+					       u32 *dump_buf,
+					       u32 num_dumped_dwords,
+					       char *results_buf,
+					       u32 *parsed_results_bytes,
+					       u32 *num_errors,
+					       u32 *num_warnings)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 *dump_buf_end = dump_buf + num_dumped_dwords;
+	u32 num_section_params = 0, num_rules;
+
+	/* Offset in results_buf in bytes */
+	u32 results_offset = 0;
+
+	*parsed_results_bytes = 0;
+	*num_errors = 0;
+	*num_warnings = 0;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_PARSING_DATA].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read idle_chk section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "idle_chk") || num_section_params != 1)
+		return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &num_rules);
+	if (strcmp(param_name, "num_rules"))
+		return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+
+	if (num_rules) {
+		u32 rules_print_size;
+
+		/* Print FW output */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "FW_IDLE_CHECK:\n");
+		rules_print_size =
+			qed_parse_idle_chk_dump_rules(p_hwfn,
+						      dump_buf,
+						      dump_buf_end,
+						      num_rules,
+						      true,
+						      results_buf ?
+						      results_buf +
+						      results_offset :
+						      NULL,
+						      num_errors,
+						      num_warnings);
+		results_offset += rules_print_size;
+		if (!rules_print_size)
+			return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+
+		/* Print LSI output */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nLSI_IDLE_CHECK:\n");
+		rules_print_size =
+			qed_parse_idle_chk_dump_rules(p_hwfn,
+						      dump_buf,
+						      dump_buf_end,
+						      num_rules,
+						      false,
+						      results_buf ?
+						      results_buf +
+						      results_offset :
+						      NULL,
+						      num_errors,
+						      num_warnings);
+		results_offset += rules_print_size;
+		if (!rules_print_size)
+			return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+	}
+
+	/* Print errors/warnings count */
+	if (*num_errors)
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nIdle Check failed!!! (with %d errors and %d warnings)\n",
+			    *num_errors, *num_warnings);
+	else if (*num_warnings)
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nIdle Check completed successfully (with %d warnings)\n",
+			    *num_warnings);
+	else
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nIdle Check completed successfully\n");
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+/* Allocates and fills MCP Trace meta data based on the specified meta data
+ * dump buffer.
+ * Returns debug status code.
+ */
+static enum dbg_status
+qed_mcp_trace_alloc_meta_data(struct ecore_hwfn *p_hwfn,
+			      const u32 *meta_buf)
+{
+	struct dbg_tools_user_data *dev_user_data;
+	u32 offset = 0, signature, i;
+	struct mcp_trace_meta *meta;
+	u8 *meta_buf_bytes = (u8 *)(osal_uintptr_t)meta_buf;
+
+	dev_user_data = qed_dbg_get_user_data(p_hwfn);
+	meta = &dev_user_data->mcp_trace_meta;
+
+	/* Free the previous meta before loading a new one. */
+	if (meta->is_allocated)
+		qed_mcp_trace_free_meta_data(p_hwfn);
+
+	OSAL_MEMSET(meta, 0, sizeof(*meta));
+
+	/* Read first signature */
+	signature = qed_read_dword_from_buf(meta_buf_bytes, &offset);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Read no. of modules and allocate memory for their pointers */
+	meta->modules_num = qed_read_byte_from_buf(meta_buf_bytes, &offset);
+	meta->modules = (char **)OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
+				    meta->modules_num * sizeof(char *));
+	if (!meta->modules)
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	/* Allocate and read all module strings */
+	for (i = 0; i < meta->modules_num; i++) {
+		u8 module_len = qed_read_byte_from_buf(meta_buf_bytes, &offset);
+
+		*(meta->modules + i) = (char *)OSAL_ZALLOC(p_hwfn->p_dev,
+							   GFP_KERNEL,
+							   module_len);
+		if (!(*(meta->modules + i))) {
+			/* Update number of modules to be released */
+			meta->modules_num = i ? i - 1 : 0;
+			return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+		}
+
+		qed_read_str_from_buf(meta_buf_bytes, &offset, module_len,
+				      *(meta->modules + i));
+		if (module_len > MCP_TRACE_MAX_MODULE_LEN)
+			(*(meta->modules + i))[MCP_TRACE_MAX_MODULE_LEN] = '\0';
+	}
+
+	/* Read second signature */
+	signature = qed_read_dword_from_buf(meta_buf_bytes, &offset);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Read number of formats and allocate memory for all formats */
+	meta->formats_num = qed_read_dword_from_buf(meta_buf_bytes, &offset);
+	meta->formats =
+		(struct mcp_trace_format *)OSAL_ZALLOC(p_hwfn->p_dev,
+						       GFP_KERNEL,
+						       meta->formats_num *
+					       sizeof(struct mcp_trace_format));
+	if (!meta->formats)
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	/* Allocate and read all strings */
+	for (i = 0; i < meta->formats_num; i++) {
+		struct mcp_trace_format *format_ptr = &meta->formats[i];
+		u8 format_len;
+
+		format_ptr->data = qed_read_dword_from_buf(meta_buf_bytes,
+							   &offset);
+		format_len = GET_MFW_FIELD(format_ptr->data,
+					   MCP_TRACE_FORMAT_LEN);
+		format_ptr->format_str = (char *)OSAL_ZALLOC(p_hwfn->p_dev,
+							     GFP_KERNEL,
+							     format_len);
+		if (!format_ptr->format_str) {
+			/* Update number of modules to be released */
+			meta->formats_num = i ? i - 1 : 0;
+			return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+		}
+
+		qed_read_str_from_buf(meta_buf_bytes,
+				      &offset,
+				      format_len, format_ptr->format_str);
+	}
+
+	meta->is_allocated = true;
+	return DBG_STATUS_OK;
+}
+
+/* Parses an MCP trace buffer. If result_buf is not NULL, the MCP Trace results
+ * are printed to it. The parsing status is returned.
+ * Arguments:
+ * trace_buf - MCP trace cyclic buffer
+ * trace_buf_size - MCP trace cyclic buffer size in bytes
+ * data_offset - offset in bytes of the data to parse in the MCP trace cyclic
+ *		 buffer.
+ * data_size - size in bytes of data to parse.
+ * parsed_buf - destination buffer for parsed data.
+ * parsed_results_bytes - size of parsed data in bytes.
+ */
+static enum dbg_status qed_parse_mcp_trace_buf(struct ecore_hwfn *p_hwfn,
+					       u8 *trace_buf,
+					       u32 trace_buf_size,
+					       u32 data_offset,
+					       u32 data_size,
+					       char *parsed_buf,
+					       u32 *parsed_results_bytes)
+{
+	struct dbg_tools_user_data *dev_user_data;
+	struct mcp_trace_meta *meta;
+	u32 param_mask, param_shift;
+	enum dbg_status status;
+
+	dev_user_data = qed_dbg_get_user_data(p_hwfn);
+	meta = &dev_user_data->mcp_trace_meta;
+	*parsed_results_bytes = 0;
+
+	if (!meta->is_allocated)
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+	status = DBG_STATUS_OK;
+
+	while (data_size) {
+		struct mcp_trace_format *format_ptr;
+		u8 format_level, format_module;
+		u32 params[3] = { 0, 0, 0 };
+		u32 header, format_idx, i;
+
+		if (data_size < MFW_TRACE_ENTRY_SIZE)
+			return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+		header = qed_read_from_cyclic_buf(trace_buf,
+						  &data_offset,
+						  trace_buf_size,
+						  MFW_TRACE_ENTRY_SIZE);
+		data_size -= MFW_TRACE_ENTRY_SIZE;
+		format_idx = header & MFW_TRACE_EVENTID_MASK;
+
+		/* Skip message if its index doesn't exist in the meta data */
+		if (format_idx >= meta->formats_num) {
+			u8 format_size = (u8)GET_MFW_FIELD(header,
+							   MFW_TRACE_PRM_SIZE);
+
+			if (data_size < format_size)
+				return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+			data_offset = qed_cyclic_add(data_offset,
+						     format_size,
+						     trace_buf_size);
+			data_size -= format_size;
+			continue;
+		}
+
+		format_ptr =
+			(struct mcp_trace_format *)&meta->formats[format_idx];
+
+		for (i = 0,
+		     param_mask = MCP_TRACE_FORMAT_P1_SIZE_MASK, param_shift =
+		     MCP_TRACE_FORMAT_P1_SIZE_OFFSET;
+		     i < MCP_TRACE_FORMAT_MAX_PARAMS;
+		     i++, param_mask <<= MCP_TRACE_FORMAT_PARAM_WIDTH,
+		     param_shift += MCP_TRACE_FORMAT_PARAM_WIDTH) {
+			/* Extract param size (0..3) */
+			u8 param_size = (u8)((format_ptr->data & param_mask) >>
+					     param_shift);
+
+			/* If the param size is zero, there are no other
+			 * parameters.
+			 */
+			if (!param_size)
+				break;
+
+			/* Size is encoded using 2 bits, where 3 is used to
+			 * encode 4.
+			 */
+			if (param_size == 3)
+				param_size = 4;
+
+			if (data_size < param_size)
+				return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+			params[i] = qed_read_from_cyclic_buf(trace_buf,
+							     &data_offset,
+							     trace_buf_size,
+							     param_size);
+			data_size -= param_size;
+		}
+
+		format_level = (u8)GET_MFW_FIELD(format_ptr->data,
+						 MCP_TRACE_FORMAT_LEVEL);
+		format_module = (u8)GET_MFW_FIELD(format_ptr->data,
+						  MCP_TRACE_FORMAT_MODULE);
+		if (format_level >= OSAL_ARRAY_SIZE(s_mcp_trace_level_str))
+			return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+		/* Print current message to results buffer */
+		*parsed_results_bytes +=
+			OSAL_SPRINTF(qed_get_buf_ptr(parsed_buf,
+						*parsed_results_bytes),
+				"%s %-8s: ",
+				s_mcp_trace_level_str[format_level],
+				meta->modules[format_module]);
+		*parsed_results_bytes +=
+		    sprintf(qed_get_buf_ptr(parsed_buf, *parsed_results_bytes),
+			    format_ptr->format_str,
+			    params[0], params[1], params[2]);
+	}
+
+	/* Add string NULL terminator */
+	(*parsed_results_bytes)++;
+
+	return status;
+}
+
+/* Parses an MCP Trace dump buffer.
+ * If result_buf is not NULL, the MCP Trace results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+						u32 *dump_buf,
+						char *results_buf,
+						u32 *parsed_results_bytes,
+						bool free_meta_data)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 data_size, trace_data_dwords, trace_meta_dwords;
+	u32 offset, results_offset, results_buf_bytes;
+	u32 param_num_val, num_section_params;
+	struct mcp_trace *trace;
+	enum dbg_status status;
+	const u32 *meta_buf;
+	u8 *trace_buf;
+
+	*parsed_results_bytes = 0;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read trace_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "mcp_trace_data") || num_section_params != 1)
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	trace_data_dwords = param_num_val;
+
+	/* Prepare trace info */
+	trace = (struct mcp_trace *)dump_buf;
+	if (trace->signature != MFW_TRACE_SIGNATURE || !trace->size)
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+	trace_buf = (u8 *)dump_buf + sizeof(*trace);
+	offset = trace->trace_oldest;
+	data_size = qed_cyclic_sub(trace->trace_prod, offset, trace->size);
+	dump_buf += trace_data_dwords;
+
+	/* Read meta_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "mcp_trace_meta"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	trace_meta_dwords = param_num_val;
+
+	/* Choose meta data buffer */
+	if (!trace_meta_dwords) {
+		/* Dump doesn't include meta data */
+		struct dbg_tools_user_data *dev_user_data =
+			qed_dbg_get_user_data(p_hwfn);
+
+		if (!dev_user_data->mcp_trace_user_meta_buf)
+			return DBG_STATUS_MCP_TRACE_NO_META;
+
+		meta_buf = dev_user_data->mcp_trace_user_meta_buf;
+	} else {
+		/* Dump includes meta data */
+		meta_buf = dump_buf;
+	}
+
+	/* Allocate meta data memory */
+	status = qed_mcp_trace_alloc_meta_data(p_hwfn, meta_buf);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	status = qed_parse_mcp_trace_buf(p_hwfn,
+					 trace_buf,
+					 trace->size,
+					 offset,
+					 data_size,
+					 results_buf ?
+					 results_buf + results_offset :
+					 NULL,
+					 &results_buf_bytes);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (free_meta_data)
+		qed_mcp_trace_free_meta_data(p_hwfn);
+
+	*parsed_results_bytes = results_offset + results_buf_bytes;
+
+	return DBG_STATUS_OK;
+}
+
+/* Parses a Reg FIFO dump buffer.
+ * If result_buf is not NULL, the Reg FIFO results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_reg_fifo_dump(u32 *dump_buf,
+					       char *results_buf,
+					       u32 *parsed_results_bytes)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 param_num_val, num_section_params, num_elements;
+	struct reg_fifo_element *elements;
+	u8 i, j, err_code, vf_val;
+	u32 results_offset = 0;
+	char vf_str[4];
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read reg_fifo_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "reg_fifo_data"))
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+	if (param_num_val % REG_FIFO_ELEMENT_DWORDS)
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+	num_elements = param_num_val / REG_FIFO_ELEMENT_DWORDS;
+	elements = (struct reg_fifo_element *)dump_buf;
+
+	/* Decode elements */
+	for (i = 0; i < num_elements; i++) {
+		const char *err_msg = NULL;
+
+		/* Discover if element belongs to a VF or a PF */
+		vf_val = GET_FIELD(elements[i].data, REG_FIFO_ELEMENT_VF);
+		if (vf_val == REG_FIFO_ELEMENT_IS_PF_VF_VAL)
+			sprintf(vf_str, "%s", "N/A");
+		else
+			sprintf(vf_str, "%d", vf_val);
+
+		/* Find error message */
+		err_code = GET_FIELD(elements[i].data, REG_FIFO_ELEMENT_ERROR);
+		for (j = 0; j < OSAL_ARRAY_SIZE(s_reg_fifo_errors) && !err_msg;
+		     j++)
+			if (err_code == s_reg_fifo_errors[j].err_code)
+				err_msg = s_reg_fifo_errors[j].err_msg;
+
+		/* Add parsed element to parsed buffer */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "raw: 0x%016lx, address: 0x%07x, access: %-5s, pf: %2d, vf: %s, port: %d, privilege: %-3s, protection: %-12s, master: %-4s, error: %s\n",
+			    elements[i].data,
+			    (u32)GET_FIELD(elements[i].data,
+					   REG_FIFO_ELEMENT_ADDRESS) *
+			    REG_FIFO_ELEMENT_ADDR_FACTOR,
+			    s_access_strs[GET_FIELD(elements[i].data,
+						    REG_FIFO_ELEMENT_ACCESS)],
+			    (u32)GET_FIELD(elements[i].data,
+					   REG_FIFO_ELEMENT_PF),
+			    vf_str,
+			    (u32)GET_FIELD(elements[i].data,
+					   REG_FIFO_ELEMENT_PORT),
+			    s_privilege_strs[GET_FIELD(elements[i].data,
+						REG_FIFO_ELEMENT_PRIVILEGE)],
+			    s_protection_strs[GET_FIELD(elements[i].data,
+						REG_FIFO_ELEMENT_PROTECTION)],
+			    s_master_strs[GET_FIELD(elements[i].data,
+						    REG_FIFO_ELEMENT_MASTER)],
+			    err_msg ? err_msg : "unknown error code");
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						  results_offset),
+				  "fifo contained %d elements", num_elements);
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status qed_parse_igu_fifo_element(struct igu_fifo_element
+						  *element, char
+						  *results_buf,
+						  u32 *results_offset)
+{
+	const struct igu_fifo_addr_data *found_addr = NULL;
+	u8 source, err_type, i, is_cleanup;
+	char parsed_addr_data[32];
+	char parsed_wr_data[256];
+	u32 wr_data, prod_cons;
+	bool is_wr_cmd, is_pf;
+	u16 cmd_addr;
+	u64 dword12;
+
+	/* Dword12 (dword index 1 and 2) contains bits 32..95 of the
+	 * FIFO element.
+	 */
+	dword12 = ((u64)element->dword2 << 32) | element->dword1;
+	is_wr_cmd = GET_FIELD(dword12, IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD);
+	is_pf = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_IS_PF);
+	cmd_addr = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR);
+	source = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_SOURCE);
+	err_type = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE);
+
+	if (source >= OSAL_ARRAY_SIZE(s_igu_fifo_source_strs))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	if (err_type >= OSAL_ARRAY_SIZE(s_igu_fifo_error_strs))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+
+	/* Find address data */
+	for (i = 0; i < OSAL_ARRAY_SIZE(s_igu_fifo_addr_data) && !found_addr;
+	     i++) {
+		const struct igu_fifo_addr_data *curr_addr =
+			&s_igu_fifo_addr_data[i];
+
+		if (cmd_addr >= curr_addr->start_addr && cmd_addr <=
+		    curr_addr->end_addr)
+			found_addr = curr_addr;
+	}
+
+	if (!found_addr)
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+
+	/* Prepare parsed address data */
+	switch (found_addr->type) {
+	case IGU_ADDR_TYPE_MSIX_MEM:
+		sprintf(parsed_addr_data, " vector_num = 0x%x", cmd_addr / 2);
+		break;
+	case IGU_ADDR_TYPE_WRITE_INT_ACK:
+	case IGU_ADDR_TYPE_WRITE_PROD_UPDATE:
+		sprintf(parsed_addr_data,
+			" SB = 0x%x", cmd_addr - found_addr->start_addr);
+		break;
+	default:
+		parsed_addr_data[0] = '\0';
+	}
+
+	if (!is_wr_cmd) {
+		parsed_wr_data[0] = '\0';
+		goto out;
+	}
+
+	/* Prepare parsed write data */
+	wr_data = GET_FIELD(dword12, IGU_FIFO_ELEMENT_DWORD12_WR_DATA);
+	prod_cons = GET_FIELD(wr_data, IGU_FIFO_WR_DATA_PROD_CONS);
+	is_cleanup = GET_FIELD(wr_data, IGU_FIFO_WR_DATA_CMD_TYPE);
+
+	if (source == IGU_SRC_ATTN) {
+		sprintf(parsed_wr_data, "prod: 0x%x, ", prod_cons);
+	} else {
+		if (is_cleanup) {
+			u8 cleanup_val, cleanup_type;
+
+			cleanup_val =
+				GET_FIELD(wr_data,
+					  IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL);
+			cleanup_type =
+			    GET_FIELD(wr_data,
+				      IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE);
+
+			sprintf(parsed_wr_data,
+				"cmd_type: cleanup, cleanup_val: %s, cleanup_type : %d, ",
+				cleanup_val ? "set" : "clear",
+				cleanup_type);
+		} else {
+			u8 update_flag, en_dis_int_for_sb, segment;
+			u8 timer_mask;
+
+			update_flag = GET_FIELD(wr_data,
+						IGU_FIFO_WR_DATA_UPDATE_FLAG);
+			en_dis_int_for_sb =
+				GET_FIELD(wr_data,
+					  IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB);
+			segment = GET_FIELD(wr_data,
+					    IGU_FIFO_WR_DATA_SEGMENT);
+			timer_mask = GET_FIELD(wr_data,
+					       IGU_FIFO_WR_DATA_TIMER_MASK);
+
+			sprintf(parsed_wr_data,
+				"cmd_type: prod/cons update, prod/cons: 0x%x, update_flag: %s, en_dis_int_for_sb : %s, segment : %s, timer_mask = %d, ",
+				prod_cons,
+				update_flag ? "update" : "nop",
+				en_dis_int_for_sb ?
+				(en_dis_int_for_sb == 1 ? "disable" : "nop") :
+				"enable",
+				segment ? "attn" : "regular",
+				timer_mask);
+		}
+	}
+out:
+	/* Add parsed element to parsed buffer */
+	*results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						   *results_offset),
+				   "raw: 0x%01x%08x%08x, %s: %d, source : %s, type : %s, cmd_addr : 0x%x(%s%s), %serror: %s\n",
+				   element->dword2, element->dword1,
+				   element->dword0,
+				   is_pf ? "pf" : "vf",
+				   GET_FIELD(element->dword0,
+					     IGU_FIFO_ELEMENT_DWORD0_FID),
+				   s_igu_fifo_source_strs[source],
+				   is_wr_cmd ? "wr" : "rd",
+				   cmd_addr,
+				   (!is_pf && found_addr->vf_desc)
+				   ? found_addr->vf_desc
+				   : found_addr->desc,
+				   parsed_addr_data,
+				   parsed_wr_data,
+				   s_igu_fifo_error_strs[err_type]);
+
+	return DBG_STATUS_OK;
+}
+
+/* Parses an IGU FIFO dump buffer.
+ * If result_buf is not NULL, the IGU FIFO results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_igu_fifo_dump(u32 *dump_buf,
+					       char *results_buf,
+					       u32 *parsed_results_bytes)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 param_num_val, num_section_params, num_elements;
+	struct igu_fifo_element *elements;
+	enum dbg_status status;
+	u32 results_offset = 0;
+	u8 i;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read igu_fifo_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "igu_fifo_data"))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	if (param_num_val % IGU_FIFO_ELEMENT_DWORDS)
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	num_elements = param_num_val / IGU_FIFO_ELEMENT_DWORDS;
+	elements = (struct igu_fifo_element *)dump_buf;
+
+	/* Decode elements */
+	for (i = 0; i < num_elements; i++) {
+		status = qed_parse_igu_fifo_element(&elements[i],
+						    results_buf,
+						    &results_offset);
+		if (status != DBG_STATUS_OK)
+			return status;
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						  results_offset),
+				  "fifo contained %d elements", num_elements);
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status
+qed_parse_protection_override_dump(u32 *dump_buf,
+				   char *results_buf,
+				   u32 *parsed_results_bytes)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 param_num_val, num_section_params, num_elements;
+	struct protection_override_element *elements;
+	u32 results_offset = 0;
+	u8 i;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read protection_override_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "protection_override_data"))
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+	if (param_num_val % PROTECTION_OVERRIDE_ELEMENT_DWORDS)
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+	num_elements = param_num_val / PROTECTION_OVERRIDE_ELEMENT_DWORDS;
+	elements = (struct protection_override_element *)dump_buf;
+
+	/* Decode elements */
+	for (i = 0; i < num_elements; i++) {
+		u32 address = GET_FIELD(elements[i].data,
+					PROTECTION_OVERRIDE_ELEMENT_ADDRESS) *
+			      PROTECTION_OVERRIDE_ELEMENT_ADDR_FACTOR;
+
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "window %2d, address: 0x%07x, size: %7d regs, read: %d, write: %d, read protection: %-12s, write protection: %-12s\n",
+			    i, address,
+			    (u32)GET_FIELD(elements[i].data,
+				      PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE),
+			    (u32)GET_FIELD(elements[i].data,
+				      PROTECTION_OVERRIDE_ELEMENT_READ),
+			    (u32)GET_FIELD(elements[i].data,
+				      PROTECTION_OVERRIDE_ELEMENT_WRITE),
+			    s_protection_strs[GET_FIELD(elements[i].data,
+				PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION)],
+			    s_protection_strs[GET_FIELD(elements[i].data,
+				PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION)]);
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						  results_offset),
+				  "protection override contained %d elements",
+				  num_elements);
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+/* Parses a FW Asserts dump buffer.
+ * If result_buf is not NULL, the FW Asserts results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_fw_asserts_dump(u32 *dump_buf,
+						 char *results_buf,
+						 u32 *parsed_results_bytes)
+{
+	u32 num_section_params, param_num_val, i, results_offset = 0;
+	const char *param_name, *param_str_val, *section_name;
+	bool last_section_found = false;
+
+	*parsed_results_bytes = 0;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	while (!last_section_found) {
+		dump_buf += qed_read_section_hdr(dump_buf,
+						 &section_name,
+						 &num_section_params);
+		if (!strcmp(section_name, "fw_asserts")) {
+			/* Extract params */
+			const char *storm_letter = NULL;
+			u32 storm_dump_size = 0;
+
+			for (i = 0; i < num_section_params; i++) {
+				dump_buf += qed_read_param(dump_buf,
+							   &param_name,
+							   &param_str_val,
+							   &param_num_val);
+				if (!strcmp(param_name, "storm"))
+					storm_letter = param_str_val;
+				else if (!strcmp(param_name, "size"))
+					storm_dump_size = param_num_val;
+				else
+					return
+					    DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+			}
+
+			if (!storm_letter || !storm_dump_size)
+				return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+
+			/* Print data */
+			results_offset +=
+			    sprintf(qed_get_buf_ptr(results_buf,
+						    results_offset),
+				    "\n%sSTORM_ASSERT: size=%d\n",
+				    storm_letter, storm_dump_size);
+			for (i = 0; i < storm_dump_size; i++, dump_buf++)
+				results_offset +=
+				    sprintf(qed_get_buf_ptr(results_buf,
+							    results_offset),
+					    "%08x\n", *dump_buf);
+		} else if (!strcmp(section_name, "last")) {
+			last_section_found = true;
+		} else {
+			return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+		}
+	}
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+/***************************** Public Functions *******************************/
+
+enum dbg_status qed_dbg_user_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+					 const u8 * const bin_ptr)
+{
+	struct bin_buffer_hdr *buf_hdrs =
+			(struct bin_buffer_hdr *)(osal_uintptr_t)bin_ptr;
+	u8 buf_id;
+
+	/* Convert binary data to debug arrays */
+	for (buf_id = 0; buf_id < MAX_BIN_DBG_BUFFER_TYPE; buf_id++)
+		qed_set_dbg_bin_buf(p_hwfn,
+				    (enum bin_dbg_buffer_type)buf_id,
+				    (const u32 *)(bin_ptr +
+						  buf_hdrs[buf_id].offset),
+						  buf_hdrs[buf_id].length);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_alloc_user_data(__rte_unused struct ecore_hwfn *p_hwfn,
+					void **user_data_ptr)
+{
+	*user_data_ptr = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
+				     sizeof(struct dbg_tools_user_data));
+	if (!(*user_data_ptr))
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	return DBG_STATUS_OK;
+}
+
+const char *qed_dbg_get_status_str(enum dbg_status status)
+{
+	return (status <
+		MAX_DBG_STATUS) ? s_status_str[status] : "Invalid debug status";
+}
+
+enum dbg_status qed_get_idle_chk_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32 num_dumped_dwords,
+						  u32 *results_buf_size)
+{
+	u32 num_errors, num_warnings;
+
+	return qed_parse_idle_chk_dump(p_hwfn,
+				       dump_buf,
+				       num_dumped_dwords,
+				       NULL,
+				       results_buf_size,
+				       &num_errors, &num_warnings);
+}
+
+enum dbg_status qed_print_idle_chk_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf,
+					   u32 *num_errors,
+					   u32 *num_warnings)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_idle_chk_dump(p_hwfn,
+				       dump_buf,
+				       num_dumped_dwords,
+				       results_buf,
+				       &parsed_buf_size,
+				       num_errors, num_warnings);
+}
+
+void qed_dbg_mcp_trace_set_meta_data(struct ecore_hwfn *p_hwfn,
+				     const u32 *meta_buf)
+{
+	struct dbg_tools_user_data *dev_user_data =
+		qed_dbg_get_user_data(p_hwfn);
+
+	dev_user_data->mcp_trace_user_meta_buf = meta_buf;
+}
+
+enum dbg_status
+qed_get_mcp_trace_results_buf_size(struct ecore_hwfn *p_hwfn,
+				   u32 *dump_buf,
+				   __rte_unused u32 num_dumped_dwords,
+				   u32 *results_buf_size)
+{
+	return qed_parse_mcp_trace_dump(p_hwfn,
+					dump_buf, NULL, results_buf_size, true);
+}
+
+enum dbg_status qed_print_mcp_trace_results(struct ecore_hwfn *p_hwfn,
+					    u32 *dump_buf,
+					    __rte_unused u32 num_dumped_dwords,
+					    char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_mcp_trace_dump(p_hwfn,
+					dump_buf,
+					results_buf, &parsed_buf_size, true);
+}
+
+enum dbg_status qed_print_mcp_trace_results_cont(struct ecore_hwfn *p_hwfn,
+						 u32 *dump_buf,
+						 char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_mcp_trace_dump(p_hwfn, dump_buf, results_buf,
+					&parsed_buf_size, false);
+}
+
+enum dbg_status qed_print_mcp_trace_line(struct ecore_hwfn *p_hwfn,
+					 u8 *dump_buf,
+					 u32 num_dumped_bytes,
+					 char *results_buf)
+{
+	u32 parsed_results_bytes;
+
+	return qed_parse_mcp_trace_buf(p_hwfn,
+				       dump_buf,
+				       num_dumped_bytes,
+				       0,
+				       num_dumped_bytes,
+				       results_buf, &parsed_results_bytes);
+}
+
+/* Frees the specified MCP Trace meta data */
+void qed_mcp_trace_free_meta_data(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_user_data *dev_user_data;
+	struct mcp_trace_meta *meta;
+	u32 i;
+
+	dev_user_data = qed_dbg_get_user_data(p_hwfn);
+	meta = &dev_user_data->mcp_trace_meta;
+	if (!meta->is_allocated)
+		return;
+
+	/* Release modules */
+	if (meta->modules) {
+		for (i = 0; i < meta->modules_num; i++)
+			OSAL_FREE(p_hwfn, meta->modules[i]);
+		OSAL_FREE(p_hwfn, meta->modules);
+	}
+
+	/* Release formats */
+	if (meta->formats) {
+		for (i = 0; i < meta->formats_num; i++)
+			OSAL_FREE(p_hwfn, meta->formats[i].format_str);
+		OSAL_FREE(p_hwfn, meta->formats);
+	}
+
+	meta->is_allocated = false;
+}
+
+enum dbg_status
+qed_get_reg_fifo_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
+				  u32 *dump_buf,
+				  __rte_unused u32 num_dumped_dwords,
+				  u32 *results_buf_size)
+{
+	return qed_parse_reg_fifo_dump(dump_buf, NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_reg_fifo_results(__rte_unused struct ecore_hwfn *p_hwfn,
+			   u32 *dump_buf,
+			   __rte_unused u32 num_dumped_dwords,
+			   char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_reg_fifo_dump(dump_buf, results_buf, &parsed_buf_size);
+}
+
+enum dbg_status
+qed_get_igu_fifo_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
+				  u32 *dump_buf,
+				  __rte_unused u32 num_dumped_dwords,
+				  u32 *results_buf_size)
+{
+	return qed_parse_igu_fifo_dump(dump_buf, NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_igu_fifo_results(__rte_unused struct ecore_hwfn *p_hwfn,
+			   u32 *dump_buf,
+			   __rte_unused u32 num_dumped_dwords,
+			   char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_igu_fifo_dump(dump_buf, results_buf, &parsed_buf_size);
+}
+
+enum dbg_status
+qed_get_protection_override_results_buf_size(__rte_unused
+					     struct ecore_hwfn *p_hwfn,
+					     u32 *dump_buf,
+					     __rte_unused u32 num_dumped_dwords,
+					     u32 *results_buf_size)
+{
+	return qed_parse_protection_override_dump(dump_buf,
+						  NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_protection_override_results(__rte_unused struct ecore_hwfn *p_hwfn,
+				      u32 *dump_buf,
+				      __rte_unused u32 num_dumped_dwords,
+				      char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_protection_override_dump(dump_buf,
+						  results_buf,
+						  &parsed_buf_size);
+}
+
+enum dbg_status
+qed_get_fw_asserts_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
+				    u32 *dump_buf,
+				    __rte_unused u32 num_dumped_dwords,
+				    u32 *results_buf_size)
+{
+	return qed_parse_fw_asserts_dump(dump_buf, NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_fw_asserts_results(__rte_unused struct ecore_hwfn *p_hwfn,
+			     u32 *dump_buf,
+			     __rte_unused u32 num_dumped_dwords,
+			     char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_fw_asserts_dump(dump_buf,
+					 results_buf, &parsed_buf_size);
+}
+
+enum dbg_status qed_dbg_parse_attn(struct ecore_hwfn *p_hwfn,
+				   struct dbg_attn_block_result *results)
+{
+	const u32 *block_attn_name_offsets;
+	const char *attn_name_base;
+	const char *block_name;
+	enum dbg_attn_type attn_type;
+	u8 num_regs, i, j;
+
+	num_regs = GET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_NUM_REGS);
+	attn_type = GET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_ATTN_TYPE);
+	block_name = qed_dbg_get_block_name(p_hwfn, results->block_id);
+	if (!block_name)
+		return DBG_STATUS_INVALID_ARGS;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_INDEXES].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_NAME_OFFSETS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	block_attn_name_offsets =
+	    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_NAME_OFFSETS].ptr +
+	    results->names_offset;
+
+	attn_name_base = p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr;
+
+	/* Go over registers with a non-zero attention status */
+	for (i = 0; i < num_regs; i++) {
+		struct dbg_attn_bit_mapping *bit_mapping;
+		struct dbg_attn_reg_result *reg_result;
+		u8 num_reg_attn, bit_idx = 0;
+
+		reg_result = &results->reg_results[i];
+		num_reg_attn = GET_FIELD(reg_result->data,
+					 DBG_ATTN_REG_RESULT_NUM_REG_ATTN);
+		bit_mapping = (struct dbg_attn_bit_mapping *)
+		    p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_INDEXES].ptr +
+		    reg_result->block_attn_offset;
+
+		/* Go over attention status bits */
+		for (j = 0; j < num_reg_attn; j++, bit_idx++) {
+			u16 attn_idx_val = GET_FIELD(bit_mapping[j].data,
+						     DBG_ATTN_BIT_MAPPING_VAL);
+			const char *attn_name, *attn_type_str, *masked_str;
+			u32 attn_name_offset;
+			u32 sts_addr;
+
+			/* Check if bit mask should be advanced (due to unused
+			 * bits).
+			 */
+			if (GET_FIELD(bit_mapping[j].data,
+				      DBG_ATTN_BIT_MAPPING_IS_UNUSED_BIT_CNT)) {
+				bit_idx += (u8)attn_idx_val;
+				continue;
+			}
+
+			/* Check current bit index */
+			if (!(reg_result->sts_val & OSAL_BIT(bit_idx)))
+				continue;
+
+			/* An attention bit with value=1 was found
+			 * Find attention name
+			 */
+			attn_name_offset =
+				block_attn_name_offsets[attn_idx_val];
+			attn_name = attn_name_base + attn_name_offset;
+			attn_type_str =
+				(attn_type ==
+				 ATTN_TYPE_INTERRUPT ? "Interrupt" :
+				 "Parity");
+			masked_str = reg_result->mask_val & OSAL_BIT(bit_idx) ?
+				     " [masked]" : "";
+			sts_addr = GET_FIELD(reg_result->data,
+					     DBG_ATTN_REG_RESULT_STS_ADDRESS);
+			DP_NOTICE(p_hwfn, false,
+				  "%s (%s) : %s [address 0x%08x, bit %d]%s\n",
+				  block_name, attn_type_str, attn_name,
+				  sts_addr * 4, bit_idx, masked_str);
+		}
+	}
+
+	return DBG_STATUS_OK;
+}
+
+/* Wrapper for unifying the idle_chk and mcp_trace api */
+static enum dbg_status
+qed_print_idle_chk_results_wrapper(struct ecore_hwfn *p_hwfn,
+				   u32 *dump_buf,
+				   u32 num_dumped_dwords,
+				   char *results_buf)
+{
+	u32 num_errors, num_warnnings;
+
+	return qed_print_idle_chk_results(p_hwfn, dump_buf, num_dumped_dwords,
+					  results_buf, &num_errors,
+					  &num_warnnings);
+}
+
+/* Feature meta data lookup table */
+static struct {
+	const char *name;
+	enum dbg_status (*get_size)(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt, u32 *size);
+	enum dbg_status (*perform_dump)(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt, u32 *dump_buf,
+					u32 buf_size, u32 *dumped_dwords);
+	enum dbg_status (*print_results)(struct ecore_hwfn *p_hwfn,
+					 u32 *dump_buf, u32 num_dumped_dwords,
+					 char *results_buf);
+	enum dbg_status (*results_buf_size)(struct ecore_hwfn *p_hwfn,
+					    u32 *dump_buf,
+					    u32 num_dumped_dwords,
+					    u32 *results_buf_size);
+} qed_features_lookup[] = {
+	{
+	"grc", qed_dbg_grc_get_dump_buf_size,
+		    qed_dbg_grc_dump, NULL, NULL}, {
+	"idle_chk",
+		    qed_dbg_idle_chk_get_dump_buf_size,
+		    qed_dbg_idle_chk_dump,
+		    qed_print_idle_chk_results_wrapper,
+		    qed_get_idle_chk_results_buf_size}, {
+	"mcp_trace",
+		    qed_dbg_mcp_trace_get_dump_buf_size,
+		    qed_dbg_mcp_trace_dump, qed_print_mcp_trace_results,
+		    qed_get_mcp_trace_results_buf_size}, {
+	"reg_fifo",
+		    qed_dbg_reg_fifo_get_dump_buf_size,
+		    qed_dbg_reg_fifo_dump, qed_print_reg_fifo_results,
+		    qed_get_reg_fifo_results_buf_size}, {
+	"igu_fifo",
+		    qed_dbg_igu_fifo_get_dump_buf_size,
+		    qed_dbg_igu_fifo_dump, qed_print_igu_fifo_results,
+		    qed_get_igu_fifo_results_buf_size}, {
+	"protection_override",
+		    qed_dbg_protection_override_get_dump_buf_size,
+		    qed_dbg_protection_override_dump,
+		    qed_print_protection_override_results,
+		    qed_get_protection_override_results_buf_size}, {
+	"fw_asserts",
+		    qed_dbg_fw_asserts_get_dump_buf_size,
+		    qed_dbg_fw_asserts_dump,
+		    qed_print_fw_asserts_results,
+		    qed_get_fw_asserts_results_buf_size}, {
+	"ilt",
+		    qed_dbg_ilt_get_dump_buf_size,
+		    qed_dbg_ilt_dump, NULL, NULL},};
+
+#define QED_RESULTS_BUF_MIN_SIZE 16
+/* Generic function for decoding debug feature info */
+static enum dbg_status format_feature(struct ecore_hwfn *p_hwfn,
+				      enum ecore_dbg_features feature_idx)
+{
+	struct ecore_dbg_feature *feature =
+	    &p_hwfn->p_dev->dbg_params.features[feature_idx];
+	u32 text_size_bytes, null_char_pos, i;
+	enum dbg_status rc;
+	char *text_buf;
+
+	/* Check if feature supports formatting capability */
+	if (!qed_features_lookup[feature_idx].results_buf_size)
+		return DBG_STATUS_OK;
+
+	/* Obtain size of formatted output */
+	rc = qed_features_lookup[feature_idx].results_buf_size(p_hwfn,
+						(u32 *)feature->dump_buf,
+						feature->dumped_dwords,
+						&text_size_bytes);
+	if (rc != DBG_STATUS_OK)
+		return rc;
+
+	/* Make sure that the allocated size is a multiple of dword (4 bytes) */
+	null_char_pos = text_size_bytes - 1;
+	text_size_bytes = (text_size_bytes + 3) & ~0x3;
+
+	if (text_size_bytes < QED_RESULTS_BUF_MIN_SIZE) {
+		DP_NOTICE(p_hwfn->p_dev, false,
+			  "formatted size of feature was too small %d. Aborting\n",
+			  text_size_bytes);
+		return DBG_STATUS_INVALID_ARGS;
+	}
+
+	/* Allocate temp text buf */
+	text_buf = OSAL_VZALLOC(p_hwfn, text_size_bytes);
+	if (!text_buf) {
+		DP_NOTICE(p_hwfn->p_dev, false,
+			  "failed to allocate text buffer. Aborting\n");
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+	}
+
+	/* Decode feature opcodes to string on temp buf */
+	rc = qed_features_lookup[feature_idx].print_results(p_hwfn,
+						(u32 *)feature->dump_buf,
+						feature->dumped_dwords,
+						text_buf);
+	if (rc != DBG_STATUS_OK) {
+		OSAL_VFREE(p_hwfn, text_buf);
+		return rc;
+	}
+
+	/* Replace the original null character with a '\n' character.
+	 * The bytes that were added as a result of the dword alignment are also
+	 * padded with '\n' characters.
+	 */
+	for (i = null_char_pos; i < text_size_bytes; i++)
+		text_buf[i] = '\n';
+
+
+	/* Free the old dump_buf and point the dump_buf to the newly allocagted
+	 * and formatted text buffer.
+	 */
+	OSAL_VFREE(p_hwfn, feature->dump_buf);
+	feature->dump_buf = (u8 *)text_buf;
+	feature->buf_size = text_size_bytes;
+	feature->dumped_dwords = text_size_bytes / 4;
+	return rc;
+}
+
+#define MAX_DBG_FEATURE_SIZE_DWORDS	0x3FFFFFFF
+
+/* Generic function for performing the dump of a debug feature. */
+static enum dbg_status qed_dbg_dump(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    enum ecore_dbg_features feature_idx)
+{
+	struct ecore_dbg_feature *feature =
+	    &p_hwfn->p_dev->dbg_params.features[feature_idx];
+	u32 buf_size_dwords;
+	enum dbg_status rc;
+
+	DP_NOTICE(p_hwfn->p_dev, false, "Collecting a debug feature [\"%s\"]\n",
+		  qed_features_lookup[feature_idx].name);
+
+	/* Dump_buf was already allocated need to free (this can happen if dump
+	 * was called but file was never read).
+	 * We can't use the buffer as is since size may have changed.
+	 */
+	if (feature->dump_buf) {
+		OSAL_VFREE(p_hwfn, feature->dump_buf);
+		feature->dump_buf = NULL;
+	}
+
+	/* Get buffer size from hsi, allocate accordingly, and perform the
+	 * dump.
+	 */
+	rc = qed_features_lookup[feature_idx].get_size(p_hwfn, p_ptt,
+						       &buf_size_dwords);
+	if (rc != DBG_STATUS_OK && rc != DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
+		return rc;
+
+	if (buf_size_dwords > MAX_DBG_FEATURE_SIZE_DWORDS) {
+		feature->buf_size = 0;
+		DP_NOTICE(p_hwfn->p_dev, false,
+			  "Debug feature [\"%s\"] size (0x%x dwords) exceeds maximum size (0x%x dwords)\n",
+			  qed_features_lookup[feature_idx].name,
+			  buf_size_dwords, MAX_DBG_FEATURE_SIZE_DWORDS);
+
+		return DBG_STATUS_OK;
+	}
+
+	feature->buf_size = buf_size_dwords * sizeof(u32);
+	feature->dump_buf = OSAL_ZALLOC(p_hwfn, GFP_KERNEL, feature->buf_size);
+	if (!feature->dump_buf)
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	rc = qed_features_lookup[feature_idx].perform_dump(p_hwfn, p_ptt,
+					(u32 *)feature->dump_buf,
+					feature->buf_size / sizeof(u32),
+					&feature->dumped_dwords);
+
+	/* If mcp is stuck we get DBG_STATUS_NVRAM_GET_IMAGE_FAILED error.
+	 * In this case the buffer holds valid binary data, but we won't able
+	 * to parse it (since parsing relies on data in NVRAM which is only
+	 * accessible when MFW is responsive). skip the formatting but return
+	 * success so that binary data is provided.
+	 */
+	if (rc == DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
+		return DBG_STATUS_OK;
+
+	if (rc != DBG_STATUS_OK)
+		return rc;
+
+	/* Format output */
+	rc = format_feature(p_hwfn, feature_idx);
+	return rc;
+}
+
+int qed_dbg_grc(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_GRC, num_dumped_bytes);
+}
+
+int qed_dbg_grc_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_GRC);
+}
+
+int
+qed_dbg_idle_chk(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_IDLE_CHK,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_idle_chk_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_IDLE_CHK);
+}
+
+int
+qed_dbg_reg_fifo(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_REG_FIFO,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_reg_fifo_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_REG_FIFO);
+}
+
+int
+qed_dbg_igu_fifo(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_IGU_FIFO,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_igu_fifo_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_IGU_FIFO);
+}
+
+static int qed_dbg_nvm_image_length(struct ecore_hwfn *p_hwfn,
+				    enum ecore_nvm_images image_id, u32 *length)
+{
+	struct ecore_nvm_image_att image_att;
+	int rc;
+
+	*length = 0;
+	rc = ecore_mcp_get_nvm_image_att(p_hwfn, image_id, &image_att);
+	if (rc)
+		return rc;
+
+	*length = image_att.length;
+
+	return rc;
+}
+
+int qed_dbg_protection_override(struct ecore_dev *edev, void *buffer,
+				u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_PROTECTION_OVERRIDE,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_protection_override_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_PROTECTION_OVERRIDE);
+}
+
+int qed_dbg_fw_asserts(struct ecore_dev *edev, void *buffer,
+		       u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_FW_ASSERTS,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_fw_asserts_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_FW_ASSERTS);
+}
+
+int qed_dbg_ilt(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_ILT, num_dumped_bytes);
+}
+
+int qed_dbg_ilt_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_ILT);
+}
+
+int qed_dbg_mcp_trace(struct ecore_dev *edev, void *buffer,
+		      u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_MCP_TRACE,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_mcp_trace_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_MCP_TRACE);
+}
+
+/* Defines the amount of bytes allocated for recording the length of debug
+ * feature buffer.
+ */
+#define REGDUMP_HEADER_SIZE			sizeof(u32)
+#define REGDUMP_HEADER_SIZE_SHIFT		0
+#define REGDUMP_HEADER_SIZE_MASK		0xffffff
+#define REGDUMP_HEADER_FEATURE_SHIFT		24
+#define REGDUMP_HEADER_FEATURE_MASK		0x3f
+#define REGDUMP_HEADER_OMIT_ENGINE_SHIFT	30
+#define REGDUMP_HEADER_OMIT_ENGINE_MASK		0x1
+#define REGDUMP_HEADER_ENGINE_SHIFT		31
+#define REGDUMP_HEADER_ENGINE_MASK		0x1
+#define REGDUMP_MAX_SIZE			0x1000000
+#define ILT_DUMP_MAX_SIZE			(1024 * 1024 * 15)
+
+enum debug_print_features {
+	OLD_MODE = 0,
+	IDLE_CHK = 1,
+	GRC_DUMP = 2,
+	MCP_TRACE = 3,
+	REG_FIFO = 4,
+	PROTECTION_OVERRIDE = 5,
+	IGU_FIFO = 6,
+	PHY = 7,
+	FW_ASSERTS = 8,
+	NVM_CFG1 = 9,
+	DEFAULT_CFG = 10,
+	NVM_META = 11,
+	MDUMP = 12,
+	ILT_DUMP = 13,
+};
+
+static u32 qed_calc_regdump_header(struct ecore_dev *edev,
+				   enum debug_print_features feature,
+				   int engine, u32 feature_size, u8 omit_engine)
+{
+	u32 res = 0;
+
+	SET_FIELD(res, REGDUMP_HEADER_SIZE, feature_size);
+	if (res != feature_size)
+		DP_NOTICE(edev, false,
+			  "Feature %d is too large (size 0x%x) and will corrupt the dump\n",
+			  feature, feature_size);
+
+	SET_FIELD(res, REGDUMP_HEADER_FEATURE, feature);
+	SET_FIELD(res, REGDUMP_HEADER_OMIT_ENGINE, omit_engine);
+	SET_FIELD(res, REGDUMP_HEADER_ENGINE, engine);
+
+	return res;
+}
+
+int qed_dbg_all_data(struct ecore_dev *edev, void *buffer)
+{
+	u8 cur_engine, omit_engine = 0, org_engine;
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	int grc_params[MAX_DBG_GRC_PARAMS], i;
+	u32 offset = 0, feature_size;
+	int rc;
+
+	for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
+		grc_params[i] = dev_data->grc.param_val[i];
+
+	if (!ECORE_IS_CMT(edev))
+		omit_engine = 1;
+
+	OSAL_MUTEX_ACQUIRE(&edev->dbg_lock);
+
+	org_engine = qed_get_debug_engine(edev);
+	for (cur_engine = 0; cur_engine < edev->num_hwfns; cur_engine++) {
+		/* Collect idle_chks and grcDump for each hw function */
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+			   "obtaining idle_chk and grcdump for current engine\n");
+		qed_set_debug_engine(edev, cur_engine);
+
+		/* First idle_chk */
+		rc = qed_dbg_idle_chk(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, IDLE_CHK, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_idle_chk failed. rc = %d\n", rc);
+		}
+
+		/* Second idle_chk */
+		rc = qed_dbg_idle_chk(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, IDLE_CHK, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_idle_chk failed. rc = %d\n", rc);
+		}
+
+		/* reg_fifo dump */
+		rc = qed_dbg_reg_fifo(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, REG_FIFO, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_reg_fifo failed. rc = %d\n", rc);
+		}
+
+		/* igu_fifo dump */
+		rc = qed_dbg_igu_fifo(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, IGU_FIFO, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_igu_fifo failed. rc = %d", rc);
+		}
+
+		/* protection_override dump */
+		rc = qed_dbg_protection_override(edev, (u8 *)buffer + offset +
+						 REGDUMP_HEADER_SIZE,
+						 &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, PROTECTION_OVERRIDE,
+						    cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev,
+			       "qed_dbg_protection_override failed. rc = %d\n",
+			       rc);
+		}
+
+		/* fw_asserts dump */
+		rc = qed_dbg_fw_asserts(edev, (u8 *)buffer + offset +
+					REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, FW_ASSERTS,
+						    cur_engine, feature_size,
+						    omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_fw_asserts failed. rc = %d\n",
+			       rc);
+		}
+
+		/* GRC dump - must be last because when mcp stuck it will
+		 * clutter idle_chk, reg_fifo, ...
+		 */
+		for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
+			dev_data->grc.param_val[i] = grc_params[i];
+
+		rc = qed_dbg_grc(edev, (u8 *)buffer + offset +
+				 REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, GRC_DUMP,
+						    cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_grc failed. rc = %d", rc);
+		}
+	}
+
+	qed_set_debug_engine(edev, org_engine);
+
+	/* mcp_trace */
+	rc = qed_dbg_mcp_trace(edev, (u8 *)buffer + offset +
+			       REGDUMP_HEADER_SIZE, &feature_size);
+	if (!rc) {
+		*(u32 *)((u8 *)buffer + offset) =
+		    qed_calc_regdump_header(edev, MCP_TRACE, cur_engine,
+					    feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+	} else {
+		DP_ERR(edev, "qed_dbg_mcp_trace failed. rc = %d\n", rc);
+	}
+
+	OSAL_MUTEX_RELEASE(&edev->dbg_lock);
+
+	return 0;
+}
+
+int qed_dbg_all_data_size(struct ecore_dev *edev)
+{
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	u32 regs_len = 0, image_len = 0, ilt_len = 0, total_ilt_len = 0;
+	u8 cur_engine, org_engine;
+
+	edev->disable_ilt_dump = false;
+	org_engine = qed_get_debug_engine(edev);
+	for (cur_engine = 0; cur_engine < edev->num_hwfns; cur_engine++) {
+		/* Engine specific */
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+			   "calculating idle_chk and grcdump register length for current engine\n");
+		qed_set_debug_engine(edev, cur_engine);
+		regs_len += REGDUMP_HEADER_SIZE + qed_dbg_idle_chk_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_idle_chk_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_grc_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_reg_fifo_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_igu_fifo_size(edev) +
+			    REGDUMP_HEADER_SIZE +
+			    qed_dbg_protection_override_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_fw_asserts_size(edev);
+
+		ilt_len = REGDUMP_HEADER_SIZE + qed_dbg_ilt_size(edev);
+		if (ilt_len < ILT_DUMP_MAX_SIZE) {
+			total_ilt_len += ilt_len;
+			regs_len += ilt_len;
+		}
+	}
+
+	qed_set_debug_engine(edev, org_engine);
+
+	/* Engine common */
+	regs_len += REGDUMP_HEADER_SIZE + qed_dbg_mcp_trace_size(edev);
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_NVM_CFG1, &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_DEFAULT_CFG,
+				 &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_NVM_META, &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_MDUMP, &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+
+	if (regs_len > REGDUMP_MAX_SIZE) {
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+			   "Dump exceeds max size 0x%x, disable ILT dump\n",
+			   REGDUMP_MAX_SIZE);
+		edev->disable_ilt_dump = true;
+		regs_len -= total_ilt_len;
+	}
+
+	return regs_len;
+}
+
+int qed_dbg_feature(struct ecore_dev *edev, void *buffer,
+		    enum ecore_dbg_features feature, u32 *num_dumped_bytes)
+{
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	struct ecore_dbg_feature *qed_feature =
+		&edev->dbg_params.features[feature];
+	enum dbg_status dbg_rc;
+	struct ecore_ptt *p_ptt;
+	int rc = 0;
+
+	/* Acquire ptt */
+	p_ptt = ecore_ptt_acquire(p_hwfn);
+	if (!p_ptt)
+		return -EINVAL;
+
+	/* Get dump */
+	dbg_rc = qed_dbg_dump(p_hwfn, p_ptt, feature);
+	if (dbg_rc != DBG_STATUS_OK) {
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG, "%s\n",
+			   qed_dbg_get_status_str(dbg_rc));
+		*num_dumped_bytes = 0;
+		rc = -EINVAL;
+		goto out;
+	}
+
+	DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+		   "copying debug feature to external buffer\n");
+	memcpy(buffer, qed_feature->dump_buf, qed_feature->buf_size);
+	*num_dumped_bytes = edev->dbg_params.features[feature].dumped_dwords *
+			    4;
+
+out:
+	ecore_ptt_release(p_hwfn, p_ptt);
+	return rc;
+}
+
+int
+qed_dbg_feature_size(struct ecore_dev *edev, enum ecore_dbg_features feature)
+{
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	struct ecore_dbg_feature *qed_feature = &edev->dbg_features[feature];
+	struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
+	u32 buf_size_dwords;
+	enum dbg_status rc;
+
+	if (!p_ptt)
+		return -EINVAL;
+
+	rc = qed_features_lookup[feature].get_size(p_hwfn, p_ptt,
+						   &buf_size_dwords);
+	if (rc != DBG_STATUS_OK)
+		buf_size_dwords = 0;
+
+	/* Feature will not be dumped if it exceeds maximum size */
+	if (buf_size_dwords > MAX_DBG_FEATURE_SIZE_DWORDS)
+		buf_size_dwords = 0;
+
+	ecore_ptt_release(p_hwfn, p_ptt);
+	qed_feature->buf_size = buf_size_dwords * sizeof(u32);
+	return qed_feature->buf_size;
+}
+
+u8 qed_get_debug_engine(struct ecore_dev *edev)
+{
+	return edev->dbg_params.engine_for_debug;
+}
+
+void qed_set_debug_engine(struct ecore_dev *edev, int engine_number)
+{
+	DP_VERBOSE(edev, ECORE_MSG_DEBUG, "set debug engine to %d\n",
+		   engine_number);
+	edev->dbg_params.engine_for_debug = engine_number;
+}
+
+void qed_dbg_pf_init(struct ecore_dev *edev)
+{
+	const u8 *dbg_values = NULL;
+	int i;
+
+	PMD_INIT_FUNC_TRACE(edev);
+
+	OSAL_MUTEX_INIT(&edev->dbg_lock);
+
+	/* Sync ver with debugbus qed code */
+	qed_dbg_set_app_ver(TOOLS_VERSION);
+
+	/* Debug values are after init values.
+	 * The offset is the first dword of the file.
+	 */
+	/* TBD: change hardcoded value to offset from FW file */
+	dbg_values = (const u8 *)edev->firmware + 1337296;
+
+	for_each_hwfn(edev, i) {
+		qed_dbg_set_bin_ptr(&edev->hwfns[i], dbg_values);
+		qed_dbg_user_set_bin_ptr(&edev->hwfns[i], dbg_values);
+	}
+
+	/* Set the hwfn to be 0 as default */
+	edev->dbg_params.engine_for_debug = 0;
+}
+
+void qed_dbg_pf_exit(struct ecore_dev *edev)
+{
+	struct ecore_dbg_feature *feature = NULL;
+	enum ecore_dbg_features feature_idx;
+
+	PMD_INIT_FUNC_TRACE(edev);
+
+	/* debug features' buffers may be allocated if debug feature was used
+	 * but dump wasn't called
+	 */
+	for (feature_idx = 0; feature_idx < DBG_FEATURE_NUM; feature_idx++) {
+		feature = &edev->dbg_features[feature_idx];
+		if (feature->dump_buf) {
+			OSAL_VFREE(edev, feature->dump_buf);
+			feature->dump_buf = NULL;
+		}
+	}
+
+	OSAL_MUTEX_DEALLOC(&edev->dbg_lock);
+}
diff --git a/drivers/net/qede/qede_debug.h b/drivers/net/qede/qede_debug.h
new file mode 100644
index 000000000..93e1bd710
--- /dev/null
+++ b/drivers/net/qede/qede_debug.h
@@ -0,0 +1,759 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Marvell Semiconductor Inc.
+ * All rights reserved.
+ * www.marvell.com
+ */
+
+#ifndef _QED_DEBUG_H
+#define _QED_DEBUG_H
+
+/* Forward Declaration */
+struct ecore_dev;
+enum ecore_dbg_features;
+
+int qed_dbg_grc(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes);
+int qed_dbg_grc_size(struct ecore_dev *edev);
+int qed_dbg_idle_chk(struct ecore_dev *edev, void *buffer,
+		     u32 *num_dumped_bytes);
+int qed_dbg_idle_chk_size(struct ecore_dev *edev);
+int qed_dbg_reg_fifo(struct ecore_dev *edev, void *buffer,
+		     u32 *num_dumped_bytes);
+int qed_dbg_reg_fifo_size(struct ecore_dev *edev);
+int qed_dbg_igu_fifo(struct ecore_dev *edev, void *buffer,
+		     u32 *num_dumped_bytes);
+int qed_dbg_igu_fifo_size(struct ecore_dev *edev);
+int qed_dbg_protection_override(struct ecore_dev *edev, void *buffer,
+				u32 *num_dumped_bytes);
+int qed_dbg_protection_override_size(struct ecore_dev *edev);
+int qed_dbg_fw_asserts(struct ecore_dev *edev, void *buffer,
+		       u32 *num_dumped_bytes);
+int qed_dbg_fw_asserts_size(struct ecore_dev *edev);
+int qed_dbg_ilt(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes);
+int qed_dbg_ilt_size(struct ecore_dev *edev);
+int qed_dbg_mcp_trace(struct ecore_dev *edev, void *buffer,
+		      u32 *num_dumped_bytes);
+int qed_dbg_mcp_trace_size(struct ecore_dev *edev);
+int qed_dbg_all_data(struct ecore_dev *edev, void *buffer);
+int qed_dbg_all_data_size(struct ecore_dev *edev);
+u8 qed_get_debug_engine(struct ecore_dev *edev);
+void qed_set_debug_engine(struct ecore_dev *edev, int engine_number);
+int qed_dbg_feature(struct ecore_dev *edev, void *buffer,
+		    enum ecore_dbg_features feature, u32 *num_dumped_bytes);
+int
+qed_dbg_feature_size(struct ecore_dev *edev, enum ecore_dbg_features feature);
+
+void qed_dbg_pf_init(struct ecore_dev *edev);
+void qed_dbg_pf_exit(struct ecore_dev *edev);
+
+/***************************** Public Functions *******************************/
+
+/**
+ * @brief qed_dbg_set_bin_ptr - Sets a pointer to the binary data with debug
+ *	arrays.
+ *
+ * @param p_hwfn -	    HW device data
+ * @param bin_ptr - a pointer to the binary data with debug arrays.
+ */
+enum dbg_status qed_dbg_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+				    const u8 * const bin_ptr);
+
+/**
+ * @brief qed_dbg_set_app_ver - Sets the version of the calling app.
+ *
+ * The application should call this function with the TOOLS_VERSION
+ * it compiles with. Must be called before all other debug functions.
+ *
+ * @return error if one of the following holds:
+ *      - the specified app version is not supported
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_set_app_ver(u32 ver);
+
+/**
+ * @brief qed_read_regs - Reads registers into a buffer (using GRC).
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf - Destination buffer.
+ * @param addr - Source GRC address in dwords.
+ * @param len - Number of registers to read.
+ */
+void qed_read_regs(struct ecore_hwfn *p_hwfn,
+		   struct ecore_ptt *p_ptt, u32 *buf, u32 addr, u32 len);
+
+/**
+ * @brief qed_read_fw_info - Reads FW info from the chip.
+ *
+ * The FW info contains FW-related information, such as the FW version,
+ * FW image (main/L2B/kuku), FW timestamp, etc.
+ * The FW info is read from the internal RAM of the first Storm that is not in
+ * reset.
+ *
+ * @param p_hwfn -	    HW device data
+ * @param p_ptt -	    Ptt window used for writing the registers.
+ * @param fw_info -	Out: a pointer to write the FW info into.
+ *
+ * @return true if the FW info was read successfully from one of the Storms,
+ * or false if all Storms are in reset.
+ */
+bool qed_read_fw_info(struct ecore_hwfn *p_hwfn,
+		      struct ecore_ptt *p_ptt, struct fw_info *fw_info);
+/**
+ * @brief qed_dbg_grc_config - Sets the value of a GRC parameter.
+ *
+ * @param p_hwfn -	HW device data
+ * @param grc_param -	GRC parameter
+ * @param val -		Value to set.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- grc_param is invalid
+ *	- val is outside the allowed boundaries
+ */
+enum dbg_status qed_dbg_grc_config(struct ecore_hwfn *p_hwfn,
+				   enum dbg_grc_params grc_param, u32 val);
+
+/**
+ * @brief qed_dbg_grc_set_params_default - Reverts all GRC parameters to their
+ *	default value.
+ *
+ * @param p_hwfn		- HW device data
+ */
+void qed_dbg_grc_set_params_default(struct ecore_hwfn *p_hwfn);
+/**
+ * @brief qed_dbg_grc_get_dump_buf_size - Returns the required buffer size for
+ *	GRC Dump.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for the GRC Dump
+ *	data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_grc_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size);
+
+/**
+ * @brief qed_dbg_grc_dump - Dumps GRC data into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the collected GRC data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified dump buffer is too small
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_grc_dump(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf,
+				 u32 buf_size_in_dwords,
+				 u32 *num_dumped_dwords);
+/**
+ * @brief qed_dbg_idle_chk_get_dump_buf_size - Returns the required buffer size
+ *	for idle check results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for the idle check
+ *	data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_idle_chk_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size);
+
+/**
+ * @brief qed_dbg_idle_chk_dump - Performs idle check and writes the results
+ *	into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the idle check data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_mcp_trace_get_dump_buf_size - Returns the required buffer size
+ *	for mcp trace results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for mcp trace data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the trace data in MCP scratchpad contain an invalid signature
+ *	- the bundle ID in NVRAM is invalid
+ *	- the trace meta data cannot be found (in NVRAM or image file)
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_mcp_trace_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						    struct ecore_ptt *p_ptt,
+						    u32 *buf_size);
+
+/**
+ * @brief qed_dbg_mcp_trace_dump - Performs mcp trace and writes the results
+ *	into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the mcp trace data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- the trace data in MCP scratchpad contain an invalid signature
+ *	- the bundle ID in NVRAM is invalid
+ *	- the trace meta data cannot be found (in NVRAM or image file)
+ *	- the trace meta data cannot be read (from NVRAM or image file)
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+				       struct ecore_ptt *p_ptt,
+				       u32 *dump_buf,
+				       u32 buf_size_in_dwords,
+				       u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_reg_fifo_get_dump_buf_size - Returns the required buffer size
+ *	for grc trace fifo results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for reg fifo data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_reg_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size);
+
+/**
+ * @brief qed_dbg_reg_fifo_dump - Reads the reg fifo and writes the results into
+ *	the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the reg fifo data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- DMAE transaction failed
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_igu_fifo_get_dump_buf_size - Returns the required buffer size
+ *	for the IGU fifo results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for the IGU fifo
+ *	data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_igu_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size);
+
+/**
+ * @brief qed_dbg_igu_fifo_dump - Reads the IGU fifo and writes the results into
+ *	the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the IGU fifo data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- DMAE transaction failed
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_protection_override_get_dump_buf_size - Returns the required
+ *	buffer size for protection override window results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for protection
+ *	override data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status
+qed_dbg_protection_override_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size);
+/**
+ * @brief qed_dbg_protection_override_dump - Reads protection override window
+ *	entries and writes the results into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the protection override data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- DMAE transaction failed
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_protection_override_dump(struct ecore_hwfn *p_hwfn,
+						 struct ecore_ptt *p_ptt,
+						 u32 *dump_buf,
+						 u32 buf_size_in_dwords,
+						 u32 *num_dumped_dwords);
+/**
+ * @brief qed_dbg_fw_asserts_get_dump_buf_size - Returns the required buffer
+ *	size for FW Asserts results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for FW Asserts data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_fw_asserts_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						     struct ecore_ptt *p_ptt,
+						     u32 *buf_size);
+/**
+ * @brief qed_dbg_fw_asserts_dump - Reads the FW Asserts and writes the results
+ *	into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the FW Asserts data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf,
+					u32 buf_size_in_dwords,
+					u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_read_attn - Reads the attention registers of the specified
+ * block and type, and writes the results into the specified buffer.
+ *
+ * @param p_hwfn -	 HW device data
+ * @param p_ptt -	 Ptt window used for writing the registers.
+ * @param block -	 Block ID.
+ * @param attn_type -	 Attention type.
+ * @param clear_status - Indicates if the attention status should be cleared.
+ * @param results -	 OUT: Pointer to write the read results into
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_read_attn(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  enum block_id block,
+				  enum dbg_attn_type attn_type,
+				  bool clear_status,
+				  struct dbg_attn_block_result *results);
+
+/**
+ * @brief qed_dbg_print_attn - Prints attention registers values in the
+ *	specified results struct.
+ *
+ * @param p_hwfn
+ * @param results - Pointer to the attention read results
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_print_attn(struct ecore_hwfn *p_hwfn,
+				   struct dbg_attn_block_result *results);
+
+/******************************* Data Types **********************************/
+
+struct mcp_trace_format {
+	u32 data;
+#define MCP_TRACE_FORMAT_MODULE_MASK	0x0000ffff
+#define MCP_TRACE_FORMAT_MODULE_OFFSET	0
+#define MCP_TRACE_FORMAT_LEVEL_MASK	0x00030000
+#define MCP_TRACE_FORMAT_LEVEL_OFFSET	16
+#define MCP_TRACE_FORMAT_P1_SIZE_MASK	0x000c0000
+#define MCP_TRACE_FORMAT_P1_SIZE_OFFSET 18
+#define MCP_TRACE_FORMAT_P2_SIZE_MASK	0x00300000
+#define MCP_TRACE_FORMAT_P2_SIZE_OFFSET 20
+#define MCP_TRACE_FORMAT_P3_SIZE_MASK	0x00c00000
+#define MCP_TRACE_FORMAT_P3_SIZE_OFFSET 22
+#define MCP_TRACE_FORMAT_LEN_MASK	0xff000000
+#define MCP_TRACE_FORMAT_LEN_OFFSET	24
+
+	char *format_str;
+};
+
+/* MCP Trace Meta data structure */
+struct mcp_trace_meta {
+	u32 modules_num;
+	char **modules;
+	u32 formats_num;
+	struct mcp_trace_format *formats;
+	bool is_allocated;
+};
+
+/* Debug Tools user data */
+struct dbg_tools_user_data {
+	struct mcp_trace_meta mcp_trace_meta;
+	const u32 *mcp_trace_user_meta_buf;
+};
+
+/******************************** Constants **********************************/
+
+#define MAX_NAME_LEN	16
+
+/***************************** Public Functions *******************************/
+
+/**
+ * @brief qed_dbg_user_set_bin_ptr - Sets a pointer to the binary data with
+ *	debug arrays.
+ *
+ * @param p_hwfn - HW device data
+ * @param bin_ptr - a pointer to the binary data with debug arrays.
+ */
+enum dbg_status qed_dbg_user_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+					 const u8 * const bin_ptr);
+
+/**
+ * @brief qed_dbg_alloc_user_data - Allocates user debug data.
+ *
+ * @param p_hwfn -		 HW device data
+ * @param user_data_ptr - OUT: a pointer to the allocated memory.
+ */
+enum dbg_status qed_dbg_alloc_user_data(struct ecore_hwfn *p_hwfn,
+					void **user_data_ptr);
+
+/**
+ * @brief qed_dbg_get_status_str - Returns a string for the specified status.
+ *
+ * @param status - a debug status code.
+ *
+ * @return a string for the specified status
+ */
+const char *qed_dbg_get_status_str(enum dbg_status status);
+
+/**
+ * @brief qed_get_idle_chk_results_buf_size - Returns the required buffer size
+ *	for idle check results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - idle check dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_idle_chk_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32  num_dumped_dwords,
+						  u32 *results_buf_size);
+/**
+ * @brief qed_print_idle_chk_results - Prints idle check results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - idle check dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the idle check results.
+ * @param num_errors - OUT: number of errors found in idle check.
+ * @param num_warnings - OUT: number of warnings found in idle check.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_idle_chk_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf,
+					   u32 *num_errors,
+					   u32 *num_warnings);
+
+/**
+ * @brief qed_dbg_mcp_trace_set_meta_data - Sets the MCP Trace meta data.
+ *
+ * Needed in case the MCP Trace dump doesn't contain the meta data (e.g. due to
+ * no NVRAM access).
+ *
+ * @param data - pointer to MCP Trace meta data
+ * @param size - size of MCP Trace meta data in dwords
+ */
+void qed_dbg_mcp_trace_set_meta_data(struct ecore_hwfn *p_hwfn,
+				     const u32 *meta_buf);
+
+/**
+ * @brief qed_get_mcp_trace_results_buf_size - Returns the required buffer size
+ *	for MCP Trace results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - MCP Trace dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_mcp_trace_results_buf_size(struct ecore_hwfn *p_hwfn,
+						   u32 *dump_buf,
+						   u32 num_dumped_dwords,
+						   u32 *results_buf_size);
+
+/**
+ * @brief qed_print_mcp_trace_results - Prints MCP Trace results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - mcp trace dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the mcp trace results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_mcp_trace_results(struct ecore_hwfn *p_hwfn,
+					    u32 *dump_buf,
+					    u32 num_dumped_dwords,
+					    char *results_buf);
+
+/**
+ * @brief qed_print_mcp_trace_results_cont - Prints MCP Trace results, and
+ * keeps the MCP trace meta data allocated, to support continuous MCP Trace
+ * parsing. After the continuous parsing ends, mcp_trace_free_meta_data should
+ * be called to free the meta data.
+ *
+ * @param p_hwfn -	      HW device data
+ * @param dump_buf -	      mcp trace dump buffer, starting from the header.
+ * @param results_buf -	      buffer for printing the mcp trace results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_mcp_trace_results_cont(struct ecore_hwfn *p_hwfn,
+						 u32 *dump_buf,
+						 char *results_buf);
+
+/**
+ * @brief print_mcp_trace_line - Prints MCP Trace results for a single line
+ *
+ * @param p_hwfn -	      HW device data
+ * @param dump_buf -	      mcp trace dump buffer, starting from the header.
+ * @param num_dumped_bytes -  number of bytes that were dumped.
+ * @param results_buf -	      buffer for printing the mcp trace results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_mcp_trace_line(struct ecore_hwfn *p_hwfn,
+					 u8 *dump_buf,
+					 u32 num_dumped_bytes,
+					 char *results_buf);
+
+/**
+ * @brief mcp_trace_free_meta_data - Frees the MCP Trace meta data.
+ * Should be called after continuous MCP Trace parsing.
+ *
+ * @param p_hwfn - HW device data
+ */
+void qed_mcp_trace_free_meta_data(struct ecore_hwfn *p_hwfn);
+
+/**
+ * @brief qed_get_reg_fifo_results_buf_size - Returns the required buffer size
+ *	for reg_fifo results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - reg fifo dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_reg_fifo_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32 num_dumped_dwords,
+						  u32 *results_buf_size);
+
+/**
+ * @brief qed_print_reg_fifo_results - Prints reg fifo results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - reg fifo dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the reg fifo results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_reg_fifo_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf);
+
+/**
+ * @brief qed_get_igu_fifo_results_buf_size - Returns the required buffer size
+ *	for igu_fifo results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - IGU fifo dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_igu_fifo_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32 num_dumped_dwords,
+						  u32 *results_buf_size);
+
+/**
+ * @brief qed_print_igu_fifo_results - Prints IGU fifo results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - IGU fifo dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the IGU fifo results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_igu_fifo_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf);
+
+/**
+ * @brief qed_get_protection_override_results_buf_size - Returns the required
+ *	buffer size for protection override results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - protection override dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status
+qed_get_protection_override_results_buf_size(struct ecore_hwfn *p_hwfn,
+					     u32 *dump_buf,
+					     u32 num_dumped_dwords,
+					     u32 *results_buf_size);
+
+/**
+ * @brief qed_print_protection_override_results - Prints protection override
+ *	results.
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - protection override dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the reg fifo results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_protection_override_results(struct ecore_hwfn *p_hwfn,
+						      u32 *dump_buf,
+						      u32 num_dumped_dwords,
+						      char *results_buf);
+
+/**
+ * @brief qed_get_fw_asserts_results_buf_size - Returns the required buffer size
+ *	for FW Asserts results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - FW Asserts dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_fw_asserts_results_buf_size(struct ecore_hwfn *p_hwfn,
+						    u32 *dump_buf,
+						    u32 num_dumped_dwords,
+						    u32 *results_buf_size);
+
+/**
+ * @brief qed_print_fw_asserts_results - Prints FW Asserts results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - FW Asserts dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the FW Asserts results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_fw_asserts_results(struct ecore_hwfn *p_hwfn,
+					     u32 *dump_buf,
+					     u32 num_dumped_dwords,
+					     char *results_buf);
+
+/**
+ * @brief qed_dbg_parse_attn - Parses and prints attention registers values in
+ * the specified results struct.
+ *
+ * @param p_hwfn -  HW device data
+ * @param results - Pointer to the attention read results
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_parse_attn(struct ecore_hwfn *p_hwfn,
+				   struct dbg_attn_block_result *results);
+
+#endif
diff --git a/drivers/net/qede/qede_if.h b/drivers/net/qede/qede_if.h
index 858cd51d5..c5ae3fb2e 100644
--- a/drivers/net/qede/qede_if.h
+++ b/drivers/net/qede/qede_if.h
@@ -189,6 +189,51 @@ struct qed_common_ops {
 			      uint32_t dp_module, uint8_t dp_level);
 
 	int (*send_drv_state)(struct ecore_dev *edev, bool active);
+
+	/* ###############  DEBUG *************************/
+
+	int     (*dbg_grc)(struct ecore_dev       *edev,
+			   void		 *buffer,
+			   u32		  *num_dumped_bytes);
+	int     (*dbg_grc_size)(struct ecore_dev *edev);
+
+	int     (*dbg_idle_chk)(struct ecore_dev  *edev,
+				void	    *buffer,
+				u32	     *num_dumped_bytes);
+	int     (*dbg_idle_chk_size)(struct ecore_dev *edev);
+
+	int     (*dbg_reg_fifo)(struct ecore_dev  *edev,
+				void	    *buffer,
+				u32	     *num_dumped_bytes);
+	int     (*dbg_reg_fifo_size)(struct ecore_dev *edev);
+
+	int     (*dbg_mcp_trace)(struct ecore_dev *edev,
+				 void	   *buffer,
+				 u32	    *num_dumped_bytes);
+	int     (*dbg_mcp_trace_size)(struct ecore_dev *edev);
+
+	int	(*dbg_protection_override)(struct ecore_dev *edev, void *buffer,
+					   u32 *num_dumped_bytes);
+	int     (*dbg_protection_override_size)(struct ecore_dev *edev);
+
+	int	(*dbg_igu_fifo_size)(struct ecore_dev *edev);
+	int	(*dbg_igu_fifo)(struct ecore_dev *edev, void *buffer,
+				u32 *num_dumped_bytes);
+
+	int	(*dbg_fw_asserts)(struct ecore_dev *edev, void *buffer,
+				  u32 *num_dumped_bytes);
+
+	int	(*dbg_fw_asserts_size)(struct ecore_dev *edev);
+
+	int	(*dbg_ilt)(struct ecore_dev *edev, void *buffer,
+			   u32 *num_dumped_bytes);
+
+	int	(*dbg_ilt_size)(struct ecore_dev *edev);
+
+	u8      (*dbg_get_debug_engine)(struct ecore_dev *edev);
+	void    (*dbg_set_debug_engine)(struct ecore_dev  *edev,
+					int	     engine_number);
+
 };
 
 /* Externs */
diff --git a/drivers/net/qede/qede_main.c b/drivers/net/qede/qede_main.c
index 51aa639c6..987a6f1e1 100644
--- a/drivers/net/qede/qede_main.c
+++ b/drivers/net/qede/qede_main.c
@@ -9,6 +9,8 @@
 #include <rte_string_fns.h>
 
 #include "qede_ethdev.h"
+/* ######### DEBUG ###########*/
+#include "qede_debug.h"
 
 /* Alarm timeout. */
 #define QEDE_ALARM_TIMEOUT_US 100000
@@ -276,10 +278,15 @@ static int qed_slowpath_start(struct ecore_dev *edev,
 	qed_start_iov_task(edev);
 
 #ifdef CONFIG_ECORE_BINARY_FW
-	if (IS_PF(edev))
+	if (IS_PF(edev)) {
 		data = (const uint8_t *)edev->firmware + sizeof(u32);
+
+		/* ############### DEBUG ################## */
+		qed_dbg_pf_init(edev);
+	}
 #endif
 
+
 	/* Start the slowpath */
 	memset(&hw_init_params, 0, sizeof(hw_init_params));
 	hw_init_params.b_hw_start = true;
@@ -779,6 +786,36 @@ const struct qed_common_ops qed_common_ops_pass = {
 	INIT_STRUCT_FIELD(slowpath_stop, &qed_slowpath_stop),
 	INIT_STRUCT_FIELD(remove, &qed_remove),
 	INIT_STRUCT_FIELD(send_drv_state, &qed_send_drv_state),
+	/* ############### DEBUG ####################*/
+
+	INIT_STRUCT_FIELD(dbg_get_debug_engine, &qed_get_debug_engine),
+	INIT_STRUCT_FIELD(dbg_set_debug_engine, &qed_set_debug_engine),
+
+	INIT_STRUCT_FIELD(dbg_protection_override,
+			  &qed_dbg_protection_override),
+	INIT_STRUCT_FIELD(dbg_protection_override_size,
+			  &qed_dbg_protection_override_size),
+
+	INIT_STRUCT_FIELD(dbg_grc, &qed_dbg_grc),
+	INIT_STRUCT_FIELD(dbg_grc_size, &qed_dbg_grc_size),
+
+	INIT_STRUCT_FIELD(dbg_idle_chk, &qed_dbg_idle_chk),
+	INIT_STRUCT_FIELD(dbg_idle_chk_size, &qed_dbg_idle_chk_size),
+
+	INIT_STRUCT_FIELD(dbg_mcp_trace, &qed_dbg_mcp_trace),
+	INIT_STRUCT_FIELD(dbg_mcp_trace_size, &qed_dbg_mcp_trace_size),
+
+	INIT_STRUCT_FIELD(dbg_fw_asserts, &qed_dbg_fw_asserts),
+	INIT_STRUCT_FIELD(dbg_fw_asserts_size, &qed_dbg_fw_asserts_size),
+
+	INIT_STRUCT_FIELD(dbg_ilt, &qed_dbg_ilt),
+	INIT_STRUCT_FIELD(dbg_ilt_size, &qed_dbg_ilt_size),
+
+	INIT_STRUCT_FIELD(dbg_reg_fifo_size, &qed_dbg_reg_fifo_size),
+	INIT_STRUCT_FIELD(dbg_reg_fifo, &qed_dbg_reg_fifo),
+
+	INIT_STRUCT_FIELD(dbg_igu_fifo_size, &qed_dbg_igu_fifo_size),
+	INIT_STRUCT_FIELD(dbg_igu_fifo, &qed_dbg_igu_fifo),
 };
 
 const struct qed_eth_ops qed_eth_ops_pass = {
-- 
2.18.0


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

* [dpdk-dev] [PATCH v4 4/4] net/qede: add support for get register operation
  2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 " Rasesh Mody
                       ` (3 preceding siblings ...)
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 3/4] net/qede: add infrastructure " Rasesh Mody
@ 2020-07-07 21:16     ` Rasesh Mody
  2020-07-08  9:29       ` Jerin Jacob
  4 siblings, 1 reply; 37+ messages in thread
From: Rasesh Mody @ 2020-07-07 21:16 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

Add support for .get_reg eth_dev ops which will be used to collect the
firmware debug data.

PMD on detecting on some HW errors will collect the FW/HW Dump to a
buffer and then it will save it to a file implemented in
qede_save_fw_dump().

Dump file location and name:
Location: <RTE_SDK> or DPDK root
Name: qede_pmd_dump_mm-dd-yy_hh-mm-ss.bin

DPDK applications can initiate a debug data collection by invoking DPDK
library’s rte_eth_dev_get_reg_info() API. This API invokes .get_reg()
interface in the PMD.

PMD implementation of .get_reg() collects the FW/HW Dump, saves it to
data field of rte_dev_reg_info and passes it to the application. It’s
the responsibility of the application to save the FW/HW Dump to a file.
We recommendation using the file name format used by qede_save_fw_dump().

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 doc/guides/nics/features/qede.ini |   1 +
 drivers/net/qede/Makefile         |   1 +
 drivers/net/qede/base/bcm_osal.c  |  25 +++
 drivers/net/qede/base/bcm_osal.h  |   5 +
 drivers/net/qede/qede_ethdev.c    |   1 +
 drivers/net/qede/qede_ethdev.h    |  25 +++
 drivers/net/qede/qede_regs.c      | 271 ++++++++++++++++++++++++++++++
 7 files changed, 329 insertions(+)
 create mode 100644 drivers/net/qede/qede_regs.c

diff --git a/doc/guides/nics/features/qede.ini b/doc/guides/nics/features/qede.ini
index 20c90e626..f8716523e 100644
--- a/doc/guides/nics/features/qede.ini
+++ b/doc/guides/nics/features/qede.ini
@@ -31,6 +31,7 @@ Packet type parsing  = Y
 Basic stats          = Y
 Extended stats       = Y
 Stats per queue      = Y
+Registers dump       = Y
 Multiprocess aware   = Y
 Linux UIO            = Y
 Linux VFIO           = Y
diff --git a/drivers/net/qede/Makefile b/drivers/net/qede/Makefile
index 3b00338ff..0e8a67b0d 100644
--- a/drivers/net/qede/Makefile
+++ b/drivers/net/qede/Makefile
@@ -104,5 +104,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_main.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_rxtx.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_filter.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_debug.c
+SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_regs.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/qede/base/bcm_osal.c b/drivers/net/qede/base/bcm_osal.c
index 45557fe3c..65837b53d 100644
--- a/drivers/net/qede/base/bcm_osal.c
+++ b/drivers/net/qede/base/bcm_osal.c
@@ -246,6 +246,28 @@ qede_get_mcp_proto_stats(struct ecore_dev *edev,
 	}
 }
 
+static void qede_hw_err_handler(void *dev, enum ecore_hw_err_type err_type)
+{
+	struct ecore_dev *edev = dev;
+
+	switch (err_type) {
+	case ECORE_HW_ERR_FAN_FAIL:
+		break;
+
+	case ECORE_HW_ERR_MFW_RESP_FAIL:
+	case ECORE_HW_ERR_HW_ATTN:
+	case ECORE_HW_ERR_DMAE_FAIL:
+	case ECORE_HW_ERR_RAMROD_FAIL:
+	case ECORE_HW_ERR_FW_ASSERT:
+		OSAL_SAVE_FW_DUMP(0); /* Using port 0 as default port_id */
+		break;
+
+	default:
+		DP_NOTICE(edev, false, "Unknown HW error [%d]\n", err_type);
+		return;
+	}
+}
+
 void
 qede_hw_err_notify(struct ecore_hwfn *p_hwfn, enum ecore_hw_err_type err_type)
 {
@@ -275,6 +297,9 @@ qede_hw_err_notify(struct ecore_hwfn *p_hwfn, enum ecore_hw_err_type err_type)
 	}
 
 	DP_ERR(p_hwfn, "HW error occurred [%s]\n", err_str);
+
+	qede_hw_err_handler(p_hwfn->p_dev, err_type);
+
 	ecore_int_attn_clr_enable(p_hwfn->p_dev, true);
 }
 
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index b4b94231b..5d4df5907 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -371,6 +371,11 @@ void qede_hw_err_notify(struct ecore_hwfn *p_hwfn,
 
 /* TODO: */
 #define OSAL_SCHEDULE_RECOVERY_HANDLER(hwfn) nothing
+
+int qede_save_fw_dump(uint8_t port_id);
+
+#define OSAL_SAVE_FW_DUMP(port_id) qede_save_fw_dump(port_id)
+
 #define OSAL_HW_ERROR_OCCURRED(hwfn, err_type) \
 	qede_hw_err_notify(hwfn, err_type)
 
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index b5d6c7c43..e5a2581dd 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -2426,6 +2426,7 @@ static const struct eth_dev_ops qede_eth_dev_ops = {
 	.udp_tunnel_port_add = qede_udp_dst_port_add,
 	.udp_tunnel_port_del = qede_udp_dst_port_del,
 	.fw_version_get = qede_fw_version_get,
+	.get_reg = qede_get_regs,
 };
 
 static const struct eth_dev_ops qede_eth_vf_dev_ops = {
diff --git a/drivers/net/qede/qede_ethdev.h b/drivers/net/qede/qede_ethdev.h
index b988a73f2..76c5dae3b 100644
--- a/drivers/net/qede/qede_ethdev.h
+++ b/drivers/net/qede/qede_ethdev.h
@@ -214,6 +214,8 @@ struct qede_tunn_params {
 	uint16_t udp_port;
 };
 
+#define QEDE_FW_DUMP_FILE_SIZE 128
+
 /*
  *  Structure to store private data for each port.
  */
@@ -252,6 +254,7 @@ struct qede_dev {
 	char drv_ver[QEDE_PMD_DRV_VER_STR_SIZE];
 	bool vport_started;
 	int vlan_offload_mask;
+	char dump_file[QEDE_FW_DUMP_FILE_SIZE];
 	void *ethdev;
 };
 
@@ -313,4 +316,26 @@ void qede_config_accept_any_vlan(struct qede_dev *qdev, bool flg);
 int qede_ucast_filter(struct rte_eth_dev *eth_dev,
 		      struct ecore_filter_ucast *ucast,
 		      bool add);
+
+#define REGDUMP_HEADER_SIZE sizeof(u32)
+#define REGDUMP_HEADER_FEATURE_SHIFT 24
+#define REGDUMP_HEADER_ENGINE_SHIFT 31
+#define REGDUMP_HEADER_OMIT_ENGINE_SHIFT 30
+
+enum debug_print_features {
+	OLD_MODE = 0,
+	IDLE_CHK = 1,
+	GRC_DUMP = 2,
+	MCP_TRACE = 3,
+	REG_FIFO = 4,
+	PROTECTION_OVERRIDE = 5,
+	IGU_FIFO = 6,
+	PHY = 7,
+	FW_ASSERTS = 8,
+};
+
+int qede_get_regs_len(struct qede_dev *qdev);
+int qede_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs);
+void qede_config_rx_mode(struct rte_eth_dev *eth_dev);
+void qed_dbg_dump(struct rte_eth_dev *eth_dev);
 #endif /* _QEDE_ETHDEV_H_ */
diff --git a/drivers/net/qede/qede_regs.c b/drivers/net/qede/qede_regs.c
new file mode 100644
index 000000000..4409d2180
--- /dev/null
+++ b/drivers/net/qede/qede_regs.c
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Marvell Semiconductor Inc.
+ * All rights reserved.
+ * www.marvell.com
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <time.h>
+#include <rte_ethdev.h>
+#include "base/bcm_osal.h"
+#include "qede_ethdev.h"
+
+int
+qede_get_regs_len(struct qede_dev *qdev)
+{
+	struct ecore_dev *edev = &qdev->edev;
+	int cur_engine, num_of_hwfns, regs_len = 0;
+	uint8_t org_engine;
+
+	if (IS_VF(edev))
+		return 0;
+
+	if (qdev->ops && qdev->ops->common) {
+		num_of_hwfns = qdev->dev_info.common.num_hwfns;
+		org_engine = qdev->ops->common->dbg_get_debug_engine(edev);
+		for (cur_engine = 0; cur_engine < num_of_hwfns; cur_engine++) {
+			/* compute required buffer size for idle_chks and
+			 * grcDump for each hw function
+			 */
+			DP_NOTICE(edev, false,
+				"Calculating idle_chk and grcdump register length for current engine\n");
+			qdev->ops->common->dbg_set_debug_engine(edev,
+								cur_engine);
+			regs_len += REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_idle_chk_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_idle_chk_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_grc_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_reg_fifo_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_protection_override_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_igu_fifo_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_fw_asserts_size(edev);
+		}
+		/* compute required buffer size for mcp trace and add it to the
+		 * total required buffer size
+		 */
+		regs_len += REGDUMP_HEADER_SIZE +
+			    qdev->ops->common->dbg_mcp_trace_size(edev);
+
+		qdev->ops->common->dbg_set_debug_engine(edev, org_engine);
+	}
+	DP_NOTICE(edev, false, "Total length = %u\n", regs_len);
+
+	return regs_len;
+}
+
+static uint32_t
+qede_calc_regdump_header(enum debug_print_features feature, int engine,
+			 uint32_t feature_size, uint8_t omit_engine)
+{
+	/* insert the engine, feature and mode inside the header and
+	 * combine it with feature size
+	 */
+	return (feature_size | (feature << REGDUMP_HEADER_FEATURE_SHIFT) |
+		(omit_engine << REGDUMP_HEADER_OMIT_ENGINE_SHIFT) |
+		(engine << REGDUMP_HEADER_ENGINE_SHIFT));
+}
+
+int qede_get_regs(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs)
+{
+	struct qede_dev *qdev = eth_dev->data->dev_private;
+	struct ecore_dev *edev = &qdev->edev;
+	uint32_t *buffer = regs->data;
+	int cur_engine, num_of_hwfns;
+	/* '1' tells the parser to omit the engine number in the output files */
+	uint8_t omit_engine = 0;
+	uint8_t org_engine;
+	uint32_t feature_size;
+	uint32_t offset = 0;
+
+	if (IS_VF(edev))
+		return -ENOTSUP;
+
+	if (buffer == NULL) {
+		regs->length = qede_get_regs_len(qdev);
+		regs->width =  sizeof(uint32_t);
+		DP_INFO(edev, "Length %u\n", regs->length);
+		return 0;
+	}
+
+	memset(buffer, 0, regs->length);
+	num_of_hwfns = qdev->dev_info.common.num_hwfns;
+	if (num_of_hwfns == 1)
+		omit_engine = 1;
+
+	OSAL_MUTEX_ACQUIRE(&edev->dbg_lock);
+
+	org_engine = qdev->ops->common->dbg_get_debug_engine(edev);
+	for (cur_engine = 0; cur_engine < num_of_hwfns; cur_engine++) {
+		/* collect idle_chks and grcDump for each hw function */
+		DP_NOTICE(edev, false, "obtaining idle_chk and grcdump for current engine\n");
+		qdev->ops->common->dbg_set_debug_engine(edev, cur_engine);
+
+		/* first idle_chk */
+		qdev->ops->common->dbg_idle_chk(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(IDLE_CHK, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Idle Check1 feature_size %u\n",
+			  feature_size);
+
+		/* second idle_chk */
+		qdev->ops->common->dbg_idle_chk(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(IDLE_CHK, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Idle Check2 feature_size %u\n",
+			  feature_size);
+
+		/* reg_fifo dump */
+		qdev->ops->common->dbg_reg_fifo(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(REG_FIFO, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Reg fifo feature_size %u\n",
+			  feature_size);
+
+		/* igu_fifo dump */
+		qdev->ops->common->dbg_igu_fifo(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(IGU_FIFO, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "IGU fifo feature_size %u\n",
+			  feature_size);
+
+		/* protection_override dump */
+		qdev->ops->common->dbg_protection_override(edev,
+							   (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+		       qede_calc_regdump_header(PROTECTION_OVERRIDE, cur_engine,
+						feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Protection override feature_size %u\n",
+			  feature_size);
+
+		/* fw_asserts dump */
+		qdev->ops->common->dbg_fw_asserts(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(FW_ASSERTS, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "FW assert feature_size %u\n",
+			  feature_size);
+
+		/* grc dump */
+		qdev->ops->common->dbg_grc(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(GRC_DUMP, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "GRC dump feature_size %u\n",
+			  feature_size);
+	}
+
+	/* mcp_trace */
+	qdev->ops->common->dbg_mcp_trace(edev, (uint8_t *)buffer +
+		offset + REGDUMP_HEADER_SIZE, &feature_size);
+	*(uint32_t *)((uint8_t *)buffer + offset) =
+		qede_calc_regdump_header(MCP_TRACE, cur_engine, feature_size,
+					 omit_engine);
+	offset += (feature_size + REGDUMP_HEADER_SIZE);
+	DP_NOTICE(edev, false, "MCP trace feature_size %u\n", feature_size);
+
+	qdev->ops->common->dbg_set_debug_engine(edev, org_engine);
+
+	OSAL_MUTEX_RELEASE(&edev->dbg_lock);
+
+	return 0;
+}
+
+static void
+qede_set_fw_dump_file_name(struct qede_dev *qdev)
+{
+	time_t ltime;
+	struct tm *tm;
+
+	ltime = time(NULL);
+	tm = localtime(&ltime);
+	snprintf(qdev->dump_file, QEDE_FW_DUMP_FILE_SIZE,
+		 "qede_pmd_dump_%02d-%02d-%02d_%02d-%02d-%02d.bin",
+		 tm->tm_mon + 1, (int)tm->tm_mday, 1900 + tm->tm_year,
+		 tm->tm_hour, tm->tm_min, tm->tm_sec);
+}
+
+static int
+qede_write_fwdump(const char *dump_file, void *dump, size_t len)
+{
+	int err = 0;
+	FILE *f;
+	size_t bytes;
+
+	f = fopen(dump_file, "wb+");
+
+	if (!f) {
+		fprintf(stderr, "Can't open file %s: %s\n",
+			dump_file, strerror(errno));
+		return 1;
+	}
+	bytes = fwrite(dump, 1, len, f);
+	if (bytes != len) {
+		fprintf(stderr, "Can not write all of dump data bytes=%ld len=%ld\n",
+			bytes, len);
+		err = 1;
+	}
+
+	if (fclose(f)) {
+		fprintf(stderr, "Can't close file %s: %s\n",
+			dump_file, strerror(errno));
+		err = 1;
+	}
+
+	return err;
+}
+
+int
+qede_save_fw_dump(uint8_t port_id)
+{
+	struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id];
+	struct rte_dev_reg_info regs;
+	struct qede_dev *qdev = eth_dev->data->dev_private;
+	struct ecore_dev *edev = &qdev->edev;
+	int rc = 0;
+
+	if (!rte_eth_dev_is_valid_port(port_id)) {
+		DP_ERR(edev, "port %u invalid port ID", port_id);
+		return -ENODEV;
+	}
+
+	memset(&regs, 0, sizeof(regs));
+	regs.length = qede_get_regs_len(qdev);
+	regs.data = OSAL_ZALLOC(eth_dev, GFP_KERNEL, regs.length);
+	if (regs.data) {
+		qede_get_regs(eth_dev, &regs);
+		qede_set_fw_dump_file_name(qdev);
+		rc = qede_write_fwdump(qdev->dump_file, regs.data, regs.length);
+		if (!rc)
+			DP_NOTICE(edev, false, "FW dump written to %s file\n",
+				  qdev->dump_file);
+		OSAL_FREE(edev, regs.data);
+	}
+
+	return rc;
+}
-- 
2.18.0


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

* Re: [dpdk-dev] [EXT] Re: [PATCH v2 1/4] net/qede/base: re-arrange few structures for DDC
  2020-06-30 17:47   ` Jerin Jacob
@ 2020-07-07 21:20     ` Rasesh Mody
  0 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-07-07 21:20 UTC (permalink / raw)
  To: Jerin Jacob
  Cc: Jerin Jacob Kollanukkaran, Ferruh Yigit, dpdk-dev,
	GR-Everest-DPDK-Dev, Igor Russkikh

>From: Jerin Jacob <jerinjacobk@gmail.com>
>Sent: Tuesday, June 30, 2020 10:47 AM
>
>On Tue, Jun 30, 2020 at 2:03 PM Rasesh Mody <rmody@marvell.com> wrote:
>>
>> This patch rearranges some of the base driver structures which will be
>> also used by debug data collection (DDC) implementation. It adds a new
>> file ecore_hsi_func_common.h with Physical, Virtual memory descriptors.
>>
>> Signed-off-by: Rasesh Mody <rmody@marvell.com>
>> Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
>
>
>This series has shared lib failure. GCC version log at [1]
>

Submitted a v4 series with compilation and typos fixed.
Remaining typo warnings are false positive.

Thanks!
-Rasesh


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

* Re: [dpdk-dev] [PATCH v4 4/4] net/qede: add support for get register operation
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 4/4] net/qede: add support for get register operation Rasesh Mody
@ 2020-07-08  9:29       ` Jerin Jacob
  0 siblings, 0 replies; 37+ messages in thread
From: Jerin Jacob @ 2020-07-08  9:29 UTC (permalink / raw)
  To: Rasesh Mody
  Cc: Jerin Jacob, Ferruh Yigit, dpdk-dev, GR-Everest-DPDK-Dev, Igor Russkikh

On Wed, Jul 8, 2020 at 2:47 AM Rasesh Mody <rmody@marvell.com> wrote:
>
> Add support for .get_reg eth_dev ops which will be used to collect the
> firmware debug data.
>
> PMD on detecting on some HW errors will collect the FW/HW Dump to a
> buffer and then it will save it to a file implemented in
> qede_save_fw_dump().
>
> Dump file location and name:
> Location: <RTE_SDK> or DPDK root
> Name: qede_pmd_dump_mm-dd-yy_hh-mm-ss.bin
>
> DPDK applications can initiate a debug data collection by invoking DPDK
> library’s rte_eth_dev_get_reg_info() API. This API invokes .get_reg()
> interface in the PMD.
>
> PMD implementation of .get_reg() collects the FW/HW Dump, saves it to
> data field of rte_dev_reg_info and passes it to the application. It’s
> the responsibility of the application to save the FW/HW Dump to a file.
> We recommendation using the file name format used by qede_save_fw_dump().
>
> Signed-off-by: Rasesh Mody <rmody@marvell.com>
> Signed-off-by: Igor Russkikh <irusskikh@marvell.com>

Found meson build failure with gcc 10. Please check.

meson  -Dexamples=l3fwd --buildtype=debugoptimized --werror
--default-library=static /export/dpdk-next-net-mrvl/devtools/..
./build-gcc-static

gcc  -o drivers/librte_pmd_qede.so.20.0.3
'drivers/a715181@@rte_pmd_qede@sha/meson-generated_.._rte_pmd_qede.pmd.c.o'
'drivers/net/qede/base/f6110d5@@qede_base@sta/bcm_osal.c.o'
'drivers/net/qede/base/f6110d5@@qede_base@sta/ecore_cxt.c.o' '
drivers/net/qede/base/f6110d5@@qede_base@sta/ecore_dcbx.c.o'
'drivers/net/qede/base/f6110d5@@qede_base@sta/ecore_dev.c.o'
'drivers/net/qede/base/f6110d5@@qede_base@sta/ecore_hw.c.o'
'drivers/net/qede/base/f6110d5@@qede_base@sta/ecore_init_f
w_funcs.c.o' 'drivers/net/qede/base/f6110d5@@qede_base@sta/ecore_init_ops.c.o'
'drivers/net/qede/base/f6110d5@@qede_base@sta/ecore_int.c.o'
'drivers/net/qede/base/f6110d5@@qede_base@sta/ecore_l2.c.o'
'drivers/net/qede/base/f6110d5@@qede_bas
e@sta/ecore_mcp.c.o'
'drivers/net/qede/base/f6110d5@@qede_base@sta/ecore_sp_commands.c.o'
'drivers/net/qede/base/f6110d5@@qede_base@sta/ecore_spq.c.o'
'drivers/net/qede/base/f6110d5@@qede_base@sta/ecore_sriov.c.o'
'drivers/net/qede/base/f61
10d5@@qede_base@sta/ecore_vf.c.o'
'drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_ethdev.c.o'
'drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_filter.c.o'
'drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o'
'drivers/a715
181@@tmp_rte_pmd_qede@sta/net_qede_qede_rxtx.c.o' -Wl,--as-needed
-Wl,--no-undefined -shared -fPIC -Wl,--start-group
-Wl,-soname,librte_pmd_qede.so.20.0 -Wl,--no-as-needed -pthread -lm
-ldl -lnuma lib/librte_ethdev.so.20.0.3 lib/librte_eal.
so.20.0.3 lib/librte_kvargs.so.20.0.3 lib/librte_telemetry.so.20.0.3
lib/librte_net.so.20.0.3 lib/librte_mbuf.so.20.0.3
lib/librte_mempool.so.20.0.3 lib/librte_ring.so.20.0.3
lib/librte_meter.so.20.0.3 drivers/librte_bus_pci.so.20.0.3 lib/l
ibrte_pci.so.20.0.3 drivers/librte_bus_vdev.so.20.0.3
-Wl,--version-script=/export/dpdk-next-net-mrvl/drivers/net/qede/rte_pmd_qede_version.map
/usr/lib/libbsd.so -Wl,--end-group
'-Wl,-rpath,$ORIGIN/../lib:$ORIGIN/' -Wl,-rpath-link,/export/
dpdk-next-net-mrvl/build-gcc-static/lib
-Wl,-rpath-link,/export/dpdk-next-net-mrvl/build-gcc-static/drivers
/usr/bin/ld: drivers/net/qede/base/f6110d5@@qede_base@sta/ecore_dev.c.o:
in function `ecore_resc_alloc':
/export/dpdk-next-net-mrvl/build-gcc-static/../drivers/net/qede/base/ecore_dev.c:2516:
undefined reference to `qed_dbg_alloc_user_data'
/usr/bin/ld: /export/dpdk-next-net-mrvl/build-gcc-static/../drivers/net/qede/base/ecore_dev.c:2525:
undefined reference to `qed_dbg_alloc_user_data'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:
in function `qed_slowpath_start':
/export/dpdk-next-net-mrvl/build-gcc-static/../drivers/net/qede/qede_main.c:285:
undefined reference to `qed_dbg_pf_init'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0xa8):
undefined reference to `qed_dbg_grc'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0xb0):
undefined reference to `qed_dbg_grc_size'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0xb8):
undefined reference to `qed_dbg_idle_chk'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0xc0):
undefined reference to `qed_dbg_idle_chk_size'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0xc8):
undefined reference to `qed_dbg_reg_fifo'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0xd0):
undefined reference to `qed_dbg_reg_fifo_size'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0xd8):
undefined reference to `qed_dbg_mcp_trace'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0xe0):
undefined reference to `qed_dbg_mcp_trace_size'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0xe8):
undefined reference to `qed_dbg_protection_override'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0xf0):
undefined reference to `qed_dbg_protection_override_size'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0xf8):
undefined reference to `qed_dbg_igu_fifo_size'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0x100):
undefined reference to `qed_dbg_igu_fifo'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0x108):
undefined reference to `qed_dbg_fw_asserts'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0x110):
undefined reference to `qed_dbg_fw_asserts_size'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0x118):
undefined reference to `qed_dbg_ilt'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0x120):
undefined reference to `qed_dbg_ilt_size'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0x128):
undefined reference to `qed_get_debug_engine'
/usr/bin/ld: drivers/a715181@@tmp_rte_pmd_qede@sta/net_qede_qede_main.c.o:(.data.rel.ro+0x130):
undefined reference to `qed_set_debug_engine'




> ---
>  doc/guides/nics/features/qede.ini |   1 +
>  drivers/net/qede/Makefile         |   1 +
>  drivers/net/qede/base/bcm_osal.c  |  25 +++
>  drivers/net/qede/base/bcm_osal.h  |   5 +
>  drivers/net/qede/qede_ethdev.c    |   1 +
>  drivers/net/qede/qede_ethdev.h    |  25 +++
>  drivers/net/qede/qede_regs.c      | 271 ++++++++++++++++++++++++++++++
>  7 files changed, 329 insertions(+)
>  create mode 100644 drivers/net/qede/qede_regs.c
>
> diff --git a/doc/guides/nics/features/qede.ini b/doc/guides/nics/features/qede.ini
> index 20c90e626..f8716523e 100644
> --- a/doc/guides/nics/features/qede.ini
> +++ b/doc/guides/nics/features/qede.ini
> @@ -31,6 +31,7 @@ Packet type parsing  = Y
>  Basic stats          = Y
>  Extended stats       = Y
>  Stats per queue      = Y
> +Registers dump       = Y
>  Multiprocess aware   = Y
>  Linux UIO            = Y
>  Linux VFIO           = Y
> diff --git a/drivers/net/qede/Makefile b/drivers/net/qede/Makefile
> index 3b00338ff..0e8a67b0d 100644
> --- a/drivers/net/qede/Makefile
> +++ b/drivers/net/qede/Makefile
> @@ -104,5 +104,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_main.c
>  SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_rxtx.c
>  SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_filter.c
>  SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_debug.c
> +SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_regs.c
>
>  include $(RTE_SDK)/mk/rte.lib.mk
> diff --git a/drivers/net/qede/base/bcm_osal.c b/drivers/net/qede/base/bcm_osal.c
> index 45557fe3c..65837b53d 100644
> --- a/drivers/net/qede/base/bcm_osal.c
> +++ b/drivers/net/qede/base/bcm_osal.c
> @@ -246,6 +246,28 @@ qede_get_mcp_proto_stats(struct ecore_dev *edev,
>         }
>  }
>
> +static void qede_hw_err_handler(void *dev, enum ecore_hw_err_type err_type)
> +{
> +       struct ecore_dev *edev = dev;
> +
> +       switch (err_type) {
> +       case ECORE_HW_ERR_FAN_FAIL:
> +               break;
> +
> +       case ECORE_HW_ERR_MFW_RESP_FAIL:
> +       case ECORE_HW_ERR_HW_ATTN:
> +       case ECORE_HW_ERR_DMAE_FAIL:
> +       case ECORE_HW_ERR_RAMROD_FAIL:
> +       case ECORE_HW_ERR_FW_ASSERT:
> +               OSAL_SAVE_FW_DUMP(0); /* Using port 0 as default port_id */
> +               break;
> +
> +       default:
> +               DP_NOTICE(edev, false, "Unknown HW error [%d]\n", err_type);
> +               return;
> +       }
> +}
> +
>  void
>  qede_hw_err_notify(struct ecore_hwfn *p_hwfn, enum ecore_hw_err_type err_type)
>  {
> @@ -275,6 +297,9 @@ qede_hw_err_notify(struct ecore_hwfn *p_hwfn, enum ecore_hw_err_type err_type)
>         }
>
>         DP_ERR(p_hwfn, "HW error occurred [%s]\n", err_str);
> +
> +       qede_hw_err_handler(p_hwfn->p_dev, err_type);
> +
>         ecore_int_attn_clr_enable(p_hwfn->p_dev, true);
>  }
>
> diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
> index b4b94231b..5d4df5907 100644
> --- a/drivers/net/qede/base/bcm_osal.h
> +++ b/drivers/net/qede/base/bcm_osal.h
> @@ -371,6 +371,11 @@ void qede_hw_err_notify(struct ecore_hwfn *p_hwfn,
>
>  /* TODO: */
>  #define OSAL_SCHEDULE_RECOVERY_HANDLER(hwfn) nothing
> +
> +int qede_save_fw_dump(uint8_t port_id);
> +
> +#define OSAL_SAVE_FW_DUMP(port_id) qede_save_fw_dump(port_id)
> +
>  #define OSAL_HW_ERROR_OCCURRED(hwfn, err_type) \
>         qede_hw_err_notify(hwfn, err_type)
>
> diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
> index b5d6c7c43..e5a2581dd 100644
> --- a/drivers/net/qede/qede_ethdev.c
> +++ b/drivers/net/qede/qede_ethdev.c
> @@ -2426,6 +2426,7 @@ static const struct eth_dev_ops qede_eth_dev_ops = {
>         .udp_tunnel_port_add = qede_udp_dst_port_add,
>         .udp_tunnel_port_del = qede_udp_dst_port_del,
>         .fw_version_get = qede_fw_version_get,
> +       .get_reg = qede_get_regs,
>  };
>
>  static const struct eth_dev_ops qede_eth_vf_dev_ops = {
> diff --git a/drivers/net/qede/qede_ethdev.h b/drivers/net/qede/qede_ethdev.h
> index b988a73f2..76c5dae3b 100644
> --- a/drivers/net/qede/qede_ethdev.h
> +++ b/drivers/net/qede/qede_ethdev.h
> @@ -214,6 +214,8 @@ struct qede_tunn_params {
>         uint16_t udp_port;
>  };
>
> +#define QEDE_FW_DUMP_FILE_SIZE 128
> +
>  /*
>   *  Structure to store private data for each port.
>   */
> @@ -252,6 +254,7 @@ struct qede_dev {
>         char drv_ver[QEDE_PMD_DRV_VER_STR_SIZE];
>         bool vport_started;
>         int vlan_offload_mask;
> +       char dump_file[QEDE_FW_DUMP_FILE_SIZE];
>         void *ethdev;
>  };
>
> @@ -313,4 +316,26 @@ void qede_config_accept_any_vlan(struct qede_dev *qdev, bool flg);
>  int qede_ucast_filter(struct rte_eth_dev *eth_dev,
>                       struct ecore_filter_ucast *ucast,
>                       bool add);
> +
> +#define REGDUMP_HEADER_SIZE sizeof(u32)
> +#define REGDUMP_HEADER_FEATURE_SHIFT 24
> +#define REGDUMP_HEADER_ENGINE_SHIFT 31
> +#define REGDUMP_HEADER_OMIT_ENGINE_SHIFT 30
> +
> +enum debug_print_features {
> +       OLD_MODE = 0,
> +       IDLE_CHK = 1,
> +       GRC_DUMP = 2,
> +       MCP_TRACE = 3,
> +       REG_FIFO = 4,
> +       PROTECTION_OVERRIDE = 5,
> +       IGU_FIFO = 6,
> +       PHY = 7,
> +       FW_ASSERTS = 8,
> +};
> +
> +int qede_get_regs_len(struct qede_dev *qdev);
> +int qede_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs);
> +void qede_config_rx_mode(struct rte_eth_dev *eth_dev);
> +void qed_dbg_dump(struct rte_eth_dev *eth_dev);
>  #endif /* _QEDE_ETHDEV_H_ */
> diff --git a/drivers/net/qede/qede_regs.c b/drivers/net/qede/qede_regs.c
> new file mode 100644
> index 000000000..4409d2180
> --- /dev/null
> +++ b/drivers/net/qede/qede_regs.c
> @@ -0,0 +1,271 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright (c) 2020 Marvell Semiconductor Inc.
> + * All rights reserved.
> + * www.marvell.com
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <fcntl.h>
> +#include <time.h>
> +#include <rte_ethdev.h>
> +#include "base/bcm_osal.h"
> +#include "qede_ethdev.h"
> +
> +int
> +qede_get_regs_len(struct qede_dev *qdev)
> +{
> +       struct ecore_dev *edev = &qdev->edev;
> +       int cur_engine, num_of_hwfns, regs_len = 0;
> +       uint8_t org_engine;
> +
> +       if (IS_VF(edev))
> +               return 0;
> +
> +       if (qdev->ops && qdev->ops->common) {
> +               num_of_hwfns = qdev->dev_info.common.num_hwfns;
> +               org_engine = qdev->ops->common->dbg_get_debug_engine(edev);
> +               for (cur_engine = 0; cur_engine < num_of_hwfns; cur_engine++) {
> +                       /* compute required buffer size for idle_chks and
> +                        * grcDump for each hw function
> +                        */
> +                       DP_NOTICE(edev, false,
> +                               "Calculating idle_chk and grcdump register length for current engine\n");
> +                       qdev->ops->common->dbg_set_debug_engine(edev,
> +                                                               cur_engine);
> +                       regs_len += REGDUMP_HEADER_SIZE +
> +                               qdev->ops->common->dbg_idle_chk_size(edev) +
> +                               REGDUMP_HEADER_SIZE +
> +                               qdev->ops->common->dbg_idle_chk_size(edev) +
> +                               REGDUMP_HEADER_SIZE +
> +                               qdev->ops->common->dbg_grc_size(edev) +
> +                               REGDUMP_HEADER_SIZE +
> +                               qdev->ops->common->dbg_reg_fifo_size(edev) +
> +                               REGDUMP_HEADER_SIZE +
> +                               qdev->ops->common->dbg_protection_override_size(edev) +
> +                               REGDUMP_HEADER_SIZE +
> +                               qdev->ops->common->dbg_igu_fifo_size(edev) +
> +                               REGDUMP_HEADER_SIZE +
> +                               qdev->ops->common->dbg_fw_asserts_size(edev);
> +               }
> +               /* compute required buffer size for mcp trace and add it to the
> +                * total required buffer size
> +                */
> +               regs_len += REGDUMP_HEADER_SIZE +
> +                           qdev->ops->common->dbg_mcp_trace_size(edev);
> +
> +               qdev->ops->common->dbg_set_debug_engine(edev, org_engine);
> +       }
> +       DP_NOTICE(edev, false, "Total length = %u\n", regs_len);
> +
> +       return regs_len;
> +}
> +
> +static uint32_t
> +qede_calc_regdump_header(enum debug_print_features feature, int engine,
> +                        uint32_t feature_size, uint8_t omit_engine)
> +{
> +       /* insert the engine, feature and mode inside the header and
> +        * combine it with feature size
> +        */
> +       return (feature_size | (feature << REGDUMP_HEADER_FEATURE_SHIFT) |
> +               (omit_engine << REGDUMP_HEADER_OMIT_ENGINE_SHIFT) |
> +               (engine << REGDUMP_HEADER_ENGINE_SHIFT));
> +}
> +
> +int qede_get_regs(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs)
> +{
> +       struct qede_dev *qdev = eth_dev->data->dev_private;
> +       struct ecore_dev *edev = &qdev->edev;
> +       uint32_t *buffer = regs->data;
> +       int cur_engine, num_of_hwfns;
> +       /* '1' tells the parser to omit the engine number in the output files */
> +       uint8_t omit_engine = 0;
> +       uint8_t org_engine;
> +       uint32_t feature_size;
> +       uint32_t offset = 0;
> +
> +       if (IS_VF(edev))
> +               return -ENOTSUP;
> +
> +       if (buffer == NULL) {
> +               regs->length = qede_get_regs_len(qdev);
> +               regs->width =  sizeof(uint32_t);
> +               DP_INFO(edev, "Length %u\n", regs->length);
> +               return 0;
> +       }
> +
> +       memset(buffer, 0, regs->length);
> +       num_of_hwfns = qdev->dev_info.common.num_hwfns;
> +       if (num_of_hwfns == 1)
> +               omit_engine = 1;
> +
> +       OSAL_MUTEX_ACQUIRE(&edev->dbg_lock);
> +
> +       org_engine = qdev->ops->common->dbg_get_debug_engine(edev);
> +       for (cur_engine = 0; cur_engine < num_of_hwfns; cur_engine++) {
> +               /* collect idle_chks and grcDump for each hw function */
> +               DP_NOTICE(edev, false, "obtaining idle_chk and grcdump for current engine\n");
> +               qdev->ops->common->dbg_set_debug_engine(edev, cur_engine);
> +
> +               /* first idle_chk */
> +               qdev->ops->common->dbg_idle_chk(edev, (uint8_t *)buffer +
> +                       offset + REGDUMP_HEADER_SIZE, &feature_size);
> +               *(uint32_t *)((uint8_t *)buffer + offset) =
> +                       qede_calc_regdump_header(IDLE_CHK, cur_engine,
> +                                                feature_size, omit_engine);
> +               offset += (feature_size + REGDUMP_HEADER_SIZE);
> +               DP_NOTICE(edev, false, "Idle Check1 feature_size %u\n",
> +                         feature_size);
> +
> +               /* second idle_chk */
> +               qdev->ops->common->dbg_idle_chk(edev, (uint8_t *)buffer +
> +                       offset + REGDUMP_HEADER_SIZE, &feature_size);
> +               *(uint32_t *)((uint8_t *)buffer + offset) =
> +                       qede_calc_regdump_header(IDLE_CHK, cur_engine,
> +                                                feature_size, omit_engine);
> +               offset += (feature_size + REGDUMP_HEADER_SIZE);
> +               DP_NOTICE(edev, false, "Idle Check2 feature_size %u\n",
> +                         feature_size);
> +
> +               /* reg_fifo dump */
> +               qdev->ops->common->dbg_reg_fifo(edev, (uint8_t *)buffer +
> +                       offset + REGDUMP_HEADER_SIZE, &feature_size);
> +               *(uint32_t *)((uint8_t *)buffer + offset) =
> +                       qede_calc_regdump_header(REG_FIFO, cur_engine,
> +                                                feature_size, omit_engine);
> +               offset += (feature_size + REGDUMP_HEADER_SIZE);
> +               DP_NOTICE(edev, false, "Reg fifo feature_size %u\n",
> +                         feature_size);
> +
> +               /* igu_fifo dump */
> +               qdev->ops->common->dbg_igu_fifo(edev, (uint8_t *)buffer +
> +                       offset + REGDUMP_HEADER_SIZE, &feature_size);
> +               *(uint32_t *)((uint8_t *)buffer + offset) =
> +                       qede_calc_regdump_header(IGU_FIFO, cur_engine,
> +                                                feature_size, omit_engine);
> +               offset += (feature_size + REGDUMP_HEADER_SIZE);
> +               DP_NOTICE(edev, false, "IGU fifo feature_size %u\n",
> +                         feature_size);
> +
> +               /* protection_override dump */
> +               qdev->ops->common->dbg_protection_override(edev,
> +                                                          (uint8_t *)buffer +
> +                       offset + REGDUMP_HEADER_SIZE, &feature_size);
> +               *(uint32_t *)((uint8_t *)buffer + offset) =
> +                      qede_calc_regdump_header(PROTECTION_OVERRIDE, cur_engine,
> +                                               feature_size, omit_engine);
> +               offset += (feature_size + REGDUMP_HEADER_SIZE);
> +               DP_NOTICE(edev, false, "Protection override feature_size %u\n",
> +                         feature_size);
> +
> +               /* fw_asserts dump */
> +               qdev->ops->common->dbg_fw_asserts(edev, (uint8_t *)buffer +
> +                       offset + REGDUMP_HEADER_SIZE, &feature_size);
> +               *(uint32_t *)((uint8_t *)buffer + offset) =
> +                       qede_calc_regdump_header(FW_ASSERTS, cur_engine,
> +                                                feature_size, omit_engine);
> +               offset += (feature_size + REGDUMP_HEADER_SIZE);
> +               DP_NOTICE(edev, false, "FW assert feature_size %u\n",
> +                         feature_size);
> +
> +               /* grc dump */
> +               qdev->ops->common->dbg_grc(edev, (uint8_t *)buffer +
> +                       offset + REGDUMP_HEADER_SIZE, &feature_size);
> +               *(uint32_t *)((uint8_t *)buffer + offset) =
> +                       qede_calc_regdump_header(GRC_DUMP, cur_engine,
> +                                                feature_size, omit_engine);
> +               offset += (feature_size + REGDUMP_HEADER_SIZE);
> +               DP_NOTICE(edev, false, "GRC dump feature_size %u\n",
> +                         feature_size);
> +       }
> +
> +       /* mcp_trace */
> +       qdev->ops->common->dbg_mcp_trace(edev, (uint8_t *)buffer +
> +               offset + REGDUMP_HEADER_SIZE, &feature_size);
> +       *(uint32_t *)((uint8_t *)buffer + offset) =
> +               qede_calc_regdump_header(MCP_TRACE, cur_engine, feature_size,
> +                                        omit_engine);
> +       offset += (feature_size + REGDUMP_HEADER_SIZE);
> +       DP_NOTICE(edev, false, "MCP trace feature_size %u\n", feature_size);
> +
> +       qdev->ops->common->dbg_set_debug_engine(edev, org_engine);
> +
> +       OSAL_MUTEX_RELEASE(&edev->dbg_lock);
> +
> +       return 0;
> +}
> +
> +static void
> +qede_set_fw_dump_file_name(struct qede_dev *qdev)
> +{
> +       time_t ltime;
> +       struct tm *tm;
> +
> +       ltime = time(NULL);
> +       tm = localtime(&ltime);
> +       snprintf(qdev->dump_file, QEDE_FW_DUMP_FILE_SIZE,
> +                "qede_pmd_dump_%02d-%02d-%02d_%02d-%02d-%02d.bin",
> +                tm->tm_mon + 1, (int)tm->tm_mday, 1900 + tm->tm_year,
> +                tm->tm_hour, tm->tm_min, tm->tm_sec);
> +}
> +
> +static int
> +qede_write_fwdump(const char *dump_file, void *dump, size_t len)
> +{
> +       int err = 0;
> +       FILE *f;
> +       size_t bytes;
> +
> +       f = fopen(dump_file, "wb+");
> +
> +       if (!f) {
> +               fprintf(stderr, "Can't open file %s: %s\n",
> +                       dump_file, strerror(errno));
> +               return 1;
> +       }
> +       bytes = fwrite(dump, 1, len, f);
> +       if (bytes != len) {
> +               fprintf(stderr, "Can not write all of dump data bytes=%ld len=%ld\n",
> +                       bytes, len);
> +               err = 1;
> +       }
> +
> +       if (fclose(f)) {
> +               fprintf(stderr, "Can't close file %s: %s\n",
> +                       dump_file, strerror(errno));
> +               err = 1;
> +       }
> +
> +       return err;
> +}
> +
> +int
> +qede_save_fw_dump(uint8_t port_id)
> +{
> +       struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id];
> +       struct rte_dev_reg_info regs;
> +       struct qede_dev *qdev = eth_dev->data->dev_private;
> +       struct ecore_dev *edev = &qdev->edev;
> +       int rc = 0;
> +
> +       if (!rte_eth_dev_is_valid_port(port_id)) {
> +               DP_ERR(edev, "port %u invalid port ID", port_id);
> +               return -ENODEV;
> +       }
> +
> +       memset(&regs, 0, sizeof(regs));
> +       regs.length = qede_get_regs_len(qdev);
> +       regs.data = OSAL_ZALLOC(eth_dev, GFP_KERNEL, regs.length);
> +       if (regs.data) {
> +               qede_get_regs(eth_dev, &regs);
> +               qede_set_fw_dump_file_name(qdev);
> +               rc = qede_write_fwdump(qdev->dump_file, regs.data, regs.length);
> +               if (!rc)
> +                       DP_NOTICE(edev, false, "FW dump written to %s file\n",
> +                                 qdev->dump_file);
> +               OSAL_FREE(edev, regs.data);
> +       }
> +
> +       return rc;
> +}
> --
> 2.18.0
>

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

* [dpdk-dev] [PATCH v5 0/4] net/qede: add FW debug data collection support
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 " Rasesh Mody
@ 2020-07-08 22:50       ` Rasesh Mody
  2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
                         ` (3 subsequent siblings)
  4 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-07-08 22:50 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev

Hi Jerin, Ferruh,

This patch-set adds an ability to collect FW and HW Debug Data/Dump
(referred to as FW/HW Dump) to QEDE PMD. The dump is collected either
when PMD detects an error or when a DPDK application asks PMD to
collect it upon detection of application error. This FW/HW Dump
needs to be saved to a file and sent to Marvell for analysis.

Please apply to dpdk-next-net-mrvl and dpdk-next-net trees.

v5:
Fixed meson build

v4:
Rectify all genuine spelling typos, remaining are false positive.

v3:
Fixed gcc-10 compilation issue.

v2:
Addressed checkpatch issues and updated supported features.

Thanks!
-Rasesh

Rasesh Mody (4):
  net/qede/base: re-arrange few structures for DDC
  net/qede/base: add changes for debug data collection
  net/qede: add infrastructure for debug data collection
  net/qede: add support for get register operation

 doc/guides/nics/features/qede.ini             |    1 +
 drivers/net/qede/Makefile                     |    5 +-
 drivers/net/qede/base/bcm_osal.c              |   31 +
 drivers/net/qede/base/bcm_osal.h              |   18 +-
 drivers/net/qede/base/common_hsi.h            |    1 +
 drivers/net/qede/base/ecore.h                 |   54 +-
 drivers/net/qede/base/ecore_cxt.c             |  200 +-
 drivers/net/qede/base/ecore_cxt.h             |  140 +-
 drivers/net/qede/base/ecore_dev.c             |   26 +-
 drivers/net/qede/base/ecore_hsi_common.h      |  184 +-
 drivers/net/qede/base/ecore_hsi_debug_tools.h |    2 +-
 drivers/net/qede/base/ecore_hsi_func_common.h |   17 +
 drivers/net/qede/base/ecore_init_fw_funcs.h   |    7 -
 drivers/net/qede/base/ecore_mcp.c             |  211 +
 drivers/net/qede/base/ecore_mcp_api.h         |   37 +
 drivers/net/qede/base/ecore_status.h          |    2 +
 drivers/net/qede/base/reg_addr.h              |  846 ++
 drivers/net/qede/meson.build                  |    6 +
 drivers/net/qede/qede_debug.c                 | 8120 +++++++++++++++++
 drivers/net/qede/qede_debug.h                 |  759 ++
 drivers/net/qede/qede_ethdev.c                |    2 +-
 drivers/net/qede/qede_ethdev.h                |   25 +
 drivers/net/qede/qede_if.h                    |   45 +
 drivers/net/qede/qede_main.c                  |   42 +-
 drivers/net/qede/qede_regs.c                  |  271 +
 25 files changed, 10889 insertions(+), 163 deletions(-)
 create mode 100644 drivers/net/qede/base/ecore_hsi_func_common.h
 create mode 100644 drivers/net/qede/qede_debug.c
 create mode 100644 drivers/net/qede/qede_debug.h
 create mode 100644 drivers/net/qede/qede_regs.c

-- 
2.18.0


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

* [dpdk-dev] [PATCH v5 1/4] net/qede/base: re-arrange few structures for DDC
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 " Rasesh Mody
  2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 " Rasesh Mody
@ 2020-07-08 22:50       ` Rasesh Mody
  2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 2/4] net/qede/base: add changes for debug data collection Rasesh Mody
                         ` (2 subsequent siblings)
  4 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-07-08 22:50 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

This patch rearranges some of the base driver structures which will be
also used by debug data collection (DDC) implementation. It adds a new
file ecore_hsi_func_common.h with Physical, Virtual memory descriptors.

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/qede/base/ecore.h                 |   2 +
 drivers/net/qede/base/ecore_cxt.c             | 140 ++----------------
 drivers/net/qede/base/ecore_cxt.h             | 135 ++++++++++++++++-
 drivers/net/qede/base/ecore_dev.c             |  13 +-
 drivers/net/qede/base/ecore_hsi_func_common.h |  17 +++
 drivers/net/qede/base/ecore_init_fw_funcs.h   |   7 -
 6 files changed, 172 insertions(+), 142 deletions(-)
 create mode 100644 drivers/net/qede/base/ecore_hsi_func_common.h

diff --git a/drivers/net/qede/base/ecore.h b/drivers/net/qede/base/ecore.h
index 498bb6f09..dc5fe4d80 100644
--- a/drivers/net/qede/base/ecore.h
+++ b/drivers/net/qede/base/ecore.h
@@ -24,6 +24,7 @@
 #include "ecore_hsi_debug_tools.h"
 #include "ecore_hsi_init_func.h"
 #include "ecore_hsi_init_tool.h"
+#include "ecore_hsi_func_common.h"
 #include "ecore_proto_if.h"
 #include "mcp_public.h"
 
@@ -671,6 +672,7 @@ struct ecore_hwfn {
 
 	struct dbg_tools_data		dbg_info;
 	void				*dbg_user_info;
+	struct virt_mem_desc		dbg_arrays[MAX_BIN_DBG_BUFFER_TYPE];
 
 	struct z_stream_s		*stream;
 
diff --git a/drivers/net/qede/base/ecore_cxt.c b/drivers/net/qede/base/ecore_cxt.c
index dda47ea67..23f37b1bf 100644
--- a/drivers/net/qede/base/ecore_cxt.c
+++ b/drivers/net/qede/base/ecore_cxt.c
@@ -20,12 +20,6 @@
 #include "ecore_sriov.h"
 #include "ecore_mcp.h"
 
-/* Max number of connection types in HW (DQ/CDU etc.) */
-#define MAX_CONN_TYPES		PROTOCOLID_COMMON
-#define NUM_TASK_TYPES		2
-#define NUM_TASK_PF_SEGMENTS	4
-#define NUM_TASK_VF_SEGMENTS	1
-
 /* Doorbell-Queue constants */
 #define DQ_RANGE_SHIFT	4
 #define DQ_RANGE_ALIGN	(1 << DQ_RANGE_SHIFT)
@@ -90,128 +84,6 @@ struct src_ent {
 /* Alignment is inherent to the type1_task_context structure */
 #define TYPE1_TASK_CXT_SIZE(p_hwfn) sizeof(union type1_task_context)
 
-/* PF per protocl configuration object */
-#define TASK_SEGMENTS   (NUM_TASK_PF_SEGMENTS + NUM_TASK_VF_SEGMENTS)
-#define TASK_SEGMENT_VF (NUM_TASK_PF_SEGMENTS)
-
-struct ecore_tid_seg {
-	u32 count;
-	u8 type;
-	bool has_fl_mem;
-};
-
-struct ecore_conn_type_cfg {
-	u32 cid_count;
-	u32 cids_per_vf;
-	struct ecore_tid_seg tid_seg[TASK_SEGMENTS];
-};
-
-/* ILT Client configuration,
- * Per connection type (protocol) resources (cids, tis, vf cids etc.)
- * 1 - for connection context (CDUC) and for each task context we need two
- * values, for regular task context and for force load memory
- */
-#define ILT_CLI_PF_BLOCKS	(1 + NUM_TASK_PF_SEGMENTS * 2)
-#define ILT_CLI_VF_BLOCKS	(1 + NUM_TASK_VF_SEGMENTS * 2)
-#define CDUC_BLK		(0)
-#define SRQ_BLK			(0)
-#define CDUT_SEG_BLK(n)		(1 + (u8)(n))
-#define CDUT_FL_SEG_BLK(n, X)	(1 + (n) + NUM_TASK_##X##_SEGMENTS)
-
-struct ilt_cfg_pair {
-	u32 reg;
-	u32 val;
-};
-
-struct ecore_ilt_cli_blk {
-	u32 total_size;		/* 0 means not active */
-	u32 real_size_in_page;
-	u32 start_line;
-	u32 dynamic_line_offset;
-	u32 dynamic_line_cnt;
-};
-
-struct ecore_ilt_client_cfg {
-	bool active;
-
-	/* ILT boundaries */
-	struct ilt_cfg_pair first;
-	struct ilt_cfg_pair last;
-	struct ilt_cfg_pair p_size;
-
-	/* ILT client blocks for PF */
-	struct ecore_ilt_cli_blk pf_blks[ILT_CLI_PF_BLOCKS];
-	u32 pf_total_lines;
-
-	/* ILT client blocks for VFs */
-	struct ecore_ilt_cli_blk vf_blks[ILT_CLI_VF_BLOCKS];
-	u32 vf_total_lines;
-};
-
-#define MAP_WORD_SIZE		sizeof(unsigned long)
-#define BITS_PER_MAP_WORD	(MAP_WORD_SIZE * 8)
-
-struct ecore_cid_acquired_map {
-	u32 start_cid;
-	u32 max_count;
-	u32 *cid_map;
-};
-
-struct ecore_src_t2 {
-	struct phys_mem_desc	*dma_mem;
-	u32			num_pages;
-	u64			first_free;
-	u64			last_free;
-};
-
-struct ecore_cxt_mngr {
-	/* Per protocl configuration */
-	struct ecore_conn_type_cfg conn_cfg[MAX_CONN_TYPES];
-
-	/* computed ILT structure */
-	struct ecore_ilt_client_cfg clients[ILT_CLI_MAX];
-
-	/* Task type sizes */
-	u32 task_type_size[NUM_TASK_TYPES];
-
-	/* total number of VFs for this hwfn -
-	 * ALL VFs are symmetric in terms of HW resources
-	 */
-	u32 vf_count;
-
-	/* Acquired CIDs */
-	struct ecore_cid_acquired_map acquired[MAX_CONN_TYPES];
-	struct ecore_cid_acquired_map *acquired_vf[MAX_CONN_TYPES];
-
-	/* ILT  shadow table */
-	struct phys_mem_desc		*ilt_shadow;
-	u32 pf_start_line;
-
-	/* Mutex for a dynamic ILT allocation */
-	osal_mutex_t mutex;
-
-	/* SRC T2 */
-	struct ecore_src_t2		src_t2;
-
-	/* The infrastructure originally was very generic and context/task
-	 * oriented - per connection-type we would set how many of those
-	 * are needed, and later when determining how much memory we're
-	 * needing for a given block we'd iterate over all the relevant
-	 * connection-types.
-	 * But since then we've had some additional resources, some of which
-	 * require memory which is indepent of the general context/task
-	 * scheme. We add those here explicitly per-feature.
-	 */
-
-	/* total number of SRQ's for this hwfn */
-	u32				srq_count;
-
-	/* Maximal number of L2 steering filters */
-	u32				arfs_count;
-
-	/* TODO - VF arfs filters ? */
-};
-
 static OSAL_INLINE bool tm_cid_proto(enum protocol_type type)
 {
 	return type == PROTOCOLID_TOE;
@@ -945,7 +817,7 @@ static enum _ecore_status_t ecore_cxt_src_t2_alloc(struct ecore_hwfn *p_hwfn)
 }
 
 #define for_each_ilt_valid_client(pos, clients)		\
-	for (pos = 0; pos < ILT_CLI_MAX; pos++)		\
+	for (pos = 0; pos < MAX_ILT_CLIENTS; pos++)		\
 		if (!clients[pos].active) {		\
 			continue;			\
 		} else					\
@@ -1238,7 +1110,7 @@ enum _ecore_status_t ecore_cxt_mngr_alloc(struct ecore_hwfn *p_hwfn)
 	clients[ILT_CLI_TSDM].p_size.reg = ILT_CFG_REG(TSDM, P_SIZE);
 
 	/* default ILT page size for all clients is 64K */
-	for (i = 0; i < ILT_CLI_MAX; i++)
+	for (i = 0; i < MAX_ILT_CLIENTS; i++)
 		p_mngr->clients[i].p_size.val = ILT_DEFAULT_HW_P_SIZE;
 
 	/* due to removal of ISCSI/FCoE files union type0_task_context
@@ -2306,3 +2178,11 @@ ecore_cxt_free_ilt_range(struct ecore_hwfn *p_hwfn,
 
 	return ECORE_SUCCESS;
 }
+
+static u16 ecore_blk_calculate_pages(struct ecore_ilt_cli_blk *p_blk)
+{
+	if (p_blk->real_size_in_page == 0)
+		return 0;
+
+	return DIV_ROUND_UP(p_blk->total_size, p_blk->real_size_in_page);
+}
diff --git a/drivers/net/qede/base/ecore_cxt.h b/drivers/net/qede/base/ecore_cxt.h
index 55f08027d..f58c4ba57 100644
--- a/drivers/net/qede/base/ecore_cxt.h
+++ b/drivers/net/qede/base/ecore_cxt.h
@@ -31,7 +31,7 @@ enum ilt_clients {
 	ILT_CLI_TSDM,
 	ILT_CLI_RGFS,
 	ILT_CLI_TGFS,
-	ILT_CLI_MAX
+	MAX_ILT_CLIENTS
 };
 
 u32 ecore_cxt_get_proto_cid_count(struct ecore_hwfn *p_hwfn,
@@ -212,4 +212,137 @@ enum _ecore_status_t ecore_cxt_free_proto_ilt(struct ecore_hwfn *p_hwfn,
 #define ECORE_CTX_WORKING_MEM 0
 #define ECORE_CTX_FL_MEM 1
 
+/* Max number of connection types in HW (DQ/CDU etc.) */
+#define MAX_CONN_TYPES		PROTOCOLID_COMMON
+#define NUM_TASK_TYPES		2
+#define NUM_TASK_PF_SEGMENTS	4
+#define NUM_TASK_VF_SEGMENTS	1
+
+/* PF per protocol configuration object */
+#define TASK_SEGMENTS   (NUM_TASK_PF_SEGMENTS + NUM_TASK_VF_SEGMENTS)
+#define TASK_SEGMENT_VF (NUM_TASK_PF_SEGMENTS)
+
+struct ecore_tid_seg {
+	u32 count;
+	u8 type;
+	bool has_fl_mem;
+};
+
+struct ecore_conn_type_cfg {
+	u32 cid_count;
+	u32 cids_per_vf;
+	struct ecore_tid_seg tid_seg[TASK_SEGMENTS];
+};
+
+/* ILT Client configuration,
+ * Per connection type (protocol) resources (cids, tis, vf cids etc.)
+ * 1 - for connection context (CDUC) and for each task context we need two
+ * values, for regular task context and for force load memory
+ */
+#define ILT_CLI_PF_BLOCKS	(1 + NUM_TASK_PF_SEGMENTS * 2)
+#define ILT_CLI_VF_BLOCKS	(1 + NUM_TASK_VF_SEGMENTS * 2)
+#define CDUC_BLK		(0)
+#define SRQ_BLK			(0)
+#define CDUT_SEG_BLK(n)		(1 + (u8)(n))
+#define CDUT_FL_SEG_BLK(n, X)	(1 + (n) + NUM_TASK_##X##_SEGMENTS)
+
+struct ilt_cfg_pair {
+	u32 reg;
+	u32 val;
+};
+
+struct ecore_ilt_cli_blk {
+	u32 total_size;		/* 0 means not active */
+	u32 real_size_in_page;
+	u32 start_line;
+	u32 dynamic_line_offset;
+	u32 dynamic_line_cnt;
+};
+
+struct ecore_ilt_client_cfg {
+	bool active;
+
+	/* ILT boundaries */
+	struct ilt_cfg_pair first;
+	struct ilt_cfg_pair last;
+	struct ilt_cfg_pair p_size;
+
+	/* ILT client blocks for PF */
+	struct ecore_ilt_cli_blk pf_blks[ILT_CLI_PF_BLOCKS];
+	u32 pf_total_lines;
+
+	/* ILT client blocks for VFs */
+	struct ecore_ilt_cli_blk vf_blks[ILT_CLI_VF_BLOCKS];
+	u32 vf_total_lines;
+};
+
+#define MAP_WORD_SIZE		sizeof(unsigned long)
+#define BITS_PER_MAP_WORD	(MAP_WORD_SIZE * 8)
+
+struct ecore_cid_acquired_map {
+	u32 start_cid;
+	u32 max_count;
+	u32 *cid_map;
+};
+
+struct ecore_src_t2 {
+	struct phys_mem_desc	*dma_mem;
+	u32			num_pages;
+	u64			first_free;
+	u64			last_free;
+};
+
+struct ecore_cxt_mngr {
+	/* Per protocol configuration */
+	struct ecore_conn_type_cfg	conn_cfg[MAX_CONN_TYPES];
+
+	/* computed ILT structure */
+	struct ecore_ilt_client_cfg	clients[MAX_ILT_CLIENTS];
+
+	/* Task type sizes */
+	u32				task_type_size[NUM_TASK_TYPES];
+
+	/* total number of VFs for this hwfn -
+	 * ALL VFs are symmetric in terms of HW resources
+	 */
+	u32				vf_count;
+	u32				first_vf_in_pf;
+
+	/* Acquired CIDs */
+	struct ecore_cid_acquired_map acquired[MAX_CONN_TYPES];
+	struct ecore_cid_acquired_map *acquired_vf[MAX_CONN_TYPES];
+
+	/* ILT  shadow table */
+	struct phys_mem_desc		*ilt_shadow;
+	u32				ilt_shadow_size;
+	u32				pf_start_line;
+
+	/* Mutex for a dynamic ILT allocation */
+	osal_mutex_t mutex;
+
+	/* SRC T2 */
+	struct ecore_src_t2		src_t2;
+
+	/* The infrastructure originally was very generic and context/task
+	 * oriented - per connection-type we would set how many of those
+	 * are needed, and later when determining how much memory we're
+	 * needing for a given block we'd iterate over all the relevant
+	 * connection-types.
+	 * But since then we've had some additional resources, some of which
+	 * require memory which is independent of the general context/task
+	 * scheme. We add those here explicitly per-feature.
+	 */
+
+	/* total number of SRQ's for this hwfn */
+	u32				srq_count;
+
+	/* Maximal number of L2 steering filters */
+	u32				arfs_count;
+
+	/* TODO - VF arfs filters ? */
+
+	u8				task_type_id;
+	u16				task_ctx_size;
+	u16				conn_ctx_size;
+};
 #endif /* _ECORE_CID_ */
diff --git a/drivers/net/qede/base/ecore_dev.c b/drivers/net/qede/base/ecore_dev.c
index e18c2fa89..814d9ced6 100644
--- a/drivers/net/qede/base/ecore_dev.c
+++ b/drivers/net/qede/base/ecore_dev.c
@@ -2358,6 +2358,7 @@ static enum _ecore_status_t ecore_alloc_qm_data(struct ecore_hwfn *p_hwfn)
 enum _ecore_status_t ecore_resc_alloc(struct ecore_dev *p_dev)
 {
 	enum _ecore_status_t rc = ECORE_SUCCESS;
+	enum dbg_status debug_status = DBG_STATUS_OK;
 	int i;
 
 	if (IS_VF(p_dev)) {
@@ -2512,17 +2513,21 @@ enum _ecore_status_t ecore_resc_alloc(struct ecore_dev *p_dev)
 			goto alloc_err;
 		}
 
-		rc = OSAL_DBG_ALLOC_USER_DATA(p_hwfn, &p_hwfn->dbg_user_info);
-		if (rc) {
+		debug_status = OSAL_DBG_ALLOC_USER_DATA(p_hwfn,
+							&p_hwfn->dbg_user_info);
+		if (debug_status) {
 			DP_NOTICE(p_hwfn, false,
 				  "Failed to allocate dbg user info structure\n");
+			rc = (enum _ecore_status_t)debug_status;
 			goto alloc_err;
 		}
 
-		rc = OSAL_DBG_ALLOC_USER_DATA(p_hwfn, &p_hwfn->dbg_user_info);
-		if (rc) {
+		debug_status = OSAL_DBG_ALLOC_USER_DATA(p_hwfn,
+							&p_hwfn->dbg_user_info);
+		if (debug_status) {
 			DP_NOTICE(p_hwfn, false,
 				  "Failed to allocate dbg user info structure\n");
+			rc = (enum _ecore_status_t)debug_status;
 			goto alloc_err;
 		}
 	} /* hwfn loop */
diff --git a/drivers/net/qede/base/ecore_hsi_func_common.h b/drivers/net/qede/base/ecore_hsi_func_common.h
new file mode 100644
index 000000000..2cd175163
--- /dev/null
+++ b/drivers/net/qede/base/ecore_hsi_func_common.h
@@ -0,0 +1,17 @@
+#ifndef _HSI_FUNC_COMMON_H
+#define _HSI_FUNC_COMMON_H
+
+/* Physical memory descriptor */
+struct phys_mem_desc {
+	dma_addr_t phys_addr;
+	void *virt_addr;
+	u32 size; /* In bytes */
+};
+
+/* Virtual memory descriptor */
+struct virt_mem_desc {
+	void *ptr;
+	u32 size; /* In bytes */
+};
+
+#endif
diff --git a/drivers/net/qede/base/ecore_init_fw_funcs.h b/drivers/net/qede/base/ecore_init_fw_funcs.h
index 912451662..a393d088f 100644
--- a/drivers/net/qede/base/ecore_init_fw_funcs.h
+++ b/drivers/net/qede/base/ecore_init_fw_funcs.h
@@ -9,13 +9,6 @@
 #include "ecore_hsi_common.h"
 #include "ecore_hsi_eth.h"
 
-/* Physical memory descriptor */
-struct phys_mem_desc {
-	dma_addr_t phys_addr;
-	void *virt_addr;
-	u32 size; /* In bytes */
-};
-
 /* Returns the VOQ based on port and TC */
 #define VOQ(port, tc, max_phys_tcs_per_port) \
 	((tc) == PURE_LB_TC ? NUM_OF_PHYS_TCS * MAX_NUM_PORTS_BB + (port) : \
-- 
2.18.0


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

* [dpdk-dev] [PATCH v5 2/4] net/qede/base: add changes for debug data collection
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 " Rasesh Mody
  2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 " Rasesh Mody
  2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
@ 2020-07-08 22:50       ` Rasesh Mody
  2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 3/4] net/qede: add infrastructure " Rasesh Mody
  2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 4/4] net/qede: add support for get register operation Rasesh Mody
  4 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-07-08 22:50 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

This patch adds base driver APIs required for debug data collection.
It adds support for dumping internal lookup tables(ilt), reading nvram
image, register definitions.

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/qede/base/bcm_osal.c              |   6 +
 drivers/net/qede/base/bcm_osal.h              |   8 +-
 drivers/net/qede/base/common_hsi.h            |   1 +
 drivers/net/qede/base/ecore.h                 |  52 +-
 drivers/net/qede/base/ecore_cxt.c             |  60 ++
 drivers/net/qede/base/ecore_cxt.h             |   5 +
 drivers/net/qede/base/ecore_dev.c             |  13 +
 drivers/net/qede/base/ecore_hsi_common.h      | 184 +++-
 drivers/net/qede/base/ecore_hsi_debug_tools.h |   2 +-
 drivers/net/qede/base/ecore_mcp.c             | 211 +++++
 drivers/net/qede/base/ecore_mcp_api.h         |  37 +
 drivers/net/qede/base/ecore_status.h          |   2 +
 drivers/net/qede/base/reg_addr.h              | 846 ++++++++++++++++++
 drivers/net/qede/qede_ethdev.c                |   1 -
 drivers/net/qede/qede_main.c                  |   3 +-
 15 files changed, 1414 insertions(+), 17 deletions(-)

diff --git a/drivers/net/qede/base/bcm_osal.c b/drivers/net/qede/base/bcm_osal.c
index 54e5e4f98..45557fe3c 100644
--- a/drivers/net/qede/base/bcm_osal.c
+++ b/drivers/net/qede/base/bcm_osal.c
@@ -289,3 +289,9 @@ u32 qede_crc32(u32 crc, u8 *ptr, u32 length)
 	}
 	return crc;
 }
+
+void qed_set_platform_str(struct ecore_hwfn *p_hwfn,
+			  char *buf_str, u32 buf_size)
+{
+	snprintf(buf_str, buf_size, "%s.", rte_version());
+}
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index 88a2500a5..6ea3e7dda 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -8,6 +8,7 @@
 #define __BCM_OSAL_H
 
 #include <stdbool.h>
+#include <time.h>
 #include <rte_bitops.h>
 #include <rte_byteorder.h>
 #include <rte_spinlock.h>
@@ -19,6 +20,7 @@
 #include <rte_debug.h>
 #include <rte_ether.h>
 #include <rte_io.h>
+#include <rte_version.h>
 
 /* Forward declaration */
 struct ecore_dev;
@@ -450,7 +452,11 @@ u32 qede_crc32(u32 crc, u8 *ptr, u32 length);
 
 #define OSAL_DIV_S64(a, b)	((a) / (b))
 #define OSAL_LLDP_RX_TLVS(p_hwfn, tlv_buf, tlv_size) nothing
-#define OSAL_GET_EPOCH(p_hwfn)	0
+void qed_set_platform_str(struct ecore_hwfn *p_hwfn,
+			  char *buf_str, u32 buf_size);
+#define OSAL_SET_PLATFORM_STR(p_hwfn, buf_str, buf_size) \
+	qed_set_platform_str(p_hwfn, buf_str, buf_size)
+#define OSAL_GET_EPOCH(p_hwfn) ((u32)time(NULL))
 #define OSAL_DBG_ALLOC_USER_DATA(p_hwfn, user_data_ptr) (0)
 #define OSAL_DB_REC_OCCURRED(p_hwfn) nothing
 
diff --git a/drivers/net/qede/base/common_hsi.h b/drivers/net/qede/base/common_hsi.h
index e230fe5ac..1a02d460b 100644
--- a/drivers/net/qede/base/common_hsi.h
+++ b/drivers/net/qede/base/common_hsi.h
@@ -145,6 +145,7 @@
 #define NUM_OF_CONNECTION_TYPES (8)
 #define NUM_OF_TASK_TYPES       (8)
 #define NUM_OF_LCIDS            (320)
+#define NUM_OF_LTIDS            (320)
 
 /* Global PXP windows (GTT) */
 #define NUM_OF_GTT          19
diff --git a/drivers/net/qede/base/ecore.h b/drivers/net/qede/base/ecore.h
index dc5fe4d80..63bd7466a 100644
--- a/drivers/net/qede/base/ecore.h
+++ b/drivers/net/qede/base/ecore.h
@@ -576,6 +576,12 @@ enum BAR_ID {
 	BAR_ID_1	/* Used for doorbells */
 };
 
+struct ecore_nvm_image_info {
+	u32				num_images;
+	struct bist_nvm_image_att	*image_att;
+	bool				valid;
+};
+
 struct ecore_hwfn {
 	struct ecore_dev		*p_dev;
 	u8				my_id;		/* ID inside the PF */
@@ -701,6 +707,9 @@ struct ecore_hwfn {
 	 */
 	bool b_en_pacing;
 
+	/* Nvm images number and attributes */
+	struct ecore_nvm_image_info     nvm_info;
+
 	struct phys_mem_desc            *fw_overlay_mem;
 
 	/* @DPDK */
@@ -714,26 +723,34 @@ enum ecore_mf_mode {
 	ECORE_MF_UFP,
 };
 
-/* @DPDK */
-struct ecore_dbg_feature {
-	u8				*dump_buf;
-	u32				buf_size;
-	u32				dumped_dwords;
+enum ecore_dev_type {
+	ECORE_DEV_TYPE_BB,
+	ECORE_DEV_TYPE_AH,
 };
 
-enum qed_dbg_features {
-	DBG_FEATURE_BUS,
+/* @DPDK */
+enum ecore_dbg_features {
 	DBG_FEATURE_GRC,
 	DBG_FEATURE_IDLE_CHK,
 	DBG_FEATURE_MCP_TRACE,
 	DBG_FEATURE_REG_FIFO,
+	DBG_FEATURE_IGU_FIFO,
 	DBG_FEATURE_PROTECTION_OVERRIDE,
+	DBG_FEATURE_FW_ASSERTS,
+	DBG_FEATURE_ILT,
 	DBG_FEATURE_NUM
 };
 
-enum ecore_dev_type {
-	ECORE_DEV_TYPE_BB,
-	ECORE_DEV_TYPE_AH,
+struct ecore_dbg_feature {
+	u8				*dump_buf;
+	u32				buf_size;
+	u32				dumped_dwords;
+};
+
+struct ecore_dbg_params {
+	struct ecore_dbg_feature features[DBG_FEATURE_NUM];
+	u8 engine_for_debug;
+	bool print_data;
 };
 
 struct ecore_dev {
@@ -914,10 +931,12 @@ struct ecore_dev {
 	void				*firmware;
 	u64				fw_len;
 #endif
+	bool				disable_ilt_dump;
 
 	/* @DPDK */
 	struct ecore_dbg_feature	dbg_features[DBG_FEATURE_NUM];
-	u8				engine_for_debug;
+	struct ecore_dbg_params		dbg_params;
+	osal_mutex_t			dbg_lock;
 };
 
 enum ecore_hsi_def_type {
@@ -1067,6 +1086,17 @@ enum _ecore_status_t ecore_all_ppfids_wr(struct ecore_hwfn *p_hwfn,
 enum _ecore_status_t ecore_llh_dump_ppfid(struct ecore_dev *p_dev, u8 ppfid);
 enum _ecore_status_t ecore_llh_dump_all(struct ecore_dev *p_dev);
 
+/**
+ * @brief ecore_set_platform_str - Set the debug dump platform string.
+ * Write the ecore version and device's string to the given buffer.
+ *
+ * @param p_hwfn
+ * @param buf_str
+ * @param buf_size
+ */
+void ecore_set_platform_str(struct ecore_hwfn *p_hwfn,
+			    char *buf_str, u32 buf_size);
+
 #define TSTORM_QZONE_START	PXP_VF_BAR0_START_SDM_ZONE_A
 
 #define MSTORM_QZONE_START(dev) \
diff --git a/drivers/net/qede/base/ecore_cxt.c b/drivers/net/qede/base/ecore_cxt.c
index 23f37b1bf..d3025724b 100644
--- a/drivers/net/qede/base/ecore_cxt.c
+++ b/drivers/net/qede/base/ecore_cxt.c
@@ -2186,3 +2186,63 @@ static u16 ecore_blk_calculate_pages(struct ecore_ilt_cli_blk *p_blk)
 
 	return DIV_ROUND_UP(p_blk->total_size, p_blk->real_size_in_page);
 }
+
+u16 ecore_get_cdut_num_pf_init_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 i, pages = 0;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_PF_SEGMENTS; i++) {
+		p_blk = &p_cli->pf_blks[CDUT_FL_SEG_BLK(i, PF)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
+
+u16 ecore_get_cdut_num_vf_init_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 i, pages = 0;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_VF_SEGMENTS; i++) {
+		p_blk = &p_cli->vf_blks[CDUT_FL_SEG_BLK(i, VF)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
+
+u16 ecore_get_cdut_num_pf_work_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 i, pages = 0;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_PF_SEGMENTS; i++) {
+		p_blk = &p_cli->pf_blks[CDUT_SEG_BLK(i)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
+
+u16 ecore_get_cdut_num_vf_work_pages(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_ilt_client_cfg *p_cli;
+	struct ecore_ilt_cli_blk *p_blk;
+	u16 pages = 0, i;
+
+	p_cli = &p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUT];
+	for (i = 0; i < NUM_TASK_VF_SEGMENTS; i++) {
+		p_blk = &p_cli->vf_blks[CDUT_SEG_BLK(i)];
+		pages += ecore_blk_calculate_pages(p_blk);
+	}
+
+	return pages;
+}
diff --git a/drivers/net/qede/base/ecore_cxt.h b/drivers/net/qede/base/ecore_cxt.h
index f58c4ba57..1a539bbc7 100644
--- a/drivers/net/qede/base/ecore_cxt.h
+++ b/drivers/net/qede/base/ecore_cxt.h
@@ -345,4 +345,9 @@ struct ecore_cxt_mngr {
 	u16				task_ctx_size;
 	u16				conn_ctx_size;
 };
+
+u16 ecore_get_cdut_num_pf_init_pages(struct ecore_hwfn *p_hwfn);
+u16 ecore_get_cdut_num_vf_init_pages(struct ecore_hwfn *p_hwfn);
+u16 ecore_get_cdut_num_pf_work_pages(struct ecore_hwfn *p_hwfn);
+u16 ecore_get_cdut_num_vf_work_pages(struct ecore_hwfn *p_hwfn);
 #endif /* _ECORE_CID_ */
diff --git a/drivers/net/qede/base/ecore_dev.c b/drivers/net/qede/base/ecore_dev.c
index 814d9ced6..35a8394de 100644
--- a/drivers/net/qede/base/ecore_dev.c
+++ b/drivers/net/qede/base/ecore_dev.c
@@ -6798,6 +6798,19 @@ void ecore_set_fw_mac_addr(__le16 *fw_msb,
 	((u8 *)fw_lsb)[1] = mac[4];
 }
 
+void ecore_set_platform_str(struct ecore_hwfn *p_hwfn,
+			    char *buf_str, u32 buf_size)
+{
+	u32 len;
+
+	OSAL_SNPRINTF(buf_str, buf_size, "Ecore %d.%d.%d.%d. ",
+		      ECORE_MAJOR_VERSION, ECORE_MINOR_VERSION,
+		      ECORE_REVISION_VERSION, ECORE_ENGINEERING_VERSION);
+
+	len = OSAL_STRLEN(buf_str);
+	OSAL_SET_PLATFORM_STR(p_hwfn, &buf_str[len], buf_size - len);
+}
+
 bool ecore_is_mf_fip_special(struct ecore_dev *p_dev)
 {
 	return !!OSAL_GET_BIT(ECORE_MF_FIP_SPECIAL, &p_dev->mf_bits);
diff --git a/drivers/net/qede/base/ecore_hsi_common.h b/drivers/net/qede/base/ecore_hsi_common.h
index 23cfcdeff..578c798a9 100644
--- a/drivers/net/qede/base/ecore_hsi_common.h
+++ b/drivers/net/qede/base/ecore_hsi_common.h
@@ -10,6 +10,7 @@
 /* Add include to common target */
 /********************************/
 #include "common_hsi.h"
+#include "mcp_public.h"
 
 
 /*
@@ -2229,7 +2230,40 @@ struct fw_info_location {
 };
 
 
-
+/* DMAE parameters */
+struct ecore_dmae_params {
+	u32 flags;
+/* If QED_DMAE_PARAMS_RW_REPL_SRC flag is set and the
+ * source is a block of length DMAE_MAX_RW_SIZE and the
+ * destination is larger, the source block will be duplicated as
+ * many times as required to fill the destination block. This is
+ * used mostly to write a zeroed buffer to destination address
+ * using DMA
+ */
+#define ECORE_DMAE_PARAMS_RW_REPL_SRC_MASK        0x1
+#define ECORE_DMAE_PARAMS_RW_REPL_SRC_SHIFT       0
+#define ECORE_DMAE_PARAMS_SRC_VF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_SRC_VF_VALID_SHIFT      1
+#define ECORE_DMAE_PARAMS_DST_VF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_DST_VF_VALID_SHIFT      2
+#define ECORE_DMAE_PARAMS_COMPLETION_DST_MASK     0x1
+#define ECORE_DMAE_PARAMS_COMPLETION_DST_SHIFT    3
+#define ECORE_DMAE_PARAMS_PORT_VALID_MASK         0x1
+#define ECORE_DMAE_PARAMS_PORT_VALID_SHIFT        4
+#define ECORE_DMAE_PARAMS_SRC_PF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_SRC_PF_VALID_SHIFT      5
+#define ECORE_DMAE_PARAMS_DST_PF_VALID_MASK       0x1
+#define ECORE_DMAE_PARAMS_DST_PF_VALID_SHIFT      6
+#define ECORE_DMAE_PARAMS_RESERVED_MASK           0x1FFFFFF
+#define ECORE_DMAE_PARAMS_RESERVED_SHIFT          7
+	u8 src_vfid;
+	u8 dst_vfid;
+	u8 port_id;
+	u8 src_pfid;
+	u8 dst_pfid;
+	u8 reserved1;
+	__le16 reserved2;
+};
 
 /*
  * IGU cleanup command
@@ -2543,4 +2577,152 @@ struct ystorm_core_conn_ag_ctx {
 	__le32 reg3 /* reg3 */;
 };
 
+/*********/
+/* DEBUG */
+/*********/
+
+#define MFW_TRACE_SIGNATURE	0x25071946
+
+/* The trace in the buffer */
+#define MFW_TRACE_EVENTID_MASK		0x00ffff
+#define MFW_TRACE_PRM_SIZE_MASK		0x0f0000
+#define MFW_TRACE_PRM_SIZE_OFFSET	16
+#define MFW_TRACE_ENTRY_SIZE		3
+
+struct mcp_trace {
+	u32	signature;	/* Help to identify that the trace is valid */
+	u32	size;		/* the size of the trace buffer in bytes*/
+	u32	curr_level;	/* 2 - all will be written to the buffer
+				 * 1 - debug trace will not be written
+				 * 0 - just errors will be written to the buffer
+				 */
+	/* a bit per module, 1 means mask it off, 0 means add it to the trace
+	 * buffer
+	 */
+	u32	modules_mask[2];
+
+	/* Warning: the following pointers are assumed to be 32bits as they are
+	 * used only in the MFW
+	 */
+	/* The next trace will be written to this offset */
+	u32	trace_prod;
+	/* The oldest valid trace starts at this offset (usually very close
+	 * after the current producer)
+	 */
+	u32	trace_oldest;
+};
+
+enum spad_sections {
+	SPAD_SECTION_TRACE,
+	SPAD_SECTION_NVM_CFG,
+	SPAD_SECTION_PUBLIC,
+	SPAD_SECTION_PRIVATE,
+	SPAD_SECTION_MAX
+};
+
+#define MCP_TRACE_SIZE          2048    /* 2kb */
+
+/* This section is located at a fixed location in the beginning of the
+ * scratchpad, to ensure that the MCP trace is not run over during MFW upgrade.
+ * All the rest of data has a floating location which differs from version to
+ * version, and is pointed by the mcp_meta_data below.
+ * Moreover, the spad_layout section is part of the MFW firmware, and is loaded
+ * with it from nvram in order to clear this portion.
+ */
+struct static_init {
+	u32 num_sections;
+	offsize_t sections[SPAD_SECTION_MAX];
+#define SECTION(_sec_) (*((offsize_t *)(STRUCT_OFFSET(sections[_sec_]))))
+
+	struct mcp_trace trace;
+#define MCP_TRACE_P ((struct mcp_trace *)(STRUCT_OFFSET(trace)))
+	u8 trace_buffer[MCP_TRACE_SIZE];
+#define MCP_TRACE_BUF ((u8 *)(STRUCT_OFFSET(trace_buffer)))
+	/* running_mfw has the same definition as in nvm_map.h.
+	 * This bit indicate both the running dir, and the running bundle.
+	 * It is set once when the LIM is loaded.
+	 */
+	u32 running_mfw;
+#define RUNNING_MFW (*((u32 *)(STRUCT_OFFSET(running_mfw))))
+	u32 build_time;
+#define MFW_BUILD_TIME (*((u32 *)(STRUCT_OFFSET(build_time))))
+	u32 reset_type;
+#define RESET_TYPE (*((u32 *)(STRUCT_OFFSET(reset_type))))
+	u32 mfw_secure_mode;
+#define MFW_SECURE_MODE (*((u32 *)(STRUCT_OFFSET(mfw_secure_mode))))
+	u16 pme_status_pf_bitmap;
+#define PME_STATUS_PF_BITMAP (*((u16 *)(STRUCT_OFFSET(pme_status_pf_bitmap))))
+	u16 pme_enable_pf_bitmap;
+#define PME_ENABLE_PF_BITMAP (*((u16 *)(STRUCT_OFFSET(pme_enable_pf_bitmap))))
+	u32 mim_nvm_addr;
+	u32 mim_start_addr;
+	u32 ah_pcie_link_params;
+#define AH_PCIE_LINK_PARAMS_LINK_SPEED_MASK     (0x000000ff)
+#define AH_PCIE_LINK_PARAMS_LINK_SPEED_SHIFT    (0)
+#define AH_PCIE_LINK_PARAMS_LINK_WIDTH_MASK     (0x0000ff00)
+#define AH_PCIE_LINK_PARAMS_LINK_WIDTH_SHIFT    (8)
+#define AH_PCIE_LINK_PARAMS_ASPM_MODE_MASK      (0x00ff0000)
+#define AH_PCIE_LINK_PARAMS_ASPM_MODE_SHIFT     (16)
+#define AH_PCIE_LINK_PARAMS_ASPM_CAP_MASK       (0xff000000)
+#define AH_PCIE_LINK_PARAMS_ASPM_CAP_SHIFT      (24)
+#define AH_PCIE_LINK_PARAMS (*((u32 *)(STRUCT_OFFSET(ah_pcie_link_params))))
+
+	u32 rsrv_persist[5];	/* Persist reserved for MFW upgrades */
+};
+
+#define NVM_MAGIC_VALUE		0x669955aa
+
+enum nvm_image_type {
+	NVM_TYPE_TIM1 = 0x01,
+	NVM_TYPE_TIM2 = 0x02,
+	NVM_TYPE_MIM1 = 0x03,
+	NVM_TYPE_MIM2 = 0x04,
+	NVM_TYPE_MBA = 0x05,
+	NVM_TYPE_MODULES_PN = 0x06,
+	NVM_TYPE_VPD = 0x07,
+	NVM_TYPE_MFW_TRACE1 = 0x08,
+	NVM_TYPE_MFW_TRACE2 = 0x09,
+	NVM_TYPE_NVM_CFG1 = 0x0a,
+	NVM_TYPE_L2B = 0x0b,
+	NVM_TYPE_DIR1 = 0x0c,
+	NVM_TYPE_EAGLE_FW1 = 0x0d,
+	NVM_TYPE_FALCON_FW1 = 0x0e,
+	NVM_TYPE_PCIE_FW1 = 0x0f,
+	NVM_TYPE_HW_SET = 0x10,
+	NVM_TYPE_LIM = 0x11,
+	NVM_TYPE_AVS_FW1 = 0x12,
+	NVM_TYPE_DIR2 = 0x13,
+	NVM_TYPE_CCM = 0x14,
+	NVM_TYPE_EAGLE_FW2 = 0x15,
+	NVM_TYPE_FALCON_FW2 = 0x16,
+	NVM_TYPE_PCIE_FW2 = 0x17,
+	NVM_TYPE_AVS_FW2 = 0x18,
+	NVM_TYPE_INIT_HW = 0x19,
+	NVM_TYPE_DEFAULT_CFG = 0x1a,
+	NVM_TYPE_MDUMP = 0x1b,
+	NVM_TYPE_META = 0x1c,
+	NVM_TYPE_ISCSI_CFG = 0x1d,
+	NVM_TYPE_FCOE_CFG = 0x1f,
+	NVM_TYPE_ETH_PHY_FW1 = 0x20,
+	NVM_TYPE_ETH_PHY_FW2 = 0x21,
+	NVM_TYPE_BDN = 0x22,
+	NVM_TYPE_8485X_PHY_FW = 0x23,
+	NVM_TYPE_PUB_KEY = 0x24,
+	NVM_TYPE_RECOVERY = 0x25,
+	NVM_TYPE_PLDM = 0x26,
+	NVM_TYPE_UPK1 = 0x27,
+	NVM_TYPE_UPK2 = 0x28,
+	NVM_TYPE_MASTER_KC = 0x29,
+	NVM_TYPE_BACKUP_KC = 0x2a,
+	NVM_TYPE_HW_DUMP = 0x2b,
+	NVM_TYPE_HW_DUMP_OUT = 0x2c,
+	NVM_TYPE_BIN_NVM_META = 0x30,
+	NVM_TYPE_ROM_TEST = 0xf0,
+	NVM_TYPE_88X33X0_PHY_FW = 0x31,
+	NVM_TYPE_88X33X0_PHY_SLAVE_FW = 0x32,
+	NVM_TYPE_MAX,
+};
+
+#define DIR_ID_1    (0)
+
 #endif /* __ECORE_HSI_COMMON__ */
diff --git a/drivers/net/qede/base/ecore_hsi_debug_tools.h b/drivers/net/qede/base/ecore_hsi_debug_tools.h
index eb72e93cf..c5ef67f84 100644
--- a/drivers/net/qede/base/ecore_hsi_debug_tools.h
+++ b/drivers/net/qede/base/ecore_hsi_debug_tools.h
@@ -245,6 +245,7 @@ struct dbg_mode_hdr {
  * Attention register
  */
 struct dbg_attn_reg {
+	struct dbg_mode_hdr mode /* Mode header */;
 /* The offset of this registers attentions within the blocks attentions list
  * (a value in the range 0..number of block attentions-1)
  */
@@ -1049,5 +1050,4 @@ struct dbg_tools_data {
 };
 
 
-
 #endif /* __ECORE_HSI_DEBUG_TOOLS__ */
diff --git a/drivers/net/qede/base/ecore_mcp.c b/drivers/net/qede/base/ecore_mcp.c
index 0a9e26805..cab089d81 100644
--- a/drivers/net/qede/base/ecore_mcp.c
+++ b/drivers/net/qede/base/ecore_mcp.c
@@ -3621,6 +3621,217 @@ enum _ecore_status_t ecore_mcp_bist_nvm_test_get_image_att(
 	return rc;
 }
 
+enum _ecore_status_t
+ecore_mcp_bist_nvm_get_num_images(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt, u32 *num_images)
+{
+	u32 drv_mb_param = 0, rsp;
+	enum _ecore_status_t rc = ECORE_SUCCESS;
+
+	SET_MFW_FIELD(drv_mb_param, DRV_MB_PARAM_BIST_TEST_INDEX,
+		      DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES);
+
+	rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
+			   drv_mb_param, &rsp, num_images);
+	if (rc != ECORE_SUCCESS)
+		return rc;
+
+	if (rsp == FW_MSG_CODE_UNSUPPORTED)
+		rc = ECORE_NOTIMPL;
+	else if (rsp != FW_MSG_CODE_OK)
+		rc = ECORE_UNKNOWN_ERROR;
+
+	return rc;
+}
+
+enum _ecore_status_t
+ecore_mcp_bist_nvm_get_image_att(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 struct bist_nvm_image_att *p_image_att,
+				 u32 image_index)
+{
+	u32 buf_size, nvm_offset = 0, resp, param;
+	enum _ecore_status_t rc;
+
+	SET_MFW_FIELD(nvm_offset, DRV_MB_PARAM_BIST_TEST_INDEX,
+		      DRV_MB_PARAM_BIST_NVM_TEST_IMAGE_BY_INDEX);
+	SET_MFW_FIELD(nvm_offset, DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX,
+		      image_index);
+	rc = ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
+				  nvm_offset, &resp, &param, &buf_size,
+				  (u32 *)p_image_att);
+	if (rc != ECORE_SUCCESS)
+		return rc;
+
+	if (resp == FW_MSG_CODE_UNSUPPORTED)
+		rc = ECORE_NOTIMPL;
+	else if ((resp != FW_MSG_CODE_OK) || (p_image_att->return_code != 1))
+		rc = ECORE_UNKNOWN_ERROR;
+
+	return rc;
+}
+
+enum _ecore_status_t ecore_mcp_nvm_info_populate(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_nvm_image_info nvm_info;
+	struct ecore_ptt *p_ptt;
+	enum _ecore_status_t rc;
+	u32 i;
+
+	if (p_hwfn->nvm_info.valid)
+		return ECORE_SUCCESS;
+
+#ifndef ASIC_ONLY
+	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev) ||
+	    CHIP_REV_IS_TEDIBEAR(p_hwfn->p_dev))
+		return ECORE_SUCCESS;
+#endif
+
+	p_ptt = ecore_ptt_acquire(p_hwfn);
+	if (!p_ptt) {
+		DP_ERR(p_hwfn, "failed to acquire ptt\n");
+		return ECORE_BUSY;
+	}
+
+	/* Acquire from MFW the amount of available images */
+	OSAL_MEM_ZERO(&nvm_info, sizeof(nvm_info));
+	rc = ecore_mcp_bist_nvm_get_num_images(p_hwfn, p_ptt,
+					       &nvm_info.num_images);
+	if (rc == ECORE_NOTIMPL) {
+		DP_INFO(p_hwfn, "DRV_MSG_CODE_BIST_TEST is not supported\n");
+		goto out;
+	} else if ((rc != ECORE_SUCCESS) || (nvm_info.num_images == 0)) {
+		DP_ERR(p_hwfn, "Failed getting number of images\n");
+		goto err0;
+	}
+
+	nvm_info.image_att = OSAL_ALLOC(p_hwfn->p_dev, GFP_KERNEL,
+					 nvm_info.num_images *
+					 sizeof(struct bist_nvm_image_att));
+	if (!nvm_info.image_att) {
+		rc = ECORE_NOMEM;
+		goto err0;
+	}
+
+	/* Iterate over images and get their attributes */
+	for (i = 0; i < nvm_info.num_images; i++) {
+		rc = ecore_mcp_bist_nvm_get_image_att(p_hwfn, p_ptt,
+						      &nvm_info.image_att[i],
+						      i);
+		if (rc != ECORE_SUCCESS) {
+			DP_ERR(p_hwfn,
+			       "Failed getting image index %d attributes\n",
+			       i);
+			goto err1;
+		}
+
+		DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "image index %d, size %x\n", i,
+			   nvm_info.image_att[i].len);
+	}
+out:
+	/* Update hwfn's nvm_info */
+	if (nvm_info.num_images) {
+		p_hwfn->nvm_info.num_images = nvm_info.num_images;
+		if (p_hwfn->nvm_info.image_att)
+			OSAL_FREE(p_hwfn->p_dev, p_hwfn->nvm_info.image_att);
+		p_hwfn->nvm_info.image_att = nvm_info.image_att;
+		p_hwfn->nvm_info.valid = true;
+	}
+
+	ecore_ptt_release(p_hwfn, p_ptt);
+	return ECORE_SUCCESS;
+
+err1:
+	OSAL_FREE(p_hwfn->p_dev, nvm_info.image_att);
+err0:
+	ecore_ptt_release(p_hwfn, p_ptt);
+	return rc;
+}
+
+enum _ecore_status_t
+ecore_mcp_get_nvm_image_att(struct ecore_hwfn *p_hwfn,
+			    enum ecore_nvm_images image_id,
+			    struct ecore_nvm_image_att *p_image_att)
+{
+	enum nvm_image_type type;
+	u32 i;
+
+	/* Translate image_id into MFW definitions */
+	switch (image_id) {
+	case ECORE_NVM_IMAGE_ISCSI_CFG:
+		type = NVM_TYPE_ISCSI_CFG;
+		break;
+	case ECORE_NVM_IMAGE_FCOE_CFG:
+		type = NVM_TYPE_FCOE_CFG;
+		break;
+	case ECORE_NVM_IMAGE_MDUMP:
+		type = NVM_TYPE_MDUMP;
+		break;
+	case ECORE_NVM_IMAGE_NVM_CFG1:
+		type = NVM_TYPE_NVM_CFG1;
+		break;
+	case ECORE_NVM_IMAGE_DEFAULT_CFG:
+		type = NVM_TYPE_DEFAULT_CFG;
+		break;
+	case ECORE_NVM_IMAGE_NVM_META:
+		type = NVM_TYPE_META;
+		break;
+	default:
+		DP_NOTICE(p_hwfn, false, "Unknown request of image_id %08x\n",
+			  image_id);
+		return ECORE_INVAL;
+	}
+
+	ecore_mcp_nvm_info_populate(p_hwfn);
+	for (i = 0; i < p_hwfn->nvm_info.num_images; i++) {
+		if (type == p_hwfn->nvm_info.image_att[i].image_type)
+			break;
+	}
+	if (i == p_hwfn->nvm_info.num_images) {
+		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
+			   "Failed to find nvram image of type %08x\n",
+			   image_id);
+		return ECORE_NOENT;
+	}
+
+	p_image_att->start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr;
+	p_image_att->length = p_hwfn->nvm_info.image_att[i].len;
+
+	return ECORE_SUCCESS;
+}
+
+enum _ecore_status_t ecore_mcp_get_nvm_image(struct ecore_hwfn *p_hwfn,
+					     enum ecore_nvm_images image_id,
+					     u8 *p_buffer, u32 buffer_len)
+{
+	struct ecore_nvm_image_att image_att;
+	enum _ecore_status_t rc;
+
+	OSAL_MEM_ZERO(p_buffer, buffer_len);
+
+	rc = ecore_mcp_get_nvm_image_att(p_hwfn, image_id, &image_att);
+	if (rc != ECORE_SUCCESS)
+		return rc;
+
+	/* Validate sizes - both the image's and the supplied buffer's */
+	if (image_att.length <= 4) {
+		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
+			   "Image [%d] is too small - only %d bytes\n",
+			   image_id, image_att.length);
+		return ECORE_INVAL;
+	}
+
+	if (image_att.length > buffer_len) {
+		DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
+			   "Image [%d] is too big - %08x bytes where only %08x are available\n",
+			   image_id, image_att.length, buffer_len);
+		return ECORE_NOMEM;
+	}
+
+	return ecore_mcp_nvm_read(p_hwfn->p_dev, image_att.start_addr,
+				  (u8 *)p_buffer, image_att.length);
+}
+
 enum _ecore_status_t
 ecore_mcp_get_temperature_info(struct ecore_hwfn *p_hwfn,
 			       struct ecore_ptt *p_ptt,
diff --git a/drivers/net/qede/base/ecore_mcp_api.h b/drivers/net/qede/base/ecore_mcp_api.h
index dc889ab8e..c3922ba43 100644
--- a/drivers/net/qede/base/ecore_mcp_api.h
+++ b/drivers/net/qede/base/ecore_mcp_api.h
@@ -121,6 +121,10 @@ struct ecore_mcp_function_info {
 enum ecore_nvm_images {
 	ECORE_NVM_IMAGE_ISCSI_CFG,
 	ECORE_NVM_IMAGE_FCOE_CFG,
+	ECORE_NVM_IMAGE_MDUMP,
+	ECORE_NVM_IMAGE_NVM_CFG1,
+	ECORE_NVM_IMAGE_DEFAULT_CFG,
+	ECORE_NVM_IMAGE_NVM_META,
 };
 #endif
 
@@ -970,6 +974,39 @@ enum _ecore_status_t ecore_mcp_phy_read(struct ecore_dev *p_dev, u32 cmd,
 enum _ecore_status_t ecore_mcp_nvm_read(struct ecore_dev *p_dev, u32 addr,
 			   u8 *p_buf, u32 len);
 
+struct ecore_nvm_image_att {
+	u32 start_addr;
+	u32 length;
+};
+
+/**
+ * @brief Allows reading a whole nvram image
+ *
+ * @param p_hwfn
+ * @param image_id - image to get attributes for
+ * @param p_image_att - image attributes structure into which to fill data
+ *
+ * @return enum _ecore_status_t - ECORE_SUCCESS - operation was successful.
+ */
+enum _ecore_status_t
+ecore_mcp_get_nvm_image_att(struct ecore_hwfn *p_hwfn,
+			    enum ecore_nvm_images image_id,
+			    struct ecore_nvm_image_att *p_image_att);
+
+/**
+ * @brief Allows reading a whole nvram image
+ *
+ * @param p_hwfn
+ * @param image_id - image requested for reading
+ * @param p_buffer - allocated buffer into which to fill data
+ * @param buffer_len - length of the allocated buffer.
+ *
+ * @return ECORE_SUCCESS if p_buffer now contains the nvram image.
+ */
+enum _ecore_status_t ecore_mcp_get_nvm_image(struct ecore_hwfn *p_hwfn,
+					     enum ecore_nvm_images image_id,
+					     u8 *p_buffer, u32 buffer_len);
+
 /**
  * @brief - Sends an NVM write command request to the MFW with
  *          payload.
diff --git a/drivers/net/qede/base/ecore_status.h b/drivers/net/qede/base/ecore_status.h
index b893f1d41..01cf9fd31 100644
--- a/drivers/net/qede/base/ecore_status.h
+++ b/drivers/net/qede/base/ecore_status.h
@@ -8,6 +8,8 @@
 #define __ECORE_STATUS_H__
 
 enum _ecore_status_t {
+	ECORE_NOENT = -15,
+	ECORE_CONN_REFUSED = -14,
 	ECORE_CONN_RESET = -13,
 	ECORE_UNKNOWN_ERROR  = -12,
 	ECORE_NORESOURCES	 = -11,
diff --git a/drivers/net/qede/base/reg_addr.h b/drivers/net/qede/base/reg_addr.h
index 91d889dc8..c84d3865f 100644
--- a/drivers/net/qede/base/reg_addr.h
+++ b/drivers/net/qede/base/reg_addr.h
@@ -1245,3 +1245,849 @@
 #define DORQ_REG_VF_USAGE_CNT_LIM 0x1009ccUL
 #define PGLUE_B_REG_SR_IOV_DISABLED_REQUEST 0x2aa06cUL
 #define PGLUE_B_REG_SR_IOV_DISABLED_REQUEST_CLR 0x2aa070UL
+
+#define PSWRQ2_REG_ILT_MEMORY_SIZE_BB 15200
+#define PSWRQ2_REG_ILT_MEMORY_SIZE_K2 22000
+#define TSEM_REG_DBG_GPRE_VECT 0x1701410UL
+#define MSEM_REG_DBG_GPRE_VECT 0x1801410UL
+#define USEM_REG_DBG_GPRE_VECT 0x1901410UL
+#define XSEM_REG_DBG_GPRE_VECT 0x1401410UL
+#define YSEM_REG_DBG_GPRE_VECT 0x1501410UL
+#define PSEM_REG_DBG_GPRE_VECT 0x1601410UL
+#define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE 0x000748UL
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_WRITE_DISABLE (0x1UL << 0)
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_WRITE_DISABLE_SHIFT 0
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_READ_DISABLE (0x1UL << 1)
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_DRA_READ_DISABLE_SHIFT 1
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_INTERRUPT_DISABLE (0x1UL << 2)
+  #define SEM_FAST_REG_DBG_MODE23_SRC_DISABLE_INTERRUPT_DISABLE_SHIFT 2
+#define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE 0x00074cUL
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_STORE_DATA_DISABLE (0x1UL << 0)
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_STORE_DATA_DISABLE_SHIFT 0
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_LOAD_DATA_DISABLE (0x1UL << 1)
+  #define SEM_FAST_REG_DBG_MODE4_SRC_DISABLE_LOAD_DATA_DISABLE_SHIFT 1
+#define NWS_REG_NWS_CMU_K2 0x720000UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_7_0_K2 0x000680UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_15_8_K2 0x000684UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_7_0_K2 0x0006c0UL
+#define PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_11_8_K2 0x0006c4UL
+#define MS_REG_MS_CMU_K2 0x6a4000UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X132_K2 0x000210UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X133_K2 0x000214UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X130_K2 0x000208UL
+#define PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X131_K2 0x00020cUL
+#define PHY_PCIE_REG_PHY0_K2 0x620000UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2 0x000210UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2 0x000214UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2 0x000208UL
+#define PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2 0x00020cUL
+#define PHY_PCIE_REG_PHY1_K2 0x624000UL
+#define PCIE_REG_DBG_REPEAT_THRESHOLD_COUNT_K2 0x054364UL
+#define PCIE_REG_DBG_FW_TRIGGER_ENABLE_K2 0x05436cUL
+#define RDIF_REG_DEBUG_ERROR_INFO 0x300400UL
+#define RDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define RDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define TDIF_REG_DEBUG_ERROR_INFO 0x310400UL
+#define TDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define TDIF_REG_DEBUG_ERROR_INFO_SIZE 64
+#define SEM_FAST_REG_VFC_STATUS 0x000b4cUL
+  #define SEM_FAST_REG_VFC_STATUS_RESPONSE_READY (0x1UL << 0)
+  #define SEM_FAST_REG_VFC_STATUS_RESPONSE_READY_SHIFT 0
+  #define SEM_FAST_REG_VFC_STATUS_VFC_BUSY (0x1UL << 1)
+  #define SEM_FAST_REG_VFC_STATUS_VFC_BUSY_SHIFT 1
+  #define SEM_FAST_REG_VFC_STATUS_SENDING_CMD_ON_GOING (0x1UL << 2)
+  #define SEM_FAST_REG_VFC_STATUS_SENDING_CMD_ON_GOING_SHIFT 2
+#define RSS_REG_RSS_RAM_DATA_SIZE 4
+#define BRB_REG_BIG_RAM_DATA_SIZE 64
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_1 0x0084c0UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_1_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_2 0x0084e4UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_2_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_3 0x008508UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_3_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_4 0x00852cUL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_4_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_5 0x008550UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_5_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_6 0x008574UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_6_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_IGU_OUT_7 0x008598UL
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_IGU_OUT_7_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_NIG 0x0085bcUL
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_NIG_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_PXP 0x0085e0UL
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_PXP_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_MCP_OUT_0 0x008628UL
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_MCP_OUT_0_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR 0x008748UL
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_GLB_UNC_ERR_GPIO31_SHIFT 31
+#define MISC_REG_AEU_ENABLE1_SYS_KILL 0x008604UL
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO0 (0x1UL << 0)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO0_SHIFT 0
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO1 (0x1UL << 1)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO1_SHIFT 1
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO2 (0x1UL << 2)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO2_SHIFT 2
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO3 (0x1UL << 3)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO3_SHIFT 3
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO4 (0x1UL << 4)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO4_SHIFT 4
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO5 (0x1UL << 5)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO5_SHIFT 5
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO6 (0x1UL << 6)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO6_SHIFT 6
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO (0x1UL << 7)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO_SHIFT 7
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO8 (0x1UL << 8)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO8_SHIFT 8
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO9 (0x1UL << 9)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO9_SHIFT 9
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO10 (0x1UL << 10)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO10_SHIFT 10
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO11 (0x1UL << 11)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO11_SHIFT 11
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO12 (0x1UL << 12)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO12_SHIFT 12
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO13 (0x1UL << 13)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO13_SHIFT 13
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO14 (0x1UL << 14)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO14_SHIFT 14
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO15 (0x1UL << 15)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO15_SHIFT 15
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO16 (0x1UL << 16)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO16_SHIFT 16
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO17 (0x1UL << 17)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO17_SHIFT 17
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO18 (0x1UL << 18)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO18_SHIFT 18
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO19 (0x1UL << 19)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO19_SHIFT 19
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO20 (0x1UL << 20)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO20_SHIFT 20
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO21 (0x1UL << 21)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO21_SHIFT 21
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO22 (0x1UL << 22)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO22_SHIFT 22
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO23 (0x1UL << 23)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO23_SHIFT 23
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO24 (0x1UL << 24)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO24_SHIFT 24
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO25 (0x1UL << 25)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO25_SHIFT 25
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO26 (0x1UL << 26)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO26_SHIFT 26
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO27 (0x1UL << 27)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO27_SHIFT 27
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO28 (0x1UL << 28)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO28_SHIFT 28
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO29 (0x1UL << 29)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO29_SHIFT 29
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO30 (0x1UL << 30)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO30_SHIFT 30
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO31 (0x1UL << 31)
+  #define MISC_REG_AEU_ENABLE1_SYS_KILL_GPIO31_SHIFT 31
+#define DBG_REG_FULL_BUFFER_THR 0x01045cUL
+#define MISC_REG_AEU_MASK_ATTN_MCP 0x008498UL
+#define MISC_REG_AEU_SYS_KILL_BEHAVIOR 0x008800UL
+#define MISC_REG_AEU_GENERAL_MASK 0x008828UL
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_PXP_CLOSE_MASK (0x1UL << 0)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_PXP_CLOSE_MASK_SHIFT 0
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_NIG_CLOSE_MASK (0x1UL << 1)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_NIG_CLOSE_MASK_SHIFT 1
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_SYS_KILL_MASK (0x1UL << 2)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_SYS_KILL_MASK_SHIFT 2
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_GLB_UNC_ERR_MASK (0x1UL << 3)
+  #define MISC_REG_AEU_GENERAL_MASK_AEU_GLB_UNC_ERR_MASK_SHIFT 3
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 7f5a34bcb..b5d6c7c43 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -7,7 +7,6 @@
 #include "qede_ethdev.h"
 #include <rte_string_fns.h>
 #include <rte_alarm.h>
-#include <rte_version.h>
 #include <rte_kvargs.h>
 
 static const struct qed_eth_ops *qed_ops;
diff --git a/drivers/net/qede/qede_main.c b/drivers/net/qede/qede_main.c
index 02f70beb3..51aa639c6 100644
--- a/drivers/net/qede/qede_main.c
+++ b/drivers/net/qede/qede_main.c
@@ -5,7 +5,6 @@
  */
 
 #include <limits.h>
-#include <time.h>
 #include <rte_alarm.h>
 #include <rte_string_fns.h>
 
@@ -66,7 +65,7 @@ qed_probe(struct ecore_dev *edev, struct rte_pci_device *pci_dev,
 	hw_prepare_params.initiate_pf_flr = true;
 	hw_prepare_params.allow_mdump = false;
 	hw_prepare_params.b_en_pacing = false;
-	hw_prepare_params.epoch = (u32)time(NULL);
+	hw_prepare_params.epoch = OSAL_GET_EPOCH(ECORE_LEADING_HWFN(edev));
 	rc = ecore_hw_prepare(edev, &hw_prepare_params);
 	if (rc) {
 		DP_ERR(edev, "hw prepare failed\n");
-- 
2.18.0


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

* [dpdk-dev] [PATCH v5 3/4] net/qede: add infrastructure for debug data collection
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 " Rasesh Mody
                         ` (2 preceding siblings ...)
  2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 2/4] net/qede/base: add changes for debug data collection Rasesh Mody
@ 2020-07-08 22:50       ` Rasesh Mody
  2020-07-09 16:37         ` Ferruh Yigit
  2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 4/4] net/qede: add support for get register operation Rasesh Mody
  4 siblings, 1 reply; 37+ messages in thread
From: Rasesh Mody @ 2020-07-08 22:50 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

The patch adds QEDE PMD ops and APIs to calculate the size and collect
the debug dump for various firmware components. The patch adds new files
qede_debug.[ch] that has all the firmware debug data collection
infrastructure changes.

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 drivers/net/qede/Makefile        |    4 +-
 drivers/net/qede/base/bcm_osal.h |    5 +-
 drivers/net/qede/meson.build     |    5 +
 drivers/net/qede/qede_debug.c    | 8120 ++++++++++++++++++++++++++++++
 drivers/net/qede/qede_debug.h    |  759 +++
 drivers/net/qede/qede_if.h       |   45 +
 drivers/net/qede/qede_main.c     |   39 +-
 7 files changed, 8973 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/qede/qede_debug.c
 create mode 100644 drivers/net/qede/qede_debug.h

diff --git a/drivers/net/qede/Makefile b/drivers/net/qede/Makefile
index 5810b4d49..3b00338ff 100644
--- a/drivers/net/qede/Makefile
+++ b/drivers/net/qede/Makefile
@@ -11,7 +11,6 @@ include $(RTE_SDK)/mk/rte.vars.mk
 LIB = librte_pmd_qede.a
 
 CFLAGS += -O3
-CFLAGS += $(WERROR_FLAGS)
 LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
 LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs
 LDLIBS += -lrte_bus_pci
@@ -37,7 +36,6 @@ CFLAGS_BASE_DRIVER += -Wno-missing-prototypes
 
 ifneq ($(CONFIG_RTE_TOOLCHAIN_ICC),y)
 CFLAGS_BASE_DRIVER += -Wno-unused-value
-CFLAGS_BASE_DRIVER += -Wno-format-nonliteral
 ifeq ($(OS_TYPE),Linux)
 ifeq ($(shell clang -Wno-shift-negative-value -Werror -E - < /dev/null > /dev/null 2>&1; echo $$?),0)
 CFLAGS_BASE_DRIVER += -Wno-shift-negative-value
@@ -48,6 +46,7 @@ endif
 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
 ifeq ($(shell test $(GCC_VERSION) -ge 44 && echo 1), 1)
 CFLAGS_BASE_DRIVER += -Wno-unused-but-set-variable
+CFLAGS += -Wno-format-nonliteral
 endif
 CFLAGS_BASE_DRIVER += -Wno-missing-declarations
 ifeq ($(shell test $(GCC_VERSION) -ge 46 && echo 1), 1)
@@ -104,5 +103,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_ethdev.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_main.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_rxtx.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_filter.c
+SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_debug.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index 6ea3e7dda..b4b94231b 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -457,7 +457,10 @@ void qed_set_platform_str(struct ecore_hwfn *p_hwfn,
 #define OSAL_SET_PLATFORM_STR(p_hwfn, buf_str, buf_size) \
 	qed_set_platform_str(p_hwfn, buf_str, buf_size)
 #define OSAL_GET_EPOCH(p_hwfn) ((u32)time(NULL))
-#define OSAL_DBG_ALLOC_USER_DATA(p_hwfn, user_data_ptr) (0)
+enum dbg_status	qed_dbg_alloc_user_data(struct ecore_hwfn *p_hwfn,
+					void **user_data_ptr);
+#define OSAL_DBG_ALLOC_USER_DATA(p_hwfn, user_data_ptr) \
+	qed_dbg_alloc_user_data(p_hwfn, user_data_ptr)
 #define OSAL_DB_REC_OCCURRED(p_hwfn) nothing
 
 #endif /* __BCM_OSAL_H */
diff --git a/drivers/net/qede/meson.build b/drivers/net/qede/meson.build
index 12388a680..50c9fad7e 100644
--- a/drivers/net/qede/meson.build
+++ b/drivers/net/qede/meson.build
@@ -9,4 +9,9 @@ sources = files(
 	'qede_filter.c',
 	'qede_main.c',
 	'qede_rxtx.c',
+	'qede_debug.c',
 )
+
+if cc.has_argument('-Wno-format-nonliteral')
+	cflags += '-Wno-format-nonliteral'
+endif
diff --git a/drivers/net/qede/qede_debug.c b/drivers/net/qede/qede_debug.c
new file mode 100644
index 000000000..f5bb7838f
--- /dev/null
+++ b/drivers/net/qede/qede_debug.c
@@ -0,0 +1,8120 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Marvell Semiconductor Inc.
+ * All rights reserved.
+ * www.marvell.com
+ */
+
+#include <rte_common.h>
+#include "base/bcm_osal.h"
+#include "base/ecore.h"
+#include "base/ecore_cxt.h"
+#include "base/ecore_hsi_common.h"
+#include "base/ecore_hw.h"
+#include "base/ecore_mcp.h"
+#include "base/reg_addr.h"
+#include "qede_debug.h"
+
+/* Memory groups enum */
+enum mem_groups {
+	MEM_GROUP_PXP_MEM,
+	MEM_GROUP_DMAE_MEM,
+	MEM_GROUP_CM_MEM,
+	MEM_GROUP_QM_MEM,
+	MEM_GROUP_DORQ_MEM,
+	MEM_GROUP_BRB_RAM,
+	MEM_GROUP_BRB_MEM,
+	MEM_GROUP_PRS_MEM,
+	MEM_GROUP_SDM_MEM,
+	MEM_GROUP_PBUF,
+	MEM_GROUP_IOR,
+	MEM_GROUP_RAM,
+	MEM_GROUP_BTB_RAM,
+	MEM_GROUP_RDIF_CTX,
+	MEM_GROUP_TDIF_CTX,
+	MEM_GROUP_CFC_MEM,
+	MEM_GROUP_CONN_CFC_MEM,
+	MEM_GROUP_CAU_PI,
+	MEM_GROUP_CAU_MEM,
+	MEM_GROUP_CAU_MEM_EXT,
+	MEM_GROUP_PXP_ILT,
+	MEM_GROUP_MULD_MEM,
+	MEM_GROUP_BTB_MEM,
+	MEM_GROUP_IGU_MEM,
+	MEM_GROUP_IGU_MSIX,
+	MEM_GROUP_CAU_SB,
+	MEM_GROUP_BMB_RAM,
+	MEM_GROUP_BMB_MEM,
+	MEM_GROUP_TM_MEM,
+	MEM_GROUP_TASK_CFC_MEM,
+	MEM_GROUPS_NUM
+};
+
+/* Memory groups names */
+static const char * const s_mem_group_names[] = {
+	"PXP_MEM",
+	"DMAE_MEM",
+	"CM_MEM",
+	"QM_MEM",
+	"DORQ_MEM",
+	"BRB_RAM",
+	"BRB_MEM",
+	"PRS_MEM",
+	"SDM_MEM",
+	"PBUF",
+	"IOR",
+	"RAM",
+	"BTB_RAM",
+	"RDIF_CTX",
+	"TDIF_CTX",
+	"CFC_MEM",
+	"CONN_CFC_MEM",
+	"CAU_PI",
+	"CAU_MEM",
+	"CAU_MEM_EXT",
+	"PXP_ILT",
+	"MULD_MEM",
+	"BTB_MEM",
+	"IGU_MEM",
+	"IGU_MSIX",
+	"CAU_SB",
+	"BMB_RAM",
+	"BMB_MEM",
+	"TM_MEM",
+	"TASK_CFC_MEM",
+};
+
+/* Idle check conditions */
+
+static u32 cond5(const u32 *r, const u32 *imm)
+{
+	return ((r[0] & imm[0]) != imm[1]) && ((r[1] & imm[2]) != imm[3]);
+}
+
+static u32 cond7(const u32 *r, const u32 *imm)
+{
+	return ((r[0] >> imm[0]) & imm[1]) != imm[2];
+}
+
+static u32 cond6(const u32 *r, const u32 *imm)
+{
+	return (r[0] & imm[0]) != imm[1];
+}
+
+static u32 cond9(const u32 *r, const u32 *imm)
+{
+	return ((r[0] & imm[0]) >> imm[1]) !=
+		(((r[0] & imm[2]) >> imm[3]) | ((r[1] & imm[4]) << imm[5]));
+}
+
+static u32 cond10(const u32 *r, const u32 *imm)
+{
+	return ((r[0] & imm[0]) >> imm[1]) != (r[0] & imm[2]);
+}
+
+static u32 cond4(const u32 *r, const u32 *imm)
+{
+	return (r[0] & ~imm[0]) != imm[1];
+}
+
+static u32 cond0(const u32 *r, const u32 *imm)
+{
+	return (r[0] & ~r[1]) != imm[0];
+}
+
+static u32 cond1(const u32 *r, const u32 *imm)
+{
+	return r[0] != imm[0];
+}
+
+static u32 cond11(const u32 *r, const u32 *imm)
+{
+	return r[0] != r[1] && r[2] == imm[0];
+}
+
+static u32 cond12(const u32 *r, const u32 *imm)
+{
+	return r[0] != r[1] && r[2] > imm[0];
+}
+
+static u32 cond3(const u32 *r, const __rte_unused u32 *imm)
+{
+	return r[0] != r[1];
+}
+
+static u32 cond13(const u32 *r, const u32 *imm)
+{
+	return r[0] & imm[0];
+}
+
+static u32 cond8(const u32 *r, const u32 *imm)
+{
+	return r[0] < (r[1] - imm[0]);
+}
+
+static u32 cond2(const u32 *r, const u32 *imm)
+{
+	return r[0] > imm[0];
+}
+
+/* Array of Idle Check conditions */
+static u32(*cond_arr[]) (const u32 *r, const u32 *imm) = {
+	cond0,
+	cond1,
+	cond2,
+	cond3,
+	cond4,
+	cond5,
+	cond6,
+	cond7,
+	cond8,
+	cond9,
+	cond10,
+	cond11,
+	cond12,
+	cond13,
+};
+
+#define NUM_PHYS_BLOCKS 84
+
+#define NUM_DBG_RESET_REGS 8
+
+/******************************* Data Types **********************************/
+
+enum hw_types {
+	HW_TYPE_ASIC,
+	PLATFORM_RESERVED,
+	PLATFORM_RESERVED2,
+	PLATFORM_RESERVED3,
+	PLATFORM_RESERVED4,
+	MAX_HW_TYPES
+};
+
+/* CM context types */
+enum cm_ctx_types {
+	CM_CTX_CONN_AG,
+	CM_CTX_CONN_ST,
+	CM_CTX_TASK_AG,
+	CM_CTX_TASK_ST,
+	NUM_CM_CTX_TYPES
+};
+
+/* Debug bus frame modes */
+enum dbg_bus_frame_modes {
+	DBG_BUS_FRAME_MODE_4ST = 0,	/* 4 Storm dwords (no HW) */
+	DBG_BUS_FRAME_MODE_2ST_2HW = 1,	/* 2 Storm dwords, 2 HW dwords */
+	DBG_BUS_FRAME_MODE_1ST_3HW = 2,	/* 1 Storm dwords, 3 HW dwords */
+	DBG_BUS_FRAME_MODE_4HW = 3,	/* 4 HW dwords (no Storms) */
+	DBG_BUS_FRAME_MODE_8HW = 4,	/* 8 HW dwords (no Storms) */
+	DBG_BUS_NUM_FRAME_MODES
+};
+
+/* Chip constant definitions */
+struct chip_defs {
+	const char *name;
+	u32 num_ilt_pages;
+};
+
+/* HW type constant definitions */
+struct hw_type_defs {
+	const char *name;
+	u32 delay_factor;
+	u32 dmae_thresh;
+	u32 log_thresh;
+};
+
+/* RBC reset definitions */
+struct rbc_reset_defs {
+	u32 reset_reg_addr;
+	u32 reset_val[MAX_CHIP_IDS];
+};
+
+/* Storm constant definitions.
+ * Addresses are in bytes, sizes are in quad-regs.
+ */
+struct storm_defs {
+	char letter;
+	enum block_id sem_block_id;
+	enum dbg_bus_clients dbg_client_id[MAX_CHIP_IDS];
+	bool has_vfc;
+	u32 sem_fast_mem_addr;
+	u32 sem_frame_mode_addr;
+	u32 sem_slow_enable_addr;
+	u32 sem_slow_mode_addr;
+	u32 sem_slow_mode1_conf_addr;
+	u32 sem_sync_dbg_empty_addr;
+	u32 sem_gpre_vect_addr;
+	u32 cm_ctx_wr_addr;
+	u32 cm_ctx_rd_addr[NUM_CM_CTX_TYPES];
+	u32 cm_ctx_lid_sizes[MAX_CHIP_IDS][NUM_CM_CTX_TYPES];
+};
+
+/* Debug Bus Constraint operation constant definitions */
+struct dbg_bus_constraint_op_defs {
+	u8 hw_op_val;
+	bool is_cyclic;
+};
+
+/* Storm Mode definitions */
+struct storm_mode_defs {
+	const char *name;
+	bool is_fast_dbg;
+	u8 id_in_hw;
+	u32 src_disable_reg_addr;
+	u32 src_enable_val;
+	bool exists[MAX_CHIP_IDS];
+};
+
+struct grc_param_defs {
+	u32 default_val[MAX_CHIP_IDS];
+	u32 min;
+	u32 max;
+	bool is_preset;
+	bool is_persistent;
+	u32 exclude_all_preset_val;
+	u32 crash_preset_val[MAX_CHIP_IDS];
+};
+
+/* Address is in 128b units. Width is in bits. */
+struct rss_mem_defs {
+	const char *mem_name;
+	const char *type_name;
+	u32 addr;
+	u32 entry_width;
+	u32 num_entries[MAX_CHIP_IDS];
+};
+
+struct vfc_ram_defs {
+	const char *mem_name;
+	const char *type_name;
+	u32 base_row;
+	u32 num_rows;
+};
+
+struct big_ram_defs {
+	const char *instance_name;
+	enum mem_groups mem_group_id;
+	enum mem_groups ram_mem_group_id;
+	enum dbg_grc_params grc_param;
+	u32 addr_reg_addr;
+	u32 data_reg_addr;
+	u32 is_256b_reg_addr;
+	u32 is_256b_bit_offset[MAX_CHIP_IDS];
+	u32 ram_size[MAX_CHIP_IDS]; /* In dwords */
+};
+
+struct phy_defs {
+	const char *phy_name;
+
+	/* PHY base GRC address */
+	u32 base_addr;
+
+	/* Relative address of indirect TBUS address register (bits 0..7) */
+	u32 tbus_addr_lo_addr;
+
+	/* Relative address of indirect TBUS address register (bits 8..10) */
+	u32 tbus_addr_hi_addr;
+
+	/* Relative address of indirect TBUS data register (bits 0..7) */
+	u32 tbus_data_lo_addr;
+
+	/* Relative address of indirect TBUS data register (bits 8..11) */
+	u32 tbus_data_hi_addr;
+};
+
+/* Split type definitions */
+struct split_type_defs {
+	const char *name;
+};
+
+/******************************** Constants **********************************/
+
+#define BYTES_IN_DWORD			sizeof(u32)
+/* In the macros below, size and offset are specified in bits */
+#define CEIL_DWORDS(size)		DIV_ROUND_UP(size, 32)
+#define FIELD_BIT_OFFSET(type, field)	type ## _ ## field ## _ ## OFFSET
+#define FIELD_BIT_SIZE(type, field)	type ## _ ## field ## _ ## SIZE
+#define FIELD_DWORD_OFFSET(type, field) \
+	 (int)(FIELD_BIT_OFFSET(type, field) / 32)
+#define FIELD_DWORD_SHIFT(type, field)	(FIELD_BIT_OFFSET(type, field) % 32)
+#define FIELD_BIT_MASK(type, field) \
+	(((1 << FIELD_BIT_SIZE(type, field)) - 1) << \
+	 FIELD_DWORD_SHIFT(type, field))
+
+#define SET_VAR_FIELD(var, type, field, val) \
+	do { \
+		var[FIELD_DWORD_OFFSET(type, field)] &=	\
+		(~FIELD_BIT_MASK(type, field));	\
+		var[FIELD_DWORD_OFFSET(type, field)] |= \
+		(val) << FIELD_DWORD_SHIFT(type, field); \
+	} while (0)
+
+#define ARR_REG_WR(dev, ptt, addr, arr, arr_size) \
+	do { \
+		for (i = 0; i < (arr_size); i++) \
+			ecore_wr(dev, ptt, addr,	(arr)[i]); \
+	} while (0)
+
+#define DWORDS_TO_BYTES(dwords)		((dwords) * BYTES_IN_DWORD)
+#define BYTES_TO_DWORDS(bytes)		((bytes) / BYTES_IN_DWORD)
+
+/* extra lines include a signature line + optional latency events line */
+#define NUM_EXTRA_DBG_LINES(block) \
+	(GET_FIELD((block)->flags, DBG_BLOCK_CHIP_HAS_LATENCY_EVENTS) ? 2 : 1)
+#define NUM_DBG_LINES(block) \
+	((block)->num_of_dbg_bus_lines + NUM_EXTRA_DBG_LINES(block))
+
+#define USE_DMAE			true
+#define PROTECT_WIDE_BUS		true
+
+#define RAM_LINES_TO_DWORDS(lines)	((lines) * 2)
+#define RAM_LINES_TO_BYTES(lines) \
+	DWORDS_TO_BYTES(RAM_LINES_TO_DWORDS(lines))
+
+#define REG_DUMP_LEN_SHIFT		24
+#define MEM_DUMP_ENTRY_SIZE_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_dump_mem))
+
+#define IDLE_CHK_RULE_SIZE_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_rule))
+
+#define IDLE_CHK_RESULT_HDR_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_result_hdr))
+
+#define IDLE_CHK_RESULT_REG_HDR_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_result_reg_hdr))
+
+#define PAGE_MEM_DESC_SIZE_DWORDS \
+	BYTES_TO_DWORDS(sizeof(struct phys_mem_desc))
+
+#define IDLE_CHK_MAX_ENTRIES_SIZE	32
+
+/* The sizes and offsets below are specified in bits */
+#define VFC_CAM_CMD_STRUCT_SIZE		64
+#define VFC_CAM_CMD_ROW_OFFSET		48
+#define VFC_CAM_CMD_ROW_SIZE		9
+#define VFC_CAM_ADDR_STRUCT_SIZE	16
+#define VFC_CAM_ADDR_OP_OFFSET		0
+#define VFC_CAM_ADDR_OP_SIZE		4
+#define VFC_CAM_RESP_STRUCT_SIZE	256
+#define VFC_RAM_ADDR_STRUCT_SIZE	16
+#define VFC_RAM_ADDR_OP_OFFSET		0
+#define VFC_RAM_ADDR_OP_SIZE		2
+#define VFC_RAM_ADDR_ROW_OFFSET		2
+#define VFC_RAM_ADDR_ROW_SIZE		10
+#define VFC_RAM_RESP_STRUCT_SIZE	256
+
+#define VFC_CAM_CMD_DWORDS		CEIL_DWORDS(VFC_CAM_CMD_STRUCT_SIZE)
+#define VFC_CAM_ADDR_DWORDS		CEIL_DWORDS(VFC_CAM_ADDR_STRUCT_SIZE)
+#define VFC_CAM_RESP_DWORDS		CEIL_DWORDS(VFC_CAM_RESP_STRUCT_SIZE)
+#define VFC_RAM_CMD_DWORDS		VFC_CAM_CMD_DWORDS
+#define VFC_RAM_ADDR_DWORDS		CEIL_DWORDS(VFC_RAM_ADDR_STRUCT_SIZE)
+#define VFC_RAM_RESP_DWORDS		CEIL_DWORDS(VFC_RAM_RESP_STRUCT_SIZE)
+
+#define NUM_VFC_RAM_TYPES		4
+
+#define VFC_CAM_NUM_ROWS		512
+
+#define VFC_OPCODE_CAM_RD		14
+#define VFC_OPCODE_RAM_RD		0
+
+#define NUM_RSS_MEM_TYPES		5
+
+#define NUM_BIG_RAM_TYPES		3
+#define BIG_RAM_NAME_LEN		3
+
+#define NUM_PHY_TBUS_ADDRESSES		2048
+#define PHY_DUMP_SIZE_DWORDS		(NUM_PHY_TBUS_ADDRESSES / 2)
+
+#define RESET_REG_UNRESET_OFFSET	4
+
+#define STALL_DELAY_MS			500
+
+#define STATIC_DEBUG_LINE_DWORDS	9
+
+#define NUM_COMMON_GLOBAL_PARAMS	11
+
+#define MAX_RECURSION_DEPTH		10
+
+#define FW_IMG_MAIN			1
+
+#define REG_FIFO_ELEMENT_DWORDS		2
+#define REG_FIFO_DEPTH_ELEMENTS		32
+#define REG_FIFO_DEPTH_DWORDS \
+	(REG_FIFO_ELEMENT_DWORDS * REG_FIFO_DEPTH_ELEMENTS)
+
+#define IGU_FIFO_ELEMENT_DWORDS		4
+#define IGU_FIFO_DEPTH_ELEMENTS		64
+#define IGU_FIFO_DEPTH_DWORDS \
+	(IGU_FIFO_ELEMENT_DWORDS * IGU_FIFO_DEPTH_ELEMENTS)
+
+#define PROTECTION_OVERRIDE_ELEMENT_DWORDS	2
+#define PROTECTION_OVERRIDE_DEPTH_ELEMENTS	20
+#define PROTECTION_OVERRIDE_DEPTH_DWORDS \
+	(PROTECTION_OVERRIDE_DEPTH_ELEMENTS * \
+	 PROTECTION_OVERRIDE_ELEMENT_DWORDS)
+
+#define MCP_SPAD_TRACE_OFFSIZE_ADDR \
+	(MCP_REG_SCRATCH + \
+	 offsetof(struct static_init, sections[SPAD_SECTION_TRACE]))
+
+#define MAX_SW_PLTAFORM_STR_SIZE	64
+
+#define EMPTY_FW_VERSION_STR		"???_???_???_???"
+#define EMPTY_FW_IMAGE_STR		"???????????????"
+
+/***************************** Constant Arrays *******************************/
+
+/* Chip constant definitions array */
+static struct chip_defs s_chip_defs[MAX_CHIP_IDS] = {
+	{"bb", PSWRQ2_REG_ILT_MEMORY_SIZE_BB / 2},
+	{"ah", PSWRQ2_REG_ILT_MEMORY_SIZE_K2 / 2}
+};
+
+/* Storm constant definitions array */
+static struct storm_defs s_storm_defs[] = {
+	/* Tstorm */
+	{'T', BLOCK_TSEM,
+		{DBG_BUS_CLIENT_RBCT, DBG_BUS_CLIENT_RBCT},
+		true,
+		TSEM_REG_FAST_MEMORY,
+		TSEM_REG_DBG_FRAME_MODE, TSEM_REG_SLOW_DBG_ACTIVE,
+		TSEM_REG_SLOW_DBG_MODE, TSEM_REG_DBG_MODE1_CFG,
+		TSEM_REG_SYNC_DBG_EMPTY, TSEM_REG_DBG_GPRE_VECT,
+		TCM_REG_CTX_RBC_ACCS,
+		{TCM_REG_AGG_CON_CTX, TCM_REG_SM_CON_CTX, TCM_REG_AGG_TASK_CTX,
+		 TCM_REG_SM_TASK_CTX},
+		{{4, 16, 2, 4}, {4, 16, 2, 4} } /* {bb} {k2} */
+	},
+
+	/* Mstorm */
+	{'M', BLOCK_MSEM,
+		{DBG_BUS_CLIENT_RBCT, DBG_BUS_CLIENT_RBCM},
+		false,
+		MSEM_REG_FAST_MEMORY,
+		MSEM_REG_DBG_FRAME_MODE,
+		MSEM_REG_SLOW_DBG_ACTIVE,
+		MSEM_REG_SLOW_DBG_MODE,
+		MSEM_REG_DBG_MODE1_CFG,
+		MSEM_REG_SYNC_DBG_EMPTY,
+		MSEM_REG_DBG_GPRE_VECT,
+		MCM_REG_CTX_RBC_ACCS,
+		{MCM_REG_AGG_CON_CTX, MCM_REG_SM_CON_CTX, MCM_REG_AGG_TASK_CTX,
+		 MCM_REG_SM_TASK_CTX },
+		{{1, 10, 2, 7}, {1, 10, 2, 7} } /* {bb} {k2}*/
+	},
+
+	/* Ustorm */
+	{'U', BLOCK_USEM,
+		{DBG_BUS_CLIENT_RBCU, DBG_BUS_CLIENT_RBCU},
+		false,
+		USEM_REG_FAST_MEMORY,
+		USEM_REG_DBG_FRAME_MODE,
+		USEM_REG_SLOW_DBG_ACTIVE,
+		USEM_REG_SLOW_DBG_MODE,
+		USEM_REG_DBG_MODE1_CFG,
+		USEM_REG_SYNC_DBG_EMPTY,
+		USEM_REG_DBG_GPRE_VECT,
+		UCM_REG_CTX_RBC_ACCS,
+		{UCM_REG_AGG_CON_CTX, UCM_REG_SM_CON_CTX, UCM_REG_AGG_TASK_CTX,
+		 UCM_REG_SM_TASK_CTX},
+		{{2, 13, 3, 3}, {2, 13, 3, 3} } /* {bb} {k2} */
+	},
+
+	/* Xstorm */
+	{'X', BLOCK_XSEM,
+		{DBG_BUS_CLIENT_RBCX, DBG_BUS_CLIENT_RBCX},
+		false,
+		XSEM_REG_FAST_MEMORY,
+		XSEM_REG_DBG_FRAME_MODE,
+		XSEM_REG_SLOW_DBG_ACTIVE,
+		XSEM_REG_SLOW_DBG_MODE,
+		XSEM_REG_DBG_MODE1_CFG,
+		XSEM_REG_SYNC_DBG_EMPTY,
+		XSEM_REG_DBG_GPRE_VECT,
+		XCM_REG_CTX_RBC_ACCS,
+		{XCM_REG_AGG_CON_CTX, XCM_REG_SM_CON_CTX, 0, 0},
+		{{9, 15, 0, 0}, {9, 15,	0, 0} } /* {bb} {k2} */
+	},
+
+	/* Ystorm */
+	{'Y', BLOCK_YSEM,
+		{DBG_BUS_CLIENT_RBCX, DBG_BUS_CLIENT_RBCY},
+		false,
+		YSEM_REG_FAST_MEMORY,
+		YSEM_REG_DBG_FRAME_MODE,
+		YSEM_REG_SLOW_DBG_ACTIVE,
+		YSEM_REG_SLOW_DBG_MODE,
+		YSEM_REG_DBG_MODE1_CFG,
+		YSEM_REG_SYNC_DBG_EMPTY,
+		YSEM_REG_DBG_GPRE_VECT,
+		YCM_REG_CTX_RBC_ACCS,
+		{YCM_REG_AGG_CON_CTX, YCM_REG_SM_CON_CTX, YCM_REG_AGG_TASK_CTX,
+		 YCM_REG_SM_TASK_CTX},
+		{{2, 3, 2, 12}, {2, 3, 2, 12} } /* {bb} {k2} */
+	},
+
+	/* Pstorm */
+	{'P', BLOCK_PSEM,
+		{DBG_BUS_CLIENT_RBCS, DBG_BUS_CLIENT_RBCS},
+		true,
+		PSEM_REG_FAST_MEMORY,
+		PSEM_REG_DBG_FRAME_MODE,
+		PSEM_REG_SLOW_DBG_ACTIVE,
+		PSEM_REG_SLOW_DBG_MODE,
+		PSEM_REG_DBG_MODE1_CFG,
+		PSEM_REG_SYNC_DBG_EMPTY,
+		PSEM_REG_DBG_GPRE_VECT,
+		PCM_REG_CTX_RBC_ACCS,
+		{0, PCM_REG_SM_CON_CTX, 0, 0},
+		{{0, 10, 0, 0}, {0, 10, 0, 0} } /* {bb} {k2} */
+	},
+};
+
+static struct hw_type_defs s_hw_type_defs[] = {
+	/* HW_TYPE_ASIC */
+	{"asic", 1, 256, 32768},
+	{"reserved", 0, 0, 0},
+	{"reserved2", 0, 0, 0},
+	{"reserved3", 0, 0, 0}
+};
+
+static struct grc_param_defs s_grc_param_defs[] = {
+	/* DBG_GRC_PARAM_DUMP_TSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_MSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_USTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_XSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_YSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PSTORM */
+	{{1, 1}, 0, 1, false, false, 1, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_REGS */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_RAM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PBUF */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_IOR */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_VFC */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_CM_CTX */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_ILT */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_RSS */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_CAU */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_QM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_MCP */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_DORQ */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_CFC */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_IGU */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_BRB */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_BTB */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_BMB */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_RESERVED1 */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_MULD */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PRS */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_DMAE */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_TM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_SDM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_DIF */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_STATIC */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_UNSTALL */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_RESERVED2 */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_MCP_TRACE_META_SIZE */
+	{{0, 0}, 1, 0xffffffff, false, true, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_EXCLUDE_ALL */
+	{{0, 0}, 0, 1, true, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_CRASH */
+	{{0, 0}, 0, 1, true, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_PARITY_SAFE */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_CM */
+	{{1, 1}, 0, 1, false, false, 0, {1, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_PHY */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_NO_MCP */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_NO_FW_VER */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_RESERVED3 */
+	{{0, 0}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_MCP_HW_DUMP */
+	{{0, 1}, 0, 1, false, false, 0, {0, 1} },
+
+	/* DBG_GRC_PARAM_DUMP_ILT_CDUC */
+	{{1, 1}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_ILT_CDUT */
+	{{1, 1}, 0, 1, false, false, 0, {0, 0} },
+
+	/* DBG_GRC_PARAM_DUMP_CAU_EXT */
+	{{0, 0}, 0, 1, false, false, 0, {1, 1} }
+};
+
+static struct rss_mem_defs s_rss_mem_defs[] = {
+	{"rss_mem_cid", "rss_cid", 0, 32,
+	 {256, 320} },
+
+	{"rss_mem_key_msb", "rss_key", 1024, 256,
+	 {128, 208} },
+
+	{"rss_mem_key_lsb", "rss_key", 2048, 64,
+	 {128, 208} },
+
+	{"rss_mem_info", "rss_info", 3072, 16,
+	 {128, 208} },
+
+	{"rss_mem_ind", "rss_ind", 4096, 16,
+	 {16384, 26624} }
+};
+
+static struct vfc_ram_defs s_vfc_ram_defs[] = {
+	{"vfc_ram_tt1", "vfc_ram", 0, 512},
+	{"vfc_ram_mtt2", "vfc_ram", 512, 128},
+	{"vfc_ram_stt2", "vfc_ram", 640, 32},
+	{"vfc_ram_ro_vect", "vfc_ram", 672, 32}
+};
+
+static struct big_ram_defs s_big_ram_defs[] = {
+	{"BRB", MEM_GROUP_BRB_MEM, MEM_GROUP_BRB_RAM, DBG_GRC_PARAM_DUMP_BRB,
+	 BRB_REG_BIG_RAM_ADDRESS, BRB_REG_BIG_RAM_DATA,
+	 MISC_REG_BLOCK_256B_EN, {0, 0},
+	 {153600, 180224} },
+
+	{"BTB", MEM_GROUP_BTB_MEM, MEM_GROUP_BTB_RAM, DBG_GRC_PARAM_DUMP_BTB,
+	 BTB_REG_BIG_RAM_ADDRESS, BTB_REG_BIG_RAM_DATA,
+	 MISC_REG_BLOCK_256B_EN, {0, 1},
+	 {92160, 117760} },
+
+	{"BMB", MEM_GROUP_BMB_MEM, MEM_GROUP_BMB_RAM, DBG_GRC_PARAM_DUMP_BMB,
+	 BMB_REG_BIG_RAM_ADDRESS, BMB_REG_BIG_RAM_DATA,
+	 MISCS_REG_BLOCK_256B_EN, {0, 0},
+	 {36864, 36864} }
+};
+
+static struct rbc_reset_defs s_rbc_reset_defs[] = {
+	{MISCS_REG_RESET_PL_HV,
+	 {0x0, 0x400} },
+	{MISC_REG_RESET_PL_PDA_VMAIN_1,
+	 {0x4404040, 0x4404040} },
+	{MISC_REG_RESET_PL_PDA_VMAIN_2,
+	 {0x7, 0x7c00007} },
+	{MISC_REG_RESET_PL_PDA_VAUX,
+	 {0x2, 0x2} },
+};
+
+static struct phy_defs s_phy_defs[] = {
+	{"nw_phy", NWS_REG_NWS_CMU_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_7_0_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_15_8_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_7_0_K2,
+	 PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_11_8_K2},
+	{"sgmii_phy", MS_REG_MS_CMU_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X132_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X133_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X130_K2,
+	 PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X131_K2},
+	{"pcie_phy0", PHY_PCIE_REG_PHY0_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2},
+	{"pcie_phy1", PHY_PCIE_REG_PHY1_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2,
+	 PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2},
+};
+
+static struct split_type_defs s_split_type_defs[] = {
+	/* SPLIT_TYPE_NONE */
+	{"eng"},
+
+	/* SPLIT_TYPE_PORT */
+	{"port"},
+
+	/* SPLIT_TYPE_PF */
+	{"pf"},
+
+	/* SPLIT_TYPE_PORT_PF */
+	{"port"},
+
+	/* SPLIT_TYPE_VF */
+	{"vf"}
+};
+
+/******************************** Variables *********************************/
+
+/**
+ * The version of the calling app
+ */
+static u32 s_app_ver;
+
+/**************************** Private Functions ******************************/
+
+/* Reads and returns a single dword from the specified unaligned buffer */
+static u32 qed_read_unaligned_dword(u8 *buf)
+{
+	u32 dword;
+
+	memcpy((u8 *)&dword, buf, sizeof(dword));
+	return dword;
+}
+
+/* Sets the value of the specified GRC param */
+static void qed_grc_set_param(struct ecore_hwfn *p_hwfn,
+			      enum dbg_grc_params grc_param, u32 val)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	dev_data->grc.param_val[grc_param] = val;
+}
+
+/* Returns the value of the specified GRC param */
+static u32 qed_grc_get_param(struct ecore_hwfn *p_hwfn,
+			     enum dbg_grc_params grc_param)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	return dev_data->grc.param_val[grc_param];
+}
+
+/* Initializes the GRC parameters */
+static void qed_dbg_grc_init_params(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	if (!dev_data->grc.params_initialized) {
+		qed_dbg_grc_set_params_default(p_hwfn);
+		dev_data->grc.params_initialized = 1;
+	}
+}
+
+/* Sets pointer and size for the specified binary buffer type */
+static void qed_set_dbg_bin_buf(struct ecore_hwfn *p_hwfn,
+				enum bin_dbg_buffer_type buf_type,
+				const u32 *ptr, u32 size)
+{
+	struct virt_mem_desc *buf = &p_hwfn->dbg_arrays[buf_type];
+
+	buf->ptr = (void *)(osal_uintptr_t)ptr;
+	buf->size = size;
+}
+
+/* Initializes debug data for the specified device */
+static enum dbg_status qed_dbg_dev_init(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 num_pfs = 0, max_pfs_per_port = 0;
+
+	if (dev_data->initialized)
+		return DBG_STATUS_OK;
+
+	/* Set chip */
+	if (ECORE_IS_K2(p_hwfn->p_dev)) {
+		dev_data->chip_id = CHIP_K2;
+		dev_data->mode_enable[MODE_K2] = 1;
+		dev_data->num_vfs = MAX_NUM_VFS_K2;
+		num_pfs = MAX_NUM_PFS_K2;
+		max_pfs_per_port = MAX_NUM_PFS_K2 / 2;
+	} else if (ECORE_IS_BB_B0(p_hwfn->p_dev)) {
+		dev_data->chip_id = CHIP_BB;
+		dev_data->mode_enable[MODE_BB] = 1;
+		dev_data->num_vfs = MAX_NUM_VFS_BB;
+		num_pfs = MAX_NUM_PFS_BB;
+		max_pfs_per_port = MAX_NUM_PFS_BB;
+	} else {
+		return DBG_STATUS_UNKNOWN_CHIP;
+	}
+
+	/* Set HW type */
+	dev_data->hw_type = HW_TYPE_ASIC;
+	dev_data->mode_enable[MODE_ASIC] = 1;
+
+	/* Set port mode */
+	switch (p_hwfn->p_dev->num_ports_in_engine) {
+	case 1:
+		dev_data->mode_enable[MODE_PORTS_PER_ENG_1] = 1;
+		break;
+	case 2:
+		dev_data->mode_enable[MODE_PORTS_PER_ENG_2] = 1;
+		break;
+	case 4:
+		dev_data->mode_enable[MODE_PORTS_PER_ENG_4] = 1;
+		break;
+	}
+
+	/* Set 100G mode */
+	if (ECORE_IS_CMT(p_hwfn->p_dev))
+		dev_data->mode_enable[MODE_100G] = 1;
+
+	/* Set number of ports */
+	if (dev_data->mode_enable[MODE_PORTS_PER_ENG_1] ||
+	    dev_data->mode_enable[MODE_100G])
+		dev_data->num_ports = 1;
+	else if (dev_data->mode_enable[MODE_PORTS_PER_ENG_2])
+		dev_data->num_ports = 2;
+	else if (dev_data->mode_enable[MODE_PORTS_PER_ENG_4])
+		dev_data->num_ports = 4;
+
+	/* Set number of PFs per port */
+	dev_data->num_pfs_per_port = OSAL_MIN_T(u32,
+						num_pfs / dev_data->num_ports,
+						max_pfs_per_port);
+
+	/* Initializes the GRC parameters */
+	qed_dbg_grc_init_params(p_hwfn);
+
+	dev_data->use_dmae = true;
+	dev_data->initialized = 1;
+
+	return DBG_STATUS_OK;
+}
+
+static const struct dbg_block *get_dbg_block(struct ecore_hwfn *p_hwfn,
+					     enum block_id block_id)
+{
+	const struct dbg_block *dbg_block;
+
+	dbg_block = p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS].ptr;
+	return dbg_block + block_id;
+}
+
+static const struct dbg_block_chip *qed_get_dbg_block_per_chip(struct ecore_hwfn
+							       *p_hwfn,
+							       enum block_id
+							       block_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	return (const struct dbg_block_chip *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS_CHIP_DATA].ptr +
+	    block_id * MAX_CHIP_IDS + dev_data->chip_id;
+}
+
+static const struct dbg_reset_reg *qed_get_dbg_reset_reg(struct ecore_hwfn
+							 *p_hwfn,
+							 u8 reset_reg_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+
+	return (const struct dbg_reset_reg *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_RESET_REGS].ptr +
+	    reset_reg_id * MAX_CHIP_IDS + dev_data->chip_id;
+}
+
+/* Reads the FW info structure for the specified Storm from the chip,
+ * and writes it to the specified fw_info pointer.
+ */
+static void qed_read_storm_fw_info(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   u8 storm_id, struct fw_info *fw_info)
+{
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	struct fw_info_location fw_info_location;
+	u32 addr, i, *dest;
+
+	memset(&fw_info_location, 0, sizeof(fw_info_location));
+	memset(fw_info, 0, sizeof(*fw_info));
+
+	/* Read first the address that points to fw_info location.
+	 * The address is located in the last line of the Storm RAM.
+	 */
+	addr = storm->sem_fast_mem_addr + SEM_FAST_REG_INT_RAM +
+	    DWORDS_TO_BYTES(SEM_FAST_REG_INT_RAM_SIZE) -
+	    sizeof(fw_info_location);
+
+	dest = (u32 *)&fw_info_location;
+
+	for (i = 0; i < BYTES_TO_DWORDS(sizeof(fw_info_location));
+	     i++, addr += BYTES_IN_DWORD)
+		dest[i] = ecore_rd(p_hwfn, p_ptt, addr);
+
+	/* Read FW version info from Storm RAM */
+	if (fw_info_location.size > 0 && fw_info_location.size <=
+	    sizeof(*fw_info)) {
+		addr = fw_info_location.grc_addr;
+		dest = (u32 *)fw_info;
+		for (i = 0; i < BYTES_TO_DWORDS(fw_info_location.size);
+		     i++, addr += BYTES_IN_DWORD)
+			dest[i] = ecore_rd(p_hwfn, p_ptt, addr);
+	}
+}
+
+/* Dumps the specified string to the specified buffer.
+ * Returns the dumped size in bytes.
+ */
+static u32 qed_dump_str(char *dump_buf, bool dump, const char *str)
+{
+	if (dump)
+		strcpy(dump_buf, str);
+
+	return (u32)strlen(str) + 1;
+}
+
+/* Dumps zeros to align the specified buffer to dwords.
+ * Returns the dumped size in bytes.
+ */
+static u32 qed_dump_align(char *dump_buf, bool dump, u32 byte_offset)
+{
+	u8 offset_in_dword, align_size;
+
+	offset_in_dword = (u8)(byte_offset & 0x3);
+	align_size = offset_in_dword ? BYTES_IN_DWORD - offset_in_dword : 0;
+
+	if (dump && align_size)
+		memset(dump_buf, 0, align_size);
+
+	return align_size;
+}
+
+/* Writes the specified string param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_str_param(u32 *dump_buf,
+			      bool dump,
+			      const char *param_name, const char *param_val)
+{
+	char *char_buf = (char *)dump_buf;
+	u32 offset = 0;
+
+	/* Dump param name */
+	offset += qed_dump_str(char_buf + offset, dump, param_name);
+
+	/* Indicate a string param value */
+	if (dump)
+		*(char_buf + offset) = 1;
+	offset++;
+
+	/* Dump param value */
+	offset += qed_dump_str(char_buf + offset, dump, param_val);
+
+	/* Align buffer to next dword */
+	offset += qed_dump_align(char_buf + offset, dump, offset);
+
+	return BYTES_TO_DWORDS(offset);
+}
+
+/* Writes the specified numeric param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_num_param(u32 *dump_buf,
+			      bool dump, const char *param_name, u32 param_val)
+{
+	char *char_buf = (char *)dump_buf;
+	u32 offset = 0;
+
+	/* Dump param name */
+	offset += qed_dump_str(char_buf + offset, dump, param_name);
+
+	/* Indicate a numeric param value */
+	if (dump)
+		*(char_buf + offset) = 0;
+	offset++;
+
+	/* Align buffer to next dword */
+	offset += qed_dump_align(char_buf + offset, dump, offset);
+
+	/* Dump param value (and change offset from bytes to dwords) */
+	offset = BYTES_TO_DWORDS(offset);
+	if (dump)
+		*(dump_buf + offset) = param_val;
+	offset++;
+
+	return offset;
+}
+
+/* Reads the FW version and writes it as a param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_fw_ver_param(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf, bool dump)
+{
+	char fw_ver_str[16] = EMPTY_FW_VERSION_STR;
+	char fw_img_str[16] = EMPTY_FW_IMAGE_STR;
+	struct fw_info fw_info = { {0}, {0} };
+	u32 offset = 0;
+
+	if (dump && !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_FW_VER)) {
+		/* Read FW info from chip */
+		qed_read_fw_info(p_hwfn, p_ptt, &fw_info);
+
+		/* Create FW version/image strings */
+		if (snprintf(fw_ver_str, sizeof(fw_ver_str),
+			     "%d_%d_%d_%d", fw_info.ver.num.major,
+			     fw_info.ver.num.minor, fw_info.ver.num.rev,
+			     fw_info.ver.num.eng) < 0)
+			DP_NOTICE(p_hwfn, false,
+				  "Unexpected debug error: invalid FW version string\n");
+		switch (fw_info.ver.image_id) {
+		case FW_IMG_MAIN:
+			strcpy(fw_img_str, "main");
+			break;
+		default:
+			strcpy(fw_img_str, "unknown");
+			break;
+		}
+	}
+
+	/* Dump FW version, image and timestamp */
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "fw-version", fw_ver_str);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "fw-image", fw_img_str);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "fw-timestamp", fw_info.ver.timestamp);
+
+	return offset;
+}
+
+/* Reads the MFW version and writes it as a param to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_mfw_ver_param(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  u32 *dump_buf, bool dump)
+{
+	char mfw_ver_str[16] = EMPTY_FW_VERSION_STR;
+
+	if (dump &&
+	    !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_FW_VER)) {
+		u32 global_section_offsize, global_section_addr, mfw_ver;
+		u32 public_data_addr, global_section_offsize_addr;
+
+		/* Find MCP public data GRC address. Needs to be ORed with
+		 * MCP_REG_SCRATCH due to a HW bug.
+		 */
+		public_data_addr = ecore_rd(p_hwfn,
+					  p_ptt,
+					  MISC_REG_SHARED_MEM_ADDR) |
+				   MCP_REG_SCRATCH;
+
+		/* Find MCP public global section offset */
+		global_section_offsize_addr = public_data_addr +
+					      offsetof(struct mcp_public_data,
+						       sections) +
+					      sizeof(offsize_t) * PUBLIC_GLOBAL;
+		global_section_offsize = ecore_rd(p_hwfn, p_ptt,
+						global_section_offsize_addr);
+		global_section_addr =
+			MCP_REG_SCRATCH +
+			(global_section_offsize & OFFSIZE_OFFSET_MASK) * 4;
+
+		/* Read MFW version from MCP public global section */
+		mfw_ver = ecore_rd(p_hwfn, p_ptt,
+				 global_section_addr +
+				 offsetof(struct public_global, mfw_ver));
+
+		/* Dump MFW version param */
+		if (snprintf(mfw_ver_str, sizeof(mfw_ver_str), "%d_%d_%d_%d",
+			     (u8)(mfw_ver >> 24), (u8)(mfw_ver >> 16),
+			     (u8)(mfw_ver >> 8), (u8)mfw_ver) < 0)
+			DP_NOTICE(p_hwfn, false,
+				  "Unexpected debug error: invalid MFW version string\n");
+	}
+
+	return qed_dump_str_param(dump_buf, dump, "mfw-version", mfw_ver_str);
+}
+
+/* Reads the chip revision from the chip and writes it as a param to the
+ * specified buffer. Returns the dumped size in dwords.
+ */
+static u32 qed_dump_chip_revision_param(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	char param_str[3] = "??";
+
+	if (dev_data->hw_type == HW_TYPE_ASIC) {
+		u32 chip_rev, chip_metal;
+
+		chip_rev = ecore_rd(p_hwfn, p_ptt, MISCS_REG_CHIP_REV);
+		chip_metal = ecore_rd(p_hwfn, p_ptt, MISCS_REG_CHIP_METAL);
+
+		param_str[0] = 'a' + (u8)chip_rev;
+		param_str[1] = '0' + (u8)chip_metal;
+	}
+
+	return qed_dump_str_param(dump_buf, dump, "chip-revision", param_str);
+}
+
+/* Writes a section header to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_section_hdr(u32 *dump_buf,
+				bool dump, const char *name, u32 num_params)
+{
+	return qed_dump_num_param(dump_buf, dump, name, num_params);
+}
+
+/* Writes the common global params to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_dump_common_global_params(struct ecore_hwfn *p_hwfn,
+					 struct ecore_ptt *p_ptt,
+					 u32 *dump_buf,
+					 bool dump,
+					 u8 num_specific_global_params)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	char sw_platform_str[MAX_SW_PLTAFORM_STR_SIZE];
+	u32 offset = 0;
+	u8 num_params;
+
+	/* Fill platform string */
+	ecore_set_platform_str(p_hwfn, sw_platform_str,
+			       MAX_SW_PLTAFORM_STR_SIZE);
+
+	/* Dump global params section header */
+	num_params = NUM_COMMON_GLOBAL_PARAMS + num_specific_global_params +
+		(dev_data->chip_id == CHIP_BB ? 1 : 0);
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "global_params", num_params);
+
+	/* Store params */
+	offset += qed_dump_fw_ver_param(p_hwfn, p_ptt, dump_buf + offset, dump);
+	offset += qed_dump_mfw_ver_param(p_hwfn,
+					 p_ptt, dump_buf + offset, dump);
+	offset += qed_dump_chip_revision_param(p_hwfn,
+					       p_ptt, dump_buf + offset, dump);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "tools-version", TOOLS_VERSION);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump,
+				     "chip",
+				     s_chip_defs[dev_data->chip_id].name);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump,
+				     "platform",
+				     s_hw_type_defs[dev_data->hw_type].name);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "sw-platform", sw_platform_str);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "pci-func", p_hwfn->abs_pf_id);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "epoch", OSAL_GET_EPOCH(p_hwfn));
+	if (dev_data->chip_id == CHIP_BB)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "path",
+					     ECORE_PATH_ID(p_hwfn));
+
+	return offset;
+}
+
+/* Writes the "last" section (including CRC) to the specified buffer at the
+ * given offset. Returns the dumped size in dwords.
+ */
+static u32 qed_dump_last_section(u32 *dump_buf, u32 offset, bool dump)
+{
+	u32 start_offset = offset;
+
+	/* Dump CRC section header */
+	offset += qed_dump_section_hdr(dump_buf + offset, dump, "last", 0);
+
+	/* Calculate CRC32 and add it to the dword after the "last" section */
+	if (dump)
+		*(dump_buf + offset) = ~OSAL_CRC32(0xffffffff,
+					      (u8 *)dump_buf,
+					      DWORDS_TO_BYTES(offset));
+
+	offset++;
+
+	return offset - start_offset;
+}
+
+/* Update blocks reset state  */
+static void qed_update_blocks_reset_state(struct ecore_hwfn *p_hwfn,
+					  struct ecore_ptt *p_ptt)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 reg_val[NUM_DBG_RESET_REGS] = { 0 };
+	u8 rst_reg_id;
+	u32 blk_id;
+
+	/* Read reset registers */
+	for (rst_reg_id = 0; rst_reg_id < NUM_DBG_RESET_REGS; rst_reg_id++) {
+		const struct dbg_reset_reg *rst_reg;
+		bool rst_reg_removed;
+		u32 rst_reg_addr;
+
+		rst_reg = qed_get_dbg_reset_reg(p_hwfn, rst_reg_id);
+		rst_reg_removed = GET_FIELD(rst_reg->data,
+					    DBG_RESET_REG_IS_REMOVED);
+		rst_reg_addr = DWORDS_TO_BYTES(GET_FIELD(rst_reg->data,
+							 DBG_RESET_REG_ADDR));
+
+		if (!rst_reg_removed)
+			reg_val[rst_reg_id] = ecore_rd(p_hwfn, p_ptt,
+						     rst_reg_addr);
+	}
+
+	/* Check if blocks are in reset */
+	for (blk_id = 0; blk_id < NUM_PHYS_BLOCKS; blk_id++) {
+		const struct dbg_block_chip *blk;
+		bool has_rst_reg;
+		bool is_removed;
+
+		blk = qed_get_dbg_block_per_chip(p_hwfn, (enum block_id)blk_id);
+		is_removed = GET_FIELD(blk->flags, DBG_BLOCK_CHIP_IS_REMOVED);
+		has_rst_reg = GET_FIELD(blk->flags,
+					DBG_BLOCK_CHIP_HAS_RESET_REG);
+
+		if (!is_removed && has_rst_reg)
+			dev_data->block_in_reset[blk_id] =
+			    !(reg_val[blk->reset_reg_id] &
+			      OSAL_BIT(blk->reset_reg_bit_offset));
+	}
+}
+
+/* is_mode_match recursive function */
+static bool qed_is_mode_match_rec(struct ecore_hwfn *p_hwfn,
+				  u16 *modes_buf_offset, u8 rec_depth)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	const u8 *dbg_array;
+	bool arg1, arg2;
+	u8 tree_val;
+
+	if (rec_depth > MAX_RECURSION_DEPTH) {
+		DP_NOTICE(p_hwfn, false,
+			  "Unexpected error: is_mode_match_rec exceeded the max recursion depth. This is probably due to a corrupt init/debug buffer.\n");
+		return false;
+	}
+
+	/* Get next element from modes tree buffer */
+	dbg_array = p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr;
+	tree_val = dbg_array[(*modes_buf_offset)++];
+
+	switch (tree_val) {
+	case INIT_MODE_OP_NOT:
+		return !qed_is_mode_match_rec(p_hwfn,
+					      modes_buf_offset, rec_depth + 1);
+	case INIT_MODE_OP_OR:
+	case INIT_MODE_OP_AND:
+		arg1 = qed_is_mode_match_rec(p_hwfn,
+					     modes_buf_offset, rec_depth + 1);
+		arg2 = qed_is_mode_match_rec(p_hwfn,
+					     modes_buf_offset, rec_depth + 1);
+		return (tree_val == INIT_MODE_OP_OR) ? (arg1 ||
+							arg2) : (arg1 && arg2);
+	default:
+		return dev_data->mode_enable[tree_val - MAX_INIT_MODE_OPS] > 0;
+	}
+}
+
+/* Returns true if the mode (specified using modes_buf_offset) is enabled */
+static bool qed_is_mode_match(struct ecore_hwfn *p_hwfn, u16 *modes_buf_offset)
+{
+	return qed_is_mode_match_rec(p_hwfn, modes_buf_offset, 0);
+}
+
+/* Enable / disable the Debug block */
+static void qed_bus_enable_dbg_block(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt, bool enable)
+{
+	ecore_wr(p_hwfn, p_ptt, DBG_REG_DBG_BLOCK_ON, enable ? 1 : 0);
+}
+
+/* Resets the Debug block */
+static void qed_bus_reset_dbg_block(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt)
+{
+	u32 reset_reg_addr, old_reset_reg_val, new_reset_reg_val;
+	const struct dbg_reset_reg *reset_reg;
+	const struct dbg_block_chip *block;
+
+	block = qed_get_dbg_block_per_chip(p_hwfn, BLOCK_DBG);
+	reset_reg = qed_get_dbg_reset_reg(p_hwfn, block->reset_reg_id);
+	reset_reg_addr =
+	    DWORDS_TO_BYTES(GET_FIELD(reset_reg->data, DBG_RESET_REG_ADDR));
+
+	old_reset_reg_val = ecore_rd(p_hwfn, p_ptt, reset_reg_addr);
+	new_reset_reg_val =
+	    old_reset_reg_val & ~OSAL_BIT(block->reset_reg_bit_offset);
+
+	ecore_wr(p_hwfn, p_ptt, reset_reg_addr, new_reset_reg_val);
+	ecore_wr(p_hwfn, p_ptt, reset_reg_addr, old_reset_reg_val);
+}
+
+/* Enable / disable Debug Bus clients according to the specified mask
+ * (1 = enable, 0 = disable).
+ */
+static void qed_bus_enable_clients(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt, u32 client_mask)
+{
+	ecore_wr(p_hwfn, p_ptt, DBG_REG_CLIENT_ENABLE, client_mask);
+}
+
+static void qed_bus_config_dbg_line(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    enum block_id block_id,
+				    u8 line_id,
+				    u8 enable_mask,
+				    u8 right_shift,
+				    u8 force_valid_mask, u8 force_frame_mask)
+{
+	const struct dbg_block_chip *block =
+		qed_get_dbg_block_per_chip(p_hwfn, block_id);
+
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_select_reg_addr),
+		 line_id);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_dword_enable_reg_addr),
+		 enable_mask);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_shift_reg_addr),
+		 right_shift);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_force_valid_reg_addr),
+		 force_valid_mask);
+	ecore_wr(p_hwfn, p_ptt,
+		 DWORDS_TO_BYTES(block->dbg_force_frame_reg_addr),
+		 force_frame_mask);
+}
+
+/* Disable debug bus in all blocks */
+static void qed_bus_disable_blocks(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_id;
+
+	/* Disable all blocks */
+	for (block_id = 0; block_id < MAX_BLOCK_ID; block_id++) {
+		const struct dbg_block_chip *block_per_chip =
+		    qed_get_dbg_block_per_chip(p_hwfn,
+					       (enum block_id)block_id);
+
+		if (GET_FIELD(block_per_chip->flags,
+			      DBG_BLOCK_CHIP_IS_REMOVED) ||
+		    dev_data->block_in_reset[block_id])
+			continue;
+
+		/* Disable debug bus */
+		if (GET_FIELD(block_per_chip->flags,
+			      DBG_BLOCK_CHIP_HAS_DBG_BUS)) {
+			u32 dbg_en_addr =
+				block_per_chip->dbg_dword_enable_reg_addr;
+			u16 modes_buf_offset =
+			    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+				      DBG_MODE_HDR_MODES_BUF_OFFSET);
+			bool eval_mode =
+			    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+
+			if (!eval_mode ||
+			    qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				ecore_wr(p_hwfn, p_ptt,
+				       DWORDS_TO_BYTES(dbg_en_addr),
+				       0);
+		}
+	}
+}
+
+/* Returns true if the specified entity (indicated by GRC param) should be
+ * included in the dump, false otherwise.
+ */
+static bool qed_grc_is_included(struct ecore_hwfn *p_hwfn,
+				enum dbg_grc_params grc_param)
+{
+	return qed_grc_get_param(p_hwfn, grc_param) > 0;
+}
+
+/* Returns the storm_id that matches the specified Storm letter,
+ * or MAX_DBG_STORMS if invalid storm letter.
+ */
+static enum dbg_storms qed_get_id_from_letter(char storm_letter)
+{
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++)
+		if (s_storm_defs[storm_id].letter == storm_letter)
+			return (enum dbg_storms)storm_id;
+
+	return MAX_DBG_STORMS;
+}
+
+/* Returns true of the specified Storm should be included in the dump, false
+ * otherwise.
+ */
+static bool qed_grc_is_storm_included(struct ecore_hwfn *p_hwfn,
+				      enum dbg_storms storm)
+{
+	return qed_grc_get_param(p_hwfn, (enum dbg_grc_params)storm) > 0;
+}
+
+/* Returns true if the specified memory should be included in the dump, false
+ * otherwise.
+ */
+static bool qed_grc_is_mem_included(struct ecore_hwfn *p_hwfn,
+				    enum block_id block_id, u8 mem_group_id)
+{
+	const struct dbg_block *block;
+	u8 i;
+
+	block = get_dbg_block(p_hwfn, block_id);
+
+	/* If the block is associated with a Storm, check Storm match */
+	if (block->associated_storm_letter) {
+		enum dbg_storms associated_storm_id =
+		    qed_get_id_from_letter(block->associated_storm_letter);
+
+		if (associated_storm_id == MAX_DBG_STORMS ||
+		    !qed_grc_is_storm_included(p_hwfn, associated_storm_id))
+			return false;
+	}
+
+	for (i = 0; i < NUM_BIG_RAM_TYPES; i++) {
+		struct big_ram_defs *big_ram = &s_big_ram_defs[i];
+
+		if (mem_group_id == big_ram->mem_group_id ||
+		    mem_group_id == big_ram->ram_mem_group_id)
+			return qed_grc_is_included(p_hwfn, big_ram->grc_param);
+	}
+
+	switch (mem_group_id) {
+	case MEM_GROUP_PXP_ILT:
+	case MEM_GROUP_PXP_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PXP);
+	case MEM_GROUP_RAM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_RAM);
+	case MEM_GROUP_PBUF:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PBUF);
+	case MEM_GROUP_CAU_MEM:
+	case MEM_GROUP_CAU_SB:
+	case MEM_GROUP_CAU_PI:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CAU);
+	case MEM_GROUP_CAU_MEM_EXT:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CAU_EXT);
+	case MEM_GROUP_QM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_QM);
+	case MEM_GROUP_CFC_MEM:
+	case MEM_GROUP_CONN_CFC_MEM:
+	case MEM_GROUP_TASK_CFC_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CFC) ||
+		       qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM_CTX);
+	case MEM_GROUP_DORQ_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DORQ);
+	case MEM_GROUP_IGU_MEM:
+	case MEM_GROUP_IGU_MSIX:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_IGU);
+	case MEM_GROUP_MULD_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MULD);
+	case MEM_GROUP_PRS_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PRS);
+	case MEM_GROUP_DMAE_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DMAE);
+	case MEM_GROUP_TM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_TM);
+	case MEM_GROUP_SDM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_SDM);
+	case MEM_GROUP_TDIF_CTX:
+	case MEM_GROUP_RDIF_CTX:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DIF);
+	case MEM_GROUP_CM_MEM:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM);
+	case MEM_GROUP_IOR:
+		return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_IOR);
+	default:
+		return true;
+	}
+}
+
+/* Stalls all Storms */
+static void qed_grc_stall_storms(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt, bool stall)
+{
+	u32 reg_addr;
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		if (!qed_grc_is_storm_included(p_hwfn,
+					       (enum dbg_storms)storm_id))
+			continue;
+
+		reg_addr = s_storm_defs[storm_id].sem_fast_mem_addr +
+		    SEM_FAST_REG_STALL_0;
+		ecore_wr(p_hwfn, p_ptt, reg_addr, stall ? 1 : 0);
+	}
+
+	OSAL_MSLEEP(STALL_DELAY_MS);
+}
+
+/* Takes all blocks out of reset. If rbc_only is true, only RBC clients are
+ * taken out of reset.
+ */
+static void qed_grc_unreset_blocks(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt, bool rbc_only)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 chip_id = dev_data->chip_id;
+	u32 i;
+
+	/* Take RBCs out of reset */
+	for (i = 0; i < OSAL_ARRAY_SIZE(s_rbc_reset_defs); i++)
+		if (s_rbc_reset_defs[i].reset_val[dev_data->chip_id])
+			ecore_wr(p_hwfn,
+			       p_ptt,
+			       s_rbc_reset_defs[i].reset_reg_addr +
+			       RESET_REG_UNRESET_OFFSET,
+			       s_rbc_reset_defs[i].reset_val[chip_id]);
+
+	if (!rbc_only) {
+		u32 reg_val[NUM_DBG_RESET_REGS] = { 0 };
+		u8 reset_reg_id;
+		u32 block_id;
+
+		/* Fill reset regs values */
+		for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
+			bool is_removed, has_reset_reg, unreset_before_dump;
+			const struct dbg_block_chip *block;
+
+			block = qed_get_dbg_block_per_chip(p_hwfn,
+							   (enum block_id)
+							   block_id);
+			is_removed =
+			    GET_FIELD(block->flags, DBG_BLOCK_CHIP_IS_REMOVED);
+			has_reset_reg =
+			    GET_FIELD(block->flags,
+				      DBG_BLOCK_CHIP_HAS_RESET_REG);
+			unreset_before_dump =
+			    GET_FIELD(block->flags,
+				      DBG_BLOCK_CHIP_UNRESET_BEFORE_DUMP);
+
+			if (!is_removed && has_reset_reg && unreset_before_dump)
+				reg_val[block->reset_reg_id] |=
+				    OSAL_BIT(block->reset_reg_bit_offset);
+		}
+
+		/* Write reset registers */
+		for (reset_reg_id = 0; reset_reg_id < NUM_DBG_RESET_REGS;
+		     reset_reg_id++) {
+			const struct dbg_reset_reg *reset_reg;
+			u32 reset_reg_addr;
+
+			reset_reg = qed_get_dbg_reset_reg(p_hwfn, reset_reg_id);
+
+			if (GET_FIELD
+			    (reset_reg->data, DBG_RESET_REG_IS_REMOVED))
+				continue;
+
+			if (reg_val[reset_reg_id]) {
+				reset_reg_addr =
+				    GET_FIELD(reset_reg->data,
+					      DBG_RESET_REG_ADDR);
+				ecore_wr(p_hwfn,
+				       p_ptt,
+				       DWORDS_TO_BYTES(reset_reg_addr) +
+				       RESET_REG_UNRESET_OFFSET,
+				       reg_val[reset_reg_id]);
+			}
+		}
+	}
+}
+
+/* Returns the attention block data of the specified block */
+static const struct dbg_attn_block_type_data *
+qed_get_block_attn_data(struct ecore_hwfn *p_hwfn,
+			enum block_id block_id, enum dbg_attn_type attn_type)
+{
+	const struct dbg_attn_block *base_attn_block_arr =
+	    (const struct dbg_attn_block *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr;
+
+	return &base_attn_block_arr[block_id].per_type_data[attn_type];
+}
+
+/* Returns the attention registers of the specified block */
+static const struct dbg_attn_reg *
+qed_get_block_attn_regs(struct ecore_hwfn *p_hwfn,
+			enum block_id block_id, enum dbg_attn_type attn_type,
+			u8 *num_attn_regs)
+{
+	const struct dbg_attn_block_type_data *block_type_data =
+	    qed_get_block_attn_data(p_hwfn, block_id, attn_type);
+
+	*num_attn_regs = block_type_data->num_regs;
+
+	return (const struct dbg_attn_reg *)
+		p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr +
+		block_type_data->regs_offset;
+}
+
+/* For each block, clear the status of all parities */
+static void qed_grc_clear_all_prty(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	const struct dbg_attn_reg *attn_reg_arr;
+	u8 reg_idx, num_attn_regs;
+	u32 block_id;
+
+	for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
+		if (dev_data->block_in_reset[block_id])
+			continue;
+
+		attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
+						       (enum block_id)block_id,
+						       ATTN_TYPE_PARITY,
+						       &num_attn_regs);
+
+		for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
+			const struct dbg_attn_reg *reg_data =
+				&attn_reg_arr[reg_idx];
+			u16 modes_buf_offset;
+			bool eval_mode;
+
+			/* Check mode */
+			eval_mode = GET_FIELD(reg_data->mode.data,
+					      DBG_MODE_HDR_EVAL_MODE) > 0;
+			modes_buf_offset =
+				GET_FIELD(reg_data->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+
+			/* If Mode match: clear parity status */
+			if (!eval_mode ||
+			    qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				ecore_rd(p_hwfn, p_ptt,
+				    DWORDS_TO_BYTES(reg_data->sts_clr_address));
+		}
+	}
+}
+
+/* Dumps GRC registers section header. Returns the dumped size in dwords.
+ * the following parameters are dumped:
+ * - count: no. of dumped entries
+ * - split_type: split type
+ * - split_id: split ID (dumped only if split_id != SPLIT_TYPE_NONE)
+ * - reg_type_name: register type name (dumped only if reg_type_name != NULL)
+ */
+static u32 qed_grc_dump_regs_hdr(u32 *dump_buf,
+				 bool dump,
+				 u32 num_reg_entries,
+				 enum init_split_types split_type,
+				 u8 split_id, const char *reg_type_name)
+{
+	u8 num_params = 2 +
+	    (split_type != SPLIT_TYPE_NONE ? 1 : 0) + (reg_type_name ? 1 : 0);
+	u32 offset = 0;
+
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "grc_regs", num_params);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "count", num_reg_entries);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "split",
+				     s_split_type_defs[split_type].name);
+	if (split_type != SPLIT_TYPE_NONE)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "id", split_id);
+	if (reg_type_name)
+		offset += qed_dump_str_param(dump_buf + offset,
+					     dump, "type", reg_type_name);
+
+	return offset;
+}
+
+/* Reads the specified registers into the specified buffer.
+ * The addr and len arguments are specified in dwords.
+ */
+void qed_read_regs(struct ecore_hwfn *p_hwfn,
+		   struct ecore_ptt *p_ptt, u32 *buf, u32 addr, u32 len)
+{
+	u32 i;
+
+	for (i = 0; i < len; i++)
+		buf[i] = ecore_rd(p_hwfn, p_ptt, DWORDS_TO_BYTES(addr + i));
+}
+
+/* Dumps the GRC registers in the specified address range.
+ * Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_addr_range(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   u32 *dump_buf,
+				   bool dump, u32 addr, u32 len, bool wide_bus,
+				   enum init_split_types split_type,
+				   u8 split_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 port_id = 0, pf_id = 0, vf_id = 0, fid = 0;
+	bool read_using_dmae = false;
+	u32 thresh;
+
+	if (!dump)
+		return len;
+
+	switch (split_type) {
+	case SPLIT_TYPE_PORT:
+		port_id = split_id;
+		break;
+	case SPLIT_TYPE_PF:
+		pf_id = split_id;
+		break;
+	case SPLIT_TYPE_PORT_PF:
+		port_id = split_id / dev_data->num_pfs_per_port;
+		pf_id = port_id + dev_data->num_ports *
+		    (split_id % dev_data->num_pfs_per_port);
+		break;
+	case SPLIT_TYPE_VF:
+		vf_id = split_id;
+		break;
+	default:
+		break;
+	}
+
+	/* Try reading using DMAE */
+	if (dev_data->use_dmae && split_type != SPLIT_TYPE_VF &&
+	    (len >= s_hw_type_defs[dev_data->hw_type].dmae_thresh ||
+	     (PROTECT_WIDE_BUS && wide_bus))) {
+		struct dmae_params dmae_params;
+
+		/* Set DMAE params */
+		memset(&dmae_params, 0, sizeof(dmae_params));
+		SET_FIELD(dmae_params.flags, DMAE_PARAMS_COMPLETION_DST, 1);
+		switch (split_type) {
+		case SPLIT_TYPE_PORT:
+			SET_FIELD(dmae_params.flags, DMAE_PARAMS_PORT_VALID,
+				  1);
+			dmae_params.port_id = port_id;
+			break;
+		case SPLIT_TYPE_PF:
+			SET_FIELD(dmae_params.flags,
+				  DMAE_PARAMS_SRC_PF_VALID, 1);
+			dmae_params.src_pf_id = pf_id;
+			break;
+		case SPLIT_TYPE_PORT_PF:
+			SET_FIELD(dmae_params.flags, DMAE_PARAMS_PORT_VALID,
+				  1);
+			SET_FIELD(dmae_params.flags,
+				  DMAE_PARAMS_SRC_PF_VALID, 1);
+			dmae_params.port_id = port_id;
+			dmae_params.src_pf_id = pf_id;
+			break;
+		default:
+			break;
+		}
+
+		/* Execute DMAE command */
+		read_using_dmae = !ecore_dmae_grc2host(p_hwfn,
+						     p_ptt,
+						     DWORDS_TO_BYTES(addr),
+						     (u64)(uintptr_t)(dump_buf),
+						     len, &dmae_params);
+		if (!read_using_dmae) {
+			dev_data->use_dmae = 0;
+			DP_VERBOSE(p_hwfn->p_dev,
+				   ECORE_MSG_DEBUG,
+				   "Failed reading from chip using DMAE, using GRC instead\n");
+		}
+	}
+
+	if (read_using_dmae)
+		goto print_log;
+
+	/* If not read using DMAE, read using GRC */
+
+	/* Set pretend */
+	if (split_type != dev_data->pretend.split_type ||
+	    split_id != dev_data->pretend.split_id) {
+		switch (split_type) {
+		case SPLIT_TYPE_PORT:
+			ecore_port_pretend(p_hwfn, p_ptt, port_id);
+			break;
+		case SPLIT_TYPE_PF:
+			fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
+					  pf_id);
+			ecore_fid_pretend(p_hwfn, p_ptt, fid);
+			break;
+		case SPLIT_TYPE_PORT_PF:
+			fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
+					  pf_id);
+			ecore_port_fid_pretend(p_hwfn, p_ptt, port_id, fid);
+			break;
+		case SPLIT_TYPE_VF:
+			fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_VFVALID, 1)
+			      | FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_VFID,
+					  vf_id);
+			ecore_fid_pretend(p_hwfn, p_ptt, fid);
+			break;
+		default:
+			break;
+		}
+
+		dev_data->pretend.split_type = (u8)split_type;
+		dev_data->pretend.split_id = split_id;
+	}
+
+	/* Read registers using GRC */
+	qed_read_regs(p_hwfn, p_ptt, dump_buf, addr, len);
+
+print_log:
+	/* Print log */
+	dev_data->num_regs_read += len;
+	thresh = s_hw_type_defs[dev_data->hw_type].log_thresh;
+	if ((dev_data->num_regs_read / thresh) >
+	    ((dev_data->num_regs_read - len) / thresh))
+		DP_VERBOSE(p_hwfn->p_dev,
+			   ECORE_MSG_DEBUG,
+			   "Dumped %d registers...\n", dev_data->num_regs_read);
+
+	return len;
+}
+
+/* Dumps GRC registers sequence header. Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_reg_entry_hdr(u32 *dump_buf,
+				      bool dump, u32 addr, u32 len)
+{
+	if (dump)
+		*dump_buf = addr | (len << REG_DUMP_LEN_SHIFT);
+
+	return 1;
+}
+
+/* Dumps GRC registers sequence. Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_reg_entry(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  u32 *dump_buf,
+				  bool dump, u32 addr, u32 len, bool wide_bus,
+				  enum init_split_types split_type, u8 split_id)
+{
+	u32 offset = 0;
+
+	offset += qed_grc_dump_reg_entry_hdr(dump_buf, dump, addr, len);
+	offset += qed_grc_dump_addr_range(p_hwfn,
+					  p_ptt,
+					  dump_buf + offset,
+					  dump, addr, len, wide_bus,
+					  split_type, split_id);
+
+	return offset;
+}
+
+/* Dumps GRC registers sequence with skip cycle.
+ * Returns the dumped size in dwords.
+ * - addr:	start GRC address in dwords
+ * - total_len:	total no. of dwords to dump
+ * - read_len:	no. consecutive dwords to read
+ * - skip_len:	no. of dwords to skip (and fill with zeros)
+ */
+static u32 qed_grc_dump_reg_entry_skip(struct ecore_hwfn *p_hwfn,
+				       struct ecore_ptt *p_ptt,
+				       u32 *dump_buf,
+				       bool dump,
+				       u32 addr,
+				       u32 total_len,
+				       u32 read_len, u32 skip_len)
+{
+	u32 offset = 0, reg_offset = 0;
+
+	offset += qed_grc_dump_reg_entry_hdr(dump_buf, dump, addr, total_len);
+
+	if (!dump)
+		return offset + total_len;
+
+	while (reg_offset < total_len) {
+		u32 curr_len = OSAL_MIN_T(u32, read_len,
+					  total_len - reg_offset);
+
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  dump,  addr, curr_len, false,
+						  SPLIT_TYPE_NONE, 0);
+		reg_offset += curr_len;
+		addr += curr_len;
+
+		if (reg_offset < total_len) {
+			curr_len = OSAL_MIN_T(u32, skip_len,
+					      total_len - skip_len);
+			memset(dump_buf + offset, 0, DWORDS_TO_BYTES(curr_len));
+			offset += curr_len;
+			reg_offset += curr_len;
+			addr += curr_len;
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC registers entries. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_regs_entries(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     struct virt_mem_desc input_regs_arr,
+				     u32 *dump_buf,
+				     bool dump,
+				     enum init_split_types split_type,
+				     u8 split_id,
+				     bool block_enable[MAX_BLOCK_ID],
+				     u32 *num_dumped_reg_entries)
+{
+	u32 i, offset = 0, input_offset = 0;
+	bool mode_match = true;
+
+	*num_dumped_reg_entries = 0;
+
+	while (input_offset < BYTES_TO_DWORDS(input_regs_arr.size)) {
+		const struct dbg_dump_cond_hdr *cond_hdr =
+		    (const struct dbg_dump_cond_hdr *)
+		    input_regs_arr.ptr + input_offset++;
+		u16 modes_buf_offset;
+		bool eval_mode;
+
+		/* Check mode/block */
+		eval_mode = GET_FIELD(cond_hdr->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		if (eval_mode) {
+			modes_buf_offset =
+				GET_FIELD(cond_hdr->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			mode_match = qed_is_mode_match(p_hwfn,
+						       &modes_buf_offset);
+		}
+
+		if (!mode_match || !block_enable[cond_hdr->block_id]) {
+			input_offset += cond_hdr->data_size;
+			continue;
+		}
+
+		for (i = 0; i < cond_hdr->data_size; i++, input_offset++) {
+			const struct dbg_dump_reg *reg =
+			    (const struct dbg_dump_reg *)
+			    input_regs_arr.ptr + input_offset;
+			u32 addr, len;
+			bool wide_bus;
+
+			addr = GET_FIELD(reg->data, DBG_DUMP_REG_ADDRESS);
+			len = GET_FIELD(reg->data, DBG_DUMP_REG_LENGTH);
+			wide_bus = GET_FIELD(reg->data, DBG_DUMP_REG_WIDE_BUS);
+			offset += qed_grc_dump_reg_entry(p_hwfn,
+							 p_ptt,
+							 dump_buf + offset,
+							 dump,
+							 addr,
+							 len,
+							 wide_bus,
+							 split_type, split_id);
+			(*num_dumped_reg_entries)++;
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC registers entries. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_split_data(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   struct virt_mem_desc input_regs_arr,
+				   u32 *dump_buf,
+				   bool dump,
+				   bool block_enable[MAX_BLOCK_ID],
+				   enum init_split_types split_type,
+				   u8 split_id, const char *reg_type_name)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	enum init_split_types hdr_split_type = split_type;
+	u32 num_dumped_reg_entries, offset;
+	u8 hdr_split_id = split_id;
+
+	/* In PORT_PF split type, print a port split header */
+	if (split_type == SPLIT_TYPE_PORT_PF) {
+		hdr_split_type = SPLIT_TYPE_PORT;
+		hdr_split_id = split_id / dev_data->num_pfs_per_port;
+	}
+
+	/* Calculate register dump header size (and skip it for now) */
+	offset = qed_grc_dump_regs_hdr(dump_buf,
+				       false,
+				       0,
+				       hdr_split_type,
+				       hdr_split_id, reg_type_name);
+
+	/* Dump registers */
+	offset += qed_grc_dump_regs_entries(p_hwfn,
+					    p_ptt,
+					    input_regs_arr,
+					    dump_buf + offset,
+					    dump,
+					    split_type,
+					    split_id,
+					    block_enable,
+					    &num_dumped_reg_entries);
+
+	/* Write register dump header */
+	if (dump && num_dumped_reg_entries > 0)
+		qed_grc_dump_regs_hdr(dump_buf,
+				      dump,
+				      num_dumped_reg_entries,
+				      hdr_split_type,
+				      hdr_split_id, reg_type_name);
+
+	return num_dumped_reg_entries > 0 ? offset : 0;
+}
+
+/* Dumps registers according to the input registers array. Returns the dumped
+ * size in dwords.
+ */
+static u32 qed_grc_dump_registers(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  u32 *dump_buf,
+				  bool dump,
+				  bool block_enable[MAX_BLOCK_ID],
+				  const char *reg_type_name)
+{
+	struct virt_mem_desc *dbg_buf =
+	    &p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG];
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 offset = 0, input_offset = 0;
+
+	while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
+		const struct dbg_dump_split_hdr *split_hdr;
+		struct virt_mem_desc curr_input_regs_arr;
+		enum init_split_types split_type;
+		u16 split_count = 0;
+		u32 split_data_size;
+		u8 split_id;
+
+		split_hdr =
+		    (const struct dbg_dump_split_hdr *)
+		    dbg_buf->ptr + input_offset++;
+		split_type =
+		    GET_FIELD(split_hdr->hdr,
+			      DBG_DUMP_SPLIT_HDR_SPLIT_TYPE_ID);
+		split_data_size = GET_FIELD(split_hdr->hdr,
+					    DBG_DUMP_SPLIT_HDR_DATA_SIZE);
+		curr_input_regs_arr.ptr =
+		    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG].ptr +
+		    input_offset;
+		curr_input_regs_arr.size = DWORDS_TO_BYTES(split_data_size);
+
+		switch (split_type) {
+		case SPLIT_TYPE_NONE:
+			split_count = 1;
+			break;
+		case SPLIT_TYPE_PORT:
+			split_count = dev_data->num_ports;
+			break;
+		case SPLIT_TYPE_PF:
+		case SPLIT_TYPE_PORT_PF:
+			split_count = dev_data->num_ports *
+			    dev_data->num_pfs_per_port;
+			break;
+		case SPLIT_TYPE_VF:
+			split_count = dev_data->num_vfs;
+			break;
+		default:
+			return 0;
+		}
+
+		for (split_id = 0; split_id < split_count; split_id++)
+			offset += qed_grc_dump_split_data(p_hwfn, p_ptt,
+							  curr_input_regs_arr,
+							  dump_buf + offset,
+							  dump, block_enable,
+							  split_type,
+							  split_id,
+							  reg_type_name);
+
+		input_offset += split_data_size;
+	}
+
+	/* Cancel pretends (pretend to original PF) */
+	if (dump) {
+		ecore_fid_pretend(p_hwfn, p_ptt,
+				FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
+					    p_hwfn->rel_pf_id));
+		dev_data->pretend.split_type = SPLIT_TYPE_NONE;
+		dev_data->pretend.split_id = 0;
+	}
+
+	return offset;
+}
+
+/* Dump reset registers. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_reset_regs(struct ecore_hwfn *p_hwfn,
+				   struct ecore_ptt *p_ptt,
+				   u32 *dump_buf, bool dump)
+{
+	u32 offset = 0, num_regs = 0;
+	u8 reset_reg_id;
+
+	/* Calculate header size */
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					false,
+					0, SPLIT_TYPE_NONE, 0, "RESET_REGS");
+
+	/* Write reset registers */
+	for (reset_reg_id = 0; reset_reg_id < NUM_DBG_RESET_REGS;
+	     reset_reg_id++) {
+		const struct dbg_reset_reg *reset_reg;
+		u32 reset_reg_addr;
+
+		reset_reg = qed_get_dbg_reset_reg(p_hwfn, reset_reg_id);
+
+		if (GET_FIELD(reset_reg->data, DBG_RESET_REG_IS_REMOVED))
+			continue;
+
+		reset_reg_addr = GET_FIELD(reset_reg->data, DBG_RESET_REG_ADDR);
+		offset += qed_grc_dump_reg_entry(p_hwfn,
+						 p_ptt,
+						 dump_buf + offset,
+						 dump,
+						 reset_reg_addr,
+						 1, false, SPLIT_TYPE_NONE, 0);
+		num_regs++;
+	}
+
+	/* Write header */
+	if (dump)
+		qed_grc_dump_regs_hdr(dump_buf,
+				      true, num_regs, SPLIT_TYPE_NONE,
+				      0, "RESET_REGS");
+
+	return offset;
+}
+
+/* Dump registers that are modified during GRC Dump and therefore must be
+ * dumped first. Returns the dumped size in dwords.
+ */
+static u32 qed_grc_dump_modified_regs(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_id, offset = 0, stall_regs_offset;
+	const struct dbg_attn_reg *attn_reg_arr;
+	u8 storm_id, reg_idx, num_attn_regs;
+	u32 num_reg_entries = 0;
+
+	/* Write empty header for attention registers */
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					false,
+					0, SPLIT_TYPE_NONE, 0, "ATTN_REGS");
+
+	/* Write parity registers */
+	for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
+		if (dev_data->block_in_reset[block_id] && dump)
+			continue;
+
+		attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
+						       (enum block_id)block_id,
+						       ATTN_TYPE_PARITY,
+						       &num_attn_regs);
+
+		for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
+			const struct dbg_attn_reg *reg_data =
+				&attn_reg_arr[reg_idx];
+			u16 modes_buf_offset;
+			bool eval_mode;
+			u32 addr;
+
+			/* Check mode */
+			eval_mode = GET_FIELD(reg_data->mode.data,
+					      DBG_MODE_HDR_EVAL_MODE) > 0;
+			modes_buf_offset =
+				GET_FIELD(reg_data->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			if (eval_mode &&
+			    !qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				continue;
+
+			/* Mode match: read & dump registers */
+			addr = reg_data->mask_address;
+			offset += qed_grc_dump_reg_entry(p_hwfn,
+							 p_ptt,
+							 dump_buf + offset,
+							 dump,
+							 addr,
+							 1, false,
+							 SPLIT_TYPE_NONE, 0);
+			addr = GET_FIELD(reg_data->data,
+					 DBG_ATTN_REG_STS_ADDRESS);
+			offset += qed_grc_dump_reg_entry(p_hwfn,
+							 p_ptt,
+							 dump_buf + offset,
+							 dump,
+							 addr,
+							 1, false,
+							 SPLIT_TYPE_NONE, 0);
+			num_reg_entries += 2;
+		}
+	}
+
+	/* Overwrite header for attention registers */
+	if (dump)
+		qed_grc_dump_regs_hdr(dump_buf,
+				      true,
+				      num_reg_entries,
+				      SPLIT_TYPE_NONE, 0, "ATTN_REGS");
+
+	/* Write empty header for stall registers */
+	stall_regs_offset = offset;
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					false, 0, SPLIT_TYPE_NONE, 0, "REGS");
+
+	/* Write Storm stall status registers */
+	for (storm_id = 0, num_reg_entries = 0; storm_id < MAX_DBG_STORMS;
+	     storm_id++) {
+		struct storm_defs *storm = &s_storm_defs[storm_id];
+		u32 addr;
+
+		if (dev_data->block_in_reset[storm->sem_block_id] && dump)
+			continue;
+
+		addr =
+		    BYTES_TO_DWORDS(storm->sem_fast_mem_addr +
+				    SEM_FAST_REG_STALLED);
+		offset += qed_grc_dump_reg_entry(p_hwfn,
+						 p_ptt,
+						 dump_buf + offset,
+						 dump,
+						 addr,
+						 1,
+						 false, SPLIT_TYPE_NONE, 0);
+		num_reg_entries++;
+	}
+
+	/* Overwrite header for stall registers */
+	if (dump)
+		qed_grc_dump_regs_hdr(dump_buf + stall_regs_offset,
+				      true,
+				      num_reg_entries,
+				      SPLIT_TYPE_NONE, 0, "REGS");
+
+	return offset;
+}
+
+/* Dumps registers that can't be represented in the debug arrays */
+static u32 qed_grc_dump_special_regs(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     u32 *dump_buf, bool dump)
+{
+	u32 offset = 0, addr;
+
+	offset += qed_grc_dump_regs_hdr(dump_buf,
+					dump, 2, SPLIT_TYPE_NONE, 0, "REGS");
+
+	/* Dump R/TDIF_REG_DEBUG_ERROR_INFO_SIZE (every 8'th register should be
+	 * skipped).
+	 */
+	addr = BYTES_TO_DWORDS(RDIF_REG_DEBUG_ERROR_INFO);
+	offset += qed_grc_dump_reg_entry_skip(p_hwfn,
+					      p_ptt,
+					      dump_buf + offset,
+					      dump,
+					      addr,
+					      RDIF_REG_DEBUG_ERROR_INFO_SIZE,
+					      7,
+					      1);
+	addr = BYTES_TO_DWORDS(TDIF_REG_DEBUG_ERROR_INFO);
+	offset +=
+	    qed_grc_dump_reg_entry_skip(p_hwfn,
+					p_ptt,
+					dump_buf + offset,
+					dump,
+					addr,
+					TDIF_REG_DEBUG_ERROR_INFO_SIZE,
+					7,
+					1);
+
+	return offset;
+}
+
+/* Dumps a GRC memory header (section and params). Returns the dumped size in
+ * dwords. The following parameters are dumped:
+ * - name:	   dumped only if it's not NULL.
+ * - addr:	   in dwords, dumped only if name is NULL.
+ * - len:	   in dwords, always dumped.
+ * - width:	   dumped if it's not zero.
+ * - packed:	   dumped only if it's not false.
+ * - mem_group:	   always dumped.
+ * - is_storm:	   true only if the memory is related to a Storm.
+ * - storm_letter: valid only if is_storm is true.
+ *
+ */
+static u32 qed_grc_dump_mem_hdr(struct ecore_hwfn *p_hwfn,
+				u32 *dump_buf,
+				bool dump,
+				const char *name,
+				u32 addr,
+				u32 len,
+				u32 bit_width,
+				bool packed,
+				const char *mem_group, char storm_letter)
+{
+	u8 num_params = 3;
+	u32 offset = 0;
+	char buf[64];
+
+	if (!len)
+		DP_NOTICE(p_hwfn, false,
+			  "Unexpected GRC Dump error: dumped memory size must be non-zero\n");
+
+	if (bit_width)
+		num_params++;
+	if (packed)
+		num_params++;
+
+	/* Dump section header */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "grc_mem", num_params);
+
+	if (name) {
+		/* Dump name */
+		if (storm_letter) {
+			strcpy(buf, "?STORM_");
+			buf[0] = storm_letter;
+			strcpy(buf + strlen(buf), name);
+		} else {
+			strcpy(buf, name);
+		}
+
+		offset += qed_dump_str_param(dump_buf + offset,
+					     dump, "name", buf);
+	} else {
+		/* Dump address */
+		u32 addr_in_bytes = DWORDS_TO_BYTES(addr);
+
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "addr", addr_in_bytes);
+	}
+
+	/* Dump len */
+	offset += qed_dump_num_param(dump_buf + offset, dump, "len", len);
+
+	/* Dump bit width */
+	if (bit_width)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "width", bit_width);
+
+	/* Dump packed */
+	if (packed)
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump, "packed", 1);
+
+	/* Dump reg type */
+	if (storm_letter) {
+		strcpy(buf, "?STORM_");
+		buf[0] = storm_letter;
+		strcpy(buf + strlen(buf), mem_group);
+	} else {
+		strcpy(buf, mem_group);
+	}
+
+	offset += qed_dump_str_param(dump_buf + offset, dump, "type", buf);
+
+	return offset;
+}
+
+/* Dumps a single GRC memory. If name is NULL, the memory is stored by address.
+ * Returns the dumped size in dwords.
+ * The addr and len arguments are specified in dwords.
+ */
+static u32 qed_grc_dump_mem(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt,
+			    u32 *dump_buf,
+			    bool dump,
+			    const char *name,
+			    u32 addr,
+			    u32 len,
+			    bool wide_bus,
+			    u32 bit_width,
+			    bool packed,
+			    const char *mem_group, char storm_letter)
+{
+	u32 offset = 0;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       name,
+				       addr,
+				       len,
+				       bit_width,
+				       packed, mem_group, storm_letter);
+	offset += qed_grc_dump_addr_range(p_hwfn,
+					  p_ptt,
+					  dump_buf + offset,
+					  dump, addr, len, wide_bus,
+					  SPLIT_TYPE_NONE, 0);
+
+	return offset;
+}
+
+/* Dumps GRC memories entries. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_mem_entries(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    struct virt_mem_desc input_mems_arr,
+				    u32 *dump_buf, bool dump)
+{
+	u32 i, offset = 0, input_offset = 0;
+	bool mode_match = true;
+
+	while (input_offset < BYTES_TO_DWORDS(input_mems_arr.size)) {
+		const struct dbg_dump_cond_hdr *cond_hdr;
+		u16 modes_buf_offset;
+		u32 num_entries;
+		bool eval_mode;
+
+		cond_hdr =
+		    (const struct dbg_dump_cond_hdr *)input_mems_arr.ptr +
+		    input_offset++;
+		num_entries = cond_hdr->data_size / MEM_DUMP_ENTRY_SIZE_DWORDS;
+
+		/* Check required mode */
+		eval_mode = GET_FIELD(cond_hdr->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		if (eval_mode) {
+			modes_buf_offset =
+				GET_FIELD(cond_hdr->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			mode_match = qed_is_mode_match(p_hwfn,
+						       &modes_buf_offset);
+		}
+
+		if (!mode_match) {
+			input_offset += cond_hdr->data_size;
+			continue;
+		}
+
+		for (i = 0; i < num_entries;
+		     i++, input_offset += MEM_DUMP_ENTRY_SIZE_DWORDS) {
+			const struct dbg_dump_mem *mem =
+			    (const struct dbg_dump_mem *)((u32 *)
+							  input_mems_arr.ptr
+							  + input_offset);
+			const struct dbg_block *block;
+			char storm_letter = 0;
+			u32 mem_addr, mem_len;
+			bool mem_wide_bus;
+			u8 mem_group_id;
+
+			mem_group_id = GET_FIELD(mem->dword0,
+						 DBG_DUMP_MEM_MEM_GROUP_ID);
+			if (mem_group_id >= MEM_GROUPS_NUM) {
+				DP_NOTICE(p_hwfn, false, "Invalid mem_group_id\n");
+				return 0;
+			}
+
+			if (!qed_grc_is_mem_included(p_hwfn,
+						     (enum block_id)
+						     cond_hdr->block_id,
+						     mem_group_id))
+				continue;
+
+			mem_addr = GET_FIELD(mem->dword0, DBG_DUMP_MEM_ADDRESS);
+			mem_len = GET_FIELD(mem->dword1, DBG_DUMP_MEM_LENGTH);
+			mem_wide_bus = GET_FIELD(mem->dword1,
+						 DBG_DUMP_MEM_WIDE_BUS);
+
+			block = get_dbg_block(p_hwfn,
+					      cond_hdr->block_id);
+
+			/* If memory is associated with Storm,
+			 * update storm details
+			 */
+			if (block->associated_storm_letter)
+				storm_letter = block->associated_storm_letter;
+
+			/* Dump memory */
+			offset += qed_grc_dump_mem(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						NULL,
+						mem_addr,
+						mem_len,
+						mem_wide_bus,
+						0,
+						false,
+						s_mem_group_names[mem_group_id],
+						storm_letter);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC memories according to the input array dump_mem.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_grc_dump_memories(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf, bool dump)
+{
+	struct virt_mem_desc *dbg_buf =
+	    &p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_MEM];
+	u32 offset = 0, input_offset = 0;
+
+	while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
+		const struct dbg_dump_split_hdr *split_hdr;
+		struct virt_mem_desc curr_input_mems_arr;
+		enum init_split_types split_type;
+		u32 split_data_size;
+
+		split_hdr =
+		    (const struct dbg_dump_split_hdr *)dbg_buf->ptr +
+		    input_offset++;
+		split_type = GET_FIELD(split_hdr->hdr,
+				       DBG_DUMP_SPLIT_HDR_SPLIT_TYPE_ID);
+		split_data_size = GET_FIELD(split_hdr->hdr,
+					    DBG_DUMP_SPLIT_HDR_DATA_SIZE);
+		curr_input_mems_arr.ptr = (u32 *)dbg_buf->ptr + input_offset;
+		curr_input_mems_arr.size = DWORDS_TO_BYTES(split_data_size);
+
+		if (split_type == SPLIT_TYPE_NONE)
+			offset += qed_grc_dump_mem_entries(p_hwfn,
+							   p_ptt,
+							   curr_input_mems_arr,
+							   dump_buf + offset,
+							   dump);
+		else
+			DP_NOTICE(p_hwfn, false,
+				  "Dumping split memories is currently not supported\n");
+
+		input_offset += split_data_size;
+	}
+
+	return offset;
+}
+
+/* Dumps GRC context data for the specified Storm.
+ * Returns the dumped size in dwords.
+ * The lid_size argument is specified in quad-regs.
+ */
+static u32 qed_grc_dump_ctx_data(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf,
+				 bool dump,
+				 const char *name,
+				 u32 num_lids,
+				 enum cm_ctx_types ctx_type, u8 storm_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	u32 i, lid, lid_size, total_size;
+	u32 rd_reg_addr, offset = 0;
+
+	/* Convert quad-regs to dwords */
+	lid_size = storm->cm_ctx_lid_sizes[dev_data->chip_id][ctx_type] * 4;
+
+	if (!lid_size)
+		return 0;
+
+	total_size = num_lids * lid_size;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       name,
+				       0,
+				       total_size,
+				       lid_size * 32,
+				       false, name, storm->letter);
+
+	if (!dump)
+		return offset + total_size;
+
+	rd_reg_addr = BYTES_TO_DWORDS(storm->cm_ctx_rd_addr[ctx_type]);
+
+	/* Dump context data */
+	for (lid = 0; lid < num_lids; lid++) {
+		for (i = 0; i < lid_size; i++) {
+			ecore_wr(p_hwfn,
+			       p_ptt, storm->cm_ctx_wr_addr, (i << 9) | lid);
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  rd_reg_addr,
+							  1,
+							  false,
+							  SPLIT_TYPE_NONE, 0);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC contexts. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_ctx(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	u32 offset = 0;
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		if (!qed_grc_is_storm_included(p_hwfn,
+					       (enum dbg_storms)storm_id))
+			continue;
+
+		/* Dump Conn AG context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"CONN_AG_CTX",
+						NUM_OF_LCIDS,
+						CM_CTX_CONN_AG, storm_id);
+
+		/* Dump Conn ST context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"CONN_ST_CTX",
+						NUM_OF_LCIDS,
+						CM_CTX_CONN_ST, storm_id);
+
+		/* Dump Task AG context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"TASK_AG_CTX",
+						NUM_OF_LTIDS,
+						CM_CTX_TASK_AG, storm_id);
+
+		/* Dump Task ST context size */
+		offset += qed_grc_dump_ctx_data(p_hwfn,
+						p_ptt,
+						dump_buf + offset,
+						dump,
+						"TASK_ST_CTX",
+						NUM_OF_LTIDS,
+						CM_CTX_TASK_ST, storm_id);
+	}
+
+	return offset;
+}
+
+#define VFC_STATUS_RESP_READY_BIT	0
+#define VFC_STATUS_BUSY_BIT		1
+#define VFC_STATUS_SENDING_CMD_BIT	2
+
+#define VFC_POLLING_DELAY_MS	1
+#define VFC_POLLING_COUNT		20
+
+/* Reads data from VFC. Returns the number of dwords read (0 on error).
+ * Sizes are specified in dwords.
+ */
+static u32 qed_grc_dump_read_from_vfc(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      struct storm_defs *storm,
+				      u32 *cmd_data,
+				      u32 cmd_size,
+				      u32 *addr_data,
+				      u32 addr_size,
+				      u32 resp_size, u32 *dump_buf)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 vfc_status, polling_ms, polling_count = 0, i;
+	u32 reg_addr, sem_base;
+	bool is_ready = false;
+
+	sem_base = storm->sem_fast_mem_addr;
+	polling_ms = VFC_POLLING_DELAY_MS *
+	    s_hw_type_defs[dev_data->hw_type].delay_factor;
+
+	/* Write VFC command */
+	ARR_REG_WR(p_hwfn,
+		   p_ptt,
+		   sem_base + SEM_FAST_REG_VFC_DATA_WR,
+		   cmd_data, cmd_size);
+
+	/* Write VFC address */
+	ARR_REG_WR(p_hwfn,
+		   p_ptt,
+		   sem_base + SEM_FAST_REG_VFC_ADDR,
+		   addr_data, addr_size);
+
+	/* Read response */
+	for (i = 0; i < resp_size; i++) {
+		/* Poll until ready */
+		do {
+			reg_addr = sem_base + SEM_FAST_REG_VFC_STATUS;
+			qed_grc_dump_addr_range(p_hwfn,
+						p_ptt,
+						&vfc_status,
+						true,
+						BYTES_TO_DWORDS(reg_addr),
+						1,
+						false, SPLIT_TYPE_NONE, 0);
+			is_ready = vfc_status &
+				   OSAL_BIT(VFC_STATUS_RESP_READY_BIT);
+
+			if (!is_ready) {
+				if (polling_count++ == VFC_POLLING_COUNT)
+					return 0;
+
+				OSAL_MSLEEP(polling_ms);
+			}
+		} while (!is_ready);
+
+		reg_addr = sem_base + SEM_FAST_REG_VFC_DATA_RD;
+		qed_grc_dump_addr_range(p_hwfn,
+					p_ptt,
+					dump_buf + i,
+					true,
+					BYTES_TO_DWORDS(reg_addr),
+					1, false, SPLIT_TYPE_NONE, 0);
+	}
+
+	return resp_size;
+}
+
+/* Dump VFC CAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_vfc_cam(struct ecore_hwfn *p_hwfn,
+				struct ecore_ptt *p_ptt,
+				u32 *dump_buf, bool dump, u8 storm_id)
+{
+	u32 total_size = VFC_CAM_NUM_ROWS * VFC_CAM_RESP_DWORDS;
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	u32 cam_addr[VFC_CAM_ADDR_DWORDS] = { 0 };
+	u32 cam_cmd[VFC_CAM_CMD_DWORDS] = { 0 };
+	u32 row, offset = 0;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       "vfc_cam",
+				       0,
+				       total_size,
+				       256,
+				       false, "vfc_cam", storm->letter);
+
+	if (!dump)
+		return offset + total_size;
+
+	/* Prepare CAM address */
+	SET_VAR_FIELD(cam_addr, VFC_CAM_ADDR, OP, VFC_OPCODE_CAM_RD);
+
+	/* Read VFC CAM data */
+	for (row = 0; row < VFC_CAM_NUM_ROWS; row++) {
+		SET_VAR_FIELD(cam_cmd, VFC_CAM_CMD, ROW, row);
+		offset += qed_grc_dump_read_from_vfc(p_hwfn,
+						     p_ptt,
+						     storm,
+						     cam_cmd,
+						     VFC_CAM_CMD_DWORDS,
+						     cam_addr,
+						     VFC_CAM_ADDR_DWORDS,
+						     VFC_CAM_RESP_DWORDS,
+						     dump_buf + offset);
+	}
+
+	return offset;
+}
+
+/* Dump VFC RAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_vfc_ram(struct ecore_hwfn *p_hwfn,
+				struct ecore_ptt *p_ptt,
+				u32 *dump_buf,
+				bool dump,
+				u8 storm_id, struct vfc_ram_defs *ram_defs)
+{
+	u32 total_size = ram_defs->num_rows * VFC_RAM_RESP_DWORDS;
+	struct storm_defs *storm = &s_storm_defs[storm_id];
+	u32 ram_addr[VFC_RAM_ADDR_DWORDS] = { 0 };
+	u32 ram_cmd[VFC_RAM_CMD_DWORDS] = { 0 };
+	u32 row, offset = 0;
+
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       ram_defs->mem_name,
+				       0,
+				       total_size,
+				       256,
+				       false,
+				       ram_defs->type_name,
+				       storm->letter);
+
+	if (!dump)
+		return offset + total_size;
+
+	/* Prepare RAM address */
+	SET_VAR_FIELD(ram_addr, VFC_RAM_ADDR, OP, VFC_OPCODE_RAM_RD);
+
+	/* Read VFC RAM data */
+	for (row = ram_defs->base_row;
+	     row < ram_defs->base_row + ram_defs->num_rows; row++) {
+		SET_VAR_FIELD(ram_addr, VFC_RAM_ADDR, ROW, row);
+		offset += qed_grc_dump_read_from_vfc(p_hwfn,
+						     p_ptt,
+						     storm,
+						     ram_cmd,
+						     VFC_RAM_CMD_DWORDS,
+						     ram_addr,
+						     VFC_RAM_ADDR_DWORDS,
+						     VFC_RAM_RESP_DWORDS,
+						     dump_buf + offset);
+	}
+
+	return offset;
+}
+
+/* Dumps GRC VFC data. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_vfc(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	u8 storm_id, i;
+	u32 offset = 0;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		if (!qed_grc_is_storm_included(p_hwfn,
+					       (enum dbg_storms)storm_id) ||
+		    !s_storm_defs[storm_id].has_vfc)
+			continue;
+
+		/* Read CAM */
+		offset += qed_grc_dump_vfc_cam(p_hwfn,
+					       p_ptt,
+					       dump_buf + offset,
+					       dump, storm_id);
+
+		/* Read RAM */
+		for (i = 0; i < NUM_VFC_RAM_TYPES; i++)
+			offset += qed_grc_dump_vfc_ram(p_hwfn,
+						       p_ptt,
+						       dump_buf + offset,
+						       dump,
+						       storm_id,
+						       &s_vfc_ram_defs[i]);
+	}
+
+	return offset;
+}
+
+/* Dumps GRC RSS data. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_rss(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 offset = 0;
+	u8 rss_mem_id;
+
+	for (rss_mem_id = 0; rss_mem_id < NUM_RSS_MEM_TYPES; rss_mem_id++) {
+		u32 rss_addr, num_entries, total_dwords;
+		struct rss_mem_defs *rss_defs;
+		u32 addr, num_dwords_to_read;
+		bool packed;
+
+		rss_defs = &s_rss_mem_defs[rss_mem_id];
+		rss_addr = rss_defs->addr;
+		num_entries = rss_defs->num_entries[dev_data->chip_id];
+		total_dwords = (num_entries * rss_defs->entry_width) / 32;
+		packed = (rss_defs->entry_width == 16);
+
+		offset += qed_grc_dump_mem_hdr(p_hwfn,
+					       dump_buf + offset,
+					       dump,
+					       rss_defs->mem_name,
+					       0,
+					       total_dwords,
+					       rss_defs->entry_width,
+					       packed,
+					       rss_defs->type_name, 0);
+
+		/* Dump RSS data */
+		if (!dump) {
+			offset += total_dwords;
+			continue;
+		}
+
+		addr = BYTES_TO_DWORDS(RSS_REG_RSS_RAM_DATA);
+		while (total_dwords) {
+			num_dwords_to_read = OSAL_MIN_T(u32,
+						      RSS_REG_RSS_RAM_DATA_SIZE,
+						      total_dwords);
+			ecore_wr(p_hwfn, p_ptt, RSS_REG_RSS_RAM_ADDR, rss_addr);
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  addr,
+							  num_dwords_to_read,
+							  false,
+							  SPLIT_TYPE_NONE, 0);
+			total_dwords -= num_dwords_to_read;
+			rss_addr++;
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps GRC Big RAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_big_ram(struct ecore_hwfn *p_hwfn,
+				struct ecore_ptt *p_ptt,
+				u32 *dump_buf, bool dump, u8 big_ram_id)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_size, ram_size, offset = 0, reg_val, i;
+	char mem_name[12] = "???_BIG_RAM";
+	char type_name[8] = "???_RAM";
+	struct big_ram_defs *big_ram;
+
+	big_ram = &s_big_ram_defs[big_ram_id];
+	ram_size = big_ram->ram_size[dev_data->chip_id];
+
+	reg_val = ecore_rd(p_hwfn, p_ptt, big_ram->is_256b_reg_addr);
+	block_size = reg_val &
+		     OSAL_BIT(big_ram->is_256b_bit_offset[dev_data->chip_id]) ?
+								     256 : 128;
+
+	strncpy(type_name, big_ram->instance_name, BIG_RAM_NAME_LEN);
+	strncpy(mem_name, big_ram->instance_name, BIG_RAM_NAME_LEN);
+
+	/* Dump memory header */
+	offset += qed_grc_dump_mem_hdr(p_hwfn,
+				       dump_buf + offset,
+				       dump,
+				       mem_name,
+				       0,
+				       ram_size,
+				       block_size * 8,
+				       false, type_name, 0);
+
+	/* Read and dump Big RAM data */
+	if (!dump)
+		return offset + ram_size;
+
+	/* Dump Big RAM */
+	for (i = 0; i < DIV_ROUND_UP(ram_size, BRB_REG_BIG_RAM_DATA_SIZE);
+	     i++) {
+		u32 addr, len;
+
+		ecore_wr(p_hwfn, p_ptt, big_ram->addr_reg_addr, i);
+		addr = BYTES_TO_DWORDS(big_ram->data_reg_addr);
+		len = BRB_REG_BIG_RAM_DATA_SIZE;
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  dump,
+						  addr,
+						  len,
+						  false, SPLIT_TYPE_NONE, 0);
+	}
+
+	return offset;
+}
+
+/* Dumps MCP scratchpad. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_mcp(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	bool block_enable[MAX_BLOCK_ID] = { 0 };
+	u32 offset = 0, addr;
+	bool halted = false;
+
+	/* Halt MCP */
+	if (dump && !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP)) {
+		halted = !ecore_mcp_halt(p_hwfn, p_ptt);
+		if (!halted)
+			DP_NOTICE(p_hwfn, false, "MCP halt failed!\n");
+	}
+
+	/* Dump MCP scratchpad */
+	offset += qed_grc_dump_mem(p_hwfn,
+				   p_ptt,
+				   dump_buf + offset,
+				   dump,
+				   NULL,
+				   BYTES_TO_DWORDS(MCP_REG_SCRATCH),
+				   MCP_REG_SCRATCH_SIZE,
+				   false, 0, false, "MCP", 0);
+
+	/* Dump MCP cpu_reg_file */
+	offset += qed_grc_dump_mem(p_hwfn,
+				   p_ptt,
+				   dump_buf + offset,
+				   dump,
+				   NULL,
+				   BYTES_TO_DWORDS(MCP_REG_CPU_REG_FILE),
+				   MCP_REG_CPU_REG_FILE_SIZE,
+				   false, 0, false, "MCP", 0);
+
+	/* Dump MCP registers */
+	block_enable[BLOCK_MCP] = true;
+	offset += qed_grc_dump_registers(p_hwfn,
+					 p_ptt,
+					 dump_buf + offset,
+					 dump, block_enable, "MCP");
+
+	/* Dump required non-MCP registers */
+	offset += qed_grc_dump_regs_hdr(dump_buf + offset,
+					dump, 1, SPLIT_TYPE_NONE, 0,
+					"MCP");
+	addr = BYTES_TO_DWORDS(MISC_REG_SHARED_MEM_ADDR);
+	offset += qed_grc_dump_reg_entry(p_hwfn,
+					 p_ptt,
+					 dump_buf + offset,
+					 dump,
+					 addr,
+					 1,
+					 false, SPLIT_TYPE_NONE, 0);
+
+	/* Release MCP */
+	if (halted && ecore_mcp_resume(p_hwfn, p_ptt))
+		DP_NOTICE(p_hwfn, false, "Failed to resume MCP after halt!\n");
+
+	return offset;
+}
+
+/* Dumps the tbus indirect memory for all PHYs.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_grc_dump_phy(struct ecore_hwfn *p_hwfn,
+			    struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	u32 offset = 0, tbus_lo_offset, tbus_hi_offset;
+	char mem_name[32];
+	u8 phy_id;
+
+	for (phy_id = 0; phy_id < OSAL_ARRAY_SIZE(s_phy_defs); phy_id++) {
+		u32 addr_lo_addr, addr_hi_addr, data_lo_addr, data_hi_addr;
+		struct phy_defs *phy_defs;
+		u8 *bytes_buf;
+
+		phy_defs = &s_phy_defs[phy_id];
+		addr_lo_addr = phy_defs->base_addr +
+			       phy_defs->tbus_addr_lo_addr;
+		addr_hi_addr = phy_defs->base_addr +
+			       phy_defs->tbus_addr_hi_addr;
+		data_lo_addr = phy_defs->base_addr +
+			       phy_defs->tbus_data_lo_addr;
+		data_hi_addr = phy_defs->base_addr +
+			       phy_defs->tbus_data_hi_addr;
+
+		if (snprintf(mem_name, sizeof(mem_name), "tbus_%s",
+			     phy_defs->phy_name) < 0)
+			DP_NOTICE(p_hwfn, false,
+				  "Unexpected debug error: invalid PHY memory name\n");
+
+		offset += qed_grc_dump_mem_hdr(p_hwfn,
+					       dump_buf + offset,
+					       dump,
+					       mem_name,
+					       0,
+					       PHY_DUMP_SIZE_DWORDS,
+					       16, true, mem_name, 0);
+
+		if (!dump) {
+			offset += PHY_DUMP_SIZE_DWORDS;
+			continue;
+		}
+
+		bytes_buf = (u8 *)(dump_buf + offset);
+		for (tbus_hi_offset = 0;
+		     tbus_hi_offset < (NUM_PHY_TBUS_ADDRESSES >> 8);
+		     tbus_hi_offset++) {
+			ecore_wr(p_hwfn, p_ptt, addr_hi_addr, tbus_hi_offset);
+			for (tbus_lo_offset = 0; tbus_lo_offset < 256;
+			     tbus_lo_offset++) {
+				ecore_wr(p_hwfn,
+				       p_ptt, addr_lo_addr, tbus_lo_offset);
+				*(bytes_buf++) = (u8)ecore_rd(p_hwfn,
+							    p_ptt,
+							    data_lo_addr);
+				*(bytes_buf++) = (u8)ecore_rd(p_hwfn,
+							    p_ptt,
+							    data_hi_addr);
+			}
+		}
+
+		offset += PHY_DUMP_SIZE_DWORDS;
+	}
+
+	return offset;
+}
+
+static enum dbg_status qed_find_nvram_image(struct ecore_hwfn *p_hwfn,
+					    struct ecore_ptt *p_ptt,
+					    u32 image_type,
+					    u32 *nvram_offset_bytes,
+					    u32 *nvram_size_bytes);
+
+static enum dbg_status qed_nvram_read(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 nvram_offset_bytes,
+				      u32 nvram_size_bytes, u32 *ret_buf);
+
+/* Dumps the MCP HW dump from NVRAM. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_mcp_hw_dump(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    u32 *dump_buf, bool dump)
+{
+	u32 hw_dump_offset_bytes = 0, hw_dump_size_bytes = 0;
+	u32 hw_dump_size_dwords = 0, offset = 0;
+	enum dbg_status status;
+
+	/* Read HW dump image from NVRAM */
+	status = qed_find_nvram_image(p_hwfn,
+				      p_ptt,
+				      NVM_TYPE_HW_DUMP_OUT,
+				      &hw_dump_offset_bytes,
+				      &hw_dump_size_bytes);
+	if (status != DBG_STATUS_OK)
+		return 0;
+
+	hw_dump_size_dwords = BYTES_TO_DWORDS(hw_dump_size_bytes);
+
+	/* Dump HW dump image section */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "mcp_hw_dump", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", hw_dump_size_dwords);
+
+	/* Read MCP HW dump image into dump buffer */
+	if (dump && hw_dump_size_dwords) {
+		status = qed_nvram_read(p_hwfn,
+					p_ptt,
+					hw_dump_offset_bytes,
+					hw_dump_size_bytes, dump_buf + offset);
+		if (status != DBG_STATUS_OK) {
+			DP_NOTICE(p_hwfn, false,
+				  "Failed to read MCP HW Dump image from NVRAM\n");
+			return 0;
+		}
+	}
+	offset += hw_dump_size_dwords;
+
+	return offset;
+}
+
+/* Dumps Static Debug data. Returns the dumped size in dwords. */
+static u32 qed_grc_dump_static_debug(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     u32 *dump_buf, bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 block_id, line_id, offset = 0, addr, len;
+
+	/* Don't dump static debug if a debug bus recording is in progress */
+	if (dump && ecore_rd(p_hwfn, p_ptt, DBG_REG_DBG_BLOCK_ON))
+		return 0;
+
+	if (dump) {
+		/* Disable debug bus in all blocks */
+		qed_bus_disable_blocks(p_hwfn, p_ptt);
+
+		qed_bus_reset_dbg_block(p_hwfn, p_ptt);
+		ecore_wr(p_hwfn,
+		       p_ptt, DBG_REG_FRAMING_MODE, DBG_BUS_FRAME_MODE_8HW);
+		ecore_wr(p_hwfn,
+		       p_ptt, DBG_REG_DEBUG_TARGET, DBG_BUS_TARGET_ID_INT_BUF);
+		ecore_wr(p_hwfn, p_ptt, DBG_REG_FULL_MODE, 1);
+		qed_bus_enable_dbg_block(p_hwfn, p_ptt, true);
+	}
+
+	/* Dump all static debug lines for each relevant block */
+	for (block_id = 0; block_id < MAX_BLOCK_ID; block_id++) {
+		const struct dbg_block_chip *block_per_chip;
+		const struct dbg_block *block;
+		bool is_removed, has_dbg_bus;
+		u16 modes_buf_offset;
+		u32 block_dwords;
+
+		block_per_chip =
+		    qed_get_dbg_block_per_chip(p_hwfn, (enum block_id)block_id);
+		is_removed = GET_FIELD(block_per_chip->flags,
+				       DBG_BLOCK_CHIP_IS_REMOVED);
+		has_dbg_bus = GET_FIELD(block_per_chip->flags,
+					DBG_BLOCK_CHIP_HAS_DBG_BUS);
+
+		/* read+clear for NWS parity is not working, skip NWS block */
+		if (block_id == BLOCK_NWS)
+			continue;
+
+		if (!is_removed && has_dbg_bus &&
+		    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+			      DBG_MODE_HDR_EVAL_MODE) > 0) {
+			modes_buf_offset =
+			    GET_FIELD(block_per_chip->dbg_bus_mode.data,
+				      DBG_MODE_HDR_MODES_BUF_OFFSET);
+			if (!qed_is_mode_match(p_hwfn, &modes_buf_offset))
+				has_dbg_bus = false;
+		}
+
+		if (is_removed || !has_dbg_bus)
+			continue;
+
+		block_dwords = NUM_DBG_LINES(block_per_chip) *
+			       STATIC_DEBUG_LINE_DWORDS;
+
+		/* Dump static section params */
+		block = get_dbg_block(p_hwfn, (enum block_id)block_id);
+		offset += qed_grc_dump_mem_hdr(p_hwfn,
+					       dump_buf + offset,
+					       dump,
+					       (const char *)block->name,
+					       0,
+					       block_dwords,
+					       32, false, "STATIC", 0);
+
+		if (!dump) {
+			offset += block_dwords;
+			continue;
+		}
+
+		/* If all lines are invalid - dump zeros */
+		if (dev_data->block_in_reset[block_id]) {
+			memset(dump_buf + offset, 0,
+			       DWORDS_TO_BYTES(block_dwords));
+			offset += block_dwords;
+			continue;
+		}
+
+		/* Enable block's client */
+		qed_bus_enable_clients(p_hwfn,
+				       p_ptt,
+				       OSAL_BIT(block_per_chip->dbg_client_id));
+
+		addr = BYTES_TO_DWORDS(DBG_REG_CALENDAR_OUT_DATA);
+		len = STATIC_DEBUG_LINE_DWORDS;
+		for (line_id = 0; line_id < (u32)NUM_DBG_LINES(block_per_chip);
+		     line_id++) {
+			/* Configure debug line ID */
+			qed_bus_config_dbg_line(p_hwfn,
+						p_ptt,
+						(enum block_id)block_id,
+						(u8)line_id, 0xf, 0, 0, 0);
+
+			/* Read debug line info */
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  addr,
+							  len,
+							  true, SPLIT_TYPE_NONE,
+							  0);
+		}
+
+		/* Disable block's client and debug output */
+		qed_bus_enable_clients(p_hwfn, p_ptt, 0);
+		qed_bus_config_dbg_line(p_hwfn, p_ptt,
+					(enum block_id)block_id, 0, 0, 0, 0, 0);
+	}
+
+	if (dump) {
+		qed_bus_enable_dbg_block(p_hwfn, p_ptt, false);
+		qed_bus_enable_clients(p_hwfn, p_ptt, 0);
+	}
+
+	return offset;
+}
+
+/* Performs GRC Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static enum dbg_status qed_grc_dump(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    u32 *dump_buf,
+				    bool dump, u32 *num_dumped_dwords)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 dwords_read, offset = 0;
+	bool parities_masked = false;
+	u8 i;
+
+	*num_dumped_dwords = 0;
+	dev_data->num_regs_read = 0;
+
+	/* Update reset state */
+	if (dump)
+		qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 4);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "grc-dump");
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "num-lcids",
+				     NUM_OF_LCIDS);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "num-ltids",
+				     NUM_OF_LTIDS);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "num-ports", dev_data->num_ports);
+
+	/* Dump reset registers (dumped before taking blocks out of reset ) */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS))
+		offset += qed_grc_dump_reset_regs(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset, dump);
+
+	/* Take all blocks out of reset (using reset registers) */
+	if (dump) {
+		qed_grc_unreset_blocks(p_hwfn, p_ptt, false);
+		qed_update_blocks_reset_state(p_hwfn, p_ptt);
+	}
+
+	/* Disable all parities using MFW command */
+	if (dump &&
+	    !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP)) {
+		parities_masked = !ecore_mcp_mask_parities(p_hwfn, p_ptt, 1);
+		if (!parities_masked) {
+			DP_NOTICE(p_hwfn, false,
+				  "Failed to mask parities using MFW\n");
+			if (qed_grc_get_param
+			    (p_hwfn, DBG_GRC_PARAM_PARITY_SAFE))
+				return DBG_STATUS_MCP_COULD_NOT_MASK_PRTY;
+		}
+	}
+
+	/* Dump modified registers (dumped before modifying them) */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS))
+		offset += qed_grc_dump_modified_regs(p_hwfn,
+						     p_ptt,
+						     dump_buf + offset, dump);
+
+	/* Stall storms */
+	if (dump &&
+	    (qed_grc_is_included(p_hwfn,
+				 DBG_GRC_PARAM_DUMP_IOR) ||
+	     qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_VFC)))
+		qed_grc_stall_storms(p_hwfn, p_ptt, true);
+
+	/* Dump all regs  */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS)) {
+		bool block_enable[MAX_BLOCK_ID];
+
+		/* Dump all blocks except MCP */
+		for (i = 0; i < MAX_BLOCK_ID; i++)
+			block_enable[i] = true;
+		block_enable[BLOCK_MCP] = false;
+		offset += qed_grc_dump_registers(p_hwfn,
+						 p_ptt,
+						 dump_buf +
+						 offset,
+						 dump,
+						 block_enable, NULL);
+
+		/* Dump special registers */
+		offset += qed_grc_dump_special_regs(p_hwfn,
+						    p_ptt,
+						    dump_buf + offset, dump);
+	}
+
+	/* Dump memories */
+	offset += qed_grc_dump_memories(p_hwfn, p_ptt, dump_buf + offset, dump);
+
+	/* Dump MCP */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MCP))
+		offset += qed_grc_dump_mcp(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump context */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM_CTX))
+		offset += qed_grc_dump_ctx(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump RSS memories */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_RSS))
+		offset += qed_grc_dump_rss(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump Big RAM */
+	for (i = 0; i < NUM_BIG_RAM_TYPES; i++)
+		if (qed_grc_is_included(p_hwfn, s_big_ram_defs[i].grc_param))
+			offset += qed_grc_dump_big_ram(p_hwfn,
+						       p_ptt,
+						       dump_buf + offset,
+						       dump, i);
+
+	/* Dump VFC */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_VFC)) {
+		dwords_read = qed_grc_dump_vfc(p_hwfn,
+					       p_ptt, dump_buf + offset, dump);
+		offset += dwords_read;
+		if (!dwords_read)
+			return DBG_STATUS_VFC_READ_ERROR;
+	}
+
+	/* Dump PHY tbus */
+	if (qed_grc_is_included(p_hwfn,
+				DBG_GRC_PARAM_DUMP_PHY) && dev_data->chip_id ==
+	    CHIP_K2 && dev_data->hw_type == HW_TYPE_ASIC)
+		offset += qed_grc_dump_phy(p_hwfn,
+					   p_ptt, dump_buf + offset, dump);
+
+	/* Dump MCP HW Dump */
+	if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MCP_HW_DUMP) &&
+	    !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP) && 1)
+		offset += qed_grc_dump_mcp_hw_dump(p_hwfn,
+						   p_ptt,
+						   dump_buf + offset, dump);
+
+	/* Dump static debug data (only if not during debug bus recording) */
+	if (qed_grc_is_included(p_hwfn,
+				DBG_GRC_PARAM_DUMP_STATIC) &&
+	    (!dump || dev_data->bus.state == DBG_BUS_STATE_IDLE))
+		offset += qed_grc_dump_static_debug(p_hwfn,
+						    p_ptt,
+						    dump_buf + offset, dump);
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	if (dump) {
+		/* Unstall storms */
+		if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_UNSTALL))
+			qed_grc_stall_storms(p_hwfn, p_ptt, false);
+
+		/* Clear parity status */
+		qed_grc_clear_all_prty(p_hwfn, p_ptt);
+
+		/* Enable all parities using MFW command */
+		if (parities_masked)
+			ecore_mcp_mask_parities(p_hwfn, p_ptt, 0);
+	}
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Writes the specified failing Idle Check rule to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_idle_chk_dump_failure(struct ecore_hwfn *p_hwfn,
+				     struct ecore_ptt *p_ptt,
+				     u32 *
+				     dump_buf,
+				     bool dump,
+				     u16 rule_id,
+				     const struct dbg_idle_chk_rule *rule,
+				     u16 fail_entry_id, u32 *cond_reg_values)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	const struct dbg_idle_chk_cond_reg *cond_regs;
+	const struct dbg_idle_chk_info_reg *info_regs;
+	u32 i, next_reg_offset = 0, offset = 0;
+	struct dbg_idle_chk_result_hdr *hdr;
+	const union dbg_idle_chk_reg *regs;
+	u8 reg_id;
+
+	hdr = (struct dbg_idle_chk_result_hdr *)dump_buf;
+	regs = (const union dbg_idle_chk_reg *)
+		p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr +
+		rule->reg_offset;
+	cond_regs = &regs[0].cond_reg;
+	info_regs = &regs[rule->num_cond_regs].info_reg;
+
+	/* Dump rule data */
+	if (dump) {
+		memset(hdr, 0, sizeof(*hdr));
+		hdr->rule_id = rule_id;
+		hdr->mem_entry_id = fail_entry_id;
+		hdr->severity = rule->severity;
+		hdr->num_dumped_cond_regs = rule->num_cond_regs;
+	}
+
+	offset += IDLE_CHK_RESULT_HDR_DWORDS;
+
+	/* Dump condition register values */
+	for (reg_id = 0; reg_id < rule->num_cond_regs; reg_id++) {
+		const struct dbg_idle_chk_cond_reg *reg = &cond_regs[reg_id];
+		struct dbg_idle_chk_result_reg_hdr *reg_hdr;
+
+		reg_hdr =
+		    (struct dbg_idle_chk_result_reg_hdr *)(dump_buf + offset);
+
+		/* Write register header */
+		if (!dump) {
+			offset += IDLE_CHK_RESULT_REG_HDR_DWORDS +
+			    reg->entry_size;
+			continue;
+		}
+
+		offset += IDLE_CHK_RESULT_REG_HDR_DWORDS;
+		memset(reg_hdr, 0, sizeof(*reg_hdr));
+		reg_hdr->start_entry = reg->start_entry;
+		reg_hdr->size = reg->entry_size;
+		SET_FIELD(reg_hdr->data,
+			  DBG_IDLE_CHK_RESULT_REG_HDR_IS_MEM,
+			  reg->num_entries > 1 || reg->start_entry > 0 ? 1 : 0);
+		SET_FIELD(reg_hdr->data,
+			  DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID, reg_id);
+
+		/* Write register values */
+		for (i = 0; i < reg_hdr->size; i++, next_reg_offset++, offset++)
+			dump_buf[offset] = cond_reg_values[next_reg_offset];
+	}
+
+	/* Dump info register values */
+	for (reg_id = 0; reg_id < rule->num_info_regs; reg_id++) {
+		const struct dbg_idle_chk_info_reg *reg = &info_regs[reg_id];
+		u32 block_id;
+
+		/* Check if register's block is in reset */
+		if (!dump) {
+			offset += IDLE_CHK_RESULT_REG_HDR_DWORDS + reg->size;
+			continue;
+		}
+
+		block_id = GET_FIELD(reg->data, DBG_IDLE_CHK_INFO_REG_BLOCK_ID);
+		if (block_id >= MAX_BLOCK_ID) {
+			DP_NOTICE(p_hwfn, false, "Invalid block_id\n");
+			return 0;
+		}
+
+		if (!dev_data->block_in_reset[block_id]) {
+			struct dbg_idle_chk_result_reg_hdr *reg_hdr;
+			bool wide_bus, eval_mode, mode_match = true;
+			u16 modes_buf_offset;
+			u32 addr;
+
+			reg_hdr = (struct dbg_idle_chk_result_reg_hdr *)
+				  (dump_buf + offset);
+
+			/* Check mode */
+			eval_mode = GET_FIELD(reg->mode.data,
+					      DBG_MODE_HDR_EVAL_MODE) > 0;
+			if (eval_mode) {
+				modes_buf_offset =
+				    GET_FIELD(reg->mode.data,
+					      DBG_MODE_HDR_MODES_BUF_OFFSET);
+				mode_match =
+					qed_is_mode_match(p_hwfn,
+							  &modes_buf_offset);
+			}
+
+			if (!mode_match)
+				continue;
+
+			addr = GET_FIELD(reg->data,
+					 DBG_IDLE_CHK_INFO_REG_ADDRESS);
+			wide_bus = GET_FIELD(reg->data,
+					     DBG_IDLE_CHK_INFO_REG_WIDE_BUS);
+
+			/* Write register header */
+			offset += IDLE_CHK_RESULT_REG_HDR_DWORDS;
+			hdr->num_dumped_info_regs++;
+			memset(reg_hdr, 0, sizeof(*reg_hdr));
+			reg_hdr->size = reg->size;
+			SET_FIELD(reg_hdr->data,
+				  DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID,
+				  rule->num_cond_regs + reg_id);
+
+			/* Write register values */
+			offset += qed_grc_dump_addr_range(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  dump,
+							  addr,
+							  reg->size, wide_bus,
+							  SPLIT_TYPE_NONE, 0);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps idle check rule entries. Returns the dumped size in dwords. */
+static u32
+qed_idle_chk_dump_rule_entries(struct ecore_hwfn *p_hwfn,
+			       struct ecore_ptt *p_ptt,
+			       u32 *dump_buf, bool dump,
+			       const struct dbg_idle_chk_rule *input_rules,
+			       u32 num_input_rules, u32 *num_failing_rules)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 cond_reg_values[IDLE_CHK_MAX_ENTRIES_SIZE];
+	u32 i, offset = 0;
+	u16 entry_id;
+	u8 reg_id;
+
+	*num_failing_rules = 0;
+
+	for (i = 0; i < num_input_rules; i++) {
+		const struct dbg_idle_chk_cond_reg *cond_regs;
+		const struct dbg_idle_chk_rule *rule;
+		const union dbg_idle_chk_reg *regs;
+		u16 num_reg_entries = 1;
+		bool check_rule = true;
+		const u32 *imm_values;
+
+		rule = &input_rules[i];
+		regs = (const union dbg_idle_chk_reg *)
+			p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr +
+			rule->reg_offset;
+		cond_regs = &regs[0].cond_reg;
+		imm_values =
+		    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_IMMS].ptr +
+		    rule->imm_offset;
+
+		/* Check if all condition register blocks are out of reset, and
+		 * find maximal number of entries (all condition registers that
+		 * are memories must have the same size, which is > 1).
+		 */
+		for (reg_id = 0; reg_id < rule->num_cond_regs && check_rule;
+		     reg_id++) {
+			u32 block_id =
+				GET_FIELD(cond_regs[reg_id].data,
+					  DBG_IDLE_CHK_COND_REG_BLOCK_ID);
+
+			if (block_id >= MAX_BLOCK_ID) {
+				DP_NOTICE(p_hwfn, false, "Invalid block_id\n");
+				return 0;
+			}
+
+			check_rule = !dev_data->block_in_reset[block_id];
+			if (cond_regs[reg_id].num_entries > num_reg_entries)
+				num_reg_entries = cond_regs[reg_id].num_entries;
+		}
+
+		if (!check_rule && dump)
+			continue;
+
+		if (!dump) {
+			u32 entry_dump_size =
+				qed_idle_chk_dump_failure(p_hwfn,
+							  p_ptt,
+							  dump_buf + offset,
+							  false,
+							  rule->rule_id,
+							  rule,
+							  0,
+							  NULL);
+
+			offset += num_reg_entries * entry_dump_size;
+			(*num_failing_rules) += num_reg_entries;
+			continue;
+		}
+
+		/* Go over all register entries (number of entries is the same
+		 * for all condition registers).
+		 */
+		for (entry_id = 0; entry_id < num_reg_entries; entry_id++) {
+			u32 next_reg_offset = 0;
+
+			/* Read current entry of all condition registers */
+			for (reg_id = 0; reg_id < rule->num_cond_regs;
+			     reg_id++) {
+				const struct dbg_idle_chk_cond_reg *reg =
+					&cond_regs[reg_id];
+				u32 padded_entry_size, addr;
+				bool wide_bus;
+
+				/* Find GRC address (if it's a memory, the
+				 * address of the specific entry is calculated).
+				 */
+				addr = GET_FIELD(reg->data,
+						 DBG_IDLE_CHK_COND_REG_ADDRESS);
+				wide_bus =
+				    GET_FIELD(reg->data,
+					      DBG_IDLE_CHK_COND_REG_WIDE_BUS);
+				if (reg->num_entries > 1 ||
+				    reg->start_entry > 0) {
+					padded_entry_size =
+					   reg->entry_size > 1 ?
+					   OSAL_ROUNDUP_POW_OF_TWO(reg->entry_size) :
+					   1;
+					addr += (reg->start_entry + entry_id) *
+						padded_entry_size;
+				}
+
+				/* Read registers */
+				if (next_reg_offset + reg->entry_size >=
+				    IDLE_CHK_MAX_ENTRIES_SIZE) {
+					DP_NOTICE(p_hwfn, false,
+						  "idle check registers entry is too large\n");
+					return 0;
+				}
+
+				next_reg_offset +=
+				    qed_grc_dump_addr_range(p_hwfn, p_ptt,
+							    cond_reg_values +
+							    next_reg_offset,
+							    dump, addr,
+							    reg->entry_size,
+							    wide_bus,
+							    SPLIT_TYPE_NONE, 0);
+			}
+
+			/* Call rule condition function.
+			 * If returns true, it's a failure.
+			 */
+			if ((*cond_arr[rule->cond_id]) (cond_reg_values,
+							imm_values)) {
+				offset += qed_idle_chk_dump_failure(p_hwfn,
+							p_ptt,
+							dump_buf + offset,
+							dump,
+							rule->rule_id,
+							rule,
+							entry_id,
+							cond_reg_values);
+				(*num_failing_rules)++;
+			}
+		}
+	}
+
+	return offset;
+}
+
+/* Performs Idle Check Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+			     struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	struct virt_mem_desc *dbg_buf =
+	    &p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_RULES];
+	u32 num_failing_rules_offset, offset = 0,
+	    input_offset = 0, num_failing_rules = 0;
+
+	/* Dump global params  - 1 must match below amount of params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "idle-chk");
+
+	/* Dump idle check section header with a single parameter */
+	offset += qed_dump_section_hdr(dump_buf + offset, dump, "idle_chk", 1);
+	num_failing_rules_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "num_rules", 0);
+
+	while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
+		const struct dbg_idle_chk_cond_hdr *cond_hdr =
+		    (const struct dbg_idle_chk_cond_hdr *)dbg_buf->ptr +
+		    input_offset++;
+		bool eval_mode, mode_match = true;
+		u32 curr_failing_rules;
+		u16 modes_buf_offset;
+
+		/* Check mode */
+		eval_mode = GET_FIELD(cond_hdr->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		if (eval_mode) {
+			modes_buf_offset =
+				GET_FIELD(cond_hdr->mode.data,
+					  DBG_MODE_HDR_MODES_BUF_OFFSET);
+			mode_match = qed_is_mode_match(p_hwfn,
+						       &modes_buf_offset);
+		}
+
+		if (mode_match) {
+			const struct dbg_idle_chk_rule *rule =
+			    (const struct dbg_idle_chk_rule *)((u32 *)
+							       dbg_buf->ptr
+							       + input_offset);
+			u32 num_input_rules =
+				cond_hdr->data_size / IDLE_CHK_RULE_SIZE_DWORDS;
+			offset +=
+			    qed_idle_chk_dump_rule_entries(p_hwfn,
+							   p_ptt,
+							   dump_buf +
+							   offset,
+							   dump,
+							   rule,
+							   num_input_rules,
+							   &curr_failing_rules);
+			num_failing_rules += curr_failing_rules;
+		}
+
+		input_offset += cond_hdr->data_size;
+	}
+
+	/* Overwrite num_rules parameter */
+	if (dump)
+		qed_dump_num_param(dump_buf + num_failing_rules_offset,
+				   dump, "num_rules", num_failing_rules);
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	return offset;
+}
+
+/* Finds the meta data image in NVRAM */
+static enum dbg_status qed_find_nvram_image(struct ecore_hwfn *p_hwfn,
+					    struct ecore_ptt *p_ptt,
+					    u32 image_type,
+					    u32 *nvram_offset_bytes,
+					    u32 *nvram_size_bytes)
+{
+	u32 ret_mcp_resp, ret_mcp_param, ret_txn_size;
+	struct mcp_file_att file_att;
+	int nvm_result;
+
+	/* Call NVRAM get file command */
+	nvm_result = ecore_mcp_nvm_rd_cmd(p_hwfn,
+					p_ptt,
+					DRV_MSG_CODE_NVM_GET_FILE_ATT,
+					image_type,
+					&ret_mcp_resp,
+					&ret_mcp_param,
+					&ret_txn_size, (u32 *)&file_att);
+
+	/* Check response */
+	if (nvm_result ||
+	    (ret_mcp_resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_NVM_OK)
+		return DBG_STATUS_NVRAM_GET_IMAGE_FAILED;
+
+	/* Update return values */
+	*nvram_offset_bytes = file_att.nvm_start_addr;
+	*nvram_size_bytes = file_att.len;
+
+	DP_VERBOSE(p_hwfn->p_dev,
+		   ECORE_MSG_DEBUG,
+		   "find_nvram_image: found NVRAM image of type %d in NVRAM offset %d bytes with size %d bytes\n",
+		   image_type, *nvram_offset_bytes, *nvram_size_bytes);
+
+	/* Check alignment */
+	if (*nvram_size_bytes & 0x3)
+		return DBG_STATUS_NON_ALIGNED_NVRAM_IMAGE;
+
+	return DBG_STATUS_OK;
+}
+
+/* Reads data from NVRAM */
+static enum dbg_status qed_nvram_read(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 nvram_offset_bytes,
+				      u32 nvram_size_bytes, u32 *ret_buf)
+{
+	u32 ret_mcp_resp, ret_mcp_param, ret_read_size, bytes_to_copy;
+	s32 bytes_left = nvram_size_bytes;
+	u32 read_offset = 0, param = 0;
+
+	DP_NOTICE(p_hwfn->p_dev, false,
+		   "nvram_read: reading image of size %d bytes from NVRAM\n",
+		   nvram_size_bytes);
+
+	do {
+		bytes_to_copy =
+		    (bytes_left >
+		     MCP_DRV_NVM_BUF_LEN) ? MCP_DRV_NVM_BUF_LEN : bytes_left;
+
+		/* Call NVRAM read command */
+		SET_MFW_FIELD(param,
+			      DRV_MB_PARAM_NVM_OFFSET,
+			      nvram_offset_bytes + read_offset);
+		SET_MFW_FIELD(param, DRV_MB_PARAM_NVM_LEN, bytes_to_copy);
+		if (ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt,
+					 DRV_MSG_CODE_NVM_READ_NVRAM, param,
+					 &ret_mcp_resp,
+					 &ret_mcp_param, &ret_read_size,
+					 (u32 *)((u8 *)ret_buf +
+						 read_offset))) {
+			DP_NOTICE(p_hwfn->p_dev, false, "rc = DBG_STATUS_NVRAM_READ_FAILED\n");
+			return DBG_STATUS_NVRAM_READ_FAILED;
+		}
+
+		/* Check response */
+		if ((ret_mcp_resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_NVM_OK) {
+			DP_NOTICE(p_hwfn->p_dev, false, "rc = DBG_STATUS_NVRAM_READ_FAILED\n");
+			return DBG_STATUS_NVRAM_READ_FAILED;
+		}
+
+		/* Update read offset */
+		read_offset += ret_read_size;
+		bytes_left -= ret_read_size;
+	} while (bytes_left > 0);
+
+	return DBG_STATUS_OK;
+}
+
+/* Get info on the MCP Trace data in the scratchpad:
+ * - trace_data_grc_addr (OUT): trace data GRC address in bytes
+ * - trace_data_size (OUT): trace data size in bytes (without the header)
+ */
+static enum dbg_status qed_mcp_trace_get_data_info(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *trace_data_grc_addr,
+						   u32 *trace_data_size)
+{
+	u32 spad_trace_offsize, signature;
+
+	/* Read trace section offsize structure from MCP scratchpad */
+	spad_trace_offsize = ecore_rd(p_hwfn, p_ptt,
+				      MCP_SPAD_TRACE_OFFSIZE_ADDR);
+
+	/* Extract trace section address from offsize (in scratchpad) */
+	*trace_data_grc_addr =
+		MCP_REG_SCRATCH + SECTION_OFFSET(spad_trace_offsize);
+
+	/* Read signature from MCP trace section */
+	signature = ecore_rd(p_hwfn, p_ptt,
+			   *trace_data_grc_addr +
+			   offsetof(struct mcp_trace, signature));
+
+	if (signature != MFW_TRACE_SIGNATURE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Read trace size from MCP trace section */
+	*trace_data_size = ecore_rd(p_hwfn,
+				  p_ptt,
+				  *trace_data_grc_addr +
+				  offsetof(struct mcp_trace, size));
+
+	return DBG_STATUS_OK;
+}
+
+/* Reads MCP trace meta data image from NVRAM
+ * - running_bundle_id (OUT): running bundle ID (invalid when loaded from file)
+ * - trace_meta_offset (OUT): trace meta offset in NVRAM in bytes (invalid when
+ *			      loaded from file).
+ * - trace_meta_size (OUT):   size in bytes of the trace meta data.
+ */
+static enum dbg_status qed_mcp_trace_get_meta_info(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 trace_data_size_bytes,
+						   u32 *running_bundle_id,
+						   u32 *trace_meta_offset,
+						   u32 *trace_meta_size)
+{
+	u32 spad_trace_offsize, nvram_image_type, running_mfw_addr;
+
+	/* Read MCP trace section offsize structure from MCP scratchpad */
+	spad_trace_offsize = ecore_rd(p_hwfn, p_ptt,
+				      MCP_SPAD_TRACE_OFFSIZE_ADDR);
+
+	/* Find running bundle ID */
+	running_mfw_addr =
+		MCP_REG_SCRATCH + SECTION_OFFSET(spad_trace_offsize) +
+		SECTION_SIZE(spad_trace_offsize) + trace_data_size_bytes;
+	*running_bundle_id = ecore_rd(p_hwfn, p_ptt, running_mfw_addr);
+	if (*running_bundle_id > 1)
+		return DBG_STATUS_INVALID_NVRAM_BUNDLE;
+
+	/* Find image in NVRAM */
+	nvram_image_type =
+	    (*running_bundle_id ==
+	     DIR_ID_1) ? NVM_TYPE_MFW_TRACE1 : NVM_TYPE_MFW_TRACE2;
+	return qed_find_nvram_image(p_hwfn,
+				    p_ptt,
+				    nvram_image_type,
+				    trace_meta_offset, trace_meta_size);
+}
+
+/* Reads the MCP Trace meta data from NVRAM into the specified buffer */
+static enum dbg_status qed_mcp_trace_read_meta(struct ecore_hwfn *p_hwfn,
+					       struct ecore_ptt *p_ptt,
+					       u32 nvram_offset_in_bytes,
+					       u32 size_in_bytes, u32 *buf)
+{
+	u8 modules_num, module_len, i, *byte_buf = (u8 *)buf;
+	enum dbg_status status;
+	u32 signature;
+
+	/* Read meta data from NVRAM */
+	status = qed_nvram_read(p_hwfn,
+				p_ptt,
+				nvram_offset_in_bytes, size_in_bytes, buf);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Extract and check first signature */
+	signature = qed_read_unaligned_dword(byte_buf);
+	byte_buf += sizeof(signature);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Extract number of modules */
+	modules_num = *(byte_buf++);
+
+	/* Skip all modules */
+	for (i = 0; i < modules_num; i++) {
+		module_len = *(byte_buf++);
+		byte_buf += module_len;
+	}
+
+	/* Extract and check second signature */
+	signature = qed_read_unaligned_dword(byte_buf);
+	byte_buf += sizeof(signature);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	return DBG_STATUS_OK;
+}
+
+/* Dump MCP Trace */
+static enum dbg_status qed_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+					  struct ecore_ptt *p_ptt,
+					  u32 *dump_buf,
+					  bool dump, u32 *num_dumped_dwords)
+{
+	u32 trace_data_grc_addr, trace_data_size_bytes, trace_data_size_dwords;
+	u32 trace_meta_size_dwords = 0, running_bundle_id, offset = 0;
+	u32 trace_meta_offset_bytes = 0, trace_meta_size_bytes = 0;
+	enum dbg_status status;
+	int halted = 0;
+	bool use_mfw;
+
+	*num_dumped_dwords = 0;
+
+	use_mfw = !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP);
+
+	/* Get trace data info */
+	status = qed_mcp_trace_get_data_info(p_hwfn,
+					     p_ptt,
+					     &trace_data_grc_addr,
+					     &trace_data_size_bytes);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "mcp-trace");
+
+	/* Halt MCP while reading from scratchpad so the read data will be
+	 * consistent. if halt fails, MCP trace is taken anyway, with a small
+	 * risk that it may be corrupt.
+	 */
+	if (dump && use_mfw) {
+		halted = !ecore_mcp_halt(p_hwfn, p_ptt);
+		if (!halted)
+			DP_NOTICE(p_hwfn, false, "MCP halt failed!\n");
+	}
+
+	/* Find trace data size */
+	trace_data_size_dwords =
+	    DIV_ROUND_UP(trace_data_size_bytes + sizeof(struct mcp_trace),
+			 BYTES_IN_DWORD);
+
+	/* Dump trace data section header and param */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "mcp_trace_data", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", trace_data_size_dwords);
+
+	/* Read trace data from scratchpad into dump buffer */
+	offset += qed_grc_dump_addr_range(p_hwfn,
+					  p_ptt,
+					  dump_buf + offset,
+					  dump,
+					  BYTES_TO_DWORDS(trace_data_grc_addr),
+					  trace_data_size_dwords, false,
+					  SPLIT_TYPE_NONE, 0);
+
+	/* Resume MCP (only if halt succeeded) */
+	if (halted && ecore_mcp_resume(p_hwfn, p_ptt))
+		DP_NOTICE(p_hwfn, false, "Failed to resume MCP after halt!\n");
+
+	/* Dump trace meta section header */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "mcp_trace_meta", 1);
+
+	/* If MCP Trace meta size parameter was set, use it.
+	 * Otherwise, read trace meta.
+	 * trace_meta_size_bytes is dword-aligned.
+	 */
+	trace_meta_size_bytes =
+		qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_MCP_TRACE_META_SIZE);
+	if ((!trace_meta_size_bytes || dump) && use_mfw)
+		status = qed_mcp_trace_get_meta_info(p_hwfn,
+						     p_ptt,
+						     trace_data_size_bytes,
+						     &running_bundle_id,
+						     &trace_meta_offset_bytes,
+						     &trace_meta_size_bytes);
+	if (status == DBG_STATUS_OK)
+		trace_meta_size_dwords = BYTES_TO_DWORDS(trace_meta_size_bytes);
+
+	/* Dump trace meta size param */
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", trace_meta_size_dwords);
+
+	/* Read trace meta image into dump buffer */
+	if (dump && trace_meta_size_dwords)
+		status = qed_mcp_trace_read_meta(p_hwfn,
+						 p_ptt,
+						 trace_meta_offset_bytes,
+						 trace_meta_size_bytes,
+						 dump_buf + offset);
+	if (status == DBG_STATUS_OK)
+		offset += trace_meta_size_dwords;
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	/* If no mcp access, indicate that the dump doesn't contain the meta
+	 * data from NVRAM.
+	 */
+	return use_mfw ? status : DBG_STATUS_NVRAM_GET_IMAGE_FAILED;
+}
+
+/* Dump GRC FIFO */
+static enum dbg_status qed_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
+					 struct ecore_ptt *p_ptt,
+					 u32 *dump_buf,
+					 bool dump, u32 *num_dumped_dwords)
+{
+	u32 dwords_read, size_param_offset, offset = 0, addr, len;
+	bool fifo_has_data;
+
+	*num_dumped_dwords = 0;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "reg-fifo");
+
+	/* Dump fifo data section header and param. The size param is 0 for
+	 * now, and is overwritten after reading the FIFO.
+	 */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "reg_fifo_data", 1);
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+
+	if (!dump) {
+		/* FIFO max size is REG_FIFO_DEPTH_DWORDS. There is no way to
+		 * test how much data is available, except for reading it.
+		 */
+		offset += REG_FIFO_DEPTH_DWORDS;
+		goto out;
+	}
+
+	fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+			       GRC_REG_TRACE_FIFO_VALID_DATA) > 0;
+
+	/* Pull available data from fifo. Use DMAE since this is widebus memory
+	 * and must be accessed atomically. Test for dwords_read not passing
+	 * buffer size since more entries could be added to the buffer as we are
+	 * emptying it.
+	 */
+	addr = BYTES_TO_DWORDS(GRC_REG_TRACE_FIFO);
+	len = REG_FIFO_ELEMENT_DWORDS;
+	for (dwords_read = 0;
+	     fifo_has_data && dwords_read < REG_FIFO_DEPTH_DWORDS;
+	     dwords_read += REG_FIFO_ELEMENT_DWORDS) {
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  true,
+						  addr,
+						  len,
+						  true, SPLIT_TYPE_NONE,
+						  0);
+		fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+				       GRC_REG_TRACE_FIFO_VALID_DATA) > 0;
+	}
+
+	qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
+			   dwords_read);
+out:
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Dump IGU FIFO */
+static enum dbg_status qed_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
+					 struct ecore_ptt *p_ptt,
+					 u32 *dump_buf,
+					 bool dump, u32 *num_dumped_dwords)
+{
+	u32 dwords_read, size_param_offset, offset = 0, addr, len;
+	bool fifo_has_data;
+
+	*num_dumped_dwords = 0;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "igu-fifo");
+
+	/* Dump fifo data section header and param. The size param is 0 for
+	 * now, and is overwritten after reading the FIFO.
+	 */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "igu_fifo_data", 1);
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+
+	if (!dump) {
+		/* FIFO max size is IGU_FIFO_DEPTH_DWORDS. There is no way to
+		 * test how much data is available, except for reading it.
+		 */
+		offset += IGU_FIFO_DEPTH_DWORDS;
+		goto out;
+	}
+
+	fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+			       IGU_REG_ERROR_HANDLING_DATA_VALID) > 0;
+
+	/* Pull available data from fifo. Use DMAE since this is widebus memory
+	 * and must be accessed atomically. Test for dwords_read not passing
+	 * buffer size since more entries could be added to the buffer as we are
+	 * emptying it.
+	 */
+	addr = BYTES_TO_DWORDS(IGU_REG_ERROR_HANDLING_MEMORY);
+	len = IGU_FIFO_ELEMENT_DWORDS;
+	for (dwords_read = 0;
+	     fifo_has_data && dwords_read < IGU_FIFO_DEPTH_DWORDS;
+	     dwords_read += IGU_FIFO_ELEMENT_DWORDS) {
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  true,
+						  addr,
+						  len,
+						  true, SPLIT_TYPE_NONE,
+						  0);
+		fifo_has_data = ecore_rd(p_hwfn, p_ptt,
+				       IGU_REG_ERROR_HANDLING_DATA_VALID) > 0;
+	}
+
+	qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
+			   dwords_read);
+out:
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Protection Override dump */
+static enum dbg_status qed_protection_override_dump(struct ecore_hwfn *p_hwfn,
+						    struct ecore_ptt *p_ptt,
+						    u32 *dump_buf,
+						    bool dump,
+						    u32 *num_dumped_dwords)
+{
+	u32 size_param_offset, override_window_dwords, offset = 0, addr;
+
+	*num_dumped_dwords = 0;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "protection-override");
+
+	/* Dump data section header and param. The size param is 0 for now,
+	 * and is overwritten after reading the data.
+	 */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "protection_override_data", 1);
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+
+	if (!dump) {
+		offset += PROTECTION_OVERRIDE_DEPTH_DWORDS;
+		goto out;
+	}
+
+	/* Add override window info to buffer */
+	override_window_dwords =
+		ecore_rd(p_hwfn, p_ptt, GRC_REG_NUMBER_VALID_OVERRIDE_WINDOW) *
+		PROTECTION_OVERRIDE_ELEMENT_DWORDS;
+	if (override_window_dwords) {
+		addr = BYTES_TO_DWORDS(GRC_REG_PROTECTION_OVERRIDE_WINDOW);
+		offset += qed_grc_dump_addr_range(p_hwfn,
+						  p_ptt,
+						  dump_buf + offset,
+						  true,
+						  addr,
+						  override_window_dwords,
+						  true, SPLIT_TYPE_NONE, 0);
+		qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
+				   override_window_dwords);
+	}
+out:
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	*num_dumped_dwords = offset;
+
+	return DBG_STATUS_OK;
+}
+
+/* Performs FW Asserts Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
+			       struct ecore_ptt *p_ptt, u32 *dump_buf,
+			       bool dump)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	struct fw_asserts_ram_section *asserts;
+	char storm_letter_str[2] = "?";
+	struct fw_info fw_info;
+	u32 offset = 0;
+	u8 storm_id;
+
+	/* Dump global params */
+	offset += qed_dump_common_global_params(p_hwfn,
+						p_ptt,
+						dump_buf + offset, dump, 1);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "fw-asserts");
+
+	/* Find Storm dump size */
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		u32 fw_asserts_section_addr, next_list_idx_addr, next_list_idx;
+		struct storm_defs *storm = &s_storm_defs[storm_id];
+		u32 last_list_idx, addr;
+
+		if (dev_data->block_in_reset[storm->sem_block_id])
+			continue;
+
+		/* Read FW info for the current Storm */
+		qed_read_storm_fw_info(p_hwfn, p_ptt, storm_id, &fw_info);
+
+		asserts = &fw_info.fw_asserts_section;
+
+		/* Dump FW Asserts section header and params */
+		storm_letter_str[0] = storm->letter;
+		offset += qed_dump_section_hdr(dump_buf + offset,
+					       dump, "fw_asserts", 2);
+		offset += qed_dump_str_param(dump_buf + offset,
+					     dump, "storm", storm_letter_str);
+		offset += qed_dump_num_param(dump_buf + offset,
+					     dump,
+					     "size",
+					     asserts->list_element_dword_size);
+
+		/* Read and dump FW Asserts data */
+		if (!dump) {
+			offset += asserts->list_element_dword_size;
+			continue;
+		}
+
+		fw_asserts_section_addr = storm->sem_fast_mem_addr +
+			SEM_FAST_REG_INT_RAM +
+			RAM_LINES_TO_BYTES(asserts->section_ram_line_offset);
+		next_list_idx_addr = fw_asserts_section_addr +
+			DWORDS_TO_BYTES(asserts->list_next_index_dword_offset);
+		next_list_idx = ecore_rd(p_hwfn, p_ptt, next_list_idx_addr);
+		last_list_idx = (next_list_idx > 0 ?
+				 next_list_idx :
+				 asserts->list_num_elements) - 1;
+		addr = BYTES_TO_DWORDS(fw_asserts_section_addr) +
+		       asserts->list_dword_offset +
+		       last_list_idx * asserts->list_element_dword_size;
+		offset +=
+		    qed_grc_dump_addr_range(p_hwfn, p_ptt,
+					    dump_buf + offset,
+					    dump, addr,
+					    asserts->list_element_dword_size,
+						  false, SPLIT_TYPE_NONE, 0);
+	}
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	return offset;
+}
+
+/* Dumps the specified ILT pages to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_ilt_dump_pages_range(u32 *dump_buf,
+				    bool dump,
+				    u32 start_page_id,
+				    u32 num_pages,
+				    struct phys_mem_desc *ilt_pages,
+				    bool dump_page_ids)
+{
+	u32 page_id, end_page_id, offset = 0;
+
+	if (num_pages == 0)
+		return offset;
+
+	end_page_id = start_page_id + num_pages - 1;
+
+	for (page_id = start_page_id; page_id <= end_page_id; page_id++) {
+		struct phys_mem_desc *mem_desc = &ilt_pages[page_id];
+
+		/**
+		 *
+		 * if (page_id >= ->p_cxt_mngr->ilt_shadow_size)
+		 *     break;
+		 */
+
+		if (!ilt_pages[page_id].virt_addr)
+			continue;
+
+		if (dump_page_ids) {
+			/* Copy page ID to dump buffer */
+			if (dump)
+				*(dump_buf + offset) = page_id;
+			offset++;
+		} else {
+			/* Copy page memory to dump buffer */
+			if (dump)
+				memcpy(dump_buf + offset,
+				       mem_desc->virt_addr, mem_desc->size);
+			offset += BYTES_TO_DWORDS(mem_desc->size);
+		}
+	}
+
+	return offset;
+}
+
+/* Dumps a section containing the dumped ILT pages.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_ilt_dump_pages_section(struct ecore_hwfn *p_hwfn,
+				      u32 *dump_buf,
+				      bool dump,
+				      u32 valid_conn_pf_pages,
+				      u32 valid_conn_vf_pages,
+				      struct phys_mem_desc *ilt_pages,
+				      bool dump_page_ids)
+{
+	struct ecore_ilt_client_cfg *clients = p_hwfn->p_cxt_mngr->clients;
+	u32 pf_start_line, start_page_id, offset = 0;
+	u32 cdut_pf_init_pages, cdut_vf_init_pages;
+	u32 cdut_pf_work_pages, cdut_vf_work_pages;
+	u32 base_data_offset, size_param_offset;
+	u32 cdut_pf_pages, cdut_vf_pages;
+	const char *section_name;
+	u8 i;
+
+	section_name = dump_page_ids ? "ilt_page_ids" : "ilt_page_mem";
+	cdut_pf_init_pages = ecore_get_cdut_num_pf_init_pages(p_hwfn);
+	cdut_vf_init_pages = ecore_get_cdut_num_vf_init_pages(p_hwfn);
+	cdut_pf_work_pages = ecore_get_cdut_num_pf_work_pages(p_hwfn);
+	cdut_vf_work_pages = ecore_get_cdut_num_vf_work_pages(p_hwfn);
+	cdut_pf_pages = cdut_pf_init_pages + cdut_pf_work_pages;
+	cdut_vf_pages = cdut_vf_init_pages + cdut_vf_work_pages;
+	pf_start_line = p_hwfn->p_cxt_mngr->pf_start_line;
+
+	offset +=
+	    qed_dump_section_hdr(dump_buf + offset, dump, section_name, 1);
+
+	/* Dump size parameter (0 for now, overwritten with real size later) */
+	size_param_offset = offset;
+	offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
+	base_data_offset = offset;
+
+	/* CDUC pages are ordered as follows:
+	 * - PF pages - valid section (included in PF connection type mapping)
+	 * - PF pages - invalid section (not dumped)
+	 * - For each VF in the PF:
+	 *   - VF pages - valid section (included in VF connection type mapping)
+	 *   - VF pages - invalid section (not dumped)
+	 */
+	if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_DUMP_ILT_CDUC)) {
+		/* Dump connection PF pages */
+		start_page_id = clients[ILT_CLI_CDUC].first.val - pf_start_line;
+		offset += qed_ilt_dump_pages_range(dump_buf + offset,
+						   dump,
+						   start_page_id,
+						   valid_conn_pf_pages,
+						   ilt_pages, dump_page_ids);
+
+		/* Dump connection VF pages */
+		start_page_id += clients[ILT_CLI_CDUC].pf_total_lines;
+		for (i = 0; i < p_hwfn->p_cxt_mngr->vf_count;
+		     i++, start_page_id += clients[ILT_CLI_CDUC].vf_total_lines)
+			offset += qed_ilt_dump_pages_range(dump_buf + offset,
+							   dump,
+							   start_page_id,
+							   valid_conn_vf_pages,
+							   ilt_pages,
+							   dump_page_ids);
+	}
+
+	/* CDUT pages are ordered as follows:
+	 * - PF init pages (not dumped)
+	 * - PF work pages
+	 * - For each VF in the PF:
+	 *   - VF init pages (not dumped)
+	 *   - VF work pages
+	 */
+	if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_DUMP_ILT_CDUT)) {
+		/* Dump task PF pages */
+		start_page_id = clients[ILT_CLI_CDUT].first.val +
+		    cdut_pf_init_pages - pf_start_line;
+		offset += qed_ilt_dump_pages_range(dump_buf + offset,
+						   dump,
+						   start_page_id,
+						   cdut_pf_work_pages,
+						   ilt_pages, dump_page_ids);
+
+		/* Dump task VF pages */
+		start_page_id = clients[ILT_CLI_CDUT].first.val +
+		    cdut_pf_pages + cdut_vf_init_pages - pf_start_line;
+		for (i = 0; i < p_hwfn->p_cxt_mngr->vf_count;
+		     i++, start_page_id += cdut_vf_pages)
+			offset += qed_ilt_dump_pages_range(dump_buf + offset,
+							   dump,
+							   start_page_id,
+							   cdut_vf_work_pages,
+							   ilt_pages,
+							   dump_page_ids);
+	}
+
+	/* Overwrite size param */
+	if (dump)
+		qed_dump_num_param(dump_buf + size_param_offset,
+				   dump, "size", offset - base_data_offset);
+
+	return offset;
+}
+
+/* Performs ILT Dump to the specified buffer.
+ * Returns the dumped size in dwords.
+ */
+static u32 qed_ilt_dump(struct ecore_hwfn *p_hwfn,
+			struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
+{
+	struct ecore_ilt_client_cfg *clients = p_hwfn->p_cxt_mngr->clients;
+	u32 valid_conn_vf_cids, valid_conn_vf_pages, offset = 0;
+	u32 valid_conn_pf_cids, valid_conn_pf_pages, num_pages;
+	u32 num_cids_per_page, conn_ctx_size;
+	u32 cduc_page_size, cdut_page_size;
+	struct phys_mem_desc *ilt_pages;
+	u8 conn_type;
+
+	cduc_page_size = 1 <<
+	    (clients[ILT_CLI_CDUC].p_size.val + PXP_ILT_PAGE_SIZE_NUM_BITS_MIN);
+	cdut_page_size = 1 <<
+	    (clients[ILT_CLI_CDUT].p_size.val + PXP_ILT_PAGE_SIZE_NUM_BITS_MIN);
+	conn_ctx_size = p_hwfn->p_cxt_mngr->conn_ctx_size;
+	num_cids_per_page = (int)(cduc_page_size / conn_ctx_size);
+	ilt_pages = p_hwfn->p_cxt_mngr->ilt_shadow;
+
+	/* Dump global params - 22 must match number of params below */
+	offset += qed_dump_common_global_params(p_hwfn, p_ptt,
+						dump_buf + offset, dump, 22);
+	offset += qed_dump_str_param(dump_buf + offset,
+				     dump, "dump-type", "ilt-dump");
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-page-size", cduc_page_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-first-page-id",
+				     clients[ILT_CLI_CDUC].first.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-last-page-id",
+				     clients[ILT_CLI_CDUC].last.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-num-pf-pages",
+				     clients
+				     [ILT_CLI_CDUC].pf_total_lines);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cduc-num-vf-pages",
+				     clients
+				     [ILT_CLI_CDUC].vf_total_lines);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "max-conn-ctx-size",
+				     conn_ctx_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-page-size", cdut_page_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-first-page-id",
+				     clients[ILT_CLI_CDUT].first.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-last-page-id",
+				     clients[ILT_CLI_CDUT].last.val);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-pf-init-pages",
+				     ecore_get_cdut_num_pf_init_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-vf-init-pages",
+				     ecore_get_cdut_num_vf_init_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-pf-work-pages",
+				     ecore_get_cdut_num_pf_work_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "cdut-num-vf-work-pages",
+				     ecore_get_cdut_num_vf_work_pages(p_hwfn));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "max-task-ctx-size",
+				     p_hwfn->p_cxt_mngr->task_ctx_size);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "task-type-id",
+				     p_hwfn->p_cxt_mngr->task_type_id);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "first-vf-id-in-pf",
+				     p_hwfn->p_cxt_mngr->first_vf_in_pf);
+	offset += /* 18 */ qed_dump_num_param(dump_buf + offset,
+					      dump,
+					      "num-vfs-in-pf",
+					      p_hwfn->p_cxt_mngr->vf_count);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "ptr-size-bytes", sizeof(void *));
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "pf-start-line",
+				     p_hwfn->p_cxt_mngr->pf_start_line);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "page-mem-desc-size-dwords",
+				     PAGE_MEM_DESC_SIZE_DWORDS);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "ilt-shadow-size",
+				     p_hwfn->p_cxt_mngr->ilt_shadow_size);
+	/* Additional/Less parameters require matching of number in call to
+	 * dump_common_global_params()
+	 */
+
+	/* Dump section containing number of PF CIDs per connection type */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "num_pf_cids_per_conn_type", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", NUM_OF_CONNECTION_TYPES);
+	for (conn_type = 0, valid_conn_pf_cids = 0;
+	     conn_type < NUM_OF_CONNECTION_TYPES; conn_type++, offset++) {
+		u32 num_pf_cids =
+		    p_hwfn->p_cxt_mngr->conn_cfg[conn_type].cid_count;
+
+		if (dump)
+			*(dump_buf + offset) = num_pf_cids;
+		valid_conn_pf_cids += num_pf_cids;
+	}
+
+	/* Dump section containing number of VF CIDs per connection type */
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "num_vf_cids_per_conn_type", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump, "size", NUM_OF_CONNECTION_TYPES);
+	for (conn_type = 0, valid_conn_vf_cids = 0;
+	     conn_type < NUM_OF_CONNECTION_TYPES; conn_type++, offset++) {
+		u32 num_vf_cids =
+		    p_hwfn->p_cxt_mngr->conn_cfg[conn_type].cids_per_vf;
+
+		if (dump)
+			*(dump_buf + offset) = num_vf_cids;
+		valid_conn_vf_cids += num_vf_cids;
+	}
+
+	/* Dump section containing physical memory descs for each ILT page */
+	num_pages = p_hwfn->p_cxt_mngr->ilt_shadow_size;
+	offset += qed_dump_section_hdr(dump_buf + offset,
+				       dump, "ilt_page_desc", 1);
+	offset += qed_dump_num_param(dump_buf + offset,
+				     dump,
+				     "size",
+				     num_pages * PAGE_MEM_DESC_SIZE_DWORDS);
+
+	/* Copy memory descriptors to dump buffer */
+	if (dump) {
+		u32 page_id;
+
+		for (page_id = 0; page_id < num_pages;
+		     page_id++, offset += PAGE_MEM_DESC_SIZE_DWORDS)
+			memcpy(dump_buf + offset,
+			       &ilt_pages[page_id],
+			       DWORDS_TO_BYTES(PAGE_MEM_DESC_SIZE_DWORDS));
+	} else {
+		offset += num_pages * PAGE_MEM_DESC_SIZE_DWORDS;
+	}
+
+	valid_conn_pf_pages = DIV_ROUND_UP(valid_conn_pf_cids,
+					   num_cids_per_page);
+	valid_conn_vf_pages = DIV_ROUND_UP(valid_conn_vf_cids,
+					   num_cids_per_page);
+
+	/* Dump ILT pages IDs */
+	offset += qed_ilt_dump_pages_section(p_hwfn,
+					     dump_buf + offset,
+					     dump,
+					     valid_conn_pf_pages,
+					     valid_conn_vf_pages,
+					     ilt_pages, true);
+
+	/* Dump ILT pages memory */
+	offset += qed_ilt_dump_pages_section(p_hwfn,
+					     dump_buf + offset,
+					     dump,
+					     valid_conn_pf_pages,
+					     valid_conn_vf_pages,
+					     ilt_pages, false);
+
+	/* Dump last section */
+	offset += qed_dump_last_section(dump_buf, offset, dump);
+
+	return offset;
+}
+
+/***************************** Public Functions *******************************/
+
+enum dbg_status qed_dbg_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+				    const u8 * const bin_ptr)
+{
+	struct bin_buffer_hdr *buf_hdrs =
+			(struct bin_buffer_hdr *)(osal_uintptr_t)bin_ptr;
+	u8 buf_id;
+
+	/* Convert binary data to debug arrays */
+	for (buf_id = 0; buf_id < MAX_BIN_DBG_BUFFER_TYPE; buf_id++)
+		qed_set_dbg_bin_buf(p_hwfn,
+				    buf_id,
+				    (const u32 *)(bin_ptr +
+						  buf_hdrs[buf_id].offset),
+						  buf_hdrs[buf_id].length);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_set_app_ver(u32 ver)
+{
+	if (ver < TOOLS_VERSION)
+		return DBG_STATUS_UNSUPPORTED_APP_VERSION;
+
+	s_app_ver = ver;
+
+	return DBG_STATUS_OK;
+}
+
+bool qed_read_fw_info(struct ecore_hwfn *p_hwfn,
+		      struct ecore_ptt *p_ptt, struct fw_info *fw_info)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u8 storm_id;
+
+	for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
+		struct storm_defs *storm = &s_storm_defs[storm_id];
+
+		/* Skip Storm if it's in reset */
+		if (dev_data->block_in_reset[storm->sem_block_id])
+			continue;
+
+		/* Read FW info for the current Storm */
+		qed_read_storm_fw_info(p_hwfn, p_ptt, storm_id, fw_info);
+
+		return true;
+	}
+
+	return false;
+}
+
+enum dbg_status qed_dbg_grc_config(struct ecore_hwfn *p_hwfn,
+				   enum dbg_grc_params grc_param, u32 val)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	enum dbg_status status;
+	int i;
+
+	DP_VERBOSE(p_hwfn->p_dev,
+		   ECORE_MSG_DEBUG,
+		   "dbg_grc_config: paramId = %d, val = %d\n", grc_param, val);
+
+	status = qed_dbg_dev_init(p_hwfn);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Initializes the GRC parameters (if not initialized). Needed in order
+	 * to set the default parameter values for the first time.
+	 */
+	qed_dbg_grc_init_params(p_hwfn);
+
+	if (grc_param >= MAX_DBG_GRC_PARAMS)
+		return DBG_STATUS_INVALID_ARGS;
+	if (val < s_grc_param_defs[grc_param].min ||
+	    val > s_grc_param_defs[grc_param].max)
+		return DBG_STATUS_INVALID_ARGS;
+
+	if (s_grc_param_defs[grc_param].is_preset) {
+		/* Preset param */
+
+		/* Disabling a preset is not allowed. Call
+		 * dbg_grc_set_params_default instead.
+		 */
+		if (!val)
+			return DBG_STATUS_INVALID_ARGS;
+
+		/* Update all params with the preset values */
+		for (i = 0; i < MAX_DBG_GRC_PARAMS; i++) {
+			struct grc_param_defs *defs = &s_grc_param_defs[i];
+			u32 preset_val;
+			/* Skip persistent params */
+			if (defs->is_persistent)
+				continue;
+
+			/* Find preset value */
+			if (grc_param == DBG_GRC_PARAM_EXCLUDE_ALL)
+				preset_val =
+				    defs->exclude_all_preset_val;
+			else if (grc_param == DBG_GRC_PARAM_CRASH)
+				preset_val =
+				    defs->crash_preset_val[dev_data->chip_id];
+			else
+				return DBG_STATUS_INVALID_ARGS;
+
+			qed_grc_set_param(p_hwfn, i, preset_val);
+		}
+	} else {
+		/* Regular param - set its value */
+		qed_grc_set_param(p_hwfn, grc_param, val);
+	}
+
+	return DBG_STATUS_OK;
+}
+
+/* Assign default GRC param values */
+void qed_dbg_grc_set_params_default(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	u32 i;
+
+	for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
+		if (!s_grc_param_defs[i].is_persistent)
+			dev_data->grc.param_val[i] =
+			    s_grc_param_defs[i].default_val[dev_data->chip_id];
+}
+
+enum dbg_status qed_dbg_grc_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_MEM].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	return qed_grc_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_grc_dump(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf,
+				 u32 buf_size_in_dwords,
+				 u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_grc_get_dump_buf_size(p_hwfn,
+					       p_ptt,
+					       &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* GRC Dump */
+	status = qed_grc_dump(p_hwfn, p_ptt, dump_buf, true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_idle_chk_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size)
+{
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	struct idle_chk_data *idle_chk = &dev_data->idle_chk;
+	enum dbg_status status;
+
+	*buf_size = 0;
+
+	status = qed_dbg_dev_init(p_hwfn);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_IMMS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_RULES].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	if (!idle_chk->buf_size_set) {
+		idle_chk->buf_size = qed_idle_chk_dump(p_hwfn,
+						       p_ptt, NULL, false);
+		idle_chk->buf_size_set = true;
+	}
+
+	*buf_size = idle_chk->buf_size;
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_idle_chk_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_grc_unreset_blocks(p_hwfn, p_ptt, true);
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	/* Idle Check Dump */
+	*num_dumped_dwords = qed_idle_chk_dump(p_hwfn, p_ptt, dump_buf, true);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_mcp_trace_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						    struct ecore_ptt *p_ptt,
+						    u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_mcp_trace_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+				       struct ecore_ptt *p_ptt,
+				       u32 *dump_buf,
+				       u32 buf_size_in_dwords,
+				       u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	status =
+		qed_dbg_mcp_trace_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK && status !=
+	    DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
+		return status;
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	/* Perform dump */
+	status = qed_mcp_trace_dump(p_hwfn,
+				    p_ptt, dump_buf, true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_reg_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_reg_fifo_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_reg_fifo_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	status = qed_reg_fifo_dump(p_hwfn,
+				   p_ptt, dump_buf, true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_igu_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_igu_fifo_dump(p_hwfn, p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_igu_fifo_get_dump_buf_size(p_hwfn,
+						    p_ptt,
+						    &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	status = qed_igu_fifo_dump(p_hwfn,
+				   p_ptt, dump_buf, true, num_dumped_dwords);
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status
+qed_dbg_protection_override_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	return qed_protection_override_dump(p_hwfn,
+					    p_ptt, NULL, false, buf_size);
+}
+
+enum dbg_status qed_dbg_protection_override_dump(struct ecore_hwfn *p_hwfn,
+						 struct ecore_ptt *p_ptt,
+						 u32 *dump_buf,
+						 u32 buf_size_in_dwords,
+						 u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords, *p_size = &needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status =
+		qed_dbg_protection_override_get_dump_buf_size(p_hwfn,
+							      p_ptt,
+							      p_size);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	status = qed_protection_override_dump(p_hwfn,
+					      p_ptt,
+					      dump_buf,
+					      true, num_dumped_dwords);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return status;
+}
+
+enum dbg_status qed_dbg_fw_asserts_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						     struct ecore_ptt *p_ptt,
+						     u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	/* Update reset state */
+	qed_update_blocks_reset_state(p_hwfn, p_ptt);
+
+	*buf_size = qed_fw_asserts_dump(p_hwfn, p_ptt, NULL, false);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf,
+					u32 buf_size_in_dwords,
+					u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords, *p_size = &needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status =
+		qed_dbg_fw_asserts_get_dump_buf_size(p_hwfn,
+						     p_ptt,
+						     p_size);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	*num_dumped_dwords = qed_fw_asserts_dump(p_hwfn, p_ptt, dump_buf, true);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status qed_dbg_ilt_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						     struct ecore_ptt *p_ptt,
+						     u32 *buf_size)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+
+	*buf_size = 0;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	*buf_size = qed_ilt_dump(p_hwfn, p_ptt, NULL, false);
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status qed_dbg_ilt_dump(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf,
+					u32 buf_size_in_dwords,
+					u32 *num_dumped_dwords)
+{
+	u32 needed_buf_size_in_dwords;
+	enum dbg_status status;
+
+	*num_dumped_dwords = 0;
+
+	status = qed_dbg_ilt_get_dump_buf_size(p_hwfn,
+					       p_ptt,
+					       &needed_buf_size_in_dwords);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (buf_size_in_dwords < needed_buf_size_in_dwords)
+		return DBG_STATUS_DUMP_BUF_TOO_SMALL;
+
+	*num_dumped_dwords = qed_ilt_dump(p_hwfn, p_ptt, dump_buf, true);
+
+	/* Revert GRC params to their default */
+	qed_dbg_grc_set_params_default(p_hwfn);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_read_attn(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  enum block_id block_id,
+				  enum dbg_attn_type attn_type,
+				  bool clear_status,
+				  struct dbg_attn_block_result *results)
+{
+	enum dbg_status status = qed_dbg_dev_init(p_hwfn);
+	u8 reg_idx, num_attn_regs, num_result_regs = 0;
+	const struct dbg_attn_reg *attn_reg_arr;
+
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
+					       block_id,
+					       attn_type, &num_attn_regs);
+
+	for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
+		const struct dbg_attn_reg *reg_data = &attn_reg_arr[reg_idx];
+		struct dbg_attn_reg_result *reg_result;
+		u32 sts_addr, sts_val;
+		u16 modes_buf_offset;
+		bool eval_mode;
+
+		/* Check mode */
+		eval_mode = GET_FIELD(reg_data->mode.data,
+				      DBG_MODE_HDR_EVAL_MODE) > 0;
+		modes_buf_offset = GET_FIELD(reg_data->mode.data,
+					     DBG_MODE_HDR_MODES_BUF_OFFSET);
+		if (eval_mode && !qed_is_mode_match(p_hwfn, &modes_buf_offset))
+			continue;
+
+		/* Mode match - read attention status register */
+		sts_addr = DWORDS_TO_BYTES(clear_status ?
+					   reg_data->sts_clr_address :
+					   GET_FIELD(reg_data->data,
+						     DBG_ATTN_REG_STS_ADDRESS));
+		sts_val = ecore_rd(p_hwfn, p_ptt, sts_addr);
+		if (!sts_val)
+			continue;
+
+		/* Non-zero attention status - add to results */
+		reg_result = &results->reg_results[num_result_regs];
+		SET_FIELD(reg_result->data,
+			  DBG_ATTN_REG_RESULT_STS_ADDRESS, sts_addr);
+		SET_FIELD(reg_result->data,
+			  DBG_ATTN_REG_RESULT_NUM_REG_ATTN,
+			  GET_FIELD(reg_data->data, DBG_ATTN_REG_NUM_REG_ATTN));
+		reg_result->block_attn_offset = reg_data->block_attn_offset;
+		reg_result->sts_val = sts_val;
+		reg_result->mask_val = ecore_rd(p_hwfn,
+					      p_ptt,
+					      DWORDS_TO_BYTES
+					      (reg_data->mask_address));
+		num_result_regs++;
+	}
+
+	results->block_id = (u8)block_id;
+	results->names_offset =
+	    qed_get_block_attn_data(p_hwfn, block_id, attn_type)->names_offset;
+	SET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_ATTN_TYPE, attn_type);
+	SET_FIELD(results->data,
+		  DBG_ATTN_BLOCK_RESULT_NUM_REGS, num_result_regs);
+
+	return DBG_STATUS_OK;
+}
+
+/******************************* Data Types **********************************/
+
+/* REG fifo element */
+struct reg_fifo_element {
+	u64 data;
+#define REG_FIFO_ELEMENT_ADDRESS_SHIFT		0
+#define REG_FIFO_ELEMENT_ADDRESS_MASK		0x7fffff
+#define REG_FIFO_ELEMENT_ACCESS_SHIFT		23
+#define REG_FIFO_ELEMENT_ACCESS_MASK		0x1
+#define REG_FIFO_ELEMENT_PF_SHIFT		24
+#define REG_FIFO_ELEMENT_PF_MASK		0xf
+#define REG_FIFO_ELEMENT_VF_SHIFT		28
+#define REG_FIFO_ELEMENT_VF_MASK		0xff
+#define REG_FIFO_ELEMENT_PORT_SHIFT		36
+#define REG_FIFO_ELEMENT_PORT_MASK		0x3
+#define REG_FIFO_ELEMENT_PRIVILEGE_SHIFT	38
+#define REG_FIFO_ELEMENT_PRIVILEGE_MASK		0x3
+#define REG_FIFO_ELEMENT_PROTECTION_SHIFT	40
+#define REG_FIFO_ELEMENT_PROTECTION_MASK	0x7
+#define REG_FIFO_ELEMENT_MASTER_SHIFT		43
+#define REG_FIFO_ELEMENT_MASTER_MASK		0xf
+#define REG_FIFO_ELEMENT_ERROR_SHIFT		47
+#define REG_FIFO_ELEMENT_ERROR_MASK		0x1f
+};
+
+/* REG fifo error element */
+struct reg_fifo_err {
+	u32 err_code;
+	const char *err_msg;
+};
+
+/* IGU fifo element */
+struct igu_fifo_element {
+	u32 dword0;
+#define IGU_FIFO_ELEMENT_DWORD0_FID_SHIFT		0
+#define IGU_FIFO_ELEMENT_DWORD0_FID_MASK		0xff
+#define IGU_FIFO_ELEMENT_DWORD0_IS_PF_SHIFT		8
+#define IGU_FIFO_ELEMENT_DWORD0_IS_PF_MASK		0x1
+#define IGU_FIFO_ELEMENT_DWORD0_SOURCE_SHIFT		9
+#define IGU_FIFO_ELEMENT_DWORD0_SOURCE_MASK		0xf
+#define IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE_SHIFT		13
+#define IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE_MASK		0xf
+#define IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR_SHIFT		17
+#define IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR_MASK		0x7fff
+	u32 dword1;
+	u32 dword2;
+#define IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD_SHIFT	0
+#define IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD_MASK		0x1
+#define IGU_FIFO_ELEMENT_DWORD12_WR_DATA_SHIFT		1
+#define IGU_FIFO_ELEMENT_DWORD12_WR_DATA_MASK		0xffffffff
+	u32 reserved;
+};
+
+struct igu_fifo_wr_data {
+	u32 data;
+#define IGU_FIFO_WR_DATA_PROD_CONS_SHIFT		0
+#define IGU_FIFO_WR_DATA_PROD_CONS_MASK			0xffffff
+#define IGU_FIFO_WR_DATA_UPDATE_FLAG_SHIFT		24
+#define IGU_FIFO_WR_DATA_UPDATE_FLAG_MASK		0x1
+#define IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB_SHIFT	25
+#define IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB_MASK		0x3
+#define IGU_FIFO_WR_DATA_SEGMENT_SHIFT			27
+#define IGU_FIFO_WR_DATA_SEGMENT_MASK			0x1
+#define IGU_FIFO_WR_DATA_TIMER_MASK_SHIFT		28
+#define IGU_FIFO_WR_DATA_TIMER_MASK_MASK		0x1
+#define IGU_FIFO_WR_DATA_CMD_TYPE_SHIFT			31
+#define IGU_FIFO_WR_DATA_CMD_TYPE_MASK			0x1
+};
+
+struct igu_fifo_cleanup_wr_data {
+	u32 data;
+#define IGU_FIFO_CLEANUP_WR_DATA_RESERVED_SHIFT		0
+#define IGU_FIFO_CLEANUP_WR_DATA_RESERVED_MASK		0x7ffffff
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL_SHIFT	27
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL_MASK	0x1
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE_SHIFT	28
+#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE_MASK	0x7
+#define IGU_FIFO_CLEANUP_WR_DATA_CMD_TYPE_SHIFT		31
+#define IGU_FIFO_CLEANUP_WR_DATA_CMD_TYPE_MASK		0x1
+};
+
+/* Protection override element */
+struct protection_override_element {
+	u64 data;
+#define PROTECTION_OVERRIDE_ELEMENT_ADDRESS_SHIFT		0
+#define PROTECTION_OVERRIDE_ELEMENT_ADDRESS_MASK		0x7fffff
+#define PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE_SHIFT		23
+#define PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE_MASK		0xffffff
+#define PROTECTION_OVERRIDE_ELEMENT_READ_SHIFT			47
+#define PROTECTION_OVERRIDE_ELEMENT_READ_MASK			0x1
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_SHIFT			48
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_MASK			0x1
+#define PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION_SHIFT	49
+#define PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION_MASK	0x7
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION_SHIFT	52
+#define PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION_MASK	0x7
+};
+
+enum igu_fifo_sources {
+	IGU_SRC_PXP0,
+	IGU_SRC_PXP1,
+	IGU_SRC_PXP2,
+	IGU_SRC_PXP3,
+	IGU_SRC_PXP4,
+	IGU_SRC_PXP5,
+	IGU_SRC_PXP6,
+	IGU_SRC_PXP7,
+	IGU_SRC_CAU,
+	IGU_SRC_ATTN,
+	IGU_SRC_GRC
+};
+
+enum igu_fifo_addr_types {
+	IGU_ADDR_TYPE_MSIX_MEM,
+	IGU_ADDR_TYPE_WRITE_PBA,
+	IGU_ADDR_TYPE_WRITE_INT_ACK,
+	IGU_ADDR_TYPE_WRITE_ATTN_BITS,
+	IGU_ADDR_TYPE_READ_INT,
+	IGU_ADDR_TYPE_WRITE_PROD_UPDATE,
+	IGU_ADDR_TYPE_RESERVED
+};
+
+struct igu_fifo_addr_data {
+	u16 start_addr;
+	u16 end_addr;
+	const char *desc;
+	const char *vf_desc;
+	enum igu_fifo_addr_types type;
+};
+
+/******************************** Constants **********************************/
+
+#define MAX_MSG_LEN				1024
+
+#define MCP_TRACE_MAX_MODULE_LEN		8
+#define MCP_TRACE_FORMAT_MAX_PARAMS		3
+#define MCP_TRACE_FORMAT_PARAM_WIDTH \
+	(MCP_TRACE_FORMAT_P2_SIZE_OFFSET - MCP_TRACE_FORMAT_P1_SIZE_OFFSET)
+
+#define REG_FIFO_ELEMENT_ADDR_FACTOR		4
+#define REG_FIFO_ELEMENT_IS_PF_VF_VAL		127
+
+#define PROTECTION_OVERRIDE_ELEMENT_ADDR_FACTOR	4
+
+/***************************** Constant Arrays *******************************/
+
+/* Status string array */
+static const char * const s_status_str[] = {
+	/* DBG_STATUS_OK */
+	"Operation completed successfully",
+
+	/* DBG_STATUS_APP_VERSION_NOT_SET */
+	"Debug application version wasn't set",
+
+	/* DBG_STATUS_UNSUPPORTED_APP_VERSION */
+	"Unsupported debug application version",
+
+	/* DBG_STATUS_DBG_BLOCK_NOT_RESET */
+	"The debug block wasn't reset since the last recording",
+
+	/* DBG_STATUS_INVALID_ARGS */
+	"Invalid arguments",
+
+	/* DBG_STATUS_OUTPUT_ALREADY_SET */
+	"The debug output was already set",
+
+	/* DBG_STATUS_INVALID_PCI_BUF_SIZE */
+	"Invalid PCI buffer size",
+
+	/* DBG_STATUS_PCI_BUF_ALLOC_FAILED */
+	"PCI buffer allocation failed",
+
+	/* DBG_STATUS_PCI_BUF_NOT_ALLOCATED */
+	"A PCI buffer wasn't allocated",
+
+	/* DBG_STATUS_INVALID_FILTER_TRIGGER_DWORDS */
+	"The filter/trigger constraint dword offsets are not enabled for recording",
+
+
+	/* DBG_STATUS_VFC_READ_ERROR */
+	"Error reading from VFC",
+
+	/* DBG_STATUS_STORM_ALREADY_ENABLED */
+	"The Storm was already enabled",
+
+	/* DBG_STATUS_STORM_NOT_ENABLED */
+	"The specified Storm wasn't enabled",
+
+	/* DBG_STATUS_BLOCK_ALREADY_ENABLED */
+	"The block was already enabled",
+
+	/* DBG_STATUS_BLOCK_NOT_ENABLED */
+	"The specified block wasn't enabled",
+
+	/* DBG_STATUS_NO_INPUT_ENABLED */
+	"No input was enabled for recording",
+
+	/* DBG_STATUS_NO_FILTER_TRIGGER_256B */
+	"Filters and triggers are not allowed in E4 256-bit mode",
+
+	/* DBG_STATUS_FILTER_ALREADY_ENABLED */
+	"The filter was already enabled",
+
+	/* DBG_STATUS_TRIGGER_ALREADY_ENABLED */
+	"The trigger was already enabled",
+
+	/* DBG_STATUS_TRIGGER_NOT_ENABLED */
+	"The trigger wasn't enabled",
+
+	/* DBG_STATUS_CANT_ADD_CONSTRAINT */
+	"A constraint can be added only after a filter was enabled or a trigger state was added",
+
+	/* DBG_STATUS_TOO_MANY_TRIGGER_STATES */
+	"Cannot add more than 3 trigger states",
+
+	/* DBG_STATUS_TOO_MANY_CONSTRAINTS */
+	"Cannot add more than 4 constraints per filter or trigger state",
+
+	/* DBG_STATUS_RECORDING_NOT_STARTED */
+	"The recording wasn't started",
+
+	/* DBG_STATUS_DATA_DID_NOT_TRIGGER */
+	"A trigger was configured, but it didn't trigger",
+
+	/* DBG_STATUS_NO_DATA_RECORDED */
+	"No data was recorded",
+
+	/* DBG_STATUS_DUMP_BUF_TOO_SMALL */
+	"Dump buffer is too small",
+
+	/* DBG_STATUS_DUMP_NOT_CHUNK_ALIGNED */
+	"Dumped data is not aligned to chunks",
+
+	/* DBG_STATUS_UNKNOWN_CHIP */
+	"Unknown chip",
+
+	/* DBG_STATUS_VIRT_MEM_ALLOC_FAILED */
+	"Failed allocating virtual memory",
+
+	/* DBG_STATUS_BLOCK_IN_RESET */
+	"The input block is in reset",
+
+	/* DBG_STATUS_INVALID_TRACE_SIGNATURE */
+	"Invalid MCP trace signature found in NVRAM",
+
+	/* DBG_STATUS_INVALID_NVRAM_BUNDLE */
+	"Invalid bundle ID found in NVRAM",
+
+	/* DBG_STATUS_NVRAM_GET_IMAGE_FAILED */
+	"Failed getting NVRAM image",
+
+	/* DBG_STATUS_NON_ALIGNED_NVRAM_IMAGE */
+	"NVRAM image is not dword-aligned",
+
+	/* DBG_STATUS_NVRAM_READ_FAILED */
+	"Failed reading from NVRAM",
+
+	/* DBG_STATUS_IDLE_CHK_PARSE_FAILED */
+	"Idle check parsing failed",
+
+	/* DBG_STATUS_MCP_TRACE_BAD_DATA */
+	"MCP Trace data is corrupt",
+
+	/* DBG_STATUS_MCP_TRACE_NO_META */
+	"Dump doesn't contain meta data - it must be provided in image file",
+
+	/* DBG_STATUS_MCP_COULD_NOT_HALT */
+	"Failed to halt MCP",
+
+	/* DBG_STATUS_MCP_COULD_NOT_RESUME */
+	"Failed to resume MCP after halt",
+
+	/* DBG_STATUS_RESERVED0 */
+	"",
+
+	/* DBG_STATUS_SEMI_FIFO_NOT_EMPTY */
+	"Failed to empty SEMI sync FIFO",
+
+	/* DBG_STATUS_IGU_FIFO_BAD_DATA */
+	"IGU FIFO data is corrupt",
+
+	/* DBG_STATUS_MCP_COULD_NOT_MASK_PRTY */
+	"MCP failed to mask parities",
+
+	/* DBG_STATUS_FW_ASSERTS_PARSE_FAILED */
+	"FW Asserts parsing failed",
+
+	/* DBG_STATUS_REG_FIFO_BAD_DATA */
+	"GRC FIFO data is corrupt",
+
+	/* DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA */
+	"Protection Override data is corrupt",
+
+	/* DBG_STATUS_DBG_ARRAY_NOT_SET */
+	"Debug arrays were not set (when using binary files, dbg_set_bin_ptr must be called)",
+
+	/* DBG_STATUS_RESERVED1 */
+	"",
+
+	/* DBG_STATUS_NON_MATCHING_LINES */
+	"Non-matching debug lines - in E4, all lines must be of the same type (either 128b or 256b)",
+
+	/* DBG_STATUS_INSUFFICIENT_HW_IDS */
+	"Insufficient HW IDs. Try to record less Storms/blocks",
+
+	/* DBG_STATUS_DBG_BUS_IN_USE */
+	"The debug bus is in use",
+
+	/* DBG_STATUS_INVALID_STORM_DBG_MODE */
+	"The storm debug mode is not supported in the current chip",
+
+	/* DBG_STATUS_OTHER_ENGINE_BB_ONLY */
+	"Other engine is supported only in BB",
+
+	/* DBG_STATUS_FILTER_SINGLE_HW_ID */
+	"The configured filter mode requires a single Storm/block input",
+
+	/* DBG_STATUS_TRIGGER_SINGLE_HW_ID */
+	"The configured filter mode requires that all the constraints of a single trigger state will be defined on a single Storm/block input",
+
+	/* DBG_STATUS_MISSING_TRIGGER_STATE_STORM */
+	"When triggering on Storm data, the Storm to trigger on must be specified"
+};
+
+/* Idle check severity names array */
+static const char * const s_idle_chk_severity_str[] = {
+	"Error",
+	"Error if no traffic",
+	"Warning"
+};
+
+/* MCP Trace level names array */
+static const char * const s_mcp_trace_level_str[] = {
+	"ERROR",
+	"TRACE",
+	"DEBUG"
+};
+
+/* Access type names array */
+static const char * const s_access_strs[] = {
+	"read",
+	"write"
+};
+
+/* Privilege type names array */
+static const char * const s_privilege_strs[] = {
+	"VF",
+	"PDA",
+	"HV",
+	"UA"
+};
+
+/* Protection type names array */
+static const char * const s_protection_strs[] = {
+	"(default)",
+	"(default)",
+	"(default)",
+	"(default)",
+	"override VF",
+	"override PDA",
+	"override HV",
+	"override UA"
+};
+
+/* Master type names array */
+static const char * const s_master_strs[] = {
+	"???",
+	"pxp",
+	"mcp",
+	"msdm",
+	"psdm",
+	"ysdm",
+	"usdm",
+	"tsdm",
+	"xsdm",
+	"dbu",
+	"dmae",
+	"jdap",
+	"???",
+	"???",
+	"???",
+	"???"
+};
+
+/* REG FIFO error messages array */
+static struct reg_fifo_err s_reg_fifo_errors[] = {
+	{1, "grc timeout"},
+	{2, "address doesn't belong to any block"},
+	{4, "reserved address in block or write to read-only address"},
+	{8, "privilege/protection mismatch"},
+	{16, "path isolation error"},
+	{17, "RSL error"}
+};
+
+/* IGU FIFO sources array */
+static const char * const s_igu_fifo_source_strs[] = {
+	"TSTORM",
+	"MSTORM",
+	"USTORM",
+	"XSTORM",
+	"YSTORM",
+	"PSTORM",
+	"PCIE",
+	"NIG_QM_PBF",
+	"CAU",
+	"ATTN",
+	"GRC",
+};
+
+/* IGU FIFO error messages */
+static const char * const s_igu_fifo_error_strs[] = {
+	"no error",
+	"length error",
+	"function disabled",
+	"VF sent command to attention address",
+	"host sent prod update command",
+	"read of during interrupt register while in MIMD mode",
+	"access to PXP BAR reserved address",
+	"producer update command to attention index",
+	"unknown error",
+	"SB index not valid",
+	"SB relative index and FID not found",
+	"FID not match",
+	"command with error flag asserted (PCI error or CAU discard)",
+	"VF sent cleanup and RF cleanup is disabled",
+	"cleanup command on type bigger than 4"
+};
+
+/* IGU FIFO address data */
+static const struct igu_fifo_addr_data s_igu_fifo_addr_data[] = {
+	{0x0, 0x101, "MSI-X Memory", NULL,
+	 IGU_ADDR_TYPE_MSIX_MEM},
+	{0x102, 0x1ff, "reserved", NULL,
+	 IGU_ADDR_TYPE_RESERVED},
+	{0x200, 0x200, "Write PBA[0:63]", NULL,
+	 IGU_ADDR_TYPE_WRITE_PBA},
+	{0x201, 0x201, "Write PBA[64:127]", "reserved",
+	 IGU_ADDR_TYPE_WRITE_PBA},
+	{0x202, 0x202, "Write PBA[128]", "reserved",
+	 IGU_ADDR_TYPE_WRITE_PBA},
+	{0x203, 0x3ff, "reserved", NULL,
+	 IGU_ADDR_TYPE_RESERVED},
+	{0x400, 0x5ef, "Write interrupt acknowledgment", NULL,
+	 IGU_ADDR_TYPE_WRITE_INT_ACK},
+	{0x5f0, 0x5f0, "Attention bits update", NULL,
+	 IGU_ADDR_TYPE_WRITE_ATTN_BITS},
+	{0x5f1, 0x5f1, "Attention bits set", NULL,
+	 IGU_ADDR_TYPE_WRITE_ATTN_BITS},
+	{0x5f2, 0x5f2, "Attention bits clear", NULL,
+	 IGU_ADDR_TYPE_WRITE_ATTN_BITS},
+	{0x5f3, 0x5f3, "Read interrupt 0:63 with mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f4, 0x5f4, "Read interrupt 0:31 with mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f5, 0x5f5, "Read interrupt 32:63 with mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f6, 0x5f6, "Read interrupt 0:63 without mask", NULL,
+	 IGU_ADDR_TYPE_READ_INT},
+	{0x5f7, 0x5ff, "reserved", NULL,
+	 IGU_ADDR_TYPE_RESERVED},
+	{0x600, 0x7ff, "Producer update", NULL,
+	 IGU_ADDR_TYPE_WRITE_PROD_UPDATE}
+};
+
+/******************************** Variables **********************************/
+
+/* Temporary buffer, used for print size calculations */
+static char s_temp_buf[MAX_MSG_LEN];
+
+/**************************** Private Functions ******************************/
+
+static u32 qed_cyclic_add(u32 a, u32 b, u32 size)
+{
+	return (a + b) % size;
+}
+
+static u32 qed_cyclic_sub(u32 a, u32 b, u32 size)
+{
+	return (size + a - b) % size;
+}
+
+/* Reads the specified number of bytes from the specified cyclic buffer (up to 4
+ * bytes) and returns them as a dword value. the specified buffer offset is
+ * updated.
+ */
+static u32 qed_read_from_cyclic_buf(void *buf,
+				    u32 *offset,
+				    u32 buf_size, u8 num_bytes_to_read)
+{
+	u8 i, *val_ptr, *bytes_buf = (u8 *)buf;
+	u32 val = 0;
+
+	val_ptr = (u8 *)&val;
+
+	/* Assume running on a LITTLE ENDIAN and the buffer is network order
+	 * (BIG ENDIAN), as high order bytes are placed in lower memory address.
+	 */
+	for (i = 0; i < num_bytes_to_read; i++) {
+		val_ptr[i] = bytes_buf[*offset];
+		*offset = qed_cyclic_add(*offset, 1, buf_size);
+	}
+
+	return val;
+}
+
+/* Reads and returns the next byte from the specified buffer.
+ * The specified buffer offset is updated.
+ */
+static u8 qed_read_byte_from_buf(void *buf, u32 *offset)
+{
+	return ((u8 *)buf)[(*offset)++];
+}
+
+/* Reads and returns the next dword from the specified buffer.
+ * The specified buffer offset is updated.
+ */
+static u32 qed_read_dword_from_buf(void *buf, u32 *offset)
+{
+	u32 dword_val = *(u32 *)&((u8 *)buf)[*offset];
+
+	*offset += 4;
+
+	return dword_val;
+}
+
+/* Reads the next string from the specified buffer, and copies it to the
+ * specified pointer. The specified buffer offset is updated.
+ */
+static void qed_read_str_from_buf(void *buf, u32 *offset, u32 size, char *dest)
+{
+	const char *source_str = &((const char *)buf)[*offset];
+
+	OSAL_STRNCPY(dest, source_str, size);
+	dest[size - 1] = '\0';
+	*offset += size;
+}
+
+/* Returns a pointer to the specified offset (in bytes) of the specified buffer.
+ * If the specified buffer in NULL, a temporary buffer pointer is returned.
+ */
+static char *qed_get_buf_ptr(void *buf, u32 offset)
+{
+	return buf ? (char *)buf + offset : s_temp_buf;
+}
+
+/* Reads a param from the specified buffer. Returns the number of dwords read.
+ * If the returned str_param is NULL, the param is numeric and its value is
+ * returned in num_param.
+ * Otheriwise, the param is a string and its pointer is returned in str_param.
+ */
+static u32 qed_read_param(u32 *dump_buf,
+			  const char **param_name,
+			  const char **param_str_val, u32 *param_num_val)
+{
+	char *char_buf = (char *)dump_buf;
+	size_t offset = 0;
+
+	/* Extract param name */
+	*param_name = char_buf;
+	offset += strlen(*param_name) + 1;
+
+	/* Check param type */
+	if (*(char_buf + offset++)) {
+		/* String param */
+		*param_str_val = char_buf + offset;
+		*param_num_val = 0;
+		offset += strlen(*param_str_val) + 1;
+		if (offset & 0x3)
+			offset += (4 - (offset & 0x3));
+	} else {
+		/* Numeric param */
+		*param_str_val = NULL;
+		if (offset & 0x3)
+			offset += (4 - (offset & 0x3));
+		*param_num_val = *(u32 *)(char_buf + offset);
+		offset += 4;
+	}
+
+	return (u32)offset / 4;
+}
+
+/* Reads a section header from the specified buffer.
+ * Returns the number of dwords read.
+ */
+static u32 qed_read_section_hdr(u32 *dump_buf,
+				const char **section_name,
+				u32 *num_section_params)
+{
+	const char *param_str_val;
+
+	return qed_read_param(dump_buf,
+			      section_name, &param_str_val, num_section_params);
+}
+
+/* Reads section params from the specified buffer and prints them to the results
+ * buffer. Returns the number of dwords read.
+ */
+static u32 qed_print_section_params(u32 *dump_buf,
+				    u32 num_section_params,
+				    char *results_buf, u32 *num_chars_printed)
+{
+	u32 i, dump_offset = 0, results_offset = 0;
+
+	for (i = 0; i < num_section_params; i++) {
+		const char *param_name, *param_str_val;
+		u32 param_num_val = 0;
+
+		dump_offset += qed_read_param(dump_buf + dump_offset,
+					      &param_name,
+					      &param_str_val, &param_num_val);
+
+		if (param_str_val) {
+			results_offset +=
+				sprintf(qed_get_buf_ptr(results_buf,
+							results_offset),
+					"%s: %s\n", param_name, param_str_val);
+		} else if (strcmp(param_name, "fw-timestamp")) {
+			results_offset +=
+				sprintf(qed_get_buf_ptr(results_buf,
+							results_offset),
+					"%s: %d\n", param_name, param_num_val);
+		}
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf, results_offset),
+				  "\n");
+
+	*num_chars_printed = results_offset;
+
+	return dump_offset;
+}
+
+/* Returns the block name that matches the specified block ID,
+ * or NULL if not found.
+ */
+static const char *qed_dbg_get_block_name(struct ecore_hwfn *p_hwfn,
+					  enum block_id block_id)
+{
+	const struct dbg_block_user *block =
+	    (const struct dbg_block_user *)
+	    p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS_USER_DATA].ptr + block_id;
+
+	return (const char *)block->name;
+}
+
+static struct dbg_tools_user_data *qed_dbg_get_user_data(struct ecore_hwfn
+							 *p_hwfn)
+{
+	return (struct dbg_tools_user_data *)p_hwfn->dbg_user_info;
+}
+
+/* Parses the idle check rules and returns the number of characters printed.
+ * In case of parsing error, returns 0.
+ */
+static u32 qed_parse_idle_chk_dump_rules(struct ecore_hwfn *p_hwfn,
+					 u32 *dump_buf,
+					 u32 *dump_buf_end,
+					 u32 num_rules,
+					 bool print_fw_idle_chk,
+					 char *results_buf,
+					 u32 *num_errors, u32 *num_warnings)
+{
+	/* Offset in results_buf in bytes */
+	u32 results_offset = 0;
+
+	u32 rule_idx;
+	u16 i, j;
+
+	*num_errors = 0;
+	*num_warnings = 0;
+
+	/* Go over dumped results */
+	for (rule_idx = 0; rule_idx < num_rules && dump_buf < dump_buf_end;
+	     rule_idx++) {
+		const struct dbg_idle_chk_rule_parsing_data *rule_parsing_data;
+		struct dbg_idle_chk_result_hdr *hdr;
+		const char *parsing_str, *lsi_msg;
+		u32 parsing_str_offset;
+		bool has_fw_msg;
+		u8 curr_reg_id;
+
+		hdr = (struct dbg_idle_chk_result_hdr *)dump_buf;
+		rule_parsing_data =
+		    (const struct dbg_idle_chk_rule_parsing_data *)
+		    p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_PARSING_DATA].ptr +
+		    hdr->rule_id;
+		parsing_str_offset =
+		    GET_FIELD(rule_parsing_data->data,
+			      DBG_IDLE_CHK_RULE_PARSING_DATA_STR_OFFSET);
+		has_fw_msg =
+		    GET_FIELD(rule_parsing_data->data,
+			      DBG_IDLE_CHK_RULE_PARSING_DATA_HAS_FW_MSG) > 0;
+		parsing_str = (const char *)
+		    p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr +
+		    parsing_str_offset;
+		lsi_msg = parsing_str;
+		curr_reg_id = 0;
+
+		if (hdr->severity >= MAX_DBG_IDLE_CHK_SEVERITY_TYPES)
+			return 0;
+
+		/* Skip rule header */
+		dump_buf += BYTES_TO_DWORDS(sizeof(*hdr));
+
+		/* Update errors/warnings count */
+		if (hdr->severity == IDLE_CHK_SEVERITY_ERROR ||
+		    hdr->severity == IDLE_CHK_SEVERITY_ERROR_NO_TRAFFIC)
+			(*num_errors)++;
+		else
+			(*num_warnings)++;
+
+		/* Print rule severity */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset), "%s: ",
+			    s_idle_chk_severity_str[hdr->severity]);
+
+		/* Print rule message */
+		if (has_fw_msg)
+			parsing_str += strlen(parsing_str) + 1;
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset), "%s.",
+			    has_fw_msg &&
+			    print_fw_idle_chk ? parsing_str : lsi_msg);
+		parsing_str += strlen(parsing_str) + 1;
+
+		/* Print register values */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset), " Registers:");
+		for (i = 0;
+		     i < hdr->num_dumped_cond_regs + hdr->num_dumped_info_regs;
+		     i++) {
+			struct dbg_idle_chk_result_reg_hdr *reg_hdr;
+			bool is_mem;
+			u8 reg_id;
+
+			reg_hdr =
+				(struct dbg_idle_chk_result_reg_hdr *)dump_buf;
+			is_mem = GET_FIELD(reg_hdr->data,
+					   DBG_IDLE_CHK_RESULT_REG_HDR_IS_MEM);
+			reg_id = GET_FIELD(reg_hdr->data,
+					   DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID);
+
+			/* Skip reg header */
+			dump_buf += BYTES_TO_DWORDS(sizeof(*reg_hdr));
+
+			/* Skip register names until the required reg_id is
+			 * reached.
+			 */
+			while (reg_id > curr_reg_id) {
+				curr_reg_id++;
+				parsing_str += strlen(parsing_str) + 1;
+			}
+
+			results_offset +=
+			    sprintf(qed_get_buf_ptr(results_buf,
+						    results_offset), " %s",
+				    parsing_str);
+			if (i < hdr->num_dumped_cond_regs && is_mem)
+				results_offset +=
+				    sprintf(qed_get_buf_ptr(results_buf,
+							    results_offset),
+					    "[%d]", hdr->mem_entry_id +
+					    reg_hdr->start_entry);
+			results_offset +=
+			    sprintf(qed_get_buf_ptr(results_buf,
+						    results_offset), "=");
+			for (j = 0; j < reg_hdr->size; j++, dump_buf++) {
+				results_offset +=
+				    sprintf(qed_get_buf_ptr(results_buf,
+							    results_offset),
+					    "0x%x", *dump_buf);
+				if (j < reg_hdr->size - 1)
+					results_offset +=
+					    sprintf(qed_get_buf_ptr
+						    (results_buf,
+						     results_offset), ",");
+			}
+		}
+
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf, results_offset), "\n");
+	}
+
+	/* Check if end of dump buffer was exceeded */
+	if (dump_buf > dump_buf_end)
+		return 0;
+
+	return results_offset;
+}
+
+/* Parses an idle check dump buffer.
+ * If result_buf is not NULL, the idle check results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+					       u32 *dump_buf,
+					       u32 num_dumped_dwords,
+					       char *results_buf,
+					       u32 *parsed_results_bytes,
+					       u32 *num_errors,
+					       u32 *num_warnings)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 *dump_buf_end = dump_buf + num_dumped_dwords;
+	u32 num_section_params = 0, num_rules;
+
+	/* Offset in results_buf in bytes */
+	u32 results_offset = 0;
+
+	*parsed_results_bytes = 0;
+	*num_errors = 0;
+	*num_warnings = 0;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_PARSING_DATA].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read idle_chk section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "idle_chk") || num_section_params != 1)
+		return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &num_rules);
+	if (strcmp(param_name, "num_rules"))
+		return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+
+	if (num_rules) {
+		u32 rules_print_size;
+
+		/* Print FW output */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "FW_IDLE_CHECK:\n");
+		rules_print_size =
+			qed_parse_idle_chk_dump_rules(p_hwfn,
+						      dump_buf,
+						      dump_buf_end,
+						      num_rules,
+						      true,
+						      results_buf ?
+						      results_buf +
+						      results_offset :
+						      NULL,
+						      num_errors,
+						      num_warnings);
+		results_offset += rules_print_size;
+		if (!rules_print_size)
+			return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+
+		/* Print LSI output */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nLSI_IDLE_CHECK:\n");
+		rules_print_size =
+			qed_parse_idle_chk_dump_rules(p_hwfn,
+						      dump_buf,
+						      dump_buf_end,
+						      num_rules,
+						      false,
+						      results_buf ?
+						      results_buf +
+						      results_offset :
+						      NULL,
+						      num_errors,
+						      num_warnings);
+		results_offset += rules_print_size;
+		if (!rules_print_size)
+			return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
+	}
+
+	/* Print errors/warnings count */
+	if (*num_errors)
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nIdle Check failed!!! (with %d errors and %d warnings)\n",
+			    *num_errors, *num_warnings);
+	else if (*num_warnings)
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nIdle Check completed successfully (with %d warnings)\n",
+			    *num_warnings);
+	else
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "\nIdle Check completed successfully\n");
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+/* Allocates and fills MCP Trace meta data based on the specified meta data
+ * dump buffer.
+ * Returns debug status code.
+ */
+static enum dbg_status
+qed_mcp_trace_alloc_meta_data(struct ecore_hwfn *p_hwfn,
+			      const u32 *meta_buf)
+{
+	struct dbg_tools_user_data *dev_user_data;
+	u32 offset = 0, signature, i;
+	struct mcp_trace_meta *meta;
+	u8 *meta_buf_bytes = (u8 *)(osal_uintptr_t)meta_buf;
+
+	dev_user_data = qed_dbg_get_user_data(p_hwfn);
+	meta = &dev_user_data->mcp_trace_meta;
+
+	/* Free the previous meta before loading a new one. */
+	if (meta->is_allocated)
+		qed_mcp_trace_free_meta_data(p_hwfn);
+
+	OSAL_MEMSET(meta, 0, sizeof(*meta));
+
+	/* Read first signature */
+	signature = qed_read_dword_from_buf(meta_buf_bytes, &offset);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Read no. of modules and allocate memory for their pointers */
+	meta->modules_num = qed_read_byte_from_buf(meta_buf_bytes, &offset);
+	meta->modules = (char **)OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
+				    meta->modules_num * sizeof(char *));
+	if (!meta->modules)
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	/* Allocate and read all module strings */
+	for (i = 0; i < meta->modules_num; i++) {
+		u8 module_len = qed_read_byte_from_buf(meta_buf_bytes, &offset);
+
+		*(meta->modules + i) = (char *)OSAL_ZALLOC(p_hwfn->p_dev,
+							   GFP_KERNEL,
+							   module_len);
+		if (!(*(meta->modules + i))) {
+			/* Update number of modules to be released */
+			meta->modules_num = i ? i - 1 : 0;
+			return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+		}
+
+		qed_read_str_from_buf(meta_buf_bytes, &offset, module_len,
+				      *(meta->modules + i));
+		if (module_len > MCP_TRACE_MAX_MODULE_LEN)
+			(*(meta->modules + i))[MCP_TRACE_MAX_MODULE_LEN] = '\0';
+	}
+
+	/* Read second signature */
+	signature = qed_read_dword_from_buf(meta_buf_bytes, &offset);
+	if (signature != NVM_MAGIC_VALUE)
+		return DBG_STATUS_INVALID_TRACE_SIGNATURE;
+
+	/* Read number of formats and allocate memory for all formats */
+	meta->formats_num = qed_read_dword_from_buf(meta_buf_bytes, &offset);
+	meta->formats =
+		(struct mcp_trace_format *)OSAL_ZALLOC(p_hwfn->p_dev,
+						       GFP_KERNEL,
+						       meta->formats_num *
+					       sizeof(struct mcp_trace_format));
+	if (!meta->formats)
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	/* Allocate and read all strings */
+	for (i = 0; i < meta->formats_num; i++) {
+		struct mcp_trace_format *format_ptr = &meta->formats[i];
+		u8 format_len;
+
+		format_ptr->data = qed_read_dword_from_buf(meta_buf_bytes,
+							   &offset);
+		format_len = GET_MFW_FIELD(format_ptr->data,
+					   MCP_TRACE_FORMAT_LEN);
+		format_ptr->format_str = (char *)OSAL_ZALLOC(p_hwfn->p_dev,
+							     GFP_KERNEL,
+							     format_len);
+		if (!format_ptr->format_str) {
+			/* Update number of modules to be released */
+			meta->formats_num = i ? i - 1 : 0;
+			return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+		}
+
+		qed_read_str_from_buf(meta_buf_bytes,
+				      &offset,
+				      format_len, format_ptr->format_str);
+	}
+
+	meta->is_allocated = true;
+	return DBG_STATUS_OK;
+}
+
+/* Parses an MCP trace buffer. If result_buf is not NULL, the MCP Trace results
+ * are printed to it. The parsing status is returned.
+ * Arguments:
+ * trace_buf - MCP trace cyclic buffer
+ * trace_buf_size - MCP trace cyclic buffer size in bytes
+ * data_offset - offset in bytes of the data to parse in the MCP trace cyclic
+ *		 buffer.
+ * data_size - size in bytes of data to parse.
+ * parsed_buf - destination buffer for parsed data.
+ * parsed_results_bytes - size of parsed data in bytes.
+ */
+static enum dbg_status qed_parse_mcp_trace_buf(struct ecore_hwfn *p_hwfn,
+					       u8 *trace_buf,
+					       u32 trace_buf_size,
+					       u32 data_offset,
+					       u32 data_size,
+					       char *parsed_buf,
+					       u32 *parsed_results_bytes)
+{
+	struct dbg_tools_user_data *dev_user_data;
+	struct mcp_trace_meta *meta;
+	u32 param_mask, param_shift;
+	enum dbg_status status;
+
+	dev_user_data = qed_dbg_get_user_data(p_hwfn);
+	meta = &dev_user_data->mcp_trace_meta;
+	*parsed_results_bytes = 0;
+
+	if (!meta->is_allocated)
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+	status = DBG_STATUS_OK;
+
+	while (data_size) {
+		struct mcp_trace_format *format_ptr;
+		u8 format_level, format_module;
+		u32 params[3] = { 0, 0, 0 };
+		u32 header, format_idx, i;
+
+		if (data_size < MFW_TRACE_ENTRY_SIZE)
+			return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+		header = qed_read_from_cyclic_buf(trace_buf,
+						  &data_offset,
+						  trace_buf_size,
+						  MFW_TRACE_ENTRY_SIZE);
+		data_size -= MFW_TRACE_ENTRY_SIZE;
+		format_idx = header & MFW_TRACE_EVENTID_MASK;
+
+		/* Skip message if its index doesn't exist in the meta data */
+		if (format_idx >= meta->formats_num) {
+			u8 format_size = (u8)GET_MFW_FIELD(header,
+							   MFW_TRACE_PRM_SIZE);
+
+			if (data_size < format_size)
+				return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+			data_offset = qed_cyclic_add(data_offset,
+						     format_size,
+						     trace_buf_size);
+			data_size -= format_size;
+			continue;
+		}
+
+		format_ptr =
+			(struct mcp_trace_format *)&meta->formats[format_idx];
+
+		for (i = 0,
+		     param_mask = MCP_TRACE_FORMAT_P1_SIZE_MASK, param_shift =
+		     MCP_TRACE_FORMAT_P1_SIZE_OFFSET;
+		     i < MCP_TRACE_FORMAT_MAX_PARAMS;
+		     i++, param_mask <<= MCP_TRACE_FORMAT_PARAM_WIDTH,
+		     param_shift += MCP_TRACE_FORMAT_PARAM_WIDTH) {
+			/* Extract param size (0..3) */
+			u8 param_size = (u8)((format_ptr->data & param_mask) >>
+					     param_shift);
+
+			/* If the param size is zero, there are no other
+			 * parameters.
+			 */
+			if (!param_size)
+				break;
+
+			/* Size is encoded using 2 bits, where 3 is used to
+			 * encode 4.
+			 */
+			if (param_size == 3)
+				param_size = 4;
+
+			if (data_size < param_size)
+				return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+			params[i] = qed_read_from_cyclic_buf(trace_buf,
+							     &data_offset,
+							     trace_buf_size,
+							     param_size);
+			data_size -= param_size;
+		}
+
+		format_level = (u8)GET_MFW_FIELD(format_ptr->data,
+						 MCP_TRACE_FORMAT_LEVEL);
+		format_module = (u8)GET_MFW_FIELD(format_ptr->data,
+						  MCP_TRACE_FORMAT_MODULE);
+		if (format_level >= OSAL_ARRAY_SIZE(s_mcp_trace_level_str))
+			return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+		/* Print current message to results buffer */
+		*parsed_results_bytes +=
+			OSAL_SPRINTF(qed_get_buf_ptr(parsed_buf,
+						*parsed_results_bytes),
+				"%s %-8s: ",
+				s_mcp_trace_level_str[format_level],
+				meta->modules[format_module]);
+		*parsed_results_bytes +=
+		    sprintf(qed_get_buf_ptr(parsed_buf, *parsed_results_bytes),
+			    format_ptr->format_str,
+			    params[0], params[1], params[2]);
+	}
+
+	/* Add string NULL terminator */
+	(*parsed_results_bytes)++;
+
+	return status;
+}
+
+/* Parses an MCP Trace dump buffer.
+ * If result_buf is not NULL, the MCP Trace results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+						u32 *dump_buf,
+						char *results_buf,
+						u32 *parsed_results_bytes,
+						bool free_meta_data)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 data_size, trace_data_dwords, trace_meta_dwords;
+	u32 offset, results_offset, results_buf_bytes;
+	u32 param_num_val, num_section_params;
+	struct mcp_trace *trace;
+	enum dbg_status status;
+	const u32 *meta_buf;
+	u8 *trace_buf;
+
+	*parsed_results_bytes = 0;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read trace_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "mcp_trace_data") || num_section_params != 1)
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	trace_data_dwords = param_num_val;
+
+	/* Prepare trace info */
+	trace = (struct mcp_trace *)dump_buf;
+	if (trace->signature != MFW_TRACE_SIGNATURE || !trace->size)
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+
+	trace_buf = (u8 *)dump_buf + sizeof(*trace);
+	offset = trace->trace_oldest;
+	data_size = qed_cyclic_sub(trace->trace_prod, offset, trace->size);
+	dump_buf += trace_data_dwords;
+
+	/* Read meta_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "mcp_trace_meta"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_MCP_TRACE_BAD_DATA;
+	trace_meta_dwords = param_num_val;
+
+	/* Choose meta data buffer */
+	if (!trace_meta_dwords) {
+		/* Dump doesn't include meta data */
+		struct dbg_tools_user_data *dev_user_data =
+			qed_dbg_get_user_data(p_hwfn);
+
+		if (!dev_user_data->mcp_trace_user_meta_buf)
+			return DBG_STATUS_MCP_TRACE_NO_META;
+
+		meta_buf = dev_user_data->mcp_trace_user_meta_buf;
+	} else {
+		/* Dump includes meta data */
+		meta_buf = dump_buf;
+	}
+
+	/* Allocate meta data memory */
+	status = qed_mcp_trace_alloc_meta_data(p_hwfn, meta_buf);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	status = qed_parse_mcp_trace_buf(p_hwfn,
+					 trace_buf,
+					 trace->size,
+					 offset,
+					 data_size,
+					 results_buf ?
+					 results_buf + results_offset :
+					 NULL,
+					 &results_buf_bytes);
+	if (status != DBG_STATUS_OK)
+		return status;
+
+	if (free_meta_data)
+		qed_mcp_trace_free_meta_data(p_hwfn);
+
+	*parsed_results_bytes = results_offset + results_buf_bytes;
+
+	return DBG_STATUS_OK;
+}
+
+/* Parses a Reg FIFO dump buffer.
+ * If result_buf is not NULL, the Reg FIFO results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_reg_fifo_dump(u32 *dump_buf,
+					       char *results_buf,
+					       u32 *parsed_results_bytes)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 param_num_val, num_section_params, num_elements;
+	struct reg_fifo_element *elements;
+	u8 i, j, err_code, vf_val;
+	u32 results_offset = 0;
+	char vf_str[4];
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read reg_fifo_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "reg_fifo_data"))
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+	if (param_num_val % REG_FIFO_ELEMENT_DWORDS)
+		return DBG_STATUS_REG_FIFO_BAD_DATA;
+	num_elements = param_num_val / REG_FIFO_ELEMENT_DWORDS;
+	elements = (struct reg_fifo_element *)dump_buf;
+
+	/* Decode elements */
+	for (i = 0; i < num_elements; i++) {
+		const char *err_msg = NULL;
+
+		/* Discover if element belongs to a VF or a PF */
+		vf_val = GET_FIELD(elements[i].data, REG_FIFO_ELEMENT_VF);
+		if (vf_val == REG_FIFO_ELEMENT_IS_PF_VF_VAL)
+			sprintf(vf_str, "%s", "N/A");
+		else
+			sprintf(vf_str, "%d", vf_val);
+
+		/* Find error message */
+		err_code = GET_FIELD(elements[i].data, REG_FIFO_ELEMENT_ERROR);
+		for (j = 0; j < OSAL_ARRAY_SIZE(s_reg_fifo_errors) && !err_msg;
+		     j++)
+			if (err_code == s_reg_fifo_errors[j].err_code)
+				err_msg = s_reg_fifo_errors[j].err_msg;
+
+		/* Add parsed element to parsed buffer */
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "raw: 0x%016lx, address: 0x%07x, access: %-5s, pf: %2d, vf: %s, port: %d, privilege: %-3s, protection: %-12s, master: %-4s, error: %s\n",
+			    elements[i].data,
+			    (u32)GET_FIELD(elements[i].data,
+					   REG_FIFO_ELEMENT_ADDRESS) *
+			    REG_FIFO_ELEMENT_ADDR_FACTOR,
+			    s_access_strs[GET_FIELD(elements[i].data,
+						    REG_FIFO_ELEMENT_ACCESS)],
+			    (u32)GET_FIELD(elements[i].data,
+					   REG_FIFO_ELEMENT_PF),
+			    vf_str,
+			    (u32)GET_FIELD(elements[i].data,
+					   REG_FIFO_ELEMENT_PORT),
+			    s_privilege_strs[GET_FIELD(elements[i].data,
+						REG_FIFO_ELEMENT_PRIVILEGE)],
+			    s_protection_strs[GET_FIELD(elements[i].data,
+						REG_FIFO_ELEMENT_PROTECTION)],
+			    s_master_strs[GET_FIELD(elements[i].data,
+						    REG_FIFO_ELEMENT_MASTER)],
+			    err_msg ? err_msg : "unknown error code");
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						  results_offset),
+				  "fifo contained %d elements", num_elements);
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status qed_parse_igu_fifo_element(struct igu_fifo_element
+						  *element, char
+						  *results_buf,
+						  u32 *results_offset)
+{
+	const struct igu_fifo_addr_data *found_addr = NULL;
+	u8 source, err_type, i, is_cleanup;
+	char parsed_addr_data[32];
+	char parsed_wr_data[256];
+	u32 wr_data, prod_cons;
+	bool is_wr_cmd, is_pf;
+	u16 cmd_addr;
+	u64 dword12;
+
+	/* Dword12 (dword index 1 and 2) contains bits 32..95 of the
+	 * FIFO element.
+	 */
+	dword12 = ((u64)element->dword2 << 32) | element->dword1;
+	is_wr_cmd = GET_FIELD(dword12, IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD);
+	is_pf = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_IS_PF);
+	cmd_addr = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR);
+	source = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_SOURCE);
+	err_type = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE);
+
+	if (source >= OSAL_ARRAY_SIZE(s_igu_fifo_source_strs))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	if (err_type >= OSAL_ARRAY_SIZE(s_igu_fifo_error_strs))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+
+	/* Find address data */
+	for (i = 0; i < OSAL_ARRAY_SIZE(s_igu_fifo_addr_data) && !found_addr;
+	     i++) {
+		const struct igu_fifo_addr_data *curr_addr =
+			&s_igu_fifo_addr_data[i];
+
+		if (cmd_addr >= curr_addr->start_addr && cmd_addr <=
+		    curr_addr->end_addr)
+			found_addr = curr_addr;
+	}
+
+	if (!found_addr)
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+
+	/* Prepare parsed address data */
+	switch (found_addr->type) {
+	case IGU_ADDR_TYPE_MSIX_MEM:
+		sprintf(parsed_addr_data, " vector_num = 0x%x", cmd_addr / 2);
+		break;
+	case IGU_ADDR_TYPE_WRITE_INT_ACK:
+	case IGU_ADDR_TYPE_WRITE_PROD_UPDATE:
+		sprintf(parsed_addr_data,
+			" SB = 0x%x", cmd_addr - found_addr->start_addr);
+		break;
+	default:
+		parsed_addr_data[0] = '\0';
+	}
+
+	if (!is_wr_cmd) {
+		parsed_wr_data[0] = '\0';
+		goto out;
+	}
+
+	/* Prepare parsed write data */
+	wr_data = GET_FIELD(dword12, IGU_FIFO_ELEMENT_DWORD12_WR_DATA);
+	prod_cons = GET_FIELD(wr_data, IGU_FIFO_WR_DATA_PROD_CONS);
+	is_cleanup = GET_FIELD(wr_data, IGU_FIFO_WR_DATA_CMD_TYPE);
+
+	if (source == IGU_SRC_ATTN) {
+		sprintf(parsed_wr_data, "prod: 0x%x, ", prod_cons);
+	} else {
+		if (is_cleanup) {
+			u8 cleanup_val, cleanup_type;
+
+			cleanup_val =
+				GET_FIELD(wr_data,
+					  IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL);
+			cleanup_type =
+			    GET_FIELD(wr_data,
+				      IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE);
+
+			sprintf(parsed_wr_data,
+				"cmd_type: cleanup, cleanup_val: %s, cleanup_type : %d, ",
+				cleanup_val ? "set" : "clear",
+				cleanup_type);
+		} else {
+			u8 update_flag, en_dis_int_for_sb, segment;
+			u8 timer_mask;
+
+			update_flag = GET_FIELD(wr_data,
+						IGU_FIFO_WR_DATA_UPDATE_FLAG);
+			en_dis_int_for_sb =
+				GET_FIELD(wr_data,
+					  IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB);
+			segment = GET_FIELD(wr_data,
+					    IGU_FIFO_WR_DATA_SEGMENT);
+			timer_mask = GET_FIELD(wr_data,
+					       IGU_FIFO_WR_DATA_TIMER_MASK);
+
+			sprintf(parsed_wr_data,
+				"cmd_type: prod/cons update, prod/cons: 0x%x, update_flag: %s, en_dis_int_for_sb : %s, segment : %s, timer_mask = %d, ",
+				prod_cons,
+				update_flag ? "update" : "nop",
+				en_dis_int_for_sb ?
+				(en_dis_int_for_sb == 1 ? "disable" : "nop") :
+				"enable",
+				segment ? "attn" : "regular",
+				timer_mask);
+		}
+	}
+out:
+	/* Add parsed element to parsed buffer */
+	*results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						   *results_offset),
+				   "raw: 0x%01x%08x%08x, %s: %d, source : %s, type : %s, cmd_addr : 0x%x(%s%s), %serror: %s\n",
+				   element->dword2, element->dword1,
+				   element->dword0,
+				   is_pf ? "pf" : "vf",
+				   GET_FIELD(element->dword0,
+					     IGU_FIFO_ELEMENT_DWORD0_FID),
+				   s_igu_fifo_source_strs[source],
+				   is_wr_cmd ? "wr" : "rd",
+				   cmd_addr,
+				   (!is_pf && found_addr->vf_desc)
+				   ? found_addr->vf_desc
+				   : found_addr->desc,
+				   parsed_addr_data,
+				   parsed_wr_data,
+				   s_igu_fifo_error_strs[err_type]);
+
+	return DBG_STATUS_OK;
+}
+
+/* Parses an IGU FIFO dump buffer.
+ * If result_buf is not NULL, the IGU FIFO results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_igu_fifo_dump(u32 *dump_buf,
+					       char *results_buf,
+					       u32 *parsed_results_bytes)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 param_num_val, num_section_params, num_elements;
+	struct igu_fifo_element *elements;
+	enum dbg_status status;
+	u32 results_offset = 0;
+	u8 i;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read igu_fifo_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "igu_fifo_data"))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	if (param_num_val % IGU_FIFO_ELEMENT_DWORDS)
+		return DBG_STATUS_IGU_FIFO_BAD_DATA;
+	num_elements = param_num_val / IGU_FIFO_ELEMENT_DWORDS;
+	elements = (struct igu_fifo_element *)dump_buf;
+
+	/* Decode elements */
+	for (i = 0; i < num_elements; i++) {
+		status = qed_parse_igu_fifo_element(&elements[i],
+						    results_buf,
+						    &results_offset);
+		if (status != DBG_STATUS_OK)
+			return status;
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						  results_offset),
+				  "fifo contained %d elements", num_elements);
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+static enum dbg_status
+qed_parse_protection_override_dump(u32 *dump_buf,
+				   char *results_buf,
+				   u32 *parsed_results_bytes)
+{
+	const char *section_name, *param_name, *param_str_val;
+	u32 param_num_val, num_section_params, num_elements;
+	struct protection_override_element *elements;
+	u32 results_offset = 0;
+	u8 i;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	/* Read protection_override_data section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "protection_override_data"))
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+	dump_buf += qed_read_param(dump_buf,
+				   &param_name, &param_str_val, &param_num_val);
+	if (strcmp(param_name, "size"))
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+	if (param_num_val % PROTECTION_OVERRIDE_ELEMENT_DWORDS)
+		return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
+	num_elements = param_num_val / PROTECTION_OVERRIDE_ELEMENT_DWORDS;
+	elements = (struct protection_override_element *)dump_buf;
+
+	/* Decode elements */
+	for (i = 0; i < num_elements; i++) {
+		u32 address = GET_FIELD(elements[i].data,
+					PROTECTION_OVERRIDE_ELEMENT_ADDRESS) *
+			      PROTECTION_OVERRIDE_ELEMENT_ADDR_FACTOR;
+
+		results_offset +=
+		    sprintf(qed_get_buf_ptr(results_buf,
+					    results_offset),
+			    "window %2d, address: 0x%07x, size: %7d regs, read: %d, write: %d, read protection: %-12s, write protection: %-12s\n",
+			    i, address,
+			    (u32)GET_FIELD(elements[i].data,
+				      PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE),
+			    (u32)GET_FIELD(elements[i].data,
+				      PROTECTION_OVERRIDE_ELEMENT_READ),
+			    (u32)GET_FIELD(elements[i].data,
+				      PROTECTION_OVERRIDE_ELEMENT_WRITE),
+			    s_protection_strs[GET_FIELD(elements[i].data,
+				PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION)],
+			    s_protection_strs[GET_FIELD(elements[i].data,
+				PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION)]);
+	}
+
+	results_offset += sprintf(qed_get_buf_ptr(results_buf,
+						  results_offset),
+				  "protection override contained %d elements",
+				  num_elements);
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+/* Parses a FW Asserts dump buffer.
+ * If result_buf is not NULL, the FW Asserts results are printed to it.
+ * In any case, the required results buffer size is assigned to
+ * parsed_results_bytes.
+ * The parsing status is returned.
+ */
+static enum dbg_status qed_parse_fw_asserts_dump(u32 *dump_buf,
+						 char *results_buf,
+						 u32 *parsed_results_bytes)
+{
+	u32 num_section_params, param_num_val, i, results_offset = 0;
+	const char *param_name, *param_str_val, *section_name;
+	bool last_section_found = false;
+
+	*parsed_results_bytes = 0;
+
+	/* Read global_params section */
+	dump_buf += qed_read_section_hdr(dump_buf,
+					 &section_name, &num_section_params);
+	if (strcmp(section_name, "global_params"))
+		return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+
+	/* Print global params */
+	dump_buf += qed_print_section_params(dump_buf,
+					     num_section_params,
+					     results_buf, &results_offset);
+
+	while (!last_section_found) {
+		dump_buf += qed_read_section_hdr(dump_buf,
+						 &section_name,
+						 &num_section_params);
+		if (!strcmp(section_name, "fw_asserts")) {
+			/* Extract params */
+			const char *storm_letter = NULL;
+			u32 storm_dump_size = 0;
+
+			for (i = 0; i < num_section_params; i++) {
+				dump_buf += qed_read_param(dump_buf,
+							   &param_name,
+							   &param_str_val,
+							   &param_num_val);
+				if (!strcmp(param_name, "storm"))
+					storm_letter = param_str_val;
+				else if (!strcmp(param_name, "size"))
+					storm_dump_size = param_num_val;
+				else
+					return
+					    DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+			}
+
+			if (!storm_letter || !storm_dump_size)
+				return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+
+			/* Print data */
+			results_offset +=
+			    sprintf(qed_get_buf_ptr(results_buf,
+						    results_offset),
+				    "\n%sSTORM_ASSERT: size=%d\n",
+				    storm_letter, storm_dump_size);
+			for (i = 0; i < storm_dump_size; i++, dump_buf++)
+				results_offset +=
+				    sprintf(qed_get_buf_ptr(results_buf,
+							    results_offset),
+					    "%08x\n", *dump_buf);
+		} else if (!strcmp(section_name, "last")) {
+			last_section_found = true;
+		} else {
+			return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
+		}
+	}
+
+	/* Add 1 for string NULL termination */
+	*parsed_results_bytes = results_offset + 1;
+
+	return DBG_STATUS_OK;
+}
+
+/***************************** Public Functions *******************************/
+
+enum dbg_status qed_dbg_user_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+					 const u8 * const bin_ptr)
+{
+	struct bin_buffer_hdr *buf_hdrs =
+			(struct bin_buffer_hdr *)(osal_uintptr_t)bin_ptr;
+	u8 buf_id;
+
+	/* Convert binary data to debug arrays */
+	for (buf_id = 0; buf_id < MAX_BIN_DBG_BUFFER_TYPE; buf_id++)
+		qed_set_dbg_bin_buf(p_hwfn,
+				    (enum bin_dbg_buffer_type)buf_id,
+				    (const u32 *)(bin_ptr +
+						  buf_hdrs[buf_id].offset),
+						  buf_hdrs[buf_id].length);
+
+	return DBG_STATUS_OK;
+}
+
+enum dbg_status qed_dbg_alloc_user_data(__rte_unused struct ecore_hwfn *p_hwfn,
+					void **user_data_ptr)
+{
+	*user_data_ptr = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
+				     sizeof(struct dbg_tools_user_data));
+	if (!(*user_data_ptr))
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	return DBG_STATUS_OK;
+}
+
+const char *qed_dbg_get_status_str(enum dbg_status status)
+{
+	return (status <
+		MAX_DBG_STATUS) ? s_status_str[status] : "Invalid debug status";
+}
+
+enum dbg_status qed_get_idle_chk_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32 num_dumped_dwords,
+						  u32 *results_buf_size)
+{
+	u32 num_errors, num_warnings;
+
+	return qed_parse_idle_chk_dump(p_hwfn,
+				       dump_buf,
+				       num_dumped_dwords,
+				       NULL,
+				       results_buf_size,
+				       &num_errors, &num_warnings);
+}
+
+enum dbg_status qed_print_idle_chk_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf,
+					   u32 *num_errors,
+					   u32 *num_warnings)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_idle_chk_dump(p_hwfn,
+				       dump_buf,
+				       num_dumped_dwords,
+				       results_buf,
+				       &parsed_buf_size,
+				       num_errors, num_warnings);
+}
+
+void qed_dbg_mcp_trace_set_meta_data(struct ecore_hwfn *p_hwfn,
+				     const u32 *meta_buf)
+{
+	struct dbg_tools_user_data *dev_user_data =
+		qed_dbg_get_user_data(p_hwfn);
+
+	dev_user_data->mcp_trace_user_meta_buf = meta_buf;
+}
+
+enum dbg_status
+qed_get_mcp_trace_results_buf_size(struct ecore_hwfn *p_hwfn,
+				   u32 *dump_buf,
+				   __rte_unused u32 num_dumped_dwords,
+				   u32 *results_buf_size)
+{
+	return qed_parse_mcp_trace_dump(p_hwfn,
+					dump_buf, NULL, results_buf_size, true);
+}
+
+enum dbg_status qed_print_mcp_trace_results(struct ecore_hwfn *p_hwfn,
+					    u32 *dump_buf,
+					    __rte_unused u32 num_dumped_dwords,
+					    char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_mcp_trace_dump(p_hwfn,
+					dump_buf,
+					results_buf, &parsed_buf_size, true);
+}
+
+enum dbg_status qed_print_mcp_trace_results_cont(struct ecore_hwfn *p_hwfn,
+						 u32 *dump_buf,
+						 char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_mcp_trace_dump(p_hwfn, dump_buf, results_buf,
+					&parsed_buf_size, false);
+}
+
+enum dbg_status qed_print_mcp_trace_line(struct ecore_hwfn *p_hwfn,
+					 u8 *dump_buf,
+					 u32 num_dumped_bytes,
+					 char *results_buf)
+{
+	u32 parsed_results_bytes;
+
+	return qed_parse_mcp_trace_buf(p_hwfn,
+				       dump_buf,
+				       num_dumped_bytes,
+				       0,
+				       num_dumped_bytes,
+				       results_buf, &parsed_results_bytes);
+}
+
+/* Frees the specified MCP Trace meta data */
+void qed_mcp_trace_free_meta_data(struct ecore_hwfn *p_hwfn)
+{
+	struct dbg_tools_user_data *dev_user_data;
+	struct mcp_trace_meta *meta;
+	u32 i;
+
+	dev_user_data = qed_dbg_get_user_data(p_hwfn);
+	meta = &dev_user_data->mcp_trace_meta;
+	if (!meta->is_allocated)
+		return;
+
+	/* Release modules */
+	if (meta->modules) {
+		for (i = 0; i < meta->modules_num; i++)
+			OSAL_FREE(p_hwfn, meta->modules[i]);
+		OSAL_FREE(p_hwfn, meta->modules);
+	}
+
+	/* Release formats */
+	if (meta->formats) {
+		for (i = 0; i < meta->formats_num; i++)
+			OSAL_FREE(p_hwfn, meta->formats[i].format_str);
+		OSAL_FREE(p_hwfn, meta->formats);
+	}
+
+	meta->is_allocated = false;
+}
+
+enum dbg_status
+qed_get_reg_fifo_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
+				  u32 *dump_buf,
+				  __rte_unused u32 num_dumped_dwords,
+				  u32 *results_buf_size)
+{
+	return qed_parse_reg_fifo_dump(dump_buf, NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_reg_fifo_results(__rte_unused struct ecore_hwfn *p_hwfn,
+			   u32 *dump_buf,
+			   __rte_unused u32 num_dumped_dwords,
+			   char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_reg_fifo_dump(dump_buf, results_buf, &parsed_buf_size);
+}
+
+enum dbg_status
+qed_get_igu_fifo_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
+				  u32 *dump_buf,
+				  __rte_unused u32 num_dumped_dwords,
+				  u32 *results_buf_size)
+{
+	return qed_parse_igu_fifo_dump(dump_buf, NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_igu_fifo_results(__rte_unused struct ecore_hwfn *p_hwfn,
+			   u32 *dump_buf,
+			   __rte_unused u32 num_dumped_dwords,
+			   char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_igu_fifo_dump(dump_buf, results_buf, &parsed_buf_size);
+}
+
+enum dbg_status
+qed_get_protection_override_results_buf_size(__rte_unused
+					     struct ecore_hwfn *p_hwfn,
+					     u32 *dump_buf,
+					     __rte_unused u32 num_dumped_dwords,
+					     u32 *results_buf_size)
+{
+	return qed_parse_protection_override_dump(dump_buf,
+						  NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_protection_override_results(__rte_unused struct ecore_hwfn *p_hwfn,
+				      u32 *dump_buf,
+				      __rte_unused u32 num_dumped_dwords,
+				      char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_protection_override_dump(dump_buf,
+						  results_buf,
+						  &parsed_buf_size);
+}
+
+enum dbg_status
+qed_get_fw_asserts_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
+				    u32 *dump_buf,
+				    __rte_unused u32 num_dumped_dwords,
+				    u32 *results_buf_size)
+{
+	return qed_parse_fw_asserts_dump(dump_buf, NULL, results_buf_size);
+}
+
+enum dbg_status
+qed_print_fw_asserts_results(__rte_unused struct ecore_hwfn *p_hwfn,
+			     u32 *dump_buf,
+			     __rte_unused u32 num_dumped_dwords,
+			     char *results_buf)
+{
+	u32 parsed_buf_size;
+
+	return qed_parse_fw_asserts_dump(dump_buf,
+					 results_buf, &parsed_buf_size);
+}
+
+enum dbg_status qed_dbg_parse_attn(struct ecore_hwfn *p_hwfn,
+				   struct dbg_attn_block_result *results)
+{
+	const u32 *block_attn_name_offsets;
+	const char *attn_name_base;
+	const char *block_name;
+	enum dbg_attn_type attn_type;
+	u8 num_regs, i, j;
+
+	num_regs = GET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_NUM_REGS);
+	attn_type = GET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_ATTN_TYPE);
+	block_name = qed_dbg_get_block_name(p_hwfn, results->block_id);
+	if (!block_name)
+		return DBG_STATUS_INVALID_ARGS;
+
+	if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_INDEXES].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_NAME_OFFSETS].ptr ||
+	    !p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr)
+		return DBG_STATUS_DBG_ARRAY_NOT_SET;
+
+	block_attn_name_offsets =
+	    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_NAME_OFFSETS].ptr +
+	    results->names_offset;
+
+	attn_name_base = p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr;
+
+	/* Go over registers with a non-zero attention status */
+	for (i = 0; i < num_regs; i++) {
+		struct dbg_attn_bit_mapping *bit_mapping;
+		struct dbg_attn_reg_result *reg_result;
+		u8 num_reg_attn, bit_idx = 0;
+
+		reg_result = &results->reg_results[i];
+		num_reg_attn = GET_FIELD(reg_result->data,
+					 DBG_ATTN_REG_RESULT_NUM_REG_ATTN);
+		bit_mapping = (struct dbg_attn_bit_mapping *)
+		    p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_INDEXES].ptr +
+		    reg_result->block_attn_offset;
+
+		/* Go over attention status bits */
+		for (j = 0; j < num_reg_attn; j++, bit_idx++) {
+			u16 attn_idx_val = GET_FIELD(bit_mapping[j].data,
+						     DBG_ATTN_BIT_MAPPING_VAL);
+			const char *attn_name, *attn_type_str, *masked_str;
+			u32 attn_name_offset;
+			u32 sts_addr;
+
+			/* Check if bit mask should be advanced (due to unused
+			 * bits).
+			 */
+			if (GET_FIELD(bit_mapping[j].data,
+				      DBG_ATTN_BIT_MAPPING_IS_UNUSED_BIT_CNT)) {
+				bit_idx += (u8)attn_idx_val;
+				continue;
+			}
+
+			/* Check current bit index */
+			if (!(reg_result->sts_val & OSAL_BIT(bit_idx)))
+				continue;
+
+			/* An attention bit with value=1 was found
+			 * Find attention name
+			 */
+			attn_name_offset =
+				block_attn_name_offsets[attn_idx_val];
+			attn_name = attn_name_base + attn_name_offset;
+			attn_type_str =
+				(attn_type ==
+				 ATTN_TYPE_INTERRUPT ? "Interrupt" :
+				 "Parity");
+			masked_str = reg_result->mask_val & OSAL_BIT(bit_idx) ?
+				     " [masked]" : "";
+			sts_addr = GET_FIELD(reg_result->data,
+					     DBG_ATTN_REG_RESULT_STS_ADDRESS);
+			DP_NOTICE(p_hwfn, false,
+				  "%s (%s) : %s [address 0x%08x, bit %d]%s\n",
+				  block_name, attn_type_str, attn_name,
+				  sts_addr * 4, bit_idx, masked_str);
+		}
+	}
+
+	return DBG_STATUS_OK;
+}
+
+/* Wrapper for unifying the idle_chk and mcp_trace api */
+static enum dbg_status
+qed_print_idle_chk_results_wrapper(struct ecore_hwfn *p_hwfn,
+				   u32 *dump_buf,
+				   u32 num_dumped_dwords,
+				   char *results_buf)
+{
+	u32 num_errors, num_warnnings;
+
+	return qed_print_idle_chk_results(p_hwfn, dump_buf, num_dumped_dwords,
+					  results_buf, &num_errors,
+					  &num_warnnings);
+}
+
+/* Feature meta data lookup table */
+static struct {
+	const char *name;
+	enum dbg_status (*get_size)(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt, u32 *size);
+	enum dbg_status (*perform_dump)(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt, u32 *dump_buf,
+					u32 buf_size, u32 *dumped_dwords);
+	enum dbg_status (*print_results)(struct ecore_hwfn *p_hwfn,
+					 u32 *dump_buf, u32 num_dumped_dwords,
+					 char *results_buf);
+	enum dbg_status (*results_buf_size)(struct ecore_hwfn *p_hwfn,
+					    u32 *dump_buf,
+					    u32 num_dumped_dwords,
+					    u32 *results_buf_size);
+} qed_features_lookup[] = {
+	{
+	"grc", qed_dbg_grc_get_dump_buf_size,
+		    qed_dbg_grc_dump, NULL, NULL}, {
+	"idle_chk",
+		    qed_dbg_idle_chk_get_dump_buf_size,
+		    qed_dbg_idle_chk_dump,
+		    qed_print_idle_chk_results_wrapper,
+		    qed_get_idle_chk_results_buf_size}, {
+	"mcp_trace",
+		    qed_dbg_mcp_trace_get_dump_buf_size,
+		    qed_dbg_mcp_trace_dump, qed_print_mcp_trace_results,
+		    qed_get_mcp_trace_results_buf_size}, {
+	"reg_fifo",
+		    qed_dbg_reg_fifo_get_dump_buf_size,
+		    qed_dbg_reg_fifo_dump, qed_print_reg_fifo_results,
+		    qed_get_reg_fifo_results_buf_size}, {
+	"igu_fifo",
+		    qed_dbg_igu_fifo_get_dump_buf_size,
+		    qed_dbg_igu_fifo_dump, qed_print_igu_fifo_results,
+		    qed_get_igu_fifo_results_buf_size}, {
+	"protection_override",
+		    qed_dbg_protection_override_get_dump_buf_size,
+		    qed_dbg_protection_override_dump,
+		    qed_print_protection_override_results,
+		    qed_get_protection_override_results_buf_size}, {
+	"fw_asserts",
+		    qed_dbg_fw_asserts_get_dump_buf_size,
+		    qed_dbg_fw_asserts_dump,
+		    qed_print_fw_asserts_results,
+		    qed_get_fw_asserts_results_buf_size}, {
+	"ilt",
+		    qed_dbg_ilt_get_dump_buf_size,
+		    qed_dbg_ilt_dump, NULL, NULL},};
+
+#define QED_RESULTS_BUF_MIN_SIZE 16
+/* Generic function for decoding debug feature info */
+static enum dbg_status format_feature(struct ecore_hwfn *p_hwfn,
+				      enum ecore_dbg_features feature_idx)
+{
+	struct ecore_dbg_feature *feature =
+	    &p_hwfn->p_dev->dbg_params.features[feature_idx];
+	u32 text_size_bytes, null_char_pos, i;
+	enum dbg_status rc;
+	char *text_buf;
+
+	/* Check if feature supports formatting capability */
+	if (!qed_features_lookup[feature_idx].results_buf_size)
+		return DBG_STATUS_OK;
+
+	/* Obtain size of formatted output */
+	rc = qed_features_lookup[feature_idx].results_buf_size(p_hwfn,
+						(u32 *)feature->dump_buf,
+						feature->dumped_dwords,
+						&text_size_bytes);
+	if (rc != DBG_STATUS_OK)
+		return rc;
+
+	/* Make sure that the allocated size is a multiple of dword (4 bytes) */
+	null_char_pos = text_size_bytes - 1;
+	text_size_bytes = (text_size_bytes + 3) & ~0x3;
+
+	if (text_size_bytes < QED_RESULTS_BUF_MIN_SIZE) {
+		DP_NOTICE(p_hwfn->p_dev, false,
+			  "formatted size of feature was too small %d. Aborting\n",
+			  text_size_bytes);
+		return DBG_STATUS_INVALID_ARGS;
+	}
+
+	/* Allocate temp text buf */
+	text_buf = OSAL_VZALLOC(p_hwfn, text_size_bytes);
+	if (!text_buf) {
+		DP_NOTICE(p_hwfn->p_dev, false,
+			  "failed to allocate text buffer. Aborting\n");
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+	}
+
+	/* Decode feature opcodes to string on temp buf */
+	rc = qed_features_lookup[feature_idx].print_results(p_hwfn,
+						(u32 *)feature->dump_buf,
+						feature->dumped_dwords,
+						text_buf);
+	if (rc != DBG_STATUS_OK) {
+		OSAL_VFREE(p_hwfn, text_buf);
+		return rc;
+	}
+
+	/* Replace the original null character with a '\n' character.
+	 * The bytes that were added as a result of the dword alignment are also
+	 * padded with '\n' characters.
+	 */
+	for (i = null_char_pos; i < text_size_bytes; i++)
+		text_buf[i] = '\n';
+
+
+	/* Free the old dump_buf and point the dump_buf to the newly allocagted
+	 * and formatted text buffer.
+	 */
+	OSAL_VFREE(p_hwfn, feature->dump_buf);
+	feature->dump_buf = (u8 *)text_buf;
+	feature->buf_size = text_size_bytes;
+	feature->dumped_dwords = text_size_bytes / 4;
+	return rc;
+}
+
+#define MAX_DBG_FEATURE_SIZE_DWORDS	0x3FFFFFFF
+
+/* Generic function for performing the dump of a debug feature. */
+static enum dbg_status qed_dbg_dump(struct ecore_hwfn *p_hwfn,
+				    struct ecore_ptt *p_ptt,
+				    enum ecore_dbg_features feature_idx)
+{
+	struct ecore_dbg_feature *feature =
+	    &p_hwfn->p_dev->dbg_params.features[feature_idx];
+	u32 buf_size_dwords;
+	enum dbg_status rc;
+
+	DP_NOTICE(p_hwfn->p_dev, false, "Collecting a debug feature [\"%s\"]\n",
+		  qed_features_lookup[feature_idx].name);
+
+	/* Dump_buf was already allocated need to free (this can happen if dump
+	 * was called but file was never read).
+	 * We can't use the buffer as is since size may have changed.
+	 */
+	if (feature->dump_buf) {
+		OSAL_VFREE(p_hwfn, feature->dump_buf);
+		feature->dump_buf = NULL;
+	}
+
+	/* Get buffer size from hsi, allocate accordingly, and perform the
+	 * dump.
+	 */
+	rc = qed_features_lookup[feature_idx].get_size(p_hwfn, p_ptt,
+						       &buf_size_dwords);
+	if (rc != DBG_STATUS_OK && rc != DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
+		return rc;
+
+	if (buf_size_dwords > MAX_DBG_FEATURE_SIZE_DWORDS) {
+		feature->buf_size = 0;
+		DP_NOTICE(p_hwfn->p_dev, false,
+			  "Debug feature [\"%s\"] size (0x%x dwords) exceeds maximum size (0x%x dwords)\n",
+			  qed_features_lookup[feature_idx].name,
+			  buf_size_dwords, MAX_DBG_FEATURE_SIZE_DWORDS);
+
+		return DBG_STATUS_OK;
+	}
+
+	feature->buf_size = buf_size_dwords * sizeof(u32);
+	feature->dump_buf = OSAL_ZALLOC(p_hwfn, GFP_KERNEL, feature->buf_size);
+	if (!feature->dump_buf)
+		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
+
+	rc = qed_features_lookup[feature_idx].perform_dump(p_hwfn, p_ptt,
+					(u32 *)feature->dump_buf,
+					feature->buf_size / sizeof(u32),
+					&feature->dumped_dwords);
+
+	/* If mcp is stuck we get DBG_STATUS_NVRAM_GET_IMAGE_FAILED error.
+	 * In this case the buffer holds valid binary data, but we won't able
+	 * to parse it (since parsing relies on data in NVRAM which is only
+	 * accessible when MFW is responsive). skip the formatting but return
+	 * success so that binary data is provided.
+	 */
+	if (rc == DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
+		return DBG_STATUS_OK;
+
+	if (rc != DBG_STATUS_OK)
+		return rc;
+
+	/* Format output */
+	rc = format_feature(p_hwfn, feature_idx);
+	return rc;
+}
+
+int qed_dbg_grc(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_GRC, num_dumped_bytes);
+}
+
+int qed_dbg_grc_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_GRC);
+}
+
+int
+qed_dbg_idle_chk(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_IDLE_CHK,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_idle_chk_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_IDLE_CHK);
+}
+
+int
+qed_dbg_reg_fifo(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_REG_FIFO,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_reg_fifo_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_REG_FIFO);
+}
+
+int
+qed_dbg_igu_fifo(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_IGU_FIFO,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_igu_fifo_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_IGU_FIFO);
+}
+
+static int qed_dbg_nvm_image_length(struct ecore_hwfn *p_hwfn,
+				    enum ecore_nvm_images image_id, u32 *length)
+{
+	struct ecore_nvm_image_att image_att;
+	int rc;
+
+	*length = 0;
+	rc = ecore_mcp_get_nvm_image_att(p_hwfn, image_id, &image_att);
+	if (rc)
+		return rc;
+
+	*length = image_att.length;
+
+	return rc;
+}
+
+int qed_dbg_protection_override(struct ecore_dev *edev, void *buffer,
+				u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_PROTECTION_OVERRIDE,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_protection_override_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_PROTECTION_OVERRIDE);
+}
+
+int qed_dbg_fw_asserts(struct ecore_dev *edev, void *buffer,
+		       u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_FW_ASSERTS,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_fw_asserts_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_FW_ASSERTS);
+}
+
+int qed_dbg_ilt(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_ILT, num_dumped_bytes);
+}
+
+int qed_dbg_ilt_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_ILT);
+}
+
+int qed_dbg_mcp_trace(struct ecore_dev *edev, void *buffer,
+		      u32 *num_dumped_bytes)
+{
+	return qed_dbg_feature(edev, buffer, DBG_FEATURE_MCP_TRACE,
+			       num_dumped_bytes);
+}
+
+int qed_dbg_mcp_trace_size(struct ecore_dev *edev)
+{
+	return qed_dbg_feature_size(edev, DBG_FEATURE_MCP_TRACE);
+}
+
+/* Defines the amount of bytes allocated for recording the length of debug
+ * feature buffer.
+ */
+#define REGDUMP_HEADER_SIZE			sizeof(u32)
+#define REGDUMP_HEADER_SIZE_SHIFT		0
+#define REGDUMP_HEADER_SIZE_MASK		0xffffff
+#define REGDUMP_HEADER_FEATURE_SHIFT		24
+#define REGDUMP_HEADER_FEATURE_MASK		0x3f
+#define REGDUMP_HEADER_OMIT_ENGINE_SHIFT	30
+#define REGDUMP_HEADER_OMIT_ENGINE_MASK		0x1
+#define REGDUMP_HEADER_ENGINE_SHIFT		31
+#define REGDUMP_HEADER_ENGINE_MASK		0x1
+#define REGDUMP_MAX_SIZE			0x1000000
+#define ILT_DUMP_MAX_SIZE			(1024 * 1024 * 15)
+
+enum debug_print_features {
+	OLD_MODE = 0,
+	IDLE_CHK = 1,
+	GRC_DUMP = 2,
+	MCP_TRACE = 3,
+	REG_FIFO = 4,
+	PROTECTION_OVERRIDE = 5,
+	IGU_FIFO = 6,
+	PHY = 7,
+	FW_ASSERTS = 8,
+	NVM_CFG1 = 9,
+	DEFAULT_CFG = 10,
+	NVM_META = 11,
+	MDUMP = 12,
+	ILT_DUMP = 13,
+};
+
+static u32 qed_calc_regdump_header(struct ecore_dev *edev,
+				   enum debug_print_features feature,
+				   int engine, u32 feature_size, u8 omit_engine)
+{
+	u32 res = 0;
+
+	SET_FIELD(res, REGDUMP_HEADER_SIZE, feature_size);
+	if (res != feature_size)
+		DP_NOTICE(edev, false,
+			  "Feature %d is too large (size 0x%x) and will corrupt the dump\n",
+			  feature, feature_size);
+
+	SET_FIELD(res, REGDUMP_HEADER_FEATURE, feature);
+	SET_FIELD(res, REGDUMP_HEADER_OMIT_ENGINE, omit_engine);
+	SET_FIELD(res, REGDUMP_HEADER_ENGINE, engine);
+
+	return res;
+}
+
+int qed_dbg_all_data(struct ecore_dev *edev, void *buffer)
+{
+	u8 cur_engine, omit_engine = 0, org_engine;
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
+	int grc_params[MAX_DBG_GRC_PARAMS], i;
+	u32 offset = 0, feature_size;
+	int rc;
+
+	for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
+		grc_params[i] = dev_data->grc.param_val[i];
+
+	if (!ECORE_IS_CMT(edev))
+		omit_engine = 1;
+
+	OSAL_MUTEX_ACQUIRE(&edev->dbg_lock);
+
+	org_engine = qed_get_debug_engine(edev);
+	for (cur_engine = 0; cur_engine < edev->num_hwfns; cur_engine++) {
+		/* Collect idle_chks and grcDump for each hw function */
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+			   "obtaining idle_chk and grcdump for current engine\n");
+		qed_set_debug_engine(edev, cur_engine);
+
+		/* First idle_chk */
+		rc = qed_dbg_idle_chk(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, IDLE_CHK, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_idle_chk failed. rc = %d\n", rc);
+		}
+
+		/* Second idle_chk */
+		rc = qed_dbg_idle_chk(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, IDLE_CHK, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_idle_chk failed. rc = %d\n", rc);
+		}
+
+		/* reg_fifo dump */
+		rc = qed_dbg_reg_fifo(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, REG_FIFO, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_reg_fifo failed. rc = %d\n", rc);
+		}
+
+		/* igu_fifo dump */
+		rc = qed_dbg_igu_fifo(edev, (u8 *)buffer + offset +
+				      REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, IGU_FIFO, cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_igu_fifo failed. rc = %d", rc);
+		}
+
+		/* protection_override dump */
+		rc = qed_dbg_protection_override(edev, (u8 *)buffer + offset +
+						 REGDUMP_HEADER_SIZE,
+						 &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, PROTECTION_OVERRIDE,
+						    cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev,
+			       "qed_dbg_protection_override failed. rc = %d\n",
+			       rc);
+		}
+
+		/* fw_asserts dump */
+		rc = qed_dbg_fw_asserts(edev, (u8 *)buffer + offset +
+					REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, FW_ASSERTS,
+						    cur_engine, feature_size,
+						    omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_fw_asserts failed. rc = %d\n",
+			       rc);
+		}
+
+		/* GRC dump - must be last because when mcp stuck it will
+		 * clutter idle_chk, reg_fifo, ...
+		 */
+		for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
+			dev_data->grc.param_val[i] = grc_params[i];
+
+		rc = qed_dbg_grc(edev, (u8 *)buffer + offset +
+				 REGDUMP_HEADER_SIZE, &feature_size);
+		if (!rc) {
+			*(u32 *)((u8 *)buffer + offset) =
+			    qed_calc_regdump_header(edev, GRC_DUMP,
+						    cur_engine,
+						    feature_size, omit_engine);
+			offset += (feature_size + REGDUMP_HEADER_SIZE);
+		} else {
+			DP_ERR(edev, "qed_dbg_grc failed. rc = %d", rc);
+		}
+	}
+
+	qed_set_debug_engine(edev, org_engine);
+
+	/* mcp_trace */
+	rc = qed_dbg_mcp_trace(edev, (u8 *)buffer + offset +
+			       REGDUMP_HEADER_SIZE, &feature_size);
+	if (!rc) {
+		*(u32 *)((u8 *)buffer + offset) =
+		    qed_calc_regdump_header(edev, MCP_TRACE, cur_engine,
+					    feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+	} else {
+		DP_ERR(edev, "qed_dbg_mcp_trace failed. rc = %d\n", rc);
+	}
+
+	OSAL_MUTEX_RELEASE(&edev->dbg_lock);
+
+	return 0;
+}
+
+int qed_dbg_all_data_size(struct ecore_dev *edev)
+{
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	u32 regs_len = 0, image_len = 0, ilt_len = 0, total_ilt_len = 0;
+	u8 cur_engine, org_engine;
+
+	edev->disable_ilt_dump = false;
+	org_engine = qed_get_debug_engine(edev);
+	for (cur_engine = 0; cur_engine < edev->num_hwfns; cur_engine++) {
+		/* Engine specific */
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+			   "calculating idle_chk and grcdump register length for current engine\n");
+		qed_set_debug_engine(edev, cur_engine);
+		regs_len += REGDUMP_HEADER_SIZE + qed_dbg_idle_chk_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_idle_chk_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_grc_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_reg_fifo_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_igu_fifo_size(edev) +
+			    REGDUMP_HEADER_SIZE +
+			    qed_dbg_protection_override_size(edev) +
+			    REGDUMP_HEADER_SIZE + qed_dbg_fw_asserts_size(edev);
+
+		ilt_len = REGDUMP_HEADER_SIZE + qed_dbg_ilt_size(edev);
+		if (ilt_len < ILT_DUMP_MAX_SIZE) {
+			total_ilt_len += ilt_len;
+			regs_len += ilt_len;
+		}
+	}
+
+	qed_set_debug_engine(edev, org_engine);
+
+	/* Engine common */
+	regs_len += REGDUMP_HEADER_SIZE + qed_dbg_mcp_trace_size(edev);
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_NVM_CFG1, &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_DEFAULT_CFG,
+				 &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_NVM_META, &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+	qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_MDUMP, &image_len);
+	if (image_len)
+		regs_len += REGDUMP_HEADER_SIZE + image_len;
+
+	if (regs_len > REGDUMP_MAX_SIZE) {
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+			   "Dump exceeds max size 0x%x, disable ILT dump\n",
+			   REGDUMP_MAX_SIZE);
+		edev->disable_ilt_dump = true;
+		regs_len -= total_ilt_len;
+	}
+
+	return regs_len;
+}
+
+int qed_dbg_feature(struct ecore_dev *edev, void *buffer,
+		    enum ecore_dbg_features feature, u32 *num_dumped_bytes)
+{
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	struct ecore_dbg_feature *qed_feature =
+		&edev->dbg_params.features[feature];
+	enum dbg_status dbg_rc;
+	struct ecore_ptt *p_ptt;
+	int rc = 0;
+
+	/* Acquire ptt */
+	p_ptt = ecore_ptt_acquire(p_hwfn);
+	if (!p_ptt)
+		return -EINVAL;
+
+	/* Get dump */
+	dbg_rc = qed_dbg_dump(p_hwfn, p_ptt, feature);
+	if (dbg_rc != DBG_STATUS_OK) {
+		DP_VERBOSE(edev, ECORE_MSG_DEBUG, "%s\n",
+			   qed_dbg_get_status_str(dbg_rc));
+		*num_dumped_bytes = 0;
+		rc = -EINVAL;
+		goto out;
+	}
+
+	DP_VERBOSE(edev, ECORE_MSG_DEBUG,
+		   "copying debug feature to external buffer\n");
+	memcpy(buffer, qed_feature->dump_buf, qed_feature->buf_size);
+	*num_dumped_bytes = edev->dbg_params.features[feature].dumped_dwords *
+			    4;
+
+out:
+	ecore_ptt_release(p_hwfn, p_ptt);
+	return rc;
+}
+
+int
+qed_dbg_feature_size(struct ecore_dev *edev, enum ecore_dbg_features feature)
+{
+	struct ecore_hwfn *p_hwfn =
+		&edev->hwfns[edev->dbg_params.engine_for_debug];
+	struct ecore_dbg_feature *qed_feature = &edev->dbg_features[feature];
+	struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
+	u32 buf_size_dwords;
+	enum dbg_status rc;
+
+	if (!p_ptt)
+		return -EINVAL;
+
+	rc = qed_features_lookup[feature].get_size(p_hwfn, p_ptt,
+						   &buf_size_dwords);
+	if (rc != DBG_STATUS_OK)
+		buf_size_dwords = 0;
+
+	/* Feature will not be dumped if it exceeds maximum size */
+	if (buf_size_dwords > MAX_DBG_FEATURE_SIZE_DWORDS)
+		buf_size_dwords = 0;
+
+	ecore_ptt_release(p_hwfn, p_ptt);
+	qed_feature->buf_size = buf_size_dwords * sizeof(u32);
+	return qed_feature->buf_size;
+}
+
+u8 qed_get_debug_engine(struct ecore_dev *edev)
+{
+	return edev->dbg_params.engine_for_debug;
+}
+
+void qed_set_debug_engine(struct ecore_dev *edev, int engine_number)
+{
+	DP_VERBOSE(edev, ECORE_MSG_DEBUG, "set debug engine to %d\n",
+		   engine_number);
+	edev->dbg_params.engine_for_debug = engine_number;
+}
+
+void qed_dbg_pf_init(struct ecore_dev *edev)
+{
+	const u8 *dbg_values = NULL;
+	int i;
+
+	PMD_INIT_FUNC_TRACE(edev);
+
+	OSAL_MUTEX_INIT(&edev->dbg_lock);
+
+	/* Sync ver with debugbus qed code */
+	qed_dbg_set_app_ver(TOOLS_VERSION);
+
+	/* Debug values are after init values.
+	 * The offset is the first dword of the file.
+	 */
+	/* TBD: change hardcoded value to offset from FW file */
+	dbg_values = (const u8 *)edev->firmware + 1337296;
+
+	for_each_hwfn(edev, i) {
+		qed_dbg_set_bin_ptr(&edev->hwfns[i], dbg_values);
+		qed_dbg_user_set_bin_ptr(&edev->hwfns[i], dbg_values);
+	}
+
+	/* Set the hwfn to be 0 as default */
+	edev->dbg_params.engine_for_debug = 0;
+}
+
+void qed_dbg_pf_exit(struct ecore_dev *edev)
+{
+	struct ecore_dbg_feature *feature = NULL;
+	enum ecore_dbg_features feature_idx;
+
+	PMD_INIT_FUNC_TRACE(edev);
+
+	/* debug features' buffers may be allocated if debug feature was used
+	 * but dump wasn't called
+	 */
+	for (feature_idx = 0; feature_idx < DBG_FEATURE_NUM; feature_idx++) {
+		feature = &edev->dbg_features[feature_idx];
+		if (feature->dump_buf) {
+			OSAL_VFREE(edev, feature->dump_buf);
+			feature->dump_buf = NULL;
+		}
+	}
+
+	OSAL_MUTEX_DEALLOC(&edev->dbg_lock);
+}
diff --git a/drivers/net/qede/qede_debug.h b/drivers/net/qede/qede_debug.h
new file mode 100644
index 000000000..93e1bd710
--- /dev/null
+++ b/drivers/net/qede/qede_debug.h
@@ -0,0 +1,759 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Marvell Semiconductor Inc.
+ * All rights reserved.
+ * www.marvell.com
+ */
+
+#ifndef _QED_DEBUG_H
+#define _QED_DEBUG_H
+
+/* Forward Declaration */
+struct ecore_dev;
+enum ecore_dbg_features;
+
+int qed_dbg_grc(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes);
+int qed_dbg_grc_size(struct ecore_dev *edev);
+int qed_dbg_idle_chk(struct ecore_dev *edev, void *buffer,
+		     u32 *num_dumped_bytes);
+int qed_dbg_idle_chk_size(struct ecore_dev *edev);
+int qed_dbg_reg_fifo(struct ecore_dev *edev, void *buffer,
+		     u32 *num_dumped_bytes);
+int qed_dbg_reg_fifo_size(struct ecore_dev *edev);
+int qed_dbg_igu_fifo(struct ecore_dev *edev, void *buffer,
+		     u32 *num_dumped_bytes);
+int qed_dbg_igu_fifo_size(struct ecore_dev *edev);
+int qed_dbg_protection_override(struct ecore_dev *edev, void *buffer,
+				u32 *num_dumped_bytes);
+int qed_dbg_protection_override_size(struct ecore_dev *edev);
+int qed_dbg_fw_asserts(struct ecore_dev *edev, void *buffer,
+		       u32 *num_dumped_bytes);
+int qed_dbg_fw_asserts_size(struct ecore_dev *edev);
+int qed_dbg_ilt(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes);
+int qed_dbg_ilt_size(struct ecore_dev *edev);
+int qed_dbg_mcp_trace(struct ecore_dev *edev, void *buffer,
+		      u32 *num_dumped_bytes);
+int qed_dbg_mcp_trace_size(struct ecore_dev *edev);
+int qed_dbg_all_data(struct ecore_dev *edev, void *buffer);
+int qed_dbg_all_data_size(struct ecore_dev *edev);
+u8 qed_get_debug_engine(struct ecore_dev *edev);
+void qed_set_debug_engine(struct ecore_dev *edev, int engine_number);
+int qed_dbg_feature(struct ecore_dev *edev, void *buffer,
+		    enum ecore_dbg_features feature, u32 *num_dumped_bytes);
+int
+qed_dbg_feature_size(struct ecore_dev *edev, enum ecore_dbg_features feature);
+
+void qed_dbg_pf_init(struct ecore_dev *edev);
+void qed_dbg_pf_exit(struct ecore_dev *edev);
+
+/***************************** Public Functions *******************************/
+
+/**
+ * @brief qed_dbg_set_bin_ptr - Sets a pointer to the binary data with debug
+ *	arrays.
+ *
+ * @param p_hwfn -	    HW device data
+ * @param bin_ptr - a pointer to the binary data with debug arrays.
+ */
+enum dbg_status qed_dbg_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+				    const u8 * const bin_ptr);
+
+/**
+ * @brief qed_dbg_set_app_ver - Sets the version of the calling app.
+ *
+ * The application should call this function with the TOOLS_VERSION
+ * it compiles with. Must be called before all other debug functions.
+ *
+ * @return error if one of the following holds:
+ *      - the specified app version is not supported
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_set_app_ver(u32 ver);
+
+/**
+ * @brief qed_read_regs - Reads registers into a buffer (using GRC).
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf - Destination buffer.
+ * @param addr - Source GRC address in dwords.
+ * @param len - Number of registers to read.
+ */
+void qed_read_regs(struct ecore_hwfn *p_hwfn,
+		   struct ecore_ptt *p_ptt, u32 *buf, u32 addr, u32 len);
+
+/**
+ * @brief qed_read_fw_info - Reads FW info from the chip.
+ *
+ * The FW info contains FW-related information, such as the FW version,
+ * FW image (main/L2B/kuku), FW timestamp, etc.
+ * The FW info is read from the internal RAM of the first Storm that is not in
+ * reset.
+ *
+ * @param p_hwfn -	    HW device data
+ * @param p_ptt -	    Ptt window used for writing the registers.
+ * @param fw_info -	Out: a pointer to write the FW info into.
+ *
+ * @return true if the FW info was read successfully from one of the Storms,
+ * or false if all Storms are in reset.
+ */
+bool qed_read_fw_info(struct ecore_hwfn *p_hwfn,
+		      struct ecore_ptt *p_ptt, struct fw_info *fw_info);
+/**
+ * @brief qed_dbg_grc_config - Sets the value of a GRC parameter.
+ *
+ * @param p_hwfn -	HW device data
+ * @param grc_param -	GRC parameter
+ * @param val -		Value to set.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- grc_param is invalid
+ *	- val is outside the allowed boundaries
+ */
+enum dbg_status qed_dbg_grc_config(struct ecore_hwfn *p_hwfn,
+				   enum dbg_grc_params grc_param, u32 val);
+
+/**
+ * @brief qed_dbg_grc_set_params_default - Reverts all GRC parameters to their
+ *	default value.
+ *
+ * @param p_hwfn		- HW device data
+ */
+void qed_dbg_grc_set_params_default(struct ecore_hwfn *p_hwfn);
+/**
+ * @brief qed_dbg_grc_get_dump_buf_size - Returns the required buffer size for
+ *	GRC Dump.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for the GRC Dump
+ *	data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_grc_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size);
+
+/**
+ * @brief qed_dbg_grc_dump - Dumps GRC data into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the collected GRC data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified dump buffer is too small
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_grc_dump(struct ecore_hwfn *p_hwfn,
+				 struct ecore_ptt *p_ptt,
+				 u32 *dump_buf,
+				 u32 buf_size_in_dwords,
+				 u32 *num_dumped_dwords);
+/**
+ * @brief qed_dbg_idle_chk_get_dump_buf_size - Returns the required buffer size
+ *	for idle check results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for the idle check
+ *	data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_idle_chk_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size);
+
+/**
+ * @brief qed_dbg_idle_chk_dump - Performs idle check and writes the results
+ *	into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the idle check data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_idle_chk_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_mcp_trace_get_dump_buf_size - Returns the required buffer size
+ *	for mcp trace results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for mcp trace data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the trace data in MCP scratchpad contain an invalid signature
+ *	- the bundle ID in NVRAM is invalid
+ *	- the trace meta data cannot be found (in NVRAM or image file)
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_mcp_trace_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						    struct ecore_ptt *p_ptt,
+						    u32 *buf_size);
+
+/**
+ * @brief qed_dbg_mcp_trace_dump - Performs mcp trace and writes the results
+ *	into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the mcp trace data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- the trace data in MCP scratchpad contain an invalid signature
+ *	- the bundle ID in NVRAM is invalid
+ *	- the trace meta data cannot be found (in NVRAM or image file)
+ *	- the trace meta data cannot be read (from NVRAM or image file)
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
+				       struct ecore_ptt *p_ptt,
+				       u32 *dump_buf,
+				       u32 buf_size_in_dwords,
+				       u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_reg_fifo_get_dump_buf_size - Returns the required buffer size
+ *	for grc trace fifo results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for reg fifo data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_reg_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size);
+
+/**
+ * @brief qed_dbg_reg_fifo_dump - Reads the reg fifo and writes the results into
+ *	the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the reg fifo data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- DMAE transaction failed
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_igu_fifo_get_dump_buf_size - Returns the required buffer size
+ *	for the IGU fifo results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for the IGU fifo
+ *	data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_igu_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						   struct ecore_ptt *p_ptt,
+						   u32 *buf_size);
+
+/**
+ * @brief qed_dbg_igu_fifo_dump - Reads the IGU fifo and writes the results into
+ *	the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the IGU fifo data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- DMAE transaction failed
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
+				      struct ecore_ptt *p_ptt,
+				      u32 *dump_buf,
+				      u32 buf_size_in_dwords,
+				      u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_protection_override_get_dump_buf_size - Returns the required
+ *	buffer size for protection override window results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for protection
+ *	override data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status
+qed_dbg_protection_override_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+					      struct ecore_ptt *p_ptt,
+					      u32 *buf_size);
+/**
+ * @brief qed_dbg_protection_override_dump - Reads protection override window
+ *	entries and writes the results into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the protection override data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ *	- DMAE transaction failed
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_protection_override_dump(struct ecore_hwfn *p_hwfn,
+						 struct ecore_ptt *p_ptt,
+						 u32 *dump_buf,
+						 u32 buf_size_in_dwords,
+						 u32 *num_dumped_dwords);
+/**
+ * @brief qed_dbg_fw_asserts_get_dump_buf_size - Returns the required buffer
+ *	size for FW Asserts results.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param buf_size - OUT: required buffer size (in dwords) for FW Asserts data.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_fw_asserts_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
+						     struct ecore_ptt *p_ptt,
+						     u32 *buf_size);
+/**
+ * @brief qed_dbg_fw_asserts_dump - Reads the FW Asserts and writes the results
+ *	into the specified buffer.
+ *
+ * @param p_hwfn - HW device data
+ * @param p_ptt - Ptt window used for writing the registers.
+ * @param dump_buf - Pointer to write the FW Asserts data into.
+ * @param buf_size_in_dwords - Size of the specified buffer in dwords.
+ * @param num_dumped_dwords - OUT: number of dumped dwords.
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ *	- the specified buffer is too small
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
+					struct ecore_ptt *p_ptt,
+					u32 *dump_buf,
+					u32 buf_size_in_dwords,
+					u32 *num_dumped_dwords);
+
+/**
+ * @brief qed_dbg_read_attn - Reads the attention registers of the specified
+ * block and type, and writes the results into the specified buffer.
+ *
+ * @param p_hwfn -	 HW device data
+ * @param p_ptt -	 Ptt window used for writing the registers.
+ * @param block -	 Block ID.
+ * @param attn_type -	 Attention type.
+ * @param clear_status - Indicates if the attention status should be cleared.
+ * @param results -	 OUT: Pointer to write the read results into
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_read_attn(struct ecore_hwfn *p_hwfn,
+				  struct ecore_ptt *p_ptt,
+				  enum block_id block,
+				  enum dbg_attn_type attn_type,
+				  bool clear_status,
+				  struct dbg_attn_block_result *results);
+
+/**
+ * @brief qed_dbg_print_attn - Prints attention registers values in the
+ *	specified results struct.
+ *
+ * @param p_hwfn
+ * @param results - Pointer to the attention read results
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_print_attn(struct ecore_hwfn *p_hwfn,
+				   struct dbg_attn_block_result *results);
+
+/******************************* Data Types **********************************/
+
+struct mcp_trace_format {
+	u32 data;
+#define MCP_TRACE_FORMAT_MODULE_MASK	0x0000ffff
+#define MCP_TRACE_FORMAT_MODULE_OFFSET	0
+#define MCP_TRACE_FORMAT_LEVEL_MASK	0x00030000
+#define MCP_TRACE_FORMAT_LEVEL_OFFSET	16
+#define MCP_TRACE_FORMAT_P1_SIZE_MASK	0x000c0000
+#define MCP_TRACE_FORMAT_P1_SIZE_OFFSET 18
+#define MCP_TRACE_FORMAT_P2_SIZE_MASK	0x00300000
+#define MCP_TRACE_FORMAT_P2_SIZE_OFFSET 20
+#define MCP_TRACE_FORMAT_P3_SIZE_MASK	0x00c00000
+#define MCP_TRACE_FORMAT_P3_SIZE_OFFSET 22
+#define MCP_TRACE_FORMAT_LEN_MASK	0xff000000
+#define MCP_TRACE_FORMAT_LEN_OFFSET	24
+
+	char *format_str;
+};
+
+/* MCP Trace Meta data structure */
+struct mcp_trace_meta {
+	u32 modules_num;
+	char **modules;
+	u32 formats_num;
+	struct mcp_trace_format *formats;
+	bool is_allocated;
+};
+
+/* Debug Tools user data */
+struct dbg_tools_user_data {
+	struct mcp_trace_meta mcp_trace_meta;
+	const u32 *mcp_trace_user_meta_buf;
+};
+
+/******************************** Constants **********************************/
+
+#define MAX_NAME_LEN	16
+
+/***************************** Public Functions *******************************/
+
+/**
+ * @brief qed_dbg_user_set_bin_ptr - Sets a pointer to the binary data with
+ *	debug arrays.
+ *
+ * @param p_hwfn - HW device data
+ * @param bin_ptr - a pointer to the binary data with debug arrays.
+ */
+enum dbg_status qed_dbg_user_set_bin_ptr(struct ecore_hwfn *p_hwfn,
+					 const u8 * const bin_ptr);
+
+/**
+ * @brief qed_dbg_alloc_user_data - Allocates user debug data.
+ *
+ * @param p_hwfn -		 HW device data
+ * @param user_data_ptr - OUT: a pointer to the allocated memory.
+ */
+enum dbg_status qed_dbg_alloc_user_data(struct ecore_hwfn *p_hwfn,
+					void **user_data_ptr);
+
+/**
+ * @brief qed_dbg_get_status_str - Returns a string for the specified status.
+ *
+ * @param status - a debug status code.
+ *
+ * @return a string for the specified status
+ */
+const char *qed_dbg_get_status_str(enum dbg_status status);
+
+/**
+ * @brief qed_get_idle_chk_results_buf_size - Returns the required buffer size
+ *	for idle check results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - idle check dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_idle_chk_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32  num_dumped_dwords,
+						  u32 *results_buf_size);
+/**
+ * @brief qed_print_idle_chk_results - Prints idle check results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - idle check dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the idle check results.
+ * @param num_errors - OUT: number of errors found in idle check.
+ * @param num_warnings - OUT: number of warnings found in idle check.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_idle_chk_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf,
+					   u32 *num_errors,
+					   u32 *num_warnings);
+
+/**
+ * @brief qed_dbg_mcp_trace_set_meta_data - Sets the MCP Trace meta data.
+ *
+ * Needed in case the MCP Trace dump doesn't contain the meta data (e.g. due to
+ * no NVRAM access).
+ *
+ * @param data - pointer to MCP Trace meta data
+ * @param size - size of MCP Trace meta data in dwords
+ */
+void qed_dbg_mcp_trace_set_meta_data(struct ecore_hwfn *p_hwfn,
+				     const u32 *meta_buf);
+
+/**
+ * @brief qed_get_mcp_trace_results_buf_size - Returns the required buffer size
+ *	for MCP Trace results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - MCP Trace dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_mcp_trace_results_buf_size(struct ecore_hwfn *p_hwfn,
+						   u32 *dump_buf,
+						   u32 num_dumped_dwords,
+						   u32 *results_buf_size);
+
+/**
+ * @brief qed_print_mcp_trace_results - Prints MCP Trace results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - mcp trace dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the mcp trace results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_mcp_trace_results(struct ecore_hwfn *p_hwfn,
+					    u32 *dump_buf,
+					    u32 num_dumped_dwords,
+					    char *results_buf);
+
+/**
+ * @brief qed_print_mcp_trace_results_cont - Prints MCP Trace results, and
+ * keeps the MCP trace meta data allocated, to support continuous MCP Trace
+ * parsing. After the continuous parsing ends, mcp_trace_free_meta_data should
+ * be called to free the meta data.
+ *
+ * @param p_hwfn -	      HW device data
+ * @param dump_buf -	      mcp trace dump buffer, starting from the header.
+ * @param results_buf -	      buffer for printing the mcp trace results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_mcp_trace_results_cont(struct ecore_hwfn *p_hwfn,
+						 u32 *dump_buf,
+						 char *results_buf);
+
+/**
+ * @brief print_mcp_trace_line - Prints MCP Trace results for a single line
+ *
+ * @param p_hwfn -	      HW device data
+ * @param dump_buf -	      mcp trace dump buffer, starting from the header.
+ * @param num_dumped_bytes -  number of bytes that were dumped.
+ * @param results_buf -	      buffer for printing the mcp trace results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_mcp_trace_line(struct ecore_hwfn *p_hwfn,
+					 u8 *dump_buf,
+					 u32 num_dumped_bytes,
+					 char *results_buf);
+
+/**
+ * @brief mcp_trace_free_meta_data - Frees the MCP Trace meta data.
+ * Should be called after continuous MCP Trace parsing.
+ *
+ * @param p_hwfn - HW device data
+ */
+void qed_mcp_trace_free_meta_data(struct ecore_hwfn *p_hwfn);
+
+/**
+ * @brief qed_get_reg_fifo_results_buf_size - Returns the required buffer size
+ *	for reg_fifo results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - reg fifo dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_reg_fifo_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32 num_dumped_dwords,
+						  u32 *results_buf_size);
+
+/**
+ * @brief qed_print_reg_fifo_results - Prints reg fifo results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - reg fifo dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the reg fifo results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_reg_fifo_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf);
+
+/**
+ * @brief qed_get_igu_fifo_results_buf_size - Returns the required buffer size
+ *	for igu_fifo results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - IGU fifo dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_igu_fifo_results_buf_size(struct ecore_hwfn *p_hwfn,
+						  u32 *dump_buf,
+						  u32 num_dumped_dwords,
+						  u32 *results_buf_size);
+
+/**
+ * @brief qed_print_igu_fifo_results - Prints IGU fifo results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - IGU fifo dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the IGU fifo results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_igu_fifo_results(struct ecore_hwfn *p_hwfn,
+					   u32 *dump_buf,
+					   u32 num_dumped_dwords,
+					   char *results_buf);
+
+/**
+ * @brief qed_get_protection_override_results_buf_size - Returns the required
+ *	buffer size for protection override results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - protection override dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status
+qed_get_protection_override_results_buf_size(struct ecore_hwfn *p_hwfn,
+					     u32 *dump_buf,
+					     u32 num_dumped_dwords,
+					     u32 *results_buf_size);
+
+/**
+ * @brief qed_print_protection_override_results - Prints protection override
+ *	results.
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - protection override dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the reg fifo results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_protection_override_results(struct ecore_hwfn *p_hwfn,
+						      u32 *dump_buf,
+						      u32 num_dumped_dwords,
+						      char *results_buf);
+
+/**
+ * @brief qed_get_fw_asserts_results_buf_size - Returns the required buffer size
+ *	for FW Asserts results (in bytes).
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - FW Asserts dump buffer.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf_size - OUT: required buffer size (in bytes) for the parsed
+ *	results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_get_fw_asserts_results_buf_size(struct ecore_hwfn *p_hwfn,
+						    u32 *dump_buf,
+						    u32 num_dumped_dwords,
+						    u32 *results_buf_size);
+
+/**
+ * @brief qed_print_fw_asserts_results - Prints FW Asserts results
+ *
+ * @param p_hwfn - HW device data
+ * @param dump_buf - FW Asserts dump buffer, starting from the header.
+ * @param num_dumped_dwords - number of dwords that were dumped.
+ * @param results_buf - buffer for printing the FW Asserts results.
+ *
+ * @return error if the parsing fails, ok otherwise.
+ */
+enum dbg_status qed_print_fw_asserts_results(struct ecore_hwfn *p_hwfn,
+					     u32 *dump_buf,
+					     u32 num_dumped_dwords,
+					     char *results_buf);
+
+/**
+ * @brief qed_dbg_parse_attn - Parses and prints attention registers values in
+ * the specified results struct.
+ *
+ * @param p_hwfn -  HW device data
+ * @param results - Pointer to the attention read results
+ *
+ * @return error if one of the following holds:
+ *	- the version wasn't set
+ * Otherwise, returns ok.
+ */
+enum dbg_status qed_dbg_parse_attn(struct ecore_hwfn *p_hwfn,
+				   struct dbg_attn_block_result *results);
+
+#endif
diff --git a/drivers/net/qede/qede_if.h b/drivers/net/qede/qede_if.h
index 858cd51d5..c5ae3fb2e 100644
--- a/drivers/net/qede/qede_if.h
+++ b/drivers/net/qede/qede_if.h
@@ -189,6 +189,51 @@ struct qed_common_ops {
 			      uint32_t dp_module, uint8_t dp_level);
 
 	int (*send_drv_state)(struct ecore_dev *edev, bool active);
+
+	/* ###############  DEBUG *************************/
+
+	int     (*dbg_grc)(struct ecore_dev       *edev,
+			   void		 *buffer,
+			   u32		  *num_dumped_bytes);
+	int     (*dbg_grc_size)(struct ecore_dev *edev);
+
+	int     (*dbg_idle_chk)(struct ecore_dev  *edev,
+				void	    *buffer,
+				u32	     *num_dumped_bytes);
+	int     (*dbg_idle_chk_size)(struct ecore_dev *edev);
+
+	int     (*dbg_reg_fifo)(struct ecore_dev  *edev,
+				void	    *buffer,
+				u32	     *num_dumped_bytes);
+	int     (*dbg_reg_fifo_size)(struct ecore_dev *edev);
+
+	int     (*dbg_mcp_trace)(struct ecore_dev *edev,
+				 void	   *buffer,
+				 u32	    *num_dumped_bytes);
+	int     (*dbg_mcp_trace_size)(struct ecore_dev *edev);
+
+	int	(*dbg_protection_override)(struct ecore_dev *edev, void *buffer,
+					   u32 *num_dumped_bytes);
+	int     (*dbg_protection_override_size)(struct ecore_dev *edev);
+
+	int	(*dbg_igu_fifo_size)(struct ecore_dev *edev);
+	int	(*dbg_igu_fifo)(struct ecore_dev *edev, void *buffer,
+				u32 *num_dumped_bytes);
+
+	int	(*dbg_fw_asserts)(struct ecore_dev *edev, void *buffer,
+				  u32 *num_dumped_bytes);
+
+	int	(*dbg_fw_asserts_size)(struct ecore_dev *edev);
+
+	int	(*dbg_ilt)(struct ecore_dev *edev, void *buffer,
+			   u32 *num_dumped_bytes);
+
+	int	(*dbg_ilt_size)(struct ecore_dev *edev);
+
+	u8      (*dbg_get_debug_engine)(struct ecore_dev *edev);
+	void    (*dbg_set_debug_engine)(struct ecore_dev  *edev,
+					int	     engine_number);
+
 };
 
 /* Externs */
diff --git a/drivers/net/qede/qede_main.c b/drivers/net/qede/qede_main.c
index 51aa639c6..987a6f1e1 100644
--- a/drivers/net/qede/qede_main.c
+++ b/drivers/net/qede/qede_main.c
@@ -9,6 +9,8 @@
 #include <rte_string_fns.h>
 
 #include "qede_ethdev.h"
+/* ######### DEBUG ###########*/
+#include "qede_debug.h"
 
 /* Alarm timeout. */
 #define QEDE_ALARM_TIMEOUT_US 100000
@@ -276,10 +278,15 @@ static int qed_slowpath_start(struct ecore_dev *edev,
 	qed_start_iov_task(edev);
 
 #ifdef CONFIG_ECORE_BINARY_FW
-	if (IS_PF(edev))
+	if (IS_PF(edev)) {
 		data = (const uint8_t *)edev->firmware + sizeof(u32);
+
+		/* ############### DEBUG ################## */
+		qed_dbg_pf_init(edev);
+	}
 #endif
 
+
 	/* Start the slowpath */
 	memset(&hw_init_params, 0, sizeof(hw_init_params));
 	hw_init_params.b_hw_start = true;
@@ -779,6 +786,36 @@ const struct qed_common_ops qed_common_ops_pass = {
 	INIT_STRUCT_FIELD(slowpath_stop, &qed_slowpath_stop),
 	INIT_STRUCT_FIELD(remove, &qed_remove),
 	INIT_STRUCT_FIELD(send_drv_state, &qed_send_drv_state),
+	/* ############### DEBUG ####################*/
+
+	INIT_STRUCT_FIELD(dbg_get_debug_engine, &qed_get_debug_engine),
+	INIT_STRUCT_FIELD(dbg_set_debug_engine, &qed_set_debug_engine),
+
+	INIT_STRUCT_FIELD(dbg_protection_override,
+			  &qed_dbg_protection_override),
+	INIT_STRUCT_FIELD(dbg_protection_override_size,
+			  &qed_dbg_protection_override_size),
+
+	INIT_STRUCT_FIELD(dbg_grc, &qed_dbg_grc),
+	INIT_STRUCT_FIELD(dbg_grc_size, &qed_dbg_grc_size),
+
+	INIT_STRUCT_FIELD(dbg_idle_chk, &qed_dbg_idle_chk),
+	INIT_STRUCT_FIELD(dbg_idle_chk_size, &qed_dbg_idle_chk_size),
+
+	INIT_STRUCT_FIELD(dbg_mcp_trace, &qed_dbg_mcp_trace),
+	INIT_STRUCT_FIELD(dbg_mcp_trace_size, &qed_dbg_mcp_trace_size),
+
+	INIT_STRUCT_FIELD(dbg_fw_asserts, &qed_dbg_fw_asserts),
+	INIT_STRUCT_FIELD(dbg_fw_asserts_size, &qed_dbg_fw_asserts_size),
+
+	INIT_STRUCT_FIELD(dbg_ilt, &qed_dbg_ilt),
+	INIT_STRUCT_FIELD(dbg_ilt_size, &qed_dbg_ilt_size),
+
+	INIT_STRUCT_FIELD(dbg_reg_fifo_size, &qed_dbg_reg_fifo_size),
+	INIT_STRUCT_FIELD(dbg_reg_fifo, &qed_dbg_reg_fifo),
+
+	INIT_STRUCT_FIELD(dbg_igu_fifo_size, &qed_dbg_igu_fifo_size),
+	INIT_STRUCT_FIELD(dbg_igu_fifo, &qed_dbg_igu_fifo),
 };
 
 const struct qed_eth_ops qed_eth_ops_pass = {
-- 
2.18.0


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

* [dpdk-dev] [PATCH v5 4/4] net/qede: add support for get register operation
  2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 " Rasesh Mody
                         ` (3 preceding siblings ...)
  2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 3/4] net/qede: add infrastructure " Rasesh Mody
@ 2020-07-08 22:50       ` Rasesh Mody
  2020-07-09 10:11         ` Jerin Jacob
  2020-07-09 16:32         ` Ferruh Yigit
  4 siblings, 2 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-07-08 22:50 UTC (permalink / raw)
  To: jerinj, ferruh.yigit; +Cc: Rasesh Mody, dev, GR-Everest-DPDK-Dev, Igor Russkikh

Add support for .get_reg eth_dev ops which will be used to collect the
firmware debug data.

PMD on detecting on some HW errors will collect the FW/HW Dump to a
buffer and then it will save it to a file implemented in
qede_save_fw_dump().

Dump file location and name:
Location: <RTE_SDK> or DPDK root
Name: qede_pmd_dump_mm-dd-yy_hh-mm-ss.bin

DPDK applications can initiate a debug data collection by invoking DPDK
library’s rte_eth_dev_get_reg_info() API. This API invokes .get_reg()
interface in the PMD.

PMD implementation of .get_reg() collects the FW/HW Dump, saves it to
data field of rte_dev_reg_info and passes it to the application. It’s
the responsibility of the application to save the FW/HW Dump to a file.
We recommendation using the file name format used by qede_save_fw_dump().

Signed-off-by: Rasesh Mody <rmody@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
---
 doc/guides/nics/features/qede.ini |   1 +
 drivers/net/qede/Makefile         |   1 +
 drivers/net/qede/base/bcm_osal.c  |  25 +++
 drivers/net/qede/base/bcm_osal.h  |   5 +
 drivers/net/qede/meson.build      |   1 +
 drivers/net/qede/qede_ethdev.c    |   1 +
 drivers/net/qede/qede_ethdev.h    |  25 +++
 drivers/net/qede/qede_regs.c      | 271 ++++++++++++++++++++++++++++++
 8 files changed, 330 insertions(+)
 create mode 100644 drivers/net/qede/qede_regs.c

diff --git a/doc/guides/nics/features/qede.ini b/doc/guides/nics/features/qede.ini
index 20c90e626..f8716523e 100644
--- a/doc/guides/nics/features/qede.ini
+++ b/doc/guides/nics/features/qede.ini
@@ -31,6 +31,7 @@ Packet type parsing  = Y
 Basic stats          = Y
 Extended stats       = Y
 Stats per queue      = Y
+Registers dump       = Y
 Multiprocess aware   = Y
 Linux UIO            = Y
 Linux VFIO           = Y
diff --git a/drivers/net/qede/Makefile b/drivers/net/qede/Makefile
index 3b00338ff..0e8a67b0d 100644
--- a/drivers/net/qede/Makefile
+++ b/drivers/net/qede/Makefile
@@ -104,5 +104,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_main.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_rxtx.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_filter.c
 SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_debug.c
+SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_regs.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/qede/base/bcm_osal.c b/drivers/net/qede/base/bcm_osal.c
index 45557fe3c..65837b53d 100644
--- a/drivers/net/qede/base/bcm_osal.c
+++ b/drivers/net/qede/base/bcm_osal.c
@@ -246,6 +246,28 @@ qede_get_mcp_proto_stats(struct ecore_dev *edev,
 	}
 }
 
+static void qede_hw_err_handler(void *dev, enum ecore_hw_err_type err_type)
+{
+	struct ecore_dev *edev = dev;
+
+	switch (err_type) {
+	case ECORE_HW_ERR_FAN_FAIL:
+		break;
+
+	case ECORE_HW_ERR_MFW_RESP_FAIL:
+	case ECORE_HW_ERR_HW_ATTN:
+	case ECORE_HW_ERR_DMAE_FAIL:
+	case ECORE_HW_ERR_RAMROD_FAIL:
+	case ECORE_HW_ERR_FW_ASSERT:
+		OSAL_SAVE_FW_DUMP(0); /* Using port 0 as default port_id */
+		break;
+
+	default:
+		DP_NOTICE(edev, false, "Unknown HW error [%d]\n", err_type);
+		return;
+	}
+}
+
 void
 qede_hw_err_notify(struct ecore_hwfn *p_hwfn, enum ecore_hw_err_type err_type)
 {
@@ -275,6 +297,9 @@ qede_hw_err_notify(struct ecore_hwfn *p_hwfn, enum ecore_hw_err_type err_type)
 	}
 
 	DP_ERR(p_hwfn, "HW error occurred [%s]\n", err_str);
+
+	qede_hw_err_handler(p_hwfn->p_dev, err_type);
+
 	ecore_int_attn_clr_enable(p_hwfn->p_dev, true);
 }
 
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index b4b94231b..5d4df5907 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -371,6 +371,11 @@ void qede_hw_err_notify(struct ecore_hwfn *p_hwfn,
 
 /* TODO: */
 #define OSAL_SCHEDULE_RECOVERY_HANDLER(hwfn) nothing
+
+int qede_save_fw_dump(uint8_t port_id);
+
+#define OSAL_SAVE_FW_DUMP(port_id) qede_save_fw_dump(port_id)
+
 #define OSAL_HW_ERROR_OCCURRED(hwfn, err_type) \
 	qede_hw_err_notify(hwfn, err_type)
 
diff --git a/drivers/net/qede/meson.build b/drivers/net/qede/meson.build
index 50c9fad7e..05c9bff73 100644
--- a/drivers/net/qede/meson.build
+++ b/drivers/net/qede/meson.build
@@ -10,6 +10,7 @@ sources = files(
 	'qede_main.c',
 	'qede_rxtx.c',
 	'qede_debug.c',
+	'qede_regs.c',
 )
 
 if cc.has_argument('-Wno-format-nonliteral')
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index b5d6c7c43..e5a2581dd 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -2426,6 +2426,7 @@ static const struct eth_dev_ops qede_eth_dev_ops = {
 	.udp_tunnel_port_add = qede_udp_dst_port_add,
 	.udp_tunnel_port_del = qede_udp_dst_port_del,
 	.fw_version_get = qede_fw_version_get,
+	.get_reg = qede_get_regs,
 };
 
 static const struct eth_dev_ops qede_eth_vf_dev_ops = {
diff --git a/drivers/net/qede/qede_ethdev.h b/drivers/net/qede/qede_ethdev.h
index b988a73f2..76c5dae3b 100644
--- a/drivers/net/qede/qede_ethdev.h
+++ b/drivers/net/qede/qede_ethdev.h
@@ -214,6 +214,8 @@ struct qede_tunn_params {
 	uint16_t udp_port;
 };
 
+#define QEDE_FW_DUMP_FILE_SIZE 128
+
 /*
  *  Structure to store private data for each port.
  */
@@ -252,6 +254,7 @@ struct qede_dev {
 	char drv_ver[QEDE_PMD_DRV_VER_STR_SIZE];
 	bool vport_started;
 	int vlan_offload_mask;
+	char dump_file[QEDE_FW_DUMP_FILE_SIZE];
 	void *ethdev;
 };
 
@@ -313,4 +316,26 @@ void qede_config_accept_any_vlan(struct qede_dev *qdev, bool flg);
 int qede_ucast_filter(struct rte_eth_dev *eth_dev,
 		      struct ecore_filter_ucast *ucast,
 		      bool add);
+
+#define REGDUMP_HEADER_SIZE sizeof(u32)
+#define REGDUMP_HEADER_FEATURE_SHIFT 24
+#define REGDUMP_HEADER_ENGINE_SHIFT 31
+#define REGDUMP_HEADER_OMIT_ENGINE_SHIFT 30
+
+enum debug_print_features {
+	OLD_MODE = 0,
+	IDLE_CHK = 1,
+	GRC_DUMP = 2,
+	MCP_TRACE = 3,
+	REG_FIFO = 4,
+	PROTECTION_OVERRIDE = 5,
+	IGU_FIFO = 6,
+	PHY = 7,
+	FW_ASSERTS = 8,
+};
+
+int qede_get_regs_len(struct qede_dev *qdev);
+int qede_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs);
+void qede_config_rx_mode(struct rte_eth_dev *eth_dev);
+void qed_dbg_dump(struct rte_eth_dev *eth_dev);
 #endif /* _QEDE_ETHDEV_H_ */
diff --git a/drivers/net/qede/qede_regs.c b/drivers/net/qede/qede_regs.c
new file mode 100644
index 000000000..73760bdfd
--- /dev/null
+++ b/drivers/net/qede/qede_regs.c
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Marvell Semiconductor Inc.
+ * All rights reserved.
+ * www.marvell.com
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <time.h>
+#include <rte_ethdev.h>
+#include "base/bcm_osal.h"
+#include "qede_ethdev.h"
+
+int
+qede_get_regs_len(struct qede_dev *qdev)
+{
+	struct ecore_dev *edev = &qdev->edev;
+	int cur_engine, num_of_hwfns, regs_len = 0;
+	uint8_t org_engine;
+
+	if (IS_VF(edev))
+		return 0;
+
+	if (qdev->ops && qdev->ops->common) {
+		num_of_hwfns = qdev->dev_info.common.num_hwfns;
+		org_engine = qdev->ops->common->dbg_get_debug_engine(edev);
+		for (cur_engine = 0; cur_engine < num_of_hwfns; cur_engine++) {
+			/* compute required buffer size for idle_chks and
+			 * grcDump for each hw function
+			 */
+			DP_NOTICE(edev, false,
+				"Calculating idle_chk and grcdump register length for current engine\n");
+			qdev->ops->common->dbg_set_debug_engine(edev,
+								cur_engine);
+			regs_len += REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_idle_chk_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_idle_chk_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_grc_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_reg_fifo_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_protection_override_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_igu_fifo_size(edev) +
+				REGDUMP_HEADER_SIZE +
+				qdev->ops->common->dbg_fw_asserts_size(edev);
+		}
+		/* compute required buffer size for mcp trace and add it to the
+		 * total required buffer size
+		 */
+		regs_len += REGDUMP_HEADER_SIZE +
+			    qdev->ops->common->dbg_mcp_trace_size(edev);
+
+		qdev->ops->common->dbg_set_debug_engine(edev, org_engine);
+	}
+	DP_NOTICE(edev, false, "Total length = %u\n", regs_len);
+
+	return regs_len;
+}
+
+static uint32_t
+qede_calc_regdump_header(enum debug_print_features feature, int engine,
+			 uint32_t feature_size, uint8_t omit_engine)
+{
+	/* insert the engine, feature and mode inside the header and
+	 * combine it with feature size
+	 */
+	return (feature_size | (feature << REGDUMP_HEADER_FEATURE_SHIFT) |
+		(omit_engine << REGDUMP_HEADER_OMIT_ENGINE_SHIFT) |
+		(engine << REGDUMP_HEADER_ENGINE_SHIFT));
+}
+
+int qede_get_regs(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs)
+{
+	struct qede_dev *qdev = eth_dev->data->dev_private;
+	struct ecore_dev *edev = &qdev->edev;
+	uint32_t *buffer = regs->data;
+	int cur_engine, num_of_hwfns;
+	/* '1' tells the parser to omit the engine number in the output files */
+	uint8_t omit_engine = 0;
+	uint8_t org_engine;
+	uint32_t feature_size;
+	uint32_t offset = 0;
+
+	if (IS_VF(edev))
+		return -ENOTSUP;
+
+	if (buffer == NULL) {
+		regs->length = qede_get_regs_len(qdev);
+		regs->width =  sizeof(uint32_t);
+		DP_INFO(edev, "Length %u\n", regs->length);
+		return 0;
+	}
+
+	memset(buffer, 0, regs->length);
+	num_of_hwfns = qdev->dev_info.common.num_hwfns;
+	if (num_of_hwfns == 1)
+		omit_engine = 1;
+
+	OSAL_MUTEX_ACQUIRE(&edev->dbg_lock);
+
+	org_engine = qdev->ops->common->dbg_get_debug_engine(edev);
+	for (cur_engine = 0; cur_engine < num_of_hwfns; cur_engine++) {
+		/* collect idle_chks and grcDump for each hw function */
+		DP_NOTICE(edev, false, "obtaining idle_chk and grcdump for current engine\n");
+		qdev->ops->common->dbg_set_debug_engine(edev, cur_engine);
+
+		/* first idle_chk */
+		qdev->ops->common->dbg_idle_chk(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(IDLE_CHK, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Idle Check1 feature_size %u\n",
+			  feature_size);
+
+		/* second idle_chk */
+		qdev->ops->common->dbg_idle_chk(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(IDLE_CHK, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Idle Check2 feature_size %u\n",
+			  feature_size);
+
+		/* reg_fifo dump */
+		qdev->ops->common->dbg_reg_fifo(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(REG_FIFO, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Reg fifo feature_size %u\n",
+			  feature_size);
+
+		/* igu_fifo dump */
+		qdev->ops->common->dbg_igu_fifo(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(IGU_FIFO, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "IGU fifo feature_size %u\n",
+			  feature_size);
+
+		/* protection_override dump */
+		qdev->ops->common->dbg_protection_override(edev,
+							   (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+		       qede_calc_regdump_header(PROTECTION_OVERRIDE, cur_engine,
+						feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "Protection override feature_size %u\n",
+			  feature_size);
+
+		/* fw_asserts dump */
+		qdev->ops->common->dbg_fw_asserts(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(FW_ASSERTS, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "FW assert feature_size %u\n",
+			  feature_size);
+
+		/* grc dump */
+		qdev->ops->common->dbg_grc(edev, (uint8_t *)buffer +
+			offset + REGDUMP_HEADER_SIZE, &feature_size);
+		*(uint32_t *)((uint8_t *)buffer + offset) =
+			qede_calc_regdump_header(GRC_DUMP, cur_engine,
+						 feature_size, omit_engine);
+		offset += (feature_size + REGDUMP_HEADER_SIZE);
+		DP_NOTICE(edev, false, "GRC dump feature_size %u\n",
+			  feature_size);
+	}
+
+	/* mcp_trace */
+	qdev->ops->common->dbg_mcp_trace(edev, (uint8_t *)buffer +
+		offset + REGDUMP_HEADER_SIZE, &feature_size);
+	*(uint32_t *)((uint8_t *)buffer + offset) =
+		qede_calc_regdump_header(MCP_TRACE, cur_engine, feature_size,
+					 omit_engine);
+	offset += (feature_size + REGDUMP_HEADER_SIZE);
+	DP_NOTICE(edev, false, "MCP trace feature_size %u\n", feature_size);
+
+	qdev->ops->common->dbg_set_debug_engine(edev, org_engine);
+
+	OSAL_MUTEX_RELEASE(&edev->dbg_lock);
+
+	return 0;
+}
+
+static void
+qede_set_fw_dump_file_name(struct qede_dev *qdev)
+{
+	time_t ltime;
+	struct tm *tm;
+
+	ltime = time(NULL);
+	tm = localtime(&ltime);
+	snprintf(qdev->dump_file, QEDE_FW_DUMP_FILE_SIZE,
+		 "qede_pmd_dump_%02d-%02d-%02d_%02d-%02d-%02d.bin",
+		 tm->tm_mon + 1, (int)tm->tm_mday, 1900 + tm->tm_year,
+		 tm->tm_hour, tm->tm_min, tm->tm_sec);
+}
+
+static int
+qede_write_fwdump(const char *dump_file, void *dump, size_t len)
+{
+	int err = 0;
+	FILE *f;
+	size_t bytes;
+
+	f = fopen(dump_file, "wb+");
+
+	if (!f) {
+		fprintf(stderr, "Can't open file %s: %s\n",
+			dump_file, strerror(errno));
+		return 1;
+	}
+	bytes = fwrite(dump, 1, len, f);
+	if (bytes != len) {
+		fprintf(stderr, "Can not write all of dump data bytes=%ld len=%ld\n",
+			bytes, len);
+		err = 1;
+	}
+
+	if (fclose(f)) {
+		fprintf(stderr, "Can't close file %s: %s\n",
+			dump_file, strerror(errno));
+		err = 1;
+	}
+
+	return err;
+}
+
+int
+qede_save_fw_dump(uint8_t port_id)
+{
+	struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id];
+	struct rte_dev_reg_info regs;
+	struct qede_dev *qdev = eth_dev->data->dev_private;
+	struct ecore_dev *edev = &qdev->edev;
+	int rc = 0;
+
+	if (!rte_eth_dev_is_valid_port(port_id)) {
+		DP_ERR(edev, "port %u invalid port ID", port_id);
+		return -ENODEV;
+	}
+
+	memset(&regs, 0, sizeof(regs));
+	regs.length = qede_get_regs_len(qdev);
+	regs.data = OSAL_ZALLOC(eth_dev, GFP_KERNEL, regs.length);
+	if (regs.data) {
+		qede_get_regs(eth_dev, &regs);
+		qede_set_fw_dump_file_name(qdev);
+		rc = qede_write_fwdump(qdev->dump_file, regs.data, regs.length);
+		if (!rc)
+			DP_NOTICE(edev, false, "FW dump written to %s file\n",
+				  qdev->dump_file);
+		OSAL_FREE(edev, regs.data);
+	}
+
+	return rc;
+}
-- 
2.18.0


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

* Re: [dpdk-dev] [PATCH v5 4/4] net/qede: add support for get register operation
  2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 4/4] net/qede: add support for get register operation Rasesh Mody
@ 2020-07-09 10:11         ` Jerin Jacob
  2020-07-09 16:32         ` Ferruh Yigit
  1 sibling, 0 replies; 37+ messages in thread
From: Jerin Jacob @ 2020-07-09 10:11 UTC (permalink / raw)
  To: Rasesh Mody
  Cc: Jerin Jacob, Ferruh Yigit, dpdk-dev, GR-Everest-DPDK-Dev, Igor Russkikh

On Thu, Jul 9, 2020 at 4:22 AM Rasesh Mody <rmody@marvell.com> wrote:
>
> Add support for .get_reg eth_dev ops which will be used to collect the
> firmware debug data.
>
> PMD on detecting on some HW errors will collect the FW/HW Dump to a
> buffer and then it will save it to a file implemented in
> qede_save_fw_dump().
>
> Dump file location and name:
> Location: <RTE_SDK> or DPDK root
> Name: qede_pmd_dump_mm-dd-yy_hh-mm-ss.bin
>
> DPDK applications can initiate a debug data collection by invoking DPDK
> library’s rte_eth_dev_get_reg_info() API. This API invokes .get_reg()
> interface in the PMD.
>
> PMD implementation of .get_reg() collects the FW/HW Dump, saves it to
> data field of rte_dev_reg_info and passes it to the application. It’s
> the responsibility of the application to save the FW/HW Dump to a file.
> We recommendation using the file name format used by qede_save_fw_dump().
>
> Signed-off-by: Rasesh Mody <rmody@marvell.com>
> Signed-off-by: Igor Russkikh <irusskikh@marvell.com>


Series applied to dpdk-next-net-mrvl/master. Thanks.

>  doc/guides/nics/features/qede.ini |   1 +
>  drivers/net/qede/Makefile         |   1 +
>  drivers/net/qede/base/bcm_osal.c  |  25 +++
>  drivers/net/qede/base/bcm_osal.h  |   5 +
>  drivers/net/qede/meson.build      |   1 +
>  drivers/net/qede/qede_ethdev.c    |   1 +
>  drivers/net/qede/qede_ethdev.h    |  25 +++
>  drivers/net/qede/qede_regs.c      | 271 ++++++++++++++++++++++++++++++
>  8 files changed, 330 insertions(+)
>  create mode 100644 drivers/net/qede/qede_regs.c
>
> diff --git a/doc/guides/nics/features/qede.ini b/doc/guides/nics/features/qede.ini
> index 20c90e626..f8716523e 100644
> --- a/doc/guides/nics/features/qede.ini
> +++ b/doc/guides/nics/features/qede.ini
> @@ -31,6 +31,7 @@ Packet type parsing  = Y
>  Basic stats          = Y
>  Extended stats       = Y
>  Stats per queue      = Y
> +Registers dump       = Y
>  Multiprocess aware   = Y
>  Linux UIO            = Y
>  Linux VFIO           = Y
> diff --git a/drivers/net/qede/Makefile b/drivers/net/qede/Makefile
> index 3b00338ff..0e8a67b0d 100644
> --- a/drivers/net/qede/Makefile
> +++ b/drivers/net/qede/Makefile
> @@ -104,5 +104,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_main.c
>  SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_rxtx.c
>  SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_filter.c
>  SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_debug.c
> +SRCS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede_regs.c
>
>  include $(RTE_SDK)/mk/rte.lib.mk
> diff --git a/drivers/net/qede/base/bcm_osal.c b/drivers/net/qede/base/bcm_osal.c
> index 45557fe3c..65837b53d 100644
> --- a/drivers/net/qede/base/bcm_osal.c
> +++ b/drivers/net/qede/base/bcm_osal.c
> @@ -246,6 +246,28 @@ qede_get_mcp_proto_stats(struct ecore_dev *edev,
>         }
>  }
>
> +static void qede_hw_err_handler(void *dev, enum ecore_hw_err_type err_type)
> +{
> +       struct ecore_dev *edev = dev;
> +
> +       switch (err_type) {
> +       case ECORE_HW_ERR_FAN_FAIL:
> +               break;
> +
> +       case ECORE_HW_ERR_MFW_RESP_FAIL:
> +       case ECORE_HW_ERR_HW_ATTN:
> +       case ECORE_HW_ERR_DMAE_FAIL:
> +       case ECORE_HW_ERR_RAMROD_FAIL:
> +       case ECORE_HW_ERR_FW_ASSERT:
> +               OSAL_SAVE_FW_DUMP(0); /* Using port 0 as default port_id */
> +               break;
> +
> +       default:
> +               DP_NOTICE(edev, false, "Unknown HW error [%d]\n", err_type);
> +               return;
> +       }
> +}
> +
>  void
>  qede_hw_err_notify(struct ecore_hwfn *p_hwfn, enum ecore_hw_err_type err_type)
>  {
> @@ -275,6 +297,9 @@ qede_hw_err_notify(struct ecore_hwfn *p_hwfn, enum ecore_hw_err_type err_type)
>         }
>
>         DP_ERR(p_hwfn, "HW error occurred [%s]\n", err_str);
> +
> +       qede_hw_err_handler(p_hwfn->p_dev, err_type);
> +
>         ecore_int_attn_clr_enable(p_hwfn->p_dev, true);
>  }
>
> diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
> index b4b94231b..5d4df5907 100644
> --- a/drivers/net/qede/base/bcm_osal.h
> +++ b/drivers/net/qede/base/bcm_osal.h
> @@ -371,6 +371,11 @@ void qede_hw_err_notify(struct ecore_hwfn *p_hwfn,
>
>  /* TODO: */
>  #define OSAL_SCHEDULE_RECOVERY_HANDLER(hwfn) nothing
> +
> +int qede_save_fw_dump(uint8_t port_id);
> +
> +#define OSAL_SAVE_FW_DUMP(port_id) qede_save_fw_dump(port_id)
> +
>  #define OSAL_HW_ERROR_OCCURRED(hwfn, err_type) \
>         qede_hw_err_notify(hwfn, err_type)
>
> diff --git a/drivers/net/qede/meson.build b/drivers/net/qede/meson.build
> index 50c9fad7e..05c9bff73 100644
> --- a/drivers/net/qede/meson.build
> +++ b/drivers/net/qede/meson.build
> @@ -10,6 +10,7 @@ sources = files(
>         'qede_main.c',
>         'qede_rxtx.c',
>         'qede_debug.c',
> +       'qede_regs.c',
>  )
>
>  if cc.has_argument('-Wno-format-nonliteral')
> diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
> index b5d6c7c43..e5a2581dd 100644
> --- a/drivers/net/qede/qede_ethdev.c
> +++ b/drivers/net/qede/qede_ethdev.c
> @@ -2426,6 +2426,7 @@ static const struct eth_dev_ops qede_eth_dev_ops = {
>         .udp_tunnel_port_add = qede_udp_dst_port_add,
>         .udp_tunnel_port_del = qede_udp_dst_port_del,
>         .fw_version_get = qede_fw_version_get,
> +       .get_reg = qede_get_regs,
>  };
>
>  static const struct eth_dev_ops qede_eth_vf_dev_ops = {
> diff --git a/drivers/net/qede/qede_ethdev.h b/drivers/net/qede/qede_ethdev.h
> index b988a73f2..76c5dae3b 100644
> --- a/drivers/net/qede/qede_ethdev.h
> +++ b/drivers/net/qede/qede_ethdev.h
> @@ -214,6 +214,8 @@ struct qede_tunn_params {
>         uint16_t udp_port;
>  };
>
> +#define QEDE_FW_DUMP_FILE_SIZE 128
> +
>  /*
>   *  Structure to store private data for each port.
>   */
> @@ -252,6 +254,7 @@ struct qede_dev {
>         char drv_ver[QEDE_PMD_DRV_VER_STR_SIZE];
>         bool vport_started;
>         int vlan_offload_mask;
> +       char dump_file[QEDE_FW_DUMP_FILE_SIZE];
>         void *ethdev;
>  };
>
> @@ -313,4 +316,26 @@ void qede_config_accept_any_vlan(struct qede_dev *qdev, bool flg);
>  int qede_ucast_filter(struct rte_eth_dev *eth_dev,
>                       struct ecore_filter_ucast *ucast,
>                       bool add);
> +
> +#define REGDUMP_HEADER_SIZE sizeof(u32)
> +#define REGDUMP_HEADER_FEATURE_SHIFT 24
> +#define REGDUMP_HEADER_ENGINE_SHIFT 31
> +#define REGDUMP_HEADER_OMIT_ENGINE_SHIFT 30
> +
> +enum debug_print_features {
> +       OLD_MODE = 0,
> +       IDLE_CHK = 1,
> +       GRC_DUMP = 2,
> +       MCP_TRACE = 3,
> +       REG_FIFO = 4,
> +       PROTECTION_OVERRIDE = 5,
> +       IGU_FIFO = 6,
> +       PHY = 7,
> +       FW_ASSERTS = 8,
> +};
> +
> +int qede_get_regs_len(struct qede_dev *qdev);
> +int qede_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs);
> +void qede_config_rx_mode(struct rte_eth_dev *eth_dev);
> +void qed_dbg_dump(struct rte_eth_dev *eth_dev);
>  #endif /* _QEDE_ETHDEV_H_ */
> diff --git a/drivers/net/qede/qede_regs.c b/drivers/net/qede/qede_regs.c
> new file mode 100644
> index 000000000..73760bdfd
> --- /dev/null
> +++ b/drivers/net/qede/qede_regs.c
> @@ -0,0 +1,271 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright (c) 2020 Marvell Semiconductor Inc.
> + * All rights reserved.
> + * www.marvell.com
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <fcntl.h>
> +#include <time.h>
> +#include <rte_ethdev.h>
> +#include "base/bcm_osal.h"
> +#include "qede_ethdev.h"
> +
> +int
> +qede_get_regs_len(struct qede_dev *qdev)
> +{
> +       struct ecore_dev *edev = &qdev->edev;
> +       int cur_engine, num_of_hwfns, regs_len = 0;
> +       uint8_t org_engine;
> +
> +       if (IS_VF(edev))
> +               return 0;
> +
> +       if (qdev->ops && qdev->ops->common) {
> +               num_of_hwfns = qdev->dev_info.common.num_hwfns;
> +               org_engine = qdev->ops->common->dbg_get_debug_engine(edev);
> +               for (cur_engine = 0; cur_engine < num_of_hwfns; cur_engine++) {
> +                       /* compute required buffer size for idle_chks and
> +                        * grcDump for each hw function
> +                        */
> +                       DP_NOTICE(edev, false,
> +                               "Calculating idle_chk and grcdump register length for current engine\n");
> +                       qdev->ops->common->dbg_set_debug_engine(edev,
> +                                                               cur_engine);
> +                       regs_len += REGDUMP_HEADER_SIZE +
> +                               qdev->ops->common->dbg_idle_chk_size(edev) +
> +                               REGDUMP_HEADER_SIZE +
> +                               qdev->ops->common->dbg_idle_chk_size(edev) +
> +                               REGDUMP_HEADER_SIZE +
> +                               qdev->ops->common->dbg_grc_size(edev) +
> +                               REGDUMP_HEADER_SIZE +
> +                               qdev->ops->common->dbg_reg_fifo_size(edev) +
> +                               REGDUMP_HEADER_SIZE +
> +                               qdev->ops->common->dbg_protection_override_size(edev) +
> +                               REGDUMP_HEADER_SIZE +
> +                               qdev->ops->common->dbg_igu_fifo_size(edev) +
> +                               REGDUMP_HEADER_SIZE +
> +                               qdev->ops->common->dbg_fw_asserts_size(edev);
> +               }
> +               /* compute required buffer size for mcp trace and add it to the
> +                * total required buffer size
> +                */
> +               regs_len += REGDUMP_HEADER_SIZE +
> +                           qdev->ops->common->dbg_mcp_trace_size(edev);
> +
> +               qdev->ops->common->dbg_set_debug_engine(edev, org_engine);
> +       }
> +       DP_NOTICE(edev, false, "Total length = %u\n", regs_len);
> +
> +       return regs_len;
> +}
> +
> +static uint32_t
> +qede_calc_regdump_header(enum debug_print_features feature, int engine,
> +                        uint32_t feature_size, uint8_t omit_engine)
> +{
> +       /* insert the engine, feature and mode inside the header and
> +        * combine it with feature size
> +        */
> +       return (feature_size | (feature << REGDUMP_HEADER_FEATURE_SHIFT) |
> +               (omit_engine << REGDUMP_HEADER_OMIT_ENGINE_SHIFT) |
> +               (engine << REGDUMP_HEADER_ENGINE_SHIFT));
> +}
> +
> +int qede_get_regs(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs)
> +{
> +       struct qede_dev *qdev = eth_dev->data->dev_private;
> +       struct ecore_dev *edev = &qdev->edev;
> +       uint32_t *buffer = regs->data;
> +       int cur_engine, num_of_hwfns;
> +       /* '1' tells the parser to omit the engine number in the output files */
> +       uint8_t omit_engine = 0;
> +       uint8_t org_engine;
> +       uint32_t feature_size;
> +       uint32_t offset = 0;
> +
> +       if (IS_VF(edev))
> +               return -ENOTSUP;
> +
> +       if (buffer == NULL) {
> +               regs->length = qede_get_regs_len(qdev);
> +               regs->width =  sizeof(uint32_t);
> +               DP_INFO(edev, "Length %u\n", regs->length);
> +               return 0;
> +       }
> +
> +       memset(buffer, 0, regs->length);
> +       num_of_hwfns = qdev->dev_info.common.num_hwfns;
> +       if (num_of_hwfns == 1)
> +               omit_engine = 1;
> +
> +       OSAL_MUTEX_ACQUIRE(&edev->dbg_lock);
> +
> +       org_engine = qdev->ops->common->dbg_get_debug_engine(edev);
> +       for (cur_engine = 0; cur_engine < num_of_hwfns; cur_engine++) {
> +               /* collect idle_chks and grcDump for each hw function */
> +               DP_NOTICE(edev, false, "obtaining idle_chk and grcdump for current engine\n");
> +               qdev->ops->common->dbg_set_debug_engine(edev, cur_engine);
> +
> +               /* first idle_chk */
> +               qdev->ops->common->dbg_idle_chk(edev, (uint8_t *)buffer +
> +                       offset + REGDUMP_HEADER_SIZE, &feature_size);
> +               *(uint32_t *)((uint8_t *)buffer + offset) =
> +                       qede_calc_regdump_header(IDLE_CHK, cur_engine,
> +                                                feature_size, omit_engine);
> +               offset += (feature_size + REGDUMP_HEADER_SIZE);
> +               DP_NOTICE(edev, false, "Idle Check1 feature_size %u\n",
> +                         feature_size);
> +
> +               /* second idle_chk */
> +               qdev->ops->common->dbg_idle_chk(edev, (uint8_t *)buffer +
> +                       offset + REGDUMP_HEADER_SIZE, &feature_size);
> +               *(uint32_t *)((uint8_t *)buffer + offset) =
> +                       qede_calc_regdump_header(IDLE_CHK, cur_engine,
> +                                                feature_size, omit_engine);
> +               offset += (feature_size + REGDUMP_HEADER_SIZE);
> +               DP_NOTICE(edev, false, "Idle Check2 feature_size %u\n",
> +                         feature_size);
> +
> +               /* reg_fifo dump */
> +               qdev->ops->common->dbg_reg_fifo(edev, (uint8_t *)buffer +
> +                       offset + REGDUMP_HEADER_SIZE, &feature_size);
> +               *(uint32_t *)((uint8_t *)buffer + offset) =
> +                       qede_calc_regdump_header(REG_FIFO, cur_engine,
> +                                                feature_size, omit_engine);
> +               offset += (feature_size + REGDUMP_HEADER_SIZE);
> +               DP_NOTICE(edev, false, "Reg fifo feature_size %u\n",
> +                         feature_size);
> +
> +               /* igu_fifo dump */
> +               qdev->ops->common->dbg_igu_fifo(edev, (uint8_t *)buffer +
> +                       offset + REGDUMP_HEADER_SIZE, &feature_size);
> +               *(uint32_t *)((uint8_t *)buffer + offset) =
> +                       qede_calc_regdump_header(IGU_FIFO, cur_engine,
> +                                                feature_size, omit_engine);
> +               offset += (feature_size + REGDUMP_HEADER_SIZE);
> +               DP_NOTICE(edev, false, "IGU fifo feature_size %u\n",
> +                         feature_size);
> +
> +               /* protection_override dump */
> +               qdev->ops->common->dbg_protection_override(edev,
> +                                                          (uint8_t *)buffer +
> +                       offset + REGDUMP_HEADER_SIZE, &feature_size);
> +               *(uint32_t *)((uint8_t *)buffer + offset) =
> +                      qede_calc_regdump_header(PROTECTION_OVERRIDE, cur_engine,
> +                                               feature_size, omit_engine);
> +               offset += (feature_size + REGDUMP_HEADER_SIZE);
> +               DP_NOTICE(edev, false, "Protection override feature_size %u\n",
> +                         feature_size);
> +
> +               /* fw_asserts dump */
> +               qdev->ops->common->dbg_fw_asserts(edev, (uint8_t *)buffer +
> +                       offset + REGDUMP_HEADER_SIZE, &feature_size);
> +               *(uint32_t *)((uint8_t *)buffer + offset) =
> +                       qede_calc_regdump_header(FW_ASSERTS, cur_engine,
> +                                                feature_size, omit_engine);
> +               offset += (feature_size + REGDUMP_HEADER_SIZE);
> +               DP_NOTICE(edev, false, "FW assert feature_size %u\n",
> +                         feature_size);
> +
> +               /* grc dump */
> +               qdev->ops->common->dbg_grc(edev, (uint8_t *)buffer +
> +                       offset + REGDUMP_HEADER_SIZE, &feature_size);
> +               *(uint32_t *)((uint8_t *)buffer + offset) =
> +                       qede_calc_regdump_header(GRC_DUMP, cur_engine,
> +                                                feature_size, omit_engine);
> +               offset += (feature_size + REGDUMP_HEADER_SIZE);
> +               DP_NOTICE(edev, false, "GRC dump feature_size %u\n",
> +                         feature_size);
> +       }
> +
> +       /* mcp_trace */
> +       qdev->ops->common->dbg_mcp_trace(edev, (uint8_t *)buffer +
> +               offset + REGDUMP_HEADER_SIZE, &feature_size);
> +       *(uint32_t *)((uint8_t *)buffer + offset) =
> +               qede_calc_regdump_header(MCP_TRACE, cur_engine, feature_size,
> +                                        omit_engine);
> +       offset += (feature_size + REGDUMP_HEADER_SIZE);
> +       DP_NOTICE(edev, false, "MCP trace feature_size %u\n", feature_size);
> +
> +       qdev->ops->common->dbg_set_debug_engine(edev, org_engine);
> +
> +       OSAL_MUTEX_RELEASE(&edev->dbg_lock);
> +
> +       return 0;
> +}
> +
> +static void
> +qede_set_fw_dump_file_name(struct qede_dev *qdev)
> +{
> +       time_t ltime;
> +       struct tm *tm;
> +
> +       ltime = time(NULL);
> +       tm = localtime(&ltime);
> +       snprintf(qdev->dump_file, QEDE_FW_DUMP_FILE_SIZE,
> +                "qede_pmd_dump_%02d-%02d-%02d_%02d-%02d-%02d.bin",
> +                tm->tm_mon + 1, (int)tm->tm_mday, 1900 + tm->tm_year,
> +                tm->tm_hour, tm->tm_min, tm->tm_sec);
> +}
> +
> +static int
> +qede_write_fwdump(const char *dump_file, void *dump, size_t len)
> +{
> +       int err = 0;
> +       FILE *f;
> +       size_t bytes;
> +
> +       f = fopen(dump_file, "wb+");
> +
> +       if (!f) {
> +               fprintf(stderr, "Can't open file %s: %s\n",
> +                       dump_file, strerror(errno));
> +               return 1;
> +       }
> +       bytes = fwrite(dump, 1, len, f);
> +       if (bytes != len) {
> +               fprintf(stderr, "Can not write all of dump data bytes=%ld len=%ld\n",
> +                       bytes, len);
> +               err = 1;
> +       }
> +
> +       if (fclose(f)) {
> +               fprintf(stderr, "Can't close file %s: %s\n",
> +                       dump_file, strerror(errno));
> +               err = 1;
> +       }
> +
> +       return err;
> +}
> +
> +int
> +qede_save_fw_dump(uint8_t port_id)
> +{
> +       struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id];
> +       struct rte_dev_reg_info regs;
> +       struct qede_dev *qdev = eth_dev->data->dev_private;
> +       struct ecore_dev *edev = &qdev->edev;
> +       int rc = 0;
> +
> +       if (!rte_eth_dev_is_valid_port(port_id)) {
> +               DP_ERR(edev, "port %u invalid port ID", port_id);
> +               return -ENODEV;
> +       }
> +
> +       memset(&regs, 0, sizeof(regs));
> +       regs.length = qede_get_regs_len(qdev);
> +       regs.data = OSAL_ZALLOC(eth_dev, GFP_KERNEL, regs.length);
> +       if (regs.data) {
> +               qede_get_regs(eth_dev, &regs);
> +               qede_set_fw_dump_file_name(qdev);
> +               rc = qede_write_fwdump(qdev->dump_file, regs.data, regs.length);
> +               if (!rc)
> +                       DP_NOTICE(edev, false, "FW dump written to %s file\n",
> +                                 qdev->dump_file);
> +               OSAL_FREE(edev, regs.data);
> +       }
> +
> +       return rc;
> +}
> --
> 2.18.0
>

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

* Re: [dpdk-dev] [PATCH v5 4/4] net/qede: add support for get register operation
  2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 4/4] net/qede: add support for get register operation Rasesh Mody
  2020-07-09 10:11         ` Jerin Jacob
@ 2020-07-09 16:32         ` Ferruh Yigit
  2020-07-09 23:30           ` [dpdk-dev] [EXT] " Rasesh Mody
  1 sibling, 1 reply; 37+ messages in thread
From: Ferruh Yigit @ 2020-07-09 16:32 UTC (permalink / raw)
  To: Rasesh Mody, jerinj; +Cc: dev, GR-Everest-DPDK-Dev, Igor Russkikh

On 7/8/2020 11:50 PM, Rasesh Mody wrote:
> Add support for .get_reg eth_dev ops which will be used to collect the
> firmware debug data.
> 
> PMD on detecting on some HW errors will collect the FW/HW Dump to a
> buffer and then it will save it to a file implemented in
> qede_save_fw_dump().
> 
> Dump file location and name:
> Location: <RTE_SDK> or DPDK root
> Name: qede_pmd_dump_mm-dd-yy_hh-mm-ss.bin
> 
> DPDK applications can initiate a debug data collection by invoking DPDK
> library’s rte_eth_dev_get_reg_info() API. This API invokes .get_reg()
> interface in the PMD.
> 
> PMD implementation of .get_reg() collects the FW/HW Dump, saves it to
> data field of rte_dev_reg_info and passes it to the application. It’s
> the responsibility of the application to save the FW/HW Dump to a file.
> We recommendation using the file name format used by qede_save_fw_dump().
> 
> Signed-off-by: Rasesh Mody <rmody@marvell.com>
> Signed-off-by: Igor Russkikh <irusskikh@marvell.com>

<...>

> +static int
> +qede_write_fwdump(const char *dump_file, void *dump, size_t len)
> +{
> +	int err = 0;
> +	FILE *f;
> +	size_t bytes;
> +
> +	f = fopen(dump_file, "wb+");
> +
> +	if (!f) {
> +		fprintf(stderr, "Can't open file %s: %s\n",
> +			dump_file, strerror(errno));
> +		return 1;
> +	}
> +	bytes = fwrite(dump, 1, len, f);
> +	if (bytes != len) {
> +		fprintf(stderr, "Can not write all of dump data bytes=%ld len=%ld\n",
> +			bytes, len);

Travis is giving build error on this for 32 bits [1], fixing while merging by
replacing '%ld' -> '%zd', please double check in next-net.

[1]
../drivers/net/qede/qede_regs.c: In function ‘qede_write_fwdump’:
../drivers/net/qede/qede_regs.c:229:59: error: format ‘%ld’ expects argument of
type ‘long int’, but argument 3 has type ‘size_t {aka unsigned int}’
[-Werror=format=]
   fprintf(stderr, "Can not write all of dump data bytes=%ld len=%ld\n",
                                                         ~~^
                                                         %d
../drivers/net/qede/qede_regs.c:229:67: error: format ‘%ld’ expects argument of
type ‘long int’, but argument 4 has type ‘size_t {aka unsigned int}’
[-Werror=format=]
   fprintf(stderr, "Can not write all of dump data bytes=%ld len=%ld\n",
                                                                 ~~^
                                                                 %d

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

* Re: [dpdk-dev] [PATCH v5 3/4] net/qede: add infrastructure for debug data collection
  2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 3/4] net/qede: add infrastructure " Rasesh Mody
@ 2020-07-09 16:37         ` Ferruh Yigit
  2020-07-09 23:30           ` [dpdk-dev] [EXT] " Rasesh Mody
  0 siblings, 1 reply; 37+ messages in thread
From: Ferruh Yigit @ 2020-07-09 16:37 UTC (permalink / raw)
  To: Rasesh Mody, jerinj; +Cc: dev, GR-Everest-DPDK-Dev, Igor Russkikh

On 7/8/2020 11:50 PM, Rasesh Mody wrote:
> The patch adds QEDE PMD ops and APIs to calculate the size and collect
> the debug dump for various firmware components. The patch adds new files
> qede_debug.[ch] that has all the firmware debug data collection
> infrastructure changes.
> 
> Signed-off-by: Rasesh Mody <rmody@marvell.com>
> Signed-off-by: Igor Russkikh <irusskikh@marvell.com>

<...>

> +		/* Add parsed element to parsed buffer */
> +		results_offset +=
> +		    sprintf(qed_get_buf_ptr(results_buf,
> +					    results_offset),
> +			    "raw: 0x%016lx, address: 0x%07x, access: %-5s, pf: %2d, vf: %s, port: %d, privilege: %-3s, protection: %-12s, master: %-4s, error: %s\n",
> +			    elements[i].data,
> +			    (u32)GET_FIELD(elements[i].data,
> +					   REG_FIFO_ELEMENT_ADDRESS) *
> +			    REG_FIFO_ELEMENT_ADDR_FACTOR,
> +			    s_access_strs[GET_FIELD(elements[i].data,
> +						    REG_FIFO_ELEMENT_ACCESS)],
> +			    (u32)GET_FIELD(elements[i].data,
> +					   REG_FIFO_ELEMENT_PF),
> +			    vf_str,
> +			    (u32)GET_FIELD(elements[i].data,
> +					   REG_FIFO_ELEMENT_PORT),
> +			    s_privilege_strs[GET_FIELD(elements[i].data,
> +						REG_FIFO_ELEMENT_PRIVILEGE)],
> +			    s_protection_strs[GET_FIELD(elements[i].data,
> +						REG_FIFO_ELEMENT_PROTECTION)],
> +			    s_master_strs[GET_FIELD(elements[i].data,
> +						    REG_FIFO_ELEMENT_MASTER)],
> +			    err_msg ? err_msg : "unknown error code");

Another 32 bits build error from this line [1], fixed while merging as
'0x%016lx' -> '0x%016"PRIx64"', please double check in next-net.

Also split long line.


[1]
../drivers/net/qede/qede_debug.c: In function ‘qed_parse_reg_fifo_dump’:
../drivers/net/qede/qede_debug.c:6742:21: error: format ‘%lx’ expects argument
of type ‘long unsigned int’, but argument 3 has type ‘u64 {aka long long
unsigned int}’ [-Werror=format=]
        "raw: 0x%016lx, address: 0x%07x, access: %-5s, pf: %2d, vf: %s, port:
%d, privilege: %-3s, protection: %-12s, master: %-4s, error: %s\n",
                ~~~~~^
                %016llx
        elements[i].data,
        ~~~~~~~~~~~~~~~~

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

* Re: [dpdk-dev] [EXT] Re: [PATCH v5 4/4] net/qede: add support for get register operation
  2020-07-09 16:32         ` Ferruh Yigit
@ 2020-07-09 23:30           ` Rasesh Mody
  0 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-07-09 23:30 UTC (permalink / raw)
  To: Ferruh Yigit, Jerin Jacob Kollanukkaran
  Cc: dev, GR-Everest-DPDK-Dev, Igor Russkikh

>From: Ferruh Yigit <ferruh.yigit@intel.com>
>Sent: Thursday, July 09, 2020 9:33 AM
>
>On 7/8/2020 11:50 PM, Rasesh Mody wrote:
>> Add support for .get_reg eth_dev ops which will be used to collect the
>> firmware debug data.
>>
>> PMD on detecting on some HW errors will collect the FW/HW Dump to a
>> buffer and then it will save it to a file implemented in
>> qede_save_fw_dump().
>>
>> Dump file location and name:
>> Location: <RTE_SDK> or DPDK root
>> Name: qede_pmd_dump_mm-dd-yy_hh-mm-ss.bin
>>
>> DPDK applications can initiate a debug data collection by invoking
>> DPDK library’s rte_eth_dev_get_reg_info() API. This API invokes
>> .get_reg() interface in the PMD.
>>
>> PMD implementation of .get_reg() collects the FW/HW Dump, saves it to
>> data field of rte_dev_reg_info and passes it to the application. It’s
>> the responsibility of the application to save the FW/HW Dump to a file.
>> We recommendation using the file name format used by
>qede_save_fw_dump().
>>
>> Signed-off-by: Rasesh Mody <rmody@marvell.com>
>> Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
>
><...>
>
>> +static int
>> +qede_write_fwdump(const char *dump_file, void *dump, size_t len) {
>> +	int err = 0;
>> +	FILE *f;
>> +	size_t bytes;
>> +
>> +	f = fopen(dump_file, "wb+");
>> +
>> +	if (!f) {
>> +		fprintf(stderr, "Can't open file %s: %s\n",
>> +			dump_file, strerror(errno));
>> +		return 1;
>> +	}
>> +	bytes = fwrite(dump, 1, len, f);
>> +	if (bytes != len) {
>> +		fprintf(stderr, "Can not write all of dump data bytes=%ld
>len=%ld\n",
>> +			bytes, len);
>
>Travis is giving build error on this for 32 bits [1], fixing while merging by
>replacing '%ld' -> '%zd', please double check in next-net.
>

Thanks Ferruh, change looks good.

>[1]
>../drivers/net/qede/qede_regs.c: In function ‘qede_write_fwdump’:
>../drivers/net/qede/qede_regs.c:229:59: error: format ‘%ld’ expects
>argument of type ‘long int’, but argument 3 has type ‘size_t {aka unsigned
>int}’
>[-Werror=format=]
>   fprintf(stderr, "Can not write all of dump data bytes=%ld len=%ld\n",
>                                                         ~~^
>                                                         %d
>../drivers/net/qede/qede_regs.c:229:67: error: format ‘%ld’ expects
>argument of type ‘long int’, but argument 4 has type ‘size_t {aka unsigned
>int}’
>[-Werror=format=]
>   fprintf(stderr, "Can not write all of dump data bytes=%ld len=%ld\n",
>                                                                 ~~^
>                                                                 %d


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

* Re: [dpdk-dev] [EXT] Re: [PATCH v5 3/4] net/qede: add infrastructure for debug data collection
  2020-07-09 16:37         ` Ferruh Yigit
@ 2020-07-09 23:30           ` Rasesh Mody
  0 siblings, 0 replies; 37+ messages in thread
From: Rasesh Mody @ 2020-07-09 23:30 UTC (permalink / raw)
  To: Ferruh Yigit, Jerin Jacob Kollanukkaran
  Cc: dev, GR-Everest-DPDK-Dev, Igor Russkikh

>From: Ferruh Yigit <ferruh.yigit@intel.com>
>Sent: Thursday, July 09, 2020 9:37 AM
>
>On 7/8/2020 11:50 PM, Rasesh Mody wrote:
>> The patch adds QEDE PMD ops and APIs to calculate the size and collect
>> the debug dump for various firmware components. The patch adds new
>> files qede_debug.[ch] that has all the firmware debug data collection
>> infrastructure changes.
>>
>> Signed-off-by: Rasesh Mody <rmody@marvell.com>
>> Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
>
><...>
>
>> +		/* Add parsed element to parsed buffer */
>> +		results_offset +=
>> +		    sprintf(qed_get_buf_ptr(results_buf,
>> +					    results_offset),
>> +			    "raw: 0x%016lx, address: 0x%07x, access: %-5s, pf:
>%2d, vf: %s, port: %d, privilege: %-3s, protection: %-12s, master: %-4s, error:
>%s\n",
>> +			    elements[i].data,
>> +			    (u32)GET_FIELD(elements[i].data,
>> +					   REG_FIFO_ELEMENT_ADDRESS) *
>> +			    REG_FIFO_ELEMENT_ADDR_FACTOR,
>> +			    s_access_strs[GET_FIELD(elements[i].data,
>> +
>REG_FIFO_ELEMENT_ACCESS)],
>> +			    (u32)GET_FIELD(elements[i].data,
>> +					   REG_FIFO_ELEMENT_PF),
>> +			    vf_str,
>> +			    (u32)GET_FIELD(elements[i].data,
>> +					   REG_FIFO_ELEMENT_PORT),
>> +			    s_privilege_strs[GET_FIELD(elements[i].data,
>> +
>	REG_FIFO_ELEMENT_PRIVILEGE)],
>> +			    s_protection_strs[GET_FIELD(elements[i].data,
>> +
>	REG_FIFO_ELEMENT_PROTECTION)],
>> +			    s_master_strs[GET_FIELD(elements[i].data,
>> +
>REG_FIFO_ELEMENT_MASTER)],
>> +			    err_msg ? err_msg : "unknown error code");
>
>Another 32 bits build error from this line [1], fixed while merging as '0x%016lx'
>-> '0x%016"PRIx64"', please double check in next-net.
>
>Also split long line.
>

Thanks Ferruh, change looks good.

>
>[1]
>../drivers/net/qede/qede_debug.c: In function ‘qed_parse_reg_fifo_dump’:
>../drivers/net/qede/qede_debug.c:6742:21: error: format ‘%lx’ expects
>argument of type ‘long unsigned int’, but argument 3 has type ‘u64 {aka long
>long unsigned int}’ [-Werror=format=]
>        "raw: 0x%016lx, address: 0x%07x, access: %-5s, pf: %2d, vf: %s, port:
>%d, privilege: %-3s, protection: %-12s, master: %-4s, error: %s\n",
>                ~~~~~^
>                %016llx
>        elements[i].data,
>        ~~~~~~~~~~~~~~~~


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

end of thread, other threads:[~2020-07-09 23:30 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-28  5:58 [dpdk-dev] [PATCH 0/4] net/qede: add FW debug data collection support Rasesh Mody
2020-06-28  5:58 ` [dpdk-dev] [PATCH 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
2020-06-28  5:58 ` [dpdk-dev] [PATCH 2/4] net/qede/base: add changes for debug data collection Rasesh Mody
2020-06-28  5:58 ` [dpdk-dev] [PATCH 3/4] net/qede: add infrastructure " Rasesh Mody
2020-06-28 12:29   ` Jerin Jacob
2020-06-30  7:38     ` [dpdk-dev] [EXT] " Rasesh Mody
2020-06-28  5:58 ` [dpdk-dev] [PATCH 4/4] net/qede: add support for get register operation Rasesh Mody
2020-06-28 12:23   ` Jerin Jacob
2020-06-30  7:37     ` [dpdk-dev] [EXT] " Rasesh Mody
2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 0/4] net/qede: add FW debug data collection support Rasesh Mody
2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 " Rasesh Mody
2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 " Rasesh Mody
2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 " Rasesh Mody
2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 2/4] net/qede/base: add changes for debug data collection Rasesh Mody
2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 3/4] net/qede: add infrastructure " Rasesh Mody
2020-07-09 16:37         ` Ferruh Yigit
2020-07-09 23:30           ` [dpdk-dev] [EXT] " Rasesh Mody
2020-07-08 22:50       ` [dpdk-dev] [PATCH v5 4/4] net/qede: add support for get register operation Rasesh Mody
2020-07-09 10:11         ` Jerin Jacob
2020-07-09 16:32         ` Ferruh Yigit
2020-07-09 23:30           ` [dpdk-dev] [EXT] " Rasesh Mody
2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 2/4] net/qede/base: add changes for debug data collection Rasesh Mody
2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 3/4] net/qede: add infrastructure " Rasesh Mody
2020-07-07 21:16     ` [dpdk-dev] [PATCH v4 4/4] net/qede: add support for get register operation Rasesh Mody
2020-07-08  9:29       ` Jerin Jacob
2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 2/4] net/qede/base: add changes for debug data collection Rasesh Mody
2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 3/4] net/qede: add infrastructure " Rasesh Mody
2020-07-07 20:18   ` [dpdk-dev] [PATCH v3 4/4] net/qede: add support for get register operation Rasesh Mody
2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 1/4] net/qede/base: re-arrange few structures for DDC Rasesh Mody
2020-06-30 17:47   ` Jerin Jacob
2020-07-07 21:20     ` [dpdk-dev] [EXT] " Rasesh Mody
2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 2/4] net/qede/base: add changes for debug data collection Rasesh Mody
2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 3/4] net/qede: add infrastructure " Rasesh Mody
2020-06-30  8:32 ` [dpdk-dev] [PATCH v2 4/4] net/qede: add support for get register operation Rasesh Mody

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.