Re: [PATCH net-next v5 2/5] ice: configure FW logging
From: Paul M Stillwell Jr <hidden>
Date: 2023-12-08 00:28:32
On 12/6/2023 7:53 PM, Jakub Kicinski wrote:
On Tue, 5 Dec 2023 13:12:45 -0800 Tony Nguyen wrote:quoted
+/** + * 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?
I can remove it, but I use it in all the _write functions. I use the argc to make sure I'm only getting one value to a write and I use argv[0] to deal with the value. Honestly I'm not sure how valuable it is to check for a single argument, but I'm fairly certain our validation team will file a bug if they pass more than one argument and something happens :) Examples of using argv are on lines 358 and 466 of ice_debugfs.c I'm open to changing it, just not sure to what
quoted
+/** + * 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.
I'm probably missing something here, but how do we get more simple than snprintf? I have a function (ice_fwlog_print_module_cfg) that handles whether the user has passed a single module ID or they want data on all the modules, but it all boils down to snprintf. I could get rid of ice_fwlog_print_module_cfg() and replace it inline with the if/else code if that would be clearer, but I'm not sure seq_printf() is helpful because each file is a single quantum of information (with the exception of the file that represents all the modules). I created a special file to represent all the modules, but maybe it's more confusing and I should get rid of it and just make the users specify all of the modules in a script. Would that be easier? Then there is no if/else it's just a single snprintf.
quoted
+/** + * 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
Will fix
quoted
+ 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)
OK
quoted
+ 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.
I'll remove them
Also - free fw_modules ?
This will get fixed by using goto in error paths as you suggested below
You probably want to use goto on all error paths herequoted
+/** + * 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
OK
quoted
+ return ice_aq_fwlog_get(hw, cfg);quoted
+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.
Will change