162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2017 Chelsio Communications. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include "t4_regs.h" 762306a36Sopenharmony_ci#include "cxgb4.h" 862306a36Sopenharmony_ci#include "cxgb4_cudbg.h" 962306a36Sopenharmony_ci#include "cudbg_zlib.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_cistatic const struct cxgb4_collect_entity cxgb4_collect_mem_dump[] = { 1262306a36Sopenharmony_ci { CUDBG_EDC0, cudbg_collect_edc0_meminfo }, 1362306a36Sopenharmony_ci { CUDBG_EDC1, cudbg_collect_edc1_meminfo }, 1462306a36Sopenharmony_ci { CUDBG_MC0, cudbg_collect_mc0_meminfo }, 1562306a36Sopenharmony_ci { CUDBG_MC1, cudbg_collect_mc1_meminfo }, 1662306a36Sopenharmony_ci { CUDBG_HMA, cudbg_collect_hma_meminfo }, 1762306a36Sopenharmony_ci}; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic const struct cxgb4_collect_entity cxgb4_collect_hw_dump[] = { 2062306a36Sopenharmony_ci { CUDBG_MBOX_LOG, cudbg_collect_mbox_log }, 2162306a36Sopenharmony_ci { CUDBG_QDESC, cudbg_collect_qdesc }, 2262306a36Sopenharmony_ci { CUDBG_DEV_LOG, cudbg_collect_fw_devlog }, 2362306a36Sopenharmony_ci { CUDBG_REG_DUMP, cudbg_collect_reg_dump }, 2462306a36Sopenharmony_ci { CUDBG_CIM_LA, cudbg_collect_cim_la }, 2562306a36Sopenharmony_ci { CUDBG_CIM_MA_LA, cudbg_collect_cim_ma_la }, 2662306a36Sopenharmony_ci { CUDBG_CIM_QCFG, cudbg_collect_cim_qcfg }, 2762306a36Sopenharmony_ci { CUDBG_CIM_IBQ_TP0, cudbg_collect_cim_ibq_tp0 }, 2862306a36Sopenharmony_ci { CUDBG_CIM_IBQ_TP1, cudbg_collect_cim_ibq_tp1 }, 2962306a36Sopenharmony_ci { CUDBG_CIM_IBQ_ULP, cudbg_collect_cim_ibq_ulp }, 3062306a36Sopenharmony_ci { CUDBG_CIM_IBQ_SGE0, cudbg_collect_cim_ibq_sge0 }, 3162306a36Sopenharmony_ci { CUDBG_CIM_IBQ_SGE1, cudbg_collect_cim_ibq_sge1 }, 3262306a36Sopenharmony_ci { CUDBG_CIM_IBQ_NCSI, cudbg_collect_cim_ibq_ncsi }, 3362306a36Sopenharmony_ci { CUDBG_CIM_OBQ_ULP0, cudbg_collect_cim_obq_ulp0 }, 3462306a36Sopenharmony_ci { CUDBG_CIM_OBQ_ULP1, cudbg_collect_cim_obq_ulp1 }, 3562306a36Sopenharmony_ci { CUDBG_CIM_OBQ_ULP2, cudbg_collect_cim_obq_ulp2 }, 3662306a36Sopenharmony_ci { CUDBG_CIM_OBQ_ULP3, cudbg_collect_cim_obq_ulp3 }, 3762306a36Sopenharmony_ci { CUDBG_CIM_OBQ_SGE, cudbg_collect_cim_obq_sge }, 3862306a36Sopenharmony_ci { CUDBG_CIM_OBQ_NCSI, cudbg_collect_cim_obq_ncsi }, 3962306a36Sopenharmony_ci { CUDBG_RSS, cudbg_collect_rss }, 4062306a36Sopenharmony_ci { CUDBG_RSS_VF_CONF, cudbg_collect_rss_vf_config }, 4162306a36Sopenharmony_ci { CUDBG_PATH_MTU, cudbg_collect_path_mtu }, 4262306a36Sopenharmony_ci { CUDBG_PM_STATS, cudbg_collect_pm_stats }, 4362306a36Sopenharmony_ci { CUDBG_HW_SCHED, cudbg_collect_hw_sched }, 4462306a36Sopenharmony_ci { CUDBG_TP_INDIRECT, cudbg_collect_tp_indirect }, 4562306a36Sopenharmony_ci { CUDBG_SGE_INDIRECT, cudbg_collect_sge_indirect }, 4662306a36Sopenharmony_ci { CUDBG_ULPRX_LA, cudbg_collect_ulprx_la }, 4762306a36Sopenharmony_ci { CUDBG_TP_LA, cudbg_collect_tp_la }, 4862306a36Sopenharmony_ci { CUDBG_MEMINFO, cudbg_collect_meminfo }, 4962306a36Sopenharmony_ci { CUDBG_CIM_PIF_LA, cudbg_collect_cim_pif_la }, 5062306a36Sopenharmony_ci { CUDBG_CLK, cudbg_collect_clk_info }, 5162306a36Sopenharmony_ci { CUDBG_CIM_OBQ_RXQ0, cudbg_collect_obq_sge_rx_q0 }, 5262306a36Sopenharmony_ci { CUDBG_CIM_OBQ_RXQ1, cudbg_collect_obq_sge_rx_q1 }, 5362306a36Sopenharmony_ci { CUDBG_PCIE_INDIRECT, cudbg_collect_pcie_indirect }, 5462306a36Sopenharmony_ci { CUDBG_PM_INDIRECT, cudbg_collect_pm_indirect }, 5562306a36Sopenharmony_ci { CUDBG_TID_INFO, cudbg_collect_tid }, 5662306a36Sopenharmony_ci { CUDBG_PCIE_CONFIG, cudbg_collect_pcie_config }, 5762306a36Sopenharmony_ci { CUDBG_DUMP_CONTEXT, cudbg_collect_dump_context }, 5862306a36Sopenharmony_ci { CUDBG_MPS_TCAM, cudbg_collect_mps_tcam }, 5962306a36Sopenharmony_ci { CUDBG_VPD_DATA, cudbg_collect_vpd_data }, 6062306a36Sopenharmony_ci { CUDBG_LE_TCAM, cudbg_collect_le_tcam }, 6162306a36Sopenharmony_ci { CUDBG_CCTRL, cudbg_collect_cctrl }, 6262306a36Sopenharmony_ci { CUDBG_MA_INDIRECT, cudbg_collect_ma_indirect }, 6362306a36Sopenharmony_ci { CUDBG_ULPTX_LA, cudbg_collect_ulptx_la }, 6462306a36Sopenharmony_ci { CUDBG_UP_CIM_INDIRECT, cudbg_collect_up_cim_indirect }, 6562306a36Sopenharmony_ci { CUDBG_PBT_TABLE, cudbg_collect_pbt_tables }, 6662306a36Sopenharmony_ci { CUDBG_HMA_INDIRECT, cudbg_collect_hma_indirect }, 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic const struct cxgb4_collect_entity cxgb4_collect_flash_dump[] = { 7062306a36Sopenharmony_ci { CUDBG_FLASH, cudbg_collect_flash }, 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ciu32 cxgb4_get_dump_length(struct adapter *adap, u32 flag) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci u32 i, entity; 7662306a36Sopenharmony_ci u32 len = 0; 7762306a36Sopenharmony_ci u32 wsize; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (flag & CXGB4_ETH_DUMP_HW) { 8062306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(cxgb4_collect_hw_dump); i++) { 8162306a36Sopenharmony_ci entity = cxgb4_collect_hw_dump[i].entity; 8262306a36Sopenharmony_ci len += cudbg_get_entity_length(adap, entity); 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci if (flag & CXGB4_ETH_DUMP_MEM) { 8762306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(cxgb4_collect_mem_dump); i++) { 8862306a36Sopenharmony_ci entity = cxgb4_collect_mem_dump[i].entity; 8962306a36Sopenharmony_ci len += cudbg_get_entity_length(adap, entity); 9062306a36Sopenharmony_ci } 9162306a36Sopenharmony_ci } 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if (flag & CXGB4_ETH_DUMP_FLASH) 9462306a36Sopenharmony_ci len += adap->params.sf_size; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci /* If compression is enabled, a smaller destination buffer is enough */ 9762306a36Sopenharmony_ci wsize = cudbg_get_workspace_size(); 9862306a36Sopenharmony_ci if (wsize && len > CUDBG_DUMP_BUFF_SIZE) 9962306a36Sopenharmony_ci len = CUDBG_DUMP_BUFF_SIZE; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci return len; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic void cxgb4_cudbg_collect_entity(struct cudbg_init *pdbg_init, 10562306a36Sopenharmony_ci struct cudbg_buffer *dbg_buff, 10662306a36Sopenharmony_ci const struct cxgb4_collect_entity *e_arr, 10762306a36Sopenharmony_ci u32 arr_size, void *buf, u32 *tot_size) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci struct cudbg_error cudbg_err = { 0 }; 11062306a36Sopenharmony_ci struct cudbg_entity_hdr *entity_hdr; 11162306a36Sopenharmony_ci u32 i, total_size = 0; 11262306a36Sopenharmony_ci int ret; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci for (i = 0; i < arr_size; i++) { 11562306a36Sopenharmony_ci const struct cxgb4_collect_entity *e = &e_arr[i]; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci entity_hdr = cudbg_get_entity_hdr(buf, e->entity); 11862306a36Sopenharmony_ci entity_hdr->entity_type = e->entity; 11962306a36Sopenharmony_ci entity_hdr->start_offset = dbg_buff->offset; 12062306a36Sopenharmony_ci memset(&cudbg_err, 0, sizeof(struct cudbg_error)); 12162306a36Sopenharmony_ci ret = e->collect_cb(pdbg_init, dbg_buff, &cudbg_err); 12262306a36Sopenharmony_ci if (ret) { 12362306a36Sopenharmony_ci entity_hdr->size = 0; 12462306a36Sopenharmony_ci dbg_buff->offset = entity_hdr->start_offset; 12562306a36Sopenharmony_ci } else { 12662306a36Sopenharmony_ci cudbg_align_debug_buffer(dbg_buff, entity_hdr); 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci /* Log error and continue with next entity */ 13062306a36Sopenharmony_ci if (cudbg_err.sys_err) 13162306a36Sopenharmony_ci ret = CUDBG_SYSTEM_ERROR; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci entity_hdr->hdr_flags = ret; 13462306a36Sopenharmony_ci entity_hdr->sys_err = cudbg_err.sys_err; 13562306a36Sopenharmony_ci entity_hdr->sys_warn = cudbg_err.sys_warn; 13662306a36Sopenharmony_ci total_size += entity_hdr->size; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci *tot_size += total_size; 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic int cudbg_alloc_compress_buff(struct cudbg_init *pdbg_init) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci u32 workspace_size; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci workspace_size = cudbg_get_workspace_size(); 14762306a36Sopenharmony_ci pdbg_init->compress_buff = vzalloc(CUDBG_COMPRESS_BUFF_SIZE + 14862306a36Sopenharmony_ci workspace_size); 14962306a36Sopenharmony_ci if (!pdbg_init->compress_buff) 15062306a36Sopenharmony_ci return -ENOMEM; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci pdbg_init->compress_buff_size = CUDBG_COMPRESS_BUFF_SIZE; 15362306a36Sopenharmony_ci pdbg_init->workspace = (u8 *)pdbg_init->compress_buff + 15462306a36Sopenharmony_ci CUDBG_COMPRESS_BUFF_SIZE - workspace_size; 15562306a36Sopenharmony_ci return 0; 15662306a36Sopenharmony_ci} 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cistatic void cudbg_free_compress_buff(struct cudbg_init *pdbg_init) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci vfree(pdbg_init->compress_buff); 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ciint cxgb4_cudbg_collect(struct adapter *adap, void *buf, u32 *buf_size, 16462306a36Sopenharmony_ci u32 flag) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci struct cudbg_buffer dbg_buff = { 0 }; 16762306a36Sopenharmony_ci u32 size, min_size, total_size = 0; 16862306a36Sopenharmony_ci struct cudbg_init cudbg_init; 16962306a36Sopenharmony_ci struct cudbg_hdr *cudbg_hdr; 17062306a36Sopenharmony_ci int rc; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci size = *buf_size; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci memset(&cudbg_init, 0, sizeof(struct cudbg_init)); 17562306a36Sopenharmony_ci cudbg_init.adap = adap; 17662306a36Sopenharmony_ci cudbg_init.outbuf = buf; 17762306a36Sopenharmony_ci cudbg_init.outbuf_size = size; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci dbg_buff.data = buf; 18062306a36Sopenharmony_ci dbg_buff.size = size; 18162306a36Sopenharmony_ci dbg_buff.offset = 0; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci cudbg_hdr = (struct cudbg_hdr *)buf; 18462306a36Sopenharmony_ci cudbg_hdr->signature = CUDBG_SIGNATURE; 18562306a36Sopenharmony_ci cudbg_hdr->hdr_len = sizeof(struct cudbg_hdr); 18662306a36Sopenharmony_ci cudbg_hdr->major_ver = CUDBG_MAJOR_VERSION; 18762306a36Sopenharmony_ci cudbg_hdr->minor_ver = CUDBG_MINOR_VERSION; 18862306a36Sopenharmony_ci cudbg_hdr->max_entities = CUDBG_MAX_ENTITY; 18962306a36Sopenharmony_ci cudbg_hdr->chip_ver = adap->params.chip; 19062306a36Sopenharmony_ci cudbg_hdr->dump_type = CUDBG_DUMP_TYPE_MINI; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci min_size = sizeof(struct cudbg_hdr) + 19362306a36Sopenharmony_ci sizeof(struct cudbg_entity_hdr) * 19462306a36Sopenharmony_ci cudbg_hdr->max_entities; 19562306a36Sopenharmony_ci if (size < min_size) 19662306a36Sopenharmony_ci return -ENOMEM; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci rc = cudbg_get_workspace_size(); 19962306a36Sopenharmony_ci if (rc) { 20062306a36Sopenharmony_ci /* Zlib available. So, use zlib deflate */ 20162306a36Sopenharmony_ci cudbg_init.compress_type = CUDBG_COMPRESSION_ZLIB; 20262306a36Sopenharmony_ci rc = cudbg_alloc_compress_buff(&cudbg_init); 20362306a36Sopenharmony_ci if (rc) { 20462306a36Sopenharmony_ci /* Ignore error and continue without compression. */ 20562306a36Sopenharmony_ci dev_warn(adap->pdev_dev, 20662306a36Sopenharmony_ci "Fail allocating compression buffer ret: %d. Continuing without compression.\n", 20762306a36Sopenharmony_ci rc); 20862306a36Sopenharmony_ci cudbg_init.compress_type = CUDBG_COMPRESSION_NONE; 20962306a36Sopenharmony_ci rc = 0; 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci } else { 21262306a36Sopenharmony_ci cudbg_init.compress_type = CUDBG_COMPRESSION_NONE; 21362306a36Sopenharmony_ci } 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci cudbg_hdr->compress_type = cudbg_init.compress_type; 21662306a36Sopenharmony_ci dbg_buff.offset += min_size; 21762306a36Sopenharmony_ci total_size = dbg_buff.offset; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci if (flag & CXGB4_ETH_DUMP_HW) 22062306a36Sopenharmony_ci cxgb4_cudbg_collect_entity(&cudbg_init, &dbg_buff, 22162306a36Sopenharmony_ci cxgb4_collect_hw_dump, 22262306a36Sopenharmony_ci ARRAY_SIZE(cxgb4_collect_hw_dump), 22362306a36Sopenharmony_ci buf, 22462306a36Sopenharmony_ci &total_size); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci if (flag & CXGB4_ETH_DUMP_MEM) 22762306a36Sopenharmony_ci cxgb4_cudbg_collect_entity(&cudbg_init, &dbg_buff, 22862306a36Sopenharmony_ci cxgb4_collect_mem_dump, 22962306a36Sopenharmony_ci ARRAY_SIZE(cxgb4_collect_mem_dump), 23062306a36Sopenharmony_ci buf, 23162306a36Sopenharmony_ci &total_size); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci if (flag & CXGB4_ETH_DUMP_FLASH) 23462306a36Sopenharmony_ci cxgb4_cudbg_collect_entity(&cudbg_init, &dbg_buff, 23562306a36Sopenharmony_ci cxgb4_collect_flash_dump, 23662306a36Sopenharmony_ci ARRAY_SIZE(cxgb4_collect_flash_dump), 23762306a36Sopenharmony_ci buf, 23862306a36Sopenharmony_ci &total_size); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci cudbg_free_compress_buff(&cudbg_init); 24162306a36Sopenharmony_ci cudbg_hdr->data_len = total_size; 24262306a36Sopenharmony_ci if (cudbg_init.compress_type != CUDBG_COMPRESSION_NONE) 24362306a36Sopenharmony_ci *buf_size = size; 24462306a36Sopenharmony_ci else 24562306a36Sopenharmony_ci *buf_size = total_size; 24662306a36Sopenharmony_ci return 0; 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_civoid cxgb4_init_ethtool_dump(struct adapter *adapter) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci adapter->eth_dump.flag = CXGB4_ETH_DUMP_NONE; 25262306a36Sopenharmony_ci adapter->eth_dump.version = adapter->params.fw_vers; 25362306a36Sopenharmony_ci adapter->eth_dump.len = 0; 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic int cxgb4_cudbg_vmcoredd_collect(struct vmcoredd_data *data, void *buf) 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci struct adapter *adap = container_of(data, struct adapter, vmcoredd); 25962306a36Sopenharmony_ci u32 len = data->size; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci return cxgb4_cudbg_collect(adap, buf, &len, CXGB4_ETH_DUMP_ALL); 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ciint cxgb4_cudbg_vmcore_add_dump(struct adapter *adap) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci struct vmcoredd_data *data = &adap->vmcoredd; 26762306a36Sopenharmony_ci u32 len; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci len = sizeof(struct cudbg_hdr) + 27062306a36Sopenharmony_ci sizeof(struct cudbg_entity_hdr) * CUDBG_MAX_ENTITY; 27162306a36Sopenharmony_ci len += CUDBG_DUMP_BUFF_SIZE; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci data->size = len; 27462306a36Sopenharmony_ci snprintf(data->dump_name, sizeof(data->dump_name), "%s_%s", 27562306a36Sopenharmony_ci cxgb4_driver_name, adap->name); 27662306a36Sopenharmony_ci data->vmcoredd_callback = cxgb4_cudbg_vmcoredd_collect; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci return vmcore_add_device_dump(data); 27962306a36Sopenharmony_ci} 280