[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20231005170110.3221306-4-anthony.l.nguyen@intel.com>
Date: Thu, 5 Oct 2023 10:01:08 -0700
From: Tony Nguyen <anthony.l.nguyen@...el.com>
To: davem@...emloft.net,
kuba@...nel.org,
pabeni@...hat.com,
edumazet@...gle.com,
netdev@...r.kernel.org
Cc: Paul M Stillwell Jr <paul.m.stillwell.jr@...el.com>,
anthony.l.nguyen@...el.com,
jacob.e.keller@...el.com,
vaishnavi.tipireddy@...el.com,
horms@...nel.org,
leon@...nel.org,
Pucha Himasekhar Reddy <himasekharx.reddy.pucha@...el.com>
Subject: [PATCH net-next v4 3/5] ice: enable FW logging
From: Paul M Stillwell Jr <paul.m.stillwell.jr@...el.com>
Once users have configured the FW logging then allow them to enable it
by writing to the 'fwlog/enable' file. The file accepts a boolean value
(0 or 1) where 1 means enable FW logging and 0 means disable FW logging.
The user can read the 'fwlog/enable' file to see whether logging is
enabled or not. Reading the actual data is a separate patch.
Signed-off-by: Paul M Stillwell Jr <paul.m.stillwell.jr@...el.com>
Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@...el.com> (A Contingent worker at Intel)
Signed-off-by: Tony Nguyen <anthony.l.nguyen@...el.com>
---
.../net/ethernet/intel/ice/ice_adminq_cmd.h | 3 +
drivers/net/ethernet/intel/ice/ice_common.c | 1 +
drivers/net/ethernet/intel/ice/ice_debugfs.c | 115 ++++++++++++++++++
drivers/net/ethernet/intel/ice/ice_fwlog.c | 91 ++++++++++++++
drivers/net/ethernet/intel/ice/ice_fwlog.h | 3 +
5 files changed, 213 insertions(+)
diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
index 5282fc290d4f..5a03fcb06d27 100644
--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
@@ -2330,6 +2330,7 @@ enum ice_aqc_fw_logging_mod {
};
/* Set FW Logging configuration (indirect 0xFF30)
+ * Register for FW Logging (indirect 0xFF31)
* Query FW Logging (indirect 0xFF32)
*/
struct ice_aqc_fw_log {
@@ -2338,6 +2339,7 @@ struct ice_aqc_fw_log {
#define ICE_AQC_FW_LOG_CONF_AQ_EN BIT(1)
#define ICE_AQC_FW_LOG_QUERY_REGISTERED BIT(2)
#define ICE_AQC_FW_LOG_CONF_SET_VALID BIT(3)
+#define ICE_AQC_FW_LOG_AQ_REGISTER BIT(0)
#define ICE_AQC_FW_LOG_AQ_QUERY BIT(2)
u8 rsp_flag;
@@ -2656,6 +2658,7 @@ enum ice_adminq_opc {
/* FW Logging Commands */
ice_aqc_opc_fw_logs_config = 0xFF30,
+ ice_aqc_opc_fw_logs_register = 0xFF31,
ice_aqc_opc_fw_logs_query = 0xFF32,
};
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
index d60c7a007cfb..7d6dbccd91a2 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.c
+++ b/drivers/net/ethernet/intel/ice/ice_common.c
@@ -1108,6 +1108,7 @@ void ice_deinit_hw(struct ice_hw *hw)
ice_free_hw_tbls(hw);
mutex_destroy(&hw->tnl_lock);
+ ice_fwlog_deinit(hw);
ice_destroy_all_ctrlq(hw);
/* Clear VSI contexts if not already cleared */
diff --git a/drivers/net/ethernet/intel/ice/ice_debugfs.c b/drivers/net/ethernet/intel/ice/ice_debugfs.c
index e354c7287ff6..104ea962adee 100644
--- a/drivers/net/ethernet/intel/ice/ice_debugfs.c
+++ b/drivers/net/ethernet/intel/ice/ice_debugfs.c
@@ -397,6 +397,118 @@ static const struct file_operations ice_debugfs_resolution_fops = {
.write = ice_debugfs_resolution_write,
};
+/**
+ * ice_debugfs_enable_read - read from 'enable' file
+ * @filp: the opened file
+ * @buffer: where to write the data for the user to read
+ * @count: the size of the user's buffer
+ * @ppos: file position offset
+ */
+static ssize_t ice_debugfs_enable_read(struct file *filp,
+ char __user *buffer, size_t count,
+ loff_t *ppos)
+{
+ struct ice_pf *pf = filp->private_data;
+ struct ice_hw *hw = &pf->hw;
+ char buff[32] = {};
+ int status;
+
+ /* don't allow commands if the FW doesn't support it */
+ if (!ice_fwlog_supported(&pf->hw))
+ return -EOPNOTSUPP;
+
+ snprintf(buff, sizeof(buff), "%u\n",
+ (u16)(hw->fwlog_cfg.options &
+ ICE_FWLOG_OPTION_IS_REGISTERED) >> 3);
+
+ status = simple_read_from_buffer(buffer, count, ppos, buff,
+ strlen(buff));
+
+ return status;
+}
+
+/**
+ * ice_debugfs_enable_write - write into 'enable' file
+ * @filp: the opened file
+ * @buf: where to find the user's data
+ * @count: the length of the user's data
+ * @ppos: file position offset
+ */
+static ssize_t
+ice_debugfs_enable_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct ice_pf *pf = filp->private_data;
+ struct device *dev = ice_pf_to_dev(pf);
+ struct ice_hw *hw = &pf->hw;
+ ssize_t ret;
+ char **argv;
+ int argc;
+
+ /* don't allow commands if the FW doesn't support it */
+ if (!ice_fwlog_supported(hw))
+ return -EOPNOTSUPP;
+
+ /* don't allow partial writes */
+ if (*ppos != 0)
+ return 0;
+
+ ret = ice_debugfs_parse_cmd_line(buf, count, &argv, &argc);
+ if (ret)
+ goto err_copy_from_user;
+
+ if (argc == 1) {
+ bool enable;
+
+ ret = kstrtobool(argv[0], &enable);
+ if (ret)
+ goto enable_write_error;
+
+ if (enable)
+ hw->fwlog_cfg.options |= ICE_FWLOG_OPTION_ARQ_ENA;
+ else
+ hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_ARQ_ENA;
+
+ ret = ice_fwlog_set(hw, &hw->fwlog_cfg);
+ if (ret)
+ goto enable_write_error;
+
+ if (enable)
+ ret = ice_fwlog_register(hw);
+ else
+ ret = ice_fwlog_unregister(hw);
+
+ if (ret)
+ goto enable_write_error;
+ } else {
+ dev_info(dev, "unknown or invalid command '%s'\n", argv[0]);
+ ret = -EINVAL;
+ goto enable_write_error;
+ }
+
+ /* if we get here, nothing went wrong; return bytes copied */
+ ret = (ssize_t)count;
+
+enable_write_error:
+ argv_free(argv);
+err_copy_from_user:
+ /* This function always consumes all of the written input, or produces
+ * an error. Check and enforce this. Otherwise, the write operation
+ * won't complete properly.
+ */
+ if (WARN_ON(ret != (ssize_t)count && ret >= 0))
+ ret = -EIO;
+
+ return ret;
+}
+
+static const struct file_operations ice_debugfs_enable_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = ice_debugfs_enable_read,
+ .write = ice_debugfs_enable_write,
+};
+
/**
* ice_debugfs_fwlog_init - setup the debugfs directory
* @pf: the ice that is starting up
@@ -428,6 +540,9 @@ void ice_debugfs_fwlog_init(struct ice_pf *pf)
debugfs_create_file("resolution", 0600,
pf->ice_debugfs_pf_fwlog, pf,
&ice_debugfs_resolution_fops);
+
+ debugfs_create_file("enable", 0600, pf->ice_debugfs_pf_fwlog,
+ pf, &ice_debugfs_enable_fops);
}
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_fwlog.c b/drivers/net/ethernet/intel/ice/ice_fwlog.c
index 1f4b474dcc97..ce857ddd4be8 100644
--- a/drivers/net/ethernet/intel/ice/ice_fwlog.c
+++ b/drivers/net/ethernet/intel/ice/ice_fwlog.c
@@ -32,6 +32,35 @@ int ice_fwlog_init(struct ice_hw *hw)
return 0;
}
+/**
+ * ice_fwlog_deinit - unroll FW logging configuration
+ * @hw: pointer to the HW structure
+ *
+ * This function should be called in ice_deinit_hw().
+ */
+void ice_fwlog_deinit(struct ice_hw *hw)
+{
+ int status;
+
+ /* only support fw log commands on PF 0 */
+ if (hw->bus.func)
+ return;
+
+ /* make sure FW logging is disabled to not put the FW in a weird state
+ * for the next driver load
+ */
+ hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_ARQ_ENA;
+ status = ice_fwlog_set(hw, &hw->fwlog_cfg);
+ if (status)
+ dev_warn(ice_hw_to_dev(hw), "Unable to turn off FW logging, status: %d\n",
+ status);
+
+ status = ice_fwlog_unregister(hw);
+ if (status)
+ dev_warn(ice_hw_to_dev(hw), "Unable to unregister FW logging, status: %d\n",
+ status);
+}
+
/**
* ice_fwlog_supported - Cached for whether FW supports FW logging or not
* @hw: pointer to the HW structure
@@ -164,6 +193,8 @@ static int ice_aq_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
cfg->options |= ICE_FWLOG_OPTION_ARQ_ENA;
if (cmd->cmd_flags & ICE_AQC_FW_LOG_CONF_UART_EN)
cfg->options |= ICE_FWLOG_OPTION_UART_ENA;
+ if (cmd->cmd_flags & ICE_AQC_FW_LOG_QUERY_REGISTERED)
+ cfg->options |= ICE_FWLOG_OPTION_IS_REGISTERED;
fw_modules = (struct ice_aqc_fw_log_cfg_resp *)buf;
@@ -196,6 +227,66 @@ int ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
return ice_aq_fwlog_get(hw, cfg);
}
+/**
+ * ice_aq_fwlog_register - Register PF for firmware logging events (0xFF31)
+ * @hw: pointer to the HW structure
+ * @reg: true to register and false to unregister
+ */
+static int ice_aq_fwlog_register(struct ice_hw *hw, bool reg)
+{
+ struct ice_aq_desc desc;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_register);
+
+ if (reg)
+ desc.params.fw_log.cmd_flags = ICE_AQC_FW_LOG_AQ_REGISTER;
+
+ return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
+}
+
+/**
+ * ice_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 ice_fwlog_set.
+ */
+int ice_fwlog_register(struct ice_hw *hw)
+{
+ int status;
+
+ if (!ice_fwlog_supported(hw))
+ return -EOPNOTSUPP;
+
+ status = ice_aq_fwlog_register(hw, true);
+ if (status)
+ ice_debug(hw, ICE_DBG_FW_LOG, "Failed to register for firmware logging events over ARQ\n");
+ else
+ hw->fwlog_cfg.options |= ICE_FWLOG_OPTION_IS_REGISTERED;
+
+ return status;
+}
+
+/**
+ * ice_fwlog_unregister - Unregister the PF from firmware logging
+ * @hw: pointer to the HW structure
+ */
+int ice_fwlog_unregister(struct ice_hw *hw)
+{
+ int status;
+
+ if (!ice_fwlog_supported(hw))
+ return -EOPNOTSUPP;
+
+ status = ice_aq_fwlog_register(hw, false);
+ if (status)
+ ice_debug(hw, ICE_DBG_FW_LOG, "Failed to unregister from firmware logging events over ARQ\n");
+ else
+ hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_IS_REGISTERED;
+
+ return status;
+}
+
/**
* ice_fwlog_set_supported - Set if FW logging is supported by FW
* @hw: pointer to the HW struct
diff --git a/drivers/net/ethernet/intel/ice/ice_fwlog.h b/drivers/net/ethernet/intel/ice/ice_fwlog.h
index 5a4194527cf9..45865558425d 100644
--- a/drivers/net/ethernet/intel/ice/ice_fwlog.h
+++ b/drivers/net/ethernet/intel/ice/ice_fwlog.h
@@ -50,6 +50,9 @@ struct ice_fwlog_cfg {
void ice_fwlog_set_supported(struct ice_hw *hw);
bool ice_fwlog_supported(struct ice_hw *hw);
int ice_fwlog_init(struct ice_hw *hw);
+void ice_fwlog_deinit(struct ice_hw *hw);
int ice_fwlog_set(struct ice_hw *hw, struct ice_fwlog_cfg *cfg);
int ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg);
+int ice_fwlog_register(struct ice_hw *hw);
+int ice_fwlog_unregister(struct ice_hw *hw);
#endif /* _ICE_FWLOG_H_ */
--
2.38.1
Powered by blists - more mailing lists