dpdk/drivers/net/qede/qede_debug.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright (c) 2020 Marvell Semiconductor Inc.
   3 * All rights reserved.
   4 * www.marvell.com
   5 */
   6
   7#include <rte_common.h>
   8#include "base/bcm_osal.h"
   9#include "base/ecore.h"
  10#include "base/ecore_cxt.h"
  11#include "base/ecore_hsi_common.h"
  12#include "base/ecore_hw.h"
  13#include "base/ecore_mcp.h"
  14#include "base/reg_addr.h"
  15#include "qede_debug.h"
  16
  17/* Memory groups enum */
  18enum mem_groups {
  19        MEM_GROUP_PXP_MEM,
  20        MEM_GROUP_DMAE_MEM,
  21        MEM_GROUP_CM_MEM,
  22        MEM_GROUP_QM_MEM,
  23        MEM_GROUP_DORQ_MEM,
  24        MEM_GROUP_BRB_RAM,
  25        MEM_GROUP_BRB_MEM,
  26        MEM_GROUP_PRS_MEM,
  27        MEM_GROUP_SDM_MEM,
  28        MEM_GROUP_PBUF,
  29        MEM_GROUP_IOR,
  30        MEM_GROUP_RAM,
  31        MEM_GROUP_BTB_RAM,
  32        MEM_GROUP_RDIF_CTX,
  33        MEM_GROUP_TDIF_CTX,
  34        MEM_GROUP_CFC_MEM,
  35        MEM_GROUP_CONN_CFC_MEM,
  36        MEM_GROUP_CAU_PI,
  37        MEM_GROUP_CAU_MEM,
  38        MEM_GROUP_CAU_MEM_EXT,
  39        MEM_GROUP_PXP_ILT,
  40        MEM_GROUP_MULD_MEM,
  41        MEM_GROUP_BTB_MEM,
  42        MEM_GROUP_IGU_MEM,
  43        MEM_GROUP_IGU_MSIX,
  44        MEM_GROUP_CAU_SB,
  45        MEM_GROUP_BMB_RAM,
  46        MEM_GROUP_BMB_MEM,
  47        MEM_GROUP_TM_MEM,
  48        MEM_GROUP_TASK_CFC_MEM,
  49        MEM_GROUPS_NUM
  50};
  51
  52/* Memory groups names */
  53static const char * const s_mem_group_names[] = {
  54        "PXP_MEM",
  55        "DMAE_MEM",
  56        "CM_MEM",
  57        "QM_MEM",
  58        "DORQ_MEM",
  59        "BRB_RAM",
  60        "BRB_MEM",
  61        "PRS_MEM",
  62        "SDM_MEM",
  63        "PBUF",
  64        "IOR",
  65        "RAM",
  66        "BTB_RAM",
  67        "RDIF_CTX",
  68        "TDIF_CTX",
  69        "CFC_MEM",
  70        "CONN_CFC_MEM",
  71        "CAU_PI",
  72        "CAU_MEM",
  73        "CAU_MEM_EXT",
  74        "PXP_ILT",
  75        "MULD_MEM",
  76        "BTB_MEM",
  77        "IGU_MEM",
  78        "IGU_MSIX",
  79        "CAU_SB",
  80        "BMB_RAM",
  81        "BMB_MEM",
  82        "TM_MEM",
  83        "TASK_CFC_MEM",
  84};
  85
  86/* Idle check conditions */
  87
  88static u32 cond5(const u32 *r, const u32 *imm)
  89{
  90        return ((r[0] & imm[0]) != imm[1]) && ((r[1] & imm[2]) != imm[3]);
  91}
  92
  93static u32 cond7(const u32 *r, const u32 *imm)
  94{
  95        return ((r[0] >> imm[0]) & imm[1]) != imm[2];
  96}
  97
  98static u32 cond6(const u32 *r, const u32 *imm)
  99{
 100        return (r[0] & imm[0]) != imm[1];
 101}
 102
 103static u32 cond9(const u32 *r, const u32 *imm)
 104{
 105        return ((r[0] & imm[0]) >> imm[1]) !=
 106                (((r[0] & imm[2]) >> imm[3]) | ((r[1] & imm[4]) << imm[5]));
 107}
 108
 109static u32 cond10(const u32 *r, const u32 *imm)
 110{
 111        return ((r[0] & imm[0]) >> imm[1]) != (r[0] & imm[2]);
 112}
 113
 114static u32 cond4(const u32 *r, const u32 *imm)
 115{
 116        return (r[0] & ~imm[0]) != imm[1];
 117}
 118
 119static u32 cond0(const u32 *r, const u32 *imm)
 120{
 121        return (r[0] & ~r[1]) != imm[0];
 122}
 123
 124static u32 cond1(const u32 *r, const u32 *imm)
 125{
 126        return r[0] != imm[0];
 127}
 128
 129static u32 cond11(const u32 *r, const u32 *imm)
 130{
 131        return r[0] != r[1] && r[2] == imm[0];
 132}
 133
 134static u32 cond12(const u32 *r, const u32 *imm)
 135{
 136        return r[0] != r[1] && r[2] > imm[0];
 137}
 138
 139static u32 cond3(const u32 *r, const __rte_unused u32 *imm)
 140{
 141        return r[0] != r[1];
 142}
 143
 144static u32 cond13(const u32 *r, const u32 *imm)
 145{
 146        return r[0] & imm[0];
 147}
 148
 149static u32 cond8(const u32 *r, const u32 *imm)
 150{
 151        return r[0] < (r[1] - imm[0]);
 152}
 153
 154static u32 cond2(const u32 *r, const u32 *imm)
 155{
 156        return r[0] > imm[0];
 157}
 158
 159/* Array of Idle Check conditions */
 160static u32(*cond_arr[]) (const u32 *r, const u32 *imm) = {
 161        cond0,
 162        cond1,
 163        cond2,
 164        cond3,
 165        cond4,
 166        cond5,
 167        cond6,
 168        cond7,
 169        cond8,
 170        cond9,
 171        cond10,
 172        cond11,
 173        cond12,
 174        cond13,
 175};
 176
 177#define NUM_PHYS_BLOCKS 84
 178
 179#define NUM_DBG_RESET_REGS 8
 180
 181/******************************* Data Types **********************************/
 182
 183enum hw_types {
 184        HW_TYPE_ASIC,
 185        PLATFORM_RESERVED,
 186        PLATFORM_RESERVED2,
 187        PLATFORM_RESERVED3,
 188        PLATFORM_RESERVED4,
 189        MAX_HW_TYPES
 190};
 191
 192/* CM context types */
 193enum cm_ctx_types {
 194        CM_CTX_CONN_AG,
 195        CM_CTX_CONN_ST,
 196        CM_CTX_TASK_AG,
 197        CM_CTX_TASK_ST,
 198        NUM_CM_CTX_TYPES
 199};
 200
 201/* Debug bus frame modes */
 202enum dbg_bus_frame_modes {
 203        DBG_BUS_FRAME_MODE_4ST = 0,     /* 4 Storm dwords (no HW) */
 204        DBG_BUS_FRAME_MODE_2ST_2HW = 1, /* 2 Storm dwords, 2 HW dwords */
 205        DBG_BUS_FRAME_MODE_1ST_3HW = 2, /* 1 Storm dwords, 3 HW dwords */
 206        DBG_BUS_FRAME_MODE_4HW = 3,     /* 4 HW dwords (no Storms) */
 207        DBG_BUS_FRAME_MODE_8HW = 4,     /* 8 HW dwords (no Storms) */
 208        DBG_BUS_NUM_FRAME_MODES
 209};
 210
 211/* Chip constant definitions */
 212struct chip_defs {
 213        const char *name;
 214        u32 num_ilt_pages;
 215};
 216
 217/* HW type constant definitions */
 218struct hw_type_defs {
 219        const char *name;
 220        u32 delay_factor;
 221        u32 dmae_thresh;
 222        u32 log_thresh;
 223};
 224
 225/* RBC reset definitions */
 226struct rbc_reset_defs {
 227        u32 reset_reg_addr;
 228        u32 reset_val[MAX_CHIP_IDS];
 229};
 230
 231/* Storm constant definitions.
 232 * Addresses are in bytes, sizes are in quad-regs.
 233 */
 234struct storm_defs {
 235        char letter;
 236        enum block_id sem_block_id;
 237        enum dbg_bus_clients dbg_client_id[MAX_CHIP_IDS];
 238        bool has_vfc;
 239        u32 sem_fast_mem_addr;
 240        u32 sem_frame_mode_addr;
 241        u32 sem_slow_enable_addr;
 242        u32 sem_slow_mode_addr;
 243        u32 sem_slow_mode1_conf_addr;
 244        u32 sem_sync_dbg_empty_addr;
 245        u32 sem_gpre_vect_addr;
 246        u32 cm_ctx_wr_addr;
 247        u32 cm_ctx_rd_addr[NUM_CM_CTX_TYPES];
 248        u32 cm_ctx_lid_sizes[MAX_CHIP_IDS][NUM_CM_CTX_TYPES];
 249};
 250
 251/* Debug Bus Constraint operation constant definitions */
 252struct dbg_bus_constraint_op_defs {
 253        u8 hw_op_val;
 254        bool is_cyclic;
 255};
 256
 257/* Storm Mode definitions */
 258struct storm_mode_defs {
 259        const char *name;
 260        bool is_fast_dbg;
 261        u8 id_in_hw;
 262        u32 src_disable_reg_addr;
 263        u32 src_enable_val;
 264        bool exists[MAX_CHIP_IDS];
 265};
 266
 267struct grc_param_defs {
 268        u32 default_val[MAX_CHIP_IDS];
 269        u32 min;
 270        u32 max;
 271        bool is_preset;
 272        bool is_persistent;
 273        u32 exclude_all_preset_val;
 274        u32 crash_preset_val[MAX_CHIP_IDS];
 275};
 276
 277/* Address is in 128b units. Width is in bits. */
 278struct rss_mem_defs {
 279        const char *mem_name;
 280        const char *type_name;
 281        u32 addr;
 282        u32 entry_width;
 283        u32 num_entries[MAX_CHIP_IDS];
 284};
 285
 286struct vfc_ram_defs {
 287        const char *mem_name;
 288        const char *type_name;
 289        u32 base_row;
 290        u32 num_rows;
 291};
 292
 293struct big_ram_defs {
 294        const char *instance_name;
 295        enum mem_groups mem_group_id;
 296        enum mem_groups ram_mem_group_id;
 297        enum dbg_grc_params grc_param;
 298        u32 addr_reg_addr;
 299        u32 data_reg_addr;
 300        u32 is_256b_reg_addr;
 301        u32 is_256b_bit_offset[MAX_CHIP_IDS];
 302        u32 ram_size[MAX_CHIP_IDS]; /* In dwords */
 303};
 304
 305struct phy_defs {
 306        const char *phy_name;
 307
 308        /* PHY base GRC address */
 309        u32 base_addr;
 310
 311        /* Relative address of indirect TBUS address register (bits 0..7) */
 312        u32 tbus_addr_lo_addr;
 313
 314        /* Relative address of indirect TBUS address register (bits 8..10) */
 315        u32 tbus_addr_hi_addr;
 316
 317        /* Relative address of indirect TBUS data register (bits 0..7) */
 318        u32 tbus_data_lo_addr;
 319
 320        /* Relative address of indirect TBUS data register (bits 8..11) */
 321        u32 tbus_data_hi_addr;
 322};
 323
 324/* Split type definitions */
 325struct split_type_defs {
 326        const char *name;
 327};
 328
 329/******************************** Constants **********************************/
 330
 331#define BYTES_IN_DWORD                  sizeof(u32)
 332/* In the macros below, size and offset are specified in bits */
 333#define CEIL_DWORDS(size)               DIV_ROUND_UP(size, 32)
 334#define FIELD_BIT_OFFSET(type, field)   type ## _ ## field ## _ ## OFFSET
 335#define FIELD_BIT_SIZE(type, field)     type ## _ ## field ## _ ## SIZE
 336#define FIELD_DWORD_OFFSET(type, field) \
 337         (int)(FIELD_BIT_OFFSET(type, field) / 32)
 338#define FIELD_DWORD_SHIFT(type, field)  (FIELD_BIT_OFFSET(type, field) % 32)
 339#define FIELD_BIT_MASK(type, field) \
 340        (((1 << FIELD_BIT_SIZE(type, field)) - 1) << \
 341         FIELD_DWORD_SHIFT(type, field))
 342
 343#define SET_VAR_FIELD(var, type, field, val) \
 344        do { \
 345                var[FIELD_DWORD_OFFSET(type, field)] &= \
 346                (~FIELD_BIT_MASK(type, field)); \
 347                var[FIELD_DWORD_OFFSET(type, field)] |= \
 348                (val) << FIELD_DWORD_SHIFT(type, field); \
 349        } while (0)
 350
 351#define ARR_REG_WR(dev, ptt, addr, arr, arr_size) \
 352        do { \
 353                for (i = 0; i < (arr_size); i++) \
 354                        ecore_wr(dev, ptt, addr,        (arr)[i]); \
 355        } while (0)
 356
 357#define DWORDS_TO_BYTES(dwords)         ((dwords) * BYTES_IN_DWORD)
 358#define BYTES_TO_DWORDS(bytes)          ((bytes) / BYTES_IN_DWORD)
 359
 360/* extra lines include a signature line + optional latency events line */
 361#define NUM_EXTRA_DBG_LINES(block) \
 362        (GET_FIELD((block)->flags, DBG_BLOCK_CHIP_HAS_LATENCY_EVENTS) ? 2 : 1)
 363#define NUM_DBG_LINES(block) \
 364        ((block)->num_of_dbg_bus_lines + NUM_EXTRA_DBG_LINES(block))
 365
 366#define USE_DMAE                        true
 367#define PROTECT_WIDE_BUS                true
 368
 369#define RAM_LINES_TO_DWORDS(lines)      ((lines) * 2)
 370#define RAM_LINES_TO_BYTES(lines) \
 371        DWORDS_TO_BYTES(RAM_LINES_TO_DWORDS(lines))
 372
 373#define REG_DUMP_LEN_SHIFT              24
 374#define MEM_DUMP_ENTRY_SIZE_DWORDS \
 375        BYTES_TO_DWORDS(sizeof(struct dbg_dump_mem))
 376
 377#define IDLE_CHK_RULE_SIZE_DWORDS \
 378        BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_rule))
 379
 380#define IDLE_CHK_RESULT_HDR_DWORDS \
 381        BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_result_hdr))
 382
 383#define IDLE_CHK_RESULT_REG_HDR_DWORDS \
 384        BYTES_TO_DWORDS(sizeof(struct dbg_idle_chk_result_reg_hdr))
 385
 386#define PAGE_MEM_DESC_SIZE_DWORDS \
 387        BYTES_TO_DWORDS(sizeof(struct phys_mem_desc))
 388
 389#define IDLE_CHK_MAX_ENTRIES_SIZE       32
 390
 391/* The sizes and offsets below are specified in bits */
 392#define VFC_CAM_CMD_STRUCT_SIZE         64
 393#define VFC_CAM_CMD_ROW_OFFSET          48
 394#define VFC_CAM_CMD_ROW_SIZE            9
 395#define VFC_CAM_ADDR_STRUCT_SIZE        16
 396#define VFC_CAM_ADDR_OP_OFFSET          0
 397#define VFC_CAM_ADDR_OP_SIZE            4
 398#define VFC_CAM_RESP_STRUCT_SIZE        256
 399#define VFC_RAM_ADDR_STRUCT_SIZE        16
 400#define VFC_RAM_ADDR_OP_OFFSET          0
 401#define VFC_RAM_ADDR_OP_SIZE            2
 402#define VFC_RAM_ADDR_ROW_OFFSET         2
 403#define VFC_RAM_ADDR_ROW_SIZE           10
 404#define VFC_RAM_RESP_STRUCT_SIZE        256
 405
 406#define VFC_CAM_CMD_DWORDS              CEIL_DWORDS(VFC_CAM_CMD_STRUCT_SIZE)
 407#define VFC_CAM_ADDR_DWORDS             CEIL_DWORDS(VFC_CAM_ADDR_STRUCT_SIZE)
 408#define VFC_CAM_RESP_DWORDS             CEIL_DWORDS(VFC_CAM_RESP_STRUCT_SIZE)
 409#define VFC_RAM_CMD_DWORDS              VFC_CAM_CMD_DWORDS
 410#define VFC_RAM_ADDR_DWORDS             CEIL_DWORDS(VFC_RAM_ADDR_STRUCT_SIZE)
 411#define VFC_RAM_RESP_DWORDS             CEIL_DWORDS(VFC_RAM_RESP_STRUCT_SIZE)
 412
 413#define NUM_VFC_RAM_TYPES               4
 414
 415#define VFC_CAM_NUM_ROWS                512
 416
 417#define VFC_OPCODE_CAM_RD               14
 418#define VFC_OPCODE_RAM_RD               0
 419
 420#define NUM_RSS_MEM_TYPES               5
 421
 422#define NUM_BIG_RAM_TYPES               3
 423#define BIG_RAM_NAME_LEN                3
 424
 425#define NUM_PHY_TBUS_ADDRESSES          2048
 426#define PHY_DUMP_SIZE_DWORDS            (NUM_PHY_TBUS_ADDRESSES / 2)
 427
 428#define RESET_REG_UNRESET_OFFSET        4
 429
 430#define STALL_DELAY_MS                  500
 431
 432#define STATIC_DEBUG_LINE_DWORDS        9
 433
 434#define NUM_COMMON_GLOBAL_PARAMS        11
 435
 436#define MAX_RECURSION_DEPTH             10
 437
 438#define FW_IMG_MAIN                     1
 439
 440#define REG_FIFO_ELEMENT_DWORDS         2
 441#define REG_FIFO_DEPTH_ELEMENTS         32
 442#define REG_FIFO_DEPTH_DWORDS \
 443        (REG_FIFO_ELEMENT_DWORDS * REG_FIFO_DEPTH_ELEMENTS)
 444
 445#define IGU_FIFO_ELEMENT_DWORDS         4
 446#define IGU_FIFO_DEPTH_ELEMENTS         64
 447#define IGU_FIFO_DEPTH_DWORDS \
 448        (IGU_FIFO_ELEMENT_DWORDS * IGU_FIFO_DEPTH_ELEMENTS)
 449
 450#define PROTECTION_OVERRIDE_ELEMENT_DWORDS      2
 451#define PROTECTION_OVERRIDE_DEPTH_ELEMENTS      20
 452#define PROTECTION_OVERRIDE_DEPTH_DWORDS \
 453        (PROTECTION_OVERRIDE_DEPTH_ELEMENTS * \
 454         PROTECTION_OVERRIDE_ELEMENT_DWORDS)
 455
 456#define MCP_SPAD_TRACE_OFFSIZE_ADDR \
 457        (MCP_REG_SCRATCH + \
 458         offsetof(struct static_init, sections[SPAD_SECTION_TRACE]))
 459
 460#define MAX_SW_PLTAFORM_STR_SIZE        64
 461
 462#define EMPTY_FW_VERSION_STR            "???_???_???_???"
 463#define EMPTY_FW_IMAGE_STR              "???????????????"
 464
 465/***************************** Constant Arrays *******************************/
 466
 467/* Chip constant definitions array */
 468static struct chip_defs s_chip_defs[MAX_CHIP_IDS] = {
 469        {"bb", PSWRQ2_REG_ILT_MEMORY_SIZE_BB / 2},
 470        {"ah", PSWRQ2_REG_ILT_MEMORY_SIZE_K2 / 2}
 471};
 472
 473/* Storm constant definitions array */
 474static struct storm_defs s_storm_defs[] = {
 475        /* Tstorm */
 476        {'T', BLOCK_TSEM,
 477                {DBG_BUS_CLIENT_RBCT, DBG_BUS_CLIENT_RBCT},
 478                true,
 479                TSEM_REG_FAST_MEMORY,
 480                TSEM_REG_DBG_FRAME_MODE, TSEM_REG_SLOW_DBG_ACTIVE,
 481                TSEM_REG_SLOW_DBG_MODE, TSEM_REG_DBG_MODE1_CFG,
 482                TSEM_REG_SYNC_DBG_EMPTY, TSEM_REG_DBG_GPRE_VECT,
 483                TCM_REG_CTX_RBC_ACCS,
 484                {TCM_REG_AGG_CON_CTX, TCM_REG_SM_CON_CTX, TCM_REG_AGG_TASK_CTX,
 485                 TCM_REG_SM_TASK_CTX},
 486                {{4, 16, 2, 4}, {4, 16, 2, 4} } /* {bb} {k2} */
 487        },
 488
 489        /* Mstorm */
 490        {'M', BLOCK_MSEM,
 491                {DBG_BUS_CLIENT_RBCT, DBG_BUS_CLIENT_RBCM},
 492                false,
 493                MSEM_REG_FAST_MEMORY,
 494                MSEM_REG_DBG_FRAME_MODE,
 495                MSEM_REG_SLOW_DBG_ACTIVE,
 496                MSEM_REG_SLOW_DBG_MODE,
 497                MSEM_REG_DBG_MODE1_CFG,
 498                MSEM_REG_SYNC_DBG_EMPTY,
 499                MSEM_REG_DBG_GPRE_VECT,
 500                MCM_REG_CTX_RBC_ACCS,
 501                {MCM_REG_AGG_CON_CTX, MCM_REG_SM_CON_CTX, MCM_REG_AGG_TASK_CTX,
 502                 MCM_REG_SM_TASK_CTX },
 503                {{1, 10, 2, 7}, {1, 10, 2, 7} } /* {bb} {k2}*/
 504        },
 505
 506        /* Ustorm */
 507        {'U', BLOCK_USEM,
 508                {DBG_BUS_CLIENT_RBCU, DBG_BUS_CLIENT_RBCU},
 509                false,
 510                USEM_REG_FAST_MEMORY,
 511                USEM_REG_DBG_FRAME_MODE,
 512                USEM_REG_SLOW_DBG_ACTIVE,
 513                USEM_REG_SLOW_DBG_MODE,
 514                USEM_REG_DBG_MODE1_CFG,
 515                USEM_REG_SYNC_DBG_EMPTY,
 516                USEM_REG_DBG_GPRE_VECT,
 517                UCM_REG_CTX_RBC_ACCS,
 518                {UCM_REG_AGG_CON_CTX, UCM_REG_SM_CON_CTX, UCM_REG_AGG_TASK_CTX,
 519                 UCM_REG_SM_TASK_CTX},
 520                {{2, 13, 3, 3}, {2, 13, 3, 3} } /* {bb} {k2} */
 521        },
 522
 523        /* Xstorm */
 524        {'X', BLOCK_XSEM,
 525                {DBG_BUS_CLIENT_RBCX, DBG_BUS_CLIENT_RBCX},
 526                false,
 527                XSEM_REG_FAST_MEMORY,
 528                XSEM_REG_DBG_FRAME_MODE,
 529                XSEM_REG_SLOW_DBG_ACTIVE,
 530                XSEM_REG_SLOW_DBG_MODE,
 531                XSEM_REG_DBG_MODE1_CFG,
 532                XSEM_REG_SYNC_DBG_EMPTY,
 533                XSEM_REG_DBG_GPRE_VECT,
 534                XCM_REG_CTX_RBC_ACCS,
 535                {XCM_REG_AGG_CON_CTX, XCM_REG_SM_CON_CTX, 0, 0},
 536                {{9, 15, 0, 0}, {9, 15, 0, 0} } /* {bb} {k2} */
 537        },
 538
 539        /* Ystorm */
 540        {'Y', BLOCK_YSEM,
 541                {DBG_BUS_CLIENT_RBCX, DBG_BUS_CLIENT_RBCY},
 542                false,
 543                YSEM_REG_FAST_MEMORY,
 544                YSEM_REG_DBG_FRAME_MODE,
 545                YSEM_REG_SLOW_DBG_ACTIVE,
 546                YSEM_REG_SLOW_DBG_MODE,
 547                YSEM_REG_DBG_MODE1_CFG,
 548                YSEM_REG_SYNC_DBG_EMPTY,
 549                YSEM_REG_DBG_GPRE_VECT,
 550                YCM_REG_CTX_RBC_ACCS,
 551                {YCM_REG_AGG_CON_CTX, YCM_REG_SM_CON_CTX, YCM_REG_AGG_TASK_CTX,
 552                 YCM_REG_SM_TASK_CTX},
 553                {{2, 3, 2, 12}, {2, 3, 2, 12} } /* {bb} {k2} */
 554        },
 555
 556        /* Pstorm */
 557        {'P', BLOCK_PSEM,
 558                {DBG_BUS_CLIENT_RBCS, DBG_BUS_CLIENT_RBCS},
 559                true,
 560                PSEM_REG_FAST_MEMORY,
 561                PSEM_REG_DBG_FRAME_MODE,
 562                PSEM_REG_SLOW_DBG_ACTIVE,
 563                PSEM_REG_SLOW_DBG_MODE,
 564                PSEM_REG_DBG_MODE1_CFG,
 565                PSEM_REG_SYNC_DBG_EMPTY,
 566                PSEM_REG_DBG_GPRE_VECT,
 567                PCM_REG_CTX_RBC_ACCS,
 568                {0, PCM_REG_SM_CON_CTX, 0, 0},
 569                {{0, 10, 0, 0}, {0, 10, 0, 0} } /* {bb} {k2} */
 570        },
 571};
 572
 573static struct hw_type_defs s_hw_type_defs[] = {
 574        /* HW_TYPE_ASIC */
 575        {"asic", 1, 256, 32768},
 576        {"reserved", 0, 0, 0},
 577        {"reserved2", 0, 0, 0},
 578        {"reserved3", 0, 0, 0}
 579};
 580
 581static struct grc_param_defs s_grc_param_defs[] = {
 582        /* DBG_GRC_PARAM_DUMP_TSTORM */
 583        {{1, 1}, 0, 1, false, false, 1, {1, 1} },
 584
 585        /* DBG_GRC_PARAM_DUMP_MSTORM */
 586        {{1, 1}, 0, 1, false, false, 1, {1, 1} },
 587
 588        /* DBG_GRC_PARAM_DUMP_USTORM */
 589        {{1, 1}, 0, 1, false, false, 1, {1, 1} },
 590
 591        /* DBG_GRC_PARAM_DUMP_XSTORM */
 592        {{1, 1}, 0, 1, false, false, 1, {1, 1} },
 593
 594        /* DBG_GRC_PARAM_DUMP_YSTORM */
 595        {{1, 1}, 0, 1, false, false, 1, {1, 1} },
 596
 597        /* DBG_GRC_PARAM_DUMP_PSTORM */
 598        {{1, 1}, 0, 1, false, false, 1, {1, 1} },
 599
 600        /* DBG_GRC_PARAM_DUMP_REGS */
 601        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 602
 603        /* DBG_GRC_PARAM_DUMP_RAM */
 604        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 605
 606        /* DBG_GRC_PARAM_DUMP_PBUF */
 607        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 608
 609        /* DBG_GRC_PARAM_DUMP_IOR */
 610        {{0, 0}, 0, 1, false, false, 0, {1, 1} },
 611
 612        /* DBG_GRC_PARAM_DUMP_VFC */
 613        {{0, 0}, 0, 1, false, false, 0, {1, 1} },
 614
 615        /* DBG_GRC_PARAM_DUMP_CM_CTX */
 616        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 617
 618        /* DBG_GRC_PARAM_DUMP_ILT */
 619        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 620
 621        /* DBG_GRC_PARAM_DUMP_RSS */
 622        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 623
 624        /* DBG_GRC_PARAM_DUMP_CAU */
 625        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 626
 627        /* DBG_GRC_PARAM_DUMP_QM */
 628        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 629
 630        /* DBG_GRC_PARAM_DUMP_MCP */
 631        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 632
 633        /* DBG_GRC_PARAM_DUMP_DORQ */
 634        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 635
 636        /* DBG_GRC_PARAM_DUMP_CFC */
 637        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 638
 639        /* DBG_GRC_PARAM_DUMP_IGU */
 640        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 641
 642        /* DBG_GRC_PARAM_DUMP_BRB */
 643        {{0, 0}, 0, 1, false, false, 0, {1, 1} },
 644
 645        /* DBG_GRC_PARAM_DUMP_BTB */
 646        {{0, 0}, 0, 1, false, false, 0, {1, 1} },
 647
 648        /* DBG_GRC_PARAM_DUMP_BMB */
 649        {{0, 0}, 0, 1, false, false, 0, {0, 0} },
 650
 651        /* DBG_GRC_PARAM_RESERVED1 */
 652        {{0, 0}, 0, 1, false, false, 0, {0, 0} },
 653
 654        /* DBG_GRC_PARAM_DUMP_MULD */
 655        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 656
 657        /* DBG_GRC_PARAM_DUMP_PRS */
 658        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 659
 660        /* DBG_GRC_PARAM_DUMP_DMAE */
 661        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 662
 663        /* DBG_GRC_PARAM_DUMP_TM */
 664        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 665
 666        /* DBG_GRC_PARAM_DUMP_SDM */
 667        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 668
 669        /* DBG_GRC_PARAM_DUMP_DIF */
 670        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 671
 672        /* DBG_GRC_PARAM_DUMP_STATIC */
 673        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 674
 675        /* DBG_GRC_PARAM_UNSTALL */
 676        {{0, 0}, 0, 1, false, false, 0, {0, 0} },
 677
 678        /* DBG_GRC_PARAM_RESERVED2 */
 679        {{0, 0}, 0, 1, false, false, 0, {0, 0} },
 680
 681        /* DBG_GRC_PARAM_MCP_TRACE_META_SIZE */
 682        {{0, 0}, 1, 0xffffffff, false, true, 0, {0, 0} },
 683
 684        /* DBG_GRC_PARAM_EXCLUDE_ALL */
 685        {{0, 0}, 0, 1, true, false, 0, {0, 0} },
 686
 687        /* DBG_GRC_PARAM_CRASH */
 688        {{0, 0}, 0, 1, true, false, 0, {0, 0} },
 689
 690        /* DBG_GRC_PARAM_PARITY_SAFE */
 691        {{0, 0}, 0, 1, false, false, 0, {0, 0} },
 692
 693        /* DBG_GRC_PARAM_DUMP_CM */
 694        {{1, 1}, 0, 1, false, false, 0, {1, 1} },
 695
 696        /* DBG_GRC_PARAM_DUMP_PHY */
 697        {{0, 0}, 0, 1, false, false, 0, {0, 0} },
 698
 699        /* DBG_GRC_PARAM_NO_MCP */
 700        {{0, 0}, 0, 1, false, false, 0, {0, 0} },
 701
 702        /* DBG_GRC_PARAM_NO_FW_VER */
 703        {{0, 0}, 0, 1, false, false, 0, {0, 0} },
 704
 705        /* DBG_GRC_PARAM_RESERVED3 */
 706        {{0, 0}, 0, 1, false, false, 0, {0, 0} },
 707
 708        /* DBG_GRC_PARAM_DUMP_MCP_HW_DUMP */
 709        {{0, 1}, 0, 1, false, false, 0, {0, 1} },
 710
 711        /* DBG_GRC_PARAM_DUMP_ILT_CDUC */
 712        {{1, 1}, 0, 1, false, false, 0, {0, 0} },
 713
 714        /* DBG_GRC_PARAM_DUMP_ILT_CDUT */
 715        {{1, 1}, 0, 1, false, false, 0, {0, 0} },
 716
 717        /* DBG_GRC_PARAM_DUMP_CAU_EXT */
 718        {{0, 0}, 0, 1, false, false, 0, {1, 1} }
 719};
 720
 721static struct rss_mem_defs s_rss_mem_defs[] = {
 722        {"rss_mem_cid", "rss_cid", 0, 32,
 723         {256, 320} },
 724
 725        {"rss_mem_key_msb", "rss_key", 1024, 256,
 726         {128, 208} },
 727
 728        {"rss_mem_key_lsb", "rss_key", 2048, 64,
 729         {128, 208} },
 730
 731        {"rss_mem_info", "rss_info", 3072, 16,
 732         {128, 208} },
 733
 734        {"rss_mem_ind", "rss_ind", 4096, 16,
 735         {16384, 26624} }
 736};
 737
 738static struct vfc_ram_defs s_vfc_ram_defs[] = {
 739        {"vfc_ram_tt1", "vfc_ram", 0, 512},
 740        {"vfc_ram_mtt2", "vfc_ram", 512, 128},
 741        {"vfc_ram_stt2", "vfc_ram", 640, 32},
 742        {"vfc_ram_ro_vect", "vfc_ram", 672, 32}
 743};
 744
 745static struct big_ram_defs s_big_ram_defs[] = {
 746        {"BRB", MEM_GROUP_BRB_MEM, MEM_GROUP_BRB_RAM, DBG_GRC_PARAM_DUMP_BRB,
 747         BRB_REG_BIG_RAM_ADDRESS, BRB_REG_BIG_RAM_DATA,
 748         MISC_REG_BLOCK_256B_EN, {0, 0},
 749         {153600, 180224} },
 750
 751        {"BTB", MEM_GROUP_BTB_MEM, MEM_GROUP_BTB_RAM, DBG_GRC_PARAM_DUMP_BTB,
 752         BTB_REG_BIG_RAM_ADDRESS, BTB_REG_BIG_RAM_DATA,
 753         MISC_REG_BLOCK_256B_EN, {0, 1},
 754         {92160, 117760} },
 755
 756        {"BMB", MEM_GROUP_BMB_MEM, MEM_GROUP_BMB_RAM, DBG_GRC_PARAM_DUMP_BMB,
 757         BMB_REG_BIG_RAM_ADDRESS, BMB_REG_BIG_RAM_DATA,
 758         MISCS_REG_BLOCK_256B_EN, {0, 0},
 759         {36864, 36864} }
 760};
 761
 762static struct rbc_reset_defs s_rbc_reset_defs[] = {
 763        {MISCS_REG_RESET_PL_HV,
 764         {0x0, 0x400} },
 765        {MISC_REG_RESET_PL_PDA_VMAIN_1,
 766         {0x4404040, 0x4404040} },
 767        {MISC_REG_RESET_PL_PDA_VMAIN_2,
 768         {0x7, 0x7c00007} },
 769        {MISC_REG_RESET_PL_PDA_VAUX,
 770         {0x2, 0x2} },
 771};
 772
 773static struct phy_defs s_phy_defs[] = {
 774        {"nw_phy", NWS_REG_NWS_CMU_K2,
 775         PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_7_0_K2,
 776         PHY_NW_IP_REG_PHY0_TOP_TBUS_ADDR_15_8_K2,
 777         PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_7_0_K2,
 778         PHY_NW_IP_REG_PHY0_TOP_TBUS_DATA_11_8_K2},
 779        {"sgmii_phy", MS_REG_MS_CMU_K2,
 780         PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X132_K2,
 781         PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X133_K2,
 782         PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X130_K2,
 783         PHY_SGMII_IP_REG_AHB_CMU_CSR_0_X131_K2},
 784        {"pcie_phy0", PHY_PCIE_REG_PHY0_K2,
 785         PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2,
 786         PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2,
 787         PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2,
 788         PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2},
 789        {"pcie_phy1", PHY_PCIE_REG_PHY1_K2,
 790         PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X132_K2,
 791         PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X133_K2,
 792         PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X130_K2,
 793         PHY_PCIE_IP_REG_AHB_CMU_CSR_0_X131_K2},
 794};
 795
 796static struct split_type_defs s_split_type_defs[] = {
 797        /* SPLIT_TYPE_NONE */
 798        {"eng"},
 799
 800        /* SPLIT_TYPE_PORT */
 801        {"port"},
 802
 803        /* SPLIT_TYPE_PF */
 804        {"pf"},
 805
 806        /* SPLIT_TYPE_PORT_PF */
 807        {"port"},
 808
 809        /* SPLIT_TYPE_VF */
 810        {"vf"}
 811};
 812
 813/******************************** Variables *********************************/
 814
 815/**
 816 * The version of the calling app
 817 */
 818static u32 s_app_ver;
 819
 820/**************************** Private Functions ******************************/
 821
 822/* Reads and returns a single dword from the specified unaligned buffer */
 823static u32 qed_read_unaligned_dword(u8 *buf)
 824{
 825        u32 dword;
 826
 827        memcpy((u8 *)&dword, buf, sizeof(dword));
 828        return dword;
 829}
 830
 831/* Sets the value of the specified GRC param */
 832static void qed_grc_set_param(struct ecore_hwfn *p_hwfn,
 833                              enum dbg_grc_params grc_param, u32 val)
 834{
 835        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
 836
 837        dev_data->grc.param_val[grc_param] = val;
 838}
 839
 840/* Returns the value of the specified GRC param */
 841static u32 qed_grc_get_param(struct ecore_hwfn *p_hwfn,
 842                             enum dbg_grc_params grc_param)
 843{
 844        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
 845
 846        return dev_data->grc.param_val[grc_param];
 847}
 848
 849/* Initializes the GRC parameters */
 850static void qed_dbg_grc_init_params(struct ecore_hwfn *p_hwfn)
 851{
 852        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
 853
 854        if (!dev_data->grc.params_initialized) {
 855                qed_dbg_grc_set_params_default(p_hwfn);
 856                dev_data->grc.params_initialized = 1;
 857        }
 858}
 859
 860/* Sets pointer and size for the specified binary buffer type */
 861static void qed_set_dbg_bin_buf(struct ecore_hwfn *p_hwfn,
 862                                enum bin_dbg_buffer_type buf_type,
 863                                const u32 *ptr, u32 size)
 864{
 865        struct virt_mem_desc *buf = &p_hwfn->dbg_arrays[buf_type];
 866
 867        buf->ptr = (void *)(osal_uintptr_t)ptr;
 868        buf->size = size;
 869}
 870
 871/* Initializes debug data for the specified device */
 872static enum dbg_status qed_dbg_dev_init(struct ecore_hwfn *p_hwfn)
 873{
 874        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
 875        u8 num_pfs = 0, max_pfs_per_port = 0;
 876
 877        if (dev_data->initialized)
 878                return DBG_STATUS_OK;
 879
 880        /* Set chip */
 881        if (ECORE_IS_K2(p_hwfn->p_dev)) {
 882                dev_data->chip_id = CHIP_K2;
 883                dev_data->mode_enable[MODE_K2] = 1;
 884                dev_data->num_vfs = MAX_NUM_VFS_K2;
 885                num_pfs = MAX_NUM_PFS_K2;
 886                max_pfs_per_port = MAX_NUM_PFS_K2 / 2;
 887        } else if (ECORE_IS_BB_B0(p_hwfn->p_dev)) {
 888                dev_data->chip_id = CHIP_BB;
 889                dev_data->mode_enable[MODE_BB] = 1;
 890                dev_data->num_vfs = MAX_NUM_VFS_BB;
 891                num_pfs = MAX_NUM_PFS_BB;
 892                max_pfs_per_port = MAX_NUM_PFS_BB;
 893        } else {
 894                return DBG_STATUS_UNKNOWN_CHIP;
 895        }
 896
 897        /* Set HW type */
 898        dev_data->hw_type = HW_TYPE_ASIC;
 899        dev_data->mode_enable[MODE_ASIC] = 1;
 900
 901        /* Set port mode */
 902        switch (p_hwfn->p_dev->num_ports_in_engine) {
 903        case 1:
 904                dev_data->mode_enable[MODE_PORTS_PER_ENG_1] = 1;
 905                break;
 906        case 2:
 907                dev_data->mode_enable[MODE_PORTS_PER_ENG_2] = 1;
 908                break;
 909        case 4:
 910                dev_data->mode_enable[MODE_PORTS_PER_ENG_4] = 1;
 911                break;
 912        }
 913
 914        /* Set 100G mode */
 915        if (ECORE_IS_CMT(p_hwfn->p_dev))
 916                dev_data->mode_enable[MODE_100G] = 1;
 917
 918        /* Set number of ports */
 919        if (dev_data->mode_enable[MODE_PORTS_PER_ENG_1] ||
 920            dev_data->mode_enable[MODE_100G])
 921                dev_data->num_ports = 1;
 922        else if (dev_data->mode_enable[MODE_PORTS_PER_ENG_2])
 923                dev_data->num_ports = 2;
 924        else if (dev_data->mode_enable[MODE_PORTS_PER_ENG_4])
 925                dev_data->num_ports = 4;
 926
 927        /* Set number of PFs per port */
 928        dev_data->num_pfs_per_port = OSAL_MIN_T(u32,
 929                                                num_pfs / dev_data->num_ports,
 930                                                max_pfs_per_port);
 931
 932        /* Initializes the GRC parameters */
 933        qed_dbg_grc_init_params(p_hwfn);
 934
 935        dev_data->use_dmae = true;
 936        dev_data->initialized = 1;
 937
 938        return DBG_STATUS_OK;
 939}
 940
 941static const struct dbg_block *get_dbg_block(struct ecore_hwfn *p_hwfn,
 942                                             enum block_id block_id)
 943{
 944        const struct dbg_block *dbg_block;
 945
 946        dbg_block = p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS].ptr;
 947        return dbg_block + block_id;
 948}
 949
 950static const struct dbg_block_chip *qed_get_dbg_block_per_chip(struct ecore_hwfn
 951                                                               *p_hwfn,
 952                                                               enum block_id
 953                                                               block_id)
 954{
 955        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
 956
 957        return (const struct dbg_block_chip *)
 958            p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS_CHIP_DATA].ptr +
 959            block_id * MAX_CHIP_IDS + dev_data->chip_id;
 960}
 961
 962static const struct dbg_reset_reg *qed_get_dbg_reset_reg(struct ecore_hwfn
 963                                                         *p_hwfn,
 964                                                         u8 reset_reg_id)
 965{
 966        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
 967
 968        return (const struct dbg_reset_reg *)
 969            p_hwfn->dbg_arrays[BIN_BUF_DBG_RESET_REGS].ptr +
 970            reset_reg_id * MAX_CHIP_IDS + dev_data->chip_id;
 971}
 972
 973/* Reads the FW info structure for the specified Storm from the chip,
 974 * and writes it to the specified fw_info pointer.
 975 */
 976static void qed_read_storm_fw_info(struct ecore_hwfn *p_hwfn,
 977                                   struct ecore_ptt *p_ptt,
 978                                   u8 storm_id, struct fw_info *fw_info)
 979{
 980        struct storm_defs *storm = &s_storm_defs[storm_id];
 981        struct fw_info_location fw_info_location;
 982        u32 addr, i, *dest;
 983
 984        memset(&fw_info_location, 0, sizeof(fw_info_location));
 985        memset(fw_info, 0, sizeof(*fw_info));
 986
 987        /* Read first the address that points to fw_info location.
 988         * The address is located in the last line of the Storm RAM.
 989         */
 990        addr = storm->sem_fast_mem_addr + SEM_FAST_REG_INT_RAM +
 991            DWORDS_TO_BYTES(SEM_FAST_REG_INT_RAM_SIZE) -
 992            sizeof(fw_info_location);
 993
 994        dest = (u32 *)&fw_info_location;
 995
 996        for (i = 0; i < BYTES_TO_DWORDS(sizeof(fw_info_location));
 997             i++, addr += BYTES_IN_DWORD)
 998                dest[i] = ecore_rd(p_hwfn, p_ptt, addr);
 999
1000        /* Read FW version info from Storm RAM */
1001        if (fw_info_location.size > 0 && fw_info_location.size <=
1002            sizeof(*fw_info)) {
1003                addr = fw_info_location.grc_addr;
1004                dest = (u32 *)fw_info;
1005                for (i = 0; i < BYTES_TO_DWORDS(fw_info_location.size);
1006                     i++, addr += BYTES_IN_DWORD)
1007                        dest[i] = ecore_rd(p_hwfn, p_ptt, addr);
1008        }
1009}
1010
1011/* Dumps the specified string to the specified buffer.
1012 * Returns the dumped size in bytes.
1013 */
1014static u32 qed_dump_str(char *dump_buf, bool dump, const char *str)
1015{
1016        if (dump)
1017                strcpy(dump_buf, str);
1018
1019        return (u32)strlen(str) + 1;
1020}
1021
1022/* Dumps zeros to align the specified buffer to dwords.
1023 * Returns the dumped size in bytes.
1024 */
1025static u32 qed_dump_align(char *dump_buf, bool dump, u32 byte_offset)
1026{
1027        u8 offset_in_dword, align_size;
1028
1029        offset_in_dword = (u8)(byte_offset & 0x3);
1030        align_size = offset_in_dword ? BYTES_IN_DWORD - offset_in_dword : 0;
1031
1032        if (dump && align_size)
1033                memset(dump_buf, 0, align_size);
1034
1035        return align_size;
1036}
1037
1038/* Writes the specified string param to the specified buffer.
1039 * Returns the dumped size in dwords.
1040 */
1041static u32 qed_dump_str_param(u32 *dump_buf,
1042                              bool dump,
1043                              const char *param_name, const char *param_val)
1044{
1045        char *char_buf = (char *)dump_buf;
1046        u32 offset = 0;
1047
1048        /* Dump param name */
1049        offset += qed_dump_str(char_buf + offset, dump, param_name);
1050
1051        /* Indicate a string param value */
1052        if (dump)
1053                *(char_buf + offset) = 1;
1054        offset++;
1055
1056        /* Dump param value */
1057        offset += qed_dump_str(char_buf + offset, dump, param_val);
1058
1059        /* Align buffer to next dword */
1060        offset += qed_dump_align(char_buf + offset, dump, offset);
1061
1062        return BYTES_TO_DWORDS(offset);
1063}
1064
1065/* Writes the specified numeric param to the specified buffer.
1066 * Returns the dumped size in dwords.
1067 */
1068static u32 qed_dump_num_param(u32 *dump_buf,
1069                              bool dump, const char *param_name, u32 param_val)
1070{
1071        char *char_buf = (char *)dump_buf;
1072        u32 offset = 0;
1073
1074        /* Dump param name */
1075        offset += qed_dump_str(char_buf + offset, dump, param_name);
1076
1077        /* Indicate a numeric param value */
1078        if (dump)
1079                *(char_buf + offset) = 0;
1080        offset++;
1081
1082        /* Align buffer to next dword */
1083        offset += qed_dump_align(char_buf + offset, dump, offset);
1084
1085        /* Dump param value (and change offset from bytes to dwords) */
1086        offset = BYTES_TO_DWORDS(offset);
1087        if (dump)
1088                *(dump_buf + offset) = param_val;
1089        offset++;
1090
1091        return offset;
1092}
1093
1094/* Reads the FW version and writes it as a param to the specified buffer.
1095 * Returns the dumped size in dwords.
1096 */
1097static u32 qed_dump_fw_ver_param(struct ecore_hwfn *p_hwfn,
1098                                 struct ecore_ptt *p_ptt,
1099                                 u32 *dump_buf, bool dump)
1100{
1101        char fw_ver_str[16] = EMPTY_FW_VERSION_STR;
1102        char fw_img_str[16] = EMPTY_FW_IMAGE_STR;
1103        struct fw_info fw_info = { {0}, {0} };
1104        u32 offset = 0;
1105
1106        if (dump && !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_FW_VER)) {
1107                /* Read FW info from chip */
1108                qed_read_fw_info(p_hwfn, p_ptt, &fw_info);
1109
1110                /* Create FW version/image strings */
1111                if (snprintf(fw_ver_str, sizeof(fw_ver_str),
1112                             "%d_%d_%d_%d", fw_info.ver.num.major,
1113                             fw_info.ver.num.minor, fw_info.ver.num.rev,
1114                             fw_info.ver.num.eng) < 0)
1115                        DP_NOTICE(p_hwfn, false,
1116                                  "Unexpected debug error: invalid FW version string\n");
1117                switch (fw_info.ver.image_id) {
1118                case FW_IMG_MAIN:
1119                        strcpy(fw_img_str, "main");
1120                        break;
1121                default:
1122                        strcpy(fw_img_str, "unknown");
1123                        break;
1124                }
1125        }
1126
1127        /* Dump FW version, image and timestamp */
1128        offset += qed_dump_str_param(dump_buf + offset,
1129                                     dump, "fw-version", fw_ver_str);
1130        offset += qed_dump_str_param(dump_buf + offset,
1131                                     dump, "fw-image", fw_img_str);
1132        offset += qed_dump_num_param(dump_buf + offset,
1133                                     dump,
1134                                     "fw-timestamp", fw_info.ver.timestamp);
1135
1136        return offset;
1137}
1138
1139/* Reads the MFW version and writes it as a param to the specified buffer.
1140 * Returns the dumped size in dwords.
1141 */
1142static u32 qed_dump_mfw_ver_param(struct ecore_hwfn *p_hwfn,
1143                                  struct ecore_ptt *p_ptt,
1144                                  u32 *dump_buf, bool dump)
1145{
1146        char mfw_ver_str[16] = EMPTY_FW_VERSION_STR;
1147
1148        if (dump &&
1149            !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_FW_VER)) {
1150                u32 global_section_offsize, global_section_addr, mfw_ver;
1151                u32 public_data_addr, global_section_offsize_addr;
1152
1153                /* Find MCP public data GRC address. Needs to be ORed with
1154                 * MCP_REG_SCRATCH due to a HW bug.
1155                 */
1156                public_data_addr = ecore_rd(p_hwfn,
1157                                          p_ptt,
1158                                          MISC_REG_SHARED_MEM_ADDR) |
1159                                   MCP_REG_SCRATCH;
1160
1161                /* Find MCP public global section offset */
1162                global_section_offsize_addr = public_data_addr +
1163                                              offsetof(struct mcp_public_data,
1164                                                       sections) +
1165                                              sizeof(offsize_t) * PUBLIC_GLOBAL;
1166                global_section_offsize = ecore_rd(p_hwfn, p_ptt,
1167                                                global_section_offsize_addr);
1168                global_section_addr =
1169                        MCP_REG_SCRATCH +
1170                        (global_section_offsize & OFFSIZE_OFFSET_MASK) * 4;
1171
1172                /* Read MFW version from MCP public global section */
1173                mfw_ver = ecore_rd(p_hwfn, p_ptt,
1174                                 global_section_addr +
1175                                 offsetof(struct public_global, mfw_ver));
1176
1177                /* Dump MFW version param */
1178                if (snprintf(mfw_ver_str, sizeof(mfw_ver_str), "%d_%d_%d_%d",
1179                             (u8)(mfw_ver >> 24), (u8)(mfw_ver >> 16),
1180                             (u8)(mfw_ver >> 8), (u8)mfw_ver) < 0)
1181                        DP_NOTICE(p_hwfn, false,
1182                                  "Unexpected debug error: invalid MFW version string\n");
1183        }
1184
1185        return qed_dump_str_param(dump_buf, dump, "mfw-version", mfw_ver_str);
1186}
1187
1188/* Reads the chip revision from the chip and writes it as a param to the
1189 * specified buffer. Returns the dumped size in dwords.
1190 */
1191static u32 qed_dump_chip_revision_param(struct ecore_hwfn *p_hwfn,
1192                                        struct ecore_ptt *p_ptt,
1193                                        u32 *dump_buf, bool dump)
1194{
1195        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
1196        char param_str[3] = "??";
1197
1198        if (dev_data->hw_type == HW_TYPE_ASIC) {
1199                u32 chip_rev, chip_metal;
1200
1201                chip_rev = ecore_rd(p_hwfn, p_ptt, MISCS_REG_CHIP_REV);
1202                chip_metal = ecore_rd(p_hwfn, p_ptt, MISCS_REG_CHIP_METAL);
1203
1204                param_str[0] = 'a' + (u8)chip_rev;
1205                param_str[1] = '0' + (u8)chip_metal;
1206        }
1207
1208        return qed_dump_str_param(dump_buf, dump, "chip-revision", param_str);
1209}
1210
1211/* Writes a section header to the specified buffer.
1212 * Returns the dumped size in dwords.
1213 */
1214static u32 qed_dump_section_hdr(u32 *dump_buf,
1215                                bool dump, const char *name, u32 num_params)
1216{
1217        return qed_dump_num_param(dump_buf, dump, name, num_params);
1218}
1219
1220/* Writes the common global params to the specified buffer.
1221 * Returns the dumped size in dwords.
1222 */
1223static u32 qed_dump_common_global_params(struct ecore_hwfn *p_hwfn,
1224                                         struct ecore_ptt *p_ptt,
1225                                         u32 *dump_buf,
1226                                         bool dump,
1227                                         u8 num_specific_global_params)
1228{
1229        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
1230        char sw_platform_str[MAX_SW_PLTAFORM_STR_SIZE];
1231        u32 offset = 0;
1232        u8 num_params;
1233
1234        /* Fill platform string */
1235        ecore_set_platform_str(p_hwfn, sw_platform_str,
1236                               MAX_SW_PLTAFORM_STR_SIZE);
1237
1238        /* Dump global params section header */
1239        num_params = NUM_COMMON_GLOBAL_PARAMS + num_specific_global_params +
1240                (dev_data->chip_id == CHIP_BB ? 1 : 0);
1241        offset += qed_dump_section_hdr(dump_buf + offset,
1242                                       dump, "global_params", num_params);
1243
1244        /* Store params */
1245        offset += qed_dump_fw_ver_param(p_hwfn, p_ptt, dump_buf + offset, dump);
1246        offset += qed_dump_mfw_ver_param(p_hwfn,
1247                                         p_ptt, dump_buf + offset, dump);
1248        offset += qed_dump_chip_revision_param(p_hwfn,
1249                                               p_ptt, dump_buf + offset, dump);
1250        offset += qed_dump_num_param(dump_buf + offset,
1251                                     dump, "tools-version", TOOLS_VERSION);
1252        offset += qed_dump_str_param(dump_buf + offset,
1253                                     dump,
1254                                     "chip",
1255                                     s_chip_defs[dev_data->chip_id].name);
1256        offset += qed_dump_str_param(dump_buf + offset,
1257                                     dump,
1258                                     "platform",
1259                                     s_hw_type_defs[dev_data->hw_type].name);
1260        offset += qed_dump_str_param(dump_buf + offset,
1261                                     dump, "sw-platform", sw_platform_str);
1262        offset += qed_dump_num_param(dump_buf + offset,
1263                                     dump, "pci-func", p_hwfn->abs_pf_id);
1264        offset += qed_dump_num_param(dump_buf + offset,
1265                                     dump, "epoch", OSAL_GET_EPOCH(p_hwfn));
1266        if (dev_data->chip_id == CHIP_BB)
1267                offset += qed_dump_num_param(dump_buf + offset,
1268                                             dump, "path",
1269                                             ECORE_PATH_ID(p_hwfn));
1270
1271        return offset;
1272}
1273
1274/* Writes the "last" section (including CRC) to the specified buffer at the
1275 * given offset. Returns the dumped size in dwords.
1276 */
1277static u32 qed_dump_last_section(u32 *dump_buf, u32 offset, bool dump)
1278{
1279        u32 start_offset = offset;
1280
1281        /* Dump CRC section header */
1282        offset += qed_dump_section_hdr(dump_buf + offset, dump, "last", 0);
1283
1284        /* Calculate CRC32 and add it to the dword after the "last" section */
1285        if (dump)
1286                *(dump_buf + offset) = ~OSAL_CRC32(0xffffffff,
1287                                              (u8 *)dump_buf,
1288                                              DWORDS_TO_BYTES(offset));
1289
1290        offset++;
1291
1292        return offset - start_offset;
1293}
1294
1295/* Update blocks reset state  */
1296static void qed_update_blocks_reset_state(struct ecore_hwfn *p_hwfn,
1297                                          struct ecore_ptt *p_ptt)
1298{
1299        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
1300        u32 reg_val[NUM_DBG_RESET_REGS] = { 0 };
1301        u8 rst_reg_id;
1302        u32 blk_id;
1303
1304        /* Read reset registers */
1305        for (rst_reg_id = 0; rst_reg_id < NUM_DBG_RESET_REGS; rst_reg_id++) {
1306                const struct dbg_reset_reg *rst_reg;
1307                bool rst_reg_removed;
1308                u32 rst_reg_addr;
1309
1310                rst_reg = qed_get_dbg_reset_reg(p_hwfn, rst_reg_id);
1311                rst_reg_removed = GET_FIELD(rst_reg->data,
1312                                            DBG_RESET_REG_IS_REMOVED);
1313                rst_reg_addr = DWORDS_TO_BYTES(GET_FIELD(rst_reg->data,
1314                                                         DBG_RESET_REG_ADDR));
1315
1316                if (!rst_reg_removed)
1317                        reg_val[rst_reg_id] = ecore_rd(p_hwfn, p_ptt,
1318                                                     rst_reg_addr);
1319        }
1320
1321        /* Check if blocks are in reset */
1322        for (blk_id = 0; blk_id < NUM_PHYS_BLOCKS; blk_id++) {
1323                const struct dbg_block_chip *blk;
1324                bool has_rst_reg;
1325                bool is_removed;
1326
1327                blk = qed_get_dbg_block_per_chip(p_hwfn, (enum block_id)blk_id);
1328                is_removed = GET_FIELD(blk->flags, DBG_BLOCK_CHIP_IS_REMOVED);
1329                has_rst_reg = GET_FIELD(blk->flags,
1330                                        DBG_BLOCK_CHIP_HAS_RESET_REG);
1331
1332                if (!is_removed && has_rst_reg)
1333                        dev_data->block_in_reset[blk_id] =
1334                            !(reg_val[blk->reset_reg_id] &
1335                              OSAL_BIT(blk->reset_reg_bit_offset));
1336        }
1337}
1338
1339/* is_mode_match recursive function */
1340static bool qed_is_mode_match_rec(struct ecore_hwfn *p_hwfn,
1341                                  u16 *modes_buf_offset, u8 rec_depth)
1342{
1343        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
1344        const u8 *dbg_array;
1345        bool arg1, arg2;
1346        u8 tree_val;
1347
1348        if (rec_depth > MAX_RECURSION_DEPTH) {
1349                DP_NOTICE(p_hwfn, false,
1350                          "Unexpected error: is_mode_match_rec exceeded the max recursion depth. This is probably due to a corrupt init/debug buffer.\n");
1351                return false;
1352        }
1353
1354        /* Get next element from modes tree buffer */
1355        dbg_array = p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr;
1356        tree_val = dbg_array[(*modes_buf_offset)++];
1357
1358        switch (tree_val) {
1359        case INIT_MODE_OP_NOT:
1360                return !qed_is_mode_match_rec(p_hwfn,
1361                                              modes_buf_offset, rec_depth + 1);
1362        case INIT_MODE_OP_OR:
1363        case INIT_MODE_OP_AND:
1364                arg1 = qed_is_mode_match_rec(p_hwfn,
1365                                             modes_buf_offset, rec_depth + 1);
1366                arg2 = qed_is_mode_match_rec(p_hwfn,
1367                                             modes_buf_offset, rec_depth + 1);
1368                return (tree_val == INIT_MODE_OP_OR) ? (arg1 ||
1369                                                        arg2) : (arg1 && arg2);
1370        default:
1371                return dev_data->mode_enable[tree_val - MAX_INIT_MODE_OPS] > 0;
1372        }
1373}
1374
1375/* Returns true if the mode (specified using modes_buf_offset) is enabled */
1376static bool qed_is_mode_match(struct ecore_hwfn *p_hwfn, u16 *modes_buf_offset)
1377{
1378        return qed_is_mode_match_rec(p_hwfn, modes_buf_offset, 0);
1379}
1380
1381/* Enable / disable the Debug block */
1382static void qed_bus_enable_dbg_block(struct ecore_hwfn *p_hwfn,
1383                                     struct ecore_ptt *p_ptt, bool enable)
1384{
1385        ecore_wr(p_hwfn, p_ptt, DBG_REG_DBG_BLOCK_ON, enable ? 1 : 0);
1386}
1387
1388/* Resets the Debug block */
1389static void qed_bus_reset_dbg_block(struct ecore_hwfn *p_hwfn,
1390                                    struct ecore_ptt *p_ptt)
1391{
1392        u32 reset_reg_addr, old_reset_reg_val, new_reset_reg_val;
1393        const struct dbg_reset_reg *reset_reg;
1394        const struct dbg_block_chip *block;
1395
1396        block = qed_get_dbg_block_per_chip(p_hwfn, BLOCK_DBG);
1397        reset_reg = qed_get_dbg_reset_reg(p_hwfn, block->reset_reg_id);
1398        reset_reg_addr =
1399            DWORDS_TO_BYTES(GET_FIELD(reset_reg->data, DBG_RESET_REG_ADDR));
1400
1401        old_reset_reg_val = ecore_rd(p_hwfn, p_ptt, reset_reg_addr);
1402        new_reset_reg_val =
1403            old_reset_reg_val & ~OSAL_BIT(block->reset_reg_bit_offset);
1404
1405        ecore_wr(p_hwfn, p_ptt, reset_reg_addr, new_reset_reg_val);
1406        ecore_wr(p_hwfn, p_ptt, reset_reg_addr, old_reset_reg_val);
1407}
1408
1409/* Enable / disable Debug Bus clients according to the specified mask
1410 * (1 = enable, 0 = disable).
1411 */
1412static void qed_bus_enable_clients(struct ecore_hwfn *p_hwfn,
1413                                   struct ecore_ptt *p_ptt, u32 client_mask)
1414{
1415        ecore_wr(p_hwfn, p_ptt, DBG_REG_CLIENT_ENABLE, client_mask);
1416}
1417
1418static void qed_bus_config_dbg_line(struct ecore_hwfn *p_hwfn,
1419                                    struct ecore_ptt *p_ptt,
1420                                    enum block_id block_id,
1421                                    u8 line_id,
1422                                    u8 enable_mask,
1423                                    u8 right_shift,
1424                                    u8 force_valid_mask, u8 force_frame_mask)
1425{
1426        const struct dbg_block_chip *block =
1427                qed_get_dbg_block_per_chip(p_hwfn, block_id);
1428
1429        ecore_wr(p_hwfn, p_ptt,
1430                 DWORDS_TO_BYTES(block->dbg_select_reg_addr),
1431                 line_id);
1432        ecore_wr(p_hwfn, p_ptt,
1433                 DWORDS_TO_BYTES(block->dbg_dword_enable_reg_addr),
1434                 enable_mask);
1435        ecore_wr(p_hwfn, p_ptt,
1436                 DWORDS_TO_BYTES(block->dbg_shift_reg_addr),
1437                 right_shift);
1438        ecore_wr(p_hwfn, p_ptt,
1439                 DWORDS_TO_BYTES(block->dbg_force_valid_reg_addr),
1440                 force_valid_mask);
1441        ecore_wr(p_hwfn, p_ptt,
1442                 DWORDS_TO_BYTES(block->dbg_force_frame_reg_addr),
1443                 force_frame_mask);
1444}
1445
1446/* Disable debug bus in all blocks */
1447static void qed_bus_disable_blocks(struct ecore_hwfn *p_hwfn,
1448                                   struct ecore_ptt *p_ptt)
1449{
1450        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
1451        u32 block_id;
1452
1453        /* Disable all blocks */
1454        for (block_id = 0; block_id < MAX_BLOCK_ID; block_id++) {
1455                const struct dbg_block_chip *block_per_chip =
1456                    qed_get_dbg_block_per_chip(p_hwfn,
1457                                               (enum block_id)block_id);
1458
1459                if (GET_FIELD(block_per_chip->flags,
1460                              DBG_BLOCK_CHIP_IS_REMOVED) ||
1461                    dev_data->block_in_reset[block_id])
1462                        continue;
1463
1464                /* Disable debug bus */
1465                if (GET_FIELD(block_per_chip->flags,
1466                              DBG_BLOCK_CHIP_HAS_DBG_BUS)) {
1467                        u32 dbg_en_addr =
1468                                block_per_chip->dbg_dword_enable_reg_addr;
1469                        u16 modes_buf_offset =
1470                            GET_FIELD(block_per_chip->dbg_bus_mode.data,
1471                                      DBG_MODE_HDR_MODES_BUF_OFFSET);
1472                        bool eval_mode =
1473                            GET_FIELD(block_per_chip->dbg_bus_mode.data,
1474                                      DBG_MODE_HDR_EVAL_MODE) > 0;
1475
1476                        if (!eval_mode ||
1477                            qed_is_mode_match(p_hwfn, &modes_buf_offset))
1478                                ecore_wr(p_hwfn, p_ptt,
1479                                       DWORDS_TO_BYTES(dbg_en_addr),
1480                                       0);
1481                }
1482        }
1483}
1484
1485/* Returns true if the specified entity (indicated by GRC param) should be
1486 * included in the dump, false otherwise.
1487 */
1488static bool qed_grc_is_included(struct ecore_hwfn *p_hwfn,
1489                                enum dbg_grc_params grc_param)
1490{
1491        return qed_grc_get_param(p_hwfn, grc_param) > 0;
1492}
1493
1494/* Returns the storm_id that matches the specified Storm letter,
1495 * or MAX_DBG_STORMS if invalid storm letter.
1496 */
1497static enum dbg_storms qed_get_id_from_letter(char storm_letter)
1498{
1499        u8 storm_id;
1500
1501        for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++)
1502                if (s_storm_defs[storm_id].letter == storm_letter)
1503                        return (enum dbg_storms)storm_id;
1504
1505        return MAX_DBG_STORMS;
1506}
1507
1508/* Returns true of the specified Storm should be included in the dump, false
1509 * otherwise.
1510 */
1511static bool qed_grc_is_storm_included(struct ecore_hwfn *p_hwfn,
1512                                      enum dbg_storms storm)
1513{
1514        return qed_grc_get_param(p_hwfn, (enum dbg_grc_params)storm) > 0;
1515}
1516
1517/* Returns true if the specified memory should be included in the dump, false
1518 * otherwise.
1519 */
1520static bool qed_grc_is_mem_included(struct ecore_hwfn *p_hwfn,
1521                                    enum block_id block_id, u8 mem_group_id)
1522{
1523        const struct dbg_block *block;
1524        u8 i;
1525
1526        block = get_dbg_block(p_hwfn, block_id);
1527
1528        /* If the block is associated with a Storm, check Storm match */
1529        if (block->associated_storm_letter) {
1530                enum dbg_storms associated_storm_id =
1531                    qed_get_id_from_letter(block->associated_storm_letter);
1532
1533                if (associated_storm_id == MAX_DBG_STORMS ||
1534                    !qed_grc_is_storm_included(p_hwfn, associated_storm_id))
1535                        return false;
1536        }
1537
1538        for (i = 0; i < NUM_BIG_RAM_TYPES; i++) {
1539                struct big_ram_defs *big_ram = &s_big_ram_defs[i];
1540
1541                if (mem_group_id == big_ram->mem_group_id ||
1542                    mem_group_id == big_ram->ram_mem_group_id)
1543                        return qed_grc_is_included(p_hwfn, big_ram->grc_param);
1544        }
1545
1546        switch (mem_group_id) {
1547        case MEM_GROUP_PXP_ILT:
1548        case MEM_GROUP_PXP_MEM:
1549                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PXP);
1550        case MEM_GROUP_RAM:
1551                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_RAM);
1552        case MEM_GROUP_PBUF:
1553                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PBUF);
1554        case MEM_GROUP_CAU_MEM:
1555        case MEM_GROUP_CAU_SB:
1556        case MEM_GROUP_CAU_PI:
1557                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CAU);
1558        case MEM_GROUP_CAU_MEM_EXT:
1559                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CAU_EXT);
1560        case MEM_GROUP_QM_MEM:
1561                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_QM);
1562        case MEM_GROUP_CFC_MEM:
1563        case MEM_GROUP_CONN_CFC_MEM:
1564        case MEM_GROUP_TASK_CFC_MEM:
1565                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CFC) ||
1566                       qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM_CTX);
1567        case MEM_GROUP_DORQ_MEM:
1568                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DORQ);
1569        case MEM_GROUP_IGU_MEM:
1570        case MEM_GROUP_IGU_MSIX:
1571                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_IGU);
1572        case MEM_GROUP_MULD_MEM:
1573                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MULD);
1574        case MEM_GROUP_PRS_MEM:
1575                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_PRS);
1576        case MEM_GROUP_DMAE_MEM:
1577                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DMAE);
1578        case MEM_GROUP_TM_MEM:
1579                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_TM);
1580        case MEM_GROUP_SDM_MEM:
1581                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_SDM);
1582        case MEM_GROUP_TDIF_CTX:
1583        case MEM_GROUP_RDIF_CTX:
1584                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_DIF);
1585        case MEM_GROUP_CM_MEM:
1586                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM);
1587        case MEM_GROUP_IOR:
1588                return qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_IOR);
1589        default:
1590                return true;
1591        }
1592}
1593
1594/* Stalls all Storms */
1595static void qed_grc_stall_storms(struct ecore_hwfn *p_hwfn,
1596                                 struct ecore_ptt *p_ptt, bool stall)
1597{
1598        u32 reg_addr;
1599        u8 storm_id;
1600
1601        for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
1602                if (!qed_grc_is_storm_included(p_hwfn,
1603                                               (enum dbg_storms)storm_id))
1604                        continue;
1605
1606                reg_addr = s_storm_defs[storm_id].sem_fast_mem_addr +
1607                    SEM_FAST_REG_STALL_0;
1608                ecore_wr(p_hwfn, p_ptt, reg_addr, stall ? 1 : 0);
1609        }
1610
1611        OSAL_MSLEEP(STALL_DELAY_MS);
1612}
1613
1614/* Takes all blocks out of reset. If rbc_only is true, only RBC clients are
1615 * taken out of reset.
1616 */
1617static void qed_grc_unreset_blocks(struct ecore_hwfn *p_hwfn,
1618                                   struct ecore_ptt *p_ptt, bool rbc_only)
1619{
1620        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
1621        u8 chip_id = dev_data->chip_id;
1622        u32 i;
1623
1624        /* Take RBCs out of reset */
1625        for (i = 0; i < OSAL_ARRAY_SIZE(s_rbc_reset_defs); i++)
1626                if (s_rbc_reset_defs[i].reset_val[dev_data->chip_id])
1627                        ecore_wr(p_hwfn,
1628                               p_ptt,
1629                               s_rbc_reset_defs[i].reset_reg_addr +
1630                               RESET_REG_UNRESET_OFFSET,
1631                               s_rbc_reset_defs[i].reset_val[chip_id]);
1632
1633        if (!rbc_only) {
1634                u32 reg_val[NUM_DBG_RESET_REGS] = { 0 };
1635                u8 reset_reg_id;
1636                u32 block_id;
1637
1638                /* Fill reset regs values */
1639                for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
1640                        bool is_removed, has_reset_reg, unreset_before_dump;
1641                        const struct dbg_block_chip *block;
1642
1643                        block = qed_get_dbg_block_per_chip(p_hwfn,
1644                                                           (enum block_id)
1645                                                           block_id);
1646                        is_removed =
1647                            GET_FIELD(block->flags, DBG_BLOCK_CHIP_IS_REMOVED);
1648                        has_reset_reg =
1649                            GET_FIELD(block->flags,
1650                                      DBG_BLOCK_CHIP_HAS_RESET_REG);
1651                        unreset_before_dump =
1652                            GET_FIELD(block->flags,
1653                                      DBG_BLOCK_CHIP_UNRESET_BEFORE_DUMP);
1654
1655                        if (!is_removed && has_reset_reg && unreset_before_dump)
1656                                reg_val[block->reset_reg_id] |=
1657                                    OSAL_BIT(block->reset_reg_bit_offset);
1658                }
1659
1660                /* Write reset registers */
1661                for (reset_reg_id = 0; reset_reg_id < NUM_DBG_RESET_REGS;
1662                     reset_reg_id++) {
1663                        const struct dbg_reset_reg *reset_reg;
1664                        u32 reset_reg_addr;
1665
1666                        reset_reg = qed_get_dbg_reset_reg(p_hwfn, reset_reg_id);
1667
1668                        if (GET_FIELD
1669                            (reset_reg->data, DBG_RESET_REG_IS_REMOVED))
1670                                continue;
1671
1672                        if (reg_val[reset_reg_id]) {
1673                                reset_reg_addr =
1674                                    GET_FIELD(reset_reg->data,
1675                                              DBG_RESET_REG_ADDR);
1676                                ecore_wr(p_hwfn,
1677                                       p_ptt,
1678                                       DWORDS_TO_BYTES(reset_reg_addr) +
1679                                       RESET_REG_UNRESET_OFFSET,
1680                                       reg_val[reset_reg_id]);
1681                        }
1682                }
1683        }
1684}
1685
1686/* Returns the attention block data of the specified block */
1687static const struct dbg_attn_block_type_data *
1688qed_get_block_attn_data(struct ecore_hwfn *p_hwfn,
1689                        enum block_id block_id, enum dbg_attn_type attn_type)
1690{
1691        const struct dbg_attn_block *base_attn_block_arr =
1692            (const struct dbg_attn_block *)
1693            p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr;
1694
1695        return &base_attn_block_arr[block_id].per_type_data[attn_type];
1696}
1697
1698/* Returns the attention registers of the specified block */
1699static const struct dbg_attn_reg *
1700qed_get_block_attn_regs(struct ecore_hwfn *p_hwfn,
1701                        enum block_id block_id, enum dbg_attn_type attn_type,
1702                        u8 *num_attn_regs)
1703{
1704        const struct dbg_attn_block_type_data *block_type_data =
1705            qed_get_block_attn_data(p_hwfn, block_id, attn_type);
1706
1707        *num_attn_regs = block_type_data->num_regs;
1708
1709        return (const struct dbg_attn_reg *)
1710                p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr +
1711                block_type_data->regs_offset;
1712}
1713
1714/* For each block, clear the status of all parities */
1715static void qed_grc_clear_all_prty(struct ecore_hwfn *p_hwfn,
1716                                   struct ecore_ptt *p_ptt)
1717{
1718        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
1719        const struct dbg_attn_reg *attn_reg_arr;
1720        u8 reg_idx, num_attn_regs;
1721        u32 block_id;
1722
1723        for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
1724                if (dev_data->block_in_reset[block_id])
1725                        continue;
1726
1727                attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
1728                                                       (enum block_id)block_id,
1729                                                       ATTN_TYPE_PARITY,
1730                                                       &num_attn_regs);
1731
1732                for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
1733                        const struct dbg_attn_reg *reg_data =
1734                                &attn_reg_arr[reg_idx];
1735                        u16 modes_buf_offset;
1736                        bool eval_mode;
1737
1738                        /* Check mode */
1739                        eval_mode = GET_FIELD(reg_data->mode.data,
1740                                              DBG_MODE_HDR_EVAL_MODE) > 0;
1741                        modes_buf_offset =
1742                                GET_FIELD(reg_data->mode.data,
1743                                          DBG_MODE_HDR_MODES_BUF_OFFSET);
1744
1745                        /* If Mode match: clear parity status */
1746                        if (!eval_mode ||
1747                            qed_is_mode_match(p_hwfn, &modes_buf_offset))
1748                                ecore_rd(p_hwfn, p_ptt,
1749                                    DWORDS_TO_BYTES(reg_data->sts_clr_address));
1750                }
1751        }
1752}
1753
1754/* Dumps GRC registers section header. Returns the dumped size in dwords.
1755 * the following parameters are dumped:
1756 * - count: no. of dumped entries
1757 * - split_type: split type
1758 * - split_id: split ID (dumped only if split_id != SPLIT_TYPE_NONE)
1759 * - reg_type_name: register type name (dumped only if reg_type_name != NULL)
1760 */
1761static u32 qed_grc_dump_regs_hdr(u32 *dump_buf,
1762                                 bool dump,
1763                                 u32 num_reg_entries,
1764                                 enum init_split_types split_type,
1765                                 u8 split_id, const char *reg_type_name)
1766{
1767        u8 num_params = 2 +
1768            (split_type != SPLIT_TYPE_NONE ? 1 : 0) + (reg_type_name ? 1 : 0);
1769        u32 offset = 0;
1770
1771        offset += qed_dump_section_hdr(dump_buf + offset,
1772                                       dump, "grc_regs", num_params);
1773        offset += qed_dump_num_param(dump_buf + offset,
1774                                     dump, "count", num_reg_entries);
1775        offset += qed_dump_str_param(dump_buf + offset,
1776                                     dump, "split",
1777                                     s_split_type_defs[split_type].name);
1778        if (split_type != SPLIT_TYPE_NONE)
1779                offset += qed_dump_num_param(dump_buf + offset,
1780                                             dump, "id", split_id);
1781        if (reg_type_name)
1782                offset += qed_dump_str_param(dump_buf + offset,
1783                                             dump, "type", reg_type_name);
1784
1785        return offset;
1786}
1787
1788/* Reads the specified registers into the specified buffer.
1789 * The addr and len arguments are specified in dwords.
1790 */
1791void qed_read_regs(struct ecore_hwfn *p_hwfn,
1792                   struct ecore_ptt *p_ptt, u32 *buf, u32 addr, u32 len)
1793{
1794        u32 i;
1795
1796        for (i = 0; i < len; i++)
1797                buf[i] = ecore_rd(p_hwfn, p_ptt, DWORDS_TO_BYTES(addr + i));
1798}
1799
1800/* Dumps the GRC registers in the specified address range.
1801 * Returns the dumped size in dwords.
1802 * The addr and len arguments are specified in dwords.
1803 */
1804static u32 qed_grc_dump_addr_range(struct ecore_hwfn *p_hwfn,
1805                                   struct ecore_ptt *p_ptt,
1806                                   u32 *dump_buf,
1807                                   bool dump, u32 addr, u32 len, bool wide_bus,
1808                                   enum init_split_types split_type,
1809                                   u8 split_id)
1810{
1811        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
1812        u8 port_id = 0, pf_id = 0, vf_id = 0, fid = 0;
1813        bool read_using_dmae = false;
1814        u32 thresh;
1815
1816        if (!dump)
1817                return len;
1818
1819        switch (split_type) {
1820        case SPLIT_TYPE_PORT:
1821                port_id = split_id;
1822                break;
1823        case SPLIT_TYPE_PF:
1824                pf_id = split_id;
1825                break;
1826        case SPLIT_TYPE_PORT_PF:
1827                port_id = split_id / dev_data->num_pfs_per_port;
1828                pf_id = port_id + dev_data->num_ports *
1829                    (split_id % dev_data->num_pfs_per_port);
1830                break;
1831        case SPLIT_TYPE_VF:
1832                vf_id = split_id;
1833                break;
1834        default:
1835                break;
1836        }
1837
1838        /* Try reading using DMAE */
1839        if (dev_data->use_dmae && split_type != SPLIT_TYPE_VF &&
1840            (len >= s_hw_type_defs[dev_data->hw_type].dmae_thresh ||
1841             (PROTECT_WIDE_BUS && wide_bus))) {
1842                struct dmae_params dmae_params;
1843
1844                /* Set DMAE params */
1845                memset(&dmae_params, 0, sizeof(dmae_params));
1846                SET_FIELD(dmae_params.flags, DMAE_PARAMS_COMPLETION_DST, 1);
1847                switch (split_type) {
1848                case SPLIT_TYPE_PORT:
1849                        SET_FIELD(dmae_params.flags, DMAE_PARAMS_PORT_VALID,
1850                                  1);
1851                        dmae_params.port_id = port_id;
1852                        break;
1853                case SPLIT_TYPE_PF:
1854                        SET_FIELD(dmae_params.flags,
1855                                  DMAE_PARAMS_SRC_PF_VALID, 1);
1856                        dmae_params.src_pf_id = pf_id;
1857                        break;
1858                case SPLIT_TYPE_PORT_PF:
1859                        SET_FIELD(dmae_params.flags, DMAE_PARAMS_PORT_VALID,
1860                                  1);
1861                        SET_FIELD(dmae_params.flags,
1862                                  DMAE_PARAMS_SRC_PF_VALID, 1);
1863                        dmae_params.port_id = port_id;
1864                        dmae_params.src_pf_id = pf_id;
1865                        break;
1866                default:
1867                        break;
1868                }
1869
1870                /* Execute DMAE command */
1871                read_using_dmae = !ecore_dmae_grc2host(p_hwfn,
1872                                                     p_ptt,
1873                                                     DWORDS_TO_BYTES(addr),
1874                                                     (u64)(uintptr_t)(dump_buf),
1875                                                     len, &dmae_params);
1876                if (!read_using_dmae) {
1877                        dev_data->use_dmae = 0;
1878                        DP_VERBOSE(p_hwfn->p_dev,
1879                                   ECORE_MSG_DEBUG,
1880                                   "Failed reading from chip using DMAE, using GRC instead\n");
1881                }
1882        }
1883
1884        if (read_using_dmae)
1885                goto print_log;
1886
1887        /* If not read using DMAE, read using GRC */
1888
1889        /* Set pretend */
1890        if (split_type != dev_data->pretend.split_type ||
1891            split_id != dev_data->pretend.split_id) {
1892                switch (split_type) {
1893                case SPLIT_TYPE_PORT:
1894                        ecore_port_pretend(p_hwfn, p_ptt, port_id);
1895                        break;
1896                case SPLIT_TYPE_PF:
1897                        fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
1898                                          pf_id);
1899                        ecore_fid_pretend(p_hwfn, p_ptt, fid);
1900                        break;
1901                case SPLIT_TYPE_PORT_PF:
1902                        fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
1903                                          pf_id);
1904                        ecore_port_fid_pretend(p_hwfn, p_ptt, port_id, fid);
1905                        break;
1906                case SPLIT_TYPE_VF:
1907                        fid = FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_VFVALID, 1)
1908                              | FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_VFID,
1909                                          vf_id);
1910                        ecore_fid_pretend(p_hwfn, p_ptt, fid);
1911                        break;
1912                default:
1913                        break;
1914                }
1915
1916                dev_data->pretend.split_type = (u8)split_type;
1917                dev_data->pretend.split_id = split_id;
1918        }
1919
1920        /* Read registers using GRC */
1921        qed_read_regs(p_hwfn, p_ptt, dump_buf, addr, len);
1922
1923print_log:
1924        /* Print log */
1925        dev_data->num_regs_read += len;
1926        thresh = s_hw_type_defs[dev_data->hw_type].log_thresh;
1927        if ((dev_data->num_regs_read / thresh) >
1928            ((dev_data->num_regs_read - len) / thresh))
1929                DP_VERBOSE(p_hwfn->p_dev,
1930                           ECORE_MSG_DEBUG,
1931                           "Dumped %d registers...\n", dev_data->num_regs_read);
1932
1933        return len;
1934}
1935
1936/* Dumps GRC registers sequence header. Returns the dumped size in dwords.
1937 * The addr and len arguments are specified in dwords.
1938 */
1939static u32 qed_grc_dump_reg_entry_hdr(u32 *dump_buf,
1940                                      bool dump, u32 addr, u32 len)
1941{
1942        if (dump)
1943                *dump_buf = addr | (len << REG_DUMP_LEN_SHIFT);
1944
1945        return 1;
1946}
1947
1948/* Dumps GRC registers sequence. Returns the dumped size in dwords.
1949 * The addr and len arguments are specified in dwords.
1950 */
1951static u32 qed_grc_dump_reg_entry(struct ecore_hwfn *p_hwfn,
1952                                  struct ecore_ptt *p_ptt,
1953                                  u32 *dump_buf,
1954                                  bool dump, u32 addr, u32 len, bool wide_bus,
1955                                  enum init_split_types split_type, u8 split_id)
1956{
1957        u32 offset = 0;
1958
1959        offset += qed_grc_dump_reg_entry_hdr(dump_buf, dump, addr, len);
1960        offset += qed_grc_dump_addr_range(p_hwfn,
1961                                          p_ptt,
1962                                          dump_buf + offset,
1963                                          dump, addr, len, wide_bus,
1964                                          split_type, split_id);
1965
1966        return offset;
1967}
1968
1969/* Dumps GRC registers sequence with skip cycle.
1970 * Returns the dumped size in dwords.
1971 * - addr:      start GRC address in dwords
1972 * - total_len: total no. of dwords to dump
1973 * - read_len:  no. consecutive dwords to read
1974 * - skip_len:  no. of dwords to skip (and fill with zeros)
1975 */
1976static u32 qed_grc_dump_reg_entry_skip(struct ecore_hwfn *p_hwfn,
1977                                       struct ecore_ptt *p_ptt,
1978                                       u32 *dump_buf,
1979                                       bool dump,
1980                                       u32 addr,
1981                                       u32 total_len,
1982                                       u32 read_len, u32 skip_len)
1983{
1984        u32 offset = 0, reg_offset = 0;
1985
1986        offset += qed_grc_dump_reg_entry_hdr(dump_buf, dump, addr, total_len);
1987
1988        if (!dump)
1989                return offset + total_len;
1990
1991        while (reg_offset < total_len) {
1992                u32 curr_len = OSAL_MIN_T(u32, read_len,
1993                                          total_len - reg_offset);
1994
1995                offset += qed_grc_dump_addr_range(p_hwfn,
1996                                                  p_ptt,
1997                                                  dump_buf + offset,
1998                                                  dump,  addr, curr_len, false,
1999                                                  SPLIT_TYPE_NONE, 0);
2000                reg_offset += curr_len;
2001                addr += curr_len;
2002
2003                if (reg_offset < total_len) {
2004                        curr_len = OSAL_MIN_T(u32, skip_len,
2005                                              total_len - skip_len);
2006                        memset(dump_buf + offset, 0, DWORDS_TO_BYTES(curr_len));
2007                        offset += curr_len;
2008                        reg_offset += curr_len;
2009                        addr += curr_len;
2010                }
2011        }
2012
2013        return offset;
2014}
2015
2016/* Dumps GRC registers entries. Returns the dumped size in dwords. */
2017static u32 qed_grc_dump_regs_entries(struct ecore_hwfn *p_hwfn,
2018                                     struct ecore_ptt *p_ptt,
2019                                     struct virt_mem_desc input_regs_arr,
2020                                     u32 *dump_buf,
2021                                     bool dump,
2022                                     enum init_split_types split_type,
2023                                     u8 split_id,
2024                                     bool block_enable[MAX_BLOCK_ID],
2025                                     u32 *num_dumped_reg_entries)
2026{
2027        u32 i, offset = 0, input_offset = 0;
2028        bool mode_match = true;
2029
2030        *num_dumped_reg_entries = 0;
2031
2032        while (input_offset < BYTES_TO_DWORDS(input_regs_arr.size)) {
2033                const struct dbg_dump_cond_hdr *cond_hdr =
2034                    (const struct dbg_dump_cond_hdr *)
2035                    input_regs_arr.ptr + input_offset++;
2036                u16 modes_buf_offset;
2037                bool eval_mode;
2038
2039                /* Check mode/block */
2040                eval_mode = GET_FIELD(cond_hdr->mode.data,
2041                                      DBG_MODE_HDR_EVAL_MODE) > 0;
2042                if (eval_mode) {
2043                        modes_buf_offset =
2044                                GET_FIELD(cond_hdr->mode.data,
2045                                          DBG_MODE_HDR_MODES_BUF_OFFSET);
2046                        mode_match = qed_is_mode_match(p_hwfn,
2047                                                       &modes_buf_offset);
2048                }
2049
2050                if (!mode_match || !block_enable[cond_hdr->block_id]) {
2051                        input_offset += cond_hdr->data_size;
2052                        continue;
2053                }
2054
2055                for (i = 0; i < cond_hdr->data_size; i++, input_offset++) {
2056                        const struct dbg_dump_reg *reg =
2057                            (const struct dbg_dump_reg *)
2058                            input_regs_arr.ptr + input_offset;
2059                        u32 addr, len;
2060                        bool wide_bus;
2061
2062                        addr = GET_FIELD(reg->data, DBG_DUMP_REG_ADDRESS);
2063                        len = GET_FIELD(reg->data, DBG_DUMP_REG_LENGTH);
2064                        wide_bus = GET_FIELD(reg->data, DBG_DUMP_REG_WIDE_BUS);
2065                        offset += qed_grc_dump_reg_entry(p_hwfn,
2066                                                         p_ptt,
2067                                                         dump_buf + offset,
2068                                                         dump,
2069                                                         addr,
2070                                                         len,
2071                                                         wide_bus,
2072                                                         split_type, split_id);
2073                        (*num_dumped_reg_entries)++;
2074                }
2075        }
2076
2077        return offset;
2078}
2079
2080/* Dumps GRC registers entries. Returns the dumped size in dwords. */
2081static u32 qed_grc_dump_split_data(struct ecore_hwfn *p_hwfn,
2082                                   struct ecore_ptt *p_ptt,
2083                                   struct virt_mem_desc input_regs_arr,
2084                                   u32 *dump_buf,
2085                                   bool dump,
2086                                   bool block_enable[MAX_BLOCK_ID],
2087                                   enum init_split_types split_type,
2088                                   u8 split_id, const char *reg_type_name)
2089{
2090        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
2091        enum init_split_types hdr_split_type = split_type;
2092        u32 num_dumped_reg_entries, offset;
2093        u8 hdr_split_id = split_id;
2094
2095        /* In PORT_PF split type, print a port split header */
2096        if (split_type == SPLIT_TYPE_PORT_PF) {
2097                hdr_split_type = SPLIT_TYPE_PORT;
2098                hdr_split_id = split_id / dev_data->num_pfs_per_port;
2099        }
2100
2101        /* Calculate register dump header size (and skip it for now) */
2102        offset = qed_grc_dump_regs_hdr(dump_buf,
2103                                       false,
2104                                       0,
2105                                       hdr_split_type,
2106                                       hdr_split_id, reg_type_name);
2107
2108        /* Dump registers */
2109        offset += qed_grc_dump_regs_entries(p_hwfn,
2110                                            p_ptt,
2111                                            input_regs_arr,
2112                                            dump_buf + offset,
2113                                            dump,
2114                                            split_type,
2115                                            split_id,
2116                                            block_enable,
2117                                            &num_dumped_reg_entries);
2118
2119        /* Write register dump header */
2120        if (dump && num_dumped_reg_entries > 0)
2121                qed_grc_dump_regs_hdr(dump_buf,
2122                                      dump,
2123                                      num_dumped_reg_entries,
2124                                      hdr_split_type,
2125                                      hdr_split_id, reg_type_name);
2126
2127        return num_dumped_reg_entries > 0 ? offset : 0;
2128}
2129
2130/* Dumps registers according to the input registers array. Returns the dumped
2131 * size in dwords.
2132 */
2133static u32 qed_grc_dump_registers(struct ecore_hwfn *p_hwfn,
2134                                  struct ecore_ptt *p_ptt,
2135                                  u32 *dump_buf,
2136                                  bool dump,
2137                                  bool block_enable[MAX_BLOCK_ID],
2138                                  const char *reg_type_name)
2139{
2140        struct virt_mem_desc *dbg_buf =
2141            &p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG];
2142        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
2143        u32 offset = 0, input_offset = 0;
2144
2145        while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
2146                const struct dbg_dump_split_hdr *split_hdr;
2147                struct virt_mem_desc curr_input_regs_arr;
2148                enum init_split_types split_type;
2149                u16 split_count = 0;
2150                u32 split_data_size;
2151                u8 split_id;
2152
2153                split_hdr =
2154                    (const struct dbg_dump_split_hdr *)
2155                    dbg_buf->ptr + input_offset++;
2156                split_type =
2157                    GET_FIELD(split_hdr->hdr,
2158                              DBG_DUMP_SPLIT_HDR_SPLIT_TYPE_ID);
2159                split_data_size = GET_FIELD(split_hdr->hdr,
2160                                            DBG_DUMP_SPLIT_HDR_DATA_SIZE);
2161                curr_input_regs_arr.ptr =
2162                    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG].ptr +
2163                    input_offset;
2164                curr_input_regs_arr.size = DWORDS_TO_BYTES(split_data_size);
2165
2166                switch (split_type) {
2167                case SPLIT_TYPE_NONE:
2168                        split_count = 1;
2169                        break;
2170                case SPLIT_TYPE_PORT:
2171                        split_count = dev_data->num_ports;
2172                        break;
2173                case SPLIT_TYPE_PF:
2174                case SPLIT_TYPE_PORT_PF:
2175                        split_count = dev_data->num_ports *
2176                            dev_data->num_pfs_per_port;
2177                        break;
2178                case SPLIT_TYPE_VF:
2179                        split_count = dev_data->num_vfs;
2180                        break;
2181                default:
2182                        return 0;
2183                }
2184
2185                for (split_id = 0; split_id < split_count; split_id++)
2186                        offset += qed_grc_dump_split_data(p_hwfn, p_ptt,
2187                                                          curr_input_regs_arr,
2188                                                          dump_buf + offset,
2189                                                          dump, block_enable,
2190                                                          split_type,
2191                                                          split_id,
2192                                                          reg_type_name);
2193
2194                input_offset += split_data_size;
2195        }
2196
2197        /* Cancel pretends (pretend to original PF) */
2198        if (dump) {
2199                ecore_fid_pretend(p_hwfn, p_ptt,
2200                                FIELD_VALUE(PXP_PRETEND_CONCRETE_FID_PFID,
2201                                            p_hwfn->rel_pf_id));
2202                dev_data->pretend.split_type = SPLIT_TYPE_NONE;
2203                dev_data->pretend.split_id = 0;
2204        }
2205
2206        return offset;
2207}
2208
2209/* Dump reset registers. Returns the dumped size in dwords. */
2210static u32 qed_grc_dump_reset_regs(struct ecore_hwfn *p_hwfn,
2211                                   struct ecore_ptt *p_ptt,
2212                                   u32 *dump_buf, bool dump)
2213{
2214        u32 offset = 0, num_regs = 0;
2215        u8 reset_reg_id;
2216
2217        /* Calculate header size */
2218        offset += qed_grc_dump_regs_hdr(dump_buf,
2219                                        false,
2220                                        0, SPLIT_TYPE_NONE, 0, "RESET_REGS");
2221
2222        /* Write reset registers */
2223        for (reset_reg_id = 0; reset_reg_id < NUM_DBG_RESET_REGS;
2224             reset_reg_id++) {
2225                const struct dbg_reset_reg *reset_reg;
2226                u32 reset_reg_addr;
2227
2228                reset_reg = qed_get_dbg_reset_reg(p_hwfn, reset_reg_id);
2229
2230                if (GET_FIELD(reset_reg->data, DBG_RESET_REG_IS_REMOVED))
2231                        continue;
2232
2233                reset_reg_addr = GET_FIELD(reset_reg->data, DBG_RESET_REG_ADDR);
2234                offset += qed_grc_dump_reg_entry(p_hwfn,
2235                                                 p_ptt,
2236                                                 dump_buf + offset,
2237                                                 dump,
2238                                                 reset_reg_addr,
2239                                                 1, false, SPLIT_TYPE_NONE, 0);
2240                num_regs++;
2241        }
2242
2243        /* Write header */
2244        if (dump)
2245                qed_grc_dump_regs_hdr(dump_buf,
2246                                      true, num_regs, SPLIT_TYPE_NONE,
2247                                      0, "RESET_REGS");
2248
2249        return offset;
2250}
2251
2252/* Dump registers that are modified during GRC Dump and therefore must be
2253 * dumped first. Returns the dumped size in dwords.
2254 */
2255static u32 qed_grc_dump_modified_regs(struct ecore_hwfn *p_hwfn,
2256                                      struct ecore_ptt *p_ptt,
2257                                      u32 *dump_buf, bool dump)
2258{
2259        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
2260        u32 block_id, offset = 0, stall_regs_offset;
2261        const struct dbg_attn_reg *attn_reg_arr;
2262        u8 storm_id, reg_idx, num_attn_regs;
2263        u32 num_reg_entries = 0;
2264
2265        /* Write empty header for attention registers */
2266        offset += qed_grc_dump_regs_hdr(dump_buf,
2267                                        false,
2268                                        0, SPLIT_TYPE_NONE, 0, "ATTN_REGS");
2269
2270        /* Write parity registers */
2271        for (block_id = 0; block_id < NUM_PHYS_BLOCKS; block_id++) {
2272                if (dev_data->block_in_reset[block_id] && dump)
2273                        continue;
2274
2275                attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
2276                                                       (enum block_id)block_id,
2277                                                       ATTN_TYPE_PARITY,
2278                                                       &num_attn_regs);
2279
2280                for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
2281                        const struct dbg_attn_reg *reg_data =
2282                                &attn_reg_arr[reg_idx];
2283                        u16 modes_buf_offset;
2284                        bool eval_mode;
2285                        u32 addr;
2286
2287                        /* Check mode */
2288                        eval_mode = GET_FIELD(reg_data->mode.data,
2289                                              DBG_MODE_HDR_EVAL_MODE) > 0;
2290                        modes_buf_offset =
2291                                GET_FIELD(reg_data->mode.data,
2292                                          DBG_MODE_HDR_MODES_BUF_OFFSET);
2293                        if (eval_mode &&
2294                            !qed_is_mode_match(p_hwfn, &modes_buf_offset))
2295                                continue;
2296
2297                        /* Mode match: read & dump registers */
2298                        addr = reg_data->mask_address;
2299                        offset += qed_grc_dump_reg_entry(p_hwfn,
2300                                                         p_ptt,
2301                                                         dump_buf + offset,
2302                                                         dump,
2303                                                         addr,
2304                                                         1, false,
2305                                                         SPLIT_TYPE_NONE, 0);
2306                        addr = GET_FIELD(reg_data->data,
2307                                         DBG_ATTN_REG_STS_ADDRESS);
2308                        offset += qed_grc_dump_reg_entry(p_hwfn,
2309                                                         p_ptt,
2310                                                         dump_buf + offset,
2311                                                         dump,
2312                                                         addr,
2313                                                         1, false,
2314                                                         SPLIT_TYPE_NONE, 0);
2315                        num_reg_entries += 2;
2316                }
2317        }
2318
2319        /* Overwrite header for attention registers */
2320        if (dump)
2321                qed_grc_dump_regs_hdr(dump_buf,
2322                                      true,
2323                                      num_reg_entries,
2324                                      SPLIT_TYPE_NONE, 0, "ATTN_REGS");
2325
2326        /* Write empty header for stall registers */
2327        stall_regs_offset = offset;
2328        offset += qed_grc_dump_regs_hdr(dump_buf,
2329                                        false, 0, SPLIT_TYPE_NONE, 0, "REGS");
2330
2331        /* Write Storm stall status registers */
2332        for (storm_id = 0, num_reg_entries = 0; storm_id < MAX_DBG_STORMS;
2333             storm_id++) {
2334                struct storm_defs *storm = &s_storm_defs[storm_id];
2335                u32 addr;
2336
2337                if (dev_data->block_in_reset[storm->sem_block_id] && dump)
2338                        continue;
2339
2340                addr =
2341                    BYTES_TO_DWORDS(storm->sem_fast_mem_addr +
2342                                    SEM_FAST_REG_STALLED);
2343                offset += qed_grc_dump_reg_entry(p_hwfn,
2344                                                 p_ptt,
2345                                                 dump_buf + offset,
2346                                                 dump,
2347                                                 addr,
2348                                                 1,
2349                                                 false, SPLIT_TYPE_NONE, 0);
2350                num_reg_entries++;
2351        }
2352
2353        /* Overwrite header for stall registers */
2354        if (dump)
2355                qed_grc_dump_regs_hdr(dump_buf + stall_regs_offset,
2356                                      true,
2357                                      num_reg_entries,
2358                                      SPLIT_TYPE_NONE, 0, "REGS");
2359
2360        return offset;
2361}
2362
2363/* Dumps registers that can't be represented in the debug arrays */
2364static u32 qed_grc_dump_special_regs(struct ecore_hwfn *p_hwfn,
2365                                     struct ecore_ptt *p_ptt,
2366                                     u32 *dump_buf, bool dump)
2367{
2368        u32 offset = 0, addr;
2369
2370        offset += qed_grc_dump_regs_hdr(dump_buf,
2371                                        dump, 2, SPLIT_TYPE_NONE, 0, "REGS");
2372
2373        /* Dump R/TDIF_REG_DEBUG_ERROR_INFO_SIZE (every 8'th register should be
2374         * skipped).
2375         */
2376        addr = BYTES_TO_DWORDS(RDIF_REG_DEBUG_ERROR_INFO);
2377        offset += qed_grc_dump_reg_entry_skip(p_hwfn,
2378                                              p_ptt,
2379                                              dump_buf + offset,
2380                                              dump,
2381                                              addr,
2382                                              RDIF_REG_DEBUG_ERROR_INFO_SIZE,
2383                                              7,
2384                                              1);
2385        addr = BYTES_TO_DWORDS(TDIF_REG_DEBUG_ERROR_INFO);
2386        offset +=
2387            qed_grc_dump_reg_entry_skip(p_hwfn,
2388                                        p_ptt,
2389                                        dump_buf + offset,
2390                                        dump,
2391                                        addr,
2392                                        TDIF_REG_DEBUG_ERROR_INFO_SIZE,
2393                                        7,
2394                                        1);
2395
2396        return offset;
2397}
2398
2399/* Dumps a GRC memory header (section and params). Returns the dumped size in
2400 * dwords. The following parameters are dumped:
2401 * - name:         dumped only if it's not NULL.
2402 * - addr:         in dwords, dumped only if name is NULL.
2403 * - len:          in dwords, always dumped.
2404 * - width:        dumped if it's not zero.
2405 * - packed:       dumped only if it's not false.
2406 * - mem_group:    always dumped.
2407 * - is_storm:     true only if the memory is related to a Storm.
2408 * - storm_letter: valid only if is_storm is true.
2409 *
2410 */
2411static u32 qed_grc_dump_mem_hdr(struct ecore_hwfn *p_hwfn,
2412                                u32 *dump_buf,
2413                                bool dump,
2414                                const char *name,
2415                                u32 addr,
2416                                u32 len,
2417                                u32 bit_width,
2418                                bool packed,
2419                                const char *mem_group, char storm_letter)
2420{
2421        u8 num_params = 3;
2422        u32 offset = 0;
2423        char buf[64];
2424
2425        if (!len)
2426                DP_NOTICE(p_hwfn, false,
2427                          "Unexpected GRC Dump error: dumped memory size must be non-zero\n");
2428
2429        if (bit_width)
2430                num_params++;
2431        if (packed)
2432                num_params++;
2433
2434        /* Dump section header */
2435        offset += qed_dump_section_hdr(dump_buf + offset,
2436                                       dump, "grc_mem", num_params);
2437
2438        if (name) {
2439                /* Dump name */
2440                if (storm_letter) {
2441                        strcpy(buf, "?STORM_");
2442                        buf[0] = storm_letter;
2443                        strcpy(buf + strlen(buf), name);
2444                } else {
2445                        strcpy(buf, name);
2446                }
2447
2448                offset += qed_dump_str_param(dump_buf + offset,
2449                                             dump, "name", buf);
2450        } else {
2451                /* Dump address */
2452                u32 addr_in_bytes = DWORDS_TO_BYTES(addr);
2453
2454                offset += qed_dump_num_param(dump_buf + offset,
2455                                             dump, "addr", addr_in_bytes);
2456        }
2457
2458        /* Dump len */
2459        offset += qed_dump_num_param(dump_buf + offset, dump, "len", len);
2460
2461        /* Dump bit width */
2462        if (bit_width)
2463                offset += qed_dump_num_param(dump_buf + offset,
2464                                             dump, "width", bit_width);
2465
2466        /* Dump packed */
2467        if (packed)
2468                offset += qed_dump_num_param(dump_buf + offset,
2469                                             dump, "packed", 1);
2470
2471        /* Dump reg type */
2472        if (storm_letter) {
2473                strcpy(buf, "?STORM_");
2474                buf[0] = storm_letter;
2475                strcpy(buf + strlen(buf), mem_group);
2476        } else {
2477                strcpy(buf, mem_group);
2478        }
2479
2480        offset += qed_dump_str_param(dump_buf + offset, dump, "type", buf);
2481
2482        return offset;
2483}
2484
2485/* Dumps a single GRC memory. If name is NULL, the memory is stored by address.
2486 * Returns the dumped size in dwords.
2487 * The addr and len arguments are specified in dwords.
2488 */
2489static u32 qed_grc_dump_mem(struct ecore_hwfn *p_hwfn,
2490                            struct ecore_ptt *p_ptt,
2491                            u32 *dump_buf,
2492                            bool dump,
2493                            const char *name,
2494                            u32 addr,
2495                            u32 len,
2496                            bool wide_bus,
2497                            u32 bit_width,
2498                            bool packed,
2499                            const char *mem_group, char storm_letter)
2500{
2501        u32 offset = 0;
2502
2503        offset += qed_grc_dump_mem_hdr(p_hwfn,
2504                                       dump_buf + offset,
2505                                       dump,
2506                                       name,
2507                                       addr,
2508                                       len,
2509                                       bit_width,
2510                                       packed, mem_group, storm_letter);
2511        offset += qed_grc_dump_addr_range(p_hwfn,
2512                                          p_ptt,
2513                                          dump_buf + offset,
2514                                          dump, addr, len, wide_bus,
2515                                          SPLIT_TYPE_NONE, 0);
2516
2517        return offset;
2518}
2519
2520/* Dumps GRC memories entries. Returns the dumped size in dwords. */
2521static u32 qed_grc_dump_mem_entries(struct ecore_hwfn *p_hwfn,
2522                                    struct ecore_ptt *p_ptt,
2523                                    struct virt_mem_desc input_mems_arr,
2524                                    u32 *dump_buf, bool dump)
2525{
2526        u32 i, offset = 0, input_offset = 0;
2527        bool mode_match = true;
2528
2529        while (input_offset < BYTES_TO_DWORDS(input_mems_arr.size)) {
2530                const struct dbg_dump_cond_hdr *cond_hdr;
2531                u16 modes_buf_offset;
2532                u32 num_entries;
2533                bool eval_mode;
2534
2535                cond_hdr =
2536                    (const struct dbg_dump_cond_hdr *)input_mems_arr.ptr +
2537                    input_offset++;
2538                num_entries = cond_hdr->data_size / MEM_DUMP_ENTRY_SIZE_DWORDS;
2539
2540                /* Check required mode */
2541                eval_mode = GET_FIELD(cond_hdr->mode.data,
2542                                      DBG_MODE_HDR_EVAL_MODE) > 0;
2543                if (eval_mode) {
2544                        modes_buf_offset =
2545                                GET_FIELD(cond_hdr->mode.data,
2546                                          DBG_MODE_HDR_MODES_BUF_OFFSET);
2547                        mode_match = qed_is_mode_match(p_hwfn,
2548                                                       &modes_buf_offset);
2549                }
2550
2551                if (!mode_match) {
2552                        input_offset += cond_hdr->data_size;
2553                        continue;
2554                }
2555
2556                for (i = 0; i < num_entries;
2557                     i++, input_offset += MEM_DUMP_ENTRY_SIZE_DWORDS) {
2558                        const struct dbg_dump_mem *mem =
2559                            (const struct dbg_dump_mem *)((u32 *)
2560                                                          input_mems_arr.ptr
2561                                                          + input_offset);
2562                        const struct dbg_block *block;
2563                        char storm_letter = 0;
2564                        u32 mem_addr, mem_len;
2565                        bool mem_wide_bus;
2566                        u8 mem_group_id;
2567
2568                        mem_group_id = GET_FIELD(mem->dword0,
2569                                                 DBG_DUMP_MEM_MEM_GROUP_ID);
2570                        if (mem_group_id >= MEM_GROUPS_NUM) {
2571                                DP_NOTICE(p_hwfn, false, "Invalid mem_group_id\n");
2572                                return 0;
2573                        }
2574
2575                        if (!qed_grc_is_mem_included(p_hwfn,
2576                                                     (enum block_id)
2577                                                     cond_hdr->block_id,
2578                                                     mem_group_id))
2579                                continue;
2580
2581                        mem_addr = GET_FIELD(mem->dword0, DBG_DUMP_MEM_ADDRESS);
2582                        mem_len = GET_FIELD(mem->dword1, DBG_DUMP_MEM_LENGTH);
2583                        mem_wide_bus = GET_FIELD(mem->dword1,
2584                                                 DBG_DUMP_MEM_WIDE_BUS);
2585
2586                        block = get_dbg_block(p_hwfn,
2587                                              cond_hdr->block_id);
2588
2589                        /* If memory is associated with Storm,
2590                         * update storm details
2591                         */
2592                        if (block->associated_storm_letter)
2593                                storm_letter = block->associated_storm_letter;
2594
2595                        /* Dump memory */
2596                        offset += qed_grc_dump_mem(p_hwfn,
2597                                                p_ptt,
2598                                                dump_buf + offset,
2599                                                dump,
2600                                                NULL,
2601                                                mem_addr,
2602                                                mem_len,
2603                                                mem_wide_bus,
2604                                                0,
2605                                                false,
2606                                                s_mem_group_names[mem_group_id],
2607                                                storm_letter);
2608                }
2609        }
2610
2611        return offset;
2612}
2613
2614/* Dumps GRC memories according to the input array dump_mem.
2615 * Returns the dumped size in dwords.
2616 */
2617static u32 qed_grc_dump_memories(struct ecore_hwfn *p_hwfn,
2618                                 struct ecore_ptt *p_ptt,
2619                                 u32 *dump_buf, bool dump)
2620{
2621        struct virt_mem_desc *dbg_buf =
2622            &p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_MEM];
2623        u32 offset = 0, input_offset = 0;
2624
2625        while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
2626                const struct dbg_dump_split_hdr *split_hdr;
2627                struct virt_mem_desc curr_input_mems_arr;
2628                enum init_split_types split_type;
2629                u32 split_data_size;
2630
2631                split_hdr =
2632                    (const struct dbg_dump_split_hdr *)dbg_buf->ptr +
2633                    input_offset++;
2634                split_type = GET_FIELD(split_hdr->hdr,
2635                                       DBG_DUMP_SPLIT_HDR_SPLIT_TYPE_ID);
2636                split_data_size = GET_FIELD(split_hdr->hdr,
2637                                            DBG_DUMP_SPLIT_HDR_DATA_SIZE);
2638                curr_input_mems_arr.ptr = (u32 *)dbg_buf->ptr + input_offset;
2639                curr_input_mems_arr.size = DWORDS_TO_BYTES(split_data_size);
2640
2641                if (split_type == SPLIT_TYPE_NONE)
2642                        offset += qed_grc_dump_mem_entries(p_hwfn,
2643                                                           p_ptt,
2644                                                           curr_input_mems_arr,
2645                                                           dump_buf + offset,
2646                                                           dump);
2647                else
2648                        DP_NOTICE(p_hwfn, false,
2649                                  "Dumping split memories is currently not supported\n");
2650
2651                input_offset += split_data_size;
2652        }
2653
2654        return offset;
2655}
2656
2657/* Dumps GRC context data for the specified Storm.
2658 * Returns the dumped size in dwords.
2659 * The lid_size argument is specified in quad-regs.
2660 */
2661static u32 qed_grc_dump_ctx_data(struct ecore_hwfn *p_hwfn,
2662                                 struct ecore_ptt *p_ptt,
2663                                 u32 *dump_buf,
2664                                 bool dump,
2665                                 const char *name,
2666                                 u32 num_lids,
2667                                 enum cm_ctx_types ctx_type, u8 storm_id)
2668{
2669        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
2670        struct storm_defs *storm = &s_storm_defs[storm_id];
2671        u32 i, lid, lid_size, total_size;
2672        u32 rd_reg_addr, offset = 0;
2673
2674        /* Convert quad-regs to dwords */
2675        lid_size = storm->cm_ctx_lid_sizes[dev_data->chip_id][ctx_type] * 4;
2676
2677        if (!lid_size)
2678                return 0;
2679
2680        total_size = num_lids * lid_size;
2681
2682        offset += qed_grc_dump_mem_hdr(p_hwfn,
2683                                       dump_buf + offset,
2684                                       dump,
2685                                       name,
2686                                       0,
2687                                       total_size,
2688                                       lid_size * 32,
2689                                       false, name, storm->letter);
2690
2691        if (!dump)
2692                return offset + total_size;
2693
2694        rd_reg_addr = BYTES_TO_DWORDS(storm->cm_ctx_rd_addr[ctx_type]);
2695
2696        /* Dump context data */
2697        for (lid = 0; lid < num_lids; lid++) {
2698                for (i = 0; i < lid_size; i++) {
2699                        ecore_wr(p_hwfn,
2700                               p_ptt, storm->cm_ctx_wr_addr, (i << 9) | lid);
2701                        offset += qed_grc_dump_addr_range(p_hwfn,
2702                                                          p_ptt,
2703                                                          dump_buf + offset,
2704                                                          dump,
2705                                                          rd_reg_addr,
2706                                                          1,
2707                                                          false,
2708                                                          SPLIT_TYPE_NONE, 0);
2709                }
2710        }
2711
2712        return offset;
2713}
2714
2715/* Dumps GRC contexts. Returns the dumped size in dwords. */
2716static u32 qed_grc_dump_ctx(struct ecore_hwfn *p_hwfn,
2717                            struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
2718{
2719        u32 offset = 0;
2720        u8 storm_id;
2721
2722        for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
2723                if (!qed_grc_is_storm_included(p_hwfn,
2724                                               (enum dbg_storms)storm_id))
2725                        continue;
2726
2727                /* Dump Conn AG context size */
2728                offset += qed_grc_dump_ctx_data(p_hwfn,
2729                                                p_ptt,
2730                                                dump_buf + offset,
2731                                                dump,
2732                                                "CONN_AG_CTX",
2733                                                NUM_OF_LCIDS,
2734                                                CM_CTX_CONN_AG, storm_id);
2735
2736                /* Dump Conn ST context size */
2737                offset += qed_grc_dump_ctx_data(p_hwfn,
2738                                                p_ptt,
2739                                                dump_buf + offset,
2740                                                dump,
2741                                                "CONN_ST_CTX",
2742                                                NUM_OF_LCIDS,
2743                                                CM_CTX_CONN_ST, storm_id);
2744
2745                /* Dump Task AG context size */
2746                offset += qed_grc_dump_ctx_data(p_hwfn,
2747                                                p_ptt,
2748                                                dump_buf + offset,
2749                                                dump,
2750                                                "TASK_AG_CTX",
2751                                                NUM_OF_LTIDS,
2752                                                CM_CTX_TASK_AG, storm_id);
2753
2754                /* Dump Task ST context size */
2755                offset += qed_grc_dump_ctx_data(p_hwfn,
2756                                                p_ptt,
2757                                                dump_buf + offset,
2758                                                dump,
2759                                                "TASK_ST_CTX",
2760                                                NUM_OF_LTIDS,
2761                                                CM_CTX_TASK_ST, storm_id);
2762        }
2763
2764        return offset;
2765}
2766
2767#define VFC_STATUS_RESP_READY_BIT       0
2768#define VFC_STATUS_BUSY_BIT             1
2769#define VFC_STATUS_SENDING_CMD_BIT      2
2770
2771#define VFC_POLLING_DELAY_MS    1
2772#define VFC_POLLING_COUNT               20
2773
2774/* Reads data from VFC. Returns the number of dwords read (0 on error).
2775 * Sizes are specified in dwords.
2776 */
2777static u32 qed_grc_dump_read_from_vfc(struct ecore_hwfn *p_hwfn,
2778                                      struct ecore_ptt *p_ptt,
2779                                      struct storm_defs *storm,
2780                                      u32 *cmd_data,
2781                                      u32 cmd_size,
2782                                      u32 *addr_data,
2783                                      u32 addr_size,
2784                                      u32 resp_size, u32 *dump_buf)
2785{
2786        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
2787        u32 vfc_status, polling_ms, polling_count = 0, i;
2788        u32 reg_addr, sem_base;
2789        bool is_ready = false;
2790
2791        sem_base = storm->sem_fast_mem_addr;
2792        polling_ms = VFC_POLLING_DELAY_MS *
2793            s_hw_type_defs[dev_data->hw_type].delay_factor;
2794
2795        /* Write VFC command */
2796        ARR_REG_WR(p_hwfn,
2797                   p_ptt,
2798                   sem_base + SEM_FAST_REG_VFC_DATA_WR,
2799                   cmd_data, cmd_size);
2800
2801        /* Write VFC address */
2802        ARR_REG_WR(p_hwfn,
2803                   p_ptt,
2804                   sem_base + SEM_FAST_REG_VFC_ADDR,
2805                   addr_data, addr_size);
2806
2807        /* Read response */
2808        for (i = 0; i < resp_size; i++) {
2809                /* Poll until ready */
2810                do {
2811                        reg_addr = sem_base + SEM_FAST_REG_VFC_STATUS;
2812                        qed_grc_dump_addr_range(p_hwfn,
2813                                                p_ptt,
2814                                                &vfc_status,
2815                                                true,
2816                                                BYTES_TO_DWORDS(reg_addr),
2817                                                1,
2818                                                false, SPLIT_TYPE_NONE, 0);
2819                        is_ready = vfc_status &
2820                                   OSAL_BIT(VFC_STATUS_RESP_READY_BIT);
2821
2822                        if (!is_ready) {
2823                                if (polling_count++ == VFC_POLLING_COUNT)
2824                                        return 0;
2825
2826                                OSAL_MSLEEP(polling_ms);
2827                        }
2828                } while (!is_ready);
2829
2830                reg_addr = sem_base + SEM_FAST_REG_VFC_DATA_RD;
2831                qed_grc_dump_addr_range(p_hwfn,
2832                                        p_ptt,
2833                                        dump_buf + i,
2834                                        true,
2835                                        BYTES_TO_DWORDS(reg_addr),
2836                                        1, false, SPLIT_TYPE_NONE, 0);
2837        }
2838
2839        return resp_size;
2840}
2841
2842/* Dump VFC CAM. Returns the dumped size in dwords. */
2843static u32 qed_grc_dump_vfc_cam(struct ecore_hwfn *p_hwfn,
2844                                struct ecore_ptt *p_ptt,
2845                                u32 *dump_buf, bool dump, u8 storm_id)
2846{
2847        u32 total_size = VFC_CAM_NUM_ROWS * VFC_CAM_RESP_DWORDS;
2848        struct storm_defs *storm = &s_storm_defs[storm_id];
2849        u32 cam_addr[VFC_CAM_ADDR_DWORDS] = { 0 };
2850        u32 cam_cmd[VFC_CAM_CMD_DWORDS] = { 0 };
2851        u32 row, offset = 0;
2852
2853        offset += qed_grc_dump_mem_hdr(p_hwfn,
2854                                       dump_buf + offset,
2855                                       dump,
2856                                       "vfc_cam",
2857                                       0,
2858                                       total_size,
2859                                       256,
2860                                       false, "vfc_cam", storm->letter);
2861
2862        if (!dump)
2863                return offset + total_size;
2864
2865        /* Prepare CAM address */
2866        SET_VAR_FIELD(cam_addr, VFC_CAM_ADDR, OP, VFC_OPCODE_CAM_RD);
2867
2868        /* Read VFC CAM data */
2869        for (row = 0; row < VFC_CAM_NUM_ROWS; row++) {
2870                SET_VAR_FIELD(cam_cmd, VFC_CAM_CMD, ROW, row);
2871                offset += qed_grc_dump_read_from_vfc(p_hwfn,
2872                                                     p_ptt,
2873                                                     storm,
2874                                                     cam_cmd,
2875                                                     VFC_CAM_CMD_DWORDS,
2876                                                     cam_addr,
2877                                                     VFC_CAM_ADDR_DWORDS,
2878                                                     VFC_CAM_RESP_DWORDS,
2879                                                     dump_buf + offset);
2880        }
2881
2882        return offset;
2883}
2884
2885/* Dump VFC RAM. Returns the dumped size in dwords. */
2886static u32 qed_grc_dump_vfc_ram(struct ecore_hwfn *p_hwfn,
2887                                struct ecore_ptt *p_ptt,
2888                                u32 *dump_buf,
2889                                bool dump,
2890                                u8 storm_id, struct vfc_ram_defs *ram_defs)
2891{
2892        u32 total_size = ram_defs->num_rows * VFC_RAM_RESP_DWORDS;
2893        struct storm_defs *storm = &s_storm_defs[storm_id];
2894        u32 ram_addr[VFC_RAM_ADDR_DWORDS] = { 0 };
2895        u32 ram_cmd[VFC_RAM_CMD_DWORDS] = { 0 };
2896        u32 row, offset = 0;
2897
2898        offset += qed_grc_dump_mem_hdr(p_hwfn,
2899                                       dump_buf + offset,
2900                                       dump,
2901                                       ram_defs->mem_name,
2902                                       0,
2903                                       total_size,
2904                                       256,
2905                                       false,
2906                                       ram_defs->type_name,
2907                                       storm->letter);
2908
2909        if (!dump)
2910                return offset + total_size;
2911
2912        /* Prepare RAM address */
2913        SET_VAR_FIELD(ram_addr, VFC_RAM_ADDR, OP, VFC_OPCODE_RAM_RD);
2914
2915        /* Read VFC RAM data */
2916        for (row = ram_defs->base_row;
2917             row < ram_defs->base_row + ram_defs->num_rows; row++) {
2918                SET_VAR_FIELD(ram_addr, VFC_RAM_ADDR, ROW, row);
2919                offset += qed_grc_dump_read_from_vfc(p_hwfn,
2920                                                     p_ptt,
2921                                                     storm,
2922                                                     ram_cmd,
2923                                                     VFC_RAM_CMD_DWORDS,
2924                                                     ram_addr,
2925                                                     VFC_RAM_ADDR_DWORDS,
2926                                                     VFC_RAM_RESP_DWORDS,
2927                                                     dump_buf + offset);
2928        }
2929
2930        return offset;
2931}
2932
2933/* Dumps GRC VFC data. Returns the dumped size in dwords. */
2934static u32 qed_grc_dump_vfc(struct ecore_hwfn *p_hwfn,
2935                            struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
2936{
2937        u8 storm_id, i;
2938        u32 offset = 0;
2939
2940        for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
2941                if (!qed_grc_is_storm_included(p_hwfn,
2942                                               (enum dbg_storms)storm_id) ||
2943                    !s_storm_defs[storm_id].has_vfc)
2944                        continue;
2945
2946                /* Read CAM */
2947                offset += qed_grc_dump_vfc_cam(p_hwfn,
2948                                               p_ptt,
2949                                               dump_buf + offset,
2950                                               dump, storm_id);
2951
2952                /* Read RAM */
2953                for (i = 0; i < NUM_VFC_RAM_TYPES; i++)
2954                        offset += qed_grc_dump_vfc_ram(p_hwfn,
2955                                                       p_ptt,
2956                                                       dump_buf + offset,
2957                                                       dump,
2958                                                       storm_id,
2959                                                       &s_vfc_ram_defs[i]);
2960        }
2961
2962        return offset;
2963}
2964
2965/* Dumps GRC RSS data. Returns the dumped size in dwords. */
2966static u32 qed_grc_dump_rss(struct ecore_hwfn *p_hwfn,
2967                            struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
2968{
2969        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
2970        u32 offset = 0;
2971        u8 rss_mem_id;
2972
2973        for (rss_mem_id = 0; rss_mem_id < NUM_RSS_MEM_TYPES; rss_mem_id++) {
2974                u32 rss_addr, num_entries, total_dwords;
2975                struct rss_mem_defs *rss_defs;
2976                u32 addr, num_dwords_to_read;
2977                bool packed;
2978
2979                rss_defs = &s_rss_mem_defs[rss_mem_id];
2980                rss_addr = rss_defs->addr;
2981                num_entries = rss_defs->num_entries[dev_data->chip_id];
2982                total_dwords = (num_entries * rss_defs->entry_width) / 32;
2983                packed = (rss_defs->entry_width == 16);
2984
2985                offset += qed_grc_dump_mem_hdr(p_hwfn,
2986                                               dump_buf + offset,
2987                                               dump,
2988                                               rss_defs->mem_name,
2989                                               0,
2990                                               total_dwords,
2991                                               rss_defs->entry_width,
2992                                               packed,
2993                                               rss_defs->type_name, 0);
2994
2995                /* Dump RSS data */
2996                if (!dump) {
2997                        offset += total_dwords;
2998                        continue;
2999                }
3000
3001                addr = BYTES_TO_DWORDS(RSS_REG_RSS_RAM_DATA);
3002                while (total_dwords) {
3003                        num_dwords_to_read = OSAL_MIN_T(u32,
3004                                                      RSS_REG_RSS_RAM_DATA_SIZE,
3005                                                      total_dwords);
3006                        ecore_wr(p_hwfn, p_ptt, RSS_REG_RSS_RAM_ADDR, rss_addr);
3007                        offset += qed_grc_dump_addr_range(p_hwfn,
3008                                                          p_ptt,
3009                                                          dump_buf + offset,
3010                                                          dump,
3011                                                          addr,
3012                                                          num_dwords_to_read,
3013                                                          false,
3014                                                          SPLIT_TYPE_NONE, 0);
3015                        total_dwords -= num_dwords_to_read;
3016                        rss_addr++;
3017                }
3018        }
3019
3020        return offset;
3021}
3022
3023/* Dumps GRC Big RAM. Returns the dumped size in dwords. */
3024static u32 qed_grc_dump_big_ram(struct ecore_hwfn *p_hwfn,
3025                                struct ecore_ptt *p_ptt,
3026                                u32 *dump_buf, bool dump, u8 big_ram_id)
3027{
3028        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
3029        u32 block_size, ram_size, offset = 0, reg_val, i;
3030        char mem_name[12] = "???_BIG_RAM";
3031        char type_name[8] = "???_RAM";
3032        struct big_ram_defs *big_ram;
3033
3034        big_ram = &s_big_ram_defs[big_ram_id];
3035        ram_size = big_ram->ram_size[dev_data->chip_id];
3036
3037        reg_val = ecore_rd(p_hwfn, p_ptt, big_ram->is_256b_reg_addr);
3038        block_size = reg_val &
3039                     OSAL_BIT(big_ram->is_256b_bit_offset[dev_data->chip_id]) ?
3040                                                                     256 : 128;
3041
3042        strncpy(type_name, big_ram->instance_name, BIG_RAM_NAME_LEN);
3043        strncpy(mem_name, big_ram->instance_name, BIG_RAM_NAME_LEN);
3044
3045        /* Dump memory header */
3046        offset += qed_grc_dump_mem_hdr(p_hwfn,
3047                                       dump_buf + offset,
3048                                       dump,
3049                                       mem_name,
3050                                       0,
3051                                       ram_size,
3052                                       block_size * 8,
3053                                       false, type_name, 0);
3054
3055        /* Read and dump Big RAM data */
3056        if (!dump)
3057                return offset + ram_size;
3058
3059        /* Dump Big RAM */
3060        for (i = 0; i < DIV_ROUND_UP(ram_size, BRB_REG_BIG_RAM_DATA_SIZE);
3061             i++) {
3062                u32 addr, len;
3063
3064                ecore_wr(p_hwfn, p_ptt, big_ram->addr_reg_addr, i);
3065                addr = BYTES_TO_DWORDS(big_ram->data_reg_addr);
3066                len = BRB_REG_BIG_RAM_DATA_SIZE;
3067                offset += qed_grc_dump_addr_range(p_hwfn,
3068                                                  p_ptt,
3069                                                  dump_buf + offset,
3070                                                  dump,
3071                                                  addr,
3072                                                  len,
3073                                                  false, SPLIT_TYPE_NONE, 0);
3074        }
3075
3076        return offset;
3077}
3078
3079/* Dumps MCP scratchpad. Returns the dumped size in dwords. */
3080static u32 qed_grc_dump_mcp(struct ecore_hwfn *p_hwfn,
3081                            struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
3082{
3083        bool block_enable[MAX_BLOCK_ID] = { 0 };
3084        u32 offset = 0, addr;
3085        bool halted = false;
3086
3087        /* Halt MCP */
3088        if (dump && !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP)) {
3089                halted = !ecore_mcp_halt(p_hwfn, p_ptt);
3090                if (!halted)
3091                        DP_NOTICE(p_hwfn, false, "MCP halt failed!\n");
3092        }
3093
3094        /* Dump MCP scratchpad */
3095        offset += qed_grc_dump_mem(p_hwfn,
3096                                   p_ptt,
3097                                   dump_buf + offset,
3098                                   dump,
3099                                   NULL,
3100                                   BYTES_TO_DWORDS(MCP_REG_SCRATCH),
3101                                   MCP_REG_SCRATCH_SIZE,
3102                                   false, 0, false, "MCP", 0);
3103
3104        /* Dump MCP cpu_reg_file */
3105        offset += qed_grc_dump_mem(p_hwfn,
3106                                   p_ptt,
3107                                   dump_buf + offset,
3108                                   dump,
3109                                   NULL,
3110                                   BYTES_TO_DWORDS(MCP_REG_CPU_REG_FILE),
3111                                   MCP_REG_CPU_REG_FILE_SIZE,
3112                                   false, 0, false, "MCP", 0);
3113
3114        /* Dump MCP registers */
3115        block_enable[BLOCK_MCP] = true;
3116        offset += qed_grc_dump_registers(p_hwfn,
3117                                         p_ptt,
3118                                         dump_buf + offset,
3119                                         dump, block_enable, "MCP");
3120
3121        /* Dump required non-MCP registers */
3122        offset += qed_grc_dump_regs_hdr(dump_buf + offset,
3123                                        dump, 1, SPLIT_TYPE_NONE, 0,
3124                                        "MCP");
3125        addr = BYTES_TO_DWORDS(MISC_REG_SHARED_MEM_ADDR);
3126        offset += qed_grc_dump_reg_entry(p_hwfn,
3127                                         p_ptt,
3128                                         dump_buf + offset,
3129                                         dump,
3130                                         addr,
3131                                         1,
3132                                         false, SPLIT_TYPE_NONE, 0);
3133
3134        /* Release MCP */
3135        if (halted && ecore_mcp_resume(p_hwfn, p_ptt))
3136                DP_NOTICE(p_hwfn, false, "Failed to resume MCP after halt!\n");
3137
3138        return offset;
3139}
3140
3141/* Dumps the tbus indirect memory for all PHYs.
3142 * Returns the dumped size in dwords.
3143 */
3144static u32 qed_grc_dump_phy(struct ecore_hwfn *p_hwfn,
3145                            struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
3146{
3147        u32 offset = 0, tbus_lo_offset, tbus_hi_offset;
3148        char mem_name[32];
3149        u8 phy_id;
3150
3151        for (phy_id = 0; phy_id < OSAL_ARRAY_SIZE(s_phy_defs); phy_id++) {
3152                u32 addr_lo_addr, addr_hi_addr, data_lo_addr, data_hi_addr;
3153                struct phy_defs *phy_defs;
3154                u8 *bytes_buf;
3155
3156                phy_defs = &s_phy_defs[phy_id];
3157                addr_lo_addr = phy_defs->base_addr +
3158                               phy_defs->tbus_addr_lo_addr;
3159                addr_hi_addr = phy_defs->base_addr +
3160                               phy_defs->tbus_addr_hi_addr;
3161                data_lo_addr = phy_defs->base_addr +
3162                               phy_defs->tbus_data_lo_addr;
3163                data_hi_addr = phy_defs->base_addr +
3164                               phy_defs->tbus_data_hi_addr;
3165
3166                if (snprintf(mem_name, sizeof(mem_name), "tbus_%s",
3167                             phy_defs->phy_name) < 0)
3168                        DP_NOTICE(p_hwfn, false,
3169                                  "Unexpected debug error: invalid PHY memory name\n");
3170
3171                offset += qed_grc_dump_mem_hdr(p_hwfn,
3172                                               dump_buf + offset,
3173                                               dump,
3174                                               mem_name,
3175                                               0,
3176                                               PHY_DUMP_SIZE_DWORDS,
3177                                               16, true, mem_name, 0);
3178
3179                if (!dump) {
3180                        offset += PHY_DUMP_SIZE_DWORDS;
3181                        continue;
3182                }
3183
3184                bytes_buf = (u8 *)(dump_buf + offset);
3185                for (tbus_hi_offset = 0;
3186                     tbus_hi_offset < (NUM_PHY_TBUS_ADDRESSES >> 8);
3187                     tbus_hi_offset++) {
3188                        ecore_wr(p_hwfn, p_ptt, addr_hi_addr, tbus_hi_offset);
3189                        for (tbus_lo_offset = 0; tbus_lo_offset < 256;
3190                             tbus_lo_offset++) {
3191                                ecore_wr(p_hwfn,
3192                                       p_ptt, addr_lo_addr, tbus_lo_offset);
3193                                *(bytes_buf++) = (u8)ecore_rd(p_hwfn,
3194                                                            p_ptt,
3195                                                            data_lo_addr);
3196                                *(bytes_buf++) = (u8)ecore_rd(p_hwfn,
3197                                                            p_ptt,
3198                                                            data_hi_addr);
3199                        }
3200                }
3201
3202                offset += PHY_DUMP_SIZE_DWORDS;
3203        }
3204
3205        return offset;
3206}
3207
3208static enum dbg_status qed_find_nvram_image(struct ecore_hwfn *p_hwfn,
3209                                            struct ecore_ptt *p_ptt,
3210                                            u32 image_type,
3211                                            u32 *nvram_offset_bytes,
3212                                            u32 *nvram_size_bytes);
3213
3214static enum dbg_status qed_nvram_read(struct ecore_hwfn *p_hwfn,
3215                                      struct ecore_ptt *p_ptt,
3216                                      u32 nvram_offset_bytes,
3217                                      u32 nvram_size_bytes, u32 *ret_buf);
3218
3219/* Dumps the MCP HW dump from NVRAM. Returns the dumped size in dwords. */
3220static u32 qed_grc_dump_mcp_hw_dump(struct ecore_hwfn *p_hwfn,
3221                                    struct ecore_ptt *p_ptt,
3222                                    u32 *dump_buf, bool dump)
3223{
3224        u32 hw_dump_offset_bytes = 0, hw_dump_size_bytes = 0;
3225        u32 hw_dump_size_dwords = 0, offset = 0;
3226        enum dbg_status status;
3227
3228        /* Read HW dump image from NVRAM */
3229        status = qed_find_nvram_image(p_hwfn,
3230                                      p_ptt,
3231                                      NVM_TYPE_HW_DUMP_OUT,
3232                                      &hw_dump_offset_bytes,
3233                                      &hw_dump_size_bytes);
3234        if (status != DBG_STATUS_OK)
3235                return 0;
3236
3237        hw_dump_size_dwords = BYTES_TO_DWORDS(hw_dump_size_bytes);
3238
3239        /* Dump HW dump image section */
3240        offset += qed_dump_section_hdr(dump_buf + offset,
3241                                       dump, "mcp_hw_dump", 1);
3242        offset += qed_dump_num_param(dump_buf + offset,
3243                                     dump, "size", hw_dump_size_dwords);
3244
3245        /* Read MCP HW dump image into dump buffer */
3246        if (dump && hw_dump_size_dwords) {
3247                status = qed_nvram_read(p_hwfn,
3248                                        p_ptt,
3249                                        hw_dump_offset_bytes,
3250                                        hw_dump_size_bytes, dump_buf + offset);
3251                if (status != DBG_STATUS_OK) {
3252                        DP_NOTICE(p_hwfn, false,
3253                                  "Failed to read MCP HW Dump image from NVRAM\n");
3254                        return 0;
3255                }
3256        }
3257        offset += hw_dump_size_dwords;
3258
3259        return offset;
3260}
3261
3262/* Dumps Static Debug data. Returns the dumped size in dwords. */
3263static u32 qed_grc_dump_static_debug(struct ecore_hwfn *p_hwfn,
3264                                     struct ecore_ptt *p_ptt,
3265                                     u32 *dump_buf, bool dump)
3266{
3267        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
3268        u32 block_id, line_id, offset = 0, addr, len;
3269
3270        /* Don't dump static debug if a debug bus recording is in progress */
3271        if (dump && ecore_rd(p_hwfn, p_ptt, DBG_REG_DBG_BLOCK_ON))
3272                return 0;
3273
3274        if (dump) {
3275                /* Disable debug bus in all blocks */
3276                qed_bus_disable_blocks(p_hwfn, p_ptt);
3277
3278                qed_bus_reset_dbg_block(p_hwfn, p_ptt);
3279                ecore_wr(p_hwfn,
3280                       p_ptt, DBG_REG_FRAMING_MODE, DBG_BUS_FRAME_MODE_8HW);
3281                ecore_wr(p_hwfn,
3282                       p_ptt, DBG_REG_DEBUG_TARGET, DBG_BUS_TARGET_ID_INT_BUF);
3283                ecore_wr(p_hwfn, p_ptt, DBG_REG_FULL_MODE, 1);
3284                qed_bus_enable_dbg_block(p_hwfn, p_ptt, true);
3285        }
3286
3287        /* Dump all static debug lines for each relevant block */
3288        for (block_id = 0; block_id < MAX_BLOCK_ID; block_id++) {
3289                const struct dbg_block_chip *block_per_chip;
3290                const struct dbg_block *block;
3291                bool is_removed, has_dbg_bus;
3292                u16 modes_buf_offset;
3293                u32 block_dwords;
3294
3295                block_per_chip =
3296                    qed_get_dbg_block_per_chip(p_hwfn, (enum block_id)block_id);
3297                is_removed = GET_FIELD(block_per_chip->flags,
3298                                       DBG_BLOCK_CHIP_IS_REMOVED);
3299                has_dbg_bus = GET_FIELD(block_per_chip->flags,
3300                                        DBG_BLOCK_CHIP_HAS_DBG_BUS);
3301
3302                /* read+clear for NWS parity is not working, skip NWS block */
3303                if (block_id == BLOCK_NWS)
3304                        continue;
3305
3306                if (!is_removed && has_dbg_bus &&
3307                    GET_FIELD(block_per_chip->dbg_bus_mode.data,
3308                              DBG_MODE_HDR_EVAL_MODE) > 0) {
3309                        modes_buf_offset =
3310                            GET_FIELD(block_per_chip->dbg_bus_mode.data,
3311                                      DBG_MODE_HDR_MODES_BUF_OFFSET);
3312                        if (!qed_is_mode_match(p_hwfn, &modes_buf_offset))
3313                                has_dbg_bus = false;
3314                }
3315
3316                if (is_removed || !has_dbg_bus)
3317                        continue;
3318
3319                block_dwords = NUM_DBG_LINES(block_per_chip) *
3320                               STATIC_DEBUG_LINE_DWORDS;
3321
3322                /* Dump static section params */
3323                block = get_dbg_block(p_hwfn, (enum block_id)block_id);
3324                offset += qed_grc_dump_mem_hdr(p_hwfn,
3325                                               dump_buf + offset,
3326                                               dump,
3327                                               (const char *)block->name,
3328                                               0,
3329                                               block_dwords,
3330                                               32, false, "STATIC", 0);
3331
3332                if (!dump) {
3333                        offset += block_dwords;
3334                        continue;
3335                }
3336
3337                /* If all lines are invalid - dump zeros */
3338                if (dev_data->block_in_reset[block_id]) {
3339                        memset(dump_buf + offset, 0,
3340                               DWORDS_TO_BYTES(block_dwords));
3341                        offset += block_dwords;
3342                        continue;
3343                }
3344
3345                /* Enable block's client */
3346                qed_bus_enable_clients(p_hwfn,
3347                                       p_ptt,
3348                                       OSAL_BIT(block_per_chip->dbg_client_id));
3349
3350                addr = BYTES_TO_DWORDS(DBG_REG_CALENDAR_OUT_DATA);
3351                len = STATIC_DEBUG_LINE_DWORDS;
3352                for (line_id = 0; line_id < (u32)NUM_DBG_LINES(block_per_chip);
3353                     line_id++) {
3354                        /* Configure debug line ID */
3355                        qed_bus_config_dbg_line(p_hwfn,
3356                                                p_ptt,
3357                                                (enum block_id)block_id,
3358                                                (u8)line_id, 0xf, 0, 0, 0);
3359
3360                        /* Read debug line info */
3361                        offset += qed_grc_dump_addr_range(p_hwfn,
3362                                                          p_ptt,
3363                                                          dump_buf + offset,
3364                                                          dump,
3365                                                          addr,
3366                                                          len,
3367                                                          true, SPLIT_TYPE_NONE,
3368                                                          0);
3369                }
3370
3371                /* Disable block's client and debug output */
3372                qed_bus_enable_clients(p_hwfn, p_ptt, 0);
3373                qed_bus_config_dbg_line(p_hwfn, p_ptt,
3374                                        (enum block_id)block_id, 0, 0, 0, 0, 0);
3375        }
3376
3377        if (dump) {
3378                qed_bus_enable_dbg_block(p_hwfn, p_ptt, false);
3379                qed_bus_enable_clients(p_hwfn, p_ptt, 0);
3380        }
3381
3382        return offset;
3383}
3384
3385/* Performs GRC Dump to the specified buffer.
3386 * Returns the dumped size in dwords.
3387 */
3388static enum dbg_status qed_grc_dump(struct ecore_hwfn *p_hwfn,
3389                                    struct ecore_ptt *p_ptt,
3390                                    u32 *dump_buf,
3391                                    bool dump, u32 *num_dumped_dwords)
3392{
3393        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
3394        u32 dwords_read, offset = 0;
3395        bool parities_masked = false;
3396        u8 i;
3397
3398        *num_dumped_dwords = 0;
3399        dev_data->num_regs_read = 0;
3400
3401        /* Update reset state */
3402        if (dump)
3403                qed_update_blocks_reset_state(p_hwfn, p_ptt);
3404
3405        /* Dump global params */
3406        offset += qed_dump_common_global_params(p_hwfn,
3407                                                p_ptt,
3408                                                dump_buf + offset, dump, 4);
3409        offset += qed_dump_str_param(dump_buf + offset,
3410                                     dump, "dump-type", "grc-dump");
3411        offset += qed_dump_num_param(dump_buf + offset,
3412                                     dump,
3413                                     "num-lcids",
3414                                     NUM_OF_LCIDS);
3415        offset += qed_dump_num_param(dump_buf + offset,
3416                                     dump,
3417                                     "num-ltids",
3418                                     NUM_OF_LTIDS);
3419        offset += qed_dump_num_param(dump_buf + offset,
3420                                     dump, "num-ports", dev_data->num_ports);
3421
3422        /* Dump reset registers (dumped before taking blocks out of reset ) */
3423        if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS))
3424                offset += qed_grc_dump_reset_regs(p_hwfn,
3425                                                  p_ptt,
3426                                                  dump_buf + offset, dump);
3427
3428        /* Take all blocks out of reset (using reset registers) */
3429        if (dump) {
3430                qed_grc_unreset_blocks(p_hwfn, p_ptt, false);
3431                qed_update_blocks_reset_state(p_hwfn, p_ptt);
3432        }
3433
3434        /* Disable all parities using MFW command */
3435        if (dump &&
3436            !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP)) {
3437                parities_masked = !ecore_mcp_mask_parities(p_hwfn, p_ptt, 1);
3438                if (!parities_masked) {
3439                        DP_NOTICE(p_hwfn, false,
3440                                  "Failed to mask parities using MFW\n");
3441                        if (qed_grc_get_param
3442                            (p_hwfn, DBG_GRC_PARAM_PARITY_SAFE))
3443                                return DBG_STATUS_MCP_COULD_NOT_MASK_PRTY;
3444                }
3445        }
3446
3447        /* Dump modified registers (dumped before modifying them) */
3448        if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS))
3449                offset += qed_grc_dump_modified_regs(p_hwfn,
3450                                                     p_ptt,
3451                                                     dump_buf + offset, dump);
3452
3453        /* Stall storms */
3454        if (dump &&
3455            (qed_grc_is_included(p_hwfn,
3456                                 DBG_GRC_PARAM_DUMP_IOR) ||
3457             qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_VFC)))
3458                qed_grc_stall_storms(p_hwfn, p_ptt, true);
3459
3460        /* Dump all regs  */
3461        if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_REGS)) {
3462                bool block_enable[MAX_BLOCK_ID];
3463
3464                /* Dump all blocks except MCP */
3465                for (i = 0; i < MAX_BLOCK_ID; i++)
3466                        block_enable[i] = true;
3467                block_enable[BLOCK_MCP] = false;
3468                offset += qed_grc_dump_registers(p_hwfn,
3469                                                 p_ptt,
3470                                                 dump_buf +
3471                                                 offset,
3472                                                 dump,
3473                                                 block_enable, NULL);
3474
3475                /* Dump special registers */
3476                offset += qed_grc_dump_special_regs(p_hwfn,
3477                                                    p_ptt,
3478                                                    dump_buf + offset, dump);
3479        }
3480
3481        /* Dump memories */
3482        offset += qed_grc_dump_memories(p_hwfn, p_ptt, dump_buf + offset, dump);
3483
3484        /* Dump MCP */
3485        if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MCP))
3486                offset += qed_grc_dump_mcp(p_hwfn,
3487                                           p_ptt, dump_buf + offset, dump);
3488
3489        /* Dump context */
3490        if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_CM_CTX))
3491                offset += qed_grc_dump_ctx(p_hwfn,
3492                                           p_ptt, dump_buf + offset, dump);
3493
3494        /* Dump RSS memories */
3495        if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_RSS))
3496                offset += qed_grc_dump_rss(p_hwfn,
3497                                           p_ptt, dump_buf + offset, dump);
3498
3499        /* Dump Big RAM */
3500        for (i = 0; i < NUM_BIG_RAM_TYPES; i++)
3501                if (qed_grc_is_included(p_hwfn, s_big_ram_defs[i].grc_param))
3502                        offset += qed_grc_dump_big_ram(p_hwfn,
3503                                                       p_ptt,
3504                                                       dump_buf + offset,
3505                                                       dump, i);
3506
3507        /* Dump VFC */
3508        if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_VFC)) {
3509                dwords_read = qed_grc_dump_vfc(p_hwfn,
3510                                               p_ptt, dump_buf + offset, dump);
3511                offset += dwords_read;
3512                if (!dwords_read)
3513                        return DBG_STATUS_VFC_READ_ERROR;
3514        }
3515
3516        /* Dump PHY tbus */
3517        if (qed_grc_is_included(p_hwfn,
3518                                DBG_GRC_PARAM_DUMP_PHY) && dev_data->chip_id ==
3519            CHIP_K2 && dev_data->hw_type == HW_TYPE_ASIC)
3520                offset += qed_grc_dump_phy(p_hwfn,
3521                                           p_ptt, dump_buf + offset, dump);
3522
3523        /* Dump MCP HW Dump */
3524        if (qed_grc_is_included(p_hwfn, DBG_GRC_PARAM_DUMP_MCP_HW_DUMP) &&
3525            !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP) && 1)
3526                offset += qed_grc_dump_mcp_hw_dump(p_hwfn,
3527                                                   p_ptt,
3528                                                   dump_buf + offset, dump);
3529
3530        /* Dump static debug data (only if not during debug bus recording) */
3531        if (qed_grc_is_included(p_hwfn,
3532                                DBG_GRC_PARAM_DUMP_STATIC) &&
3533            (!dump || dev_data->bus.state == DBG_BUS_STATE_IDLE))
3534                offset += qed_grc_dump_static_debug(p_hwfn,
3535                                                    p_ptt,
3536                                                    dump_buf + offset, dump);
3537
3538        /* Dump last section */
3539        offset += qed_dump_last_section(dump_buf, offset, dump);
3540
3541        if (dump) {
3542                /* Unstall storms */
3543                if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_UNSTALL))
3544                        qed_grc_stall_storms(p_hwfn, p_ptt, false);
3545
3546                /* Clear parity status */
3547                qed_grc_clear_all_prty(p_hwfn, p_ptt);
3548
3549                /* Enable all parities using MFW command */
3550                if (parities_masked)
3551                        ecore_mcp_mask_parities(p_hwfn, p_ptt, 0);
3552        }
3553
3554        *num_dumped_dwords = offset;
3555
3556        return DBG_STATUS_OK;
3557}
3558
3559/* Writes the specified failing Idle Check rule to the specified buffer.
3560 * Returns the dumped size in dwords.
3561 */
3562static u32 qed_idle_chk_dump_failure(struct ecore_hwfn *p_hwfn,
3563                                     struct ecore_ptt *p_ptt,
3564                                     u32 *
3565                                     dump_buf,
3566                                     bool dump,
3567                                     u16 rule_id,
3568                                     const struct dbg_idle_chk_rule *rule,
3569                                     u16 fail_entry_id, u32 *cond_reg_values)
3570{
3571        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
3572        const struct dbg_idle_chk_cond_reg *cond_regs;
3573        const struct dbg_idle_chk_info_reg *info_regs;
3574        u32 i, next_reg_offset = 0, offset = 0;
3575        struct dbg_idle_chk_result_hdr *hdr;
3576        const union dbg_idle_chk_reg *regs;
3577        u8 reg_id;
3578
3579        hdr = (struct dbg_idle_chk_result_hdr *)dump_buf;
3580        regs = (const union dbg_idle_chk_reg *)
3581                p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr +
3582                rule->reg_offset;
3583        cond_regs = &regs[0].cond_reg;
3584        info_regs = &regs[rule->num_cond_regs].info_reg;
3585
3586        /* Dump rule data */
3587        if (dump) {
3588                memset(hdr, 0, sizeof(*hdr));
3589                hdr->rule_id = rule_id;
3590                hdr->mem_entry_id = fail_entry_id;
3591                hdr->severity = rule->severity;
3592                hdr->num_dumped_cond_regs = rule->num_cond_regs;
3593        }
3594
3595        offset += IDLE_CHK_RESULT_HDR_DWORDS;
3596
3597        /* Dump condition register values */
3598        for (reg_id = 0; reg_id < rule->num_cond_regs; reg_id++) {
3599                const struct dbg_idle_chk_cond_reg *reg = &cond_regs[reg_id];
3600                struct dbg_idle_chk_result_reg_hdr *reg_hdr;
3601
3602                reg_hdr =
3603                    (struct dbg_idle_chk_result_reg_hdr *)(dump_buf + offset);
3604
3605                /* Write register header */
3606                if (!dump) {
3607                        offset += IDLE_CHK_RESULT_REG_HDR_DWORDS +
3608                            reg->entry_size;
3609                        continue;
3610                }
3611
3612                offset += IDLE_CHK_RESULT_REG_HDR_DWORDS;
3613                memset(reg_hdr, 0, sizeof(*reg_hdr));
3614                reg_hdr->start_entry = reg->start_entry;
3615                reg_hdr->size = reg->entry_size;
3616                SET_FIELD(reg_hdr->data,
3617                          DBG_IDLE_CHK_RESULT_REG_HDR_IS_MEM,
3618                          reg->num_entries > 1 || reg->start_entry > 0 ? 1 : 0);
3619                SET_FIELD(reg_hdr->data,
3620                          DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID, reg_id);
3621
3622                /* Write register values */
3623                for (i = 0; i < reg_hdr->size; i++, next_reg_offset++, offset++)
3624                        dump_buf[offset] = cond_reg_values[next_reg_offset];
3625        }
3626
3627        /* Dump info register values */
3628        for (reg_id = 0; reg_id < rule->num_info_regs; reg_id++) {
3629                const struct dbg_idle_chk_info_reg *reg = &info_regs[reg_id];
3630                u32 block_id;
3631
3632                /* Check if register's block is in reset */
3633                if (!dump) {
3634                        offset += IDLE_CHK_RESULT_REG_HDR_DWORDS + reg->size;
3635                        continue;
3636                }
3637
3638                block_id = GET_FIELD(reg->data, DBG_IDLE_CHK_INFO_REG_BLOCK_ID);
3639                if (block_id >= MAX_BLOCK_ID) {
3640                        DP_NOTICE(p_hwfn, false, "Invalid block_id\n");
3641                        return 0;
3642                }
3643
3644                if (!dev_data->block_in_reset[block_id]) {
3645                        struct dbg_idle_chk_result_reg_hdr *reg_hdr;
3646                        bool wide_bus, eval_mode, mode_match = true;
3647                        u16 modes_buf_offset;
3648                        u32 addr;
3649
3650                        reg_hdr = (struct dbg_idle_chk_result_reg_hdr *)
3651                                  (dump_buf + offset);
3652
3653                        /* Check mode */
3654                        eval_mode = GET_FIELD(reg->mode.data,
3655                                              DBG_MODE_HDR_EVAL_MODE) > 0;
3656                        if (eval_mode) {
3657                                modes_buf_offset =
3658                                    GET_FIELD(reg->mode.data,
3659                                              DBG_MODE_HDR_MODES_BUF_OFFSET);
3660                                mode_match =
3661                                        qed_is_mode_match(p_hwfn,
3662                                                          &modes_buf_offset);
3663                        }
3664
3665                        if (!mode_match)
3666                                continue;
3667
3668                        addr = GET_FIELD(reg->data,
3669                                         DBG_IDLE_CHK_INFO_REG_ADDRESS);
3670                        wide_bus = GET_FIELD(reg->data,
3671                                             DBG_IDLE_CHK_INFO_REG_WIDE_BUS);
3672
3673                        /* Write register header */
3674                        offset += IDLE_CHK_RESULT_REG_HDR_DWORDS;
3675                        hdr->num_dumped_info_regs++;
3676                        memset(reg_hdr, 0, sizeof(*reg_hdr));
3677                        reg_hdr->size = reg->size;
3678                        SET_FIELD(reg_hdr->data,
3679                                  DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID,
3680                                  rule->num_cond_regs + reg_id);
3681
3682                        /* Write register values */
3683                        offset += qed_grc_dump_addr_range(p_hwfn,
3684                                                          p_ptt,
3685                                                          dump_buf + offset,
3686                                                          dump,
3687                                                          addr,
3688                                                          reg->size, wide_bus,
3689                                                          SPLIT_TYPE_NONE, 0);
3690                }
3691        }
3692
3693        return offset;
3694}
3695
3696/* Dumps idle check rule entries. Returns the dumped size in dwords. */
3697static u32
3698qed_idle_chk_dump_rule_entries(struct ecore_hwfn *p_hwfn,
3699                               struct ecore_ptt *p_ptt,
3700                               u32 *dump_buf, bool dump,
3701                               const struct dbg_idle_chk_rule *input_rules,
3702                               u32 num_input_rules, u32 *num_failing_rules)
3703{
3704        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
3705        u32 cond_reg_values[IDLE_CHK_MAX_ENTRIES_SIZE];
3706        u32 i, offset = 0;
3707        u16 entry_id;
3708        u8 reg_id;
3709
3710        *num_failing_rules = 0;
3711
3712        for (i = 0; i < num_input_rules; i++) {
3713                const struct dbg_idle_chk_cond_reg *cond_regs;
3714                const struct dbg_idle_chk_rule *rule;
3715                const union dbg_idle_chk_reg *regs;
3716                u16 num_reg_entries = 1;
3717                bool check_rule = true;
3718                const u32 *imm_values;
3719
3720                rule = &input_rules[i];
3721                regs = (const union dbg_idle_chk_reg *)
3722                        p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr +
3723                        rule->reg_offset;
3724                cond_regs = &regs[0].cond_reg;
3725                imm_values =
3726                    (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_IMMS].ptr +
3727                    rule->imm_offset;
3728
3729                /* Check if all condition register blocks are out of reset, and
3730                 * find maximal number of entries (all condition registers that
3731                 * are memories must have the same size, which is > 1).
3732                 */
3733                for (reg_id = 0; reg_id < rule->num_cond_regs && check_rule;
3734                     reg_id++) {
3735                        u32 block_id =
3736                                GET_FIELD(cond_regs[reg_id].data,
3737                                          DBG_IDLE_CHK_COND_REG_BLOCK_ID);
3738
3739                        if (block_id >= MAX_BLOCK_ID) {
3740                                DP_NOTICE(p_hwfn, false, "Invalid block_id\n");
3741                                return 0;
3742                        }
3743
3744                        check_rule = !dev_data->block_in_reset[block_id];
3745                        if (cond_regs[reg_id].num_entries > num_reg_entries)
3746                                num_reg_entries = cond_regs[reg_id].num_entries;
3747                }
3748
3749                if (!check_rule && dump)
3750                        continue;
3751
3752                if (!dump) {
3753                        u32 entry_dump_size =
3754                                qed_idle_chk_dump_failure(p_hwfn,
3755                                                          p_ptt,
3756                                                          dump_buf + offset,
3757                                                          false,
3758                                                          rule->rule_id,
3759                                                          rule,
3760                                                          0,
3761                                                          NULL);
3762
3763                        offset += num_reg_entries * entry_dump_size;
3764                        (*num_failing_rules) += num_reg_entries;
3765                        continue;
3766                }
3767
3768                /* Go over all register entries (number of entries is the same
3769                 * for all condition registers).
3770                 */
3771                for (entry_id = 0; entry_id < num_reg_entries; entry_id++) {
3772                        u32 next_reg_offset = 0;
3773
3774                        /* Read current entry of all condition registers */
3775                        for (reg_id = 0; reg_id < rule->num_cond_regs;
3776                             reg_id++) {
3777                                const struct dbg_idle_chk_cond_reg *reg =
3778                                        &cond_regs[reg_id];
3779                                u32 padded_entry_size, addr;
3780                                bool wide_bus;
3781
3782                                /* Find GRC address (if it's a memory, the
3783                                 * address of the specific entry is calculated).
3784                                 */
3785                                addr = GET_FIELD(reg->data,
3786                                                 DBG_IDLE_CHK_COND_REG_ADDRESS);
3787                                wide_bus =
3788                                    GET_FIELD(reg->data,
3789                                              DBG_IDLE_CHK_COND_REG_WIDE_BUS);
3790                                if (reg->num_entries > 1 ||
3791                                    reg->start_entry > 0) {
3792                                        padded_entry_size =
3793                                           reg->entry_size > 1 ?
3794                                           OSAL_ROUNDUP_POW_OF_TWO(reg->entry_size) :
3795                                           1;
3796                                        addr += (reg->start_entry + entry_id) *
3797                                                padded_entry_size;
3798                                }
3799
3800                                /* Read registers */
3801                                if (next_reg_offset + reg->entry_size >=
3802                                    IDLE_CHK_MAX_ENTRIES_SIZE) {
3803                                        DP_NOTICE(p_hwfn, false,
3804                                                  "idle check registers entry is too large\n");
3805                                        return 0;
3806                                }
3807
3808                                next_reg_offset +=
3809                                    qed_grc_dump_addr_range(p_hwfn, p_ptt,
3810                                                            cond_reg_values +
3811                                                            next_reg_offset,
3812                                                            dump, addr,
3813                                                            reg->entry_size,
3814                                                            wide_bus,
3815                                                            SPLIT_TYPE_NONE, 0);
3816                        }
3817
3818                        /* Call rule condition function.
3819                         * If returns true, it's a failure.
3820                         */
3821                        if ((*cond_arr[rule->cond_id]) (cond_reg_values,
3822                                                        imm_values)) {
3823                                offset += qed_idle_chk_dump_failure(p_hwfn,
3824                                                        p_ptt,
3825                                                        dump_buf + offset,
3826                                                        dump,
3827                                                        rule->rule_id,
3828                                                        rule,
3829                                                        entry_id,
3830                                                        cond_reg_values);
3831                                (*num_failing_rules)++;
3832                        }
3833                }
3834        }
3835
3836        return offset;
3837}
3838
3839/* Performs Idle Check Dump to the specified buffer.
3840 * Returns the dumped size in dwords.
3841 */
3842static u32 qed_idle_chk_dump(struct ecore_hwfn *p_hwfn,
3843                             struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
3844{
3845        struct virt_mem_desc *dbg_buf =
3846            &p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_RULES];
3847        u32 num_failing_rules_offset, offset = 0,
3848            input_offset = 0, num_failing_rules = 0;
3849
3850        /* Dump global params  - 1 must match below amount of params */
3851        offset += qed_dump_common_global_params(p_hwfn,
3852                                                p_ptt,
3853                                                dump_buf + offset, dump, 1);
3854        offset += qed_dump_str_param(dump_buf + offset,
3855                                     dump, "dump-type", "idle-chk");
3856
3857        /* Dump idle check section header with a single parameter */
3858        offset += qed_dump_section_hdr(dump_buf + offset, dump, "idle_chk", 1);
3859        num_failing_rules_offset = offset;
3860        offset += qed_dump_num_param(dump_buf + offset, dump, "num_rules", 0);
3861
3862        while (input_offset < BYTES_TO_DWORDS(dbg_buf->size)) {
3863                const struct dbg_idle_chk_cond_hdr *cond_hdr =
3864                    (const struct dbg_idle_chk_cond_hdr *)dbg_buf->ptr +
3865                    input_offset++;
3866                bool eval_mode, mode_match = true;
3867                u32 curr_failing_rules;
3868                u16 modes_buf_offset;
3869
3870                /* Check mode */
3871                eval_mode = GET_FIELD(cond_hdr->mode.data,
3872                                      DBG_MODE_HDR_EVAL_MODE) > 0;
3873                if (eval_mode) {
3874                        modes_buf_offset =
3875                                GET_FIELD(cond_hdr->mode.data,
3876                                          DBG_MODE_HDR_MODES_BUF_OFFSET);
3877                        mode_match = qed_is_mode_match(p_hwfn,
3878                                                       &modes_buf_offset);
3879                }
3880
3881                if (mode_match) {
3882                        const struct dbg_idle_chk_rule *rule =
3883                            (const struct dbg_idle_chk_rule *)((u32 *)
3884                                                               dbg_buf->ptr
3885                                                               + input_offset);
3886                        u32 num_input_rules =
3887                                cond_hdr->data_size / IDLE_CHK_RULE_SIZE_DWORDS;
3888                        offset +=
3889                            qed_idle_chk_dump_rule_entries(p_hwfn,
3890                                                           p_ptt,
3891                                                           dump_buf +
3892                                                           offset,
3893                                                           dump,
3894                                                           rule,
3895                                                           num_input_rules,
3896                                                           &curr_failing_rules);
3897                        num_failing_rules += curr_failing_rules;
3898                }
3899
3900                input_offset += cond_hdr->data_size;
3901        }
3902
3903        /* Overwrite num_rules parameter */
3904        if (dump)
3905                qed_dump_num_param(dump_buf + num_failing_rules_offset,
3906                                   dump, "num_rules", num_failing_rules);
3907
3908        /* Dump last section */
3909        offset += qed_dump_last_section(dump_buf, offset, dump);
3910
3911        return offset;
3912}
3913
3914/* Finds the meta data image in NVRAM */
3915static enum dbg_status qed_find_nvram_image(struct ecore_hwfn *p_hwfn,
3916                                            struct ecore_ptt *p_ptt,
3917                                            u32 image_type,
3918                                            u32 *nvram_offset_bytes,
3919                                            u32 *nvram_size_bytes)
3920{
3921        u32 ret_mcp_resp, ret_mcp_param, ret_txn_size;
3922        struct mcp_file_att file_att;
3923        int nvm_result;
3924
3925        /* Call NVRAM get file command */
3926        nvm_result = ecore_mcp_nvm_rd_cmd(p_hwfn,
3927                                        p_ptt,
3928                                        DRV_MSG_CODE_NVM_GET_FILE_ATT,
3929                                        image_type,
3930                                        &ret_mcp_resp,
3931                                        &ret_mcp_param,
3932                                        &ret_txn_size, (u32 *)&file_att);
3933
3934        /* Check response */
3935        if (nvm_result ||
3936            (ret_mcp_resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_NVM_OK)
3937                return DBG_STATUS_NVRAM_GET_IMAGE_FAILED;
3938
3939        /* Update return values */
3940        *nvram_offset_bytes = file_att.nvm_start_addr;
3941        *nvram_size_bytes = file_att.len;
3942
3943        DP_VERBOSE(p_hwfn->p_dev,
3944                   ECORE_MSG_DEBUG,
3945                   "find_nvram_image: found NVRAM image of type %d in NVRAM offset %d bytes with size %d bytes\n",
3946                   image_type, *nvram_offset_bytes, *nvram_size_bytes);
3947
3948        /* Check alignment */
3949        if (*nvram_size_bytes & 0x3)
3950                return DBG_STATUS_NON_ALIGNED_NVRAM_IMAGE;
3951
3952        return DBG_STATUS_OK;
3953}
3954
3955/* Reads data from NVRAM */
3956static enum dbg_status qed_nvram_read(struct ecore_hwfn *p_hwfn,
3957                                      struct ecore_ptt *p_ptt,
3958                                      u32 nvram_offset_bytes,
3959                                      u32 nvram_size_bytes, u32 *ret_buf)
3960{
3961        u32 ret_mcp_resp, ret_mcp_param, ret_read_size, bytes_to_copy;
3962        s32 bytes_left = nvram_size_bytes;
3963        u32 read_offset = 0, param = 0;
3964
3965        DP_NOTICE(p_hwfn->p_dev, false,
3966                   "nvram_read: reading image of size %d bytes from NVRAM\n",
3967                   nvram_size_bytes);
3968
3969        do {
3970                bytes_to_copy =
3971                    (bytes_left >
3972                     MCP_DRV_NVM_BUF_LEN) ? MCP_DRV_NVM_BUF_LEN : bytes_left;
3973
3974                /* Call NVRAM read command */
3975                SET_MFW_FIELD(param,
3976                              DRV_MB_PARAM_NVM_OFFSET,
3977                              nvram_offset_bytes + read_offset);
3978                SET_MFW_FIELD(param, DRV_MB_PARAM_NVM_LEN, bytes_to_copy);
3979                if (ecore_mcp_nvm_rd_cmd(p_hwfn, p_ptt,
3980                                         DRV_MSG_CODE_NVM_READ_NVRAM, param,
3981                                         &ret_mcp_resp,
3982                                         &ret_mcp_param, &ret_read_size,
3983                                         (u32 *)((u8 *)ret_buf +
3984                                                 read_offset))) {
3985                        DP_NOTICE(p_hwfn->p_dev, false, "rc = DBG_STATUS_NVRAM_READ_FAILED\n");
3986                        return DBG_STATUS_NVRAM_READ_FAILED;
3987                }
3988
3989                /* Check response */
3990                if ((ret_mcp_resp & FW_MSG_CODE_MASK) != FW_MSG_CODE_NVM_OK) {
3991                        DP_NOTICE(p_hwfn->p_dev, false, "rc = DBG_STATUS_NVRAM_READ_FAILED\n");
3992                        return DBG_STATUS_NVRAM_READ_FAILED;
3993                }
3994
3995                /* Update read offset */
3996                read_offset += ret_read_size;
3997                bytes_left -= ret_read_size;
3998        } while (bytes_left > 0);
3999
4000        return DBG_STATUS_OK;
4001}
4002
4003/* Get info on the MCP Trace data in the scratchpad:
4004 * - trace_data_grc_addr (OUT): trace data GRC address in bytes
4005 * - trace_data_size (OUT): trace data size in bytes (without the header)
4006 */
4007static enum dbg_status qed_mcp_trace_get_data_info(struct ecore_hwfn *p_hwfn,
4008                                                   struct ecore_ptt *p_ptt,
4009                                                   u32 *trace_data_grc_addr,
4010                                                   u32 *trace_data_size)
4011{
4012        u32 spad_trace_offsize, signature;
4013
4014        /* Read trace section offsize structure from MCP scratchpad */
4015        spad_trace_offsize = ecore_rd(p_hwfn, p_ptt,
4016                                      MCP_SPAD_TRACE_OFFSIZE_ADDR);
4017
4018        /* Extract trace section address from offsize (in scratchpad) */
4019        *trace_data_grc_addr =
4020                MCP_REG_SCRATCH + SECTION_OFFSET(spad_trace_offsize);
4021
4022        /* Read signature from MCP trace section */
4023        signature = ecore_rd(p_hwfn, p_ptt,
4024                           *trace_data_grc_addr +
4025                           offsetof(struct mcp_trace, signature));
4026
4027        if (signature != MFW_TRACE_SIGNATURE)
4028                return DBG_STATUS_INVALID_TRACE_SIGNATURE;
4029
4030        /* Read trace size from MCP trace section */
4031        *trace_data_size = ecore_rd(p_hwfn,
4032                                  p_ptt,
4033                                  *trace_data_grc_addr +
4034                                  offsetof(struct mcp_trace, size));
4035
4036        return DBG_STATUS_OK;
4037}
4038
4039/* Reads MCP trace meta data image from NVRAM
4040 * - running_bundle_id (OUT): running bundle ID (invalid when loaded from file)
4041 * - trace_meta_offset (OUT): trace meta offset in NVRAM in bytes (invalid when
4042 *                            loaded from file).
4043 * - trace_meta_size (OUT):   size in bytes of the trace meta data.
4044 */
4045static enum dbg_status qed_mcp_trace_get_meta_info(struct ecore_hwfn *p_hwfn,
4046                                                   struct ecore_ptt *p_ptt,
4047                                                   u32 trace_data_size_bytes,
4048                                                   u32 *running_bundle_id,
4049                                                   u32 *trace_meta_offset,
4050                                                   u32 *trace_meta_size)
4051{
4052        u32 spad_trace_offsize, nvram_image_type, running_mfw_addr;
4053
4054        /* Read MCP trace section offsize structure from MCP scratchpad */
4055        spad_trace_offsize = ecore_rd(p_hwfn, p_ptt,
4056                                      MCP_SPAD_TRACE_OFFSIZE_ADDR);
4057
4058        /* Find running bundle ID */
4059        running_mfw_addr =
4060                MCP_REG_SCRATCH + SECTION_OFFSET(spad_trace_offsize) +
4061                SECTION_SIZE(spad_trace_offsize) + trace_data_size_bytes;
4062        *running_bundle_id = ecore_rd(p_hwfn, p_ptt, running_mfw_addr);
4063        if (*running_bundle_id > 1)
4064                return DBG_STATUS_INVALID_NVRAM_BUNDLE;
4065
4066        /* Find image in NVRAM */
4067        nvram_image_type =
4068            (*running_bundle_id ==
4069             DIR_ID_1) ? NVM_TYPE_MFW_TRACE1 : NVM_TYPE_MFW_TRACE2;
4070        return qed_find_nvram_image(p_hwfn,
4071                                    p_ptt,
4072                                    nvram_image_type,
4073                                    trace_meta_offset, trace_meta_size);
4074}
4075
4076/* Reads the MCP Trace meta data from NVRAM into the specified buffer */
4077static enum dbg_status qed_mcp_trace_read_meta(struct ecore_hwfn *p_hwfn,
4078                                               struct ecore_ptt *p_ptt,
4079                                               u32 nvram_offset_in_bytes,
4080                                               u32 size_in_bytes, u32 *buf)
4081{
4082        u8 modules_num, module_len, i, *byte_buf = (u8 *)buf;
4083        enum dbg_status status;
4084        u32 signature;
4085
4086        /* Read meta data from NVRAM */
4087        status = qed_nvram_read(p_hwfn,
4088                                p_ptt,
4089                                nvram_offset_in_bytes, size_in_bytes, buf);
4090        if (status != DBG_STATUS_OK)
4091                return status;
4092
4093        /* Extract and check first signature */
4094        signature = qed_read_unaligned_dword(byte_buf);
4095        byte_buf += sizeof(signature);
4096        if (signature != NVM_MAGIC_VALUE)
4097                return DBG_STATUS_INVALID_TRACE_SIGNATURE;
4098
4099        /* Extract number of modules */
4100        modules_num = *(byte_buf++);
4101
4102        /* Skip all modules */
4103        for (i = 0; i < modules_num; i++) {
4104                module_len = *(byte_buf++);
4105                byte_buf += module_len;
4106        }
4107
4108        /* Extract and check second signature */
4109        signature = qed_read_unaligned_dword(byte_buf);
4110        byte_buf += sizeof(signature);
4111        if (signature != NVM_MAGIC_VALUE)
4112                return DBG_STATUS_INVALID_TRACE_SIGNATURE;
4113
4114        return DBG_STATUS_OK;
4115}
4116
4117/* Dump MCP Trace */
4118static enum dbg_status qed_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
4119                                          struct ecore_ptt *p_ptt,
4120                                          u32 *dump_buf,
4121                                          bool dump, u32 *num_dumped_dwords)
4122{
4123        u32 trace_data_grc_addr, trace_data_size_bytes, trace_data_size_dwords;
4124        u32 trace_meta_size_dwords = 0, running_bundle_id, offset = 0;
4125        u32 trace_meta_offset_bytes = 0, trace_meta_size_bytes = 0;
4126        enum dbg_status status;
4127        int halted = 0;
4128        bool use_mfw;
4129
4130        *num_dumped_dwords = 0;
4131
4132        use_mfw = !qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_NO_MCP);
4133
4134        /* Get trace data info */
4135        status = qed_mcp_trace_get_data_info(p_hwfn,
4136                                             p_ptt,
4137                                             &trace_data_grc_addr,
4138                                             &trace_data_size_bytes);
4139        if (status != DBG_STATUS_OK)
4140                return status;
4141
4142        /* Dump global params */
4143        offset += qed_dump_common_global_params(p_hwfn,
4144                                                p_ptt,
4145                                                dump_buf + offset, dump, 1);
4146        offset += qed_dump_str_param(dump_buf + offset,
4147                                     dump, "dump-type", "mcp-trace");
4148
4149        /* Halt MCP while reading from scratchpad so the read data will be
4150         * consistent. if halt fails, MCP trace is taken anyway, with a small
4151         * risk that it may be corrupt.
4152         */
4153        if (dump && use_mfw) {
4154                halted = !ecore_mcp_halt(p_hwfn, p_ptt);
4155                if (!halted)
4156                        DP_NOTICE(p_hwfn, false, "MCP halt failed!\n");
4157        }
4158
4159        /* Find trace data size */
4160        trace_data_size_dwords =
4161            DIV_ROUND_UP(trace_data_size_bytes + sizeof(struct mcp_trace),
4162                         BYTES_IN_DWORD);
4163
4164        /* Dump trace data section header and param */
4165        offset += qed_dump_section_hdr(dump_buf + offset,
4166                                       dump, "mcp_trace_data", 1);
4167        offset += qed_dump_num_param(dump_buf + offset,
4168                                     dump, "size", trace_data_size_dwords);
4169
4170        /* Read trace data from scratchpad into dump buffer */
4171        offset += qed_grc_dump_addr_range(p_hwfn,
4172                                          p_ptt,
4173                                          dump_buf + offset,
4174                                          dump,
4175                                          BYTES_TO_DWORDS(trace_data_grc_addr),
4176                                          trace_data_size_dwords, false,
4177                                          SPLIT_TYPE_NONE, 0);
4178
4179        /* Resume MCP (only if halt succeeded) */
4180        if (halted && ecore_mcp_resume(p_hwfn, p_ptt))
4181                DP_NOTICE(p_hwfn, false, "Failed to resume MCP after halt!\n");
4182
4183        /* Dump trace meta section header */
4184        offset += qed_dump_section_hdr(dump_buf + offset,
4185                                       dump, "mcp_trace_meta", 1);
4186
4187        /* If MCP Trace meta size parameter was set, use it.
4188         * Otherwise, read trace meta.
4189         * trace_meta_size_bytes is dword-aligned.
4190         */
4191        trace_meta_size_bytes =
4192                qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_MCP_TRACE_META_SIZE);
4193        if ((!trace_meta_size_bytes || dump) && use_mfw)
4194                status = qed_mcp_trace_get_meta_info(p_hwfn,
4195                                                     p_ptt,
4196                                                     trace_data_size_bytes,
4197                                                     &running_bundle_id,
4198                                                     &trace_meta_offset_bytes,
4199                                                     &trace_meta_size_bytes);
4200        if (status == DBG_STATUS_OK)
4201                trace_meta_size_dwords = BYTES_TO_DWORDS(trace_meta_size_bytes);
4202
4203        /* Dump trace meta size param */
4204        offset += qed_dump_num_param(dump_buf + offset,
4205                                     dump, "size", trace_meta_size_dwords);
4206
4207        /* Read trace meta image into dump buffer */
4208        if (dump && trace_meta_size_dwords)
4209                status = qed_mcp_trace_read_meta(p_hwfn,
4210                                                 p_ptt,
4211                                                 trace_meta_offset_bytes,
4212                                                 trace_meta_size_bytes,
4213                                                 dump_buf + offset);
4214        if (status == DBG_STATUS_OK)
4215                offset += trace_meta_size_dwords;
4216
4217        /* Dump last section */
4218        offset += qed_dump_last_section(dump_buf, offset, dump);
4219
4220        *num_dumped_dwords = offset;
4221
4222        /* If no mcp access, indicate that the dump doesn't contain the meta
4223         * data from NVRAM.
4224         */
4225        return use_mfw ? status : DBG_STATUS_NVRAM_GET_IMAGE_FAILED;
4226}
4227
4228/* Dump GRC FIFO */
4229static enum dbg_status qed_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
4230                                         struct ecore_ptt *p_ptt,
4231                                         u32 *dump_buf,
4232                                         bool dump, u32 *num_dumped_dwords)
4233{
4234        u32 dwords_read, size_param_offset, offset = 0, addr, len;
4235        bool fifo_has_data;
4236
4237        *num_dumped_dwords = 0;
4238
4239        /* Dump global params */
4240        offset += qed_dump_common_global_params(p_hwfn,
4241                                                p_ptt,
4242                                                dump_buf + offset, dump, 1);
4243        offset += qed_dump_str_param(dump_buf + offset,
4244                                     dump, "dump-type", "reg-fifo");
4245
4246        /* Dump fifo data section header and param. The size param is 0 for
4247         * now, and is overwritten after reading the FIFO.
4248         */
4249        offset += qed_dump_section_hdr(dump_buf + offset,
4250                                       dump, "reg_fifo_data", 1);
4251        size_param_offset = offset;
4252        offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
4253
4254        if (!dump) {
4255                /* FIFO max size is REG_FIFO_DEPTH_DWORDS. There is no way to
4256                 * test how much data is available, except for reading it.
4257                 */
4258                offset += REG_FIFO_DEPTH_DWORDS;
4259                goto out;
4260        }
4261
4262        fifo_has_data = ecore_rd(p_hwfn, p_ptt,
4263                               GRC_REG_TRACE_FIFO_VALID_DATA) > 0;
4264
4265        /* Pull available data from fifo. Use DMAE since this is widebus memory
4266         * and must be accessed atomically. Test for dwords_read not passing
4267         * buffer size since more entries could be added to the buffer as we are
4268         * emptying it.
4269         */
4270        addr = BYTES_TO_DWORDS(GRC_REG_TRACE_FIFO);
4271        len = REG_FIFO_ELEMENT_DWORDS;
4272        for (dwords_read = 0;
4273             fifo_has_data && dwords_read < REG_FIFO_DEPTH_DWORDS;
4274             dwords_read += REG_FIFO_ELEMENT_DWORDS) {
4275                offset += qed_grc_dump_addr_range(p_hwfn,
4276                                                  p_ptt,
4277                                                  dump_buf + offset,
4278                                                  true,
4279                                                  addr,
4280                                                  len,
4281                                                  true, SPLIT_TYPE_NONE,
4282                                                  0);
4283                fifo_has_data = ecore_rd(p_hwfn, p_ptt,
4284                                       GRC_REG_TRACE_FIFO_VALID_DATA) > 0;
4285        }
4286
4287        qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
4288                           dwords_read);
4289out:
4290        /* Dump last section */
4291        offset += qed_dump_last_section(dump_buf, offset, dump);
4292
4293        *num_dumped_dwords = offset;
4294
4295        return DBG_STATUS_OK;
4296}
4297
4298/* Dump IGU FIFO */
4299static enum dbg_status qed_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
4300                                         struct ecore_ptt *p_ptt,
4301                                         u32 *dump_buf,
4302                                         bool dump, u32 *num_dumped_dwords)
4303{
4304        u32 dwords_read, size_param_offset, offset = 0, addr, len;
4305        bool fifo_has_data;
4306
4307        *num_dumped_dwords = 0;
4308
4309        /* Dump global params */
4310        offset += qed_dump_common_global_params(p_hwfn,
4311                                                p_ptt,
4312                                                dump_buf + offset, dump, 1);
4313        offset += qed_dump_str_param(dump_buf + offset,
4314                                     dump, "dump-type", "igu-fifo");
4315
4316        /* Dump fifo data section header and param. The size param is 0 for
4317         * now, and is overwritten after reading the FIFO.
4318         */
4319        offset += qed_dump_section_hdr(dump_buf + offset,
4320                                       dump, "igu_fifo_data", 1);
4321        size_param_offset = offset;
4322        offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
4323
4324        if (!dump) {
4325                /* FIFO max size is IGU_FIFO_DEPTH_DWORDS. There is no way to
4326                 * test how much data is available, except for reading it.
4327                 */
4328                offset += IGU_FIFO_DEPTH_DWORDS;
4329                goto out;
4330        }
4331
4332        fifo_has_data = ecore_rd(p_hwfn, p_ptt,
4333                               IGU_REG_ERROR_HANDLING_DATA_VALID) > 0;
4334
4335        /* Pull available data from fifo. Use DMAE since this is widebus memory
4336         * and must be accessed atomically. Test for dwords_read not passing
4337         * buffer size since more entries could be added to the buffer as we are
4338         * emptying it.
4339         */
4340        addr = BYTES_TO_DWORDS(IGU_REG_ERROR_HANDLING_MEMORY);
4341        len = IGU_FIFO_ELEMENT_DWORDS;
4342        for (dwords_read = 0;
4343             fifo_has_data && dwords_read < IGU_FIFO_DEPTH_DWORDS;
4344             dwords_read += IGU_FIFO_ELEMENT_DWORDS) {
4345                offset += qed_grc_dump_addr_range(p_hwfn,
4346                                                  p_ptt,
4347                                                  dump_buf + offset,
4348                                                  true,
4349                                                  addr,
4350                                                  len,
4351                                                  true, SPLIT_TYPE_NONE,
4352                                                  0);
4353                fifo_has_data = ecore_rd(p_hwfn, p_ptt,
4354                                       IGU_REG_ERROR_HANDLING_DATA_VALID) > 0;
4355        }
4356
4357        qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
4358                           dwords_read);
4359out:
4360        /* Dump last section */
4361        offset += qed_dump_last_section(dump_buf, offset, dump);
4362
4363        *num_dumped_dwords = offset;
4364
4365        return DBG_STATUS_OK;
4366}
4367
4368/* Protection Override dump */
4369static enum dbg_status qed_protection_override_dump(struct ecore_hwfn *p_hwfn,
4370                                                    struct ecore_ptt *p_ptt,
4371                                                    u32 *dump_buf,
4372                                                    bool dump,
4373                                                    u32 *num_dumped_dwords)
4374{
4375        u32 size_param_offset, override_window_dwords, offset = 0, addr;
4376
4377        *num_dumped_dwords = 0;
4378
4379        /* Dump global params */
4380        offset += qed_dump_common_global_params(p_hwfn,
4381                                                p_ptt,
4382                                                dump_buf + offset, dump, 1);
4383        offset += qed_dump_str_param(dump_buf + offset,
4384                                     dump, "dump-type", "protection-override");
4385
4386        /* Dump data section header and param. The size param is 0 for now,
4387         * and is overwritten after reading the data.
4388         */
4389        offset += qed_dump_section_hdr(dump_buf + offset,
4390                                       dump, "protection_override_data", 1);
4391        size_param_offset = offset;
4392        offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
4393
4394        if (!dump) {
4395                offset += PROTECTION_OVERRIDE_DEPTH_DWORDS;
4396                goto out;
4397        }
4398
4399        /* Add override window info to buffer */
4400        override_window_dwords =
4401                ecore_rd(p_hwfn, p_ptt, GRC_REG_NUMBER_VALID_OVERRIDE_WINDOW) *
4402                PROTECTION_OVERRIDE_ELEMENT_DWORDS;
4403        if (override_window_dwords) {
4404                addr = BYTES_TO_DWORDS(GRC_REG_PROTECTION_OVERRIDE_WINDOW);
4405                offset += qed_grc_dump_addr_range(p_hwfn,
4406                                                  p_ptt,
4407                                                  dump_buf + offset,
4408                                                  true,
4409                                                  addr,
4410                                                  override_window_dwords,
4411                                                  true, SPLIT_TYPE_NONE, 0);
4412                qed_dump_num_param(dump_buf + size_param_offset, dump, "size",
4413                                   override_window_dwords);
4414        }
4415out:
4416        /* Dump last section */
4417        offset += qed_dump_last_section(dump_buf, offset, dump);
4418
4419        *num_dumped_dwords = offset;
4420
4421        return DBG_STATUS_OK;
4422}
4423
4424/* Performs FW Asserts Dump to the specified buffer.
4425 * Returns the dumped size in dwords.
4426 */
4427static u32 qed_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
4428                               struct ecore_ptt *p_ptt, u32 *dump_buf,
4429                               bool dump)
4430{
4431        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
4432        struct fw_asserts_ram_section *asserts;
4433        char storm_letter_str[2] = "?";
4434        struct fw_info fw_info;
4435        u32 offset = 0;
4436        u8 storm_id;
4437
4438        /* Dump global params */
4439        offset += qed_dump_common_global_params(p_hwfn,
4440                                                p_ptt,
4441                                                dump_buf + offset, dump, 1);
4442        offset += qed_dump_str_param(dump_buf + offset,
4443                                     dump, "dump-type", "fw-asserts");
4444
4445        /* Find Storm dump size */
4446        for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
4447                u32 fw_asserts_section_addr, next_list_idx_addr, next_list_idx;
4448                struct storm_defs *storm = &s_storm_defs[storm_id];
4449                u32 last_list_idx, addr;
4450
4451                if (dev_data->block_in_reset[storm->sem_block_id])
4452                        continue;
4453
4454                /* Read FW info for the current Storm */
4455                qed_read_storm_fw_info(p_hwfn, p_ptt, storm_id, &fw_info);
4456
4457                asserts = &fw_info.fw_asserts_section;
4458
4459                /* Dump FW Asserts section header and params */
4460                storm_letter_str[0] = storm->letter;
4461                offset += qed_dump_section_hdr(dump_buf + offset,
4462                                               dump, "fw_asserts", 2);
4463                offset += qed_dump_str_param(dump_buf + offset,
4464                                             dump, "storm", storm_letter_str);
4465                offset += qed_dump_num_param(dump_buf + offset,
4466                                             dump,
4467                                             "size",
4468                                             asserts->list_element_dword_size);
4469
4470                /* Read and dump FW Asserts data */
4471                if (!dump) {
4472                        offset += asserts->list_element_dword_size;
4473                        continue;
4474                }
4475
4476                fw_asserts_section_addr = storm->sem_fast_mem_addr +
4477                        SEM_FAST_REG_INT_RAM +
4478                        RAM_LINES_TO_BYTES(asserts->section_ram_line_offset);
4479                next_list_idx_addr = fw_asserts_section_addr +
4480                        DWORDS_TO_BYTES(asserts->list_next_index_dword_offset);
4481                next_list_idx = ecore_rd(p_hwfn, p_ptt, next_list_idx_addr);
4482                last_list_idx = (next_list_idx > 0 ?
4483                                 next_list_idx :
4484                                 asserts->list_num_elements) - 1;
4485                addr = BYTES_TO_DWORDS(fw_asserts_section_addr) +
4486                       asserts->list_dword_offset +
4487                       last_list_idx * asserts->list_element_dword_size;
4488                offset +=
4489                    qed_grc_dump_addr_range(p_hwfn, p_ptt,
4490                                            dump_buf + offset,
4491                                            dump, addr,
4492                                            asserts->list_element_dword_size,
4493                                                  false, SPLIT_TYPE_NONE, 0);
4494        }
4495
4496        /* Dump last section */
4497        offset += qed_dump_last_section(dump_buf, offset, dump);
4498
4499        return offset;
4500}
4501
4502/* Dumps the specified ILT pages to the specified buffer.
4503 * Returns the dumped size in dwords.
4504 */
4505static u32 qed_ilt_dump_pages_range(u32 *dump_buf,
4506                                    bool dump,
4507                                    u32 start_page_id,
4508                                    u32 num_pages,
4509                                    struct phys_mem_desc *ilt_pages,
4510                                    bool dump_page_ids)
4511{
4512        u32 page_id, end_page_id, offset = 0;
4513
4514        if (num_pages == 0)
4515                return offset;
4516
4517        end_page_id = start_page_id + num_pages - 1;
4518
4519        for (page_id = start_page_id; page_id <= end_page_id; page_id++) {
4520                struct phys_mem_desc *mem_desc = &ilt_pages[page_id];
4521
4522                /**
4523                 *
4524                 * if (page_id >= ->p_cxt_mngr->ilt_shadow_size)
4525                 *     break;
4526                 */
4527
4528                if (!ilt_pages[page_id].virt_addr)
4529                        continue;
4530
4531                if (dump_page_ids) {
4532                        /* Copy page ID to dump buffer */
4533                        if (dump)
4534                                *(dump_buf + offset) = page_id;
4535                        offset++;
4536                } else {
4537                        /* Copy page memory to dump buffer */
4538                        if (dump)
4539                                memcpy(dump_buf + offset,
4540                                       mem_desc->virt_addr, mem_desc->size);
4541                        offset += BYTES_TO_DWORDS(mem_desc->size);
4542                }
4543        }
4544
4545        return offset;
4546}
4547
4548/* Dumps a section containing the dumped ILT pages.
4549 * Returns the dumped size in dwords.
4550 */
4551static u32 qed_ilt_dump_pages_section(struct ecore_hwfn *p_hwfn,
4552                                      u32 *dump_buf,
4553                                      bool dump,
4554                                      u32 valid_conn_pf_pages,
4555                                      u32 valid_conn_vf_pages,
4556                                      struct phys_mem_desc *ilt_pages,
4557                                      bool dump_page_ids)
4558{
4559        struct ecore_ilt_client_cfg *clients = p_hwfn->p_cxt_mngr->clients;
4560        u32 pf_start_line, start_page_id, offset = 0;
4561        u32 cdut_pf_init_pages, cdut_vf_init_pages;
4562        u32 cdut_pf_work_pages, cdut_vf_work_pages;
4563        u32 base_data_offset, size_param_offset;
4564        u32 cdut_pf_pages, cdut_vf_pages;
4565        const char *section_name;
4566        u8 i;
4567
4568        section_name = dump_page_ids ? "ilt_page_ids" : "ilt_page_mem";
4569        cdut_pf_init_pages = ecore_get_cdut_num_pf_init_pages(p_hwfn);
4570        cdut_vf_init_pages = ecore_get_cdut_num_vf_init_pages(p_hwfn);
4571        cdut_pf_work_pages = ecore_get_cdut_num_pf_work_pages(p_hwfn);
4572        cdut_vf_work_pages = ecore_get_cdut_num_vf_work_pages(p_hwfn);
4573        cdut_pf_pages = cdut_pf_init_pages + cdut_pf_work_pages;
4574        cdut_vf_pages = cdut_vf_init_pages + cdut_vf_work_pages;
4575        pf_start_line = p_hwfn->p_cxt_mngr->pf_start_line;
4576
4577        offset +=
4578            qed_dump_section_hdr(dump_buf + offset, dump, section_name, 1);
4579
4580        /* Dump size parameter (0 for now, overwritten with real size later) */
4581        size_param_offset = offset;
4582        offset += qed_dump_num_param(dump_buf + offset, dump, "size", 0);
4583        base_data_offset = offset;
4584
4585        /* CDUC pages are ordered as follows:
4586         * - PF pages - valid section (included in PF connection type mapping)
4587         * - PF pages - invalid section (not dumped)
4588         * - For each VF in the PF:
4589         *   - VF pages - valid section (included in VF connection type mapping)
4590         *   - VF pages - invalid section (not dumped)
4591         */
4592        if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_DUMP_ILT_CDUC)) {
4593                /* Dump connection PF pages */
4594                start_page_id = clients[ILT_CLI_CDUC].first.val - pf_start_line;
4595                offset += qed_ilt_dump_pages_range(dump_buf + offset,
4596                                                   dump,
4597                                                   start_page_id,
4598                                                   valid_conn_pf_pages,
4599                                                   ilt_pages, dump_page_ids);
4600
4601                /* Dump connection VF pages */
4602                start_page_id += clients[ILT_CLI_CDUC].pf_total_lines;
4603                for (i = 0; i < p_hwfn->p_cxt_mngr->vf_count;
4604                     i++, start_page_id += clients[ILT_CLI_CDUC].vf_total_lines)
4605                        offset += qed_ilt_dump_pages_range(dump_buf + offset,
4606                                                           dump,
4607                                                           start_page_id,
4608                                                           valid_conn_vf_pages,
4609                                                           ilt_pages,
4610                                                           dump_page_ids);
4611        }
4612
4613        /* CDUT pages are ordered as follows:
4614         * - PF init pages (not dumped)
4615         * - PF work pages
4616         * - For each VF in the PF:
4617         *   - VF init pages (not dumped)
4618         *   - VF work pages
4619         */
4620        if (qed_grc_get_param(p_hwfn, DBG_GRC_PARAM_DUMP_ILT_CDUT)) {
4621                /* Dump task PF pages */
4622                start_page_id = clients[ILT_CLI_CDUT].first.val +
4623                    cdut_pf_init_pages - pf_start_line;
4624                offset += qed_ilt_dump_pages_range(dump_buf + offset,
4625                                                   dump,
4626                                                   start_page_id,
4627                                                   cdut_pf_work_pages,
4628                                                   ilt_pages, dump_page_ids);
4629
4630                /* Dump task VF pages */
4631                start_page_id = clients[ILT_CLI_CDUT].first.val +
4632                    cdut_pf_pages + cdut_vf_init_pages - pf_start_line;
4633                for (i = 0; i < p_hwfn->p_cxt_mngr->vf_count;
4634                     i++, start_page_id += cdut_vf_pages)
4635                        offset += qed_ilt_dump_pages_range(dump_buf + offset,
4636                                                           dump,
4637                                                           start_page_id,
4638                                                           cdut_vf_work_pages,
4639                                                           ilt_pages,
4640                                                           dump_page_ids);
4641        }
4642
4643        /* Overwrite size param */
4644        if (dump)
4645                qed_dump_num_param(dump_buf + size_param_offset,
4646                                   dump, "size", offset - base_data_offset);
4647
4648        return offset;
4649}
4650
4651/* Performs ILT Dump to the specified buffer.
4652 * Returns the dumped size in dwords.
4653 */
4654static u32 qed_ilt_dump(struct ecore_hwfn *p_hwfn,
4655                        struct ecore_ptt *p_ptt, u32 *dump_buf, bool dump)
4656{
4657        struct ecore_ilt_client_cfg *clients = p_hwfn->p_cxt_mngr->clients;
4658        u32 valid_conn_vf_cids, valid_conn_vf_pages, offset = 0;
4659        u32 valid_conn_pf_cids, valid_conn_pf_pages, num_pages;
4660        u32 num_cids_per_page, conn_ctx_size;
4661        u32 cduc_page_size, cdut_page_size;
4662        struct phys_mem_desc *ilt_pages;
4663        u8 conn_type;
4664
4665        cduc_page_size = 1 <<
4666            (clients[ILT_CLI_CDUC].p_size.val + PXP_ILT_PAGE_SIZE_NUM_BITS_MIN);
4667        cdut_page_size = 1 <<
4668            (clients[ILT_CLI_CDUT].p_size.val + PXP_ILT_PAGE_SIZE_NUM_BITS_MIN);
4669        conn_ctx_size = p_hwfn->p_cxt_mngr->conn_ctx_size;
4670        num_cids_per_page = (int)(cduc_page_size / conn_ctx_size);
4671        ilt_pages = p_hwfn->p_cxt_mngr->ilt_shadow;
4672
4673        /* Dump global params - 22 must match number of params below */
4674        offset += qed_dump_common_global_params(p_hwfn, p_ptt,
4675                                                dump_buf + offset, dump, 22);
4676        offset += qed_dump_str_param(dump_buf + offset,
4677                                     dump, "dump-type", "ilt-dump");
4678        offset += qed_dump_num_param(dump_buf + offset,
4679                                     dump,
4680                                     "cduc-page-size", cduc_page_size);
4681        offset += qed_dump_num_param(dump_buf + offset,
4682                                     dump,
4683                                     "cduc-first-page-id",
4684                                     clients[ILT_CLI_CDUC].first.val);
4685        offset += qed_dump_num_param(dump_buf + offset,
4686                                     dump,
4687                                     "cduc-last-page-id",
4688                                     clients[ILT_CLI_CDUC].last.val);
4689        offset += qed_dump_num_param(dump_buf + offset,
4690                                     dump,
4691                                     "cduc-num-pf-pages",
4692                                     clients
4693                                     [ILT_CLI_CDUC].pf_total_lines);
4694        offset += qed_dump_num_param(dump_buf + offset,
4695                                     dump,
4696                                     "cduc-num-vf-pages",
4697                                     clients
4698                                     [ILT_CLI_CDUC].vf_total_lines);
4699        offset += qed_dump_num_param(dump_buf + offset,
4700                                     dump,
4701                                     "max-conn-ctx-size",
4702                                     conn_ctx_size);
4703        offset += qed_dump_num_param(dump_buf + offset,
4704                                     dump,
4705                                     "cdut-page-size", cdut_page_size);
4706        offset += qed_dump_num_param(dump_buf + offset,
4707                                     dump,
4708                                     "cdut-first-page-id",
4709                                     clients[ILT_CLI_CDUT].first.val);
4710        offset += qed_dump_num_param(dump_buf + offset,
4711                                     dump,
4712                                     "cdut-last-page-id",
4713                                     clients[ILT_CLI_CDUT].last.val);
4714        offset += qed_dump_num_param(dump_buf + offset,
4715                                     dump,
4716                                     "cdut-num-pf-init-pages",
4717                                     ecore_get_cdut_num_pf_init_pages(p_hwfn));
4718        offset += qed_dump_num_param(dump_buf + offset,
4719                                     dump,
4720                                     "cdut-num-vf-init-pages",
4721                                     ecore_get_cdut_num_vf_init_pages(p_hwfn));
4722        offset += qed_dump_num_param(dump_buf + offset,
4723                                     dump,
4724                                     "cdut-num-pf-work-pages",
4725                                     ecore_get_cdut_num_pf_work_pages(p_hwfn));
4726        offset += qed_dump_num_param(dump_buf + offset,
4727                                     dump,
4728                                     "cdut-num-vf-work-pages",
4729                                     ecore_get_cdut_num_vf_work_pages(p_hwfn));
4730        offset += qed_dump_num_param(dump_buf + offset,
4731                                     dump,
4732                                     "max-task-ctx-size",
4733                                     p_hwfn->p_cxt_mngr->task_ctx_size);
4734        offset += qed_dump_num_param(dump_buf + offset,
4735                                     dump,
4736                                     "task-type-id",
4737                                     p_hwfn->p_cxt_mngr->task_type_id);
4738        offset += qed_dump_num_param(dump_buf + offset,
4739                                     dump,
4740                                     "first-vf-id-in-pf",
4741                                     p_hwfn->p_cxt_mngr->first_vf_in_pf);
4742        offset += /* 18 */ qed_dump_num_param(dump_buf + offset,
4743                                              dump,
4744                                              "num-vfs-in-pf",
4745                                              p_hwfn->p_cxt_mngr->vf_count);
4746        offset += qed_dump_num_param(dump_buf + offset,
4747                                     dump,
4748                                     "ptr-size-bytes", sizeof(void *));
4749        offset += qed_dump_num_param(dump_buf + offset,
4750                                     dump,
4751                                     "pf-start-line",
4752                                     p_hwfn->p_cxt_mngr->pf_start_line);
4753        offset += qed_dump_num_param(dump_buf + offset,
4754                                     dump,
4755                                     "page-mem-desc-size-dwords",
4756                                     PAGE_MEM_DESC_SIZE_DWORDS);
4757        offset += qed_dump_num_param(dump_buf + offset,
4758                                     dump,
4759                                     "ilt-shadow-size",
4760                                     p_hwfn->p_cxt_mngr->ilt_shadow_size);
4761        /* Additional/Less parameters require matching of number in call to
4762         * dump_common_global_params()
4763         */
4764
4765        /* Dump section containing number of PF CIDs per connection type */
4766        offset += qed_dump_section_hdr(dump_buf + offset,
4767                                       dump, "num_pf_cids_per_conn_type", 1);
4768        offset += qed_dump_num_param(dump_buf + offset,
4769                                     dump, "size", NUM_OF_CONNECTION_TYPES);
4770        for (conn_type = 0, valid_conn_pf_cids = 0;
4771             conn_type < NUM_OF_CONNECTION_TYPES; conn_type++, offset++) {
4772                u32 num_pf_cids =
4773                    p_hwfn->p_cxt_mngr->conn_cfg[conn_type].cid_count;
4774
4775                if (dump)
4776                        *(dump_buf + offset) = num_pf_cids;
4777                valid_conn_pf_cids += num_pf_cids;
4778        }
4779
4780        /* Dump section containing number of VF CIDs per connection type */
4781        offset += qed_dump_section_hdr(dump_buf + offset,
4782                                       dump, "num_vf_cids_per_conn_type", 1);
4783        offset += qed_dump_num_param(dump_buf + offset,
4784                                     dump, "size", NUM_OF_CONNECTION_TYPES);
4785        for (conn_type = 0, valid_conn_vf_cids = 0;
4786             conn_type < NUM_OF_CONNECTION_TYPES; conn_type++, offset++) {
4787                u32 num_vf_cids =
4788                    p_hwfn->p_cxt_mngr->conn_cfg[conn_type].cids_per_vf;
4789
4790                if (dump)
4791                        *(dump_buf + offset) = num_vf_cids;
4792                valid_conn_vf_cids += num_vf_cids;
4793        }
4794
4795        /* Dump section containing physical memory descs for each ILT page */
4796        num_pages = p_hwfn->p_cxt_mngr->ilt_shadow_size;
4797        offset += qed_dump_section_hdr(dump_buf + offset,
4798                                       dump, "ilt_page_desc", 1);
4799        offset += qed_dump_num_param(dump_buf + offset,
4800                                     dump,
4801                                     "size",
4802                                     num_pages * PAGE_MEM_DESC_SIZE_DWORDS);
4803
4804        /* Copy memory descriptors to dump buffer */
4805        if (dump) {
4806                u32 page_id;
4807
4808                for (page_id = 0; page_id < num_pages;
4809                     page_id++, offset += PAGE_MEM_DESC_SIZE_DWORDS)
4810                        memcpy(dump_buf + offset,
4811                               &ilt_pages[page_id],
4812                               DWORDS_TO_BYTES(PAGE_MEM_DESC_SIZE_DWORDS));
4813        } else {
4814                offset += num_pages * PAGE_MEM_DESC_SIZE_DWORDS;
4815        }
4816
4817        valid_conn_pf_pages = DIV_ROUND_UP(valid_conn_pf_cids,
4818                                           num_cids_per_page);
4819        valid_conn_vf_pages = DIV_ROUND_UP(valid_conn_vf_cids,
4820                                           num_cids_per_page);
4821
4822        /* Dump ILT pages IDs */
4823        offset += qed_ilt_dump_pages_section(p_hwfn,
4824                                             dump_buf + offset,
4825                                             dump,
4826                                             valid_conn_pf_pages,
4827                                             valid_conn_vf_pages,
4828                                             ilt_pages, true);
4829
4830        /* Dump ILT pages memory */
4831        offset += qed_ilt_dump_pages_section(p_hwfn,
4832                                             dump_buf + offset,
4833                                             dump,
4834                                             valid_conn_pf_pages,
4835                                             valid_conn_vf_pages,
4836                                             ilt_pages, false);
4837
4838        /* Dump last section */
4839        offset += qed_dump_last_section(dump_buf, offset, dump);
4840
4841        return offset;
4842}
4843
4844/***************************** Public Functions *******************************/
4845
4846enum dbg_status qed_dbg_set_bin_ptr(struct ecore_hwfn *p_hwfn,
4847                                    const u8 * const bin_ptr)
4848{
4849        struct bin_buffer_hdr *buf_hdrs =
4850                        (struct bin_buffer_hdr *)(osal_uintptr_t)bin_ptr;
4851        u8 buf_id;
4852
4853        /* Convert binary data to debug arrays */
4854        for (buf_id = 0; buf_id < MAX_BIN_DBG_BUFFER_TYPE; buf_id++)
4855                qed_set_dbg_bin_buf(p_hwfn,
4856                                    buf_id,
4857                                    (const u32 *)(bin_ptr +
4858                                                  buf_hdrs[buf_id].offset),
4859                                                  buf_hdrs[buf_id].length);
4860
4861        return DBG_STATUS_OK;
4862}
4863
4864enum dbg_status qed_dbg_set_app_ver(u32 ver)
4865{
4866        if (ver < TOOLS_VERSION)
4867                return DBG_STATUS_UNSUPPORTED_APP_VERSION;
4868
4869        s_app_ver = ver;
4870
4871        return DBG_STATUS_OK;
4872}
4873
4874bool qed_read_fw_info(struct ecore_hwfn *p_hwfn,
4875                      struct ecore_ptt *p_ptt, struct fw_info *fw_info)
4876{
4877        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
4878        u8 storm_id;
4879
4880        for (storm_id = 0; storm_id < MAX_DBG_STORMS; storm_id++) {
4881                struct storm_defs *storm = &s_storm_defs[storm_id];
4882
4883                /* Skip Storm if it's in reset */
4884                if (dev_data->block_in_reset[storm->sem_block_id])
4885                        continue;
4886
4887                /* Read FW info for the current Storm */
4888                qed_read_storm_fw_info(p_hwfn, p_ptt, storm_id, fw_info);
4889
4890                return true;
4891        }
4892
4893        return false;
4894}
4895
4896enum dbg_status qed_dbg_grc_config(struct ecore_hwfn *p_hwfn,
4897                                   enum dbg_grc_params grc_param, u32 val)
4898{
4899        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
4900        enum dbg_status status;
4901        int i;
4902
4903        DP_VERBOSE(p_hwfn->p_dev,
4904                   ECORE_MSG_DEBUG,
4905                   "dbg_grc_config: paramId = %d, val = %d\n", grc_param, val);
4906
4907        status = qed_dbg_dev_init(p_hwfn);
4908        if (status != DBG_STATUS_OK)
4909                return status;
4910
4911        /* Initializes the GRC parameters (if not initialized). Needed in order
4912         * to set the default parameter values for the first time.
4913         */
4914        qed_dbg_grc_init_params(p_hwfn);
4915
4916        if (grc_param >= MAX_DBG_GRC_PARAMS)
4917                return DBG_STATUS_INVALID_ARGS;
4918        if (val < s_grc_param_defs[grc_param].min ||
4919            val > s_grc_param_defs[grc_param].max)
4920                return DBG_STATUS_INVALID_ARGS;
4921
4922        if (s_grc_param_defs[grc_param].is_preset) {
4923                /* Preset param */
4924
4925                /* Disabling a preset is not allowed. Call
4926                 * dbg_grc_set_params_default instead.
4927                 */
4928                if (!val)
4929                        return DBG_STATUS_INVALID_ARGS;
4930
4931                /* Update all params with the preset values */
4932                for (i = 0; i < MAX_DBG_GRC_PARAMS; i++) {
4933                        struct grc_param_defs *defs = &s_grc_param_defs[i];
4934                        u32 preset_val;
4935                        /* Skip persistent params */
4936                        if (defs->is_persistent)
4937                                continue;
4938
4939                        /* Find preset value */
4940                        if (grc_param == DBG_GRC_PARAM_EXCLUDE_ALL)
4941                                preset_val =
4942                                    defs->exclude_all_preset_val;
4943                        else if (grc_param == DBG_GRC_PARAM_CRASH)
4944                                preset_val =
4945                                    defs->crash_preset_val[dev_data->chip_id];
4946                        else
4947                                return DBG_STATUS_INVALID_ARGS;
4948
4949                        qed_grc_set_param(p_hwfn, i, preset_val);
4950                }
4951        } else {
4952                /* Regular param - set its value */
4953                qed_grc_set_param(p_hwfn, grc_param, val);
4954        }
4955
4956        return DBG_STATUS_OK;
4957}
4958
4959/* Assign default GRC param values */
4960void qed_dbg_grc_set_params_default(struct ecore_hwfn *p_hwfn)
4961{
4962        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
4963        u32 i;
4964
4965        for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
4966                if (!s_grc_param_defs[i].is_persistent)
4967                        dev_data->grc.param_val[i] =
4968                            s_grc_param_defs[i].default_val[dev_data->chip_id];
4969}
4970
4971enum dbg_status qed_dbg_grc_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
4972                                              struct ecore_ptt *p_ptt,
4973                                              u32 *buf_size)
4974{
4975        enum dbg_status status = qed_dbg_dev_init(p_hwfn);
4976
4977        *buf_size = 0;
4978
4979        if (status != DBG_STATUS_OK)
4980                return status;
4981
4982        if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
4983            !p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_REG].ptr ||
4984            !p_hwfn->dbg_arrays[BIN_BUF_DBG_DUMP_MEM].ptr ||
4985            !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr ||
4986            !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr)
4987                return DBG_STATUS_DBG_ARRAY_NOT_SET;
4988
4989        return qed_grc_dump(p_hwfn, p_ptt, NULL, false, buf_size);
4990}
4991
4992enum dbg_status qed_dbg_grc_dump(struct ecore_hwfn *p_hwfn,
4993                                 struct ecore_ptt *p_ptt,
4994                                 u32 *dump_buf,
4995                                 u32 buf_size_in_dwords,
4996                                 u32 *num_dumped_dwords)
4997{
4998        u32 needed_buf_size_in_dwords;
4999        enum dbg_status status;
5000
5001        *num_dumped_dwords = 0;
5002
5003        status = qed_dbg_grc_get_dump_buf_size(p_hwfn,
5004                                               p_ptt,
5005                                               &needed_buf_size_in_dwords);
5006        if (status != DBG_STATUS_OK)
5007                return status;
5008
5009        if (buf_size_in_dwords < needed_buf_size_in_dwords)
5010                return DBG_STATUS_DUMP_BUF_TOO_SMALL;
5011
5012        /* GRC Dump */
5013        status = qed_grc_dump(p_hwfn, p_ptt, dump_buf, true, num_dumped_dwords);
5014
5015        /* Revert GRC params to their default */
5016        qed_dbg_grc_set_params_default(p_hwfn);
5017
5018        return status;
5019}
5020
5021enum dbg_status qed_dbg_idle_chk_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
5022                                                   struct ecore_ptt *p_ptt,
5023                                                   u32 *buf_size)
5024{
5025        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
5026        struct idle_chk_data *idle_chk = &dev_data->idle_chk;
5027        enum dbg_status status;
5028
5029        *buf_size = 0;
5030
5031        status = qed_dbg_dev_init(p_hwfn);
5032        if (status != DBG_STATUS_OK)
5033                return status;
5034
5035        if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
5036            !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_REGS].ptr ||
5037            !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_IMMS].ptr ||
5038            !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_RULES].ptr)
5039                return DBG_STATUS_DBG_ARRAY_NOT_SET;
5040
5041        if (!idle_chk->buf_size_set) {
5042                idle_chk->buf_size = qed_idle_chk_dump(p_hwfn,
5043                                                       p_ptt, NULL, false);
5044                idle_chk->buf_size_set = true;
5045        }
5046
5047        *buf_size = idle_chk->buf_size;
5048
5049        return DBG_STATUS_OK;
5050}
5051
5052enum dbg_status qed_dbg_idle_chk_dump(struct ecore_hwfn *p_hwfn,
5053                                      struct ecore_ptt *p_ptt,
5054                                      u32 *dump_buf,
5055                                      u32 buf_size_in_dwords,
5056                                      u32 *num_dumped_dwords)
5057{
5058        u32 needed_buf_size_in_dwords;
5059        enum dbg_status status;
5060
5061        *num_dumped_dwords = 0;
5062
5063        status = qed_dbg_idle_chk_get_dump_buf_size(p_hwfn,
5064                                                    p_ptt,
5065                                                    &needed_buf_size_in_dwords);
5066        if (status != DBG_STATUS_OK)
5067                return status;
5068
5069        if (buf_size_in_dwords < needed_buf_size_in_dwords)
5070                return DBG_STATUS_DUMP_BUF_TOO_SMALL;
5071
5072        /* Update reset state */
5073        qed_grc_unreset_blocks(p_hwfn, p_ptt, true);
5074        qed_update_blocks_reset_state(p_hwfn, p_ptt);
5075
5076        /* Idle Check Dump */
5077        *num_dumped_dwords = qed_idle_chk_dump(p_hwfn, p_ptt, dump_buf, true);
5078
5079        /* Revert GRC params to their default */
5080        qed_dbg_grc_set_params_default(p_hwfn);
5081
5082        return DBG_STATUS_OK;
5083}
5084
5085enum dbg_status qed_dbg_mcp_trace_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
5086                                                    struct ecore_ptt *p_ptt,
5087                                                    u32 *buf_size)
5088{
5089        enum dbg_status status = qed_dbg_dev_init(p_hwfn);
5090
5091        *buf_size = 0;
5092
5093        if (status != DBG_STATUS_OK)
5094                return status;
5095
5096        return qed_mcp_trace_dump(p_hwfn, p_ptt, NULL, false, buf_size);
5097}
5098
5099enum dbg_status qed_dbg_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
5100                                       struct ecore_ptt *p_ptt,
5101                                       u32 *dump_buf,
5102                                       u32 buf_size_in_dwords,
5103                                       u32 *num_dumped_dwords)
5104{
5105        u32 needed_buf_size_in_dwords;
5106        enum dbg_status status;
5107
5108        status =
5109                qed_dbg_mcp_trace_get_dump_buf_size(p_hwfn,
5110                                                    p_ptt,
5111                                                    &needed_buf_size_in_dwords);
5112        if (status != DBG_STATUS_OK && status !=
5113            DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
5114                return status;
5115        if (buf_size_in_dwords < needed_buf_size_in_dwords)
5116                return DBG_STATUS_DUMP_BUF_TOO_SMALL;
5117
5118        /* Update reset state */
5119        qed_update_blocks_reset_state(p_hwfn, p_ptt);
5120
5121        /* Perform dump */
5122        status = qed_mcp_trace_dump(p_hwfn,
5123                                    p_ptt, dump_buf, true, num_dumped_dwords);
5124
5125        /* Revert GRC params to their default */
5126        qed_dbg_grc_set_params_default(p_hwfn);
5127
5128        return status;
5129}
5130
5131enum dbg_status qed_dbg_reg_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
5132                                                   struct ecore_ptt *p_ptt,
5133                                                   u32 *buf_size)
5134{
5135        enum dbg_status status = qed_dbg_dev_init(p_hwfn);
5136
5137        *buf_size = 0;
5138
5139        if (status != DBG_STATUS_OK)
5140                return status;
5141
5142        return qed_reg_fifo_dump(p_hwfn, p_ptt, NULL, false, buf_size);
5143}
5144
5145enum dbg_status qed_dbg_reg_fifo_dump(struct ecore_hwfn *p_hwfn,
5146                                      struct ecore_ptt *p_ptt,
5147                                      u32 *dump_buf,
5148                                      u32 buf_size_in_dwords,
5149                                      u32 *num_dumped_dwords)
5150{
5151        u32 needed_buf_size_in_dwords;
5152        enum dbg_status status;
5153
5154        *num_dumped_dwords = 0;
5155
5156        status = qed_dbg_reg_fifo_get_dump_buf_size(p_hwfn,
5157                                                    p_ptt,
5158                                                    &needed_buf_size_in_dwords);
5159        if (status != DBG_STATUS_OK)
5160                return status;
5161
5162        if (buf_size_in_dwords < needed_buf_size_in_dwords)
5163                return DBG_STATUS_DUMP_BUF_TOO_SMALL;
5164
5165        /* Update reset state */
5166        qed_update_blocks_reset_state(p_hwfn, p_ptt);
5167
5168        status = qed_reg_fifo_dump(p_hwfn,
5169                                   p_ptt, dump_buf, true, num_dumped_dwords);
5170
5171        /* Revert GRC params to their default */
5172        qed_dbg_grc_set_params_default(p_hwfn);
5173
5174        return status;
5175}
5176
5177enum dbg_status qed_dbg_igu_fifo_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
5178                                                   struct ecore_ptt *p_ptt,
5179                                                   u32 *buf_size)
5180{
5181        enum dbg_status status = qed_dbg_dev_init(p_hwfn);
5182
5183        *buf_size = 0;
5184
5185        if (status != DBG_STATUS_OK)
5186                return status;
5187
5188        return qed_igu_fifo_dump(p_hwfn, p_ptt, NULL, false, buf_size);
5189}
5190
5191enum dbg_status qed_dbg_igu_fifo_dump(struct ecore_hwfn *p_hwfn,
5192                                      struct ecore_ptt *p_ptt,
5193                                      u32 *dump_buf,
5194                                      u32 buf_size_in_dwords,
5195                                      u32 *num_dumped_dwords)
5196{
5197        u32 needed_buf_size_in_dwords;
5198        enum dbg_status status;
5199
5200        *num_dumped_dwords = 0;
5201
5202        status = qed_dbg_igu_fifo_get_dump_buf_size(p_hwfn,
5203                                                    p_ptt,
5204                                                    &needed_buf_size_in_dwords);
5205        if (status != DBG_STATUS_OK)
5206                return status;
5207
5208        if (buf_size_in_dwords < needed_buf_size_in_dwords)
5209                return DBG_STATUS_DUMP_BUF_TOO_SMALL;
5210
5211        /* Update reset state */
5212        qed_update_blocks_reset_state(p_hwfn, p_ptt);
5213
5214        status = qed_igu_fifo_dump(p_hwfn,
5215                                   p_ptt, dump_buf, true, num_dumped_dwords);
5216        /* Revert GRC params to their default */
5217        qed_dbg_grc_set_params_default(p_hwfn);
5218
5219        return status;
5220}
5221
5222enum dbg_status
5223qed_dbg_protection_override_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
5224                                              struct ecore_ptt *p_ptt,
5225                                              u32 *buf_size)
5226{
5227        enum dbg_status status = qed_dbg_dev_init(p_hwfn);
5228
5229        *buf_size = 0;
5230
5231        if (status != DBG_STATUS_OK)
5232                return status;
5233
5234        return qed_protection_override_dump(p_hwfn,
5235                                            p_ptt, NULL, false, buf_size);
5236}
5237
5238enum dbg_status qed_dbg_protection_override_dump(struct ecore_hwfn *p_hwfn,
5239                                                 struct ecore_ptt *p_ptt,
5240                                                 u32 *dump_buf,
5241                                                 u32 buf_size_in_dwords,
5242                                                 u32 *num_dumped_dwords)
5243{
5244        u32 needed_buf_size_in_dwords, *p_size = &needed_buf_size_in_dwords;
5245        enum dbg_status status;
5246
5247        *num_dumped_dwords = 0;
5248
5249        status =
5250                qed_dbg_protection_override_get_dump_buf_size(p_hwfn,
5251                                                              p_ptt,
5252                                                              p_size);
5253        if (status != DBG_STATUS_OK)
5254                return status;
5255
5256        if (buf_size_in_dwords < needed_buf_size_in_dwords)
5257                return DBG_STATUS_DUMP_BUF_TOO_SMALL;
5258
5259        /* Update reset state */
5260        qed_update_blocks_reset_state(p_hwfn, p_ptt);
5261
5262        status = qed_protection_override_dump(p_hwfn,
5263                                              p_ptt,
5264                                              dump_buf,
5265                                              true, num_dumped_dwords);
5266
5267        /* Revert GRC params to their default */
5268        qed_dbg_grc_set_params_default(p_hwfn);
5269
5270        return status;
5271}
5272
5273enum dbg_status qed_dbg_fw_asserts_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
5274                                                     struct ecore_ptt *p_ptt,
5275                                                     u32 *buf_size)
5276{
5277        enum dbg_status status = qed_dbg_dev_init(p_hwfn);
5278
5279        *buf_size = 0;
5280
5281        if (status != DBG_STATUS_OK)
5282                return status;
5283
5284        /* Update reset state */
5285        qed_update_blocks_reset_state(p_hwfn, p_ptt);
5286
5287        *buf_size = qed_fw_asserts_dump(p_hwfn, p_ptt, NULL, false);
5288
5289        return DBG_STATUS_OK;
5290}
5291
5292enum dbg_status qed_dbg_fw_asserts_dump(struct ecore_hwfn *p_hwfn,
5293                                        struct ecore_ptt *p_ptt,
5294                                        u32 *dump_buf,
5295                                        u32 buf_size_in_dwords,
5296                                        u32 *num_dumped_dwords)
5297{
5298        u32 needed_buf_size_in_dwords, *p_size = &needed_buf_size_in_dwords;
5299        enum dbg_status status;
5300
5301        *num_dumped_dwords = 0;
5302
5303        status =
5304                qed_dbg_fw_asserts_get_dump_buf_size(p_hwfn,
5305                                                     p_ptt,
5306                                                     p_size);
5307        if (status != DBG_STATUS_OK)
5308                return status;
5309
5310        if (buf_size_in_dwords < needed_buf_size_in_dwords)
5311                return DBG_STATUS_DUMP_BUF_TOO_SMALL;
5312
5313        *num_dumped_dwords = qed_fw_asserts_dump(p_hwfn, p_ptt, dump_buf, true);
5314
5315        /* Revert GRC params to their default */
5316        qed_dbg_grc_set_params_default(p_hwfn);
5317
5318        return DBG_STATUS_OK;
5319}
5320
5321static enum dbg_status qed_dbg_ilt_get_dump_buf_size(struct ecore_hwfn *p_hwfn,
5322                                                     struct ecore_ptt *p_ptt,
5323                                                     u32 *buf_size)
5324{
5325        enum dbg_status status = qed_dbg_dev_init(p_hwfn);
5326
5327        *buf_size = 0;
5328
5329        if (status != DBG_STATUS_OK)
5330                return status;
5331
5332        *buf_size = qed_ilt_dump(p_hwfn, p_ptt, NULL, false);
5333
5334        return DBG_STATUS_OK;
5335}
5336
5337static enum dbg_status qed_dbg_ilt_dump(struct ecore_hwfn *p_hwfn,
5338                                        struct ecore_ptt *p_ptt,
5339                                        u32 *dump_buf,
5340                                        u32 buf_size_in_dwords,
5341                                        u32 *num_dumped_dwords)
5342{
5343        u32 needed_buf_size_in_dwords;
5344        enum dbg_status status;
5345
5346        *num_dumped_dwords = 0;
5347
5348        status = qed_dbg_ilt_get_dump_buf_size(p_hwfn,
5349                                               p_ptt,
5350                                               &needed_buf_size_in_dwords);
5351        if (status != DBG_STATUS_OK)
5352                return status;
5353
5354        if (buf_size_in_dwords < needed_buf_size_in_dwords)
5355                return DBG_STATUS_DUMP_BUF_TOO_SMALL;
5356
5357        *num_dumped_dwords = qed_ilt_dump(p_hwfn, p_ptt, dump_buf, true);
5358
5359        /* Revert GRC params to their default */
5360        qed_dbg_grc_set_params_default(p_hwfn);
5361
5362        return DBG_STATUS_OK;
5363}
5364
5365enum dbg_status qed_dbg_read_attn(struct ecore_hwfn *p_hwfn,
5366                                  struct ecore_ptt *p_ptt,
5367                                  enum block_id block_id,
5368                                  enum dbg_attn_type attn_type,
5369                                  bool clear_status,
5370                                  struct dbg_attn_block_result *results)
5371{
5372        enum dbg_status status = qed_dbg_dev_init(p_hwfn);
5373        u8 reg_idx, num_attn_regs, num_result_regs = 0;
5374        const struct dbg_attn_reg *attn_reg_arr;
5375
5376        if (status != DBG_STATUS_OK)
5377                return status;
5378
5379        if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_MODE_TREE].ptr ||
5380            !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_BLOCKS].ptr ||
5381            !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_REGS].ptr)
5382                return DBG_STATUS_DBG_ARRAY_NOT_SET;
5383
5384        attn_reg_arr = qed_get_block_attn_regs(p_hwfn,
5385                                               block_id,
5386                                               attn_type, &num_attn_regs);
5387
5388        for (reg_idx = 0; reg_idx < num_attn_regs; reg_idx++) {
5389                const struct dbg_attn_reg *reg_data = &attn_reg_arr[reg_idx];
5390                struct dbg_attn_reg_result *reg_result;
5391                u32 sts_addr, sts_val;
5392                u16 modes_buf_offset;
5393                bool eval_mode;
5394
5395                /* Check mode */
5396                eval_mode = GET_FIELD(reg_data->mode.data,
5397                                      DBG_MODE_HDR_EVAL_MODE) > 0;
5398                modes_buf_offset = GET_FIELD(reg_data->mode.data,
5399                                             DBG_MODE_HDR_MODES_BUF_OFFSET);
5400                if (eval_mode && !qed_is_mode_match(p_hwfn, &modes_buf_offset))
5401                        continue;
5402
5403                /* Mode match - read attention status register */
5404                sts_addr = DWORDS_TO_BYTES(clear_status ?
5405                                           reg_data->sts_clr_address :
5406                                           GET_FIELD(reg_data->data,
5407                                                     DBG_ATTN_REG_STS_ADDRESS));
5408                sts_val = ecore_rd(p_hwfn, p_ptt, sts_addr);
5409                if (!sts_val)
5410                        continue;
5411
5412                /* Non-zero attention status - add to results */
5413                reg_result = &results->reg_results[num_result_regs];
5414                SET_FIELD(reg_result->data,
5415                          DBG_ATTN_REG_RESULT_STS_ADDRESS, sts_addr);
5416                SET_FIELD(reg_result->data,
5417                          DBG_ATTN_REG_RESULT_NUM_REG_ATTN,
5418                          GET_FIELD(reg_data->data, DBG_ATTN_REG_NUM_REG_ATTN));
5419                reg_result->block_attn_offset = reg_data->block_attn_offset;
5420                reg_result->sts_val = sts_val;
5421                reg_result->mask_val = ecore_rd(p_hwfn,
5422                                              p_ptt,
5423                                              DWORDS_TO_BYTES
5424                                              (reg_data->mask_address));
5425                num_result_regs++;
5426        }
5427
5428        results->block_id = (u8)block_id;
5429        results->names_offset =
5430            qed_get_block_attn_data(p_hwfn, block_id, attn_type)->names_offset;
5431        SET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_ATTN_TYPE, attn_type);
5432        SET_FIELD(results->data,
5433                  DBG_ATTN_BLOCK_RESULT_NUM_REGS, num_result_regs);
5434
5435        return DBG_STATUS_OK;
5436}
5437
5438/******************************* Data Types **********************************/
5439
5440/* REG fifo element */
5441struct reg_fifo_element {
5442        u64 data;
5443#define REG_FIFO_ELEMENT_ADDRESS_SHIFT          0
5444#define REG_FIFO_ELEMENT_ADDRESS_MASK           0x7fffff
5445#define REG_FIFO_ELEMENT_ACCESS_SHIFT           23
5446#define REG_FIFO_ELEMENT_ACCESS_MASK            0x1
5447#define REG_FIFO_ELEMENT_PF_SHIFT               24
5448#define REG_FIFO_ELEMENT_PF_MASK                0xf
5449#define REG_FIFO_ELEMENT_VF_SHIFT               28
5450#define REG_FIFO_ELEMENT_VF_MASK                0xff
5451#define REG_FIFO_ELEMENT_PORT_SHIFT             36
5452#define REG_FIFO_ELEMENT_PORT_MASK              0x3
5453#define REG_FIFO_ELEMENT_PRIVILEGE_SHIFT        38
5454#define REG_FIFO_ELEMENT_PRIVILEGE_MASK         0x3
5455#define REG_FIFO_ELEMENT_PROTECTION_SHIFT       40
5456#define REG_FIFO_ELEMENT_PROTECTION_MASK        0x7
5457#define REG_FIFO_ELEMENT_MASTER_SHIFT           43
5458#define REG_FIFO_ELEMENT_MASTER_MASK            0xf
5459#define REG_FIFO_ELEMENT_ERROR_SHIFT            47
5460#define REG_FIFO_ELEMENT_ERROR_MASK             0x1f
5461};
5462
5463/* REG fifo error element */
5464struct reg_fifo_err {
5465        u32 err_code;
5466        const char *err_msg;
5467};
5468
5469/* IGU fifo element */
5470struct igu_fifo_element {
5471        u32 dword0;
5472#define IGU_FIFO_ELEMENT_DWORD0_FID_SHIFT               0
5473#define IGU_FIFO_ELEMENT_DWORD0_FID_MASK                0xff
5474#define IGU_FIFO_ELEMENT_DWORD0_IS_PF_SHIFT             8
5475#define IGU_FIFO_ELEMENT_DWORD0_IS_PF_MASK              0x1
5476#define IGU_FIFO_ELEMENT_DWORD0_SOURCE_SHIFT            9
5477#define IGU_FIFO_ELEMENT_DWORD0_SOURCE_MASK             0xf
5478#define IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE_SHIFT          13
5479#define IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE_MASK           0xf
5480#define IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR_SHIFT          17
5481#define IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR_MASK           0x7fff
5482        u32 dword1;
5483        u32 dword2;
5484#define IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD_SHIFT        0
5485#define IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD_MASK         0x1
5486#define IGU_FIFO_ELEMENT_DWORD12_WR_DATA_SHIFT          1
5487#define IGU_FIFO_ELEMENT_DWORD12_WR_DATA_MASK           0xffffffff
5488        u32 reserved;
5489};
5490
5491struct igu_fifo_wr_data {
5492        u32 data;
5493#define IGU_FIFO_WR_DATA_PROD_CONS_SHIFT                0
5494#define IGU_FIFO_WR_DATA_PROD_CONS_MASK                 0xffffff
5495#define IGU_FIFO_WR_DATA_UPDATE_FLAG_SHIFT              24
5496#define IGU_FIFO_WR_DATA_UPDATE_FLAG_MASK               0x1
5497#define IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB_SHIFT        25
5498#define IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB_MASK         0x3
5499#define IGU_FIFO_WR_DATA_SEGMENT_SHIFT                  27
5500#define IGU_FIFO_WR_DATA_SEGMENT_MASK                   0x1
5501#define IGU_FIFO_WR_DATA_TIMER_MASK_SHIFT               28
5502#define IGU_FIFO_WR_DATA_TIMER_MASK_MASK                0x1
5503#define IGU_FIFO_WR_DATA_CMD_TYPE_SHIFT                 31
5504#define IGU_FIFO_WR_DATA_CMD_TYPE_MASK                  0x1
5505};
5506
5507struct igu_fifo_cleanup_wr_data {
5508        u32 data;
5509#define IGU_FIFO_CLEANUP_WR_DATA_RESERVED_SHIFT         0
5510#define IGU_FIFO_CLEANUP_WR_DATA_RESERVED_MASK          0x7ffffff
5511#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL_SHIFT      27
5512#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL_MASK       0x1
5513#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE_SHIFT     28
5514#define IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE_MASK      0x7
5515#define IGU_FIFO_CLEANUP_WR_DATA_CMD_TYPE_SHIFT         31
5516#define IGU_FIFO_CLEANUP_WR_DATA_CMD_TYPE_MASK          0x1
5517};
5518
5519/* Protection override element */
5520struct protection_override_element {
5521        u64 data;
5522#define PROTECTION_OVERRIDE_ELEMENT_ADDRESS_SHIFT               0
5523#define PROTECTION_OVERRIDE_ELEMENT_ADDRESS_MASK                0x7fffff
5524#define PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE_SHIFT           23
5525#define PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE_MASK            0xffffff
5526#define PROTECTION_OVERRIDE_ELEMENT_READ_SHIFT                  47
5527#define PROTECTION_OVERRIDE_ELEMENT_READ_MASK                   0x1
5528#define PROTECTION_OVERRIDE_ELEMENT_WRITE_SHIFT                 48
5529#define PROTECTION_OVERRIDE_ELEMENT_WRITE_MASK                  0x1
5530#define PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION_SHIFT       49
5531#define PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION_MASK        0x7
5532#define PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION_SHIFT      52
5533#define PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION_MASK       0x7
5534};
5535
5536enum igu_fifo_sources {
5537        IGU_SRC_PXP0,
5538        IGU_SRC_PXP1,
5539        IGU_SRC_PXP2,
5540        IGU_SRC_PXP3,
5541        IGU_SRC_PXP4,
5542        IGU_SRC_PXP5,
5543        IGU_SRC_PXP6,
5544        IGU_SRC_PXP7,
5545        IGU_SRC_CAU,
5546        IGU_SRC_ATTN,
5547        IGU_SRC_GRC
5548};
5549
5550enum igu_fifo_addr_types {
5551        IGU_ADDR_TYPE_MSIX_MEM,
5552        IGU_ADDR_TYPE_WRITE_PBA,
5553        IGU_ADDR_TYPE_WRITE_INT_ACK,
5554        IGU_ADDR_TYPE_WRITE_ATTN_BITS,
5555        IGU_ADDR_TYPE_READ_INT,
5556        IGU_ADDR_TYPE_WRITE_PROD_UPDATE,
5557        IGU_ADDR_TYPE_RESERVED
5558};
5559
5560struct igu_fifo_addr_data {
5561        u16 start_addr;
5562        u16 end_addr;
5563        const char *desc;
5564        const char *vf_desc;
5565        enum igu_fifo_addr_types type;
5566};
5567
5568/******************************** Constants **********************************/
5569
5570#define MAX_MSG_LEN                             1024
5571
5572#define MCP_TRACE_MAX_MODULE_LEN                8
5573#define MCP_TRACE_FORMAT_MAX_PARAMS             3
5574#define MCP_TRACE_FORMAT_PARAM_WIDTH \
5575        (MCP_TRACE_FORMAT_P2_SIZE_OFFSET - MCP_TRACE_FORMAT_P1_SIZE_OFFSET)
5576
5577#define REG_FIFO_ELEMENT_ADDR_FACTOR            4
5578#define REG_FIFO_ELEMENT_IS_PF_VF_VAL           127
5579
5580#define PROTECTION_OVERRIDE_ELEMENT_ADDR_FACTOR 4
5581
5582/***************************** Constant Arrays *******************************/
5583
5584/* Status string array */
5585static const char * const s_status_str[] = {
5586        /* DBG_STATUS_OK */
5587        "Operation completed successfully",
5588
5589        /* DBG_STATUS_APP_VERSION_NOT_SET */
5590        "Debug application version wasn't set",
5591
5592        /* DBG_STATUS_UNSUPPORTED_APP_VERSION */
5593        "Unsupported debug application version",
5594
5595        /* DBG_STATUS_DBG_BLOCK_NOT_RESET */
5596        "The debug block wasn't reset since the last recording",
5597
5598        /* DBG_STATUS_INVALID_ARGS */
5599        "Invalid arguments",
5600
5601        /* DBG_STATUS_OUTPUT_ALREADY_SET */
5602        "The debug output was already set",
5603
5604        /* DBG_STATUS_INVALID_PCI_BUF_SIZE */
5605        "Invalid PCI buffer size",
5606
5607        /* DBG_STATUS_PCI_BUF_ALLOC_FAILED */
5608        "PCI buffer allocation failed",
5609
5610        /* DBG_STATUS_PCI_BUF_NOT_ALLOCATED */
5611        "A PCI buffer wasn't allocated",
5612
5613        /* DBG_STATUS_INVALID_FILTER_TRIGGER_DWORDS */
5614        "The filter/trigger constraint dword offsets are not enabled for recording",
5615
5616
5617        /* DBG_STATUS_VFC_READ_ERROR */
5618        "Error reading from VFC",
5619
5620        /* DBG_STATUS_STORM_ALREADY_ENABLED */
5621        "The Storm was already enabled",
5622
5623        /* DBG_STATUS_STORM_NOT_ENABLED */
5624        "The specified Storm wasn't enabled",
5625
5626        /* DBG_STATUS_BLOCK_ALREADY_ENABLED */
5627        "The block was already enabled",
5628
5629        /* DBG_STATUS_BLOCK_NOT_ENABLED */
5630        "The specified block wasn't enabled",
5631
5632        /* DBG_STATUS_NO_INPUT_ENABLED */
5633        "No input was enabled for recording",
5634
5635        /* DBG_STATUS_NO_FILTER_TRIGGER_256B */
5636        "Filters and triggers are not allowed in E4 256-bit mode",
5637
5638        /* DBG_STATUS_FILTER_ALREADY_ENABLED */
5639        "The filter was already enabled",
5640
5641        /* DBG_STATUS_TRIGGER_ALREADY_ENABLED */
5642        "The trigger was already enabled",
5643
5644        /* DBG_STATUS_TRIGGER_NOT_ENABLED */
5645        "The trigger wasn't enabled",
5646
5647        /* DBG_STATUS_CANT_ADD_CONSTRAINT */
5648        "A constraint can be added only after a filter was enabled or a trigger state was added",
5649
5650        /* DBG_STATUS_TOO_MANY_TRIGGER_STATES */
5651        "Cannot add more than 3 trigger states",
5652
5653        /* DBG_STATUS_TOO_MANY_CONSTRAINTS */
5654        "Cannot add more than 4 constraints per filter or trigger state",
5655
5656        /* DBG_STATUS_RECORDING_NOT_STARTED */
5657        "The recording wasn't started",
5658
5659        /* DBG_STATUS_DATA_DID_NOT_TRIGGER */
5660        "A trigger was configured, but it didn't trigger",
5661
5662        /* DBG_STATUS_NO_DATA_RECORDED */
5663        "No data was recorded",
5664
5665        /* DBG_STATUS_DUMP_BUF_TOO_SMALL */
5666        "Dump buffer is too small",
5667
5668        /* DBG_STATUS_DUMP_NOT_CHUNK_ALIGNED */
5669        "Dumped data is not aligned to chunks",
5670
5671        /* DBG_STATUS_UNKNOWN_CHIP */
5672        "Unknown chip",
5673
5674        /* DBG_STATUS_VIRT_MEM_ALLOC_FAILED */
5675        "Failed allocating virtual memory",
5676
5677        /* DBG_STATUS_BLOCK_IN_RESET */
5678        "The input block is in reset",
5679
5680        /* DBG_STATUS_INVALID_TRACE_SIGNATURE */
5681        "Invalid MCP trace signature found in NVRAM",
5682
5683        /* DBG_STATUS_INVALID_NVRAM_BUNDLE */
5684        "Invalid bundle ID found in NVRAM",
5685
5686        /* DBG_STATUS_NVRAM_GET_IMAGE_FAILED */
5687        "Failed getting NVRAM image",
5688
5689        /* DBG_STATUS_NON_ALIGNED_NVRAM_IMAGE */
5690        "NVRAM image is not dword-aligned",
5691
5692        /* DBG_STATUS_NVRAM_READ_FAILED */
5693        "Failed reading from NVRAM",
5694
5695        /* DBG_STATUS_IDLE_CHK_PARSE_FAILED */
5696        "Idle check parsing failed",
5697
5698        /* DBG_STATUS_MCP_TRACE_BAD_DATA */
5699        "MCP Trace data is corrupt",
5700
5701        /* DBG_STATUS_MCP_TRACE_NO_META */
5702        "Dump doesn't contain meta data - it must be provided in image file",
5703
5704        /* DBG_STATUS_MCP_COULD_NOT_HALT */
5705        "Failed to halt MCP",
5706
5707        /* DBG_STATUS_MCP_COULD_NOT_RESUME */
5708        "Failed to resume MCP after halt",
5709
5710        /* DBG_STATUS_RESERVED0 */
5711        "",
5712
5713        /* DBG_STATUS_SEMI_FIFO_NOT_EMPTY */
5714        "Failed to empty SEMI sync FIFO",
5715
5716        /* DBG_STATUS_IGU_FIFO_BAD_DATA */
5717        "IGU FIFO data is corrupt",
5718
5719        /* DBG_STATUS_MCP_COULD_NOT_MASK_PRTY */
5720        "MCP failed to mask parities",
5721
5722        /* DBG_STATUS_FW_ASSERTS_PARSE_FAILED */
5723        "FW Asserts parsing failed",
5724
5725        /* DBG_STATUS_REG_FIFO_BAD_DATA */
5726        "GRC FIFO data is corrupt",
5727
5728        /* DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA */
5729        "Protection Override data is corrupt",
5730
5731        /* DBG_STATUS_DBG_ARRAY_NOT_SET */
5732        "Debug arrays were not set (when using binary files, dbg_set_bin_ptr must be called)",
5733
5734        /* DBG_STATUS_RESERVED1 */
5735        "",
5736
5737        /* DBG_STATUS_NON_MATCHING_LINES */
5738        "Non-matching debug lines - in E4, all lines must be of the same type (either 128b or 256b)",
5739
5740        /* DBG_STATUS_INSUFFICIENT_HW_IDS */
5741        "Insufficient HW IDs. Try to record less Storms/blocks",
5742
5743        /* DBG_STATUS_DBG_BUS_IN_USE */
5744        "The debug bus is in use",
5745
5746        /* DBG_STATUS_INVALID_STORM_DBG_MODE */
5747        "The storm debug mode is not supported in the current chip",
5748
5749        /* DBG_STATUS_OTHER_ENGINE_BB_ONLY */
5750        "Other engine is supported only in BB",
5751
5752        /* DBG_STATUS_FILTER_SINGLE_HW_ID */
5753        "The configured filter mode requires a single Storm/block input",
5754
5755        /* DBG_STATUS_TRIGGER_SINGLE_HW_ID */
5756        "The configured filter mode requires that all the constraints of a single trigger state will be defined on a single Storm/block input",
5757
5758        /* DBG_STATUS_MISSING_TRIGGER_STATE_STORM */
5759        "When triggering on Storm data, the Storm to trigger on must be specified"
5760};
5761
5762/* Idle check severity names array */
5763static const char * const s_idle_chk_severity_str[] = {
5764        "Error",
5765        "Error if no traffic",
5766        "Warning"
5767};
5768
5769/* MCP Trace level names array */
5770static const char * const s_mcp_trace_level_str[] = {
5771        "ERROR",
5772        "TRACE",
5773        "DEBUG"
5774};
5775
5776/* Access type names array */
5777static const char * const s_access_strs[] = {
5778        "read",
5779        "write"
5780};
5781
5782/* Privilege type names array */
5783static const char * const s_privilege_strs[] = {
5784        "VF",
5785        "PDA",
5786        "HV",
5787        "UA"
5788};
5789
5790/* Protection type names array */
5791static const char * const s_protection_strs[] = {
5792        "(default)",
5793        "(default)",
5794        "(default)",
5795        "(default)",
5796        "override VF",
5797        "override PDA",
5798        "override HV",
5799        "override UA"
5800};
5801
5802/* Master type names array */
5803static const char * const s_master_strs[] = {
5804        "???",
5805        "pxp",
5806        "mcp",
5807        "msdm",
5808        "psdm",
5809        "ysdm",
5810        "usdm",
5811        "tsdm",
5812        "xsdm",
5813        "dbu",
5814        "dmae",
5815        "jdap",
5816        "???",
5817        "???",
5818        "???",
5819        "???"
5820};
5821
5822/* REG FIFO error messages array */
5823static struct reg_fifo_err s_reg_fifo_errors[] = {
5824        {1, "grc timeout"},
5825        {2, "address doesn't belong to any block"},
5826        {4, "reserved address in block or write to read-only address"},
5827        {8, "privilege/protection mismatch"},
5828        {16, "path isolation error"},
5829        {17, "RSL error"}
5830};
5831
5832/* IGU FIFO sources array */
5833static const char * const s_igu_fifo_source_strs[] = {
5834        "TSTORM",
5835        "MSTORM",
5836        "USTORM",
5837        "XSTORM",
5838        "YSTORM",
5839        "PSTORM",
5840        "PCIE",
5841        "NIG_QM_PBF",
5842        "CAU",
5843        "ATTN",
5844        "GRC",
5845};
5846
5847/* IGU FIFO error messages */
5848static const char * const s_igu_fifo_error_strs[] = {
5849        "no error",
5850        "length error",
5851        "function disabled",
5852        "VF sent command to attention address",
5853        "host sent prod update command",
5854        "read of during interrupt register while in MIMD mode",
5855        "access to PXP BAR reserved address",
5856        "producer update command to attention index",
5857        "unknown error",
5858        "SB index not valid",
5859        "SB relative index and FID not found",
5860        "FID not match",
5861        "command with error flag asserted (PCI error or CAU discard)",
5862        "VF sent cleanup and RF cleanup is disabled",
5863        "cleanup command on type bigger than 4"
5864};
5865
5866/* IGU FIFO address data */
5867static const struct igu_fifo_addr_data s_igu_fifo_addr_data[] = {
5868        {0x0, 0x101, "MSI-X Memory", NULL,
5869         IGU_ADDR_TYPE_MSIX_MEM},
5870        {0x102, 0x1ff, "reserved", NULL,
5871         IGU_ADDR_TYPE_RESERVED},
5872        {0x200, 0x200, "Write PBA[0:63]", NULL,
5873         IGU_ADDR_TYPE_WRITE_PBA},
5874        {0x201, 0x201, "Write PBA[64:127]", "reserved",
5875         IGU_ADDR_TYPE_WRITE_PBA},
5876        {0x202, 0x202, "Write PBA[128]", "reserved",
5877         IGU_ADDR_TYPE_WRITE_PBA},
5878        {0x203, 0x3ff, "reserved", NULL,
5879         IGU_ADDR_TYPE_RESERVED},
5880        {0x400, 0x5ef, "Write interrupt acknowledgment", NULL,
5881         IGU_ADDR_TYPE_WRITE_INT_ACK},
5882        {0x5f0, 0x5f0, "Attention bits update", NULL,
5883         IGU_ADDR_TYPE_WRITE_ATTN_BITS},
5884        {0x5f1, 0x5f1, "Attention bits set", NULL,
5885         IGU_ADDR_TYPE_WRITE_ATTN_BITS},
5886        {0x5f2, 0x5f2, "Attention bits clear", NULL,
5887         IGU_ADDR_TYPE_WRITE_ATTN_BITS},
5888        {0x5f3, 0x5f3, "Read interrupt 0:63 with mask", NULL,
5889         IGU_ADDR_TYPE_READ_INT},
5890        {0x5f4, 0x5f4, "Read interrupt 0:31 with mask", NULL,
5891         IGU_ADDR_TYPE_READ_INT},
5892        {0x5f5, 0x5f5, "Read interrupt 32:63 with mask", NULL,
5893         IGU_ADDR_TYPE_READ_INT},
5894        {0x5f6, 0x5f6, "Read interrupt 0:63 without mask", NULL,
5895         IGU_ADDR_TYPE_READ_INT},
5896        {0x5f7, 0x5ff, "reserved", NULL,
5897         IGU_ADDR_TYPE_RESERVED},
5898        {0x600, 0x7ff, "Producer update", NULL,
5899         IGU_ADDR_TYPE_WRITE_PROD_UPDATE}
5900};
5901
5902/******************************** Variables **********************************/
5903
5904/* Temporary buffer, used for print size calculations */
5905static char s_temp_buf[MAX_MSG_LEN];
5906
5907/**************************** Private Functions ******************************/
5908
5909static u32 qed_cyclic_add(u32 a, u32 b, u32 size)
5910{
5911        return (a + b) % size;
5912}
5913
5914static u32 qed_cyclic_sub(u32 a, u32 b, u32 size)
5915{
5916        return (size + a - b) % size;
5917}
5918
5919/* Reads the specified number of bytes from the specified cyclic buffer (up to 4
5920 * bytes) and returns them as a dword value. the specified buffer offset is
5921 * updated.
5922 */
5923static u32 qed_read_from_cyclic_buf(void *buf,
5924                                    u32 *offset,
5925                                    u32 buf_size, u8 num_bytes_to_read)
5926{
5927        u8 i, *val_ptr, *bytes_buf = (u8 *)buf;
5928        u32 val = 0;
5929
5930        val_ptr = (u8 *)&val;
5931
5932        /* Assume running on a LITTLE ENDIAN and the buffer is network order
5933         * (BIG ENDIAN), as high order bytes are placed in lower memory address.
5934         */
5935        for (i = 0; i < num_bytes_to_read; i++) {
5936                val_ptr[i] = bytes_buf[*offset];
5937                *offset = qed_cyclic_add(*offset, 1, buf_size);
5938        }
5939
5940        return val;
5941}
5942
5943/* Reads and returns the next byte from the specified buffer.
5944 * The specified buffer offset is updated.
5945 */
5946static u8 qed_read_byte_from_buf(void *buf, u32 *offset)
5947{
5948        return ((u8 *)buf)[(*offset)++];
5949}
5950
5951/* Reads and returns the next dword from the specified buffer.
5952 * The specified buffer offset is updated.
5953 */
5954static u32 qed_read_dword_from_buf(void *buf, u32 *offset)
5955{
5956        u32 dword_val = *(u32 *)&((u8 *)buf)[*offset];
5957
5958        *offset += 4;
5959
5960        return dword_val;
5961}
5962
5963/* Reads the next string from the specified buffer, and copies it to the
5964 * specified pointer. The specified buffer offset is updated.
5965 */
5966static void qed_read_str_from_buf(void *buf, u32 *offset, u32 size, char *dest)
5967{
5968        const char *source_str = &((const char *)buf)[*offset];
5969
5970        OSAL_STRNCPY(dest, source_str, size);
5971        dest[size - 1] = '\0';
5972        *offset += size;
5973}
5974
5975/* Returns a pointer to the specified offset (in bytes) of the specified buffer.
5976 * If the specified buffer in NULL, a temporary buffer pointer is returned.
5977 */
5978static char *qed_get_buf_ptr(void *buf, u32 offset)
5979{
5980        return buf ? (char *)buf + offset : s_temp_buf;
5981}
5982
5983/* Reads a param from the specified buffer. Returns the number of dwords read.
5984 * If the returned str_param is NULL, the param is numeric and its value is
5985 * returned in num_param.
5986 * Otheriwise, the param is a string and its pointer is returned in str_param.
5987 */
5988static u32 qed_read_param(u32 *dump_buf,
5989                          const char **param_name,
5990                          const char **param_str_val, u32 *param_num_val)
5991{
5992        char *char_buf = (char *)dump_buf;
5993        size_t offset = 0;
5994
5995        /* Extract param name */
5996        *param_name = char_buf;
5997        offset += strlen(*param_name) + 1;
5998
5999        /* Check param type */
6000        if (*(char_buf + offset++)) {
6001                /* String param */
6002                *param_str_val = char_buf + offset;
6003                *param_num_val = 0;
6004                offset += strlen(*param_str_val) + 1;
6005                if (offset & 0x3)
6006                        offset += (4 - (offset & 0x3));
6007        } else {
6008                /* Numeric param */
6009                *param_str_val = NULL;
6010                if (offset & 0x3)
6011                        offset += (4 - (offset & 0x3));
6012                *param_num_val = *(u32 *)(char_buf + offset);
6013                offset += 4;
6014        }
6015
6016        return (u32)offset / 4;
6017}
6018
6019/* Reads a section header from the specified buffer.
6020 * Returns the number of dwords read.
6021 */
6022static u32 qed_read_section_hdr(u32 *dump_buf,
6023                                const char **section_name,
6024                                u32 *num_section_params)
6025{
6026        const char *param_str_val;
6027
6028        return qed_read_param(dump_buf,
6029                              section_name, &param_str_val, num_section_params);
6030}
6031
6032/* Reads section params from the specified buffer and prints them to the results
6033 * buffer. Returns the number of dwords read.
6034 */
6035static u32 qed_print_section_params(u32 *dump_buf,
6036                                    u32 num_section_params,
6037                                    char *results_buf, u32 *num_chars_printed)
6038{
6039        u32 i, dump_offset = 0, results_offset = 0;
6040
6041        for (i = 0; i < num_section_params; i++) {
6042                const char *param_name, *param_str_val;
6043                u32 param_num_val = 0;
6044
6045                dump_offset += qed_read_param(dump_buf + dump_offset,
6046                                              &param_name,
6047                                              &param_str_val, &param_num_val);
6048
6049                if (param_str_val) {
6050                        results_offset +=
6051                                sprintf(qed_get_buf_ptr(results_buf,
6052                                                        results_offset),
6053                                        "%s: %s\n", param_name, param_str_val);
6054                } else if (strcmp(param_name, "fw-timestamp")) {
6055                        results_offset +=
6056                                sprintf(qed_get_buf_ptr(results_buf,
6057                                                        results_offset),
6058                                        "%s: %d\n", param_name, param_num_val);
6059                }
6060        }
6061
6062        results_offset += sprintf(qed_get_buf_ptr(results_buf, results_offset),
6063                                  "\n");
6064
6065        *num_chars_printed = results_offset;
6066
6067        return dump_offset;
6068}
6069
6070/* Returns the block name that matches the specified block ID,
6071 * or NULL if not found.
6072 */
6073static const char *qed_dbg_get_block_name(struct ecore_hwfn *p_hwfn,
6074                                          enum block_id block_id)
6075{
6076        const struct dbg_block_user *block =
6077            (const struct dbg_block_user *)
6078            p_hwfn->dbg_arrays[BIN_BUF_DBG_BLOCKS_USER_DATA].ptr + block_id;
6079
6080        return (const char *)block->name;
6081}
6082
6083static struct dbg_tools_user_data *qed_dbg_get_user_data(struct ecore_hwfn
6084                                                         *p_hwfn)
6085{
6086        return (struct dbg_tools_user_data *)p_hwfn->dbg_user_info;
6087}
6088
6089/* Parses the idle check rules and returns the number of characters printed.
6090 * In case of parsing error, returns 0.
6091 */
6092static u32 qed_parse_idle_chk_dump_rules(struct ecore_hwfn *p_hwfn,
6093                                         u32 *dump_buf,
6094                                         u32 *dump_buf_end,
6095                                         u32 num_rules,
6096                                         bool print_fw_idle_chk,
6097                                         char *results_buf,
6098                                         u32 *num_errors, u32 *num_warnings)
6099{
6100        /* Offset in results_buf in bytes */
6101        u32 results_offset = 0;
6102
6103        u32 rule_idx;
6104        u16 i, j;
6105
6106        *num_errors = 0;
6107        *num_warnings = 0;
6108
6109        /* Go over dumped results */
6110        for (rule_idx = 0; rule_idx < num_rules && dump_buf < dump_buf_end;
6111             rule_idx++) {
6112                const struct dbg_idle_chk_rule_parsing_data *rule_parsing_data;
6113                struct dbg_idle_chk_result_hdr *hdr;
6114                const char *parsing_str, *lsi_msg;
6115                u32 parsing_str_offset;
6116                bool has_fw_msg;
6117                u8 curr_reg_id;
6118
6119                hdr = (struct dbg_idle_chk_result_hdr *)dump_buf;
6120                rule_parsing_data =
6121                    (const struct dbg_idle_chk_rule_parsing_data *)
6122                    p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_PARSING_DATA].ptr +
6123                    hdr->rule_id;
6124                parsing_str_offset =
6125                    GET_FIELD(rule_parsing_data->data,
6126                              DBG_IDLE_CHK_RULE_PARSING_DATA_STR_OFFSET);
6127                has_fw_msg =
6128                    GET_FIELD(rule_parsing_data->data,
6129                              DBG_IDLE_CHK_RULE_PARSING_DATA_HAS_FW_MSG) > 0;
6130                parsing_str = (const char *)
6131                    p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr +
6132                    parsing_str_offset;
6133                lsi_msg = parsing_str;
6134                curr_reg_id = 0;
6135
6136                if (hdr->severity >= MAX_DBG_IDLE_CHK_SEVERITY_TYPES)
6137                        return 0;
6138
6139                /* Skip rule header */
6140                dump_buf += BYTES_TO_DWORDS(sizeof(*hdr));
6141
6142                /* Update errors/warnings count */
6143                if (hdr->severity == IDLE_CHK_SEVERITY_ERROR ||
6144                    hdr->severity == IDLE_CHK_SEVERITY_ERROR_NO_TRAFFIC)
6145                        (*num_errors)++;
6146                else
6147                        (*num_warnings)++;
6148
6149                /* Print rule severity */
6150                results_offset +=
6151                    sprintf(qed_get_buf_ptr(results_buf,
6152                                            results_offset), "%s: ",
6153                            s_idle_chk_severity_str[hdr->severity]);
6154
6155                /* Print rule message */
6156                if (has_fw_msg)
6157                        parsing_str += strlen(parsing_str) + 1;
6158                results_offset +=
6159                    sprintf(qed_get_buf_ptr(results_buf,
6160                                            results_offset), "%s.",
6161                            has_fw_msg &&
6162                            print_fw_idle_chk ? parsing_str : lsi_msg);
6163                parsing_str += strlen(parsing_str) + 1;
6164
6165                /* Print register values */
6166                results_offset +=
6167                    sprintf(qed_get_buf_ptr(results_buf,
6168                                            results_offset), " Registers:");
6169                for (i = 0;
6170                     i < hdr->num_dumped_cond_regs + hdr->num_dumped_info_regs;
6171                     i++) {
6172                        struct dbg_idle_chk_result_reg_hdr *reg_hdr;
6173                        bool is_mem;
6174                        u8 reg_id;
6175
6176                        reg_hdr =
6177                                (struct dbg_idle_chk_result_reg_hdr *)dump_buf;
6178                        is_mem = GET_FIELD(reg_hdr->data,
6179                                           DBG_IDLE_CHK_RESULT_REG_HDR_IS_MEM);
6180                        reg_id = GET_FIELD(reg_hdr->data,
6181                                           DBG_IDLE_CHK_RESULT_REG_HDR_REG_ID);
6182
6183                        /* Skip reg header */
6184                        dump_buf += BYTES_TO_DWORDS(sizeof(*reg_hdr));
6185
6186                        /* Skip register names until the required reg_id is
6187                         * reached.
6188                         */
6189                        while (reg_id > curr_reg_id) {
6190                                curr_reg_id++;
6191                                parsing_str += strlen(parsing_str) + 1;
6192                        }
6193
6194                        results_offset +=
6195                            sprintf(qed_get_buf_ptr(results_buf,
6196                                                    results_offset), " %s",
6197                                    parsing_str);
6198                        if (i < hdr->num_dumped_cond_regs && is_mem)
6199                                results_offset +=
6200                                    sprintf(qed_get_buf_ptr(results_buf,
6201                                                            results_offset),
6202                                            "[%d]", hdr->mem_entry_id +
6203                                            reg_hdr->start_entry);
6204                        results_offset +=
6205                            sprintf(qed_get_buf_ptr(results_buf,
6206                                                    results_offset), "=");
6207                        for (j = 0; j < reg_hdr->size; j++, dump_buf++) {
6208                                results_offset +=
6209                                    sprintf(qed_get_buf_ptr(results_buf,
6210                                                            results_offset),
6211                                            "0x%x", *dump_buf);
6212                                if (j < reg_hdr->size - 1)
6213                                        results_offset +=
6214                                            sprintf(qed_get_buf_ptr
6215                                                    (results_buf,
6216                                                     results_offset), ",");
6217                        }
6218                }
6219
6220                results_offset +=
6221                    sprintf(qed_get_buf_ptr(results_buf, results_offset), "\n");
6222        }
6223
6224        /* Check if end of dump buffer was exceeded */
6225        if (dump_buf > dump_buf_end)
6226                return 0;
6227
6228        return results_offset;
6229}
6230
6231/* Parses an idle check dump buffer.
6232 * If result_buf is not NULL, the idle check results are printed to it.
6233 * In any case, the required results buffer size is assigned to
6234 * parsed_results_bytes.
6235 * The parsing status is returned.
6236 */
6237static enum dbg_status qed_parse_idle_chk_dump(struct ecore_hwfn *p_hwfn,
6238                                               u32 *dump_buf,
6239                                               u32 num_dumped_dwords,
6240                                               char *results_buf,
6241                                               u32 *parsed_results_bytes,
6242                                               u32 *num_errors,
6243                                               u32 *num_warnings)
6244{
6245        const char *section_name, *param_name, *param_str_val;
6246        u32 *dump_buf_end = dump_buf + num_dumped_dwords;
6247        u32 num_section_params = 0, num_rules;
6248
6249        /* Offset in results_buf in bytes */
6250        u32 results_offset = 0;
6251
6252        *parsed_results_bytes = 0;
6253        *num_errors = 0;
6254        *num_warnings = 0;
6255
6256        if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr ||
6257            !p_hwfn->dbg_arrays[BIN_BUF_DBG_IDLE_CHK_PARSING_DATA].ptr)
6258                return DBG_STATUS_DBG_ARRAY_NOT_SET;
6259
6260        /* Read global_params section */
6261        dump_buf += qed_read_section_hdr(dump_buf,
6262                                         &section_name, &num_section_params);
6263        if (strcmp(section_name, "global_params"))
6264                return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
6265
6266        /* Print global params */
6267        dump_buf += qed_print_section_params(dump_buf,
6268                                             num_section_params,
6269                                             results_buf, &results_offset);
6270
6271        /* Read idle_chk section */
6272        dump_buf += qed_read_section_hdr(dump_buf,
6273                                         &section_name, &num_section_params);
6274        if (strcmp(section_name, "idle_chk") || num_section_params != 1)
6275                return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
6276        dump_buf += qed_read_param(dump_buf,
6277                                   &param_name, &param_str_val, &num_rules);
6278        if (strcmp(param_name, "num_rules"))
6279                return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
6280
6281        if (num_rules) {
6282                u32 rules_print_size;
6283
6284                /* Print FW output */
6285                results_offset +=
6286                    sprintf(qed_get_buf_ptr(results_buf,
6287                                            results_offset),
6288                            "FW_IDLE_CHECK:\n");
6289                rules_print_size =
6290                        qed_parse_idle_chk_dump_rules(p_hwfn,
6291                                                      dump_buf,
6292                                                      dump_buf_end,
6293                                                      num_rules,
6294                                                      true,
6295                                                      results_buf ?
6296                                                      results_buf +
6297                                                      results_offset :
6298                                                      NULL,
6299                                                      num_errors,
6300                                                      num_warnings);
6301                results_offset += rules_print_size;
6302                if (!rules_print_size)
6303                        return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
6304
6305                /* Print LSI output */
6306                results_offset +=
6307                    sprintf(qed_get_buf_ptr(results_buf,
6308                                            results_offset),
6309                            "\nLSI_IDLE_CHECK:\n");
6310                rules_print_size =
6311                        qed_parse_idle_chk_dump_rules(p_hwfn,
6312                                                      dump_buf,
6313                                                      dump_buf_end,
6314                                                      num_rules,
6315                                                      false,
6316                                                      results_buf ?
6317                                                      results_buf +
6318                                                      results_offset :
6319                                                      NULL,
6320                                                      num_errors,
6321                                                      num_warnings);
6322                results_offset += rules_print_size;
6323                if (!rules_print_size)
6324                        return DBG_STATUS_IDLE_CHK_PARSE_FAILED;
6325        }
6326
6327        /* Print errors/warnings count */
6328        if (*num_errors)
6329                results_offset +=
6330                    sprintf(qed_get_buf_ptr(results_buf,
6331                                            results_offset),
6332                            "\nIdle Check failed!!! (with %d errors and %d warnings)\n",
6333                            *num_errors, *num_warnings);
6334        else if (*num_warnings)
6335                results_offset +=
6336                    sprintf(qed_get_buf_ptr(results_buf,
6337                                            results_offset),
6338                            "\nIdle Check completed successfully (with %d warnings)\n",
6339                            *num_warnings);
6340        else
6341                results_offset +=
6342                    sprintf(qed_get_buf_ptr(results_buf,
6343                                            results_offset),
6344                            "\nIdle Check completed successfully\n");
6345
6346        /* Add 1 for string NULL termination */
6347        *parsed_results_bytes = results_offset + 1;
6348
6349        return DBG_STATUS_OK;
6350}
6351
6352/* Allocates and fills MCP Trace meta data based on the specified meta data
6353 * dump buffer.
6354 * Returns debug status code.
6355 */
6356static enum dbg_status
6357qed_mcp_trace_alloc_meta_data(struct ecore_hwfn *p_hwfn,
6358                              const u32 *meta_buf)
6359{
6360        struct dbg_tools_user_data *dev_user_data;
6361        u32 offset = 0, signature, i;
6362        struct mcp_trace_meta *meta;
6363        u8 *meta_buf_bytes = (u8 *)(osal_uintptr_t)meta_buf;
6364
6365        dev_user_data = qed_dbg_get_user_data(p_hwfn);
6366        meta = &dev_user_data->mcp_trace_meta;
6367
6368        /* Free the previous meta before loading a new one. */
6369        if (meta->is_allocated)
6370                qed_mcp_trace_free_meta_data(p_hwfn);
6371
6372        OSAL_MEMSET(meta, 0, sizeof(*meta));
6373
6374        /* Read first signature */
6375        signature = qed_read_dword_from_buf(meta_buf_bytes, &offset);
6376        if (signature != NVM_MAGIC_VALUE)
6377                return DBG_STATUS_INVALID_TRACE_SIGNATURE;
6378
6379        /* Read no. of modules and allocate memory for their pointers */
6380        meta->modules_num = qed_read_byte_from_buf(meta_buf_bytes, &offset);
6381        meta->modules = (char **)OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
6382                                    meta->modules_num * sizeof(char *));
6383        if (!meta->modules)
6384                return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
6385
6386        /* Allocate and read all module strings */
6387        for (i = 0; i < meta->modules_num; i++) {
6388                u8 module_len = qed_read_byte_from_buf(meta_buf_bytes, &offset);
6389
6390                *(meta->modules + i) = (char *)OSAL_ZALLOC(p_hwfn->p_dev,
6391                                                           GFP_KERNEL,
6392                                                           module_len);
6393                if (!(*(meta->modules + i))) {
6394                        /* Update number of modules to be released */
6395                        meta->modules_num = i ? i - 1 : 0;
6396                        return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
6397                }
6398
6399                qed_read_str_from_buf(meta_buf_bytes, &offset, module_len,
6400                                      *(meta->modules + i));
6401                if (module_len > MCP_TRACE_MAX_MODULE_LEN)
6402                        (*(meta->modules + i))[MCP_TRACE_MAX_MODULE_LEN] = '\0';
6403        }
6404
6405        /* Read second signature */
6406        signature = qed_read_dword_from_buf(meta_buf_bytes, &offset);
6407        if (signature != NVM_MAGIC_VALUE)
6408                return DBG_STATUS_INVALID_TRACE_SIGNATURE;
6409
6410        /* Read number of formats and allocate memory for all formats */
6411        meta->formats_num = qed_read_dword_from_buf(meta_buf_bytes, &offset);
6412        meta->formats =
6413                (struct mcp_trace_format *)OSAL_ZALLOC(p_hwfn->p_dev,
6414                                                       GFP_KERNEL,
6415                                                       meta->formats_num *
6416                                               sizeof(struct mcp_trace_format));
6417        if (!meta->formats)
6418                return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
6419
6420        /* Allocate and read all strings */
6421        for (i = 0; i < meta->formats_num; i++) {
6422                struct mcp_trace_format *format_ptr = &meta->formats[i];
6423                u8 format_len;
6424
6425                format_ptr->data = qed_read_dword_from_buf(meta_buf_bytes,
6426                                                           &offset);
6427                format_len = GET_MFW_FIELD(format_ptr->data,
6428                                           MCP_TRACE_FORMAT_LEN);
6429                format_ptr->format_str = (char *)OSAL_ZALLOC(p_hwfn->p_dev,
6430                                                             GFP_KERNEL,
6431                                                             format_len);
6432                if (!format_ptr->format_str) {
6433                        /* Update number of modules to be released */
6434                        meta->formats_num = i ? i - 1 : 0;
6435                        return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
6436                }
6437
6438                qed_read_str_from_buf(meta_buf_bytes,
6439                                      &offset,
6440                                      format_len, format_ptr->format_str);
6441        }
6442
6443        meta->is_allocated = true;
6444        return DBG_STATUS_OK;
6445}
6446
6447/* Parses an MCP trace buffer. If result_buf is not NULL, the MCP Trace results
6448 * are printed to it. The parsing status is returned.
6449 * Arguments:
6450 * trace_buf - MCP trace cyclic buffer
6451 * trace_buf_size - MCP trace cyclic buffer size in bytes
6452 * data_offset - offset in bytes of the data to parse in the MCP trace cyclic
6453 *               buffer.
6454 * data_size - size in bytes of data to parse.
6455 * parsed_buf - destination buffer for parsed data.
6456 * parsed_results_bytes - size of parsed data in bytes.
6457 */
6458static enum dbg_status qed_parse_mcp_trace_buf(struct ecore_hwfn *p_hwfn,
6459                                               u8 *trace_buf,
6460                                               u32 trace_buf_size,
6461                                               u32 data_offset,
6462                                               u32 data_size,
6463                                               char *parsed_buf,
6464                                               u32 *parsed_results_bytes)
6465{
6466        struct dbg_tools_user_data *dev_user_data;
6467        struct mcp_trace_meta *meta;
6468        u32 param_mask, param_shift;
6469        enum dbg_status status;
6470
6471        dev_user_data = qed_dbg_get_user_data(p_hwfn);
6472        meta = &dev_user_data->mcp_trace_meta;
6473        *parsed_results_bytes = 0;
6474
6475        if (!meta->is_allocated)
6476                return DBG_STATUS_MCP_TRACE_BAD_DATA;
6477
6478        status = DBG_STATUS_OK;
6479
6480        while (data_size) {
6481                struct mcp_trace_format *format_ptr;
6482                u8 format_level, format_module;
6483                u32 params[3] = { 0, 0, 0 };
6484                u32 header, format_idx, i;
6485
6486                if (data_size < MFW_TRACE_ENTRY_SIZE)
6487                        return DBG_STATUS_MCP_TRACE_BAD_DATA;
6488
6489                header = qed_read_from_cyclic_buf(trace_buf,
6490                                                  &data_offset,
6491                                                  trace_buf_size,
6492                                                  MFW_TRACE_ENTRY_SIZE);
6493                data_size -= MFW_TRACE_ENTRY_SIZE;
6494                format_idx = header & MFW_TRACE_EVENTID_MASK;
6495
6496                /* Skip message if its index doesn't exist in the meta data */
6497                if (format_idx >= meta->formats_num) {
6498                        u8 format_size = (u8)GET_MFW_FIELD(header,
6499                                                           MFW_TRACE_PRM_SIZE);
6500
6501                        if (data_size < format_size)
6502                                return DBG_STATUS_MCP_TRACE_BAD_DATA;
6503
6504                        data_offset = qed_cyclic_add(data_offset,
6505                                                     format_size,
6506                                                     trace_buf_size);
6507                        data_size -= format_size;
6508                        continue;
6509                }
6510
6511                format_ptr =
6512                        (struct mcp_trace_format *)&meta->formats[format_idx];
6513
6514                for (i = 0,
6515                     param_mask = MCP_TRACE_FORMAT_P1_SIZE_MASK, param_shift =
6516                     MCP_TRACE_FORMAT_P1_SIZE_OFFSET;
6517                     i < MCP_TRACE_FORMAT_MAX_PARAMS;
6518                     i++, param_mask <<= MCP_TRACE_FORMAT_PARAM_WIDTH,
6519                     param_shift += MCP_TRACE_FORMAT_PARAM_WIDTH) {
6520                        /* Extract param size (0..3) */
6521                        u8 param_size = (u8)((format_ptr->data & param_mask) >>
6522                                             param_shift);
6523
6524                        /* If the param size is zero, there are no other
6525                         * parameters.
6526                         */
6527                        if (!param_size)
6528                                break;
6529
6530                        /* Size is encoded using 2 bits, where 3 is used to
6531                         * encode 4.
6532                         */
6533                        if (param_size == 3)
6534                                param_size = 4;
6535
6536                        if (data_size < param_size)
6537                                return DBG_STATUS_MCP_TRACE_BAD_DATA;
6538
6539                        params[i] = qed_read_from_cyclic_buf(trace_buf,
6540                                                             &data_offset,
6541                                                             trace_buf_size,
6542                                                             param_size);
6543                        data_size -= param_size;
6544                }
6545
6546                format_level = (u8)GET_MFW_FIELD(format_ptr->data,
6547                                                 MCP_TRACE_FORMAT_LEVEL);
6548                format_module = (u8)GET_MFW_FIELD(format_ptr->data,
6549                                                  MCP_TRACE_FORMAT_MODULE);
6550                if (format_level >= OSAL_ARRAY_SIZE(s_mcp_trace_level_str))
6551                        return DBG_STATUS_MCP_TRACE_BAD_DATA;
6552
6553                /* Print current message to results buffer */
6554                *parsed_results_bytes +=
6555                        OSAL_SPRINTF(qed_get_buf_ptr(parsed_buf,
6556                                                *parsed_results_bytes),
6557                                "%s %-8s: ",
6558                                s_mcp_trace_level_str[format_level],
6559                                meta->modules[format_module]);
6560                *parsed_results_bytes +=
6561                    sprintf(qed_get_buf_ptr(parsed_buf, *parsed_results_bytes),
6562                            format_ptr->format_str,
6563                            params[0], params[1], params[2]);
6564        }
6565
6566        /* Add string NULL terminator */
6567        (*parsed_results_bytes)++;
6568
6569        return status;
6570}
6571
6572/* Parses an MCP Trace dump buffer.
6573 * If result_buf is not NULL, the MCP Trace results are printed to it.
6574 * In any case, the required results buffer size is assigned to
6575 * parsed_results_bytes.
6576 * The parsing status is returned.
6577 */
6578static enum dbg_status qed_parse_mcp_trace_dump(struct ecore_hwfn *p_hwfn,
6579                                                u32 *dump_buf,
6580                                                char *results_buf,
6581                                                u32 *parsed_results_bytes,
6582                                                bool free_meta_data)
6583{
6584        const char *section_name, *param_name, *param_str_val;
6585        u32 data_size, trace_data_dwords, trace_meta_dwords;
6586        u32 offset, results_offset, results_buf_bytes;
6587        u32 param_num_val, num_section_params;
6588        struct mcp_trace *trace;
6589        enum dbg_status status;
6590        const u32 *meta_buf;
6591        u8 *trace_buf;
6592
6593        *parsed_results_bytes = 0;
6594
6595        /* Read global_params section */
6596        dump_buf += qed_read_section_hdr(dump_buf,
6597                                         &section_name, &num_section_params);
6598        if (strcmp(section_name, "global_params"))
6599                return DBG_STATUS_MCP_TRACE_BAD_DATA;
6600
6601        /* Print global params */
6602        dump_buf += qed_print_section_params(dump_buf,
6603                                             num_section_params,
6604                                             results_buf, &results_offset);
6605
6606        /* Read trace_data section */
6607        dump_buf += qed_read_section_hdr(dump_buf,
6608                                         &section_name, &num_section_params);
6609        if (strcmp(section_name, "mcp_trace_data") || num_section_params != 1)
6610                return DBG_STATUS_MCP_TRACE_BAD_DATA;
6611        dump_buf += qed_read_param(dump_buf,
6612                                   &param_name, &param_str_val, &param_num_val);
6613        if (strcmp(param_name, "size"))
6614                return DBG_STATUS_MCP_TRACE_BAD_DATA;
6615        trace_data_dwords = param_num_val;
6616
6617        /* Prepare trace info */
6618        trace = (struct mcp_trace *)dump_buf;
6619        if (trace->signature != MFW_TRACE_SIGNATURE || !trace->size)
6620                return DBG_STATUS_MCP_TRACE_BAD_DATA;
6621
6622        trace_buf = (u8 *)dump_buf + sizeof(*trace);
6623        offset = trace->trace_oldest;
6624        data_size = qed_cyclic_sub(trace->trace_prod, offset, trace->size);
6625        dump_buf += trace_data_dwords;
6626
6627        /* Read meta_data section */
6628        dump_buf += qed_read_section_hdr(dump_buf,
6629                                         &section_name, &num_section_params);
6630        if (strcmp(section_name, "mcp_trace_meta"))
6631                return DBG_STATUS_MCP_TRACE_BAD_DATA;
6632        dump_buf += qed_read_param(dump_buf,
6633                                   &param_name, &param_str_val, &param_num_val);
6634        if (strcmp(param_name, "size"))
6635                return DBG_STATUS_MCP_TRACE_BAD_DATA;
6636        trace_meta_dwords = param_num_val;
6637
6638        /* Choose meta data buffer */
6639        if (!trace_meta_dwords) {
6640                /* Dump doesn't include meta data */
6641                struct dbg_tools_user_data *dev_user_data =
6642                        qed_dbg_get_user_data(p_hwfn);
6643
6644                if (!dev_user_data->mcp_trace_user_meta_buf)
6645                        return DBG_STATUS_MCP_TRACE_NO_META;
6646
6647                meta_buf = dev_user_data->mcp_trace_user_meta_buf;
6648        } else {
6649                /* Dump includes meta data */
6650                meta_buf = dump_buf;
6651        }
6652
6653        /* Allocate meta data memory */
6654        status = qed_mcp_trace_alloc_meta_data(p_hwfn, meta_buf);
6655        if (status != DBG_STATUS_OK)
6656                return status;
6657
6658        status = qed_parse_mcp_trace_buf(p_hwfn,
6659                                         trace_buf,
6660                                         trace->size,
6661                                         offset,
6662                                         data_size,
6663                                         results_buf ?
6664                                         results_buf + results_offset :
6665                                         NULL,
6666                                         &results_buf_bytes);
6667        if (status != DBG_STATUS_OK)
6668                return status;
6669
6670        if (free_meta_data)
6671                qed_mcp_trace_free_meta_data(p_hwfn);
6672
6673        *parsed_results_bytes = results_offset + results_buf_bytes;
6674
6675        return DBG_STATUS_OK;
6676}
6677
6678/* Parses a Reg FIFO dump buffer.
6679 * If result_buf is not NULL, the Reg FIFO results are printed to it.
6680 * In any case, the required results buffer size is assigned to
6681 * parsed_results_bytes.
6682 * The parsing status is returned.
6683 */
6684static enum dbg_status qed_parse_reg_fifo_dump(u32 *dump_buf,
6685                                               char *results_buf,
6686                                               u32 *parsed_results_bytes)
6687{
6688        const char *section_name, *param_name, *param_str_val;
6689        u32 param_num_val, num_section_params, num_elements;
6690        struct reg_fifo_element *elements;
6691        u8 i, j, err_code, vf_val;
6692        u32 results_offset = 0;
6693        char vf_str[4];
6694
6695        /* Read global_params section */
6696        dump_buf += qed_read_section_hdr(dump_buf,
6697                                         &section_name, &num_section_params);
6698        if (strcmp(section_name, "global_params"))
6699                return DBG_STATUS_REG_FIFO_BAD_DATA;
6700
6701        /* Print global params */
6702        dump_buf += qed_print_section_params(dump_buf,
6703                                             num_section_params,
6704                                             results_buf, &results_offset);
6705
6706        /* Read reg_fifo_data section */
6707        dump_buf += qed_read_section_hdr(dump_buf,
6708                                         &section_name, &num_section_params);
6709        if (strcmp(section_name, "reg_fifo_data"))
6710                return DBG_STATUS_REG_FIFO_BAD_DATA;
6711        dump_buf += qed_read_param(dump_buf,
6712                                   &param_name, &param_str_val, &param_num_val);
6713        if (strcmp(param_name, "size"))
6714                return DBG_STATUS_REG_FIFO_BAD_DATA;
6715        if (param_num_val % REG_FIFO_ELEMENT_DWORDS)
6716                return DBG_STATUS_REG_FIFO_BAD_DATA;
6717        num_elements = param_num_val / REG_FIFO_ELEMENT_DWORDS;
6718        elements = (struct reg_fifo_element *)dump_buf;
6719
6720        /* Decode elements */
6721        for (i = 0; i < num_elements; i++) {
6722                const char *err_msg = NULL;
6723
6724                /* Discover if element belongs to a VF or a PF */
6725                vf_val = GET_FIELD(elements[i].data, REG_FIFO_ELEMENT_VF);
6726                if (vf_val == REG_FIFO_ELEMENT_IS_PF_VF_VAL)
6727                        sprintf(vf_str, "%s", "N/A");
6728                else
6729                        sprintf(vf_str, "%d", vf_val);
6730
6731                /* Find error message */
6732                err_code = GET_FIELD(elements[i].data, REG_FIFO_ELEMENT_ERROR);
6733                for (j = 0; j < OSAL_ARRAY_SIZE(s_reg_fifo_errors) && !err_msg;
6734                     j++)
6735                        if (err_code == s_reg_fifo_errors[j].err_code)
6736                                err_msg = s_reg_fifo_errors[j].err_msg;
6737
6738                /* Add parsed element to parsed buffer */
6739                results_offset +=
6740                    sprintf(qed_get_buf_ptr(results_buf,
6741                                            results_offset),
6742                            "raw: 0x%016"PRIx64", address: 0x%07x, access: %-5s, pf: %2d, vf: %s, "
6743                            "port: %d, privilege: %-3s, protection: %-12s, master: %-4s, error: %s\n",
6744                            elements[i].data,
6745                            (u32)GET_FIELD(elements[i].data,
6746                                           REG_FIFO_ELEMENT_ADDRESS) *
6747                            REG_FIFO_ELEMENT_ADDR_FACTOR,
6748                            s_access_strs[GET_FIELD(elements[i].data,
6749                                                    REG_FIFO_ELEMENT_ACCESS)],
6750                            (u32)GET_FIELD(elements[i].data,
6751                                           REG_FIFO_ELEMENT_PF),
6752                            vf_str,
6753                            (u32)GET_FIELD(elements[i].data,
6754                                           REG_FIFO_ELEMENT_PORT),
6755                            s_privilege_strs[GET_FIELD(elements[i].data,
6756                                                REG_FIFO_ELEMENT_PRIVILEGE)],
6757                            s_protection_strs[GET_FIELD(elements[i].data,
6758                                                REG_FIFO_ELEMENT_PROTECTION)],
6759                            s_master_strs[GET_FIELD(elements[i].data,
6760                                                    REG_FIFO_ELEMENT_MASTER)],
6761                            err_msg ? err_msg : "unknown error code");
6762        }
6763
6764        results_offset += sprintf(qed_get_buf_ptr(results_buf,
6765                                                  results_offset),
6766                                  "fifo contained %d elements", num_elements);
6767
6768        /* Add 1 for string NULL termination */
6769        *parsed_results_bytes = results_offset + 1;
6770
6771        return DBG_STATUS_OK;
6772}
6773
6774static enum dbg_status qed_parse_igu_fifo_element(struct igu_fifo_element
6775                                                  *element, char
6776                                                  *results_buf,
6777                                                  u32 *results_offset)
6778{
6779        const struct igu_fifo_addr_data *found_addr = NULL;
6780        u8 source, err_type, i, is_cleanup;
6781        char parsed_addr_data[32];
6782        char parsed_wr_data[256];
6783        u32 wr_data, prod_cons;
6784        bool is_wr_cmd, is_pf;
6785        u16 cmd_addr;
6786        u64 dword12;
6787
6788        /* Dword12 (dword index 1 and 2) contains bits 32..95 of the
6789         * FIFO element.
6790         */
6791        dword12 = ((u64)element->dword2 << 32) | element->dword1;
6792        is_wr_cmd = GET_FIELD(dword12, IGU_FIFO_ELEMENT_DWORD12_IS_WR_CMD);
6793        is_pf = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_IS_PF);
6794        cmd_addr = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_CMD_ADDR);
6795        source = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_SOURCE);
6796        err_type = GET_FIELD(element->dword0, IGU_FIFO_ELEMENT_DWORD0_ERR_TYPE);
6797
6798        if (source >= OSAL_ARRAY_SIZE(s_igu_fifo_source_strs))
6799                return DBG_STATUS_IGU_FIFO_BAD_DATA;
6800        if (err_type >= OSAL_ARRAY_SIZE(s_igu_fifo_error_strs))
6801                return DBG_STATUS_IGU_FIFO_BAD_DATA;
6802
6803        /* Find address data */
6804        for (i = 0; i < OSAL_ARRAY_SIZE(s_igu_fifo_addr_data) && !found_addr;
6805             i++) {
6806                const struct igu_fifo_addr_data *curr_addr =
6807                        &s_igu_fifo_addr_data[i];
6808
6809                if (cmd_addr >= curr_addr->start_addr && cmd_addr <=
6810                    curr_addr->end_addr)
6811                        found_addr = curr_addr;
6812        }
6813
6814        if (!found_addr)
6815                return DBG_STATUS_IGU_FIFO_BAD_DATA;
6816
6817        /* Prepare parsed address data */
6818        switch (found_addr->type) {
6819        case IGU_ADDR_TYPE_MSIX_MEM:
6820                sprintf(parsed_addr_data, " vector_num = 0x%x", cmd_addr / 2);
6821                break;
6822        case IGU_ADDR_TYPE_WRITE_INT_ACK:
6823        case IGU_ADDR_TYPE_WRITE_PROD_UPDATE:
6824                sprintf(parsed_addr_data,
6825                        " SB = 0x%x", cmd_addr - found_addr->start_addr);
6826                break;
6827        default:
6828                parsed_addr_data[0] = '\0';
6829        }
6830
6831        if (!is_wr_cmd) {
6832                parsed_wr_data[0] = '\0';
6833                goto out;
6834        }
6835
6836        /* Prepare parsed write data */
6837        wr_data = GET_FIELD(dword12, IGU_FIFO_ELEMENT_DWORD12_WR_DATA);
6838        prod_cons = GET_FIELD(wr_data, IGU_FIFO_WR_DATA_PROD_CONS);
6839        is_cleanup = GET_FIELD(wr_data, IGU_FIFO_WR_DATA_CMD_TYPE);
6840
6841        if (source == IGU_SRC_ATTN) {
6842                sprintf(parsed_wr_data, "prod: 0x%x, ", prod_cons);
6843        } else {
6844                if (is_cleanup) {
6845                        u8 cleanup_val, cleanup_type;
6846
6847                        cleanup_val =
6848                                GET_FIELD(wr_data,
6849                                          IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_VAL);
6850                        cleanup_type =
6851                            GET_FIELD(wr_data,
6852                                      IGU_FIFO_CLEANUP_WR_DATA_CLEANUP_TYPE);
6853
6854                        sprintf(parsed_wr_data,
6855                                "cmd_type: cleanup, cleanup_val: %s, cleanup_type : %d, ",
6856                                cleanup_val ? "set" : "clear",
6857                                cleanup_type);
6858                } else {
6859                        u8 update_flag, en_dis_int_for_sb, segment;
6860                        u8 timer_mask;
6861
6862                        update_flag = GET_FIELD(wr_data,
6863                                                IGU_FIFO_WR_DATA_UPDATE_FLAG);
6864                        en_dis_int_for_sb =
6865                                GET_FIELD(wr_data,
6866                                          IGU_FIFO_WR_DATA_EN_DIS_INT_FOR_SB);
6867                        segment = GET_FIELD(wr_data,
6868                                            IGU_FIFO_WR_DATA_SEGMENT);
6869                        timer_mask = GET_FIELD(wr_data,
6870                                               IGU_FIFO_WR_DATA_TIMER_MASK);
6871
6872                        sprintf(parsed_wr_data,
6873                                "cmd_type: prod/cons update, prod/cons: 0x%x, update_flag: %s, en_dis_int_for_sb : %s, segment : %s, timer_mask = %d, ",
6874                                prod_cons,
6875                                update_flag ? "update" : "nop",
6876                                en_dis_int_for_sb ?
6877                                (en_dis_int_for_sb == 1 ? "disable" : "nop") :
6878                                "enable",
6879                                segment ? "attn" : "regular",
6880                                timer_mask);
6881                }
6882        }
6883out:
6884        /* Add parsed element to parsed buffer */
6885        *results_offset += sprintf(qed_get_buf_ptr(results_buf,
6886                                                   *results_offset),
6887                                   "raw: 0x%01x%08x%08x, %s: %d, source : %s, type : %s, cmd_addr : 0x%x(%s%s), %serror: %s\n",
6888                                   element->dword2, element->dword1,
6889                                   element->dword0,
6890                                   is_pf ? "pf" : "vf",
6891                                   GET_FIELD(element->dword0,
6892                                             IGU_FIFO_ELEMENT_DWORD0_FID),
6893                                   s_igu_fifo_source_strs[source],
6894                                   is_wr_cmd ? "wr" : "rd",
6895                                   cmd_addr,
6896                                   (!is_pf && found_addr->vf_desc)
6897                                   ? found_addr->vf_desc
6898                                   : found_addr->desc,
6899                                   parsed_addr_data,
6900                                   parsed_wr_data,
6901                                   s_igu_fifo_error_strs[err_type]);
6902
6903        return DBG_STATUS_OK;
6904}
6905
6906/* Parses an IGU FIFO dump buffer.
6907 * If result_buf is not NULL, the IGU FIFO results are printed to it.
6908 * In any case, the required results buffer size is assigned to
6909 * parsed_results_bytes.
6910 * The parsing status is returned.
6911 */
6912static enum dbg_status qed_parse_igu_fifo_dump(u32 *dump_buf,
6913                                               char *results_buf,
6914                                               u32 *parsed_results_bytes)
6915{
6916        const char *section_name, *param_name, *param_str_val;
6917        u32 param_num_val, num_section_params, num_elements;
6918        struct igu_fifo_element *elements;
6919        enum dbg_status status;
6920        u32 results_offset = 0;
6921        u8 i;
6922
6923        /* Read global_params section */
6924        dump_buf += qed_read_section_hdr(dump_buf,
6925                                         &section_name, &num_section_params);
6926        if (strcmp(section_name, "global_params"))
6927                return DBG_STATUS_IGU_FIFO_BAD_DATA;
6928
6929        /* Print global params */
6930        dump_buf += qed_print_section_params(dump_buf,
6931                                             num_section_params,
6932                                             results_buf, &results_offset);
6933
6934        /* Read igu_fifo_data section */
6935        dump_buf += qed_read_section_hdr(dump_buf,
6936                                         &section_name, &num_section_params);
6937        if (strcmp(section_name, "igu_fifo_data"))
6938                return DBG_STATUS_IGU_FIFO_BAD_DATA;
6939        dump_buf += qed_read_param(dump_buf,
6940                                   &param_name, &param_str_val, &param_num_val);
6941        if (strcmp(param_name, "size"))
6942                return DBG_STATUS_IGU_FIFO_BAD_DATA;
6943        if (param_num_val % IGU_FIFO_ELEMENT_DWORDS)
6944                return DBG_STATUS_IGU_FIFO_BAD_DATA;
6945        num_elements = param_num_val / IGU_FIFO_ELEMENT_DWORDS;
6946        elements = (struct igu_fifo_element *)dump_buf;
6947
6948        /* Decode elements */
6949        for (i = 0; i < num_elements; i++) {
6950                status = qed_parse_igu_fifo_element(&elements[i],
6951                                                    results_buf,
6952                                                    &results_offset);
6953                if (status != DBG_STATUS_OK)
6954                        return status;
6955        }
6956
6957        results_offset += sprintf(qed_get_buf_ptr(results_buf,
6958                                                  results_offset),
6959                                  "fifo contained %d elements", num_elements);
6960
6961        /* Add 1 for string NULL termination */
6962        *parsed_results_bytes = results_offset + 1;
6963
6964        return DBG_STATUS_OK;
6965}
6966
6967static enum dbg_status
6968qed_parse_protection_override_dump(u32 *dump_buf,
6969                                   char *results_buf,
6970                                   u32 *parsed_results_bytes)
6971{
6972        const char *section_name, *param_name, *param_str_val;
6973        u32 param_num_val, num_section_params, num_elements;
6974        struct protection_override_element *elements;
6975        u32 results_offset = 0;
6976        u8 i;
6977
6978        /* Read global_params section */
6979        dump_buf += qed_read_section_hdr(dump_buf,
6980                                         &section_name, &num_section_params);
6981        if (strcmp(section_name, "global_params"))
6982                return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
6983
6984        /* Print global params */
6985        dump_buf += qed_print_section_params(dump_buf,
6986                                             num_section_params,
6987                                             results_buf, &results_offset);
6988
6989        /* Read protection_override_data section */
6990        dump_buf += qed_read_section_hdr(dump_buf,
6991                                         &section_name, &num_section_params);
6992        if (strcmp(section_name, "protection_override_data"))
6993                return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
6994        dump_buf += qed_read_param(dump_buf,
6995                                   &param_name, &param_str_val, &param_num_val);
6996        if (strcmp(param_name, "size"))
6997                return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
6998        if (param_num_val % PROTECTION_OVERRIDE_ELEMENT_DWORDS)
6999                return DBG_STATUS_PROTECTION_OVERRIDE_BAD_DATA;
7000        num_elements = param_num_val / PROTECTION_OVERRIDE_ELEMENT_DWORDS;
7001        elements = (struct protection_override_element *)dump_buf;
7002
7003        /* Decode elements */
7004        for (i = 0; i < num_elements; i++) {
7005                u32 address = GET_FIELD(elements[i].data,
7006                                        PROTECTION_OVERRIDE_ELEMENT_ADDRESS) *
7007                              PROTECTION_OVERRIDE_ELEMENT_ADDR_FACTOR;
7008
7009                results_offset +=
7010                    sprintf(qed_get_buf_ptr(results_buf,
7011                                            results_offset),
7012                            "window %2d, address: 0x%07x, size: %7d regs, read: %d, write: %d, read protection: %-12s, write protection: %-12s\n",
7013                            i, address,
7014                            (u32)GET_FIELD(elements[i].data,
7015                                      PROTECTION_OVERRIDE_ELEMENT_WINDOW_SIZE),
7016                            (u32)GET_FIELD(elements[i].data,
7017                                      PROTECTION_OVERRIDE_ELEMENT_READ),
7018                            (u32)GET_FIELD(elements[i].data,
7019                                      PROTECTION_OVERRIDE_ELEMENT_WRITE),
7020                            s_protection_strs[GET_FIELD(elements[i].data,
7021                                PROTECTION_OVERRIDE_ELEMENT_READ_PROTECTION)],
7022                            s_protection_strs[GET_FIELD(elements[i].data,
7023                                PROTECTION_OVERRIDE_ELEMENT_WRITE_PROTECTION)]);
7024        }
7025
7026        results_offset += sprintf(qed_get_buf_ptr(results_buf,
7027                                                  results_offset),
7028                                  "protection override contained %d elements",
7029                                  num_elements);
7030
7031        /* Add 1 for string NULL termination */
7032        *parsed_results_bytes = results_offset + 1;
7033
7034        return DBG_STATUS_OK;
7035}
7036
7037/* Parses a FW Asserts dump buffer.
7038 * If result_buf is not NULL, the FW Asserts results are printed to it.
7039 * In any case, the required results buffer size is assigned to
7040 * parsed_results_bytes.
7041 * The parsing status is returned.
7042 */
7043static enum dbg_status qed_parse_fw_asserts_dump(u32 *dump_buf,
7044                                                 char *results_buf,
7045                                                 u32 *parsed_results_bytes)
7046{
7047        u32 num_section_params, param_num_val, i, results_offset = 0;
7048        const char *param_name, *param_str_val, *section_name;
7049        bool last_section_found = false;
7050
7051        *parsed_results_bytes = 0;
7052
7053        /* Read global_params section */
7054        dump_buf += qed_read_section_hdr(dump_buf,
7055                                         &section_name, &num_section_params);
7056        if (strcmp(section_name, "global_params"))
7057                return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
7058
7059        /* Print global params */
7060        dump_buf += qed_print_section_params(dump_buf,
7061                                             num_section_params,
7062                                             results_buf, &results_offset);
7063
7064        while (!last_section_found) {
7065                dump_buf += qed_read_section_hdr(dump_buf,
7066                                                 &section_name,
7067                                                 &num_section_params);
7068                if (!strcmp(section_name, "fw_asserts")) {
7069                        /* Extract params */
7070                        const char *storm_letter = NULL;
7071                        u32 storm_dump_size = 0;
7072
7073                        for (i = 0; i < num_section_params; i++) {
7074                                dump_buf += qed_read_param(dump_buf,
7075                                                           &param_name,
7076                                                           &param_str_val,
7077                                                           &param_num_val);
7078                                if (!strcmp(param_name, "storm"))
7079                                        storm_letter = param_str_val;
7080                                else if (!strcmp(param_name, "size"))
7081                                        storm_dump_size = param_num_val;
7082                                else
7083                                        return
7084                                            DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
7085                        }
7086
7087                        if (!storm_letter || !storm_dump_size)
7088                                return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
7089
7090                        /* Print data */
7091                        results_offset +=
7092                            sprintf(qed_get_buf_ptr(results_buf,
7093                                                    results_offset),
7094                                    "\n%sSTORM_ASSERT: size=%d\n",
7095                                    storm_letter, storm_dump_size);
7096                        for (i = 0; i < storm_dump_size; i++, dump_buf++)
7097                                results_offset +=
7098                                    sprintf(qed_get_buf_ptr(results_buf,
7099                                                            results_offset),
7100                                            "%08x\n", *dump_buf);
7101                } else if (!strcmp(section_name, "last")) {
7102                        last_section_found = true;
7103                } else {
7104                        return DBG_STATUS_FW_ASSERTS_PARSE_FAILED;
7105                }
7106        }
7107
7108        /* Add 1 for string NULL termination */
7109        *parsed_results_bytes = results_offset + 1;
7110
7111        return DBG_STATUS_OK;
7112}
7113
7114/***************************** Public Functions *******************************/
7115
7116enum dbg_status qed_dbg_user_set_bin_ptr(struct ecore_hwfn *p_hwfn,
7117                                         const u8 * const bin_ptr)
7118{
7119        struct bin_buffer_hdr *buf_hdrs =
7120                        (struct bin_buffer_hdr *)(osal_uintptr_t)bin_ptr;
7121        u8 buf_id;
7122
7123        /* Convert binary data to debug arrays */
7124        for (buf_id = 0; buf_id < MAX_BIN_DBG_BUFFER_TYPE; buf_id++)
7125                qed_set_dbg_bin_buf(p_hwfn,
7126                                    (enum bin_dbg_buffer_type)buf_id,
7127                                    (const u32 *)(bin_ptr +
7128                                                  buf_hdrs[buf_id].offset),
7129                                                  buf_hdrs[buf_id].length);
7130
7131        return DBG_STATUS_OK;
7132}
7133
7134enum dbg_status qed_dbg_alloc_user_data(__rte_unused struct ecore_hwfn *p_hwfn,
7135                                        void **user_data_ptr)
7136{
7137        *user_data_ptr = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
7138                                     sizeof(struct dbg_tools_user_data));
7139        if (!(*user_data_ptr))
7140                return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
7141
7142        return DBG_STATUS_OK;
7143}
7144
7145const char *qed_dbg_get_status_str(enum dbg_status status)
7146{
7147        return (status <
7148                MAX_DBG_STATUS) ? s_status_str[status] : "Invalid debug status";
7149}
7150
7151enum dbg_status qed_get_idle_chk_results_buf_size(struct ecore_hwfn *p_hwfn,
7152                                                  u32 *dump_buf,
7153                                                  u32 num_dumped_dwords,
7154                                                  u32 *results_buf_size)
7155{
7156        u32 num_errors, num_warnings;
7157
7158        return qed_parse_idle_chk_dump(p_hwfn,
7159                                       dump_buf,
7160                                       num_dumped_dwords,
7161                                       NULL,
7162                                       results_buf_size,
7163                                       &num_errors, &num_warnings);
7164}
7165
7166enum dbg_status qed_print_idle_chk_results(struct ecore_hwfn *p_hwfn,
7167                                           u32 *dump_buf,
7168                                           u32 num_dumped_dwords,
7169                                           char *results_buf,
7170                                           u32 *num_errors,
7171                                           u32 *num_warnings)
7172{
7173        u32 parsed_buf_size;
7174
7175        return qed_parse_idle_chk_dump(p_hwfn,
7176                                       dump_buf,
7177                                       num_dumped_dwords,
7178                                       results_buf,
7179                                       &parsed_buf_size,
7180                                       num_errors, num_warnings);
7181}
7182
7183void qed_dbg_mcp_trace_set_meta_data(struct ecore_hwfn *p_hwfn,
7184                                     const u32 *meta_buf)
7185{
7186        struct dbg_tools_user_data *dev_user_data =
7187                qed_dbg_get_user_data(p_hwfn);
7188
7189        dev_user_data->mcp_trace_user_meta_buf = meta_buf;
7190}
7191
7192enum dbg_status
7193qed_get_mcp_trace_results_buf_size(struct ecore_hwfn *p_hwfn,
7194                                   u32 *dump_buf,
7195                                   __rte_unused u32 num_dumped_dwords,
7196                                   u32 *results_buf_size)
7197{
7198        return qed_parse_mcp_trace_dump(p_hwfn,
7199                                        dump_buf, NULL, results_buf_size, true);
7200}
7201
7202enum dbg_status qed_print_mcp_trace_results(struct ecore_hwfn *p_hwfn,
7203                                            u32 *dump_buf,
7204                                            __rte_unused u32 num_dumped_dwords,
7205                                            char *results_buf)
7206{
7207        u32 parsed_buf_size;
7208
7209        return qed_parse_mcp_trace_dump(p_hwfn,
7210                                        dump_buf,
7211                                        results_buf, &parsed_buf_size, true);
7212}
7213
7214enum dbg_status qed_print_mcp_trace_results_cont(struct ecore_hwfn *p_hwfn,
7215                                                 u32 *dump_buf,
7216                                                 char *results_buf)
7217{
7218        u32 parsed_buf_size;
7219
7220        return qed_parse_mcp_trace_dump(p_hwfn, dump_buf, results_buf,
7221                                        &parsed_buf_size, false);
7222}
7223
7224enum dbg_status qed_print_mcp_trace_line(struct ecore_hwfn *p_hwfn,
7225                                         u8 *dump_buf,
7226                                         u32 num_dumped_bytes,
7227                                         char *results_buf)
7228{
7229        u32 parsed_results_bytes;
7230
7231        return qed_parse_mcp_trace_buf(p_hwfn,
7232                                       dump_buf,
7233                                       num_dumped_bytes,
7234                                       0,
7235                                       num_dumped_bytes,
7236                                       results_buf, &parsed_results_bytes);
7237}
7238
7239/* Frees the specified MCP Trace meta data */
7240void qed_mcp_trace_free_meta_data(struct ecore_hwfn *p_hwfn)
7241{
7242        struct dbg_tools_user_data *dev_user_data;
7243        struct mcp_trace_meta *meta;
7244        u32 i;
7245
7246        dev_user_data = qed_dbg_get_user_data(p_hwfn);
7247        meta = &dev_user_data->mcp_trace_meta;
7248        if (!meta->is_allocated)
7249                return;
7250
7251        /* Release modules */
7252        if (meta->modules) {
7253                for (i = 0; i < meta->modules_num; i++)
7254                        OSAL_FREE(p_hwfn, meta->modules[i]);
7255                OSAL_FREE(p_hwfn, meta->modules);
7256        }
7257
7258        /* Release formats */
7259        if (meta->formats) {
7260                for (i = 0; i < meta->formats_num; i++)
7261                        OSAL_FREE(p_hwfn, meta->formats[i].format_str);
7262                OSAL_FREE(p_hwfn, meta->formats);
7263        }
7264
7265        meta->is_allocated = false;
7266}
7267
7268enum dbg_status
7269qed_get_reg_fifo_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
7270                                  u32 *dump_buf,
7271                                  __rte_unused u32 num_dumped_dwords,
7272                                  u32 *results_buf_size)
7273{
7274        return qed_parse_reg_fifo_dump(dump_buf, NULL, results_buf_size);
7275}
7276
7277enum dbg_status
7278qed_print_reg_fifo_results(__rte_unused struct ecore_hwfn *p_hwfn,
7279                           u32 *dump_buf,
7280                           __rte_unused u32 num_dumped_dwords,
7281                           char *results_buf)
7282{
7283        u32 parsed_buf_size;
7284
7285        return qed_parse_reg_fifo_dump(dump_buf, results_buf, &parsed_buf_size);
7286}
7287
7288enum dbg_status
7289qed_get_igu_fifo_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
7290                                  u32 *dump_buf,
7291                                  __rte_unused u32 num_dumped_dwords,
7292                                  u32 *results_buf_size)
7293{
7294        return qed_parse_igu_fifo_dump(dump_buf, NULL, results_buf_size);
7295}
7296
7297enum dbg_status
7298qed_print_igu_fifo_results(__rte_unused struct ecore_hwfn *p_hwfn,
7299                           u32 *dump_buf,
7300                           __rte_unused u32 num_dumped_dwords,
7301                           char *results_buf)
7302{
7303        u32 parsed_buf_size;
7304
7305        return qed_parse_igu_fifo_dump(dump_buf, results_buf, &parsed_buf_size);
7306}
7307
7308enum dbg_status
7309qed_get_protection_override_results_buf_size(__rte_unused
7310                                             struct ecore_hwfn *p_hwfn,
7311                                             u32 *dump_buf,
7312                                             __rte_unused u32 num_dumped_dwords,
7313                                             u32 *results_buf_size)
7314{
7315        return qed_parse_protection_override_dump(dump_buf,
7316                                                  NULL, results_buf_size);
7317}
7318
7319enum dbg_status
7320qed_print_protection_override_results(__rte_unused struct ecore_hwfn *p_hwfn,
7321                                      u32 *dump_buf,
7322                                      __rte_unused u32 num_dumped_dwords,
7323                                      char *results_buf)
7324{
7325        u32 parsed_buf_size;
7326
7327        return qed_parse_protection_override_dump(dump_buf,
7328                                                  results_buf,
7329                                                  &parsed_buf_size);
7330}
7331
7332enum dbg_status
7333qed_get_fw_asserts_results_buf_size(__rte_unused struct ecore_hwfn *p_hwfn,
7334                                    u32 *dump_buf,
7335                                    __rte_unused u32 num_dumped_dwords,
7336                                    u32 *results_buf_size)
7337{
7338        return qed_parse_fw_asserts_dump(dump_buf, NULL, results_buf_size);
7339}
7340
7341enum dbg_status
7342qed_print_fw_asserts_results(__rte_unused struct ecore_hwfn *p_hwfn,
7343                             u32 *dump_buf,
7344                             __rte_unused u32 num_dumped_dwords,
7345                             char *results_buf)
7346{
7347        u32 parsed_buf_size;
7348
7349        return qed_parse_fw_asserts_dump(dump_buf,
7350                                         results_buf, &parsed_buf_size);
7351}
7352
7353enum dbg_status qed_dbg_parse_attn(struct ecore_hwfn *p_hwfn,
7354                                   struct dbg_attn_block_result *results)
7355{
7356        const u32 *block_attn_name_offsets;
7357        const char *attn_name_base;
7358        const char *block_name;
7359        enum dbg_attn_type attn_type;
7360        u8 num_regs, i, j;
7361
7362        num_regs = GET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_NUM_REGS);
7363        attn_type = GET_FIELD(results->data, DBG_ATTN_BLOCK_RESULT_ATTN_TYPE);
7364        block_name = qed_dbg_get_block_name(p_hwfn, results->block_id);
7365        if (!block_name)
7366                return DBG_STATUS_INVALID_ARGS;
7367
7368        if (!p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_INDEXES].ptr ||
7369            !p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_NAME_OFFSETS].ptr ||
7370            !p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr)
7371                return DBG_STATUS_DBG_ARRAY_NOT_SET;
7372
7373        block_attn_name_offsets =
7374            (u32 *)p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_NAME_OFFSETS].ptr +
7375            results->names_offset;
7376
7377        attn_name_base = p_hwfn->dbg_arrays[BIN_BUF_DBG_PARSING_STRINGS].ptr;
7378
7379        /* Go over registers with a non-zero attention status */
7380        for (i = 0; i < num_regs; i++) {
7381                struct dbg_attn_bit_mapping *bit_mapping;
7382                struct dbg_attn_reg_result *reg_result;
7383                u8 num_reg_attn, bit_idx = 0;
7384
7385                reg_result = &results->reg_results[i];
7386                num_reg_attn = GET_FIELD(reg_result->data,
7387                                         DBG_ATTN_REG_RESULT_NUM_REG_ATTN);
7388                bit_mapping = (struct dbg_attn_bit_mapping *)
7389                    p_hwfn->dbg_arrays[BIN_BUF_DBG_ATTN_INDEXES].ptr +
7390                    reg_result->block_attn_offset;
7391
7392                /* Go over attention status bits */
7393                for (j = 0; j < num_reg_attn; j++, bit_idx++) {
7394                        u16 attn_idx_val = GET_FIELD(bit_mapping[j].data,
7395                                                     DBG_ATTN_BIT_MAPPING_VAL);
7396                        const char *attn_name, *attn_type_str, *masked_str;
7397                        u32 attn_name_offset;
7398                        u32 sts_addr;
7399
7400                        /* Check if bit mask should be advanced (due to unused
7401                         * bits).
7402                         */
7403                        if (GET_FIELD(bit_mapping[j].data,
7404                                      DBG_ATTN_BIT_MAPPING_IS_UNUSED_BIT_CNT)) {
7405                                bit_idx += (u8)attn_idx_val;
7406                                continue;
7407                        }
7408
7409                        /* Check current bit index */
7410                        if (!(reg_result->sts_val & OSAL_BIT(bit_idx)))
7411                                continue;
7412
7413                        /* An attention bit with value=1 was found
7414                         * Find attention name
7415                         */
7416                        attn_name_offset =
7417                                block_attn_name_offsets[attn_idx_val];
7418                        attn_name = attn_name_base + attn_name_offset;
7419                        attn_type_str =
7420                                (attn_type ==
7421                                 ATTN_TYPE_INTERRUPT ? "Interrupt" :
7422                                 "Parity");
7423                        masked_str = reg_result->mask_val & OSAL_BIT(bit_idx) ?
7424                                     " [masked]" : "";
7425                        sts_addr = GET_FIELD(reg_result->data,
7426                                             DBG_ATTN_REG_RESULT_STS_ADDRESS);
7427                        DP_NOTICE(p_hwfn, false,
7428                                  "%s (%s) : %s [address 0x%08x, bit %d]%s\n",
7429                                  block_name, attn_type_str, attn_name,
7430                                  sts_addr * 4, bit_idx, masked_str);
7431                }
7432        }
7433
7434        return DBG_STATUS_OK;
7435}
7436
7437/* Wrapper for unifying the idle_chk and mcp_trace api */
7438static enum dbg_status
7439qed_print_idle_chk_results_wrapper(struct ecore_hwfn *p_hwfn,
7440                                   u32 *dump_buf,
7441                                   u32 num_dumped_dwords,
7442                                   char *results_buf)
7443{
7444        u32 num_errors, num_warnnings;
7445
7446        return qed_print_idle_chk_results(p_hwfn, dump_buf, num_dumped_dwords,
7447                                          results_buf, &num_errors,
7448                                          &num_warnnings);
7449}
7450
7451/* Feature meta data lookup table */
7452static struct {
7453        const char *name;
7454        enum dbg_status (*get_size)(struct ecore_hwfn *p_hwfn,
7455                                    struct ecore_ptt *p_ptt, u32 *size);
7456        enum dbg_status (*perform_dump)(struct ecore_hwfn *p_hwfn,
7457                                        struct ecore_ptt *p_ptt, u32 *dump_buf,
7458                                        u32 buf_size, u32 *dumped_dwords);
7459        enum dbg_status (*print_results)(struct ecore_hwfn *p_hwfn,
7460                                         u32 *dump_buf, u32 num_dumped_dwords,
7461                                         char *results_buf);
7462        enum dbg_status (*results_buf_size)(struct ecore_hwfn *p_hwfn,
7463                                            u32 *dump_buf,
7464                                            u32 num_dumped_dwords,
7465                                            u32 *results_buf_size);
7466} qed_features_lookup[] = {
7467        {
7468        "grc", qed_dbg_grc_get_dump_buf_size,
7469                    qed_dbg_grc_dump, NULL, NULL}, {
7470        "idle_chk",
7471                    qed_dbg_idle_chk_get_dump_buf_size,
7472                    qed_dbg_idle_chk_dump,
7473                    qed_print_idle_chk_results_wrapper,
7474                    qed_get_idle_chk_results_buf_size}, {
7475        "mcp_trace",
7476                    qed_dbg_mcp_trace_get_dump_buf_size,
7477                    qed_dbg_mcp_trace_dump, qed_print_mcp_trace_results,
7478                    qed_get_mcp_trace_results_buf_size}, {
7479        "reg_fifo",
7480                    qed_dbg_reg_fifo_get_dump_buf_size,
7481                    qed_dbg_reg_fifo_dump, qed_print_reg_fifo_results,
7482                    qed_get_reg_fifo_results_buf_size}, {
7483        "igu_fifo",
7484                    qed_dbg_igu_fifo_get_dump_buf_size,
7485                    qed_dbg_igu_fifo_dump, qed_print_igu_fifo_results,
7486                    qed_get_igu_fifo_results_buf_size}, {
7487        "protection_override",
7488                    qed_dbg_protection_override_get_dump_buf_size,
7489                    qed_dbg_protection_override_dump,
7490                    qed_print_protection_override_results,
7491                    qed_get_protection_override_results_buf_size}, {
7492        "fw_asserts",
7493                    qed_dbg_fw_asserts_get_dump_buf_size,
7494                    qed_dbg_fw_asserts_dump,
7495                    qed_print_fw_asserts_results,
7496                    qed_get_fw_asserts_results_buf_size}, {
7497        "ilt",
7498                    qed_dbg_ilt_get_dump_buf_size,
7499                    qed_dbg_ilt_dump, NULL, NULL},};
7500
7501#define QED_RESULTS_BUF_MIN_SIZE 16
7502/* Generic function for decoding debug feature info */
7503static enum dbg_status format_feature(struct ecore_hwfn *p_hwfn,
7504                                      enum ecore_dbg_features feature_idx)
7505{
7506        struct ecore_dbg_feature *feature =
7507            &p_hwfn->p_dev->dbg_params.features[feature_idx];
7508        u32 text_size_bytes, null_char_pos, i;
7509        enum dbg_status rc;
7510        char *text_buf;
7511
7512        /* Check if feature supports formatting capability */
7513        if (!qed_features_lookup[feature_idx].results_buf_size)
7514                return DBG_STATUS_OK;
7515
7516        /* Obtain size of formatted output */
7517        rc = qed_features_lookup[feature_idx].results_buf_size(p_hwfn,
7518                                                (u32 *)feature->dump_buf,
7519                                                feature->dumped_dwords,
7520                                                &text_size_bytes);
7521        if (rc != DBG_STATUS_OK)
7522                return rc;
7523
7524        /* Make sure that the allocated size is a multiple of dword (4 bytes) */
7525        null_char_pos = text_size_bytes - 1;
7526        text_size_bytes = (text_size_bytes + 3) & ~0x3;
7527
7528        if (text_size_bytes < QED_RESULTS_BUF_MIN_SIZE) {
7529                DP_NOTICE(p_hwfn->p_dev, false,
7530                          "formatted size of feature was too small %d. Aborting\n",
7531                          text_size_bytes);
7532                return DBG_STATUS_INVALID_ARGS;
7533        }
7534
7535        /* Allocate temp text buf */
7536        text_buf = OSAL_VZALLOC(p_hwfn, text_size_bytes);
7537        if (!text_buf) {
7538                DP_NOTICE(p_hwfn->p_dev, false,
7539                          "failed to allocate text buffer. Aborting\n");
7540                return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
7541        }
7542
7543        /* Decode feature opcodes to string on temp buf */
7544        rc = qed_features_lookup[feature_idx].print_results(p_hwfn,
7545                                                (u32 *)feature->dump_buf,
7546                                                feature->dumped_dwords,
7547                                                text_buf);
7548        if (rc != DBG_STATUS_OK) {
7549                OSAL_VFREE(p_hwfn, text_buf);
7550                return rc;
7551        }
7552
7553        /* Replace the original null character with a '\n' character.
7554         * The bytes that were added as a result of the dword alignment are also
7555         * padded with '\n' characters.
7556         */
7557        for (i = null_char_pos; i < text_size_bytes; i++)
7558                text_buf[i] = '\n';
7559
7560
7561        /* Free the old dump_buf and point the dump_buf to the newly allocagted
7562         * and formatted text buffer.
7563         */
7564        OSAL_VFREE(p_hwfn, feature->dump_buf);
7565        feature->dump_buf = (u8 *)text_buf;
7566        feature->buf_size = text_size_bytes;
7567        feature->dumped_dwords = text_size_bytes / 4;
7568        return rc;
7569}
7570
7571#define MAX_DBG_FEATURE_SIZE_DWORDS     0x3FFFFFFF
7572
7573/* Generic function for performing the dump of a debug feature. */
7574static enum dbg_status qed_dbg_dump(struct ecore_hwfn *p_hwfn,
7575                                    struct ecore_ptt *p_ptt,
7576                                    enum ecore_dbg_features feature_idx)
7577{
7578        struct ecore_dbg_feature *feature =
7579            &p_hwfn->p_dev->dbg_params.features[feature_idx];
7580        u32 buf_size_dwords;
7581        enum dbg_status rc;
7582
7583        DP_NOTICE(p_hwfn->p_dev, false, "Collecting a debug feature [\"%s\"]\n",
7584                  qed_features_lookup[feature_idx].name);
7585
7586        /* Dump_buf was already allocated need to free (this can happen if dump
7587         * was called but file was never read).
7588         * We can't use the buffer as is since size may have changed.
7589         */
7590        if (feature->dump_buf) {
7591                OSAL_VFREE(p_hwfn, feature->dump_buf);
7592                feature->dump_buf = NULL;
7593        }
7594
7595        /* Get buffer size from hsi, allocate accordingly, and perform the
7596         * dump.
7597         */
7598        rc = qed_features_lookup[feature_idx].get_size(p_hwfn, p_ptt,
7599                                                       &buf_size_dwords);
7600        if (rc != DBG_STATUS_OK && rc != DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
7601                return rc;
7602
7603        if (buf_size_dwords > MAX_DBG_FEATURE_SIZE_DWORDS) {
7604                feature->buf_size = 0;
7605                DP_NOTICE(p_hwfn->p_dev, false,
7606                          "Debug feature [\"%s\"] size (0x%x dwords) exceeds maximum size (0x%x dwords)\n",
7607                          qed_features_lookup[feature_idx].name,
7608                          buf_size_dwords, MAX_DBG_FEATURE_SIZE_DWORDS);
7609
7610                return DBG_STATUS_OK;
7611        }
7612
7613        feature->buf_size = buf_size_dwords * sizeof(u32);
7614        feature->dump_buf = OSAL_ZALLOC(p_hwfn, GFP_KERNEL, feature->buf_size);
7615        if (!feature->dump_buf)
7616                return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
7617
7618        rc = qed_features_lookup[feature_idx].perform_dump(p_hwfn, p_ptt,
7619                                        (u32 *)feature->dump_buf,
7620                                        feature->buf_size / sizeof(u32),
7621                                        &feature->dumped_dwords);
7622
7623        /* If mcp is stuck we get DBG_STATUS_NVRAM_GET_IMAGE_FAILED error.
7624         * In this case the buffer holds valid binary data, but we won't able
7625         * to parse it (since parsing relies on data in NVRAM which is only
7626         * accessible when MFW is responsive). skip the formatting but return
7627         * success so that binary data is provided.
7628         */
7629        if (rc == DBG_STATUS_NVRAM_GET_IMAGE_FAILED)
7630                return DBG_STATUS_OK;
7631
7632        if (rc != DBG_STATUS_OK)
7633                return rc;
7634
7635        /* Format output */
7636        rc = format_feature(p_hwfn, feature_idx);
7637        return rc;
7638}
7639
7640int qed_dbg_grc(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
7641{
7642        return qed_dbg_feature(edev, buffer, DBG_FEATURE_GRC, num_dumped_bytes);
7643}
7644
7645int qed_dbg_grc_size(struct ecore_dev *edev)
7646{
7647        return qed_dbg_feature_size(edev, DBG_FEATURE_GRC);
7648}
7649
7650int
7651qed_dbg_idle_chk(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
7652{
7653        return qed_dbg_feature(edev, buffer, DBG_FEATURE_IDLE_CHK,
7654                               num_dumped_bytes);
7655}
7656
7657int qed_dbg_idle_chk_size(struct ecore_dev *edev)
7658{
7659        return qed_dbg_feature_size(edev, DBG_FEATURE_IDLE_CHK);
7660}
7661
7662int
7663qed_dbg_reg_fifo(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
7664{
7665        return qed_dbg_feature(edev, buffer, DBG_FEATURE_REG_FIFO,
7666                               num_dumped_bytes);
7667}
7668
7669int qed_dbg_reg_fifo_size(struct ecore_dev *edev)
7670{
7671        return qed_dbg_feature_size(edev, DBG_FEATURE_REG_FIFO);
7672}
7673
7674int
7675qed_dbg_igu_fifo(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
7676{
7677        return qed_dbg_feature(edev, buffer, DBG_FEATURE_IGU_FIFO,
7678                               num_dumped_bytes);
7679}
7680
7681int qed_dbg_igu_fifo_size(struct ecore_dev *edev)
7682{
7683        return qed_dbg_feature_size(edev, DBG_FEATURE_IGU_FIFO);
7684}
7685
7686static int qed_dbg_nvm_image_length(struct ecore_hwfn *p_hwfn,
7687                                    enum ecore_nvm_images image_id, u32 *length)
7688{
7689        struct ecore_nvm_image_att image_att;
7690        int rc;
7691
7692        *length = 0;
7693        rc = ecore_mcp_get_nvm_image_att(p_hwfn, image_id, &image_att);
7694        if (rc)
7695                return rc;
7696
7697        *length = image_att.length;
7698
7699        return rc;
7700}
7701
7702int qed_dbg_protection_override(struct ecore_dev *edev, void *buffer,
7703                                u32 *num_dumped_bytes)
7704{
7705        return qed_dbg_feature(edev, buffer, DBG_FEATURE_PROTECTION_OVERRIDE,
7706                               num_dumped_bytes);
7707}
7708
7709int qed_dbg_protection_override_size(struct ecore_dev *edev)
7710{
7711        return qed_dbg_feature_size(edev, DBG_FEATURE_PROTECTION_OVERRIDE);
7712}
7713
7714int qed_dbg_fw_asserts(struct ecore_dev *edev, void *buffer,
7715                       u32 *num_dumped_bytes)
7716{
7717        return qed_dbg_feature(edev, buffer, DBG_FEATURE_FW_ASSERTS,
7718                               num_dumped_bytes);
7719}
7720
7721int qed_dbg_fw_asserts_size(struct ecore_dev *edev)
7722{
7723        return qed_dbg_feature_size(edev, DBG_FEATURE_FW_ASSERTS);
7724}
7725
7726int qed_dbg_ilt(struct ecore_dev *edev, void *buffer, u32 *num_dumped_bytes)
7727{
7728        return qed_dbg_feature(edev, buffer, DBG_FEATURE_ILT, num_dumped_bytes);
7729}
7730
7731int qed_dbg_ilt_size(struct ecore_dev *edev)
7732{
7733        return qed_dbg_feature_size(edev, DBG_FEATURE_ILT);
7734}
7735
7736int qed_dbg_mcp_trace(struct ecore_dev *edev, void *buffer,
7737                      u32 *num_dumped_bytes)
7738{
7739        return qed_dbg_feature(edev, buffer, DBG_FEATURE_MCP_TRACE,
7740                               num_dumped_bytes);
7741}
7742
7743int qed_dbg_mcp_trace_size(struct ecore_dev *edev)
7744{
7745        return qed_dbg_feature_size(edev, DBG_FEATURE_MCP_TRACE);
7746}
7747
7748/* Defines the amount of bytes allocated for recording the length of debug
7749 * feature buffer.
7750 */
7751#define REGDUMP_HEADER_SIZE                     sizeof(u32)
7752#define REGDUMP_HEADER_SIZE_SHIFT               0
7753#define REGDUMP_HEADER_SIZE_MASK                0xffffff
7754#define REGDUMP_HEADER_FEATURE_SHIFT            24
7755#define REGDUMP_HEADER_FEATURE_MASK             0x3f
7756#define REGDUMP_HEADER_OMIT_ENGINE_SHIFT        30
7757#define REGDUMP_HEADER_OMIT_ENGINE_MASK         0x1
7758#define REGDUMP_HEADER_ENGINE_SHIFT             31
7759#define REGDUMP_HEADER_ENGINE_MASK              0x1
7760#define REGDUMP_MAX_SIZE                        0x1000000
7761#define ILT_DUMP_MAX_SIZE                       (1024 * 1024 * 15)
7762
7763enum debug_print_features {
7764        OLD_MODE = 0,
7765        IDLE_CHK = 1,
7766        GRC_DUMP = 2,
7767        MCP_TRACE = 3,
7768        REG_FIFO = 4,
7769        PROTECTION_OVERRIDE = 5,
7770        IGU_FIFO = 6,
7771        PHY = 7,
7772        FW_ASSERTS = 8,
7773        NVM_CFG1 = 9,
7774        DEFAULT_CFG = 10,
7775        NVM_META = 11,
7776        MDUMP = 12,
7777        ILT_DUMP = 13,
7778};
7779
7780static u32 qed_calc_regdump_header(struct ecore_dev *edev,
7781                                   enum debug_print_features feature,
7782                                   int engine, u32 feature_size, u8 omit_engine)
7783{
7784        u32 res = 0;
7785
7786        SET_FIELD(res, REGDUMP_HEADER_SIZE, feature_size);
7787        if (res != feature_size)
7788                DP_NOTICE(edev, false,
7789                          "Feature %d is too large (size 0x%x) and will corrupt the dump\n",
7790                          feature, feature_size);
7791
7792        SET_FIELD(res, REGDUMP_HEADER_FEATURE, feature);
7793        SET_FIELD(res, REGDUMP_HEADER_OMIT_ENGINE, omit_engine);
7794        SET_FIELD(res, REGDUMP_HEADER_ENGINE, engine);
7795
7796        return res;
7797}
7798
7799int qed_dbg_all_data(struct ecore_dev *edev, void *buffer)
7800{
7801        u8 cur_engine, omit_engine = 0, org_engine;
7802        struct ecore_hwfn *p_hwfn =
7803                &edev->hwfns[edev->dbg_params.engine_for_debug];
7804        struct dbg_tools_data *dev_data = &p_hwfn->dbg_info;
7805        int grc_params[MAX_DBG_GRC_PARAMS], i;
7806        u32 offset = 0, feature_size;
7807        int rc;
7808
7809        for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
7810                grc_params[i] = dev_data->grc.param_val[i];
7811
7812        if (!ECORE_IS_CMT(edev))
7813                omit_engine = 1;
7814
7815        OSAL_MUTEX_ACQUIRE(&edev->dbg_lock);
7816
7817        org_engine = qed_get_debug_engine(edev);
7818        for (cur_engine = 0; cur_engine < edev->num_hwfns; cur_engine++) {
7819                /* Collect idle_chks and grcDump for each hw function */
7820                DP_VERBOSE(edev, ECORE_MSG_DEBUG,
7821                           "obtaining idle_chk and grcdump for current engine\n");
7822                qed_set_debug_engine(edev, cur_engine);
7823
7824                /* First idle_chk */
7825                rc = qed_dbg_idle_chk(edev, (u8 *)buffer + offset +
7826                                      REGDUMP_HEADER_SIZE, &feature_size);
7827                if (!rc) {
7828                        *(u32 *)((u8 *)buffer + offset) =
7829                            qed_calc_regdump_header(edev, IDLE_CHK, cur_engine,
7830                                                    feature_size, omit_engine);
7831                        offset += (feature_size + REGDUMP_HEADER_SIZE);
7832                } else {
7833                        DP_ERR(edev, "qed_dbg_idle_chk failed. rc = %d\n", rc);
7834                }
7835
7836                /* Second idle_chk */
7837                rc = qed_dbg_idle_chk(edev, (u8 *)buffer + offset +
7838                                      REGDUMP_HEADER_SIZE, &feature_size);
7839                if (!rc) {
7840                        *(u32 *)((u8 *)buffer + offset) =
7841                            qed_calc_regdump_header(edev, IDLE_CHK, cur_engine,
7842                                                    feature_size, omit_engine);
7843                        offset += (feature_size + REGDUMP_HEADER_SIZE);
7844                } else {
7845                        DP_ERR(edev, "qed_dbg_idle_chk failed. rc = %d\n", rc);
7846                }
7847
7848                /* reg_fifo dump */
7849                rc = qed_dbg_reg_fifo(edev, (u8 *)buffer + offset +
7850                                      REGDUMP_HEADER_SIZE, &feature_size);
7851                if (!rc) {
7852                        *(u32 *)((u8 *)buffer + offset) =
7853                            qed_calc_regdump_header(edev, REG_FIFO, cur_engine,
7854                                                    feature_size, omit_engine);
7855                        offset += (feature_size + REGDUMP_HEADER_SIZE);
7856                } else {
7857                        DP_ERR(edev, "qed_dbg_reg_fifo failed. rc = %d\n", rc);
7858                }
7859
7860                /* igu_fifo dump */
7861                rc = qed_dbg_igu_fifo(edev, (u8 *)buffer + offset +
7862                                      REGDUMP_HEADER_SIZE, &feature_size);
7863                if (!rc) {
7864                        *(u32 *)((u8 *)buffer + offset) =
7865                            qed_calc_regdump_header(edev, IGU_FIFO, cur_engine,
7866                                                    feature_size, omit_engine);
7867                        offset += (feature_size + REGDUMP_HEADER_SIZE);
7868                } else {
7869                        DP_ERR(edev, "qed_dbg_igu_fifo failed. rc = %d", rc);
7870                }
7871
7872                /* protection_override dump */
7873                rc = qed_dbg_protection_override(edev, (u8 *)buffer + offset +
7874                                                 REGDUMP_HEADER_SIZE,
7875                                                 &feature_size);
7876                if (!rc) {
7877                        *(u32 *)((u8 *)buffer + offset) =
7878                            qed_calc_regdump_header(edev, PROTECTION_OVERRIDE,
7879                                                    cur_engine,
7880                                                    feature_size, omit_engine);
7881                        offset += (feature_size + REGDUMP_HEADER_SIZE);
7882                } else {
7883                        DP_ERR(edev,
7884                               "qed_dbg_protection_override failed. rc = %d\n",
7885                               rc);
7886                }
7887
7888                /* fw_asserts dump */
7889                rc = qed_dbg_fw_asserts(edev, (u8 *)buffer + offset +
7890                                        REGDUMP_HEADER_SIZE, &feature_size);
7891                if (!rc) {
7892                        *(u32 *)((u8 *)buffer + offset) =
7893                            qed_calc_regdump_header(edev, FW_ASSERTS,
7894                                                    cur_engine, feature_size,
7895                                                    omit_engine);
7896                        offset += (feature_size + REGDUMP_HEADER_SIZE);
7897                } else {
7898                        DP_ERR(edev, "qed_dbg_fw_asserts failed. rc = %d\n",
7899                               rc);
7900                }
7901
7902                /* GRC dump - must be last because when mcp stuck it will
7903                 * clutter idle_chk, reg_fifo, ...
7904                 */
7905                for (i = 0; i < MAX_DBG_GRC_PARAMS; i++)
7906                        dev_data->grc.param_val[i] = grc_params[i];
7907
7908                rc = qed_dbg_grc(edev, (u8 *)buffer + offset +
7909                                 REGDUMP_HEADER_SIZE, &feature_size);
7910                if (!rc) {
7911                        *(u32 *)((u8 *)buffer + offset) =
7912                            qed_calc_regdump_header(edev, GRC_DUMP,
7913                                                    cur_engine,
7914                                                    feature_size, omit_engine);
7915                        offset += (feature_size + REGDUMP_HEADER_SIZE);
7916                } else {
7917                        DP_ERR(edev, "qed_dbg_grc failed. rc = %d", rc);
7918                }
7919        }
7920
7921        qed_set_debug_engine(edev, org_engine);
7922
7923        /* mcp_trace */
7924        rc = qed_dbg_mcp_trace(edev, (u8 *)buffer + offset +
7925                               REGDUMP_HEADER_SIZE, &feature_size);
7926        if (!rc) {
7927                *(u32 *)((u8 *)buffer + offset) =
7928                    qed_calc_regdump_header(edev, MCP_TRACE, cur_engine,
7929                                            feature_size, omit_engine);
7930                offset += (feature_size + REGDUMP_HEADER_SIZE);
7931        } else {
7932                DP_ERR(edev, "qed_dbg_mcp_trace failed. rc = %d\n", rc);
7933        }
7934
7935        OSAL_MUTEX_RELEASE(&edev->dbg_lock);
7936
7937        return 0;
7938}
7939
7940int qed_dbg_all_data_size(struct ecore_dev *edev)
7941{
7942        struct ecore_hwfn *p_hwfn =
7943                &edev->hwfns[edev->dbg_params.engine_for_debug];
7944        u32 regs_len = 0, image_len = 0, ilt_len = 0, total_ilt_len = 0;
7945        u8 cur_engine, org_engine;
7946
7947        edev->disable_ilt_dump = false;
7948        org_engine = qed_get_debug_engine(edev);
7949        for (cur_engine = 0; cur_engine < edev->num_hwfns; cur_engine++) {
7950                /* Engine specific */
7951                DP_VERBOSE(edev, ECORE_MSG_DEBUG,
7952                           "calculating idle_chk and grcdump register length for current engine\n");
7953                qed_set_debug_engine(edev, cur_engine);
7954                regs_len += REGDUMP_HEADER_SIZE + qed_dbg_idle_chk_size(edev) +
7955                            REGDUMP_HEADER_SIZE + qed_dbg_idle_chk_size(edev) +
7956                            REGDUMP_HEADER_SIZE + qed_dbg_grc_size(edev) +
7957                            REGDUMP_HEADER_SIZE + qed_dbg_reg_fifo_size(edev) +
7958                            REGDUMP_HEADER_SIZE + qed_dbg_igu_fifo_size(edev) +
7959                            REGDUMP_HEADER_SIZE +
7960                            qed_dbg_protection_override_size(edev) +
7961                            REGDUMP_HEADER_SIZE + qed_dbg_fw_asserts_size(edev);
7962
7963                ilt_len = REGDUMP_HEADER_SIZE + qed_dbg_ilt_size(edev);
7964                if (ilt_len < ILT_DUMP_MAX_SIZE) {
7965                        total_ilt_len += ilt_len;
7966                        regs_len += ilt_len;
7967                }
7968        }
7969
7970        qed_set_debug_engine(edev, org_engine);
7971
7972        /* Engine common */
7973        regs_len += REGDUMP_HEADER_SIZE + qed_dbg_mcp_trace_size(edev);
7974        qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_NVM_CFG1, &image_len);
7975        if (image_len)
7976                regs_len += REGDUMP_HEADER_SIZE + image_len;
7977        qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_DEFAULT_CFG,
7978                                 &image_len);
7979        if (image_len)
7980                regs_len += REGDUMP_HEADER_SIZE + image_len;
7981        qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_NVM_META, &image_len);
7982        if (image_len)
7983                regs_len += REGDUMP_HEADER_SIZE + image_len;
7984        qed_dbg_nvm_image_length(p_hwfn, ECORE_NVM_IMAGE_MDUMP, &image_len);
7985        if (image_len)
7986                regs_len += REGDUMP_HEADER_SIZE + image_len;
7987
7988        if (regs_len > REGDUMP_MAX_SIZE) {
7989                DP_VERBOSE(edev, ECORE_MSG_DEBUG,
7990                           "Dump exceeds max size 0x%x, disable ILT dump\n",
7991                           REGDUMP_MAX_SIZE);
7992                edev->disable_ilt_dump = true;
7993                regs_len -= total_ilt_len;
7994        }
7995
7996        return regs_len;
7997}
7998
7999int qed_dbg_feature(struct ecore_dev *edev, void *buffer,
8000                    enum ecore_dbg_features feature, u32 *num_dumped_bytes)
8001{
8002        struct ecore_hwfn *p_hwfn =
8003                &edev->hwfns[edev->dbg_params.engine_for_debug];
8004        struct ecore_dbg_feature *qed_feature =
8005                &edev->dbg_params.features[feature];
8006        enum dbg_status dbg_rc;
8007        struct ecore_ptt *p_ptt;
8008        int rc = 0;
8009
8010        /* Acquire ptt */
8011        p_ptt = ecore_ptt_acquire(p_hwfn);
8012        if (!p_ptt)
8013                return -EINVAL;
8014
8015        /* Get dump */
8016        dbg_rc = qed_dbg_dump(p_hwfn, p_ptt, feature);
8017        if (dbg_rc != DBG_STATUS_OK) {
8018                DP_VERBOSE(edev, ECORE_MSG_DEBUG, "%s\n",
8019                           qed_dbg_get_status_str(dbg_rc));
8020                *num_dumped_bytes = 0;
8021                rc = -EINVAL;
8022                goto out;
8023        }
8024
8025        DP_VERBOSE(edev, ECORE_MSG_DEBUG,
8026                   "copying debug feature to external buffer\n");
8027        memcpy(buffer, qed_feature->dump_buf, qed_feature->buf_size);
8028        *num_dumped_bytes = edev->dbg_params.features[feature].dumped_dwords *
8029                            4;
8030
8031out:
8032        ecore_ptt_release(p_hwfn, p_ptt);
8033        return rc;
8034}
8035
8036int
8037qed_dbg_feature_size(struct ecore_dev *edev, enum ecore_dbg_features feature)
8038{
8039        struct ecore_hwfn *p_hwfn =
8040                &edev->hwfns[edev->dbg_params.engine_for_debug];
8041        struct ecore_dbg_feature *qed_feature = &edev->dbg_features[feature];
8042        struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
8043        u32 buf_size_dwords;
8044        enum dbg_status rc;
8045
8046        if (!p_ptt)
8047                return -EINVAL;
8048
8049        rc = qed_features_lookup[feature].get_size(p_hwfn, p_ptt,
8050                                                   &buf_size_dwords);
8051        if (rc != DBG_STATUS_OK)
8052                buf_size_dwords = 0;
8053
8054        /* Feature will not be dumped if it exceeds maximum size */
8055        if (buf_size_dwords > MAX_DBG_FEATURE_SIZE_DWORDS)
8056                buf_size_dwords = 0;
8057
8058        ecore_ptt_release(p_hwfn, p_ptt);
8059        qed_feature->buf_size = buf_size_dwords * sizeof(u32);
8060        return qed_feature->buf_size;
8061}
8062
8063u8 qed_get_debug_engine(struct ecore_dev *edev)
8064{
8065        return edev->dbg_params.engine_for_debug;
8066}
8067
8068void qed_set_debug_engine(struct ecore_dev *edev, int engine_number)
8069{
8070        DP_VERBOSE(edev, ECORE_MSG_DEBUG, "set debug engine to %d\n",
8071                   engine_number);
8072        edev->dbg_params.engine_for_debug = engine_number;
8073}
8074
8075void qed_dbg_pf_init(struct ecore_dev *edev)
8076{
8077        const u8 *dbg_values = NULL;
8078        int i;
8079
8080        PMD_INIT_FUNC_TRACE(edev);
8081
8082        OSAL_MUTEX_INIT(&edev->dbg_lock);
8083
8084        /* Sync ver with debugbus qed code */
8085        qed_dbg_set_app_ver(TOOLS_VERSION);
8086
8087        /* Debug values are after init values.
8088         * The offset is the first dword of the file.
8089         */
8090        /* TBD: change hardcoded value to offset from FW file */
8091        dbg_values = (const u8 *)edev->firmware + 1337296;
8092
8093        for_each_hwfn(edev, i) {
8094                qed_dbg_set_bin_ptr(&edev->hwfns[i], dbg_values);
8095                qed_dbg_user_set_bin_ptr(&edev->hwfns[i], dbg_values);
8096        }
8097
8098        /* Set the hwfn to be 0 as default */
8099        edev->dbg_params.engine_for_debug = 0;
8100}
8101
8102void qed_dbg_pf_exit(struct ecore_dev *edev)
8103{
8104        struct ecore_dbg_feature *feature = NULL;
8105        enum ecore_dbg_features feature_idx;
8106
8107        PMD_INIT_FUNC_TRACE(edev);
8108
8109        /* debug features' buffers may be allocated if debug feature was used
8110         * but dump wasn't called
8111         */
8112        for (feature_idx = 0; feature_idx < DBG_FEATURE_NUM; feature_idx++) {
8113                feature = &edev->dbg_features[feature_idx];
8114                if (feature->dump_buf) {
8115                        OSAL_VFREE(edev, feature->dump_buf);
8116                        feature->dump_buf = NULL;
8117                }
8118        }
8119
8120        OSAL_MUTEX_DEALLOC(&edev->dbg_lock);
8121}
8122