Page MenuHomeFreeBSD

D53973.id167230.diff
No OneTemporary

D53973.id167230.diff

diff --git a/share/man/man4/ix.4 b/share/man/man4/ix.4
--- a/share/man/man4/ix.4
+++ b/share/man/man4/ix.4
@@ -138,7 +138,7 @@
driver supports the following
.Xr sysctl 8
variables:
-.Bl -tag -width "dev.ix.?.debug.dump.clusters"
+.Bl -tag -width "dev.ix.?.debug.fw_log.severity.<module>"
.It Va dev.ix.?.debug.dump.clusters
Specify a bitmask to select firmware event clusters
to be included in the debug dump.
@@ -160,6 +160,38 @@
and decoded by Intel Customer Support.
.Pp
This feature is only supported on E610.
+.It Va dev.ix.?.debug.fw_log.severity.<module>
+Specify firmware logging verbosity level for the specified module.
+Available levels include:
+.Pp
+.Bl -tag -compact
+.It 0
+none
+.It 1
+error
+.It 2
+warning
+.It 3
+normal
+.It 4
+verbose
+.El
+.Pp
+Supported modules: general, ctrl, link, link_topo, dnl, i2c, sdp, mdio,
+adminq, hdma, lldp, dcbx, dcb, xlr, nvm, auth, vpd, iosf, parser, sw,
+scheduler, txq, acl, post, watchdog, task_dispatch, mng, synce, health,
+tsdrv, pfreg, mdlver.
+.Pp
+This feature is only supported on E610 devices.
+.It Va dev.ix.?.debug.fw_log.register
+Specify 1 to apply per-device firmware logging configuration.
+.Pp
+This feature is only supported on E610 devices.
+.It Va dev.ix.?.debug.fw_log.on_load
+Enable firmware logging during driver initialization when set via
+.Xr kenv 1 .
+.Pp
+This feature is only supported on E610 devices.
.El
.Sh DIAGNOSTICS
.Bl -diag
diff --git a/sys/conf/files b/sys/conf/files
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -2302,6 +2302,8 @@
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
dev/ixgbe/ixgbe_common.c optional ix inet | ixv inet \
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
+dev/ixgbe/ixgbe_fw_logging.c optional ix inet | ixv inet \
+ compile-with "${NORMAL_C} -I$S/dev/ixgbe"
dev/ixgbe/ixgbe_mbx.c optional ix inet | ixv inet \
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
dev/ixgbe/ixgbe_vf.c optional ix inet | ixv inet \
diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c
--- a/sys/dev/ixgbe/if_ix.c
+++ b/sys/dev/ixgbe/if_ix.c
@@ -1118,10 +1118,13 @@
break;
}
- /* Check the FW API version */
- if (hw->mac.type == ixgbe_mac_E610 && ixgbe_check_fw_api_version(sc)) {
- error = EIO;
- goto err_pci;
+ /* Check the FW API version and enable FW logging support for E610 */
+ if (hw->mac.type == ixgbe_mac_E610) {
+ if (ixgbe_check_fw_api_version(sc)) {
+ error = EIO;
+ goto err_pci;
+ }
+ ixgbe_fwlog_set_support_ena(hw);
}
/* Most of the iflib initialization... */
@@ -3395,6 +3398,9 @@
if (sc->feat_en & IXGBE_FEATURE_DBG_DUMP)
ixgbe_add_debug_dump_sysctls(sc);
+
+ if (sc->feat_en & IXGBE_FEATURE_FW_LOGGING)
+ ixgbe_add_fw_logging_tunables(sc, sc->debug_sysctls);
} /* ixgbe_add_debug_sysctls */
/************************************************************************
@@ -4491,6 +4497,10 @@
sc->task_requests |= IXGBE_REQUEST_TASK_LSC;
break;
+ case ixgbe_aci_opc_fw_logs_event:
+ ixgbe_fwlog_event_dump(&sc->hw, &event.desc, event.msg_buf);
+ break;
+
case ixgbe_aci_opc_temp_tca_event:
if (hw->adapter_stopped == FALSE)
ixgbe_if_stop(ctx);
diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h
--- a/sys/dev/ixgbe/ixgbe.h
+++ b/sys/dev/ixgbe/ixgbe.h
@@ -607,6 +607,11 @@
void ixgbe_free_receive_structures(struct ixgbe_softc *);
int ixgbe_get_regs(SYSCTL_HANDLER_ARGS);
+void ixgbe_add_fw_logging_tunables(struct ixgbe_softc *sc,
+ struct sysctl_oid *parent);
+
+#define IXGBE_STR_BUF_LEN 32
+
#include "ixgbe_bypass.h"
#include "ixgbe_fdir.h"
#include "ixgbe_rss.h"
diff --git a/sys/dev/ixgbe/ixgbe_e610.h b/sys/dev/ixgbe/ixgbe_e610.h
--- a/sys/dev/ixgbe/ixgbe_e610.h
+++ b/sys/dev/ixgbe/ixgbe_e610.h
@@ -169,6 +169,19 @@
s32 ixgbe_aci_set_health_status_config(struct ixgbe_hw *hw, u8 event_source);
+s32 ixgbe_fwlog_init(struct ixgbe_hw *hw, struct ixgbe_fwlog_cfg *cfg);
+bool ixgbe_fwlog_supported(struct ixgbe_hw *hw);
+s32 ixgbe_fwlog_set(struct ixgbe_hw *hw, struct ixgbe_fwlog_cfg *cfg);
+s32 ixgbe_fwlog_update_modules(struct ixgbe_hw *hw,
+ struct ixgbe_fwlog_module_entry *entries,
+ u16 num_entries);
+s32 ixgbe_fwlog_register(struct ixgbe_hw *hw);
+s32 ixgbe_fwlog_unregister(struct ixgbe_hw *hw);
+void ixgbe_fwlog_set_support_ena(struct ixgbe_hw *hw);
+s32 ixgbe_fwlog_get(struct ixgbe_hw *hw, struct ixgbe_fwlog_cfg *cfg);
+void ixgbe_fwlog_event_dump(struct ixgbe_hw *hw,
+ struct ixgbe_aci_desc *desc, void *buf);
+
/* E610 operations */
s32 ixgbe_init_ops_E610(struct ixgbe_hw *hw);
s32 ixgbe_reset_hw_E610(struct ixgbe_hw *hw);
diff --git a/sys/dev/ixgbe/ixgbe_e610.c b/sys/dev/ixgbe/ixgbe_e610.c
--- a/sys/dev/ixgbe/ixgbe_e610.c
+++ b/sys/dev/ixgbe/ixgbe_e610.c
@@ -3811,6 +3811,492 @@
}
}
+/**
+ * ixgbe_fwlog_cache_cfg - Cache FW logging config
+ * @hw: pointer to the HW structure
+ * @cfg: config to cache
+ *
+ * Cache FW logging config.
+ */
+static void ixgbe_fwlog_cache_cfg(struct ixgbe_hw *hw,
+ struct ixgbe_fwlog_cfg *cfg)
+{
+ hw->fwlog_cfg = *cfg;
+}
+
+/**
+ * ixgbe_fwlog_valid_module_entries - validate all the module entry IDs and
+ * log levels
+ * @hw: pointer to the HW structure
+ * @entries: entries to validate
+ * @num_entries: number of entries to validate
+ *
+ * Checks if all the module entry IDs and log levels are valid.
+ *
+ * Return: true if all the module entry IDs and log levels are valid,
+ * otherwise false.
+ */
+static bool ixgbe_fwlog_valid_module_entries(struct ixgbe_hw *hw,
+ struct ixgbe_fwlog_module_entry *entries,
+ u16 num_entries)
+{
+ u16 i;
+
+ UNREFERENCED_1PARAMETER(hw);
+
+ if (!entries) {
+ return false;
+ }
+
+ if (!num_entries) {
+ return false;
+ }
+
+ for (i = 0; i < num_entries; i++) {
+ struct ixgbe_fwlog_module_entry *entry = &entries[i];
+
+ if (entry->module_id >= IXGBE_ACI_FW_LOG_ID_MAX) {
+ return false;
+ }
+
+ if (entry->log_level >= IXGBE_FWLOG_LEVEL_INVALID) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * ixgbe_fwlog_valid_cfg - validate configuration
+ * @hw: pointer to the HW structure
+ * @cfg: config to validate
+ *
+ * Validate the entire configuration.
+ *
+ * Return: true if the entire configuration is valid, otherwise false.
+ */
+static bool ixgbe_fwlog_valid_cfg(struct ixgbe_hw *hw,
+ struct ixgbe_fwlog_cfg *cfg)
+{
+ if (!cfg) {
+ return false;
+ }
+
+ if (cfg->log_resolution < IXGBE_ACI_FW_LOG_MIN_RESOLUTION ||
+ cfg->log_resolution > IXGBE_ACI_FW_LOG_MAX_RESOLUTION) {
+ return false;
+ }
+
+ if (!ixgbe_fwlog_valid_module_entries(hw, cfg->module_entries,
+ IXGBE_ACI_FW_LOG_ID_MAX))
+ return false;
+
+ return true;
+}
+
+/**
+ * ixgbe_fwlog_init - Initialize cached structures for tracking FW logging
+ * @hw: pointer to the HW structure
+ * @cfg: config used to initialize the cached structures
+ *
+ * Initialize cached structures for tracking FW logging
+ * Called on driver initialization and before calling
+ * ixgbe_init_hw(). Firmware logging will be configured based on these settings
+ * and also the PF will be registered on init.
+ *
+ * Return: the exit code of the operation.
+ */
+s32 ixgbe_fwlog_init(struct ixgbe_hw *hw, struct ixgbe_fwlog_cfg *cfg)
+{
+ if (!ixgbe_fwlog_valid_cfg(hw, cfg))
+ return IXGBE_ERR_PARAM;
+
+ ixgbe_fwlog_cache_cfg(hw, cfg);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_aci_fwlog_set - Set FW logging configuration
+ * @hw: pointer to the HW structure
+ * @entries: entries to configure
+ * @num_entries: number of @entries
+ * @options: options from ixgbe_fwlog_cfg->options structure
+ * @log_resolution: logging resolution
+ *
+ * Set FW logging configuration using ACI command (0xFF30).
+ *
+ * Return: the exit code of the operation.
+ */
+static s32 ixgbe_aci_fwlog_set(struct ixgbe_hw *hw,
+ struct ixgbe_fwlog_module_entry *entries,
+ u16 num_entries, u16 options, u16 log_resolution)
+{
+ struct ixgbe_aci_cmd_fw_log_cfg_resp fw_modules[IXGBE_ACI_FW_LOG_ID_MAX];
+ struct ixgbe_aci_cmd_fw_log *cmd;
+ struct ixgbe_aci_desc desc;
+ s32 status;
+ u16 i;
+
+ if (num_entries > IXGBE_ACI_FW_LOG_ID_MAX)
+ return IXGBE_ERR_PARAM;
+
+ for (i = 0; i < num_entries; i++) {
+ fw_modules[i].module_identifier =
+ IXGBE_CPU_TO_LE16(entries[i].module_id);
+ fw_modules[i].log_level = entries[i].log_level;
+ }
+
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_fw_logs_config);
+ desc.flags |= IXGBE_CPU_TO_LE16(IXGBE_ACI_FLAG_RD);
+
+ cmd = &desc.params.fw_log;
+
+ cmd->cmd_flags = IXGBE_ACI_FW_LOG_CONF_SET_VALID;
+ cmd->ops.cfg.log_resolution = IXGBE_CPU_TO_LE16(log_resolution);
+ cmd->ops.cfg.mdl_cnt = IXGBE_CPU_TO_LE16(num_entries);
+
+ if (options & IXGBE_FWLOG_OPTION_ARQ_ENA)
+ cmd->cmd_flags |= IXGBE_ACI_FW_LOG_CONF_AQ_EN;
+ if (options & IXGBE_FWLOG_OPTION_UART_ENA)
+ cmd->cmd_flags |= IXGBE_ACI_FW_LOG_CONF_UART_EN;
+
+ status = ixgbe_aci_send_cmd(hw, &desc, fw_modules,
+ sizeof(*fw_modules) * num_entries);
+
+ return status;
+}
+
+/**
+ * ixgbe_fwlog_supported - Cached for whether FW supports FW logging or not
+ * @hw: pointer to the HW structure
+ *
+ * This will always return false if called before ixgbe_init_hw(), so it must be
+ * called after ixgbe_init_hw().
+ *
+ * Return: true if FW supports FW logging.
+ * If this function is called before ixgbe_init_hw(), return false.
+ */
+bool ixgbe_fwlog_supported(struct ixgbe_hw *hw)
+{
+ return hw->fwlog_support_ena;
+}
+
+/**
+ * ixgbe_fwlog_set - Set the firmware logging settings
+ * @hw: pointer to the HW structure
+ * @cfg: config used to set firmware logging
+ *
+ * Call this function whenever the driver needs to set the firmware
+ * logging configuration. It can be called on initialization, reset, or during
+ * runtime.
+ *
+ * If the PF wishes to receive FW logging then it must register via
+ * ixgbe_fwlog_register. Note, that ixgbe_fwlog_register does not need to
+ * be called for init.
+ *
+ * Return: the exit code of the operation.
+ */
+s32 ixgbe_fwlog_set(struct ixgbe_hw *hw, struct ixgbe_fwlog_cfg *cfg)
+{
+ s32 status;
+
+ if (!ixgbe_fwlog_supported(hw))
+ return IXGBE_ERR_NOT_SUPPORTED;
+
+ if (!ixgbe_fwlog_valid_cfg(hw, cfg))
+ return IXGBE_ERR_PARAM;
+
+ status = ixgbe_aci_fwlog_set(hw, cfg->module_entries,
+ IXGBE_ACI_FW_LOG_ID_MAX, cfg->options,
+ cfg->log_resolution);
+ if (!status)
+ ixgbe_fwlog_cache_cfg(hw, cfg);
+
+ return status;
+}
+
+/**
+ * ixgbe_fwlog_update_cached_entries - Update module entries in cached
+ * FW logging config
+ * @hw: pointer to the HW structure
+ * @entries: entries to cache
+ * @num_entries: number of @entries
+ *
+ * Update module entries in cached FW logging config.
+ */
+static void ixgbe_fwlog_update_cached_entries(struct ixgbe_hw *hw,
+ struct ixgbe_fwlog_module_entry *entries,
+ u16 num_entries)
+{
+ u16 i;
+
+ for (i = 0; i < num_entries; i++) {
+ struct ixgbe_fwlog_module_entry *updated = &entries[i];
+ u16 j;
+
+ for (j = 0; j < IXGBE_ACI_FW_LOG_ID_MAX; j++) {
+ struct ixgbe_fwlog_module_entry *cached =
+ &hw->fwlog_cfg.module_entries[j];
+
+ if (cached->module_id == updated->module_id) {
+ cached->log_level = updated->log_level;
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * ixgbe_fwlog_update_modules - Update the log level 1 or more
+ * FW logging modules
+ * @hw: pointer to the HW structure
+ * @entries: array of ixgbe_fwlog_module_entry(s)
+ * @num_entries: number of entries
+ *
+ * Update the log level of 1 or more FW logging modules via module ID.
+ *
+ * Only the entries passed in will be affected. All other firmware logging
+ * settings will be unaffected.
+ *
+ * Return: the exit code of the operation.
+ */
+s32 ixgbe_fwlog_update_modules(struct ixgbe_hw *hw,
+ struct ixgbe_fwlog_module_entry *entries,
+ u16 num_entries)
+{
+ struct ixgbe_fwlog_cfg cfg;
+ s32 status;
+
+ if (!ixgbe_fwlog_supported(hw))
+ return IXGBE_ERR_NOT_SUPPORTED;
+
+ if (num_entries > IXGBE_ACI_FW_LOG_ID_MAX)
+ return IXGBE_ERR_PARAM;
+
+ if (!ixgbe_fwlog_valid_module_entries(hw, entries, num_entries))
+ return IXGBE_ERR_PARAM;
+
+ status = ixgbe_fwlog_get(hw, &cfg);
+ if (status)
+ goto status_out;
+
+ status = ixgbe_aci_fwlog_set(hw, entries, num_entries, cfg.options,
+ cfg.log_resolution);
+ if (!status)
+ ixgbe_fwlog_update_cached_entries(hw, entries, num_entries);
+
+status_out:
+ return status;
+}
+
+/**
+ * ixgbe_aci_fwlog_register - Register PF for firmware logging events.
+ * @hw: pointer to the HW structure
+ * @reg: true to register and false to unregister
+ *
+ * Register a PF for firmware logging events using ACI command (0xFF31).
+ *
+ * Return: the exit code of the operation.
+ */
+static s32 ixgbe_aci_fwlog_register(struct ixgbe_hw *hw, bool reg)
+{
+ struct ixgbe_aci_desc desc;
+
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_fw_logs_register);
+
+ if (reg)
+ desc.params.fw_log.cmd_flags = IXGBE_ACI_FW_LOG_AQ_REGISTER;
+
+ return ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
+}
+
+/**
+ * ixgbe_fwlog_register - Register the PF for firmware logging
+ * @hw: pointer to the HW structure
+ *
+ * After this call the PF will start to receive firmware logging based on the
+ * configuration set in ixgbe_fwlog_set.
+ *
+ * Return: the exit code of the operation.
+ */
+s32 ixgbe_fwlog_register(struct ixgbe_hw *hw)
+{
+ s32 status;
+
+ if (!ixgbe_fwlog_supported(hw))
+ return IXGBE_ERR_NOT_SUPPORTED;
+
+ status = ixgbe_aci_fwlog_register(hw, true);
+
+ if (!status)
+ hw->fwlog_cfg.options |= IXGBE_FWLOG_OPTION_IS_REGISTERED;
+
+ return status;
+}
+
+/**
+ * ixgbe_fwlog_unregister - Unregister the PF from firmware logging
+ * @hw: pointer to the HW structure
+ *
+ * Make an attempt to unregister the PF from firmware logging.
+ *
+ * Return: the exit code of the operation.
+ */
+s32 ixgbe_fwlog_unregister(struct ixgbe_hw *hw)
+{
+ s32 status;
+
+ if (!ixgbe_fwlog_supported(hw))
+ return IXGBE_ERR_NOT_SUPPORTED;
+
+ status = ixgbe_aci_fwlog_register(hw, false);
+ if (!status)
+ hw->fwlog_cfg.options &= ~IXGBE_FWLOG_OPTION_IS_REGISTERED;
+
+ return status;
+}
+
+/**
+ * ixgbe_aci_fwlog_get - Get the current firmware logging configuration
+ * @hw: pointer to the HW structure
+ * @cfg: firmware logging configuration to populate
+ *
+ * Make an attempt to get the current firmware logging
+ * configuration using ACI command (0xFF32).
+ *
+ * Return: the exit code of the operation.
+ */
+static s32 ixgbe_aci_fwlog_get(struct ixgbe_hw *hw, struct ixgbe_fwlog_cfg *cfg)
+{
+ struct ixgbe_aci_cmd_fw_log_cfg_resp *fw_modules;
+ struct ixgbe_aci_cmd_fw_log *cmd;
+ struct ixgbe_aci_desc desc;
+ u16 i, module_id_cnt;
+ u8 *buf = NULL;
+ s32 status;
+
+ memset(cfg, 0, sizeof(*cfg));
+
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_fw_logs_query);
+ cmd = &desc.params.fw_log;
+
+ cmd->cmd_flags = IXGBE_ACI_FW_LOG_AQ_QUERY;
+
+ buf = (u8 *)ixgbe_malloc(hw, IXGBE_ACI_MAX_BUFFER_SIZE);
+ if (!buf)
+ return IXGBE_ERR_OUT_OF_MEM;
+
+ status = ixgbe_aci_send_cmd(hw, &desc, buf, IXGBE_ACI_MAX_BUFFER_SIZE);
+ if (status) {
+ goto status_out;
+ }
+
+ module_id_cnt = IXGBE_LE16_TO_CPU(cmd->ops.cfg.mdl_cnt);
+ if (module_id_cnt > IXGBE_ACI_FW_LOG_ID_MAX) {
+ module_id_cnt = IXGBE_ACI_FW_LOG_ID_MAX;
+ }
+
+ cfg->log_resolution = (u8)IXGBE_LE16_TO_CPU(cmd->ops.cfg.log_resolution);
+ if (cmd->cmd_flags & IXGBE_ACI_FW_LOG_CONF_AQ_EN)
+ cfg->options |= IXGBE_FWLOG_OPTION_ARQ_ENA;
+ if (cmd->cmd_flags & IXGBE_ACI_FW_LOG_CONF_UART_EN)
+ cfg->options |= IXGBE_FWLOG_OPTION_UART_ENA;
+ if (cmd->cmd_flags & IXGBE_ACI_FW_LOG_QUERY_REGISTERED)
+ cfg->options |= IXGBE_FWLOG_OPTION_IS_REGISTERED;
+
+ fw_modules = (struct ixgbe_aci_cmd_fw_log_cfg_resp *)buf;
+
+ for (i = 0; i < module_id_cnt; i++) {
+ struct ixgbe_aci_cmd_fw_log_cfg_resp *fw_module = &fw_modules[i];
+
+ cfg->module_entries[i].module_id =
+ IXGBE_LE16_TO_CPU(fw_module->module_identifier);
+ cfg->module_entries[i].log_level = fw_module->log_level;
+ }
+
+status_out:
+ if (buf)
+ ixgbe_free(hw, buf);
+ return status;
+}
+
+/**
+ * ixgbe_fwlog_set_support_ena - Set if FW logging is supported by FW
+ * @hw: pointer to the HW struct
+ *
+ * If FW returns success to the ixgbe_aci_fwlog_get call then it supports FW
+ * logging, else it doesn't. Set the fwlog_support_ena flag accordingly.
+ *
+ * This function is only meant to be called during driver init to determine if
+ * the FW support FW logging.
+ *
+ * Return: the exit code of the operation.
+ */
+void ixgbe_fwlog_set_support_ena(struct ixgbe_hw *hw)
+{
+ struct ixgbe_fwlog_cfg cfg;
+ s32 status;
+
+ hw->fwlog_support_ena = false;
+
+ /* don't call ixgbe_fwlog_get() because that would overwrite the cached
+ * configuration from the call to ixgbe_fwlog_init(), which is expected
+ * to be called prior to this function
+ */
+ status = ixgbe_aci_fwlog_get(hw, &cfg);
+ if (!status)
+ hw->fwlog_support_ena = true;
+}
+
+/**
+ * ixgbe_fwlog_get - Get the firmware logging settings
+ * @hw: pointer to the HW structure
+ * @cfg: config to populate based on current firmware logging settings
+ *
+ * Get the current firmware logging settings.
+ *
+ * Return: the exit code of the operation.
+ */
+s32 ixgbe_fwlog_get(struct ixgbe_hw *hw, struct ixgbe_fwlog_cfg *cfg)
+{
+ s32 status;
+
+ if (!ixgbe_fwlog_supported(hw))
+ return IXGBE_ERR_NOT_SUPPORTED;
+
+ if (!cfg)
+ return IXGBE_ERR_PARAM;
+
+ status = ixgbe_aci_fwlog_get(hw, cfg);
+ if (status)
+ return status;
+
+ ixgbe_fwlog_cache_cfg(hw, cfg);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_fwlog_event_dump - Dump the event received over the Admin Receive Queue
+ * @hw: pointer to the HW structure
+ * @desc: Admin Receive Queue descriptor
+ * @buf: buffer that contains the FW log event data
+ *
+ * If the driver receives the ixgbe_aci_opc_fw_logs_event on the Admin Receive
+ * Queue, then it should call this function to dump the FW log data.
+ */
+void ixgbe_fwlog_event_dump(struct ixgbe_hw *hw,
+ struct ixgbe_aci_desc *desc, void *buf)
+{
+ if (!ixgbe_fwlog_supported(hw))
+ return;
+
+ ixgbe_info_fwlog(hw, 32, 1, (u8 *)buf,
+ IXGBE_LE16_TO_CPU(desc->datalen));
+}
+
/**
* ixgbe_aci_set_health_status_config - Configure FW health events
* @hw: pointer to the HW struct
diff --git a/sys/dev/ixgbe/ixgbe_features.h b/sys/dev/ixgbe/ixgbe_features.h
--- a/sys/dev/ixgbe/ixgbe_features.h
+++ b/sys/dev/ixgbe/ixgbe_features.h
@@ -58,6 +58,7 @@
#define IXGBE_FEATURE_NEEDS_CTXD (u32)(1 << 13)
#define IXGBE_FEATURE_RECOVERY_MODE (u32)(1 << 15)
#define IXGBE_FEATURE_DBG_DUMP (u32)(1 << 16)
+#define IXGBE_FEATURE_FW_LOGGING (u32)(1 << 17)
/* Check for OS support. Undefine features if not included in the OS */
#ifndef PCI_IOV
diff --git a/sys/dev/ixgbe/ixgbe_fw_logging.c b/sys/dev/ixgbe/ixgbe_fw_logging.c
new file mode 100644
--- /dev/null
+++ b/sys/dev/ixgbe/ixgbe_fw_logging.c
@@ -0,0 +1,467 @@
+/**
+ * @file ixgbe_fw_logging.c
+ * @brief firmware logging sysctls
+ *
+ * Contains sysctls to enable and configure firmware logging debug support.
+ */
+
+ #include "ixgbe.h"
+
+ /**
+ * ixgbe_reconfig_fw_log - Re-program firmware logging configuration
+ * @sc: private softc structure
+ * @cfg: firmware log configuration to latch
+ *
+ * If the adminq is currently active, ask firmware to update the logging
+ * configuration. If the adminq is currently down, then do nothing. In this
+ * case, ixgbe_init_hw() will re-configure firmware logging as soon as it brings
+ * up the adminq.
+ */
+ static int
+ ixgbe_reconfig_fw_log(struct ixgbe_softc *sc, struct ixgbe_fwlog_cfg *cfg)
+ {
+ int status;
+
+ ixgbe_fwlog_init(&sc->hw, cfg);
+
+ if (!ixgbe_fwlog_supported(&sc->hw))
+ return (0);
+
+ status = ixgbe_fwlog_set(&sc->hw, cfg);
+ if (status != IXGBE_SUCCESS) {
+ DEBUGOUT1("Failed to reconfigure firmware logging, status %d\n",
+ status);
+ return (ENODEV);
+ }
+
+ return (0);
+ }
+
+ /**
+ * ixgbe_sysctl_fwlog_set_cfg_options - Sysctl for setting fwlog cfg options
+ * @oidp: sysctl oid structure
+ * @arg1: private softc structure
+ * @arg2: option to adjust
+ * @req: sysctl request pointer
+ *
+ * On read: displays whether firmware logging was reported during attachment
+ * On write: enables/disables firmware logging during attach phase
+ *
+ * This has no effect on the legacy (V1) version of firmware logging.
+ */
+ static int
+ ixgbe_sysctl_fwlog_set_cfg_options(SYSCTL_HANDLER_ARGS)
+ {
+ struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1;
+ struct ixgbe_fwlog_cfg *cfg = &sc->hw.fwlog_cfg;
+ int error;
+ u16 option = (u16)arg2;
+ bool enabled;
+
+ enabled = !!(cfg->options & option);
+
+ error = sysctl_handle_bool(oidp, &enabled, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ if (enabled)
+ cfg->options |= option;
+ else
+ cfg->options &= ~option;
+
+ return ixgbe_reconfig_fw_log(sc, cfg);
+ }
+
+ /**
+ * ixgbe_sysctl_fwlog_log_resolution - Sysctl for setting log message resolution
+ * @oidp: sysctl oid structure
+ * @arg1: private softc structure
+ * @arg2: __unused__
+ * @req: sysctl request pointer
+ *
+ * On read: displays message queue limit before posting
+ * On write: sets message queue limit before posting
+ *
+ * This has no effect on the legacy (V1) version of firmware logging.
+ */
+ static int
+ ixgbe_sysctl_fwlog_log_resolution(SYSCTL_HANDLER_ARGS)
+ {
+ struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1;
+ struct ixgbe_fwlog_cfg *cfg = &sc->hw.fwlog_cfg;
+ int error;
+ u8 resolution;
+
+ UNREFERENCED_PARAMETER(arg2);
+
+ resolution = cfg->log_resolution;
+
+ error = sysctl_handle_8(oidp, &resolution, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ if ((resolution < IXGBE_ACI_FW_LOG_MIN_RESOLUTION) ||
+ (resolution > IXGBE_ACI_FW_LOG_MAX_RESOLUTION)) {
+ DEBUGOUT("Log resolution out-of-bounds\n");
+ return (EINVAL);
+ }
+
+ cfg->log_resolution = resolution;
+
+ return ixgbe_reconfig_fw_log(sc, cfg);
+ }
+
+ /**
+ * ixgbe_sysctl_fwlog_register - Sysctl for (de)registering firmware logs
+ * @oidp: sysctl oid structure
+ * @arg1: private softc structure
+ * @arg2: __unused__
+ * @req: sysctl request pointer
+ *
+ * On read: displays whether firmware logging is registered
+ * On write: (de)registers firmware logging.
+ */
+ static int
+ ixgbe_sysctl_fwlog_register(SYSCTL_HANDLER_ARGS)
+ {
+ struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1;
+ struct ixgbe_fwlog_cfg *cfg = &sc->hw.fwlog_cfg;
+ int status;
+ int error;
+ u8 enabled;
+
+ UNREFERENCED_PARAMETER(arg2);
+
+ if (cfg->options & IXGBE_FWLOG_OPTION_IS_REGISTERED)
+ enabled = true;
+ else
+ enabled = false;
+
+ error = sysctl_handle_bool(oidp, &enabled, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ if (enabled) {
+ status = ixgbe_fwlog_register(&sc->hw);
+ if (status == IXGBE_SUCCESS)
+ sc->feat_en |= IXGBE_FEATURE_FW_LOGGING;
+ } else {
+ status = ixgbe_fwlog_unregister(&sc->hw);
+ if (status == IXGBE_SUCCESS)
+ sc->feat_en &= ~IXGBE_FEATURE_FW_LOGGING;
+ }
+
+ if (status != IXGBE_SUCCESS)
+ return (EIO);
+
+ return (0);
+ }
+
+ /**
+ * ixgbe_log_sev_str - Convert log level to a string
+ * @log_level: the log level to convert
+ *
+ * Convert the u8 log level of a FW logging module into a readable
+ * string for outputting in a sysctl.
+ */
+ struct ixgbe_str_buf {
+ char str[IXGBE_STR_BUF_LEN];
+ };
+
+ static struct ixgbe_str_buf
+ _ixgbe_log_sev_str(u8 log_level)
+ {
+ struct ixgbe_str_buf buf = { .str = "" };
+ const char *str = NULL;
+
+ switch (log_level) {
+ case IXGBE_FWLOG_LEVEL_NONE:
+ str = "none";
+ break;
+ case IXGBE_FWLOG_LEVEL_ERROR:
+ str = "error";
+ break;
+ case IXGBE_FWLOG_LEVEL_WARNING:
+ str = "warning";
+ break;
+ case IXGBE_FWLOG_LEVEL_NORMAL:
+ str = "normal";
+ break;
+ case IXGBE_FWLOG_LEVEL_VERBOSE:
+ str = "verbose";
+ break;
+ default:
+ break;
+ }
+
+ if (str)
+ snprintf(buf.str, IXGBE_STR_BUF_LEN, "%s", str);
+ else
+ snprintf(buf.str, IXGBE_STR_BUF_LEN, "%u", log_level);
+
+ return buf;
+ }
+
+ #define ixgbe_log_sev_str(log_level) _ixgbe_log_sev_str(log_level).str
+
+ /**
+ * ixgbe_sysctl_fwlog_module_log_severity - Add tunables for a FW logging module
+ * @oidp: sysctl oid structure
+ * @arg1: private softc structure
+ * @arg2: index to logging module
+ * @req: sysctl request pointer
+ */
+ static int
+ ixgbe_sysctl_fwlog_module_log_severity(SYSCTL_HANDLER_ARGS)
+ {
+ struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1;
+ struct ixgbe_fwlog_cfg *cfg = &sc->hw.fwlog_cfg;
+ struct sbuf *sbuf;
+ char *sev_str_end;
+ enum ixgbe_aci_fw_logging_mod module = (enum ixgbe_aci_fw_logging_mod)arg2;
+ int error, ll_num;
+ u8 log_level;
+ char sev_str[16];
+ bool sev_set = false;
+
+ log_level = cfg->module_entries[module].log_level;
+ sbuf = sbuf_new(NULL, sev_str, sizeof(sev_str), SBUF_FIXEDLEN);
+ sbuf_printf(sbuf, "%d<%s>", log_level, ixgbe_log_sev_str(log_level));
+ sbuf_finish(sbuf);
+ sbuf_delete(sbuf);
+
+ error = sysctl_handle_string(oidp, sev_str, sizeof(sev_str), req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ if (strcasecmp(ixgbe_log_sev_str(IXGBE_FWLOG_LEVEL_VERBOSE), sev_str) == 0) {
+ log_level = IXGBE_FWLOG_LEVEL_VERBOSE;
+ sev_set = true;
+ } else if (strcasecmp(ixgbe_log_sev_str(IXGBE_FWLOG_LEVEL_NORMAL), sev_str) == 0) {
+ log_level = IXGBE_FWLOG_LEVEL_NORMAL;
+ sev_set = true;
+ } else if (strcasecmp(ixgbe_log_sev_str(IXGBE_FWLOG_LEVEL_WARNING), sev_str) == 0) {
+ log_level = IXGBE_FWLOG_LEVEL_WARNING;
+ sev_set = true;
+ } else if (strcasecmp(ixgbe_log_sev_str(IXGBE_FWLOG_LEVEL_ERROR), sev_str) == 0) {
+ log_level = IXGBE_FWLOG_LEVEL_ERROR;
+ sev_set = true;
+ } else if (strcasecmp(ixgbe_log_sev_str(IXGBE_FWLOG_LEVEL_NONE), sev_str) == 0) {
+ log_level = IXGBE_FWLOG_LEVEL_NONE;
+ sev_set = true;
+ }
+
+ if (!sev_set) {
+ ll_num = strtol(sev_str, &sev_str_end, 0);
+ if (sev_str_end == sev_str)
+ ll_num = -1;
+ if ((ll_num >= IXGBE_FWLOG_LEVEL_NONE) &&
+ (ll_num < IXGBE_FWLOG_LEVEL_INVALID))
+ log_level = ll_num;
+ else {
+ DEBUGOUT2("%s: \"%s\" is not a valid log level\n",
+ __func__, sev_str);
+ return (EINVAL);
+ }
+ }
+
+ cfg->module_entries[module].log_level = log_level;
+
+ return ixgbe_reconfig_fw_log(sc, cfg);
+ }
+
+ #define IXGBE_SYSCTL_HELP_FWLOG_LOG_RESOLUTION \
+ "\nControl firmware message limit to send per ARQ event" \
+ "\t\nMin: 1" \
+ "\t\nMax: 128"
+
+ #define IXGBE_SYSCTL_HELP_FWLOG_ARQ_ENA \
+ "\nControl whether to enable/disable reporting to admin Rx queue" \
+ "\n1 - Enable firmware reporting via ARQ" \
+ "\n0 - Disable firmware reporting via ARQ"
+
+ #define IXGBE_SYSCTL_HELP_FWLOG_UART_ENA \
+ "\nControl whether to enable/disable reporting to UART" \
+ "\n1 - Enable firmware reporting via UART" \
+ "\n0 - Disable firmware reporting via UART"
+
+ #define IXGBE_SYSCTL_HELP_FWLOG_ENABLE_ON_LOAD \
+ "\nControl whether to enable logging during the attach phase" \
+ "\n1 - Enable firmware logging during attach phase" \
+ "\n0 - Disable firmware logging during attach phase"
+
+ #define IXGBE_SYSCTL_HELP_FWLOG_REGISTER \
+ "\nControl whether to enable/disable firmware logging" \
+ "\n1 - Enable firmware logging" \
+ "\n0 - Disable firmware logging"
+
+ #define IXGBE_SYSCTL_HELP_FWLOG_MODULE_SEVERITY \
+ "\nControl the level of log output messages for this module" \
+ "\n\tverbose <4> - Verbose messages + (Error|Warning|Normal)" \
+ "\n\tnormal <3> - Normal messages + (Error|Warning)" \
+ "\n\twarning <2> - Warning messages + (Error)" \
+ "\n\terror <1> - Error messages" \
+ "\n\tnone <0> - Disables all logging for this module"
+
+ /**
+ * ixgbe_fw_module_str - Convert a FW logging module to a string name
+ * @module: the module to convert
+ *
+ * Given a FW logging module id, convert it to a shorthand human readable
+ * name, for generating sysctl tunables.
+ */
+ static const char *
+ ixgbe_fw_module_str(enum ixgbe_aci_fw_logging_mod module)
+ {
+ switch (module) {
+ case IXGBE_ACI_FW_LOG_ID_GENERAL:
+ return "general";
+ case IXGBE_ACI_FW_LOG_ID_CTRL:
+ return "ctrl";
+ case IXGBE_ACI_FW_LOG_ID_LINK:
+ return "link";
+ case IXGBE_ACI_FW_LOG_ID_LINK_TOPO:
+ return "link_topo";
+ case IXGBE_ACI_FW_LOG_ID_DNL:
+ return "dnl";
+ case IXGBE_ACI_FW_LOG_ID_I2C:
+ return "i2c";
+ case IXGBE_ACI_FW_LOG_ID_SDP:
+ return "sdp";
+ case IXGBE_ACI_FW_LOG_ID_MDIO:
+ return "mdio";
+ case IXGBE_ACI_FW_LOG_ID_ADMINQ:
+ return "adminq";
+ case IXGBE_ACI_FW_LOG_ID_HDMA:
+ return "hdma";
+ case IXGBE_ACI_FW_LOG_ID_LLDP:
+ return "lldp";
+ case IXGBE_ACI_FW_LOG_ID_DCBX:
+ return "dcbx";
+ case IXGBE_ACI_FW_LOG_ID_DCB:
+ return "dcb";
+ case IXGBE_ACI_FW_LOG_ID_XLR:
+ return "xlr";
+ case IXGBE_ACI_FW_LOG_ID_NVM:
+ return "nvm";
+ case IXGBE_ACI_FW_LOG_ID_AUTH:
+ return "auth";
+ case IXGBE_ACI_FW_LOG_ID_VPD:
+ return "vpd";
+ case IXGBE_ACI_FW_LOG_ID_IOSF:
+ return "iosf";
+ case IXGBE_ACI_FW_LOG_ID_PARSER:
+ return "parser";
+ case IXGBE_ACI_FW_LOG_ID_SW:
+ return "sw";
+ case IXGBE_ACI_FW_LOG_ID_SCHEDULER:
+ return "scheduler";
+ case IXGBE_ACI_FW_LOG_ID_TXQ:
+ return "txq";
+ case IXGBE_ACI_FW_LOG_ID_ACL:
+ return "acl";
+ case IXGBE_ACI_FW_LOG_ID_POST:
+ return "post";
+ case IXGBE_ACI_FW_LOG_ID_WATCHDOG:
+ return "watchdog";
+ case IXGBE_ACI_FW_LOG_ID_TASK_DISPATCH:
+ return "task_dispatch";
+ case IXGBE_ACI_FW_LOG_ID_MNG:
+ return "mng";
+ case IXGBE_ACI_FW_LOG_ID_SYNCE:
+ return "synce";
+ case IXGBE_ACI_FW_LOG_ID_HEALTH:
+ return "health";
+ case IXGBE_ACI_FW_LOG_ID_TSDRV:
+ return "tsdrv";
+ case IXGBE_ACI_FW_LOG_ID_PFREG:
+ return "pfreg";
+ case IXGBE_ACI_FW_LOG_ID_MDLVER:
+ return "mdlver";
+ case IXGBE_ACI_FW_LOG_ID_MAX:
+ return "unknown";
+ }
+
+ /* The compiler generates errors on unhandled enum values if we omit
+ * the default case.
+ */
+ return "unknown";
+ }
+
+ /**
+ * ixgbe_add_fw_logging_tunables - Add tunables to configure FW logging events
+ * @sc: private softc structure
+ * @parent: parent node to add the tunables under
+ *
+ * Add tunables for configuring the firmware logging support. This includes
+ * a control to enable the logging, and controls for each module to configure
+ * which events to receive.
+ */
+ void
+ ixgbe_add_fw_logging_tunables(struct ixgbe_softc *sc, struct sysctl_oid *parent)
+ {
+ struct sysctl_oid_list *parent_list, *fwlog_list, *module_list;
+ struct sysctl_oid *fwlog_node, *module_node;
+ struct sysctl_ctx_list *ctx;
+ struct ixgbe_hw *hw = &sc->hw;
+ struct ixgbe_fwlog_cfg *cfg;
+ device_t dev = sc->dev;
+ enum ixgbe_aci_fw_logging_mod module;
+ u16 i;
+
+ cfg = &hw->fwlog_cfg;
+ ctx = device_get_sysctl_ctx(dev);
+ parent_list = SYSCTL_CHILDREN(parent);
+
+ fwlog_node = SYSCTL_ADD_NODE(ctx, parent_list, OID_AUTO, "fw_log",
+ CTLFLAG_RD, NULL,
+ "Firmware Logging");
+ fwlog_list = SYSCTL_CHILDREN(fwlog_node);
+
+ cfg->log_resolution = 10;
+ SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "log_resolution",
+ CTLTYPE_U8 | CTLFLAG_RWTUN, sc,
+ 0, ixgbe_sysctl_fwlog_log_resolution,
+ "CU", IXGBE_SYSCTL_HELP_FWLOG_LOG_RESOLUTION);
+
+ cfg->options |= IXGBE_FWLOG_OPTION_ARQ_ENA;
+ SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "arq_en",
+ CTLTYPE_U8 | CTLFLAG_RWTUN, sc,
+ IXGBE_FWLOG_OPTION_ARQ_ENA, ixgbe_sysctl_fwlog_set_cfg_options,
+ "CU", IXGBE_SYSCTL_HELP_FWLOG_ARQ_ENA);
+
+ SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "uart_en",
+ CTLTYPE_U8 | CTLFLAG_RWTUN, sc,
+ IXGBE_FWLOG_OPTION_UART_ENA, ixgbe_sysctl_fwlog_set_cfg_options,
+ "CU", IXGBE_SYSCTL_HELP_FWLOG_UART_ENA);
+
+ SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "on_load",
+ CTLTYPE_U8 | CTLFLAG_RWTUN, sc,
+ IXGBE_FWLOG_OPTION_REGISTER_ON_INIT, ixgbe_sysctl_fwlog_set_cfg_options,
+ "CU", IXGBE_SYSCTL_HELP_FWLOG_ENABLE_ON_LOAD);
+
+ SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "register",
+ CTLTYPE_U8 | CTLFLAG_RWTUN, sc,
+ 0, ixgbe_sysctl_fwlog_register,
+ "CU", IXGBE_SYSCTL_HELP_FWLOG_REGISTER);
+
+ module_node = SYSCTL_ADD_NODE(ctx, fwlog_list, OID_AUTO, "severity",
+ CTLFLAG_RD, NULL,
+ "Level of log output");
+
+ module_list = SYSCTL_CHILDREN(module_node);
+
+ for (i = 0; i < IXGBE_ACI_FW_LOG_ID_MAX; i++) {
+ /* Setup some defaults */
+ cfg->module_entries[i].module_id = i;
+ cfg->module_entries[i].log_level = IXGBE_FWLOG_LEVEL_NONE;
+ module = (enum ixgbe_aci_fw_logging_mod)i;
+
+ SYSCTL_ADD_PROC(ctx, module_list,
+ OID_AUTO, ixgbe_fw_module_str(module),
+ CTLTYPE_STRING | CTLFLAG_RWTUN, sc,
+ module, ixgbe_sysctl_fwlog_module_log_severity,
+ "A", IXGBE_SYSCTL_HELP_FWLOG_MODULE_SEVERITY);
+ }
+ }
+
\ No newline at end of file
diff --git a/sys/dev/ixgbe/ixgbe_osdep.h b/sys/dev/ixgbe/ixgbe_osdep.h
--- a/sys/dev/ixgbe/ixgbe_osdep.h
+++ b/sys/dev/ixgbe/ixgbe_osdep.h
@@ -253,4 +253,7 @@
free(addr, M_DEVBUF);
}
+void ixgbe_info_fwlog(struct ixgbe_hw *hw, uint32_t rowsize,
+ uint32_t groupsize, uint8_t *buf, size_t len);
+
#endif /* _IXGBE_OSDEP_H_ */
diff --git a/sys/dev/ixgbe/ixgbe_osdep.c b/sys/dev/ixgbe/ixgbe_osdep.c
--- a/sys/dev/ixgbe/ixgbe_osdep.c
+++ b/sys/dev/ixgbe/ixgbe_osdep.c
@@ -140,3 +140,39 @@
if (mtx_initialized(&lock->mutex))
mtx_destroy(&lock->mutex);
}
+
+/**
+ * ixgbe_info_fwlog - Format and print an array of values to the console
+ * @hw: private hardware structure
+ * @rowsize: preferred number of rows to use
+ * @groupsize: preferred size in bytes to print each chunk
+ * @buf: the array buffer to print
+ * @len: size of the array buffer
+ *
+ * Format the given array as a series of uint8_t values with hexadecimal
+ * notation and log the contents to the console log. This variation is
+ * specific to firmware logging.
+ *
+ * TODO: Currently only supports a group size of 1, due to the way hexdump is
+ * implemented.
+ */
+void
+ixgbe_info_fwlog(struct ixgbe_hw *hw, uint32_t rowsize, uint32_t __unused groupsize,
+ uint8_t *buf, size_t len)
+{
+ device_t dev = ((struct ixgbe_softc *)hw->back)->dev;
+ char prettyname[20];
+
+ if (!ixgbe_fwlog_supported(hw))
+ return;
+
+ /* Format the device header to a string */
+ snprintf(prettyname, sizeof(prettyname), "%s: FWLOG: ",
+ device_get_nameunit(dev));
+
+ /* Make sure the row-size isn't too large */
+ if (rowsize > 0xFF)
+ rowsize = 0xFF;
+
+ hexdump(buf, len, prettyname, HD_OMIT_CHARS | rowsize);
+}
diff --git a/sys/modules/ix/Makefile b/sys/modules/ix/Makefile
--- a/sys/modules/ix/Makefile
+++ b/sys/modules/ix/Makefile
@@ -8,6 +8,7 @@
SRCS += ixgbe_common.c ixgbe_api.c ixgbe_phy.c ixgbe_mbx.c ixgbe_vf.c
SRCS += ixgbe_dcb.c ixgbe_dcb_82598.c ixgbe_dcb_82599.c
SRCS += ixgbe_82598.c ixgbe_82599.c ixgbe_x540.c ixgbe_x550.c ixgbe_e610.c
+SRCS += ixgbe_fw_logging.c
CFLAGS+= -I${SRCTOP}/sys/dev/ixgbe
.include <bsd.kmod.mk>
diff --git a/sys/modules/ixv/Makefile b/sys/modules/ixv/Makefile
--- a/sys/modules/ixv/Makefile
+++ b/sys/modules/ixv/Makefile
@@ -8,6 +8,7 @@
SRCS += ixgbe_common.c ixgbe_api.c ixgbe_phy.c ixgbe_mbx.c ixgbe_vf.c
SRCS += ixgbe_dcb.c ixgbe_dcb_82598.c ixgbe_dcb_82599.c
SRCS += ixgbe_82598.c ixgbe_82599.c ixgbe_x540.c ixgbe_x550.c ixgbe_e610.c
+SRCS += ixgbe_fw_logging.c
CFLAGS+= -I${SRCTOP}/sys/dev/ixgbe
.include <bsd.kmod.mk>

File Metadata

Mime Type
text/plain
Expires
Mon, Apr 20, 6:08 AM (18 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31822573
Default Alt Text
D53973.id167230.diff (37 KB)

Event Timeline