xref: /freebsd/sys/dev/ice/ice_fw_logging.c (revision 015f8cc5)
156429daeSEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */
2015f8cc5SEric 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 /**
3356429daeSEric Joyner  * @file ice_fw_logging.c
3456429daeSEric Joyner  * @brief firmware logging sysctls
3556429daeSEric Joyner  *
3656429daeSEric Joyner  * Contains sysctls to enable and configure firmware logging debug support.
3756429daeSEric Joyner  */
3856429daeSEric Joyner 
3956429daeSEric Joyner #include "ice_lib.h"
4056429daeSEric Joyner #include "ice_iflib.h"
4156429daeSEric Joyner #include <sys/queue.h>
4256429daeSEric Joyner #include <sys/sdt.h>
4356429daeSEric Joyner 
4456429daeSEric Joyner /*
4556429daeSEric Joyner  * SDT provider for DTrace probes related to firmware logging events
4656429daeSEric Joyner  */
4756429daeSEric Joyner SDT_PROVIDER_DEFINE(ice_fwlog);
4856429daeSEric Joyner 
4956429daeSEric Joyner /*
5056429daeSEric Joyner  * SDT DTrace probe fired when a firmware log message is received over the
5156429daeSEric Joyner  * AdminQ. It passes the buffer of the firwmare log message along with its
5256429daeSEric Joyner  * length in bytes to the DTrace framework.
5356429daeSEric Joyner  */
5456429daeSEric Joyner SDT_PROBE_DEFINE2(ice_fwlog, , , message, "uint8_t *", "int");
5556429daeSEric Joyner 
5656429daeSEric Joyner /*
5756429daeSEric Joyner  * Helper function prototypes
5856429daeSEric Joyner  */
5956429daeSEric Joyner static int ice_reconfig_fw_log(struct ice_softc *sc, struct ice_fwlog_cfg *cfg);
6056429daeSEric Joyner 
6156429daeSEric Joyner /*
6256429daeSEric Joyner  * dynamic sysctl handlers
6356429daeSEric Joyner  */
6456429daeSEric Joyner static int ice_sysctl_fwlog_set_cfg_options(SYSCTL_HANDLER_ARGS);
6556429daeSEric Joyner static int ice_sysctl_fwlog_log_resolution(SYSCTL_HANDLER_ARGS);
6656429daeSEric Joyner static int ice_sysctl_fwlog_register(SYSCTL_HANDLER_ARGS);
6756429daeSEric Joyner static int ice_sysctl_fwlog_module_log_severity(SYSCTL_HANDLER_ARGS);
6856429daeSEric Joyner 
6956429daeSEric Joyner /**
7056429daeSEric Joyner  * ice_reconfig_fw_log - Re-program firmware logging configuration
7156429daeSEric Joyner  * @sc: private softc structure
7256429daeSEric Joyner  * @cfg: firmware log configuration to latch
7356429daeSEric Joyner  *
7456429daeSEric Joyner  * If the adminq is currently active, ask firmware to update the logging
7556429daeSEric Joyner  * configuration. If the adminq is currently down, then do nothing. In this
7656429daeSEric Joyner  * case, ice_init_hw() will re-configure firmware logging as soon as it brings
7756429daeSEric Joyner  * up the adminq.
7856429daeSEric Joyner  */
7956429daeSEric Joyner static int
ice_reconfig_fw_log(struct ice_softc * sc,struct ice_fwlog_cfg * cfg)8056429daeSEric Joyner ice_reconfig_fw_log(struct ice_softc *sc, struct ice_fwlog_cfg *cfg)
8156429daeSEric Joyner {
8256429daeSEric Joyner 	enum ice_status status;
8356429daeSEric Joyner 
8456429daeSEric Joyner 	ice_fwlog_init(&sc->hw, cfg);
8556429daeSEric Joyner 
8656429daeSEric Joyner 	if (!ice_check_sq_alive(&sc->hw, &sc->hw.adminq))
8756429daeSEric Joyner 		return (0);
8856429daeSEric Joyner 
8956429daeSEric Joyner 	if (!ice_fwlog_supported(&sc->hw))
9056429daeSEric Joyner 		return (0);
9156429daeSEric Joyner 
9256429daeSEric Joyner 	status = ice_fwlog_set(&sc->hw, cfg);
9356429daeSEric Joyner 	if (status) {
9456429daeSEric Joyner 		device_printf(sc->dev,
9556429daeSEric Joyner 		    "Failed to reconfigure firmware logging, err %s aq_err %s\n",
9656429daeSEric Joyner 		    ice_status_str(status),
9756429daeSEric Joyner 		    ice_aq_str(sc->hw.adminq.sq_last_status));
9856429daeSEric Joyner 		return (ENODEV);
9956429daeSEric Joyner 	}
10056429daeSEric Joyner 
10156429daeSEric Joyner 	return (0);
10256429daeSEric Joyner }
10356429daeSEric Joyner 
10456429daeSEric Joyner #define ICE_SYSCTL_HELP_FWLOG_LOG_RESOLUTION				\
10556429daeSEric Joyner "\nControl firmware message limit to send per ARQ event"		\
10656429daeSEric Joyner "\t\nMin: 1"								\
10756429daeSEric Joyner "\t\nMax: 128"
10856429daeSEric Joyner 
10956429daeSEric Joyner #define ICE_SYSCTL_HELP_FWLOG_ARQ_ENA					\
1109c30461dSEric Joyner "\nControl whether to enable/disable reporting to admin Rx queue"	\
11156429daeSEric Joyner "\n0 - Enable firmware reporting via ARQ"				\
11256429daeSEric Joyner "\n1 - Disable firmware reporting via ARQ"
11356429daeSEric Joyner 
11456429daeSEric Joyner #define ICE_SYSCTL_HELP_FWLOG_UART_ENA					\
1159c30461dSEric Joyner "\nControl whether to enable/disable reporting to UART"			\
11656429daeSEric Joyner "\n0 - Enable firmware reporting via UART"				\
11756429daeSEric Joyner "\n1 - Disable firmware reporting via UART"
11856429daeSEric Joyner 
11956429daeSEric Joyner #define ICE_SYSCTL_HELP_FWLOG_ENABLE_ON_LOAD				\
12056429daeSEric Joyner "\nControl whether to enable logging during the attach phase"		\
12156429daeSEric Joyner "\n0 - Enable firmware logging during attach phase"			\
12256429daeSEric Joyner "\n1 - Disable firmware logging during attach phase"
12356429daeSEric Joyner 
12456429daeSEric Joyner #define ICE_SYSCTL_HELP_FWLOG_REGISTER					\
12556429daeSEric Joyner "\nControl whether to enable/disable firmware logging"			\
12656429daeSEric Joyner "\n0 - Enable firmware logging"						\
12756429daeSEric Joyner "\n1 - Disable firmware logging"
12856429daeSEric Joyner 
12956429daeSEric Joyner #define ICE_SYSCTL_HELP_FWLOG_MODULE_SEVERITY				\
13056429daeSEric Joyner "\nControl the level of log output messages for this module"		\
13156429daeSEric Joyner "\n\tverbose <4> - Verbose messages + (Error|Warning|Normal)"		\
13256429daeSEric Joyner "\n\tnormal  <3> - Normal messages  + (Error|Warning)"			\
13356429daeSEric Joyner "\n\twarning <2> - Warning messages + (Error)"				\
13456429daeSEric Joyner "\n\terror   <1> - Error messages"					\
13556429daeSEric Joyner "\n\tnone    <0> - Disables all logging for this module"
13656429daeSEric Joyner 
13756429daeSEric Joyner /**
13856429daeSEric Joyner  * ice_sysctl_fwlog_set_cfg_options - Sysctl for setting fwlog cfg options
13956429daeSEric Joyner  * @oidp: sysctl oid structure
14056429daeSEric Joyner  * @arg1: private softc structure
14156429daeSEric Joyner  * @arg2: option to adjust
14256429daeSEric Joyner  * @req: sysctl request pointer
14356429daeSEric Joyner  *
14456429daeSEric Joyner  * On read: displays whether firmware logging was reported during attachment
14556429daeSEric Joyner  * On write: enables/disables firmware logging during attach phase
14656429daeSEric Joyner  *
14756429daeSEric Joyner  * This has no effect on the legacy (V1) version of firmware logging.
14856429daeSEric Joyner  */
14956429daeSEric Joyner static int
ice_sysctl_fwlog_set_cfg_options(SYSCTL_HANDLER_ARGS)15056429daeSEric Joyner ice_sysctl_fwlog_set_cfg_options(SYSCTL_HANDLER_ARGS)
15156429daeSEric Joyner {
15256429daeSEric Joyner 	struct ice_softc *sc = (struct ice_softc *)arg1;
15356429daeSEric Joyner 	struct ice_fwlog_cfg *cfg = &sc->hw.fwlog_cfg;
15456429daeSEric Joyner 	int error;
15556429daeSEric Joyner 	u16 option = (u16)arg2;
15656429daeSEric Joyner 	bool enabled;
15756429daeSEric Joyner 
15856429daeSEric Joyner 	enabled = !!(cfg->options & option);
15956429daeSEric Joyner 
16056429daeSEric Joyner 	error = sysctl_handle_bool(oidp, &enabled, 0, req);
16156429daeSEric Joyner 	if ((error) || (req->newptr == NULL))
16256429daeSEric Joyner 		return (error);
16356429daeSEric Joyner 
16456429daeSEric Joyner 	if (enabled)
16556429daeSEric Joyner 		cfg->options |= option;
16656429daeSEric Joyner 	else
16756429daeSEric Joyner 		cfg->options &= ~option;
16856429daeSEric Joyner 
16956429daeSEric Joyner 	return ice_reconfig_fw_log(sc, cfg);
17056429daeSEric Joyner }
17156429daeSEric Joyner 
17256429daeSEric Joyner /**
17356429daeSEric Joyner  * ice_sysctl_fwlog_log_resolution - Sysctl for setting log message resolution
17456429daeSEric Joyner  * @oidp: sysctl oid structure
17556429daeSEric Joyner  * @arg1: private softc structure
17656429daeSEric Joyner  * @arg2: __unused__
17756429daeSEric Joyner  * @req: sysctl request pointer
17856429daeSEric Joyner  *
17956429daeSEric Joyner  * On read: displays message queue limit before posting
18056429daeSEric Joyner  * On write: sets message queue limit before posting
18156429daeSEric Joyner  *
18256429daeSEric Joyner  * This has no effect on the legacy (V1) version of firmware logging.
18356429daeSEric Joyner  */
18456429daeSEric Joyner static int
ice_sysctl_fwlog_log_resolution(SYSCTL_HANDLER_ARGS)18556429daeSEric Joyner ice_sysctl_fwlog_log_resolution(SYSCTL_HANDLER_ARGS)
18656429daeSEric Joyner {
18756429daeSEric Joyner 	struct ice_softc *sc = (struct ice_softc *)arg1;
18856429daeSEric Joyner 	struct ice_fwlog_cfg *cfg = &sc->hw.fwlog_cfg;
18956429daeSEric Joyner 	int error;
19056429daeSEric Joyner 	u8 resolution;
19156429daeSEric Joyner 
19256429daeSEric Joyner 	UNREFERENCED_PARAMETER(arg2);
19356429daeSEric Joyner 
19456429daeSEric Joyner 	resolution = cfg->log_resolution;
19556429daeSEric Joyner 
19656429daeSEric Joyner 	error = sysctl_handle_8(oidp, &resolution, 0, req);
19756429daeSEric Joyner 	if ((error) || (req->newptr == NULL))
19856429daeSEric Joyner 		return (error);
19956429daeSEric Joyner 
20056429daeSEric Joyner 	if ((resolution < ICE_AQC_FW_LOG_MIN_RESOLUTION) ||
20156429daeSEric Joyner 	    (resolution > ICE_AQC_FW_LOG_MAX_RESOLUTION)) {
20256429daeSEric Joyner 		device_printf(sc->dev, "Log resolution out-of-bounds\n");
20356429daeSEric Joyner 		return (EINVAL);
20456429daeSEric Joyner 	}
20556429daeSEric Joyner 
20656429daeSEric Joyner 	cfg->log_resolution = resolution;
20756429daeSEric Joyner 
20856429daeSEric Joyner 	return ice_reconfig_fw_log(sc, cfg);
20956429daeSEric Joyner }
21056429daeSEric Joyner 
21156429daeSEric Joyner /**
21256429daeSEric Joyner  * ice_sysctl_fwlog_register - Sysctl for (de)registering firmware logs
21356429daeSEric Joyner  * @oidp: sysctl oid structure
21456429daeSEric Joyner  * @arg1: private softc structure
21556429daeSEric Joyner  * @arg2: __unused__
21656429daeSEric Joyner  * @req: sysctl request pointer
21756429daeSEric Joyner  *
21856429daeSEric Joyner  * On read: displays whether firmware logging is registered
21956429daeSEric Joyner  * On write: (de)registers firmware logging.
22056429daeSEric Joyner  */
22156429daeSEric Joyner static int
ice_sysctl_fwlog_register(SYSCTL_HANDLER_ARGS)22256429daeSEric Joyner ice_sysctl_fwlog_register(SYSCTL_HANDLER_ARGS)
22356429daeSEric Joyner {
22456429daeSEric Joyner 	struct ice_softc *sc = (struct ice_softc *)arg1;
22556429daeSEric Joyner 	struct ice_fwlog_cfg *cfg = &sc->hw.fwlog_cfg;
22656429daeSEric Joyner 	enum ice_status status;
22756429daeSEric Joyner 	int error;
22856429daeSEric Joyner 	u8 enabled;
22956429daeSEric Joyner 
23056429daeSEric Joyner 	UNREFERENCED_PARAMETER(arg2);
23156429daeSEric Joyner 
23256429daeSEric Joyner 	if (ice_test_state(&sc->state, ICE_STATE_ATTACHING)) {
23356429daeSEric Joyner 		device_printf(sc->dev, "Registering FW Logging via kenv is supported with the on_load option\n");
23456429daeSEric Joyner 		return (EIO);
23556429daeSEric Joyner 	}
23656429daeSEric Joyner 
23756429daeSEric Joyner 	if (cfg->options & ICE_FWLOG_OPTION_IS_REGISTERED)
23856429daeSEric Joyner 		enabled = true;
23956429daeSEric Joyner 	else
24056429daeSEric Joyner 		enabled = false;
24156429daeSEric Joyner 
24256429daeSEric Joyner 	error = sysctl_handle_bool(oidp, &enabled, 0, req);
24356429daeSEric Joyner 	if ((error) || (req->newptr == NULL))
24456429daeSEric Joyner 		return (error);
24556429daeSEric Joyner 
24656429daeSEric Joyner 	if (!ice_check_sq_alive(&sc->hw, &sc->hw.adminq))
24756429daeSEric Joyner 		return (0);
24856429daeSEric Joyner 
24956429daeSEric Joyner 	if (enabled) {
25056429daeSEric Joyner 		status = ice_fwlog_register(&sc->hw);
25156429daeSEric Joyner 		if (!status)
25256429daeSEric Joyner 			ice_set_bit(ICE_FEATURE_FW_LOGGING, sc->feat_en);
25356429daeSEric Joyner 	} else {
25456429daeSEric Joyner 		status = ice_fwlog_unregister(&sc->hw);
25556429daeSEric Joyner 		if (!status)
25656429daeSEric Joyner 			ice_clear_bit(ICE_FEATURE_FW_LOGGING, sc->feat_en);
25756429daeSEric Joyner 	}
25856429daeSEric Joyner 
25956429daeSEric Joyner 	if (status)
26056429daeSEric Joyner 		return (EIO);
26156429daeSEric Joyner 
26256429daeSEric Joyner 	return (0);
26356429daeSEric Joyner }
26456429daeSEric Joyner 
26556429daeSEric Joyner /**
26656429daeSEric Joyner  * ice_sysctl_fwlog_module_log_severity - Add tunables for a FW logging module
26756429daeSEric Joyner  * @oidp: sysctl oid structure
26856429daeSEric Joyner  * @arg1: private softc structure
26956429daeSEric Joyner  * @arg2: index to logging module
27056429daeSEric Joyner  * @req: sysctl request pointer
27156429daeSEric Joyner  */
27256429daeSEric Joyner static int
ice_sysctl_fwlog_module_log_severity(SYSCTL_HANDLER_ARGS)27356429daeSEric Joyner ice_sysctl_fwlog_module_log_severity(SYSCTL_HANDLER_ARGS)
27456429daeSEric Joyner {
27556429daeSEric Joyner 	struct ice_softc *sc = (struct ice_softc *)arg1;
27656429daeSEric Joyner 	struct ice_fwlog_cfg *cfg = &sc->hw.fwlog_cfg;
27756429daeSEric Joyner 	struct sbuf *sbuf;
27856429daeSEric Joyner 	char *sev_str_end;
27956429daeSEric Joyner 	enum ice_aqc_fw_logging_mod module = (enum ice_aqc_fw_logging_mod)arg2;
28056429daeSEric Joyner 	int error, ll_num;
28156429daeSEric Joyner 	u8 log_level;
28256429daeSEric Joyner 	char sev_str[16];
28356429daeSEric Joyner 	bool sev_set = false;
28456429daeSEric Joyner 
28556429daeSEric Joyner 	log_level = cfg->module_entries[module].log_level;
28656429daeSEric Joyner 	sbuf = sbuf_new(NULL, sev_str, sizeof(sev_str), SBUF_FIXEDLEN);
28756429daeSEric Joyner 	sbuf_printf(sbuf, "%d<%s>", log_level, ice_log_sev_str(log_level));
28856429daeSEric Joyner 	sbuf_finish(sbuf);
28956429daeSEric Joyner 	sbuf_delete(sbuf);
29056429daeSEric Joyner 
29156429daeSEric Joyner 	error = sysctl_handle_string(oidp, sev_str, sizeof(sev_str), req);
29256429daeSEric Joyner 	if ((error) || (req->newptr == NULL))
29356429daeSEric Joyner 		return (error);
29456429daeSEric Joyner 
29556429daeSEric Joyner 	if (strcasecmp(ice_log_sev_str(ICE_FWLOG_LEVEL_VERBOSE), sev_str) == 0) {
29656429daeSEric Joyner 		log_level = ICE_FWLOG_LEVEL_VERBOSE;
29756429daeSEric Joyner 		sev_set = true;
29856429daeSEric Joyner 	} else if (strcasecmp(ice_log_sev_str(ICE_FWLOG_LEVEL_NORMAL), sev_str) == 0) {
29956429daeSEric Joyner 		log_level = ICE_FWLOG_LEVEL_NORMAL;
30056429daeSEric Joyner 		sev_set = true;
30156429daeSEric Joyner 	} else if (strcasecmp(ice_log_sev_str(ICE_FWLOG_LEVEL_WARNING), sev_str) == 0) {
30256429daeSEric Joyner 		log_level = ICE_FWLOG_LEVEL_WARNING;
30356429daeSEric Joyner 		sev_set = true;
30456429daeSEric Joyner 	} else if (strcasecmp(ice_log_sev_str(ICE_FWLOG_LEVEL_ERROR), sev_str) == 0) {
30556429daeSEric Joyner 		log_level = ICE_FWLOG_LEVEL_ERROR;
30656429daeSEric Joyner 		sev_set = true;
30756429daeSEric Joyner 	} else if (strcasecmp(ice_log_sev_str(ICE_FWLOG_LEVEL_NONE), sev_str) == 0) {
30856429daeSEric Joyner 		log_level = ICE_FWLOG_LEVEL_NONE;
30956429daeSEric Joyner 		sev_set = true;
31056429daeSEric Joyner 	}
31156429daeSEric Joyner 
31256429daeSEric Joyner 	if (!sev_set) {
31356429daeSEric Joyner 		ll_num = strtol(sev_str, &sev_str_end, 0);
31456429daeSEric Joyner 		if (sev_str_end == sev_str)
31556429daeSEric Joyner 			ll_num = -1;
31656429daeSEric Joyner 		if ((ll_num >= ICE_FWLOG_LEVEL_NONE) &&
31756429daeSEric Joyner 		    (ll_num < ICE_FWLOG_LEVEL_INVALID))
31856429daeSEric Joyner 			log_level = ll_num;
31956429daeSEric Joyner 		else {
32056429daeSEric Joyner 			device_printf(sc->dev,
32156429daeSEric Joyner 			    "%s: \"%s\" is not a valid log level\n",
32256429daeSEric Joyner 			    __func__, sev_str);
32356429daeSEric Joyner 			return (EINVAL);
32456429daeSEric Joyner 		}
32556429daeSEric Joyner 	}
32656429daeSEric Joyner 
32756429daeSEric Joyner 	cfg->module_entries[module].log_level = log_level;
32856429daeSEric Joyner 
32956429daeSEric Joyner 	return ice_reconfig_fw_log(sc, cfg);
33056429daeSEric Joyner }
33156429daeSEric Joyner 
33256429daeSEric Joyner /**
33356429daeSEric Joyner  * ice_add_fw_logging_tunables - Add tunables to configure FW logging events
33456429daeSEric Joyner  * @sc: private softc structure
33556429daeSEric Joyner  * @parent: parent node to add the tunables under
33656429daeSEric Joyner  *
33756429daeSEric Joyner  * Add tunables for configuring the firmware logging support. This includes
33856429daeSEric Joyner  * a control to enable the logging, and controls for each module to configure
33956429daeSEric Joyner  * which events to receive.
34056429daeSEric Joyner  */
34156429daeSEric Joyner void
ice_add_fw_logging_tunables(struct ice_softc * sc,struct sysctl_oid * parent)34256429daeSEric Joyner ice_add_fw_logging_tunables(struct ice_softc *sc, struct sysctl_oid *parent)
34356429daeSEric Joyner {
34456429daeSEric Joyner 	struct sysctl_oid_list *parent_list, *fwlog_list, *module_list;
34556429daeSEric Joyner 	struct sysctl_oid *fwlog_node, *module_node;
34656429daeSEric Joyner 	struct sysctl_ctx_list *ctx;
34756429daeSEric Joyner 	struct ice_hw *hw = &sc->hw;
34856429daeSEric Joyner 	struct ice_fwlog_cfg *cfg;
34956429daeSEric Joyner 	device_t dev = sc->dev;
35056429daeSEric Joyner 	enum ice_aqc_fw_logging_mod module;
35156429daeSEric Joyner 	u16 i;
35256429daeSEric Joyner 
35356429daeSEric Joyner 	cfg = &hw->fwlog_cfg;
35456429daeSEric Joyner 	ctx = device_get_sysctl_ctx(dev);
35556429daeSEric Joyner 	parent_list = SYSCTL_CHILDREN(parent);
35656429daeSEric Joyner 
35756429daeSEric Joyner 	fwlog_node = SYSCTL_ADD_NODE(ctx, parent_list, OID_AUTO, "fw_log",
35856429daeSEric Joyner 				     ICE_CTLFLAG_DEBUG | CTLFLAG_RD, NULL,
35956429daeSEric Joyner 				     "Firmware Logging");
36056429daeSEric Joyner 	fwlog_list = SYSCTL_CHILDREN(fwlog_node);
36156429daeSEric Joyner 
36256429daeSEric Joyner 	cfg->log_resolution = 10;
36356429daeSEric Joyner 	SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "log_resolution",
36456429daeSEric Joyner 	    ICE_CTLFLAG_DEBUG | CTLTYPE_U8 | CTLFLAG_RWTUN, sc,
36556429daeSEric Joyner 	    0, ice_sysctl_fwlog_log_resolution,
36656429daeSEric Joyner 	    "CU", ICE_SYSCTL_HELP_FWLOG_LOG_RESOLUTION);
36756429daeSEric Joyner 
36856429daeSEric Joyner 	cfg->options |= ICE_FWLOG_OPTION_ARQ_ENA;
36956429daeSEric Joyner 	SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "arq_en",
37056429daeSEric Joyner 	    ICE_CTLFLAG_DEBUG | CTLTYPE_U8 | CTLFLAG_RWTUN, sc,
37156429daeSEric Joyner 	    ICE_FWLOG_OPTION_ARQ_ENA, ice_sysctl_fwlog_set_cfg_options,
37256429daeSEric Joyner 	    "CU", ICE_SYSCTL_HELP_FWLOG_ARQ_ENA);
37356429daeSEric Joyner 
37456429daeSEric Joyner 	SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "uart_en",
37556429daeSEric Joyner 	    ICE_CTLFLAG_DEBUG | CTLTYPE_U8 | CTLFLAG_RWTUN, sc,
37656429daeSEric Joyner 	    ICE_FWLOG_OPTION_UART_ENA, ice_sysctl_fwlog_set_cfg_options,
37756429daeSEric Joyner 	    "CU", ICE_SYSCTL_HELP_FWLOG_UART_ENA);
37856429daeSEric Joyner 
37956429daeSEric Joyner 	SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "on_load",
38056429daeSEric Joyner 	    ICE_CTLFLAG_DEBUG | CTLTYPE_U8 | CTLFLAG_RWTUN, sc,
38156429daeSEric Joyner 	    ICE_FWLOG_OPTION_REGISTER_ON_INIT, ice_sysctl_fwlog_set_cfg_options,
38256429daeSEric Joyner 	    "CU", ICE_SYSCTL_HELP_FWLOG_ENABLE_ON_LOAD);
38356429daeSEric Joyner 
38456429daeSEric Joyner 	SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "register",
38556429daeSEric Joyner 	    ICE_CTLFLAG_DEBUG | CTLTYPE_U8 | CTLFLAG_RWTUN, sc,
38656429daeSEric Joyner 	    0, ice_sysctl_fwlog_register,
38756429daeSEric Joyner 	    "CU", ICE_SYSCTL_HELP_FWLOG_REGISTER);
38856429daeSEric Joyner 
38956429daeSEric Joyner 	module_node = SYSCTL_ADD_NODE(ctx, fwlog_list, OID_AUTO, "severity",
39056429daeSEric Joyner 				      ICE_CTLFLAG_DEBUG | CTLFLAG_RD, NULL,
39156429daeSEric Joyner 				      "Level of log output");
39256429daeSEric Joyner 
39356429daeSEric Joyner 	module_list = SYSCTL_CHILDREN(module_node);
39456429daeSEric Joyner 
39556429daeSEric Joyner 	for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) {
39656429daeSEric Joyner 		/* Setup some defaults */
39756429daeSEric Joyner 		cfg->module_entries[i].module_id = i;
39856429daeSEric Joyner 		cfg->module_entries[i].log_level = ICE_FWLOG_LEVEL_NONE;
39956429daeSEric Joyner 		module = (enum ice_aqc_fw_logging_mod)i;
40056429daeSEric Joyner 
40156429daeSEric Joyner 		SYSCTL_ADD_PROC(ctx, module_list,
40256429daeSEric Joyner 		    OID_AUTO, ice_fw_module_str(module),
40356429daeSEric Joyner 		    ICE_CTLFLAG_DEBUG | CTLTYPE_STRING | CTLFLAG_RWTUN, sc,
40456429daeSEric Joyner 		    module, ice_sysctl_fwlog_module_log_severity,
40556429daeSEric Joyner 		    "A", ICE_SYSCTL_HELP_FWLOG_MODULE_SEVERITY);
40656429daeSEric Joyner 	}
40756429daeSEric Joyner }
40856429daeSEric Joyner 
40956429daeSEric Joyner /**
41056429daeSEric Joyner  * ice_handle_fw_log_event - Handle a firmware logging event from the AdminQ
41156429daeSEric Joyner  * @sc: pointer to private softc structure
41256429daeSEric Joyner  * @desc: the AdminQ descriptor for this firmware event
41356429daeSEric Joyner  * @buf: pointer to the buffer accompanying the AQ message
41456429daeSEric Joyner  */
41556429daeSEric Joyner void
ice_handle_fw_log_event(struct ice_softc * sc,struct ice_aq_desc * desc,void * buf)41656429daeSEric Joyner ice_handle_fw_log_event(struct ice_softc *sc, struct ice_aq_desc *desc,
41756429daeSEric Joyner 			void *buf)
41856429daeSEric Joyner {
41956429daeSEric Joyner 	/* Trigger a DTrace probe event for this firmware message */
42056429daeSEric Joyner 	SDT_PROBE2(ice_fwlog, , , message, (const u8 *)buf, desc->datalen);
42156429daeSEric Joyner 
42256429daeSEric Joyner 	/* Possibly dump the firmware message to the console, if enabled */
42356429daeSEric Joyner 	ice_fwlog_event_dump(&sc->hw, desc, buf);
42456429daeSEric Joyner }
425