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/ice/ice_fwlog.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 /* SPDX-License-Identifier: BSD-3-Clause */
    2 /*  Copyright (c) 2021, Intel Corporation
    3  *  All rights reserved.
    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
   12  *      notice, this list of conditions and the following disclaimer in the
   13  *      documentation and/or other materials provided with the distribution.
   14  *
   15  *   3. Neither the name of the Intel Corporation nor the names of its
   16  *      contributors may be used to endorse or promote products derived from
   17  *      this software 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 OWNER 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 #include "ice_common.h"
   34 #include "ice_fwlog.h"
   35 
   36 /**
   37  * cache_cfg - Cache FW logging config
   38  * @hw: pointer to the HW structure
   39  * @cfg: config to cache
   40  */
   41 static void cache_cfg(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
   42 {
   43         hw->fwlog_cfg = *cfg;
   44 }
   45 
   46 /**
   47  * valid_module_entries - validate all the module entry IDs and log levels
   48  * @hw: pointer to the HW structure
   49  * @entries: entries to validate
   50  * @num_entries: number of entries to validate
   51  */
   52 static bool
   53 valid_module_entries(struct ice_hw *hw, struct ice_fwlog_module_entry *entries,
   54                      u16 num_entries)
   55 {
   56         u16 i;
   57 
   58         if (!entries) {
   59                 ice_debug(hw, ICE_DBG_FW_LOG, "Null ice_fwlog_module_entry array\n");
   60                 return false;
   61         }
   62 
   63         if (!num_entries) {
   64                 ice_debug(hw, ICE_DBG_FW_LOG, "num_entries must be non-zero\n");
   65                 return false;
   66         }
   67 
   68         for (i = 0; i < num_entries; i++) {
   69                 struct ice_fwlog_module_entry *entry = &entries[i];
   70 
   71                 if (entry->module_id >= ICE_AQC_FW_LOG_ID_MAX) {
   72                         ice_debug(hw, ICE_DBG_FW_LOG, "Invalid module_id %u, max valid module_id is %u\n",
   73                                   entry->module_id, ICE_AQC_FW_LOG_ID_MAX - 1);
   74                         return false;
   75                 }
   76 
   77                 if (entry->log_level >= ICE_FWLOG_LEVEL_INVALID) {
   78                         ice_debug(hw, ICE_DBG_FW_LOG, "Invalid log_level %u, max valid log_level is %u\n",
   79                                   entry->log_level,
   80                                   ICE_AQC_FW_LOG_ID_MAX - 1);
   81                         return false;
   82                 }
   83         }
   84 
   85         return true;
   86 }
   87 
   88 /**
   89  * valid_cfg - validate entire configuration
   90  * @hw: pointer to the HW structure
   91  * @cfg: config to validate
   92  */
   93 static bool valid_cfg(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
   94 {
   95         if (!cfg) {
   96                 ice_debug(hw, ICE_DBG_FW_LOG, "Null ice_fwlog_cfg\n");
   97                 return false;
   98         }
   99 
  100         if (cfg->log_resolution < ICE_AQC_FW_LOG_MIN_RESOLUTION ||
  101             cfg->log_resolution > ICE_AQC_FW_LOG_MAX_RESOLUTION) {
  102                 ice_debug(hw, ICE_DBG_FW_LOG, "Unsupported log_resolution %u, must be between %u and %u\n",
  103                           cfg->log_resolution, ICE_AQC_FW_LOG_MIN_RESOLUTION,
  104                           ICE_AQC_FW_LOG_MAX_RESOLUTION);
  105                 return false;
  106         }
  107 
  108         if (!valid_module_entries(hw, cfg->module_entries,
  109                                   ICE_AQC_FW_LOG_ID_MAX))
  110                 return false;
  111 
  112         return true;
  113 }
  114 
  115 /**
  116  * ice_fwlog_init - Initialize cached structures for tracking FW logging
  117  * @hw: pointer to the HW structure
  118  * @cfg: config used to initialize the cached structures
  119  *
  120  * This function should be called on driver initialization and before calling
  121  * ice_init_hw(). Firmware logging will be configured based on these settings
  122  * and also the PF will be registered on init.
  123  */
  124 enum ice_status
  125 ice_fwlog_init(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
  126 {
  127         if (!valid_cfg(hw, cfg))
  128                 return ICE_ERR_PARAM;
  129 
  130         cache_cfg(hw, cfg);
  131 
  132         return ICE_SUCCESS;
  133 }
  134 
  135 /**
  136  * ice_aq_fwlog_set - Set FW logging configuration AQ command (0xFF30)
  137  * @hw: pointer to the HW structure
  138  * @entries: entries to configure
  139  * @num_entries: number of @entries
  140  * @options: options from ice_fwlog_cfg->options structure
  141  * @log_resolution: logging resolution
  142  */
  143 static enum ice_status
  144 ice_aq_fwlog_set(struct ice_hw *hw, struct ice_fwlog_module_entry *entries,
  145                  u16 num_entries, u16 options, u16 log_resolution)
  146 {
  147         struct ice_aqc_fw_log_cfg_resp *fw_modules;
  148         struct ice_aqc_fw_log *cmd;
  149         struct ice_aq_desc desc;
  150         enum ice_status status;
  151         u16 i;
  152 
  153         fw_modules = (struct ice_aqc_fw_log_cfg_resp *)
  154                 ice_calloc(hw, num_entries, sizeof(*fw_modules));
  155         if (!fw_modules)
  156                 return ICE_ERR_NO_MEMORY;
  157 
  158         for (i = 0; i < num_entries; i++) {
  159                 fw_modules[i].module_identifier =
  160                         CPU_TO_LE16(entries[i].module_id);
  161                 fw_modules[i].log_level = entries[i].log_level;
  162         }
  163 
  164         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_config);
  165         desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
  166 
  167         cmd = &desc.params.fw_log;
  168 
  169         cmd->cmd_flags = ICE_AQC_FW_LOG_CONF_SET_VALID;
  170         cmd->ops.cfg.log_resolution = CPU_TO_LE16(log_resolution);
  171         cmd->ops.cfg.mdl_cnt = CPU_TO_LE16(num_entries);
  172 
  173         if (options & ICE_FWLOG_OPTION_ARQ_ENA)
  174                 cmd->cmd_flags |= ICE_AQC_FW_LOG_CONF_AQ_EN;
  175         if (options & ICE_FWLOG_OPTION_UART_ENA)
  176                 cmd->cmd_flags |= ICE_AQC_FW_LOG_CONF_UART_EN;
  177 
  178         status = ice_aq_send_cmd(hw, &desc, fw_modules,
  179                                  sizeof(*fw_modules) * num_entries,
  180                                  NULL);
  181 
  182         ice_free(hw, fw_modules);
  183 
  184         return status;
  185 }
  186 
  187 /**
  188  * ice_fwlog_supported - Cached for whether FW supports FW logging or not
  189  * @hw: pointer to the HW structure
  190  *
  191  * This will always return false if called before ice_init_hw(), so it must be
  192  * called after ice_init_hw().
  193  */
  194 bool ice_fwlog_supported(struct ice_hw *hw)
  195 {
  196         return hw->fwlog_support_ena;
  197 }
  198 
  199 /**
  200  * ice_fwlog_set - Set the firmware logging settings
  201  * @hw: pointer to the HW structure
  202  * @cfg: config used to set firmware logging
  203  *
  204  * This function should be called whenever the driver needs to set the firmware
  205  * logging configuration. It can be called on initialization, reset, or during
  206  * runtime.
  207  *
  208  * If the PF wishes to receive FW logging then it must register via
  209  * ice_fwlog_register. Note, that ice_fwlog_register does not need to be called
  210  * for init.
  211  */
  212 enum ice_status
  213 ice_fwlog_set(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
  214 {
  215         enum ice_status status;
  216 
  217         if (!ice_fwlog_supported(hw))
  218                 return ICE_ERR_NOT_SUPPORTED;
  219 
  220         if (!valid_cfg(hw, cfg))
  221                 return ICE_ERR_PARAM;
  222 
  223         status = ice_aq_fwlog_set(hw, cfg->module_entries,
  224                                   ICE_AQC_FW_LOG_ID_MAX, cfg->options,
  225                                   cfg->log_resolution);
  226         if (!status)
  227                 cache_cfg(hw, cfg);
  228 
  229         return status;
  230 }
  231 
  232 /**
  233  * update_cached_entries - Update module entries in cached FW logging config
  234  * @hw: pointer to the HW structure
  235  * @entries: entries to cache
  236  * @num_entries: number of @entries
  237  */
  238 static void
  239 update_cached_entries(struct ice_hw *hw, struct ice_fwlog_module_entry *entries,
  240                       u16 num_entries)
  241 {
  242         u16 i;
  243 
  244         for (i = 0; i < num_entries; i++) {
  245                 struct ice_fwlog_module_entry *updated = &entries[i];
  246                 u16 j;
  247 
  248                 for (j = 0; j < ICE_AQC_FW_LOG_ID_MAX; j++) {
  249                         struct ice_fwlog_module_entry *cached =
  250                                 &hw->fwlog_cfg.module_entries[j];
  251 
  252                         if (cached->module_id == updated->module_id) {
  253                                 cached->log_level = updated->log_level;
  254                                 break;
  255                         }
  256                 }
  257         }
  258 }
  259 
  260 /**
  261  * ice_fwlog_update_modules - Update the log level 1 or more FW logging modules
  262  * @hw: pointer to the HW structure
  263  * @entries: array of ice_fwlog_module_entry(s)
  264  * @num_entries: number of entries
  265  *
  266  * This function should be called to update the log level of 1 or more FW
  267  * logging modules via module ID.
  268  *
  269  * Only the entries passed in will be affected. All other firmware logging
  270  * settings will be unaffected.
  271  */
  272 enum ice_status
  273 ice_fwlog_update_modules(struct ice_hw *hw,
  274                          struct ice_fwlog_module_entry *entries,
  275                          u16 num_entries)
  276 {
  277         struct ice_fwlog_cfg *cfg;
  278         enum ice_status status;
  279 
  280         if (!ice_fwlog_supported(hw))
  281                 return ICE_ERR_NOT_SUPPORTED;
  282 
  283         if (!valid_module_entries(hw, entries, num_entries))
  284                 return ICE_ERR_PARAM;
  285 
  286         cfg = (struct ice_fwlog_cfg *)ice_calloc(hw, 1, sizeof(*cfg));
  287         if (!cfg)
  288                 return ICE_ERR_NO_MEMORY;
  289 
  290         status = ice_fwlog_get(hw, cfg);
  291         if (status)
  292                 goto status_out;
  293 
  294         status = ice_aq_fwlog_set(hw, entries, num_entries, cfg->options,
  295                                   cfg->log_resolution);
  296         if (!status)
  297                 update_cached_entries(hw, entries, num_entries);
  298 
  299 status_out:
  300         ice_free(hw, cfg);
  301         return status;
  302 }
  303 
  304 /**
  305  * ice_aq_fwlog_register - Register PF for firmware logging events (0xFF31)
  306  * @hw: pointer to the HW structure
  307  * @reg: true to register and false to unregister
  308  */
  309 static enum ice_status ice_aq_fwlog_register(struct ice_hw *hw, bool reg)
  310 {
  311         struct ice_aq_desc desc;
  312 
  313         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_register);
  314 
  315         if (reg)
  316                 desc.params.fw_log.cmd_flags = ICE_AQC_FW_LOG_AQ_REGISTER;
  317 
  318         return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
  319 }
  320 
  321 /**
  322  * ice_fwlog_register - Register the PF for firmware logging
  323  * @hw: pointer to the HW structure
  324  *
  325  * After this call the PF will start to receive firmware logging based on the
  326  * configuration set in ice_fwlog_set.
  327  */
  328 enum ice_status ice_fwlog_register(struct ice_hw *hw)
  329 {
  330         enum ice_status status;
  331 
  332         if (!ice_fwlog_supported(hw))
  333                 return ICE_ERR_NOT_SUPPORTED;
  334 
  335         status = ice_aq_fwlog_register(hw, true);
  336         if (status)
  337                 ice_debug(hw, ICE_DBG_FW_LOG, "Failed to register for firmware logging events over ARQ\n");
  338         else
  339                 hw->fwlog_cfg.options |= ICE_FWLOG_OPTION_IS_REGISTERED;
  340 
  341         return status;
  342 }
  343 
  344 /**
  345  * ice_fwlog_unregister - Unregister the PF from firmware logging
  346  * @hw: pointer to the HW structure
  347  */
  348 enum ice_status ice_fwlog_unregister(struct ice_hw *hw)
  349 {
  350         enum ice_status status;
  351 
  352         if (!ice_fwlog_supported(hw))
  353                 return ICE_ERR_NOT_SUPPORTED;
  354 
  355         status = ice_aq_fwlog_register(hw, false);
  356         if (status)
  357                 ice_debug(hw, ICE_DBG_FW_LOG, "Failed to unregister from firmware logging events over ARQ\n");
  358         else
  359                 hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_IS_REGISTERED;
  360 
  361         return status;
  362 }
  363 
  364 /**
  365  * ice_aq_fwlog_get - Get the current firmware logging configuration (0xFF32)
  366  * @hw: pointer to the HW structure
  367  * @cfg: firmware logging configuration to populate
  368  */
  369 static enum ice_status
  370 ice_aq_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
  371 {
  372         struct ice_aqc_fw_log_cfg_resp *fw_modules;
  373         struct ice_aqc_fw_log *cmd;
  374         struct ice_aq_desc desc;
  375         enum ice_status status;
  376         u16 i, module_id_cnt;
  377         void *buf;
  378 
  379         ice_memset(cfg, 0, sizeof(*cfg), ICE_NONDMA_MEM);
  380 
  381         buf = ice_calloc(hw, 1, ICE_AQ_MAX_BUF_LEN);
  382         if (!buf)
  383                 return ICE_ERR_NO_MEMORY;
  384 
  385         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_query);
  386         cmd = &desc.params.fw_log;
  387 
  388         cmd->cmd_flags = ICE_AQC_FW_LOG_AQ_QUERY;
  389 
  390         status = ice_aq_send_cmd(hw, &desc, buf, ICE_AQ_MAX_BUF_LEN, NULL);
  391         if (status) {
  392                 ice_debug(hw, ICE_DBG_FW_LOG, "Failed to get FW log configuration\n");
  393                 goto status_out;
  394         }
  395 
  396         module_id_cnt = LE16_TO_CPU(cmd->ops.cfg.mdl_cnt);
  397         if (module_id_cnt < ICE_AQC_FW_LOG_ID_MAX) {
  398                 ice_debug(hw, ICE_DBG_FW_LOG, "FW returned less than the expected number of FW log module IDs\n");
  399         } else {
  400                 if (module_id_cnt > ICE_AQC_FW_LOG_ID_MAX)
  401                         ice_debug(hw, ICE_DBG_FW_LOG, "FW returned more than expected number of FW log module IDs, setting module_id_cnt to software expected max %u\n",
  402                                   ICE_AQC_FW_LOG_ID_MAX);
  403                 module_id_cnt = ICE_AQC_FW_LOG_ID_MAX;
  404         }
  405 
  406         cfg->log_resolution = LE16_TO_CPU(cmd->ops.cfg.log_resolution);
  407         if (cmd->cmd_flags & ICE_AQC_FW_LOG_CONF_AQ_EN)
  408                 cfg->options |= ICE_FWLOG_OPTION_ARQ_ENA;
  409         if (cmd->cmd_flags & ICE_AQC_FW_LOG_CONF_UART_EN)
  410                 cfg->options |= ICE_FWLOG_OPTION_UART_ENA;
  411         if (cmd->cmd_flags & ICE_AQC_FW_LOG_QUERY_REGISTERED)
  412                 cfg->options |= ICE_FWLOG_OPTION_IS_REGISTERED;
  413 
  414         fw_modules = (struct ice_aqc_fw_log_cfg_resp *)buf;
  415 
  416         for (i = 0; i < module_id_cnt; i++) {
  417                 struct ice_aqc_fw_log_cfg_resp *fw_module = &fw_modules[i];
  418 
  419                 cfg->module_entries[i].module_id =
  420                         LE16_TO_CPU(fw_module->module_identifier);
  421                 cfg->module_entries[i].log_level = fw_module->log_level;
  422         }
  423 
  424 status_out:
  425         ice_free(hw, buf);
  426         return status;
  427 }
  428 
  429 /**
  430  * ice_fwlog_set_support_ena - Set if FW logging is supported by FW
  431  * @hw: pointer to the HW struct
  432  *
  433  * If FW returns success to the ice_aq_fwlog_get call then it supports FW
  434  * logging, else it doesn't. Set the fwlog_support_ena flag accordingly.
  435  *
  436  * This function is only meant to be called during driver init to determine if
  437  * the FW support FW logging.
  438  */
  439 void ice_fwlog_set_support_ena(struct ice_hw *hw)
  440 {
  441         struct ice_fwlog_cfg *cfg;
  442         enum ice_status status;
  443 
  444         hw->fwlog_support_ena = false;
  445 
  446         cfg = (struct ice_fwlog_cfg *)ice_calloc(hw, 1, sizeof(*cfg));
  447         if (!cfg)
  448                 return;
  449 
  450         /* don't call ice_fwlog_get() because that would overwrite the cached
  451          * configuration from the call to ice_fwlog_init(), which is expected to
  452          * be called prior to this function
  453          */
  454         status = ice_aq_fwlog_get(hw, cfg);
  455         if (status)
  456                 ice_debug(hw, ICE_DBG_FW_LOG, "ice_fwlog_get failed, FW logging is not supported on this version of FW, status %d\n",
  457                           status);
  458         else
  459                 hw->fwlog_support_ena = true;
  460 
  461         ice_free(hw, cfg);
  462 }
  463 
  464 /**
  465  * ice_fwlog_get - Get the firmware logging settings
  466  * @hw: pointer to the HW structure
  467  * @cfg: config to populate based on current firmware logging settings
  468  */
  469 enum ice_status
  470 ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
  471 {
  472         enum ice_status status;
  473 
  474         if (!ice_fwlog_supported(hw))
  475                 return ICE_ERR_NOT_SUPPORTED;
  476 
  477         if (!cfg)
  478                 return ICE_ERR_PARAM;
  479 
  480         status = ice_aq_fwlog_get(hw, cfg);
  481         if (status)
  482                 return status;
  483 
  484         cache_cfg(hw, cfg);
  485 
  486         return ICE_SUCCESS;
  487 }
  488 
  489 /**
  490  * ice_fwlog_event_dump - Dump the event received over the Admin Receive Queue
  491  * @hw: pointer to the HW structure
  492  * @desc: Admin Receive Queue descriptor
  493  * @buf: buffer that contains the FW log event data
  494  *
  495  * If the driver receives the ice_aqc_opc_fw_logs_event on the Admin Receive
  496  * Queue, then it should call this function to dump the FW log data.
  497  */
  498 void
  499 ice_fwlog_event_dump(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf)
  500 {
  501         if (!ice_fwlog_supported(hw))
  502                 return;
  503 
  504         ice_info_fwlog(hw, 32, 1, (u8 *)buf, LE16_TO_CPU(desc->datalen));
  505 }

Cache object: 37b9c33af12e8e4a1d3336b15da5beab


[ 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.