1 /* 2 * Copyright (C) 2017 Chelsio Communications. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms and conditions of the GNU General Public License, 6 * version 2, as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * more details. 12 * 13 * The full GNU General Public License is included in this distribution in 14 * the file called "COPYING". 15 * 16 */ 17 18 #include "t4_regs.h" 19 #include "cxgb4.h" 20 #include "cxgb4_cudbg.h" 21 22 static const struct cxgb4_collect_entity cxgb4_collect_mem_dump[] = { 23 { CUDBG_EDC0, cudbg_collect_edc0_meminfo }, 24 { CUDBG_EDC1, cudbg_collect_edc1_meminfo }, 25 { CUDBG_MC0, cudbg_collect_mc0_meminfo }, 26 { CUDBG_MC1, cudbg_collect_mc1_meminfo }, 27 { CUDBG_HMA, cudbg_collect_hma_meminfo }, 28 }; 29 30 static const struct cxgb4_collect_entity cxgb4_collect_hw_dump[] = { 31 { CUDBG_MBOX_LOG, cudbg_collect_mbox_log }, 32 { CUDBG_DEV_LOG, cudbg_collect_fw_devlog }, 33 { CUDBG_REG_DUMP, cudbg_collect_reg_dump }, 34 { CUDBG_CIM_LA, cudbg_collect_cim_la }, 35 { CUDBG_CIM_MA_LA, cudbg_collect_cim_ma_la }, 36 { CUDBG_CIM_QCFG, cudbg_collect_cim_qcfg }, 37 { CUDBG_CIM_IBQ_TP0, cudbg_collect_cim_ibq_tp0 }, 38 { CUDBG_CIM_IBQ_TP1, cudbg_collect_cim_ibq_tp1 }, 39 { CUDBG_CIM_IBQ_ULP, cudbg_collect_cim_ibq_ulp }, 40 { CUDBG_CIM_IBQ_SGE0, cudbg_collect_cim_ibq_sge0 }, 41 { CUDBG_CIM_IBQ_SGE1, cudbg_collect_cim_ibq_sge1 }, 42 { CUDBG_CIM_IBQ_NCSI, cudbg_collect_cim_ibq_ncsi }, 43 { CUDBG_CIM_OBQ_ULP0, cudbg_collect_cim_obq_ulp0 }, 44 { CUDBG_CIM_OBQ_ULP1, cudbg_collect_cim_obq_ulp1 }, 45 { CUDBG_CIM_OBQ_ULP2, cudbg_collect_cim_obq_ulp2 }, 46 { CUDBG_CIM_OBQ_ULP3, cudbg_collect_cim_obq_ulp3 }, 47 { CUDBG_CIM_OBQ_SGE, cudbg_collect_cim_obq_sge }, 48 { CUDBG_CIM_OBQ_NCSI, cudbg_collect_cim_obq_ncsi }, 49 { CUDBG_RSS, cudbg_collect_rss }, 50 { CUDBG_RSS_VF_CONF, cudbg_collect_rss_vf_config }, 51 { CUDBG_PATH_MTU, cudbg_collect_path_mtu }, 52 { CUDBG_PM_STATS, cudbg_collect_pm_stats }, 53 { CUDBG_HW_SCHED, cudbg_collect_hw_sched }, 54 { CUDBG_TP_INDIRECT, cudbg_collect_tp_indirect }, 55 { CUDBG_SGE_INDIRECT, cudbg_collect_sge_indirect }, 56 { CUDBG_ULPRX_LA, cudbg_collect_ulprx_la }, 57 { CUDBG_TP_LA, cudbg_collect_tp_la }, 58 { CUDBG_MEMINFO, cudbg_collect_meminfo }, 59 { CUDBG_CIM_PIF_LA, cudbg_collect_cim_pif_la }, 60 { CUDBG_CLK, cudbg_collect_clk_info }, 61 { CUDBG_CIM_OBQ_RXQ0, cudbg_collect_obq_sge_rx_q0 }, 62 { CUDBG_CIM_OBQ_RXQ1, cudbg_collect_obq_sge_rx_q1 }, 63 { CUDBG_PCIE_INDIRECT, cudbg_collect_pcie_indirect }, 64 { CUDBG_PM_INDIRECT, cudbg_collect_pm_indirect }, 65 { CUDBG_TID_INFO, cudbg_collect_tid }, 66 { CUDBG_PCIE_CONFIG, cudbg_collect_pcie_config }, 67 { CUDBG_DUMP_CONTEXT, cudbg_collect_dump_context }, 68 { CUDBG_MPS_TCAM, cudbg_collect_mps_tcam }, 69 { CUDBG_VPD_DATA, cudbg_collect_vpd_data }, 70 { CUDBG_LE_TCAM, cudbg_collect_le_tcam }, 71 { CUDBG_CCTRL, cudbg_collect_cctrl }, 72 { CUDBG_MA_INDIRECT, cudbg_collect_ma_indirect }, 73 { CUDBG_ULPTX_LA, cudbg_collect_ulptx_la }, 74 { CUDBG_UP_CIM_INDIRECT, cudbg_collect_up_cim_indirect }, 75 { CUDBG_PBT_TABLE, cudbg_collect_pbt_tables }, 76 { CUDBG_HMA_INDIRECT, cudbg_collect_hma_indirect }, 77 }; 78 79 static u32 cxgb4_get_entity_length(struct adapter *adap, u32 entity) 80 { 81 struct cudbg_tcam tcam_region = { 0 }; 82 u32 value, n = 0, len = 0; 83 84 switch (entity) { 85 case CUDBG_REG_DUMP: 86 switch (CHELSIO_CHIP_VERSION(adap->params.chip)) { 87 case CHELSIO_T4: 88 len = T4_REGMAP_SIZE; 89 break; 90 case CHELSIO_T5: 91 case CHELSIO_T6: 92 len = T5_REGMAP_SIZE; 93 break; 94 default: 95 break; 96 } 97 break; 98 case CUDBG_DEV_LOG: 99 len = adap->params.devlog.size; 100 break; 101 case CUDBG_CIM_LA: 102 if (is_t6(adap->params.chip)) { 103 len = adap->params.cim_la_size / 10 + 1; 104 len *= 11 * sizeof(u32); 105 } else { 106 len = adap->params.cim_la_size / 8; 107 len *= 8 * sizeof(u32); 108 } 109 len += sizeof(u32); /* for reading CIM LA configuration */ 110 break; 111 case CUDBG_CIM_MA_LA: 112 len = 2 * CIM_MALA_SIZE * 5 * sizeof(u32); 113 break; 114 case CUDBG_CIM_QCFG: 115 len = sizeof(struct cudbg_cim_qcfg); 116 break; 117 case CUDBG_CIM_IBQ_TP0: 118 case CUDBG_CIM_IBQ_TP1: 119 case CUDBG_CIM_IBQ_ULP: 120 case CUDBG_CIM_IBQ_SGE0: 121 case CUDBG_CIM_IBQ_SGE1: 122 case CUDBG_CIM_IBQ_NCSI: 123 len = CIM_IBQ_SIZE * 4 * sizeof(u32); 124 break; 125 case CUDBG_CIM_OBQ_ULP0: 126 len = cudbg_cim_obq_size(adap, 0); 127 break; 128 case CUDBG_CIM_OBQ_ULP1: 129 len = cudbg_cim_obq_size(adap, 1); 130 break; 131 case CUDBG_CIM_OBQ_ULP2: 132 len = cudbg_cim_obq_size(adap, 2); 133 break; 134 case CUDBG_CIM_OBQ_ULP3: 135 len = cudbg_cim_obq_size(adap, 3); 136 break; 137 case CUDBG_CIM_OBQ_SGE: 138 len = cudbg_cim_obq_size(adap, 4); 139 break; 140 case CUDBG_CIM_OBQ_NCSI: 141 len = cudbg_cim_obq_size(adap, 5); 142 break; 143 case CUDBG_CIM_OBQ_RXQ0: 144 len = cudbg_cim_obq_size(adap, 6); 145 break; 146 case CUDBG_CIM_OBQ_RXQ1: 147 len = cudbg_cim_obq_size(adap, 7); 148 break; 149 case CUDBG_EDC0: 150 value = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A); 151 if (value & EDRAM0_ENABLE_F) { 152 value = t4_read_reg(adap, MA_EDRAM0_BAR_A); 153 len = EDRAM0_SIZE_G(value); 154 } 155 len = cudbg_mbytes_to_bytes(len); 156 break; 157 case CUDBG_EDC1: 158 value = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A); 159 if (value & EDRAM1_ENABLE_F) { 160 value = t4_read_reg(adap, MA_EDRAM1_BAR_A); 161 len = EDRAM1_SIZE_G(value); 162 } 163 len = cudbg_mbytes_to_bytes(len); 164 break; 165 case CUDBG_MC0: 166 value = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A); 167 if (value & EXT_MEM0_ENABLE_F) { 168 value = t4_read_reg(adap, MA_EXT_MEMORY0_BAR_A); 169 len = EXT_MEM0_SIZE_G(value); 170 } 171 len = cudbg_mbytes_to_bytes(len); 172 break; 173 case CUDBG_MC1: 174 value = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A); 175 if (value & EXT_MEM1_ENABLE_F) { 176 value = t4_read_reg(adap, MA_EXT_MEMORY1_BAR_A); 177 len = EXT_MEM1_SIZE_G(value); 178 } 179 len = cudbg_mbytes_to_bytes(len); 180 break; 181 case CUDBG_RSS: 182 len = t4_chip_rss_size(adap) * sizeof(u16); 183 break; 184 case CUDBG_RSS_VF_CONF: 185 len = adap->params.arch.vfcount * 186 sizeof(struct cudbg_rss_vf_conf); 187 break; 188 case CUDBG_PATH_MTU: 189 len = NMTUS * sizeof(u16); 190 break; 191 case CUDBG_PM_STATS: 192 len = sizeof(struct cudbg_pm_stats); 193 break; 194 case CUDBG_HW_SCHED: 195 len = sizeof(struct cudbg_hw_sched); 196 break; 197 case CUDBG_TP_INDIRECT: 198 switch (CHELSIO_CHIP_VERSION(adap->params.chip)) { 199 case CHELSIO_T5: 200 n = sizeof(t5_tp_pio_array) + 201 sizeof(t5_tp_tm_pio_array) + 202 sizeof(t5_tp_mib_index_array); 203 break; 204 case CHELSIO_T6: 205 n = sizeof(t6_tp_pio_array) + 206 sizeof(t6_tp_tm_pio_array) + 207 sizeof(t6_tp_mib_index_array); 208 break; 209 default: 210 break; 211 } 212 n = n / (IREG_NUM_ELEM * sizeof(u32)); 213 len = sizeof(struct ireg_buf) * n; 214 break; 215 case CUDBG_SGE_INDIRECT: 216 len = sizeof(struct ireg_buf) * 2; 217 break; 218 case CUDBG_ULPRX_LA: 219 len = sizeof(struct cudbg_ulprx_la); 220 break; 221 case CUDBG_TP_LA: 222 len = sizeof(struct cudbg_tp_la) + TPLA_SIZE * sizeof(u64); 223 break; 224 case CUDBG_MEMINFO: 225 len = sizeof(struct cudbg_meminfo); 226 break; 227 case CUDBG_CIM_PIF_LA: 228 len = sizeof(struct cudbg_cim_pif_la); 229 len += 2 * CIM_PIFLA_SIZE * 6 * sizeof(u32); 230 break; 231 case CUDBG_CLK: 232 len = sizeof(struct cudbg_clk_info); 233 break; 234 case CUDBG_PCIE_INDIRECT: 235 n = sizeof(t5_pcie_pdbg_array) / (IREG_NUM_ELEM * sizeof(u32)); 236 len = sizeof(struct ireg_buf) * n * 2; 237 break; 238 case CUDBG_PM_INDIRECT: 239 n = sizeof(t5_pm_rx_array) / (IREG_NUM_ELEM * sizeof(u32)); 240 len = sizeof(struct ireg_buf) * n * 2; 241 break; 242 case CUDBG_TID_INFO: 243 len = sizeof(struct cudbg_tid_info_region_rev1); 244 break; 245 case CUDBG_PCIE_CONFIG: 246 len = sizeof(u32) * CUDBG_NUM_PCIE_CONFIG_REGS; 247 break; 248 case CUDBG_DUMP_CONTEXT: 249 len = cudbg_dump_context_size(adap); 250 break; 251 case CUDBG_MPS_TCAM: 252 len = sizeof(struct cudbg_mps_tcam) * 253 adap->params.arch.mps_tcam_size; 254 break; 255 case CUDBG_VPD_DATA: 256 len = sizeof(struct cudbg_vpd_data); 257 break; 258 case CUDBG_LE_TCAM: 259 cudbg_fill_le_tcam_info(adap, &tcam_region); 260 len = sizeof(struct cudbg_tcam) + 261 sizeof(struct cudbg_tid_data) * tcam_region.max_tid; 262 break; 263 case CUDBG_CCTRL: 264 len = sizeof(u16) * NMTUS * NCCTRL_WIN; 265 break; 266 case CUDBG_MA_INDIRECT: 267 if (CHELSIO_CHIP_VERSION(adap->params.chip) > CHELSIO_T5) { 268 n = sizeof(t6_ma_ireg_array) / 269 (IREG_NUM_ELEM * sizeof(u32)); 270 len = sizeof(struct ireg_buf) * n * 2; 271 } 272 break; 273 case CUDBG_ULPTX_LA: 274 len = sizeof(struct cudbg_ulptx_la); 275 break; 276 case CUDBG_UP_CIM_INDIRECT: 277 n = 0; 278 if (is_t5(adap->params.chip)) 279 n = sizeof(t5_up_cim_reg_array) / 280 ((IREG_NUM_ELEM + 1) * sizeof(u32)); 281 else if (is_t6(adap->params.chip)) 282 n = sizeof(t6_up_cim_reg_array) / 283 ((IREG_NUM_ELEM + 1) * sizeof(u32)); 284 len = sizeof(struct ireg_buf) * n; 285 break; 286 case CUDBG_PBT_TABLE: 287 len = sizeof(struct cudbg_pbt_tables); 288 break; 289 case CUDBG_MBOX_LOG: 290 len = sizeof(struct cudbg_mbox_log) * adap->mbox_log->size; 291 break; 292 case CUDBG_HMA_INDIRECT: 293 if (CHELSIO_CHIP_VERSION(adap->params.chip) > CHELSIO_T5) { 294 n = sizeof(t6_hma_ireg_array) / 295 (IREG_NUM_ELEM * sizeof(u32)); 296 len = sizeof(struct ireg_buf) * n; 297 } 298 break; 299 case CUDBG_HMA: 300 value = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A); 301 if (value & HMA_MUX_F) { 302 /* In T6, there's no MC1. So, HMA shares MC1 303 * address space. 304 */ 305 value = t4_read_reg(adap, MA_EXT_MEMORY1_BAR_A); 306 len = EXT_MEM1_SIZE_G(value); 307 } 308 len = cudbg_mbytes_to_bytes(len); 309 break; 310 default: 311 break; 312 } 313 314 return len; 315 } 316 317 u32 cxgb4_get_dump_length(struct adapter *adap, u32 flag) 318 { 319 u32 i, entity; 320 u32 len = 0; 321 322 if (flag & CXGB4_ETH_DUMP_HW) { 323 for (i = 0; i < ARRAY_SIZE(cxgb4_collect_hw_dump); i++) { 324 entity = cxgb4_collect_hw_dump[i].entity; 325 len += cxgb4_get_entity_length(adap, entity); 326 } 327 } 328 329 if (flag & CXGB4_ETH_DUMP_MEM) { 330 for (i = 0; i < ARRAY_SIZE(cxgb4_collect_mem_dump); i++) { 331 entity = cxgb4_collect_mem_dump[i].entity; 332 len += cxgb4_get_entity_length(adap, entity); 333 } 334 } 335 336 return len; 337 } 338 339 static void cxgb4_cudbg_collect_entity(struct cudbg_init *pdbg_init, 340 struct cudbg_buffer *dbg_buff, 341 const struct cxgb4_collect_entity *e_arr, 342 u32 arr_size, void *buf, u32 *tot_size) 343 { 344 struct adapter *adap = pdbg_init->adap; 345 struct cudbg_error cudbg_err = { 0 }; 346 struct cudbg_entity_hdr *entity_hdr; 347 u32 entity_size, i; 348 u32 total_size = 0; 349 int ret; 350 351 for (i = 0; i < arr_size; i++) { 352 const struct cxgb4_collect_entity *e = &e_arr[i]; 353 354 /* Skip entities that won't fit in output buffer */ 355 entity_size = cxgb4_get_entity_length(adap, e->entity); 356 if (entity_size > 357 pdbg_init->outbuf_size - *tot_size - total_size) 358 continue; 359 360 entity_hdr = cudbg_get_entity_hdr(buf, e->entity); 361 entity_hdr->entity_type = e->entity; 362 entity_hdr->start_offset = dbg_buff->offset; 363 memset(&cudbg_err, 0, sizeof(struct cudbg_error)); 364 ret = e->collect_cb(pdbg_init, dbg_buff, &cudbg_err); 365 if (ret) { 366 entity_hdr->size = 0; 367 dbg_buff->offset = entity_hdr->start_offset; 368 } else { 369 cudbg_align_debug_buffer(dbg_buff, entity_hdr); 370 } 371 372 /* Log error and continue with next entity */ 373 if (cudbg_err.sys_err) 374 ret = CUDBG_SYSTEM_ERROR; 375 376 entity_hdr->hdr_flags = ret; 377 entity_hdr->sys_err = cudbg_err.sys_err; 378 entity_hdr->sys_warn = cudbg_err.sys_warn; 379 total_size += entity_hdr->size; 380 } 381 382 *tot_size += total_size; 383 } 384 385 int cxgb4_cudbg_collect(struct adapter *adap, void *buf, u32 *buf_size, 386 u32 flag) 387 { 388 struct cudbg_init cudbg_init = { 0 }; 389 struct cudbg_buffer dbg_buff = { 0 }; 390 u32 size, min_size, total_size = 0; 391 struct cudbg_hdr *cudbg_hdr; 392 393 size = *buf_size; 394 395 cudbg_init.adap = adap; 396 cudbg_init.outbuf = buf; 397 cudbg_init.outbuf_size = size; 398 399 dbg_buff.data = buf; 400 dbg_buff.size = size; 401 dbg_buff.offset = 0; 402 403 cudbg_hdr = (struct cudbg_hdr *)buf; 404 cudbg_hdr->signature = CUDBG_SIGNATURE; 405 cudbg_hdr->hdr_len = sizeof(struct cudbg_hdr); 406 cudbg_hdr->major_ver = CUDBG_MAJOR_VERSION; 407 cudbg_hdr->minor_ver = CUDBG_MINOR_VERSION; 408 cudbg_hdr->max_entities = CUDBG_MAX_ENTITY; 409 cudbg_hdr->chip_ver = adap->params.chip; 410 cudbg_hdr->dump_type = CUDBG_DUMP_TYPE_MINI; 411 cudbg_hdr->compress_type = CUDBG_COMPRESSION_NONE; 412 413 min_size = sizeof(struct cudbg_hdr) + 414 sizeof(struct cudbg_entity_hdr) * 415 cudbg_hdr->max_entities; 416 if (size < min_size) 417 return -ENOMEM; 418 419 dbg_buff.offset += min_size; 420 total_size = dbg_buff.offset; 421 422 if (flag & CXGB4_ETH_DUMP_HW) 423 cxgb4_cudbg_collect_entity(&cudbg_init, &dbg_buff, 424 cxgb4_collect_hw_dump, 425 ARRAY_SIZE(cxgb4_collect_hw_dump), 426 buf, 427 &total_size); 428 429 if (flag & CXGB4_ETH_DUMP_MEM) 430 cxgb4_cudbg_collect_entity(&cudbg_init, &dbg_buff, 431 cxgb4_collect_mem_dump, 432 ARRAY_SIZE(cxgb4_collect_mem_dump), 433 buf, 434 &total_size); 435 436 cudbg_hdr->data_len = total_size; 437 *buf_size = total_size; 438 return 0; 439 } 440 441 void cxgb4_init_ethtool_dump(struct adapter *adapter) 442 { 443 adapter->eth_dump.flag = CXGB4_ETH_DUMP_NONE; 444 adapter->eth_dump.version = adapter->params.fw_vers; 445 adapter->eth_dump.len = 0; 446 } 447