1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright (c) 2021, Intel Corporation
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
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.
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.
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.
33 #include "ice_common.h"
34 #include "ice_fwlog.h"
37 * cache_cfg - Cache FW logging config
38 * @hw: pointer to the HW structure
39 * @cfg: config to cache
41 static void cache_cfg(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
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
53 valid_module_entries(struct ice_hw *hw, struct ice_fwlog_module_entry *entries,
59 ice_debug(hw, ICE_DBG_FW_LOG, "Null ice_fwlog_module_entry array\n");
64 ice_debug(hw, ICE_DBG_FW_LOG, "num_entries must be non-zero\n");
68 for (i = 0; i < num_entries; i++) {
69 struct ice_fwlog_module_entry *entry = &entries[i];
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);
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",
80 ICE_AQC_FW_LOG_ID_MAX - 1);
89 * valid_cfg - validate entire configuration
90 * @hw: pointer to the HW structure
91 * @cfg: config to validate
93 static bool valid_cfg(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
96 ice_debug(hw, ICE_DBG_FW_LOG, "Null ice_fwlog_cfg\n");
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);
108 if (!valid_module_entries(hw, cfg->module_entries,
109 ICE_AQC_FW_LOG_ID_MAX))
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
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.
125 ice_fwlog_init(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
127 if (!valid_cfg(hw, cfg))
128 return ICE_ERR_PARAM;
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
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)
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;
153 fw_modules = (struct ice_aqc_fw_log_cfg_resp *)
154 ice_calloc(hw, num_entries, sizeof(*fw_modules));
156 return ICE_ERR_NO_MEMORY;
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;
164 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_config);
165 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
167 cmd = &desc.params.fw_log;
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);
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;
178 status = ice_aq_send_cmd(hw, &desc, fw_modules,
179 sizeof(*fw_modules) * num_entries,
182 ice_free(hw, fw_modules);
188 * ice_fwlog_supported - Cached for whether FW supports FW logging or not
189 * @hw: pointer to the HW structure
191 * This will always return false if called before ice_init_hw(), so it must be
192 * called after ice_init_hw().
194 bool ice_fwlog_supported(struct ice_hw *hw)
196 return hw->fwlog_support_ena;
200 * ice_fwlog_set - Set the firmware logging settings
201 * @hw: pointer to the HW structure
202 * @cfg: config used to set firmware logging
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
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
213 ice_fwlog_set(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
215 enum ice_status status;
217 if (!ice_fwlog_supported(hw))
218 return ICE_ERR_NOT_SUPPORTED;
220 if (!valid_cfg(hw, cfg))
221 return ICE_ERR_PARAM;
223 status = ice_aq_fwlog_set(hw, cfg->module_entries,
224 ICE_AQC_FW_LOG_ID_MAX, cfg->options,
225 cfg->log_resolution);
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
239 update_cached_entries(struct ice_hw *hw, struct ice_fwlog_module_entry *entries,
244 for (i = 0; i < num_entries; i++) {
245 struct ice_fwlog_module_entry *updated = &entries[i];
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];
252 if (cached->module_id == updated->module_id) {
253 cached->log_level = updated->log_level;
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
266 * This function should be called to update the log level of 1 or more FW
267 * logging modules via module ID.
269 * Only the entries passed in will be affected. All other firmware logging
270 * settings will be unaffected.
273 ice_fwlog_update_modules(struct ice_hw *hw,
274 struct ice_fwlog_module_entry *entries,
277 struct ice_fwlog_cfg *cfg;
278 enum ice_status status;
280 if (!ice_fwlog_supported(hw))
281 return ICE_ERR_NOT_SUPPORTED;
283 if (!valid_module_entries(hw, entries, num_entries))
284 return ICE_ERR_PARAM;
286 cfg = (struct ice_fwlog_cfg *)ice_calloc(hw, 1, sizeof(*cfg));
288 return ICE_ERR_NO_MEMORY;
290 status = ice_fwlog_get(hw, cfg);
294 status = ice_aq_fwlog_set(hw, entries, num_entries, cfg->options,
295 cfg->log_resolution);
297 update_cached_entries(hw, entries, num_entries);
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
309 static enum ice_status ice_aq_fwlog_register(struct ice_hw *hw, bool reg)
311 struct ice_aq_desc desc;
313 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_register);
316 desc.params.fw_log.cmd_flags = ICE_AQC_FW_LOG_AQ_REGISTER;
318 return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
322 * ice_fwlog_register - Register the PF for firmware logging
323 * @hw: pointer to the HW structure
325 * After this call the PF will start to receive firmware logging based on the
326 * configuration set in ice_fwlog_set.
328 enum ice_status ice_fwlog_register(struct ice_hw *hw)
330 enum ice_status status;
332 if (!ice_fwlog_supported(hw))
333 return ICE_ERR_NOT_SUPPORTED;
335 status = ice_aq_fwlog_register(hw, true);
337 ice_debug(hw, ICE_DBG_FW_LOG, "Failed to register for firmware logging events over ARQ\n");
339 hw->fwlog_cfg.options |= ICE_FWLOG_OPTION_IS_REGISTERED;
345 * ice_fwlog_unregister - Unregister the PF from firmware logging
346 * @hw: pointer to the HW structure
348 enum ice_status ice_fwlog_unregister(struct ice_hw *hw)
350 enum ice_status status;
352 if (!ice_fwlog_supported(hw))
353 return ICE_ERR_NOT_SUPPORTED;
355 status = ice_aq_fwlog_register(hw, false);
357 ice_debug(hw, ICE_DBG_FW_LOG, "Failed to unregister from firmware logging events over ARQ\n");
359 hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_IS_REGISTERED;
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
369 static enum ice_status
370 ice_aq_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
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;
379 ice_memset(cfg, 0, sizeof(*cfg), ICE_NONDMA_MEM);
381 buf = ice_calloc(hw, 1, ICE_AQ_MAX_BUF_LEN);
383 return ICE_ERR_NO_MEMORY;
385 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_query);
386 cmd = &desc.params.fw_log;
388 cmd->cmd_flags = ICE_AQC_FW_LOG_AQ_QUERY;
390 status = ice_aq_send_cmd(hw, &desc, buf, ICE_AQ_MAX_BUF_LEN, NULL);
392 ice_debug(hw, ICE_DBG_FW_LOG, "Failed to get FW log configuration\n");
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");
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;
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;
414 fw_modules = (struct ice_aqc_fw_log_cfg_resp *)buf;
416 for (i = 0; i < module_id_cnt; i++) {
417 struct ice_aqc_fw_log_cfg_resp *fw_module = &fw_modules[i];
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;
430 * ice_fwlog_set_support_ena - Set if FW logging is supported by FW
431 * @hw: pointer to the HW struct
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.
436 * This function is only meant to be called during driver init to determine if
437 * the FW support FW logging.
439 void ice_fwlog_set_support_ena(struct ice_hw *hw)
441 struct ice_fwlog_cfg *cfg;
442 enum ice_status status;
444 hw->fwlog_support_ena = false;
446 cfg = (struct ice_fwlog_cfg *)ice_calloc(hw, 1, sizeof(*cfg));
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
454 status = ice_aq_fwlog_get(hw, cfg);
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",
459 hw->fwlog_support_ena = true;
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
470 ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
472 enum ice_status status;
474 if (!ice_fwlog_supported(hw))
475 return ICE_ERR_NOT_SUPPORTED;
478 return ICE_ERR_PARAM;
480 status = ice_aq_fwlog_get(hw, cfg);
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
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.
499 ice_fwlog_event_dump(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf)
501 if (!ice_fwlog_supported(hw))
504 ice_info_fwlog(hw, 32, 1, (u8 *)buf, LE16_TO_CPU(desc->datalen));