Skip to content

Commit

Permalink
ice: enable FW logging
Browse files Browse the repository at this point in the history
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.

  # echo <value> > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/enable

Where <value> is 0 or 1.

The user can read the 'fwlog/enable' file to see whether logging is
enabled or not. Reading the actual data is a separate patch. To see the
current value then:

  # cat /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/enable

Signed-off-by: Paul M Stillwell Jr <paul.m.stillwell.jr@intel.com>
Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
  • Loading branch information
Paul M Stillwell Jr authored and Tony Nguyen committed Dec 14, 2023
1 parent 96a9a93 commit 73671c3
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 0 deletions.
3 changes: 3 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -2393,6 +2393,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 {
Expand All @@ -2401,6 +2402,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;
Expand Down Expand Up @@ -2722,6 +2724,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,
};

Expand Down
98 changes: 98 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,101 @@ static const struct file_operations ice_debugfs_nr_messages_fops = {
.write = ice_debugfs_nr_messages_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] = {};

snprintf(buff, sizeof(buff), "%u\n",
(u16)(hw->fwlog_cfg.options &
ICE_FWLOG_OPTION_IS_REGISTERED) >> 3);

return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff));
}

/**
* 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 ice_hw *hw = &pf->hw;
char user_val[8], *cmd_buf;
bool enable;
ssize_t ret;

/* don't allow partial writes or invalid input */
if (*ppos != 0 || count > 2)
return -EINVAL;

cmd_buf = memdup_user(buf, count);
if (IS_ERR(cmd_buf))
return PTR_ERR(cmd_buf);

ret = sscanf(cmd_buf, "%s", user_val);
if (ret != 1)
return -EINVAL;

ret = kstrtobool(user_val, &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;

/* if we get here, nothing went wrong; return count since we didn't
* really write anything
*/
ret = (ssize_t)count;

enable_write_error:
/* 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
Expand Down Expand Up @@ -332,6 +427,9 @@ void ice_debugfs_fwlog_init(struct ice_pf *pf)

pf->ice_debugfs_pf_fwlog_modules = fw_modules;

debugfs_create_file("enable", 0600, pf->ice_debugfs_pf_fwlog,
pf, &ice_debugfs_enable_fops);

return;

err_create_module_files:
Expand Down
67 changes: 67 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_fwlog.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ void ice_fwlog_deinit(struct ice_hw *hw)
kfree(pf->ice_debugfs_pf_fwlog_modules);

pf->ice_debugfs_pf_fwlog_modules = NULL;

status = ice_fwlog_unregister(hw);
if (status)
dev_warn(ice_hw_to_dev(hw), "Unable to unregister FW logging, status: %d\n",
status);
}

/**
Expand Down Expand Up @@ -197,6 +202,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;

Expand Down Expand Up @@ -226,6 +233,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
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_fwlog.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,6 @@ 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_ */

0 comments on commit 73671c3

Please sign in to comment.