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