1 /*- 2 * Copyright (c) 2017 Broadcom. All rights reserved. 3 * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 * 31 * $FreeBSD$ 32 */ 33 34 /** 35 * @file 36 * generate FC ddump 37 * 38 */ 39 40 #include "ocs.h" 41 #include "ocs_ddump.h" 42 43 #define DEFAULT_SAVED_DUMP_SIZE (4*1024*1024) 44 45 void hw_queue_ddump(ocs_textbuf_t *textbuf, ocs_hw_t *hw); 46 47 /** 48 * @brief Generate sli4 queue ddump 49 * 50 * Generates sli4 queue ddump data 51 * 52 * @param textbuf pointer to text buffer 53 * @param name name of SLI4 queue 54 * @param hw pointer HW context 55 * @param q pointer to SLI4 queues array 56 * @param q_count count of SLI4 queues 57 * @param qentries number of SLI4 queue entries to dump 58 * 59 * @return none 60 */ 61 62 static void 63 ocs_ddump_sli4_queue(ocs_textbuf_t *textbuf, const char *name, ocs_hw_t *hw, sli4_queue_t *q, uint32_t q_count, uint32_t qentries) 64 { 65 uint32_t i; 66 67 for (i = 0; i < q_count; i ++, q ++) { 68 ocs_ddump_section(textbuf, name, i); 69 ocs_ddump_value(textbuf, "index", "%d", q->index); 70 ocs_ddump_value(textbuf, "size", "%d", q->size); 71 ocs_ddump_value(textbuf, "length", "%d", q->length); 72 ocs_ddump_value(textbuf, "n_posted", "%d", q->n_posted); 73 ocs_ddump_value(textbuf, "id", "%d", q->id); 74 ocs_ddump_value(textbuf, "type", "%d", q->type); 75 ocs_ddump_value(textbuf, "proc_limit", "%d", q->proc_limit); 76 ocs_ddump_value(textbuf, "posted_limit", "%d", q->posted_limit); 77 ocs_ddump_value(textbuf, "max_num_processed", "%d", q->max_num_processed); 78 ocs_ddump_value(textbuf, "max_process_time", "%ld", (unsigned long)q->max_process_time); 79 ocs_ddump_value(textbuf, "virt_addr", "%p", q->dma.virt); 80 ocs_ddump_value(textbuf, "phys_addr", "%lx", (unsigned long)q->dma.phys); 81 82 /* queue-specific information */ 83 switch (q->type) { 84 case SLI_QTYPE_MQ: 85 ocs_ddump_value(textbuf, "r_idx", "%d", q->u.r_idx); 86 break; 87 case SLI_QTYPE_CQ: 88 ocs_ddump_value(textbuf, "is_mq", "%d", q->u.flag.is_mq); 89 break; 90 case SLI_QTYPE_WQ: 91 break; 92 case SLI_QTYPE_RQ: { 93 uint32_t i; 94 uint32_t j; 95 uint32_t rqe_count = 0; 96 hw_rq_t *rq; 97 98 ocs_ddump_value(textbuf, "is_hdr", "%d", q->u.flag.is_hdr); 99 ocs_ddump_value(textbuf, "rq_batch", "%d", q->u.flag.rq_batch); 100 101 /* loop through RQ tracker to see how many RQEs were produced */ 102 for (i = 0; i < hw->hw_rq_count; i++) { 103 rq = hw->hw_rq[i]; 104 for (j = 0; j < rq->entry_count; j++) { 105 if (rq->rq_tracker[j] != NULL) { 106 rqe_count++; 107 } 108 } 109 } 110 ocs_ddump_value(textbuf, "rqes_produced", "%d", rqe_count); 111 break; 112 } 113 } 114 ocs_ddump_queue_entries(textbuf, q->dma.virt, q->size, q->length, 115 ((q->type == SLI_QTYPE_MQ) ? q->u.r_idx : q->index), 116 qentries); 117 ocs_ddump_endsection(textbuf, name, i); 118 } 119 } 120 121 122 /** 123 * @brief Generate SLI4 ddump 124 * 125 * Generates sli4 ddump 126 * 127 * @param textbuf pointer to text buffer 128 * @param sli4 pointer SLI context 129 * @param qtype SLI4 queue type 130 * 131 * @return none 132 */ 133 134 static void 135 ocs_ddump_sli_q_fields(ocs_textbuf_t *textbuf, sli4_t *sli4, sli4_qtype_e qtype) 136 { 137 char * q_desc; 138 139 switch(qtype) { 140 case SLI_QTYPE_EQ: q_desc = "EQ"; break; 141 case SLI_QTYPE_CQ: q_desc = "CQ"; break; 142 case SLI_QTYPE_MQ: q_desc = "MQ"; break; 143 case SLI_QTYPE_WQ: q_desc = "WQ"; break; 144 case SLI_QTYPE_RQ: q_desc = "RQ"; break; 145 default: q_desc = "unknown"; break; 146 } 147 148 ocs_ddump_section(textbuf, q_desc, qtype); 149 150 ocs_ddump_value(textbuf, "max_qcount", "%d", sli4->config.max_qcount[qtype]); 151 ocs_ddump_value(textbuf, "max_qentries", "%d", sli4->config.max_qentries[qtype]); 152 ocs_ddump_value(textbuf, "qpage_count", "%d", sli4->config.qpage_count[qtype]); 153 ocs_ddump_endsection(textbuf, q_desc, qtype); 154 } 155 156 157 /** 158 * @brief Generate SLI4 ddump 159 * 160 * Generates sli4 ddump 161 * 162 * @param textbuf pointer to text buffer 163 * @param sli4 pointer SLI context 164 * 165 * @return none 166 */ 167 168 static void 169 ocs_ddump_sli(ocs_textbuf_t *textbuf, sli4_t *sli4) 170 { 171 sli4_sgl_chaining_params_t *cparams = &sli4->config.sgl_chaining_params; 172 const char *p; 173 174 ocs_ddump_section(textbuf, "sli4", 0); 175 176 ocs_ddump_value(textbuf, "sli_rev", "%d", sli4->sli_rev); 177 ocs_ddump_value(textbuf, "sli_family", "%d", sli4->sli_family); 178 ocs_ddump_value(textbuf, "if_type", "%d", sli4->if_type); 179 180 switch(sli4->asic_type) { 181 case SLI4_ASIC_TYPE_BE3: p = "BE3"; break; 182 case SLI4_ASIC_TYPE_SKYHAWK: p = "Skyhawk"; break; 183 case SLI4_ASIC_TYPE_LANCER: p = "Lancer"; break; 184 case SLI4_ASIC_TYPE_LANCERG6: p = "LancerG6"; break; 185 default: p = "unknown"; break; 186 } 187 ocs_ddump_value(textbuf, "asic_type", "%s", p); 188 189 switch(sli4->asic_rev) { 190 case SLI4_ASIC_REV_FPGA: p = "fpga"; break; 191 case SLI4_ASIC_REV_A0: p = "A0"; break; 192 case SLI4_ASIC_REV_A1: p = "A1"; break; 193 case SLI4_ASIC_REV_A2: p = "A2"; break; 194 case SLI4_ASIC_REV_A3: p = "A3"; break; 195 case SLI4_ASIC_REV_B0: p = "B0"; break; 196 case SLI4_ASIC_REV_C0: p = "C0"; break; 197 case SLI4_ASIC_REV_D0: p = "D0"; break; 198 default: p = "unknown"; break; 199 } 200 ocs_ddump_value(textbuf, "asic_rev", "%s", p); 201 202 ocs_ddump_value(textbuf, "e_d_tov", "%d", sli4->config.e_d_tov); 203 ocs_ddump_value(textbuf, "r_a_tov", "%d", sli4->config.r_a_tov); 204 ocs_ddump_value(textbuf, "link_module_type", "%d", sli4->config.link_module_type); 205 ocs_ddump_value(textbuf, "rq_batch", "%d", sli4->config.rq_batch); 206 ocs_ddump_value(textbuf, "topology", "%d", sli4->config.topology); 207 ocs_ddump_value(textbuf, "wwpn", "%02x%02x%02x%02x%02x%02x%02x%02x", 208 sli4->config.wwpn[0], 209 sli4->config.wwpn[1], 210 sli4->config.wwpn[2], 211 sli4->config.wwpn[3], 212 sli4->config.wwpn[4], 213 sli4->config.wwpn[5], 214 sli4->config.wwpn[6], 215 sli4->config.wwpn[7]); 216 ocs_ddump_value(textbuf, "wwnn", "%02x%02x%02x%02x%02x%02x%02x%02x", 217 sli4->config.wwnn[0], 218 sli4->config.wwnn[1], 219 sli4->config.wwnn[2], 220 sli4->config.wwnn[3], 221 sli4->config.wwnn[4], 222 sli4->config.wwnn[5], 223 sli4->config.wwnn[6], 224 sli4->config.wwnn[7]); 225 ocs_ddump_value(textbuf, "fw_rev0", "%d", sli4->config.fw_rev[0]); 226 ocs_ddump_value(textbuf, "fw_rev1", "%d", sli4->config.fw_rev[1]); 227 ocs_ddump_value(textbuf, "fw_name0", "%s", (char*)sli4->config.fw_name[0]); 228 ocs_ddump_value(textbuf, "fw_name1", "%s", (char*)sli4->config.fw_name[1]); 229 ocs_ddump_value(textbuf, "hw_rev0", "%x", sli4->config.hw_rev[0]); 230 ocs_ddump_value(textbuf, "hw_rev1", "%x", sli4->config.hw_rev[1]); 231 ocs_ddump_value(textbuf, "hw_rev2", "%x", sli4->config.hw_rev[2]); 232 ocs_ddump_value(textbuf, "sge_supported_length", "%x", sli4->config.sge_supported_length); 233 ocs_ddump_value(textbuf, "sgl_page_sizes", "%x", sli4->config.sgl_page_sizes); 234 ocs_ddump_value(textbuf, "max_sgl_pages", "%x", sli4->config.max_sgl_pages); 235 ocs_ddump_value(textbuf, "high_login_mode", "%x", sli4->config.high_login_mode); 236 ocs_ddump_value(textbuf, "sgl_pre_registered", "%x", sli4->config.sgl_pre_registered); 237 ocs_ddump_value(textbuf, "sgl_pre_registration_required", "%x", sli4->config.sgl_pre_registration_required); 238 239 ocs_ddump_value(textbuf, "sgl_chaining_capable", "%x", cparams->chaining_capable); 240 ocs_ddump_value(textbuf, "frag_num_field_offset", "%x", cparams->frag_num_field_offset); 241 ocs_ddump_value(textbuf, "frag_num_field_mask", "%016llx", (unsigned long long)cparams->frag_num_field_mask); 242 ocs_ddump_value(textbuf, "sgl_index_field_offset", "%x", cparams->sgl_index_field_offset); 243 ocs_ddump_value(textbuf, "sgl_index_field_mask", "%016llx", (unsigned long long)cparams->sgl_index_field_mask); 244 ocs_ddump_value(textbuf, "chain_sge_initial_value_lo", "%x", cparams->chain_sge_initial_value_lo); 245 ocs_ddump_value(textbuf, "chain_sge_initial_value_hi", "%x", cparams->chain_sge_initial_value_hi); 246 247 ocs_ddump_value(textbuf, "max_vfi", "%d", sli_get_max_rsrc(sli4, SLI_RSRC_FCOE_VFI)); 248 ocs_ddump_value(textbuf, "max_vpi", "%d", sli_get_max_rsrc(sli4, SLI_RSRC_FCOE_VPI)); 249 ocs_ddump_value(textbuf, "max_rpi", "%d", sli_get_max_rsrc(sli4, SLI_RSRC_FCOE_RPI)); 250 ocs_ddump_value(textbuf, "max_xri", "%d", sli_get_max_rsrc(sli4, SLI_RSRC_FCOE_XRI)); 251 ocs_ddump_value(textbuf, "max_fcfi", "%d", sli_get_max_rsrc(sli4, SLI_RSRC_FCOE_FCFI)); 252 253 ocs_ddump_sli_q_fields(textbuf, sli4, SLI_QTYPE_EQ); 254 ocs_ddump_sli_q_fields(textbuf, sli4, SLI_QTYPE_CQ); 255 ocs_ddump_sli_q_fields(textbuf, sli4, SLI_QTYPE_MQ); 256 ocs_ddump_sli_q_fields(textbuf, sli4, SLI_QTYPE_WQ); 257 ocs_ddump_sli_q_fields(textbuf, sli4, SLI_QTYPE_RQ); 258 259 ocs_ddump_endsection(textbuf, "sli4", 0); 260 } 261 262 263 /** 264 * @brief Dump HW IO 265 * 266 * Dump HW IO 267 * 268 * @param textbuf pointer to text buffer 269 * @param io pointer to HW IO object 270 * 271 * @return none 272 */ 273 274 static void 275 ocs_ddump_hw_io(ocs_textbuf_t *textbuf, ocs_hw_io_t *io) 276 { 277 ocs_assert(io); 278 279 ocs_ddump_section(textbuf, "hw_io", io->indicator); 280 281 ocs_ddump_value(textbuf, "state", "%d", io->state); 282 ocs_ddump_value(textbuf, "xri", "0x%x", io->indicator); 283 ocs_ddump_value(textbuf, "tag", "0x%x", io->reqtag); 284 ocs_ddump_value(textbuf, "abort_reqtag", "0x%x", io->abort_reqtag); 285 ocs_ddump_value(textbuf, "ref_count", "%d", ocs_ref_read_count(&io->ref)); 286 287 /* just to make it obvious, display abort bit from tag */ 288 ocs_ddump_value(textbuf, "abort", "0x%x", io->abort_in_progress); 289 ocs_ddump_value(textbuf, "wq_index", "%d", (io->wq == NULL ? 0xffff : io->wq->instance)); 290 ocs_ddump_value(textbuf, "type", "%d", io->type); 291 ocs_ddump_value(textbuf, "xbusy", "%d", io->xbusy); 292 ocs_ddump_value(textbuf, "active_wqe_link", "%d", ocs_list_on_list(&io->wqe_link)); 293 ocs_ddump_value(textbuf, "def_sgl_count", "%d", io->def_sgl_count); 294 ocs_ddump_value(textbuf, "n_sge", "%d", io->n_sge); 295 ocs_ddump_value(textbuf, "has_ovfl_sgl", "%s", (io->ovfl_sgl != NULL ? "TRUE" : "FALSE")); 296 ocs_ddump_value(textbuf, "has_ovfl_io", "%s", (io->ovfl_io != NULL ? "TRUE" : "FALSE")); 297 298 ocs_ddump_endsection(textbuf, "hw_io", io->indicator); 299 } 300 301 #if defined(OCS_DEBUG_QUEUE_HISTORY) 302 303 /** 304 * @brief Generate queue history ddump 305 * 306 * @param textbuf pointer to text buffer 307 * @param q_hist Pointer to queue history object. 308 */ 309 static void 310 ocs_ddump_queue_history(ocs_textbuf_t *textbuf, ocs_hw_q_hist_t *q_hist) 311 { 312 uint32_t x; 313 314 ocs_ddump_section(textbuf, "q_hist", 0); 315 ocs_ddump_value(textbuf, "count", "%ld", OCS_Q_HIST_SIZE); 316 ocs_ddump_value(textbuf, "index", "%d", q_hist->q_hist_index); 317 318 if (q_hist->q_hist == NULL) { 319 ocs_ddump_section(textbuf, "history", 0); 320 ocs_textbuf_printf(textbuf, "No history available\n"); 321 ocs_ddump_endsection(textbuf, "history", 0); 322 ocs_ddump_endsection(textbuf, "q_hist", 0); 323 return; 324 } 325 326 /* start from last entry and go backwards */ 327 ocs_textbuf_printf(textbuf, "<history>\n"); 328 ocs_textbuf_printf(textbuf, "(newest first):\n"); 329 330 ocs_lock(&q_hist->q_hist_lock); 331 x = ocs_queue_history_prev_index(q_hist->q_hist_index); 332 do { 333 int i; 334 ocs_q_hist_ftr_t ftr; 335 uint32_t mask; 336 337 338 /* footer's mask indicates what words were captured */ 339 ftr.word = q_hist->q_hist[x]; 340 mask = ftr.s.mask; 341 i = 0; 342 343 /* if we've encountered a mask of 0, must be done */ 344 if (mask == 0) { 345 break; 346 } 347 348 /* display entry type */ 349 ocs_textbuf_printf(textbuf, "%s:\n", 350 ocs_queue_history_type_name(ftr.s.type)); 351 352 if (ocs_queue_history_timestamp_enabled()) { 353 uint64_t tsc_value; 354 x = ocs_queue_history_prev_index(x); 355 tsc_value = ((q_hist->q_hist[x]) & 0x00000000FFFFFFFFull); 356 x = ocs_queue_history_prev_index(x); 357 tsc_value |= (((uint64_t)q_hist->q_hist[x] << 32) & 0xFFFFFFFF00000000ull); 358 ocs_textbuf_printf(textbuf, " t: %" PRIu64 "\n", tsc_value); 359 } 360 361 if (ocs_queue_history_q_info_enabled()) { 362 if (ftr.s.type == OCS_Q_HIST_TYPE_CWQE || 363 ftr.s.type == OCS_Q_HIST_TYPE_CXABT || 364 ftr.s.type == OCS_Q_HIST_TYPE_WQE) { 365 x = ocs_queue_history_prev_index(x); 366 ocs_textbuf_printf(textbuf, " qid=0x%x idx=0x%x\n", 367 ((q_hist->q_hist[x] >> 16) & 0xFFFF), 368 ((q_hist->q_hist[x] >> 0) & 0xFFFF)); 369 } 370 } 371 372 while (mask) { 373 if ((mask & 1) && (x != q_hist->q_hist_index)){ 374 /* get next word */ 375 x = ocs_queue_history_prev_index(x); 376 ocs_textbuf_printf(textbuf, " [%d]=%x\n", 377 i, q_hist->q_hist[x]); 378 } 379 mask = (mask >> 1UL); 380 i++; 381 } 382 383 /* go backwards to next element */ 384 x = ocs_queue_history_prev_index(x); 385 } while (x != ocs_queue_history_prev_index(q_hist->q_hist_index)); 386 ocs_unlock(&q_hist->q_hist_lock); 387 388 ocs_textbuf_printf(textbuf, "</history>\n"); 389 ocs_ddump_endsection(textbuf, "q_hist", 0); 390 } 391 #endif 392 393 /** 394 * @brief Generate hw ddump 395 * 396 * Generates hw ddump 397 * 398 * @param textbuf pointer to text buffer 399 * @param hw pointer HW context 400 * @param flags ddump flags 401 * @param qentries number of qentries to dump 402 * 403 * @return none 404 */ 405 406 static void 407 ocs_ddump_hw(ocs_textbuf_t *textbuf, ocs_hw_t *hw, uint32_t flags, uint32_t qentries) 408 { 409 ocs_t *ocs = hw->os; 410 uint32_t cnt = 0; 411 ocs_hw_io_t *io = NULL; 412 uint32_t i; 413 uint32_t j; 414 uint32_t max_rpi = sli_get_max_rsrc(&hw->sli, SLI_RSRC_FCOE_RPI); 415 416 ocs_assert(ocs); 417 418 ocs_ddump_section(textbuf, "hw", ocs->instance_index); 419 420 /* device specific information */ 421 switch(hw->sli.if_type) { 422 case 0: 423 ocs_ddump_value(textbuf, "uerr_mask_hi", "%08x", 424 sli_reg_read(&hw->sli, SLI4_REG_UERR_MASK_HI)); 425 ocs_ddump_value(textbuf, "uerr_mask_lo", "%08x", 426 sli_reg_read(&hw->sli, SLI4_REG_UERR_MASK_LO)); 427 ocs_ddump_value(textbuf, "uerr_status_hi", "%08x", 428 sli_reg_read(&hw->sli, SLI4_REG_UERR_STATUS_HI)); 429 ocs_ddump_value(textbuf, "uerr_status_lo", "%08x", 430 sli_reg_read(&hw->sli, SLI4_REG_UERR_STATUS_LO)); 431 break; 432 case 2: 433 ocs_ddump_value(textbuf, "sliport_status", "%08x", 434 sli_reg_read(&hw->sli, SLI4_REG_SLIPORT_STATUS)); 435 ocs_ddump_value(textbuf, "sliport_error1", "%08x", 436 sli_reg_read(&hw->sli, SLI4_REG_SLIPORT_ERROR1)); 437 ocs_ddump_value(textbuf, "sliport_error2", "%08x", 438 sli_reg_read(&hw->sli, SLI4_REG_SLIPORT_ERROR2)); 439 break; 440 } 441 442 ocs_ddump_value(textbuf, "link_status", "%d", hw->link.status); 443 ocs_ddump_value(textbuf, "link_speed", "%d", hw->link.speed); 444 ocs_ddump_value(textbuf, "link_topology", "%d", hw->link.topology); 445 ocs_ddump_value(textbuf, "state", "%d", hw->state); 446 ocs_ddump_value(textbuf, "io_alloc_failed_count", "%d", ocs_atomic_read(&hw->io_alloc_failed_count)); 447 ocs_ddump_value(textbuf, "n_io", "%d", hw->config.n_io); 448 449 ocs_ddump_value(textbuf, "queue_topology", "%s", hw->config.queue_topology); 450 ocs_ddump_value(textbuf, "rq_selection_policy", "%d", hw->config.rq_selection_policy); 451 ocs_ddump_value(textbuf, "rr_quanta", "%d", hw->config.rr_quanta); 452 for (i = 0; i < ARRAY_SIZE(hw->config.filter_def); i++) { 453 ocs_ddump_value(textbuf, "filter_def", "%08X", hw->config.filter_def[i]); 454 } 455 ocs_ddump_value(textbuf, "n_eq", "%d", hw->eq_count); 456 ocs_ddump_value(textbuf, "n_cq", "%d", hw->cq_count); 457 ocs_ddump_value(textbuf, "n_mq", "%d", hw->mq_count); 458 ocs_ddump_value(textbuf, "n_rq", "%d", hw->rq_count); 459 ocs_ddump_value(textbuf, "n_wq", "%d", hw->wq_count); 460 ocs_ddump_value(textbuf, "n_sgl", "%d", hw->config.n_sgl); 461 462 ocs_ddump_sli(textbuf, &hw->sli); 463 464 ocs_ddump_sli4_queue(textbuf, "wq", hw, hw->wq, hw->wq_count, 465 ((flags & OCS_DDUMP_FLAGS_WQES) ? qentries : 0)); 466 ocs_ddump_sli4_queue(textbuf, "rq", hw, hw->rq, hw->rq_count, 467 ((flags & OCS_DDUMP_FLAGS_RQES) ? qentries : 0)); 468 ocs_ddump_sli4_queue(textbuf, "mq", hw, hw->mq, hw->mq_count, 469 ((flags & OCS_DDUMP_FLAGS_MQES) ? qentries : 0)); 470 ocs_ddump_sli4_queue(textbuf, "cq", hw, hw->cq, hw->cq_count, 471 ((flags & OCS_DDUMP_FLAGS_CQES) ? qentries : 0)); 472 ocs_ddump_sli4_queue(textbuf, "eq", hw, hw->eq, hw->eq_count, 473 ((flags & OCS_DDUMP_FLAGS_EQES) ? qentries : 0)); 474 475 /* dump the IO quarantine list */ 476 for (i = 0; i < hw->wq_count; i++) { 477 ocs_ddump_section(textbuf, "io_quarantine", i); 478 ocs_ddump_value(textbuf, "quarantine_index", "%d", hw->hw_wq[i]->quarantine_info.quarantine_index); 479 for (j = 0; j < OCS_HW_QUARANTINE_QUEUE_DEPTH; j++) { 480 if (hw->hw_wq[i]->quarantine_info.quarantine_ios[j] != NULL) { 481 ocs_ddump_hw_io(textbuf, hw->hw_wq[i]->quarantine_info.quarantine_ios[j]); 482 } 483 } 484 ocs_ddump_endsection(textbuf, "io_quarantine", i); 485 } 486 487 ocs_ddump_section(textbuf, "workaround", ocs->instance_index); 488 ocs_ddump_value(textbuf, "fwrev", "%08llx", (unsigned long long)hw->workaround.fwrev); 489 ocs_ddump_endsection(textbuf, "workaround", ocs->instance_index); 490 491 ocs_lock(&hw->io_lock); 492 ocs_ddump_section(textbuf, "io_inuse", ocs->instance_index); 493 ocs_list_foreach(&hw->io_inuse, io) { 494 ocs_ddump_hw_io(textbuf, io); 495 } 496 ocs_ddump_endsection(textbuf, "io_inuse", ocs->instance_index); 497 498 ocs_ddump_section(textbuf, "io_wait_free", ocs->instance_index); 499 ocs_list_foreach(&hw->io_wait_free, io) { 500 ocs_ddump_hw_io(textbuf, io); 501 } 502 ocs_ddump_endsection(textbuf, "io_wait_free", ocs->instance_index); 503 ocs_ddump_section(textbuf, "io_free", ocs->instance_index); 504 ocs_list_foreach(&hw->io_free, io) { 505 if (io->xbusy) { 506 /* only display free ios if they're active */ 507 ocs_ddump_hw_io(textbuf, io); 508 } 509 cnt++; 510 } 511 ocs_ddump_endsection(textbuf, "io_free", ocs->instance_index); 512 ocs_ddump_value(textbuf, "ios_free", "%d", cnt); 513 514 ocs_ddump_value(textbuf, "sec_hio_wait_count", "%d", hw->sec_hio_wait_count); 515 ocs_unlock(&hw->io_lock); 516 517 /* now check the IOs not in a list; i.e. sequence coalescing xris */ 518 ocs_ddump_section(textbuf, "port_owned_ios", ocs->instance_index); 519 for (i = 0; i < hw->config.n_io; i++) { 520 io = hw->io[i]; 521 if (!io) 522 continue; 523 524 if (ocs_hw_is_xri_port_owned(hw, io->indicator)) { 525 if (ocs_ref_read_count(&io->ref)) { 526 /* only display free ios if they're active */ 527 ocs_ddump_hw_io(textbuf, io); 528 } 529 } 530 } 531 ocs_ddump_endsection(textbuf, "port_owned_ios", ocs->instance_index); 532 533 ocs_textbuf_printf(textbuf, "<rpi_ref>"); 534 for (i = 0; i < max_rpi; i++) { 535 if (ocs_atomic_read(&hw->rpi_ref[i].rpi_attached) || 536 ocs_atomic_read(&hw->rpi_ref[i].rpi_count) ) { 537 ocs_textbuf_printf(textbuf, "[%d] att=%d cnt=%d\n", i, 538 ocs_atomic_read(&hw->rpi_ref[i].rpi_attached), 539 ocs_atomic_read(&hw->rpi_ref[i].rpi_count)); 540 } 541 } 542 ocs_textbuf_printf(textbuf, "</rpi_ref>"); 543 544 for (i = 0; i < hw->wq_count; i++) { 545 ocs_ddump_value(textbuf, "wq_submit", "%d", hw->tcmd_wq_submit[i]); 546 } 547 for (i = 0; i < hw->wq_count; i++) { 548 ocs_ddump_value(textbuf, "wq_complete", "%d", hw->tcmd_wq_complete[i]); 549 } 550 551 hw_queue_ddump(textbuf, hw); 552 553 ocs_ddump_endsection(textbuf, "hw", ocs->instance_index); 554 555 } 556 557 void 558 hw_queue_ddump(ocs_textbuf_t *textbuf, ocs_hw_t *hw) 559 { 560 hw_eq_t *eq; 561 hw_cq_t *cq; 562 hw_q_t *q; 563 hw_mq_t *mq; 564 hw_wq_t *wq; 565 hw_rq_t *rq; 566 567 ocs_ddump_section(textbuf, "hw_queue", 0); 568 ocs_list_foreach(&hw->eq_list, eq) { 569 ocs_ddump_section(textbuf, "eq", eq->instance); 570 ocs_ddump_value(textbuf, "queue-id", "%d", eq->queue->id); 571 OCS_STAT(ocs_ddump_value(textbuf, "use_count", "%d", eq->use_count)); 572 ocs_list_foreach(&eq->cq_list, cq) { 573 ocs_ddump_section(textbuf, "cq", cq->instance); 574 ocs_ddump_value(textbuf, "queue-id", "%d", cq->queue->id); 575 OCS_STAT(ocs_ddump_value(textbuf, "use_count", "%d", cq->use_count)); 576 ocs_list_foreach(&cq->q_list, q) { 577 switch(q->type) { 578 case SLI_QTYPE_MQ: 579 mq = (hw_mq_t *) q; 580 ocs_ddump_section(textbuf, "mq", mq->instance); 581 ocs_ddump_value(textbuf, "queue-id", "%d", mq->queue->id); 582 OCS_STAT(ocs_ddump_value(textbuf, "use_count", "%d", mq->use_count)); 583 ocs_ddump_endsection(textbuf, "mq", mq->instance); 584 break; 585 case SLI_QTYPE_WQ: 586 wq = (hw_wq_t *) q; 587 ocs_ddump_section(textbuf, "wq", wq->instance); 588 ocs_ddump_value(textbuf, "queue-id", "%d", wq->queue->id); 589 OCS_STAT(ocs_ddump_value(textbuf, "use_count", "%d", wq->use_count)); 590 ocs_ddump_value(textbuf, "wqec_count", "%d", wq->wqec_count); 591 ocs_ddump_value(textbuf, "free_count", "%d", wq->free_count); 592 OCS_STAT(ocs_ddump_value(textbuf, "wq_pending_count", "%d", 593 wq->wq_pending_count)); 594 ocs_ddump_endsection(textbuf, "wq", wq->instance); 595 break; 596 case SLI_QTYPE_RQ: 597 rq = (hw_rq_t *) q; 598 ocs_ddump_section(textbuf, "rq", rq->instance); 599 OCS_STAT(ocs_ddump_value(textbuf, "use_count", "%d", rq->use_count)); 600 ocs_ddump_value(textbuf, "filter_mask", "%d", rq->filter_mask); 601 if (rq->hdr != NULL) { 602 ocs_ddump_value(textbuf, "hdr-id", "%d", rq->hdr->id); 603 OCS_STAT(ocs_ddump_value(textbuf, "hdr_use_count", "%d", rq->hdr_use_count)); 604 } 605 if (rq->first_burst != NULL) { 606 OCS_STAT(ocs_ddump_value(textbuf, "fb-id", "%d", rq->first_burst->id)); 607 OCS_STAT(ocs_ddump_value(textbuf, "fb_use_count", "%d", rq->fb_use_count)); 608 } 609 if (rq->data != NULL) { 610 OCS_STAT(ocs_ddump_value(textbuf, "payload-id", "%d", rq->data->id)); 611 OCS_STAT(ocs_ddump_value(textbuf, "payload_use_count", "%d", rq->payload_use_count)); 612 } 613 ocs_ddump_endsection(textbuf, "rq", rq->instance); 614 break; 615 default: 616 break; 617 } 618 } 619 ocs_ddump_endsection(textbuf, "cq", cq->instance); 620 } 621 ocs_ddump_endsection(textbuf, "eq", eq->instance); 622 } 623 ocs_ddump_endsection(textbuf, "hw_queue", 0); 624 } 625 626 /** 627 * @brief Initiate ddump 628 * 629 * Traverses the ocs/domain/port/node/io data structures to generate a driver 630 * dump. 631 * 632 * @param ocs pointer to device context 633 * @param textbuf pointer to text buffer 634 * @param flags ddump flags 635 * @param qentries number of queue entries to dump 636 * 637 * @return Returns 0 on success, or a negative value on failure. 638 */ 639 640 int 641 ocs_ddump(ocs_t *ocs, ocs_textbuf_t *textbuf, uint32_t flags, uint32_t qentries) 642 { 643 ocs_xport_t *xport = ocs->xport; 644 ocs_domain_t *domain; 645 uint32_t instance; 646 ocs_vport_spec_t *vport; 647 ocs_io_t *io; 648 int retval = 0; 649 uint32_t i; 650 651 ocs_ddump_startfile(textbuf); 652 653 ocs_ddump_section(textbuf, "ocs", ocs->instance_index); 654 655 ocs_ddump_section(textbuf, "ocs_os", ocs->instance_index); 656 #ifdef OCS_ENABLE_NUMA_SUPPORT 657 ocs_ddump_value(textbuf, "numa_node", "%d", ocs->ocs_os.numa_node); 658 #endif 659 ocs_ddump_endsection(textbuf, "ocs_os", ocs->instance_index); 660 661 ocs_ddump_value(textbuf, "drv_name", "%s", DRV_NAME); 662 ocs_ddump_value(textbuf, "drv_version", "%s", DRV_VERSION); 663 ocs_ddump_value(textbuf, "display_name", "%s", ocs->display_name); 664 ocs_ddump_value(textbuf, "enable_ini", "%d", ocs->enable_ini); 665 ocs_ddump_value(textbuf, "enable_tgt", "%d", ocs->enable_tgt); 666 ocs_ddump_value(textbuf, "nodes_count", "%d", xport->nodes_count); 667 ocs_ddump_value(textbuf, "enable_hlm", "%d", ocs->enable_hlm); 668 ocs_ddump_value(textbuf, "hlm_group_size", "%d", ocs->hlm_group_size); 669 ocs_ddump_value(textbuf, "auto_xfer_rdy_size", "%d", ocs->auto_xfer_rdy_size); 670 ocs_ddump_value(textbuf, "io_alloc_failed_count", "%d", ocs_atomic_read(&xport->io_alloc_failed_count)); 671 ocs_ddump_value(textbuf, "io_active_count", "%d", ocs_atomic_read(&xport->io_active_count)); 672 ocs_ddump_value(textbuf, "io_pending_count", "%d", ocs_atomic_read(&xport->io_pending_count)); 673 ocs_ddump_value(textbuf, "io_total_alloc", "%d", ocs_atomic_read(&xport->io_total_alloc)); 674 ocs_ddump_value(textbuf, "io_total_free", "%d", ocs_atomic_read(&xport->io_total_free)); 675 ocs_ddump_value(textbuf, "io_total_pending", "%d", ocs_atomic_read(&xport->io_total_pending)); 676 ocs_ddump_value(textbuf, "io_pending_recursing", "%d", ocs_atomic_read(&xport->io_pending_recursing)); 677 ocs_ddump_value(textbuf, "max_isr_time_msec", "%d", ocs->max_isr_time_msec); 678 for (i = 0; i < SLI4_MAX_FCFI; i++) { 679 ocs_lock(&xport->fcfi[i].pend_frames_lock); 680 if (!ocs_list_empty(&xport->fcfi[i].pend_frames)) { 681 ocs_hw_sequence_t *frame; 682 ocs_ddump_section(textbuf, "pending_frames", i); 683 ocs_ddump_value(textbuf, "hold_frames", "%d", xport->fcfi[i].hold_frames); 684 ocs_list_foreach(&xport->fcfi[i].pend_frames, frame) { 685 fc_header_t *hdr; 686 char buf[128]; 687 688 hdr = frame->header->dma.virt; 689 ocs_snprintf(buf, sizeof(buf), "%02x/%04x/%04x len %zu", 690 hdr->r_ctl, ocs_be16toh(hdr->ox_id), ocs_be16toh(hdr->rx_id), 691 frame->payload->dma.len); 692 ocs_ddump_value(textbuf, "frame", "%s", buf); 693 } 694 ocs_ddump_endsection(textbuf, "pending_frames", i); 695 } 696 ocs_unlock(&xport->fcfi[i].pend_frames_lock); 697 } 698 699 ocs_lock(&xport->io_pending_lock); 700 ocs_ddump_section(textbuf, "io_pending_list", ocs->instance_index); 701 ocs_list_foreach(&xport->io_pending_list, io) { 702 ocs_ddump_io(textbuf, io); 703 } 704 ocs_ddump_endsection(textbuf, "io_pending_list", ocs->instance_index); 705 ocs_unlock(&xport->io_pending_lock); 706 707 #if defined(ENABLE_LOCK_DEBUG) 708 /* Dump the lock list */ 709 ocs_ddump_section(textbuf, "locks", 0); 710 ocs_lock(&ocs->ocs_os.locklist_lock); { 711 ocs_lock_t *l; 712 uint32_t idx = 0; 713 ocs_list_foreach(&ocs->ocs_os.locklist, l) { 714 ocs_ddump_section(textbuf, "lock", idx); 715 ocs_ddump_value(textbuf, "name", "%s", l->name); 716 ocs_ddump_value(textbuf, "inuse", "%d", l->inuse); 717 ocs_ddump_value(textbuf, "caller", "%p", l->caller[0]); 718 ocs_ddump_value(textbuf, "pid", "%08x", l->pid.l); 719 ocs_ddump_endsection(textbuf, "lock", idx); 720 idx++; 721 } 722 } ocs_unlock(&ocs->ocs_os.locklist_lock); 723 ocs_ddump_endsection(textbuf, "locks", 0); 724 #endif 725 726 /* Dump any pending vports */ 727 if (ocs_device_lock_try(ocs) != TRUE) { 728 /* Didn't get the lock */ 729 return -1; 730 } 731 instance = 0; 732 ocs_list_foreach(&xport->vport_list, vport) { 733 ocs_ddump_section(textbuf, "vport_spec", instance); 734 ocs_ddump_value(textbuf, "domain_instance", "%d", vport->domain_instance); 735 ocs_ddump_value(textbuf, "wwnn", "%llx", (unsigned long long)vport->wwnn); 736 ocs_ddump_value(textbuf, "wwpn", "%llx", (unsigned long long)vport->wwpn); 737 ocs_ddump_value(textbuf, "fc_id", "0x%x", vport->fc_id); 738 ocs_ddump_value(textbuf, "enable_tgt", "%d", vport->enable_tgt); 739 ocs_ddump_value(textbuf, "enable_ini", "%d" PRIx64, vport->enable_ini); 740 ocs_ddump_endsection(textbuf, "vport_spec", instance ++); 741 } 742 ocs_device_unlock(ocs); 743 744 /* Dump target and initiator private data */ 745 ocs_scsi_ini_ddump(textbuf, OCS_SCSI_DDUMP_DEVICE, ocs); 746 ocs_scsi_tgt_ddump(textbuf, OCS_SCSI_DDUMP_DEVICE, ocs); 747 748 ocs_ddump_hw(textbuf, &ocs->hw, flags, qentries); 749 750 if (ocs_device_lock_try(ocs) != TRUE) { 751 /* Didn't get the lock */ 752 return -1; 753 } 754 /* Here the device lock is held */ 755 ocs_list_foreach(&ocs->domain_list, domain) { 756 retval = ocs_ddump_domain(textbuf, domain); 757 if (retval != 0) { 758 break; 759 } 760 } 761 762 /* Dump ramlog */ 763 ocs_ddump_ramlog(textbuf, ocs->ramlog); 764 ocs_device_unlock(ocs); 765 766 #if !defined(OCS_DEBUG_QUEUE_HISTORY) 767 ocs_ddump_section(textbuf, "q_hist", ocs->instance_index); 768 ocs_textbuf_printf(textbuf, "<history>\n"); 769 ocs_textbuf_printf(textbuf, "No history available\n"); 770 ocs_textbuf_printf(textbuf, "</history>\n"); 771 ocs_ddump_endsection(textbuf, "q_hist", ocs->instance_index); 772 #else 773 ocs_ddump_queue_history(textbuf, &ocs->hw.q_hist); 774 #endif 775 776 #if defined(OCS_DEBUG_MEMORY) 777 ocs_memory_allocated_ddump(textbuf); 778 #endif 779 780 ocs_ddump_endsection(textbuf, "ocs", ocs->instance_index); 781 782 ocs_ddump_endfile(textbuf); 783 784 return retval; 785 } 786 787 /** 788 * @brief Capture and save ddump 789 * 790 * Captures and saves a ddump to the ocs_t structure to save the 791 * current state. The goal of this function is to save a ddump 792 * as soon as an issue is encountered. The saved ddump will be 793 * kept until the user reads it. 794 * 795 * @param ocs pointer to device context 796 * @param flags ddump flags 797 * @param qentries number of queue entries to dump 798 * 799 * @return 0 if ddump was saved; > 0 of one already exists; < 0 800 * error 801 */ 802 803 int32_t 804 ocs_save_ddump(ocs_t *ocs, uint32_t flags, uint32_t qentries) 805 { 806 if (ocs_textbuf_get_written(&ocs->ddump_saved) > 0) { 807 ocs_log_debug(ocs, "Saved ddump already exists\n"); 808 return 1; 809 } 810 811 if (!ocs_textbuf_initialized(&ocs->ddump_saved)) { 812 ocs_log_err(ocs, "Saved ddump not allocated\n"); 813 return -1; 814 } 815 816 ocs_log_debug(ocs, "Saving ddump\n"); 817 ocs_ddump(ocs, &ocs->ddump_saved, flags, qentries); 818 ocs_log_debug(ocs, "Saved ddump: %d bytes written\n", ocs_textbuf_get_written(&ocs->ddump_saved)); 819 return 0; 820 } 821 822 /** 823 * @brief Capture and save ddump for all OCS instances 824 * 825 * Calls ocs_save_ddump() for each OCS instance. 826 * 827 * @param flags ddump flags 828 * @param qentries number of queue entries to dump 829 * @param alloc_flag allocate dump buffer if not already allocated 830 * 831 * @return 0 if ddump was saved; > 0 of one already exists; < 0 832 * error 833 */ 834 835 int32_t 836 ocs_save_ddump_all(uint32_t flags, uint32_t qentries, uint32_t alloc_flag) 837 { 838 ocs_t *ocs; 839 uint32_t i; 840 int32_t rc = 0; 841 842 for (i = 0; (ocs = ocs_get_instance(i)) != NULL; i++) { 843 if (alloc_flag && (!ocs_textbuf_initialized(&ocs->ddump_saved))) { 844 rc = ocs_textbuf_alloc(ocs, &ocs->ddump_saved, DEFAULT_SAVED_DUMP_SIZE); 845 if (rc) { 846 break; 847 } 848 } 849 850 rc = ocs_save_ddump(ocs, flags, qentries); 851 if (rc < 0) { 852 break; 853 } 854 } 855 return rc; 856 } 857 858 /** 859 * @brief Clear saved ddump 860 * 861 * Clears saved ddump to make room for next one. 862 * 863 * @param ocs pointer to device context 864 * 865 * @return 0 if ddump was cleared; > 0 no saved ddump found 866 */ 867 868 int32_t 869 ocs_clear_saved_ddump(ocs_t *ocs) 870 { 871 /* if there's a saved ddump, copy to newly allocated textbuf */ 872 if (ocs_textbuf_get_written(&ocs->ddump_saved)) { 873 ocs_log_debug(ocs, "saved ddump cleared\n"); 874 ocs_textbuf_reset(&ocs->ddump_saved); 875 return 0; 876 } else { 877 ocs_log_debug(ocs, "no saved ddump found\n"); 878 return 1; 879 } 880 } 881 882