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