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_entity.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 }; 27 28 static const struct cxgb4_collect_entity cxgb4_collect_hw_dump[] = { 29 { CUDBG_MBOX_LOG, cudbg_collect_mbox_log }, 30 { CUDBG_DEV_LOG, cudbg_collect_fw_devlog }, 31 { CUDBG_REG_DUMP, cudbg_collect_reg_dump }, 32 { CUDBG_CIM_LA, cudbg_collect_cim_la }, 33 { CUDBG_CIM_MA_LA, cudbg_collect_cim_ma_la }, 34 { CUDBG_CIM_QCFG, cudbg_collect_cim_qcfg }, 35 { CUDBG_CIM_IBQ_TP0, cudbg_collect_cim_ibq_tp0 }, 36 { CUDBG_CIM_IBQ_TP1, cudbg_collect_cim_ibq_tp1 }, 37 { CUDBG_CIM_IBQ_ULP, cudbg_collect_cim_ibq_ulp }, 38 { CUDBG_CIM_IBQ_SGE0, cudbg_collect_cim_ibq_sge0 }, 39 { CUDBG_CIM_IBQ_SGE1, cudbg_collect_cim_ibq_sge1 }, 40 { CUDBG_CIM_IBQ_NCSI, cudbg_collect_cim_ibq_ncsi }, 41 { CUDBG_CIM_OBQ_ULP0, cudbg_collect_cim_obq_ulp0 }, 42 { CUDBG_CIM_OBQ_ULP1, cudbg_collect_cim_obq_ulp1 }, 43 { CUDBG_CIM_OBQ_ULP2, cudbg_collect_cim_obq_ulp2 }, 44 { CUDBG_CIM_OBQ_ULP3, cudbg_collect_cim_obq_ulp3 }, 45 { CUDBG_CIM_OBQ_SGE, cudbg_collect_cim_obq_sge }, 46 { CUDBG_CIM_OBQ_NCSI, cudbg_collect_cim_obq_ncsi }, 47 { CUDBG_RSS, cudbg_collect_rss }, 48 { CUDBG_RSS_VF_CONF, cudbg_collect_rss_vf_config }, 49 { CUDBG_PATH_MTU, cudbg_collect_path_mtu }, 50 { CUDBG_PM_STATS, cudbg_collect_pm_stats }, 51 { CUDBG_HW_SCHED, cudbg_collect_hw_sched }, 52 { CUDBG_TP_INDIRECT, cudbg_collect_tp_indirect }, 53 { CUDBG_SGE_INDIRECT, cudbg_collect_sge_indirect }, 54 { CUDBG_ULPRX_LA, cudbg_collect_ulprx_la }, 55 { CUDBG_TP_LA, cudbg_collect_tp_la }, 56 { CUDBG_CIM_PIF_LA, cudbg_collect_cim_pif_la }, 57 { CUDBG_CLK, cudbg_collect_clk_info }, 58 { CUDBG_CIM_OBQ_RXQ0, cudbg_collect_obq_sge_rx_q0 }, 59 { CUDBG_CIM_OBQ_RXQ1, cudbg_collect_obq_sge_rx_q1 }, 60 { CUDBG_PCIE_INDIRECT, cudbg_collect_pcie_indirect }, 61 { CUDBG_PM_INDIRECT, cudbg_collect_pm_indirect }, 62 { CUDBG_TID_INFO, cudbg_collect_tid }, 63 { CUDBG_DUMP_CONTEXT, cudbg_collect_dump_context }, 64 { CUDBG_MPS_TCAM, cudbg_collect_mps_tcam }, 65 { CUDBG_VPD_DATA, cudbg_collect_vpd_data }, 66 { CUDBG_LE_TCAM, cudbg_collect_le_tcam }, 67 { CUDBG_CCTRL, cudbg_collect_cctrl }, 68 { CUDBG_MA_INDIRECT, cudbg_collect_ma_indirect }, 69 { CUDBG_ULPTX_LA, cudbg_collect_ulptx_la }, 70 { CUDBG_UP_CIM_INDIRECT, cudbg_collect_up_cim_indirect }, 71 { CUDBG_PBT_TABLE, cudbg_collect_pbt_tables }, 72 { CUDBG_HMA_INDIRECT, cudbg_collect_hma_indirect }, 73 }; 74 75 static u32 cxgb4_get_entity_length(struct adapter *adap, u32 entity) 76 { 77 struct cudbg_tcam tcam_region = { 0 }; 78 u32 value, n = 0, len = 0; 79 80 switch (entity) { 81 case CUDBG_REG_DUMP: 82 switch (CHELSIO_CHIP_VERSION(adap->params.chip)) { 83 case CHELSIO_T4: 84 len = T4_REGMAP_SIZE; 85 break; 86 case CHELSIO_T5: 87 case CHELSIO_T6: 88 len = T5_REGMAP_SIZE; 89 break; 90 default: 91 break; 92 } 93 break; 94 case CUDBG_DEV_LOG: 95 len = adap->params.devlog.size; 96 break; 97 case CUDBG_CIM_LA: 98 if (is_t6(adap->params.chip)) { 99 len = adap->params.cim_la_size / 10 + 1; 100 len *= 11 * sizeof(u32); 101 } else { 102 len = adap->params.cim_la_size / 8; 103 len *= 8 * sizeof(u32); 104 } 105 len += sizeof(u32); /* for reading CIM LA configuration */ 106 break; 107 case CUDBG_CIM_MA_LA: 108 len = 2 * CIM_MALA_SIZE * 5 * sizeof(u32); 109 break; 110 case CUDBG_CIM_QCFG: 111 len = sizeof(struct cudbg_cim_qcfg); 112 break; 113 case CUDBG_CIM_IBQ_TP0: 114 case CUDBG_CIM_IBQ_TP1: 115 case CUDBG_CIM_IBQ_ULP: 116 case CUDBG_CIM_IBQ_SGE0: 117 case CUDBG_CIM_IBQ_SGE1: 118 case CUDBG_CIM_IBQ_NCSI: 119 len = CIM_IBQ_SIZE * 4 * sizeof(u32); 120 break; 121 case CUDBG_CIM_OBQ_ULP0: 122 len = cudbg_cim_obq_size(adap, 0); 123 break; 124 case CUDBG_CIM_OBQ_ULP1: 125 len = cudbg_cim_obq_size(adap, 1); 126 break; 127 case CUDBG_CIM_OBQ_ULP2: 128 len = cudbg_cim_obq_size(adap, 2); 129 break; 130 case CUDBG_CIM_OBQ_ULP3: 131 len = cudbg_cim_obq_size(adap, 3); 132 break; 133 case CUDBG_CIM_OBQ_SGE: 134 len = cudbg_cim_obq_size(adap, 4); 135 break; 136 case CUDBG_CIM_OBQ_NCSI: 137 len = cudbg_cim_obq_size(adap, 5); 138 break; 139 case CUDBG_CIM_OBQ_RXQ0: 140 len = cudbg_cim_obq_size(adap, 6); 141 break; 142 case CUDBG_CIM_OBQ_RXQ1: 143 len = cudbg_cim_obq_size(adap, 7); 144 break; 145 case CUDBG_EDC0: 146 value = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A); 147 if (value & EDRAM0_ENABLE_F) { 148 value = t4_read_reg(adap, MA_EDRAM0_BAR_A); 149 len = EDRAM0_SIZE_G(value); 150 } 151 len = cudbg_mbytes_to_bytes(len); 152 break; 153 case CUDBG_EDC1: 154 value = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A); 155 if (value & EDRAM1_ENABLE_F) { 156 value = t4_read_reg(adap, MA_EDRAM1_BAR_A); 157 len = EDRAM1_SIZE_G(value); 158 } 159 len = cudbg_mbytes_to_bytes(len); 160 break; 161 case CUDBG_RSS: 162 len = RSS_NENTRIES * sizeof(u16); 163 break; 164 case CUDBG_RSS_VF_CONF: 165 len = adap->params.arch.vfcount * 166 sizeof(struct cudbg_rss_vf_conf); 167 break; 168 case CUDBG_PATH_MTU: 169 len = NMTUS * sizeof(u16); 170 break; 171 case CUDBG_PM_STATS: 172 len = sizeof(struct cudbg_pm_stats); 173 break; 174 case CUDBG_HW_SCHED: 175 len = sizeof(struct cudbg_hw_sched); 176 break; 177 case CUDBG_TP_INDIRECT: 178 switch (CHELSIO_CHIP_VERSION(adap->params.chip)) { 179 case CHELSIO_T5: 180 n = sizeof(t5_tp_pio_array) + 181 sizeof(t5_tp_tm_pio_array) + 182 sizeof(t5_tp_mib_index_array); 183 break; 184 case CHELSIO_T6: 185 n = sizeof(t6_tp_pio_array) + 186 sizeof(t6_tp_tm_pio_array) + 187 sizeof(t6_tp_mib_index_array); 188 break; 189 default: 190 break; 191 } 192 n = n / (IREG_NUM_ELEM * sizeof(u32)); 193 len = sizeof(struct ireg_buf) * n; 194 break; 195 case CUDBG_SGE_INDIRECT: 196 len = sizeof(struct ireg_buf) * 2; 197 break; 198 case CUDBG_ULPRX_LA: 199 len = sizeof(struct cudbg_ulprx_la); 200 break; 201 case CUDBG_TP_LA: 202 len = sizeof(struct cudbg_tp_la) + TPLA_SIZE * sizeof(u64); 203 break; 204 case CUDBG_CIM_PIF_LA: 205 len = sizeof(struct cudbg_cim_pif_la); 206 len += 2 * CIM_PIFLA_SIZE * 6 * sizeof(u32); 207 break; 208 case CUDBG_CLK: 209 len = sizeof(struct cudbg_clk_info); 210 break; 211 case CUDBG_PCIE_INDIRECT: 212 n = sizeof(t5_pcie_pdbg_array) / (IREG_NUM_ELEM * sizeof(u32)); 213 len = sizeof(struct ireg_buf) * n * 2; 214 break; 215 case CUDBG_PM_INDIRECT: 216 n = sizeof(t5_pm_rx_array) / (IREG_NUM_ELEM * sizeof(u32)); 217 len = sizeof(struct ireg_buf) * n * 2; 218 break; 219 case CUDBG_TID_INFO: 220 len = sizeof(struct cudbg_tid_info_region_rev1); 221 break; 222 case CUDBG_DUMP_CONTEXT: 223 len = cudbg_dump_context_size(adap); 224 break; 225 case CUDBG_MPS_TCAM: 226 len = sizeof(struct cudbg_mps_tcam) * 227 adap->params.arch.mps_tcam_size; 228 break; 229 case CUDBG_VPD_DATA: 230 len = sizeof(struct cudbg_vpd_data); 231 break; 232 case CUDBG_LE_TCAM: 233 cudbg_fill_le_tcam_info(adap, &tcam_region); 234 len = sizeof(struct cudbg_tcam) + 235 sizeof(struct cudbg_tid_data) * tcam_region.max_tid; 236 break; 237 case CUDBG_CCTRL: 238 len = sizeof(u16) * NMTUS * NCCTRL_WIN; 239 break; 240 case CUDBG_MA_INDIRECT: 241 if (CHELSIO_CHIP_VERSION(adap->params.chip) > CHELSIO_T5) { 242 n = sizeof(t6_ma_ireg_array) / 243 (IREG_NUM_ELEM * sizeof(u32)); 244 len = sizeof(struct ireg_buf) * n * 2; 245 } 246 break; 247 case CUDBG_ULPTX_LA: 248 len = sizeof(struct cudbg_ulptx_la); 249 break; 250 case CUDBG_UP_CIM_INDIRECT: 251 n = sizeof(t5_up_cim_reg_array) / (IREG_NUM_ELEM * sizeof(u32)); 252 len = sizeof(struct ireg_buf) * n; 253 break; 254 case CUDBG_PBT_TABLE: 255 len = sizeof(struct cudbg_pbt_tables); 256 break; 257 case CUDBG_MBOX_LOG: 258 len = sizeof(struct cudbg_mbox_log) * adap->mbox_log->size; 259 break; 260 case CUDBG_HMA_INDIRECT: 261 if (CHELSIO_CHIP_VERSION(adap->params.chip) > CHELSIO_T5) { 262 n = sizeof(t6_hma_ireg_array) / 263 (IREG_NUM_ELEM * sizeof(u32)); 264 len = sizeof(struct ireg_buf) * n; 265 } 266 break; 267 default: 268 break; 269 } 270 271 return len; 272 } 273 274 u32 cxgb4_get_dump_length(struct adapter *adap, u32 flag) 275 { 276 u32 i, entity; 277 u32 len = 0; 278 279 if (flag & CXGB4_ETH_DUMP_HW) { 280 for (i = 0; i < ARRAY_SIZE(cxgb4_collect_hw_dump); i++) { 281 entity = cxgb4_collect_hw_dump[i].entity; 282 len += cxgb4_get_entity_length(adap, entity); 283 } 284 } 285 286 if (flag & CXGB4_ETH_DUMP_MEM) { 287 for (i = 0; i < ARRAY_SIZE(cxgb4_collect_mem_dump); i++) { 288 entity = cxgb4_collect_mem_dump[i].entity; 289 len += cxgb4_get_entity_length(adap, entity); 290 } 291 } 292 293 return len; 294 } 295 296 static void cxgb4_cudbg_collect_entity(struct cudbg_init *pdbg_init, 297 struct cudbg_buffer *dbg_buff, 298 const struct cxgb4_collect_entity *e_arr, 299 u32 arr_size, void *buf, u32 *tot_size) 300 { 301 struct adapter *adap = pdbg_init->adap; 302 struct cudbg_error cudbg_err = { 0 }; 303 struct cudbg_entity_hdr *entity_hdr; 304 u32 entity_size, i; 305 u32 total_size = 0; 306 int ret; 307 308 for (i = 0; i < arr_size; i++) { 309 const struct cxgb4_collect_entity *e = &e_arr[i]; 310 311 /* Skip entities that won't fit in output buffer */ 312 entity_size = cxgb4_get_entity_length(adap, e->entity); 313 if (entity_size > 314 pdbg_init->outbuf_size - *tot_size - total_size) 315 continue; 316 317 entity_hdr = cudbg_get_entity_hdr(buf, e->entity); 318 entity_hdr->entity_type = e->entity; 319 entity_hdr->start_offset = dbg_buff->offset; 320 memset(&cudbg_err, 0, sizeof(struct cudbg_error)); 321 ret = e->collect_cb(pdbg_init, dbg_buff, &cudbg_err); 322 if (ret) { 323 entity_hdr->size = 0; 324 dbg_buff->offset = entity_hdr->start_offset; 325 } else { 326 cudbg_align_debug_buffer(dbg_buff, entity_hdr); 327 } 328 329 /* Log error and continue with next entity */ 330 if (cudbg_err.sys_err) 331 ret = CUDBG_SYSTEM_ERROR; 332 333 entity_hdr->hdr_flags = ret; 334 entity_hdr->sys_err = cudbg_err.sys_err; 335 entity_hdr->sys_warn = cudbg_err.sys_warn; 336 total_size += entity_hdr->size; 337 } 338 339 *tot_size += total_size; 340 } 341 342 int cxgb4_cudbg_collect(struct adapter *adap, void *buf, u32 *buf_size, 343 u32 flag) 344 { 345 struct cudbg_init cudbg_init = { 0 }; 346 struct cudbg_buffer dbg_buff = { 0 }; 347 u32 size, min_size, total_size = 0; 348 struct cudbg_hdr *cudbg_hdr; 349 350 size = *buf_size; 351 352 cudbg_init.adap = adap; 353 cudbg_init.outbuf = buf; 354 cudbg_init.outbuf_size = size; 355 356 dbg_buff.data = buf; 357 dbg_buff.size = size; 358 dbg_buff.offset = 0; 359 360 cudbg_hdr = (struct cudbg_hdr *)buf; 361 cudbg_hdr->signature = CUDBG_SIGNATURE; 362 cudbg_hdr->hdr_len = sizeof(struct cudbg_hdr); 363 cudbg_hdr->major_ver = CUDBG_MAJOR_VERSION; 364 cudbg_hdr->minor_ver = CUDBG_MINOR_VERSION; 365 cudbg_hdr->max_entities = CUDBG_MAX_ENTITY; 366 cudbg_hdr->chip_ver = adap->params.chip; 367 cudbg_hdr->dump_type = CUDBG_DUMP_TYPE_MINI; 368 cudbg_hdr->compress_type = CUDBG_COMPRESSION_NONE; 369 370 min_size = sizeof(struct cudbg_hdr) + 371 sizeof(struct cudbg_entity_hdr) * 372 cudbg_hdr->max_entities; 373 if (size < min_size) 374 return -ENOMEM; 375 376 dbg_buff.offset += min_size; 377 total_size = dbg_buff.offset; 378 379 if (flag & CXGB4_ETH_DUMP_HW) 380 cxgb4_cudbg_collect_entity(&cudbg_init, &dbg_buff, 381 cxgb4_collect_hw_dump, 382 ARRAY_SIZE(cxgb4_collect_hw_dump), 383 buf, 384 &total_size); 385 386 if (flag & CXGB4_ETH_DUMP_MEM) 387 cxgb4_cudbg_collect_entity(&cudbg_init, &dbg_buff, 388 cxgb4_collect_mem_dump, 389 ARRAY_SIZE(cxgb4_collect_mem_dump), 390 buf, 391 &total_size); 392 393 cudbg_hdr->data_len = total_size; 394 *buf_size = total_size; 395 return 0; 396 } 397 398 void cxgb4_init_ethtool_dump(struct adapter *adapter) 399 { 400 adapter->eth_dump.flag = CXGB4_ETH_DUMP_NONE; 401 adapter->eth_dump.version = adapter->params.fw_vers; 402 adapter->eth_dump.len = 0; 403 } 404