The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ocs_fc/ocs_ddump.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 }

Cache object: 9f09c53136d33920362d2ac4c15b91f9


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.