Subject: Re: [PATCH net-next v5 2/5] ice: configure FW logging

From: Jakub Kicinski <[email-masked]>
Date: Wed, 6 Dec 2023 19:53:04 -0800

On Tue,  5 Dec 2023 13:12:45 -0800 Tony Nguyen wrote:
> +/**
> + * ice_debugfs_parse_cmd_line - Parse the command line that was passed in
> + * @src: pointer to a buffer holding the command line
> + * @len: size of the buffer in bytes
> + * @argv: pointer to store the command line items
> + * @argc: pointer to store the number of command line items
> + */
> +static ssize_t ice_debugfs_parse_cmd_line(const char __user *src, size_t len,
> +					  char ***argv, int *argc)
> +{
> +	char *cmd_buf, *cmd_buf_tmp;
> +
> +	cmd_buf = memdup_user(src, len);
> +	if (IS_ERR(cmd_buf))
> +		return PTR_ERR(cmd_buf);
> +	cmd_buf[len] = '\0';
> +
> +	/* the cmd_buf has a newline at the end of the command so
> +	 * remove it
> +	 */
> +	cmd_buf_tmp = strchr(cmd_buf, '\n');
> +	if (cmd_buf_tmp) {
> +		*cmd_buf_tmp = '\0';
> +		len = (size_t)cmd_buf_tmp - (size_t)cmd_buf;
> +	}
> +
> +	*argv = argv_split(GFP_KERNEL, cmd_buf, argc);
> +	kfree(cmd_buf);
> +	if (!*argv)
> +		return -ENOMEM;

I haven't spotted a single caller wanting this full argc/argv parsing.
Can we please not add this complexity until its really needed?

> +/**
> + * ice_debugfs_module_read - read from 'module' 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_module_read(struct file *filp, char __user *buffer,
> +				       size_t count, loff_t *ppos)
> +{
> +	struct dentry *dentry = filp->f_path.dentry;
> +	struct ice_pf *pf = filp->private_data;
> +	int status, module;
> +	char *data = NULL;
> +
> +	/* don't allow commands if the FW doesn't support it */
> +	if (!ice_fwlog_supported(&pf->hw))
> +		return -EOPNOTSUPP;
> +
> +	module = ice_find_module_by_dentry(pf, dentry);
> +	if (module < 0) {
> +		dev_info(ice_pf_to_dev(pf), "unknown module\n");
> +		return -EINVAL;
> +	}
> +
> +	data = vzalloc(ICE_AQ_MAX_BUF_LEN);
> +	if (!data) {
> +		dev_warn(ice_pf_to_dev(pf), "Unable to allocate memory for FW configuration!\n");
> +		return -ENOMEM;

Can we use seq_print() here? It should simplify the reading quite a bit,
not sure how well it works with files that can also be written, tho.

> +/**
> + * ice_debugfs_fwlog_init - setup the debugfs directory
> + * @pf: the ice that is starting up
> + */
> +void ice_debugfs_fwlog_init(struct ice_pf *pf)
> +{
> +	const char *name = pci_name(pf->pdev);
> +	struct dentry *fw_modules_dir;
> +	struct dentry **fw_modules;
> +	int i;
> +
> +	/* only support fw log commands on PF 0 */
> +	if (pf->hw.bus.func)
> +		return;
> +
> +	/* allocate space for this first because if it fails then we don't
> +	 * need to unwind
> +	 */
> +	fw_modules = kcalloc(ICE_NR_FW_LOG_MODULES, sizeof(*fw_modules),
> +			     GFP_KERNEL);
> +

nit: no new line between call and error check

> +	if (!fw_modules) {
> +		pr_info("Unable to allocate space for modules\n");

no warnings on allocation failures, there will be a splat for GFP_KERNEL
(checkpatch should catch this)

> +		return;
> +	}
> +
> +	pf->ice_debugfs_pf = debugfs_create_dir(name, ice_debugfs_root);
> +	if (IS_ERR(pf->ice_debugfs_pf)) {
> +		pr_info("init of debugfs PCI dir failed\n");
> +		kfree(fw_modules);
> +		return;
> +	}
> +
> +	pf->ice_debugfs_pf_fwlog = debugfs_create_dir("fwlog",
> +						      pf->ice_debugfs_pf);
> +	if (IS_ERR(pf->ice_debugfs_pf)) {
> +		pr_info("init of debugfs fwlog dir failed\n");

If GregKH sees all the info message on debugfs failures he may
complain, DebugFS is supposed to be completely optional.

Also - free fw_modules ?

You probably want to use goto on all error paths here
> +/**
> + * ice_fwlog_get - Get the firmware logging settings
> + * @hw: pointer to the HW structure
> + * @cfg: config to populate based on current firmware logging settings
> + */
> +int ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
> +{
> +	if (!ice_fwlog_supported(hw))
> +		return -EOPNOTSUPP;
> +
> +	if (!cfg)
> +		return -EINVAL;

can't be, let's avoid defensive programming

> +	return ice_aq_fwlog_get(hw, cfg);

> +void ice_pf_fwlog_update_module(struct ice_pf *pf, int log_level, int module)
> +{
> +	struct ice_fwlog_module_entry *entries;
> +	struct ice_hw *hw = &pf->hw;
> +
> +	entries = (struct ice_fwlog_module_entry *)hw->fwlog_cfg.module_entries;
> +
> +	entries[module].log_level = log_level;
> +}

Isn't this just 

	hw->fwlog_cfg.module_entries[module].log_level = log_level;

? The cast specifically look alarming but unnecessary.