156429daeSEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */ 2*015f8cc5SEric Joyner /* Copyright (c) 2024, Intel Corporation 356429daeSEric Joyner * All rights reserved. 456429daeSEric Joyner * 556429daeSEric Joyner * Redistribution and use in source and binary forms, with or without 656429daeSEric Joyner * modification, are permitted provided that the following conditions are met: 756429daeSEric Joyner * 856429daeSEric Joyner * 1. Redistributions of source code must retain the above copyright notice, 956429daeSEric Joyner * this list of conditions and the following disclaimer. 1056429daeSEric Joyner * 1156429daeSEric Joyner * 2. Redistributions in binary form must reproduce the above copyright 1256429daeSEric Joyner * notice, this list of conditions and the following disclaimer in the 1356429daeSEric Joyner * documentation and/or other materials provided with the distribution. 1456429daeSEric Joyner * 1556429daeSEric Joyner * 3. Neither the name of the Intel Corporation nor the names of its 1656429daeSEric Joyner * contributors may be used to endorse or promote products derived from 1756429daeSEric Joyner * this software without specific prior written permission. 1856429daeSEric Joyner * 1956429daeSEric Joyner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2056429daeSEric Joyner * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2156429daeSEric Joyner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2256429daeSEric Joyner * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2356429daeSEric Joyner * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2456429daeSEric Joyner * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2556429daeSEric Joyner * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2656429daeSEric Joyner * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2756429daeSEric Joyner * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2856429daeSEric Joyner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2956429daeSEric Joyner * POSSIBILITY OF SUCH DAMAGE. 3056429daeSEric Joyner */ 3156429daeSEric Joyner 3256429daeSEric Joyner #include "ice_common.h" 3356429daeSEric Joyner #include "ice_fwlog.h" 3456429daeSEric Joyner 3556429daeSEric Joyner /** 3656429daeSEric Joyner * cache_cfg - Cache FW logging config 3756429daeSEric Joyner * @hw: pointer to the HW structure 3856429daeSEric Joyner * @cfg: config to cache 3956429daeSEric Joyner */ 4056429daeSEric Joyner static void cache_cfg(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) 4156429daeSEric Joyner { 4256429daeSEric Joyner hw->fwlog_cfg = *cfg; 4356429daeSEric Joyner } 4456429daeSEric Joyner 4556429daeSEric Joyner /** 4656429daeSEric Joyner * valid_module_entries - validate all the module entry IDs and log levels 4756429daeSEric Joyner * @hw: pointer to the HW structure 4856429daeSEric Joyner * @entries: entries to validate 4956429daeSEric Joyner * @num_entries: number of entries to validate 5056429daeSEric Joyner */ 5156429daeSEric Joyner static bool 5256429daeSEric Joyner valid_module_entries(struct ice_hw *hw, struct ice_fwlog_module_entry *entries, 5356429daeSEric Joyner u16 num_entries) 5456429daeSEric Joyner { 5556429daeSEric Joyner u16 i; 5656429daeSEric Joyner 5756429daeSEric Joyner if (!entries) { 5856429daeSEric Joyner ice_debug(hw, ICE_DBG_FW_LOG, "Null ice_fwlog_module_entry array\n"); 5956429daeSEric Joyner return false; 6056429daeSEric Joyner } 6156429daeSEric Joyner 6256429daeSEric Joyner if (!num_entries) { 6356429daeSEric Joyner ice_debug(hw, ICE_DBG_FW_LOG, "num_entries must be non-zero\n"); 6456429daeSEric Joyner return false; 6556429daeSEric Joyner } 6656429daeSEric Joyner 6756429daeSEric Joyner for (i = 0; i < num_entries; i++) { 6856429daeSEric Joyner struct ice_fwlog_module_entry *entry = &entries[i]; 6956429daeSEric Joyner 7056429daeSEric Joyner if (entry->module_id >= ICE_AQC_FW_LOG_ID_MAX) { 7156429daeSEric Joyner ice_debug(hw, ICE_DBG_FW_LOG, "Invalid module_id %u, max valid module_id is %u\n", 7256429daeSEric Joyner entry->module_id, ICE_AQC_FW_LOG_ID_MAX - 1); 7356429daeSEric Joyner return false; 7456429daeSEric Joyner } 7556429daeSEric Joyner 7656429daeSEric Joyner if (entry->log_level >= ICE_FWLOG_LEVEL_INVALID) { 7756429daeSEric Joyner ice_debug(hw, ICE_DBG_FW_LOG, "Invalid log_level %u, max valid log_level is %u\n", 7856429daeSEric Joyner entry->log_level, 7956429daeSEric Joyner ICE_AQC_FW_LOG_ID_MAX - 1); 8056429daeSEric Joyner return false; 8156429daeSEric Joyner } 8256429daeSEric Joyner } 8356429daeSEric Joyner 8456429daeSEric Joyner return true; 8556429daeSEric Joyner } 8656429daeSEric Joyner 8756429daeSEric Joyner /** 8856429daeSEric Joyner * valid_cfg - validate entire configuration 8956429daeSEric Joyner * @hw: pointer to the HW structure 9056429daeSEric Joyner * @cfg: config to validate 9156429daeSEric Joyner */ 9256429daeSEric Joyner static bool valid_cfg(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) 9356429daeSEric Joyner { 9456429daeSEric Joyner if (!cfg) { 9556429daeSEric Joyner ice_debug(hw, ICE_DBG_FW_LOG, "Null ice_fwlog_cfg\n"); 9656429daeSEric Joyner return false; 9756429daeSEric Joyner } 9856429daeSEric Joyner 9956429daeSEric Joyner if (cfg->log_resolution < ICE_AQC_FW_LOG_MIN_RESOLUTION || 10056429daeSEric Joyner cfg->log_resolution > ICE_AQC_FW_LOG_MAX_RESOLUTION) { 10156429daeSEric Joyner ice_debug(hw, ICE_DBG_FW_LOG, "Unsupported log_resolution %u, must be between %u and %u\n", 10256429daeSEric Joyner cfg->log_resolution, ICE_AQC_FW_LOG_MIN_RESOLUTION, 10356429daeSEric Joyner ICE_AQC_FW_LOG_MAX_RESOLUTION); 10456429daeSEric Joyner return false; 10556429daeSEric Joyner } 10656429daeSEric Joyner 10756429daeSEric Joyner if (!valid_module_entries(hw, cfg->module_entries, 10856429daeSEric Joyner ICE_AQC_FW_LOG_ID_MAX)) 10956429daeSEric Joyner return false; 11056429daeSEric Joyner 11156429daeSEric Joyner return true; 11256429daeSEric Joyner } 11356429daeSEric Joyner 11456429daeSEric Joyner /** 11556429daeSEric Joyner * ice_fwlog_init - Initialize cached structures for tracking FW logging 11656429daeSEric Joyner * @hw: pointer to the HW structure 11756429daeSEric Joyner * @cfg: config used to initialize the cached structures 11856429daeSEric Joyner * 11956429daeSEric Joyner * This function should be called on driver initialization and before calling 12056429daeSEric Joyner * ice_init_hw(). Firmware logging will be configured based on these settings 12156429daeSEric Joyner * and also the PF will be registered on init. 12256429daeSEric Joyner */ 12356429daeSEric Joyner enum ice_status 12456429daeSEric Joyner ice_fwlog_init(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) 12556429daeSEric Joyner { 12656429daeSEric Joyner if (!valid_cfg(hw, cfg)) 12756429daeSEric Joyner return ICE_ERR_PARAM; 12856429daeSEric Joyner 12956429daeSEric Joyner cache_cfg(hw, cfg); 13056429daeSEric Joyner 13156429daeSEric Joyner return ICE_SUCCESS; 13256429daeSEric Joyner } 13356429daeSEric Joyner 13456429daeSEric Joyner /** 13556429daeSEric Joyner * ice_aq_fwlog_set - Set FW logging configuration AQ command (0xFF30) 13656429daeSEric Joyner * @hw: pointer to the HW structure 13756429daeSEric Joyner * @entries: entries to configure 13856429daeSEric Joyner * @num_entries: number of @entries 13956429daeSEric Joyner * @options: options from ice_fwlog_cfg->options structure 14056429daeSEric Joyner * @log_resolution: logging resolution 14156429daeSEric Joyner */ 14256429daeSEric Joyner static enum ice_status 14356429daeSEric Joyner ice_aq_fwlog_set(struct ice_hw *hw, struct ice_fwlog_module_entry *entries, 14456429daeSEric Joyner u16 num_entries, u16 options, u16 log_resolution) 14556429daeSEric Joyner { 14656429daeSEric Joyner struct ice_aqc_fw_log_cfg_resp *fw_modules; 14756429daeSEric Joyner struct ice_aqc_fw_log *cmd; 14856429daeSEric Joyner struct ice_aq_desc desc; 14956429daeSEric Joyner enum ice_status status; 15056429daeSEric Joyner u16 i; 15156429daeSEric Joyner 15256429daeSEric Joyner fw_modules = (struct ice_aqc_fw_log_cfg_resp *) 15356429daeSEric Joyner ice_calloc(hw, num_entries, sizeof(*fw_modules)); 15456429daeSEric Joyner if (!fw_modules) 15556429daeSEric Joyner return ICE_ERR_NO_MEMORY; 15656429daeSEric Joyner 15756429daeSEric Joyner for (i = 0; i < num_entries; i++) { 15856429daeSEric Joyner fw_modules[i].module_identifier = 15956429daeSEric Joyner CPU_TO_LE16(entries[i].module_id); 16056429daeSEric Joyner fw_modules[i].log_level = entries[i].log_level; 16156429daeSEric Joyner } 16256429daeSEric Joyner 16356429daeSEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_config); 16456429daeSEric Joyner desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 16556429daeSEric Joyner 16656429daeSEric Joyner cmd = &desc.params.fw_log; 16756429daeSEric Joyner 16856429daeSEric Joyner cmd->cmd_flags = ICE_AQC_FW_LOG_CONF_SET_VALID; 16956429daeSEric Joyner cmd->ops.cfg.log_resolution = CPU_TO_LE16(log_resolution); 17056429daeSEric Joyner cmd->ops.cfg.mdl_cnt = CPU_TO_LE16(num_entries); 17156429daeSEric Joyner 17256429daeSEric Joyner if (options & ICE_FWLOG_OPTION_ARQ_ENA) 17356429daeSEric Joyner cmd->cmd_flags |= ICE_AQC_FW_LOG_CONF_AQ_EN; 17456429daeSEric Joyner if (options & ICE_FWLOG_OPTION_UART_ENA) 17556429daeSEric Joyner cmd->cmd_flags |= ICE_AQC_FW_LOG_CONF_UART_EN; 17656429daeSEric Joyner 17756429daeSEric Joyner status = ice_aq_send_cmd(hw, &desc, fw_modules, 17856429daeSEric Joyner sizeof(*fw_modules) * num_entries, 17956429daeSEric Joyner NULL); 18056429daeSEric Joyner 18156429daeSEric Joyner ice_free(hw, fw_modules); 18256429daeSEric Joyner 18356429daeSEric Joyner return status; 18456429daeSEric Joyner } 18556429daeSEric Joyner 18656429daeSEric Joyner /** 18756429daeSEric Joyner * ice_fwlog_supported - Cached for whether FW supports FW logging or not 18856429daeSEric Joyner * @hw: pointer to the HW structure 18956429daeSEric Joyner * 19056429daeSEric Joyner * This will always return false if called before ice_init_hw(), so it must be 19156429daeSEric Joyner * called after ice_init_hw(). 19256429daeSEric Joyner */ 19356429daeSEric Joyner bool ice_fwlog_supported(struct ice_hw *hw) 19456429daeSEric Joyner { 19556429daeSEric Joyner return hw->fwlog_support_ena; 19656429daeSEric Joyner } 19756429daeSEric Joyner 19856429daeSEric Joyner /** 19956429daeSEric Joyner * ice_fwlog_set - Set the firmware logging settings 20056429daeSEric Joyner * @hw: pointer to the HW structure 20156429daeSEric Joyner * @cfg: config used to set firmware logging 20256429daeSEric Joyner * 20356429daeSEric Joyner * This function should be called whenever the driver needs to set the firmware 20456429daeSEric Joyner * logging configuration. It can be called on initialization, reset, or during 20556429daeSEric Joyner * runtime. 20656429daeSEric Joyner * 20756429daeSEric Joyner * If the PF wishes to receive FW logging then it must register via 20856429daeSEric Joyner * ice_fwlog_register. Note, that ice_fwlog_register does not need to be called 20956429daeSEric Joyner * for init. 21056429daeSEric Joyner */ 21156429daeSEric Joyner enum ice_status 21256429daeSEric Joyner ice_fwlog_set(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) 21356429daeSEric Joyner { 21456429daeSEric Joyner enum ice_status status; 21556429daeSEric Joyner 21656429daeSEric Joyner if (!ice_fwlog_supported(hw)) 21756429daeSEric Joyner return ICE_ERR_NOT_SUPPORTED; 21856429daeSEric Joyner 21956429daeSEric Joyner if (!valid_cfg(hw, cfg)) 22056429daeSEric Joyner return ICE_ERR_PARAM; 22156429daeSEric Joyner 22256429daeSEric Joyner status = ice_aq_fwlog_set(hw, cfg->module_entries, 22356429daeSEric Joyner ICE_AQC_FW_LOG_ID_MAX, cfg->options, 22456429daeSEric Joyner cfg->log_resolution); 22556429daeSEric Joyner if (!status) 22656429daeSEric Joyner cache_cfg(hw, cfg); 22756429daeSEric Joyner 22856429daeSEric Joyner return status; 22956429daeSEric Joyner } 23056429daeSEric Joyner 23156429daeSEric Joyner /** 23256429daeSEric Joyner * update_cached_entries - Update module entries in cached FW logging config 23356429daeSEric Joyner * @hw: pointer to the HW structure 23456429daeSEric Joyner * @entries: entries to cache 23556429daeSEric Joyner * @num_entries: number of @entries 23656429daeSEric Joyner */ 23756429daeSEric Joyner static void 23856429daeSEric Joyner update_cached_entries(struct ice_hw *hw, struct ice_fwlog_module_entry *entries, 23956429daeSEric Joyner u16 num_entries) 24056429daeSEric Joyner { 24156429daeSEric Joyner u16 i; 24256429daeSEric Joyner 24356429daeSEric Joyner for (i = 0; i < num_entries; i++) { 24456429daeSEric Joyner struct ice_fwlog_module_entry *updated = &entries[i]; 24556429daeSEric Joyner u16 j; 24656429daeSEric Joyner 24756429daeSEric Joyner for (j = 0; j < ICE_AQC_FW_LOG_ID_MAX; j++) { 24856429daeSEric Joyner struct ice_fwlog_module_entry *cached = 24956429daeSEric Joyner &hw->fwlog_cfg.module_entries[j]; 25056429daeSEric Joyner 25156429daeSEric Joyner if (cached->module_id == updated->module_id) { 25256429daeSEric Joyner cached->log_level = updated->log_level; 25356429daeSEric Joyner break; 25456429daeSEric Joyner } 25556429daeSEric Joyner } 25656429daeSEric Joyner } 25756429daeSEric Joyner } 25856429daeSEric Joyner 25956429daeSEric Joyner /** 26056429daeSEric Joyner * ice_fwlog_update_modules - Update the log level 1 or more FW logging modules 26156429daeSEric Joyner * @hw: pointer to the HW structure 26256429daeSEric Joyner * @entries: array of ice_fwlog_module_entry(s) 26356429daeSEric Joyner * @num_entries: number of entries 26456429daeSEric Joyner * 26556429daeSEric Joyner * This function should be called to update the log level of 1 or more FW 26656429daeSEric Joyner * logging modules via module ID. 26756429daeSEric Joyner * 26856429daeSEric Joyner * Only the entries passed in will be affected. All other firmware logging 26956429daeSEric Joyner * settings will be unaffected. 27056429daeSEric Joyner */ 27156429daeSEric Joyner enum ice_status 27256429daeSEric Joyner ice_fwlog_update_modules(struct ice_hw *hw, 27356429daeSEric Joyner struct ice_fwlog_module_entry *entries, 27456429daeSEric Joyner u16 num_entries) 27556429daeSEric Joyner { 27656429daeSEric Joyner struct ice_fwlog_cfg *cfg; 27756429daeSEric Joyner enum ice_status status; 27856429daeSEric Joyner 27956429daeSEric Joyner if (!ice_fwlog_supported(hw)) 28056429daeSEric Joyner return ICE_ERR_NOT_SUPPORTED; 28156429daeSEric Joyner 28256429daeSEric Joyner if (!valid_module_entries(hw, entries, num_entries)) 28356429daeSEric Joyner return ICE_ERR_PARAM; 28456429daeSEric Joyner 28556429daeSEric Joyner cfg = (struct ice_fwlog_cfg *)ice_calloc(hw, 1, sizeof(*cfg)); 28656429daeSEric Joyner if (!cfg) 28756429daeSEric Joyner return ICE_ERR_NO_MEMORY; 28856429daeSEric Joyner 28956429daeSEric Joyner status = ice_fwlog_get(hw, cfg); 29056429daeSEric Joyner if (status) 29156429daeSEric Joyner goto status_out; 29256429daeSEric Joyner 29356429daeSEric Joyner status = ice_aq_fwlog_set(hw, entries, num_entries, cfg->options, 29456429daeSEric Joyner cfg->log_resolution); 29556429daeSEric Joyner if (!status) 29656429daeSEric Joyner update_cached_entries(hw, entries, num_entries); 29756429daeSEric Joyner 29856429daeSEric Joyner status_out: 29956429daeSEric Joyner ice_free(hw, cfg); 30056429daeSEric Joyner return status; 30156429daeSEric Joyner } 30256429daeSEric Joyner 30356429daeSEric Joyner /** 30456429daeSEric Joyner * ice_aq_fwlog_register - Register PF for firmware logging events (0xFF31) 30556429daeSEric Joyner * @hw: pointer to the HW structure 30656429daeSEric Joyner * @reg: true to register and false to unregister 30756429daeSEric Joyner */ 30856429daeSEric Joyner static enum ice_status ice_aq_fwlog_register(struct ice_hw *hw, bool reg) 30956429daeSEric Joyner { 31056429daeSEric Joyner struct ice_aq_desc desc; 31156429daeSEric Joyner 31256429daeSEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_register); 31356429daeSEric Joyner 31456429daeSEric Joyner if (reg) 31556429daeSEric Joyner desc.params.fw_log.cmd_flags = ICE_AQC_FW_LOG_AQ_REGISTER; 31656429daeSEric Joyner 31756429daeSEric Joyner return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 31856429daeSEric Joyner } 31956429daeSEric Joyner 32056429daeSEric Joyner /** 32156429daeSEric Joyner * ice_fwlog_register - Register the PF for firmware logging 32256429daeSEric Joyner * @hw: pointer to the HW structure 32356429daeSEric Joyner * 32456429daeSEric Joyner * After this call the PF will start to receive firmware logging based on the 32556429daeSEric Joyner * configuration set in ice_fwlog_set. 32656429daeSEric Joyner */ 32756429daeSEric Joyner enum ice_status ice_fwlog_register(struct ice_hw *hw) 32856429daeSEric Joyner { 32956429daeSEric Joyner enum ice_status status; 33056429daeSEric Joyner 33156429daeSEric Joyner if (!ice_fwlog_supported(hw)) 33256429daeSEric Joyner return ICE_ERR_NOT_SUPPORTED; 33356429daeSEric Joyner 33456429daeSEric Joyner status = ice_aq_fwlog_register(hw, true); 33556429daeSEric Joyner if (status) 33656429daeSEric Joyner ice_debug(hw, ICE_DBG_FW_LOG, "Failed to register for firmware logging events over ARQ\n"); 33756429daeSEric Joyner else 33856429daeSEric Joyner hw->fwlog_cfg.options |= ICE_FWLOG_OPTION_IS_REGISTERED; 33956429daeSEric Joyner 34056429daeSEric Joyner return status; 34156429daeSEric Joyner } 34256429daeSEric Joyner 34356429daeSEric Joyner /** 34456429daeSEric Joyner * ice_fwlog_unregister - Unregister the PF from firmware logging 34556429daeSEric Joyner * @hw: pointer to the HW structure 34656429daeSEric Joyner */ 34756429daeSEric Joyner enum ice_status ice_fwlog_unregister(struct ice_hw *hw) 34856429daeSEric Joyner { 34956429daeSEric Joyner enum ice_status status; 35056429daeSEric Joyner 35156429daeSEric Joyner if (!ice_fwlog_supported(hw)) 35256429daeSEric Joyner return ICE_ERR_NOT_SUPPORTED; 35356429daeSEric Joyner 35456429daeSEric Joyner status = ice_aq_fwlog_register(hw, false); 35556429daeSEric Joyner if (status) 35656429daeSEric Joyner ice_debug(hw, ICE_DBG_FW_LOG, "Failed to unregister from firmware logging events over ARQ\n"); 35756429daeSEric Joyner else 35856429daeSEric Joyner hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_IS_REGISTERED; 35956429daeSEric Joyner 36056429daeSEric Joyner return status; 36156429daeSEric Joyner } 36256429daeSEric Joyner 36356429daeSEric Joyner /** 36456429daeSEric Joyner * ice_aq_fwlog_get - Get the current firmware logging configuration (0xFF32) 36556429daeSEric Joyner * @hw: pointer to the HW structure 36656429daeSEric Joyner * @cfg: firmware logging configuration to populate 36756429daeSEric Joyner */ 36856429daeSEric Joyner static enum ice_status 36956429daeSEric Joyner ice_aq_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) 37056429daeSEric Joyner { 37156429daeSEric Joyner struct ice_aqc_fw_log_cfg_resp *fw_modules; 37256429daeSEric Joyner struct ice_aqc_fw_log *cmd; 37356429daeSEric Joyner struct ice_aq_desc desc; 37456429daeSEric Joyner enum ice_status status; 37556429daeSEric Joyner u16 i, module_id_cnt; 37656429daeSEric Joyner void *buf; 37756429daeSEric Joyner 37856429daeSEric Joyner ice_memset(cfg, 0, sizeof(*cfg), ICE_NONDMA_MEM); 37956429daeSEric Joyner 38056429daeSEric Joyner buf = ice_calloc(hw, 1, ICE_AQ_MAX_BUF_LEN); 38156429daeSEric Joyner if (!buf) 38256429daeSEric Joyner return ICE_ERR_NO_MEMORY; 38356429daeSEric Joyner 38456429daeSEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_query); 38556429daeSEric Joyner cmd = &desc.params.fw_log; 38656429daeSEric Joyner 38756429daeSEric Joyner cmd->cmd_flags = ICE_AQC_FW_LOG_AQ_QUERY; 38856429daeSEric Joyner 38956429daeSEric Joyner status = ice_aq_send_cmd(hw, &desc, buf, ICE_AQ_MAX_BUF_LEN, NULL); 39056429daeSEric Joyner if (status) { 39156429daeSEric Joyner ice_debug(hw, ICE_DBG_FW_LOG, "Failed to get FW log configuration\n"); 39256429daeSEric Joyner goto status_out; 39356429daeSEric Joyner } 39456429daeSEric Joyner 39556429daeSEric Joyner module_id_cnt = LE16_TO_CPU(cmd->ops.cfg.mdl_cnt); 39656429daeSEric Joyner if (module_id_cnt < ICE_AQC_FW_LOG_ID_MAX) { 39756429daeSEric Joyner ice_debug(hw, ICE_DBG_FW_LOG, "FW returned less than the expected number of FW log module IDs\n"); 39856429daeSEric Joyner } else { 39956429daeSEric Joyner if (module_id_cnt > ICE_AQC_FW_LOG_ID_MAX) 40056429daeSEric Joyner 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", 40156429daeSEric Joyner ICE_AQC_FW_LOG_ID_MAX); 40256429daeSEric Joyner module_id_cnt = ICE_AQC_FW_LOG_ID_MAX; 40356429daeSEric Joyner } 40456429daeSEric Joyner 40556429daeSEric Joyner cfg->log_resolution = LE16_TO_CPU(cmd->ops.cfg.log_resolution); 40656429daeSEric Joyner if (cmd->cmd_flags & ICE_AQC_FW_LOG_CONF_AQ_EN) 40756429daeSEric Joyner cfg->options |= ICE_FWLOG_OPTION_ARQ_ENA; 40856429daeSEric Joyner if (cmd->cmd_flags & ICE_AQC_FW_LOG_CONF_UART_EN) 40956429daeSEric Joyner cfg->options |= ICE_FWLOG_OPTION_UART_ENA; 41056429daeSEric Joyner if (cmd->cmd_flags & ICE_AQC_FW_LOG_QUERY_REGISTERED) 41156429daeSEric Joyner cfg->options |= ICE_FWLOG_OPTION_IS_REGISTERED; 41256429daeSEric Joyner 41356429daeSEric Joyner fw_modules = (struct ice_aqc_fw_log_cfg_resp *)buf; 41456429daeSEric Joyner 41556429daeSEric Joyner for (i = 0; i < module_id_cnt; i++) { 41656429daeSEric Joyner struct ice_aqc_fw_log_cfg_resp *fw_module = &fw_modules[i]; 41756429daeSEric Joyner 41856429daeSEric Joyner cfg->module_entries[i].module_id = 41956429daeSEric Joyner LE16_TO_CPU(fw_module->module_identifier); 42056429daeSEric Joyner cfg->module_entries[i].log_level = fw_module->log_level; 42156429daeSEric Joyner } 42256429daeSEric Joyner 42356429daeSEric Joyner status_out: 42456429daeSEric Joyner ice_free(hw, buf); 42556429daeSEric Joyner return status; 42656429daeSEric Joyner } 42756429daeSEric Joyner 42856429daeSEric Joyner /** 42956429daeSEric Joyner * ice_fwlog_set_support_ena - Set if FW logging is supported by FW 43056429daeSEric Joyner * @hw: pointer to the HW struct 43156429daeSEric Joyner * 43256429daeSEric Joyner * If FW returns success to the ice_aq_fwlog_get call then it supports FW 43356429daeSEric Joyner * logging, else it doesn't. Set the fwlog_support_ena flag accordingly. 43456429daeSEric Joyner * 43556429daeSEric Joyner * This function is only meant to be called during driver init to determine if 43656429daeSEric Joyner * the FW support FW logging. 43756429daeSEric Joyner */ 43856429daeSEric Joyner void ice_fwlog_set_support_ena(struct ice_hw *hw) 43956429daeSEric Joyner { 44056429daeSEric Joyner struct ice_fwlog_cfg *cfg; 44156429daeSEric Joyner enum ice_status status; 44256429daeSEric Joyner 44356429daeSEric Joyner hw->fwlog_support_ena = false; 44456429daeSEric Joyner 44556429daeSEric Joyner cfg = (struct ice_fwlog_cfg *)ice_calloc(hw, 1, sizeof(*cfg)); 44656429daeSEric Joyner if (!cfg) 44756429daeSEric Joyner return; 44856429daeSEric Joyner 44956429daeSEric Joyner /* don't call ice_fwlog_get() because that would overwrite the cached 45056429daeSEric Joyner * configuration from the call to ice_fwlog_init(), which is expected to 45156429daeSEric Joyner * be called prior to this function 45256429daeSEric Joyner */ 45356429daeSEric Joyner status = ice_aq_fwlog_get(hw, cfg); 45456429daeSEric Joyner if (status) 45556429daeSEric Joyner ice_debug(hw, ICE_DBG_FW_LOG, "ice_fwlog_get failed, FW logging is not supported on this version of FW, status %d\n", 45656429daeSEric Joyner status); 45756429daeSEric Joyner else 45856429daeSEric Joyner hw->fwlog_support_ena = true; 45956429daeSEric Joyner 46056429daeSEric Joyner ice_free(hw, cfg); 46156429daeSEric Joyner } 46256429daeSEric Joyner 46356429daeSEric Joyner /** 46456429daeSEric Joyner * ice_fwlog_get - Get the firmware logging settings 46556429daeSEric Joyner * @hw: pointer to the HW structure 46656429daeSEric Joyner * @cfg: config to populate based on current firmware logging settings 46756429daeSEric Joyner */ 46856429daeSEric Joyner enum ice_status 46956429daeSEric Joyner ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) 47056429daeSEric Joyner { 47156429daeSEric Joyner enum ice_status status; 47256429daeSEric Joyner 47356429daeSEric Joyner if (!ice_fwlog_supported(hw)) 47456429daeSEric Joyner return ICE_ERR_NOT_SUPPORTED; 47556429daeSEric Joyner 47656429daeSEric Joyner if (!cfg) 47756429daeSEric Joyner return ICE_ERR_PARAM; 47856429daeSEric Joyner 47956429daeSEric Joyner status = ice_aq_fwlog_get(hw, cfg); 48056429daeSEric Joyner if (status) 48156429daeSEric Joyner return status; 48256429daeSEric Joyner 48356429daeSEric Joyner cache_cfg(hw, cfg); 48456429daeSEric Joyner 48556429daeSEric Joyner return ICE_SUCCESS; 48656429daeSEric Joyner } 48756429daeSEric Joyner 48856429daeSEric Joyner /** 48956429daeSEric Joyner * ice_fwlog_event_dump - Dump the event received over the Admin Receive Queue 49056429daeSEric Joyner * @hw: pointer to the HW structure 49156429daeSEric Joyner * @desc: Admin Receive Queue descriptor 49256429daeSEric Joyner * @buf: buffer that contains the FW log event data 49356429daeSEric Joyner * 49456429daeSEric Joyner * If the driver receives the ice_aqc_opc_fw_logs_event on the Admin Receive 49556429daeSEric Joyner * Queue, then it should call this function to dump the FW log data. 49656429daeSEric Joyner */ 49756429daeSEric Joyner void 49856429daeSEric Joyner ice_fwlog_event_dump(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf) 49956429daeSEric Joyner { 50056429daeSEric Joyner if (!ice_fwlog_supported(hw)) 50156429daeSEric Joyner return; 50256429daeSEric Joyner 50356429daeSEric Joyner ice_info_fwlog(hw, 32, 1, (u8 *)buf, LE16_TO_CPU(desc->datalen)); 50456429daeSEric Joyner } 5059c30461dSEric Joyner 506