Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch '10GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue

Tony Nguyen says:

====================
Fwlog support in ixgbe

Michal Swiatkowski says:

Firmware logging is a feature that allow user to dump firmware log using
debugfs interface. It is supported on device that can handle specific
firmware ops. It is true for ice and ixgbe driver.

Prepare code from ice driver to be moved to the library code and reuse
it in ixgbe driver.

* '10GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue:
ixgbe: fwlog support for e610
ice, libie: move fwlog code to libie
ice: reregister fwlog after driver reinit
ice: prepare for moving file to libie
ice: move debugfs code to fwlog
libie, ice: move fwlog admin queue to libie
ice: drop driver specific structure from fwlog code
ice: check for PF number outside the fwlog code
ice: move out debugfs init from fwlog
ice: allow calling custom send function in fwlog
ice: add pdev into fwlog structure and use it for logging
ice: introduce ice_fwlog structure
ice: drop ice_pf_fwlog_update_module()
ice: move get_fwlog_data() to fwlog file
ice: make fwlog functions static
====================

Link: https://patch.msgid.link/20250911210525.345110-1-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+1403 -1314
+2
drivers/net/ethernet/intel/Kconfig
··· 146 146 tristate "Intel(R) 10GbE PCI Express adapters support" 147 147 depends on PCI 148 148 depends on PTP_1588_CLOCK_OPTIONAL 149 + select LIBIE_FWLOG 149 150 select MDIO 150 151 select NET_DEVLINK 151 152 select PLDMFW ··· 298 297 select DIMLIB 299 298 select LIBIE 300 299 select LIBIE_ADMINQ 300 + select LIBIE_FWLOG 301 301 select NET_DEVLINK 302 302 select PACKING 303 303 select PLDMFW
-1
drivers/net/ethernet/intel/ice/Makefile
··· 42 42 ice_ethtool.o \ 43 43 ice_repr.o \ 44 44 ice_tc_lib.o \ 45 - ice_fwlog.o \ 46 45 ice_debugfs.o \ 47 46 ice_adapter.o 48 47 ice-$(CONFIG_PCI_IOV) += \
+1 -5
drivers/net/ethernet/intel/ice/ice.h
··· 568 568 struct ice_sw *first_sw; /* first switch created by firmware */ 569 569 u16 eswitch_mode; /* current mode of eswitch */ 570 570 struct dentry *ice_debugfs_pf; 571 - struct dentry *ice_debugfs_pf_fwlog; 572 - /* keep track of all the dentrys for FW log modules */ 573 - struct dentry **ice_debugfs_pf_fwlog_modules; 574 571 struct ice_vfs vfs; 575 572 DECLARE_BITMAP(features, ICE_F_MAX); 576 573 DECLARE_BITMAP(state, ICE_STATE_NBITS); ··· 905 908 return false; 906 909 } 907 910 908 - void ice_debugfs_fwlog_init(struct ice_pf *pf); 911 + int ice_debugfs_pf_init(struct ice_pf *pf); 909 912 void ice_debugfs_pf_deinit(struct ice_pf *pf); 910 913 void ice_debugfs_init(void); 911 914 void ice_debugfs_exit(void); 912 - void ice_pf_fwlog_update_module(struct ice_pf *pf, int log_level, int module); 913 915 914 916 bool netif_is_ice(const struct net_device *dev); 915 917 int ice_vsi_setup_tx_rings(struct ice_vsi *vsi);
-78
drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
··· 2399 2399 u8 reserved[8]; 2400 2400 }; 2401 2401 2402 - enum ice_aqc_fw_logging_mod { 2403 - ICE_AQC_FW_LOG_ID_GENERAL = 0, 2404 - ICE_AQC_FW_LOG_ID_CTRL, 2405 - ICE_AQC_FW_LOG_ID_LINK, 2406 - ICE_AQC_FW_LOG_ID_LINK_TOPO, 2407 - ICE_AQC_FW_LOG_ID_DNL, 2408 - ICE_AQC_FW_LOG_ID_I2C, 2409 - ICE_AQC_FW_LOG_ID_SDP, 2410 - ICE_AQC_FW_LOG_ID_MDIO, 2411 - ICE_AQC_FW_LOG_ID_ADMINQ, 2412 - ICE_AQC_FW_LOG_ID_HDMA, 2413 - ICE_AQC_FW_LOG_ID_LLDP, 2414 - ICE_AQC_FW_LOG_ID_DCBX, 2415 - ICE_AQC_FW_LOG_ID_DCB, 2416 - ICE_AQC_FW_LOG_ID_XLR, 2417 - ICE_AQC_FW_LOG_ID_NVM, 2418 - ICE_AQC_FW_LOG_ID_AUTH, 2419 - ICE_AQC_FW_LOG_ID_VPD, 2420 - ICE_AQC_FW_LOG_ID_IOSF, 2421 - ICE_AQC_FW_LOG_ID_PARSER, 2422 - ICE_AQC_FW_LOG_ID_SW, 2423 - ICE_AQC_FW_LOG_ID_SCHEDULER, 2424 - ICE_AQC_FW_LOG_ID_TXQ, 2425 - ICE_AQC_FW_LOG_ID_RSVD, 2426 - ICE_AQC_FW_LOG_ID_POST, 2427 - ICE_AQC_FW_LOG_ID_WATCHDOG, 2428 - ICE_AQC_FW_LOG_ID_TASK_DISPATCH, 2429 - ICE_AQC_FW_LOG_ID_MNG, 2430 - ICE_AQC_FW_LOG_ID_SYNCE, 2431 - ICE_AQC_FW_LOG_ID_HEALTH, 2432 - ICE_AQC_FW_LOG_ID_TSDRV, 2433 - ICE_AQC_FW_LOG_ID_PFREG, 2434 - ICE_AQC_FW_LOG_ID_MDLVER, 2435 - ICE_AQC_FW_LOG_ID_MAX, 2436 - }; 2437 - 2438 2402 enum ice_aqc_health_status_mask { 2439 2403 ICE_AQC_HEALTH_STATUS_SET_PF_SPECIFIC_MASK = BIT(0), 2440 2404 ICE_AQC_HEALTH_STATUS_SET_ALL_PF_MASK = BIT(1), ··· 2478 2514 __le16 event_source; 2479 2515 __le32 internal_data1; 2480 2516 __le32 internal_data2; 2481 - }; 2482 - 2483 - /* Set FW Logging configuration (indirect 0xFF30) 2484 - * Register for FW Logging (indirect 0xFF31) 2485 - * Query FW Logging (indirect 0xFF32) 2486 - * FW Log Event (indirect 0xFF33) 2487 - */ 2488 - struct ice_aqc_fw_log { 2489 - u8 cmd_flags; 2490 - #define ICE_AQC_FW_LOG_CONF_UART_EN BIT(0) 2491 - #define ICE_AQC_FW_LOG_CONF_AQ_EN BIT(1) 2492 - #define ICE_AQC_FW_LOG_QUERY_REGISTERED BIT(2) 2493 - #define ICE_AQC_FW_LOG_CONF_SET_VALID BIT(3) 2494 - #define ICE_AQC_FW_LOG_AQ_REGISTER BIT(0) 2495 - #define ICE_AQC_FW_LOG_AQ_QUERY BIT(2) 2496 - 2497 - u8 rsp_flag; 2498 - __le16 fw_rt_msb; 2499 - union { 2500 - struct { 2501 - __le32 fw_rt_lsb; 2502 - } sync; 2503 - struct { 2504 - __le16 log_resolution; 2505 - #define ICE_AQC_FW_LOG_MIN_RESOLUTION (1) 2506 - #define ICE_AQC_FW_LOG_MAX_RESOLUTION (128) 2507 - 2508 - __le16 mdl_cnt; 2509 - } cfg; 2510 - } ops; 2511 - __le32 addr_high; 2512 - __le32 addr_low; 2513 - }; 2514 - 2515 - /* Response Buffer for: 2516 - * Set Firmware Logging Configuration (0xFF30) 2517 - * Query FW Logging (0xFF32) 2518 - */ 2519 - struct ice_aqc_fw_log_cfg_resp { 2520 - __le16 module_identifier; 2521 - u8 log_level; 2522 - u8 rsvd0; 2523 2517 }; 2524 2518 2525 2519 /* Admin Queue command opcodes */
+43 -3
drivers/net/ethernet/intel/ice/ice_common.c
··· 984 984 return -ETIMEDOUT; 985 985 } 986 986 987 + static int __fwlog_send_cmd(void *priv, struct libie_aq_desc *desc, void *buf, 988 + u16 size) 989 + { 990 + struct ice_hw *hw = priv; 991 + 992 + return ice_aq_send_cmd(hw, desc, buf, size, NULL); 993 + } 994 + 995 + static int __fwlog_init(struct ice_hw *hw) 996 + { 997 + struct ice_pf *pf = hw->back; 998 + struct libie_fwlog_api api = { 999 + .pdev = pf->pdev, 1000 + .send_cmd = __fwlog_send_cmd, 1001 + .priv = hw, 1002 + }; 1003 + int err; 1004 + 1005 + /* only support fw log commands on PF 0 */ 1006 + if (hw->bus.func) 1007 + return -EINVAL; 1008 + 1009 + err = ice_debugfs_pf_init(pf); 1010 + if (err) 1011 + return err; 1012 + 1013 + api.debugfs_root = pf->ice_debugfs_pf; 1014 + 1015 + return libie_fwlog_init(&hw->fwlog, &api); 1016 + } 1017 + 987 1018 /** 988 1019 * ice_init_hw - main hardware initialization routine 989 1020 * @hw: pointer to the hardware structure ··· 1043 1012 if (status) 1044 1013 goto err_unroll_cqinit; 1045 1014 1046 - status = ice_fwlog_init(hw); 1015 + status = __fwlog_init(hw); 1047 1016 if (status) 1048 1017 ice_debug(hw, ICE_DBG_FW_LOG, "Error initializing FW logging: %d\n", 1049 1018 status); ··· 1190 1159 return status; 1191 1160 } 1192 1161 1162 + static void __fwlog_deinit(struct ice_hw *hw) 1163 + { 1164 + /* only support fw log commands on PF 0 */ 1165 + if (hw->bus.func) 1166 + return; 1167 + 1168 + ice_debugfs_pf_deinit(hw->back); 1169 + libie_fwlog_deinit(&hw->fwlog); 1170 + } 1171 + 1193 1172 /** 1194 1173 * ice_deinit_hw - unroll initialization operations done by ice_init_hw 1195 1174 * @hw: pointer to the hardware structure ··· 1218 1177 ice_free_seg(hw); 1219 1178 ice_free_hw_tbls(hw); 1220 1179 mutex_destroy(&hw->tnl_lock); 1221 - 1222 - ice_fwlog_deinit(hw); 1180 + __fwlog_deinit(hw); 1223 1181 ice_destroy_all_ctrlq(hw); 1224 1182 1225 1183 /* Clear VSI contexts if not already cleared */
+3 -630
drivers/net/ethernet/intel/ice/ice_debugfs.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* Copyright (c) 2022, Intel Corporation. */ 3 3 4 - #include <linux/fs.h> 5 4 #include <linux/debugfs.h> 6 - #include <linux/random.h> 7 - #include <linux/vmalloc.h> 8 5 #include "ice.h" 9 6 10 7 static struct dentry *ice_debugfs_root; 11 8 12 - /* create a define that has an extra module that doesn't really exist. this 13 - * is so we can add a module 'all' to easily enable/disable all the modules 14 - */ 15 - #define ICE_NR_FW_LOG_MODULES (ICE_AQC_FW_LOG_ID_MAX + 1) 16 - 17 - /* the ordering in this array is important. it matches the ordering of the 18 - * values in the FW so the index is the same value as in ice_aqc_fw_logging_mod 19 - */ 20 - static const char * const ice_fwlog_module_string[] = { 21 - "general", 22 - "ctrl", 23 - "link", 24 - "link_topo", 25 - "dnl", 26 - "i2c", 27 - "sdp", 28 - "mdio", 29 - "adminq", 30 - "hdma", 31 - "lldp", 32 - "dcbx", 33 - "dcb", 34 - "xlr", 35 - "nvm", 36 - "auth", 37 - "vpd", 38 - "iosf", 39 - "parser", 40 - "sw", 41 - "scheduler", 42 - "txq", 43 - "rsvd", 44 - "post", 45 - "watchdog", 46 - "task_dispatch", 47 - "mng", 48 - "synce", 49 - "health", 50 - "tsdrv", 51 - "pfreg", 52 - "mdlver", 53 - "all", 54 - }; 55 - 56 - /* the ordering in this array is important. it matches the ordering of the 57 - * values in the FW so the index is the same value as in ice_fwlog_level 58 - */ 59 - static const char * const ice_fwlog_level_string[] = { 60 - "none", 61 - "error", 62 - "warning", 63 - "normal", 64 - "verbose", 65 - }; 66 - 67 - static const char * const ice_fwlog_log_size[] = { 68 - "128K", 69 - "256K", 70 - "512K", 71 - "1M", 72 - "2M", 73 - }; 74 - 75 - /** 76 - * ice_fwlog_print_module_cfg - print current FW logging module configuration 77 - * @hw: pointer to the HW structure 78 - * @module: module to print 79 - * @s: the seq file to put data into 80 - */ 81 - static void 82 - ice_fwlog_print_module_cfg(struct ice_hw *hw, int module, struct seq_file *s) 83 - { 84 - struct ice_fwlog_cfg *cfg = &hw->fwlog_cfg; 85 - struct ice_fwlog_module_entry *entry; 86 - 87 - if (module != ICE_AQC_FW_LOG_ID_MAX) { 88 - entry = &cfg->module_entries[module]; 89 - 90 - seq_printf(s, "\tModule: %s, Log Level: %s\n", 91 - ice_fwlog_module_string[entry->module_id], 92 - ice_fwlog_level_string[entry->log_level]); 93 - } else { 94 - int i; 95 - 96 - for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) { 97 - entry = &cfg->module_entries[i]; 98 - 99 - seq_printf(s, "\tModule: %s, Log Level: %s\n", 100 - ice_fwlog_module_string[entry->module_id], 101 - ice_fwlog_level_string[entry->log_level]); 102 - } 103 - } 104 - } 105 - 106 - static int ice_find_module_by_dentry(struct ice_pf *pf, struct dentry *d) 107 - { 108 - int i, module; 109 - 110 - module = -1; 111 - /* find the module based on the dentry */ 112 - for (i = 0; i < ICE_NR_FW_LOG_MODULES; i++) { 113 - if (d == pf->ice_debugfs_pf_fwlog_modules[i]) { 114 - module = i; 115 - break; 116 - } 117 - } 118 - 119 - return module; 120 - } 121 - 122 - /** 123 - * ice_debugfs_module_show - read from 'module' file 124 - * @s: the opened file 125 - * @v: pointer to the offset 126 - */ 127 - static int ice_debugfs_module_show(struct seq_file *s, void *v) 128 - { 129 - const struct file *filp = s->file; 130 - struct dentry *dentry; 131 - struct ice_pf *pf; 132 - int module; 133 - 134 - dentry = file_dentry(filp); 135 - pf = s->private; 136 - 137 - module = ice_find_module_by_dentry(pf, dentry); 138 - if (module < 0) { 139 - dev_info(ice_pf_to_dev(pf), "unknown module\n"); 140 - return -EINVAL; 141 - } 142 - 143 - ice_fwlog_print_module_cfg(&pf->hw, module, s); 144 - 145 - return 0; 146 - } 147 - 148 - static int ice_debugfs_module_open(struct inode *inode, struct file *filp) 149 - { 150 - return single_open(filp, ice_debugfs_module_show, inode->i_private); 151 - } 152 - 153 - /** 154 - * ice_debugfs_module_write - write into 'module' file 155 - * @filp: the opened file 156 - * @buf: where to find the user's data 157 - * @count: the length of the user's data 158 - * @ppos: file position offset 159 - */ 160 - static ssize_t 161 - ice_debugfs_module_write(struct file *filp, const char __user *buf, 162 - size_t count, loff_t *ppos) 163 - { 164 - struct ice_pf *pf = file_inode(filp)->i_private; 165 - struct dentry *dentry = file_dentry(filp); 166 - struct device *dev = ice_pf_to_dev(pf); 167 - char user_val[16], *cmd_buf; 168 - int module, log_level, cnt; 169 - 170 - /* don't allow partial writes or invalid input */ 171 - if (*ppos != 0 || count > 8) 172 - return -EINVAL; 173 - 174 - cmd_buf = memdup_user_nul(buf, count); 175 - if (IS_ERR(cmd_buf)) 176 - return PTR_ERR(cmd_buf); 177 - 178 - module = ice_find_module_by_dentry(pf, dentry); 179 - if (module < 0) { 180 - dev_info(dev, "unknown module\n"); 181 - return -EINVAL; 182 - } 183 - 184 - cnt = sscanf(cmd_buf, "%s", user_val); 185 - if (cnt != 1) 186 - return -EINVAL; 187 - 188 - log_level = sysfs_match_string(ice_fwlog_level_string, user_val); 189 - if (log_level < 0) { 190 - dev_info(dev, "unknown log level '%s'\n", user_val); 191 - return -EINVAL; 192 - } 193 - 194 - if (module != ICE_AQC_FW_LOG_ID_MAX) { 195 - ice_pf_fwlog_update_module(pf, log_level, module); 196 - } else { 197 - /* the module 'all' is a shortcut so that we can set 198 - * all of the modules to the same level quickly 199 - */ 200 - int i; 201 - 202 - for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) 203 - ice_pf_fwlog_update_module(pf, log_level, i); 204 - } 205 - 206 - return count; 207 - } 208 - 209 - static const struct file_operations ice_debugfs_module_fops = { 210 - .owner = THIS_MODULE, 211 - .open = ice_debugfs_module_open, 212 - .read = seq_read, 213 - .release = single_release, 214 - .write = ice_debugfs_module_write, 215 - }; 216 - 217 - /** 218 - * ice_debugfs_nr_messages_read - read from 'nr_messages' file 219 - * @filp: the opened file 220 - * @buffer: where to write the data for the user to read 221 - * @count: the size of the user's buffer 222 - * @ppos: file position offset 223 - */ 224 - static ssize_t ice_debugfs_nr_messages_read(struct file *filp, 225 - char __user *buffer, size_t count, 226 - loff_t *ppos) 227 - { 228 - struct ice_pf *pf = filp->private_data; 229 - struct ice_hw *hw = &pf->hw; 230 - char buff[32] = {}; 231 - 232 - snprintf(buff, sizeof(buff), "%d\n", 233 - hw->fwlog_cfg.log_resolution); 234 - 235 - return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff)); 236 - } 237 - 238 - /** 239 - * ice_debugfs_nr_messages_write - write into 'nr_messages' file 240 - * @filp: the opened file 241 - * @buf: where to find the user's data 242 - * @count: the length of the user's data 243 - * @ppos: file position offset 244 - */ 245 - static ssize_t 246 - ice_debugfs_nr_messages_write(struct file *filp, const char __user *buf, 247 - size_t count, loff_t *ppos) 248 - { 249 - struct ice_pf *pf = filp->private_data; 250 - struct device *dev = ice_pf_to_dev(pf); 251 - struct ice_hw *hw = &pf->hw; 252 - char user_val[8], *cmd_buf; 253 - s16 nr_messages; 254 - ssize_t ret; 255 - 256 - /* don't allow partial writes or invalid input */ 257 - if (*ppos != 0 || count > 4) 258 - return -EINVAL; 259 - 260 - cmd_buf = memdup_user_nul(buf, count); 261 - if (IS_ERR(cmd_buf)) 262 - return PTR_ERR(cmd_buf); 263 - 264 - ret = sscanf(cmd_buf, "%s", user_val); 265 - if (ret != 1) 266 - return -EINVAL; 267 - 268 - ret = kstrtos16(user_val, 0, &nr_messages); 269 - if (ret) 270 - return ret; 271 - 272 - if (nr_messages < ICE_AQC_FW_LOG_MIN_RESOLUTION || 273 - nr_messages > ICE_AQC_FW_LOG_MAX_RESOLUTION) { 274 - dev_err(dev, "Invalid FW log number of messages %d, value must be between %d - %d\n", 275 - nr_messages, ICE_AQC_FW_LOG_MIN_RESOLUTION, 276 - ICE_AQC_FW_LOG_MAX_RESOLUTION); 277 - return -EINVAL; 278 - } 279 - 280 - hw->fwlog_cfg.log_resolution = nr_messages; 281 - 282 - return count; 283 - } 284 - 285 - static const struct file_operations ice_debugfs_nr_messages_fops = { 286 - .owner = THIS_MODULE, 287 - .open = simple_open, 288 - .read = ice_debugfs_nr_messages_read, 289 - .write = ice_debugfs_nr_messages_write, 290 - }; 291 - 292 - /** 293 - * ice_debugfs_enable_read - read from 'enable' file 294 - * @filp: the opened file 295 - * @buffer: where to write the data for the user to read 296 - * @count: the size of the user's buffer 297 - * @ppos: file position offset 298 - */ 299 - static ssize_t ice_debugfs_enable_read(struct file *filp, 300 - char __user *buffer, size_t count, 301 - loff_t *ppos) 302 - { 303 - struct ice_pf *pf = filp->private_data; 304 - struct ice_hw *hw = &pf->hw; 305 - char buff[32] = {}; 306 - 307 - snprintf(buff, sizeof(buff), "%u\n", 308 - (u16)(hw->fwlog_cfg.options & 309 - ICE_FWLOG_OPTION_IS_REGISTERED) >> 3); 310 - 311 - return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff)); 312 - } 313 - 314 - /** 315 - * ice_debugfs_enable_write - write into 'enable' file 316 - * @filp: the opened file 317 - * @buf: where to find the user's data 318 - * @count: the length of the user's data 319 - * @ppos: file position offset 320 - */ 321 - static ssize_t 322 - ice_debugfs_enable_write(struct file *filp, const char __user *buf, 323 - size_t count, loff_t *ppos) 324 - { 325 - struct ice_pf *pf = filp->private_data; 326 - struct ice_hw *hw = &pf->hw; 327 - char user_val[8], *cmd_buf; 328 - bool enable; 329 - ssize_t ret; 330 - 331 - /* don't allow partial writes or invalid input */ 332 - if (*ppos != 0 || count > 2) 333 - return -EINVAL; 334 - 335 - cmd_buf = memdup_user_nul(buf, count); 336 - if (IS_ERR(cmd_buf)) 337 - return PTR_ERR(cmd_buf); 338 - 339 - ret = sscanf(cmd_buf, "%s", user_val); 340 - if (ret != 1) 341 - return -EINVAL; 342 - 343 - ret = kstrtobool(user_val, &enable); 344 - if (ret) 345 - goto enable_write_error; 346 - 347 - if (enable) 348 - hw->fwlog_cfg.options |= ICE_FWLOG_OPTION_ARQ_ENA; 349 - else 350 - hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_ARQ_ENA; 351 - 352 - ret = ice_fwlog_set(hw, &hw->fwlog_cfg); 353 - if (ret) 354 - goto enable_write_error; 355 - 356 - if (enable) 357 - ret = ice_fwlog_register(hw); 358 - else 359 - ret = ice_fwlog_unregister(hw); 360 - 361 - if (ret) 362 - goto enable_write_error; 363 - 364 - /* if we get here, nothing went wrong; return count since we didn't 365 - * really write anything 366 - */ 367 - ret = (ssize_t)count; 368 - 369 - enable_write_error: 370 - /* This function always consumes all of the written input, or produces 371 - * an error. Check and enforce this. Otherwise, the write operation 372 - * won't complete properly. 373 - */ 374 - if (WARN_ON(ret != (ssize_t)count && ret >= 0)) 375 - ret = -EIO; 376 - 377 - return ret; 378 - } 379 - 380 - static const struct file_operations ice_debugfs_enable_fops = { 381 - .owner = THIS_MODULE, 382 - .open = simple_open, 383 - .read = ice_debugfs_enable_read, 384 - .write = ice_debugfs_enable_write, 385 - }; 386 - 387 - /** 388 - * ice_debugfs_log_size_read - read from 'log_size' file 389 - * @filp: the opened file 390 - * @buffer: where to write the data for the user to read 391 - * @count: the size of the user's buffer 392 - * @ppos: file position offset 393 - */ 394 - static ssize_t ice_debugfs_log_size_read(struct file *filp, 395 - char __user *buffer, size_t count, 396 - loff_t *ppos) 397 - { 398 - struct ice_pf *pf = filp->private_data; 399 - struct ice_hw *hw = &pf->hw; 400 - char buff[32] = {}; 401 - int index; 402 - 403 - index = hw->fwlog_ring.index; 404 - snprintf(buff, sizeof(buff), "%s\n", ice_fwlog_log_size[index]); 405 - 406 - return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff)); 407 - } 408 - 409 - /** 410 - * ice_debugfs_log_size_write - write into 'log_size' file 411 - * @filp: the opened file 412 - * @buf: where to find the user's data 413 - * @count: the length of the user's data 414 - * @ppos: file position offset 415 - */ 416 - static ssize_t 417 - ice_debugfs_log_size_write(struct file *filp, const char __user *buf, 418 - size_t count, loff_t *ppos) 419 - { 420 - struct ice_pf *pf = filp->private_data; 421 - struct device *dev = ice_pf_to_dev(pf); 422 - struct ice_hw *hw = &pf->hw; 423 - char user_val[8], *cmd_buf; 424 - ssize_t ret; 425 - int index; 426 - 427 - /* don't allow partial writes or invalid input */ 428 - if (*ppos != 0 || count > 5) 429 - return -EINVAL; 430 - 431 - cmd_buf = memdup_user_nul(buf, count); 432 - if (IS_ERR(cmd_buf)) 433 - return PTR_ERR(cmd_buf); 434 - 435 - ret = sscanf(cmd_buf, "%s", user_val); 436 - if (ret != 1) 437 - return -EINVAL; 438 - 439 - index = sysfs_match_string(ice_fwlog_log_size, user_val); 440 - if (index < 0) { 441 - dev_info(dev, "Invalid log size '%s'. The value must be one of 128K, 256K, 512K, 1M, 2M\n", 442 - user_val); 443 - ret = -EINVAL; 444 - goto log_size_write_error; 445 - } else if (hw->fwlog_cfg.options & ICE_FWLOG_OPTION_IS_REGISTERED) { 446 - dev_info(dev, "FW logging is currently running. Please disable FW logging to change log_size\n"); 447 - ret = -EINVAL; 448 - goto log_size_write_error; 449 - } 450 - 451 - /* free all the buffers and the tracking info and resize */ 452 - ice_fwlog_realloc_rings(hw, index); 453 - 454 - /* if we get here, nothing went wrong; return count since we didn't 455 - * really write anything 456 - */ 457 - ret = (ssize_t)count; 458 - 459 - log_size_write_error: 460 - /* This function always consumes all of the written input, or produces 461 - * an error. Check and enforce this. Otherwise, the write operation 462 - * won't complete properly. 463 - */ 464 - if (WARN_ON(ret != (ssize_t)count && ret >= 0)) 465 - ret = -EIO; 466 - 467 - return ret; 468 - } 469 - 470 - static const struct file_operations ice_debugfs_log_size_fops = { 471 - .owner = THIS_MODULE, 472 - .open = simple_open, 473 - .read = ice_debugfs_log_size_read, 474 - .write = ice_debugfs_log_size_write, 475 - }; 476 - 477 - /** 478 - * ice_debugfs_data_read - read from 'data' file 479 - * @filp: the opened file 480 - * @buffer: where to write the data for the user to read 481 - * @count: the size of the user's buffer 482 - * @ppos: file position offset 483 - */ 484 - static ssize_t ice_debugfs_data_read(struct file *filp, char __user *buffer, 485 - size_t count, loff_t *ppos) 486 - { 487 - struct ice_pf *pf = filp->private_data; 488 - struct ice_hw *hw = &pf->hw; 489 - int data_copied = 0; 490 - bool done = false; 491 - 492 - if (ice_fwlog_ring_empty(&hw->fwlog_ring)) 493 - return 0; 494 - 495 - while (!ice_fwlog_ring_empty(&hw->fwlog_ring) && !done) { 496 - struct ice_fwlog_data *log; 497 - u16 cur_buf_len; 498 - 499 - log = &hw->fwlog_ring.rings[hw->fwlog_ring.head]; 500 - cur_buf_len = log->data_size; 501 - if (cur_buf_len >= count) { 502 - done = true; 503 - continue; 504 - } 505 - 506 - if (copy_to_user(buffer, log->data, cur_buf_len)) { 507 - /* if there is an error then bail and return whatever 508 - * the driver has copied so far 509 - */ 510 - done = true; 511 - continue; 512 - } 513 - 514 - data_copied += cur_buf_len; 515 - buffer += cur_buf_len; 516 - count -= cur_buf_len; 517 - *ppos += cur_buf_len; 518 - ice_fwlog_ring_increment(&hw->fwlog_ring.head, 519 - hw->fwlog_ring.size); 520 - } 521 - 522 - return data_copied; 523 - } 524 - 525 - /** 526 - * ice_debugfs_data_write - write into 'data' file 527 - * @filp: the opened file 528 - * @buf: where to find the user's data 529 - * @count: the length of the user's data 530 - * @ppos: file position offset 531 - */ 532 - static ssize_t 533 - ice_debugfs_data_write(struct file *filp, const char __user *buf, size_t count, 534 - loff_t *ppos) 535 - { 536 - struct ice_pf *pf = filp->private_data; 537 - struct device *dev = ice_pf_to_dev(pf); 538 - struct ice_hw *hw = &pf->hw; 539 - ssize_t ret; 540 - 541 - /* don't allow partial writes */ 542 - if (*ppos != 0) 543 - return 0; 544 - 545 - /* any value is allowed to clear the buffer so no need to even look at 546 - * what the value is 547 - */ 548 - if (!(hw->fwlog_cfg.options & ICE_FWLOG_OPTION_IS_REGISTERED)) { 549 - hw->fwlog_ring.head = 0; 550 - hw->fwlog_ring.tail = 0; 551 - } else { 552 - dev_info(dev, "Can't clear FW log data while FW log running\n"); 553 - ret = -EINVAL; 554 - goto nr_buffs_write_error; 555 - } 556 - 557 - /* if we get here, nothing went wrong; return count since we didn't 558 - * really write anything 559 - */ 560 - ret = (ssize_t)count; 561 - 562 - nr_buffs_write_error: 563 - /* This function always consumes all of the written input, or produces 564 - * an error. Check and enforce this. Otherwise, the write operation 565 - * won't complete properly. 566 - */ 567 - if (WARN_ON(ret != (ssize_t)count && ret >= 0)) 568 - ret = -EIO; 569 - 570 - return ret; 571 - } 572 - 573 - static const struct file_operations ice_debugfs_data_fops = { 574 - .owner = THIS_MODULE, 575 - .open = simple_open, 576 - .read = ice_debugfs_data_read, 577 - .write = ice_debugfs_data_write, 578 - }; 579 - 580 - /** 581 - * ice_debugfs_fwlog_init - setup the debugfs directory 582 - * @pf: the ice that is starting up 583 - */ 584 - void ice_debugfs_fwlog_init(struct ice_pf *pf) 9 + int ice_debugfs_pf_init(struct ice_pf *pf) 585 10 { 586 11 const char *name = pci_name(pf->pdev); 587 - struct dentry *fw_modules_dir; 588 - struct dentry **fw_modules; 589 - int i; 590 - 591 - /* only support fw log commands on PF 0 */ 592 - if (pf->hw.bus.func) 593 - return; 594 - 595 - /* allocate space for this first because if it fails then we don't 596 - * need to unwind 597 - */ 598 - fw_modules = kcalloc(ICE_NR_FW_LOG_MODULES, sizeof(*fw_modules), 599 - GFP_KERNEL); 600 - if (!fw_modules) 601 - return; 602 12 603 13 pf->ice_debugfs_pf = debugfs_create_dir(name, ice_debugfs_root); 604 14 if (IS_ERR(pf->ice_debugfs_pf)) 605 - goto err_create_module_files; 15 + return PTR_ERR(pf->ice_debugfs_pf); 606 16 607 - pf->ice_debugfs_pf_fwlog = debugfs_create_dir("fwlog", 608 - pf->ice_debugfs_pf); 609 - if (IS_ERR(pf->ice_debugfs_pf_fwlog)) 610 - goto err_create_module_files; 611 - 612 - fw_modules_dir = debugfs_create_dir("modules", 613 - pf->ice_debugfs_pf_fwlog); 614 - if (IS_ERR(fw_modules_dir)) 615 - goto err_create_module_files; 616 - 617 - for (i = 0; i < ICE_NR_FW_LOG_MODULES; i++) { 618 - fw_modules[i] = debugfs_create_file(ice_fwlog_module_string[i], 619 - 0600, fw_modules_dir, pf, 620 - &ice_debugfs_module_fops); 621 - if (IS_ERR(fw_modules[i])) 622 - goto err_create_module_files; 623 - } 624 - 625 - debugfs_create_file("nr_messages", 0600, 626 - pf->ice_debugfs_pf_fwlog, pf, 627 - &ice_debugfs_nr_messages_fops); 628 - 629 - pf->ice_debugfs_pf_fwlog_modules = fw_modules; 630 - 631 - debugfs_create_file("enable", 0600, pf->ice_debugfs_pf_fwlog, 632 - pf, &ice_debugfs_enable_fops); 633 - 634 - debugfs_create_file("log_size", 0600, pf->ice_debugfs_pf_fwlog, 635 - pf, &ice_debugfs_log_size_fops); 636 - 637 - debugfs_create_file("data", 0600, pf->ice_debugfs_pf_fwlog, 638 - pf, &ice_debugfs_data_fops); 639 - 640 - return; 641 - 642 - err_create_module_files: 643 - debugfs_remove_recursive(pf->ice_debugfs_pf_fwlog); 644 - kfree(fw_modules); 17 + return 0; 645 18 } 646 19 647 20 /**
-474
drivers/net/ethernet/intel/ice/ice_fwlog.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* Copyright (c) 2022, Intel Corporation. */ 3 - 4 - #include <linux/vmalloc.h> 5 - #include "ice.h" 6 - #include "ice_common.h" 7 - #include "ice_fwlog.h" 8 - 9 - bool ice_fwlog_ring_full(struct ice_fwlog_ring *rings) 10 - { 11 - u16 head, tail; 12 - 13 - head = rings->head; 14 - tail = rings->tail; 15 - 16 - if (head < tail && (tail - head == (rings->size - 1))) 17 - return true; 18 - else if (head > tail && (tail == (head - 1))) 19 - return true; 20 - 21 - return false; 22 - } 23 - 24 - bool ice_fwlog_ring_empty(struct ice_fwlog_ring *rings) 25 - { 26 - return rings->head == rings->tail; 27 - } 28 - 29 - void ice_fwlog_ring_increment(u16 *item, u16 size) 30 - { 31 - *item = (*item + 1) & (size - 1); 32 - } 33 - 34 - static int ice_fwlog_alloc_ring_buffs(struct ice_fwlog_ring *rings) 35 - { 36 - int i, nr_bytes; 37 - u8 *mem; 38 - 39 - nr_bytes = rings->size * ICE_AQ_MAX_BUF_LEN; 40 - mem = vzalloc(nr_bytes); 41 - if (!mem) 42 - return -ENOMEM; 43 - 44 - for (i = 0; i < rings->size; i++) { 45 - struct ice_fwlog_data *ring = &rings->rings[i]; 46 - 47 - ring->data_size = ICE_AQ_MAX_BUF_LEN; 48 - ring->data = mem; 49 - mem += ICE_AQ_MAX_BUF_LEN; 50 - } 51 - 52 - return 0; 53 - } 54 - 55 - static void ice_fwlog_free_ring_buffs(struct ice_fwlog_ring *rings) 56 - { 57 - int i; 58 - 59 - for (i = 0; i < rings->size; i++) { 60 - struct ice_fwlog_data *ring = &rings->rings[i]; 61 - 62 - /* the first ring is the base memory for the whole range so 63 - * free it 64 - */ 65 - if (!i) 66 - vfree(ring->data); 67 - 68 - ring->data = NULL; 69 - ring->data_size = 0; 70 - } 71 - } 72 - 73 - #define ICE_FWLOG_INDEX_TO_BYTES(n) ((128 * 1024) << (n)) 74 - /** 75 - * ice_fwlog_realloc_rings - reallocate the FW log rings 76 - * @hw: pointer to the HW structure 77 - * @index: the new index to use to allocate memory for the log data 78 - * 79 - */ 80 - void ice_fwlog_realloc_rings(struct ice_hw *hw, int index) 81 - { 82 - struct ice_fwlog_ring ring; 83 - int status, ring_size; 84 - 85 - /* convert the number of bytes into a number of 4K buffers. externally 86 - * the driver presents the interface to the FW log data as a number of 87 - * bytes because that's easy for users to understand. internally the 88 - * driver uses a ring of buffers because the driver doesn't know where 89 - * the beginning and end of any line of log data is so the driver has 90 - * to overwrite data as complete blocks. when the data is returned to 91 - * the user the driver knows that the data is correct and the FW log 92 - * can be correctly parsed by the tools 93 - */ 94 - ring_size = ICE_FWLOG_INDEX_TO_BYTES(index) / ICE_AQ_MAX_BUF_LEN; 95 - if (ring_size == hw->fwlog_ring.size) 96 - return; 97 - 98 - /* allocate space for the new rings and buffers then release the 99 - * old rings and buffers. that way if we don't have enough 100 - * memory then we at least have what we had before 101 - */ 102 - ring.rings = kcalloc(ring_size, sizeof(*ring.rings), GFP_KERNEL); 103 - if (!ring.rings) 104 - return; 105 - 106 - ring.size = ring_size; 107 - 108 - status = ice_fwlog_alloc_ring_buffs(&ring); 109 - if (status) { 110 - dev_warn(ice_hw_to_dev(hw), "Unable to allocate memory for FW log ring data buffers\n"); 111 - ice_fwlog_free_ring_buffs(&ring); 112 - kfree(ring.rings); 113 - return; 114 - } 115 - 116 - ice_fwlog_free_ring_buffs(&hw->fwlog_ring); 117 - kfree(hw->fwlog_ring.rings); 118 - 119 - hw->fwlog_ring.rings = ring.rings; 120 - hw->fwlog_ring.size = ring.size; 121 - hw->fwlog_ring.index = index; 122 - hw->fwlog_ring.head = 0; 123 - hw->fwlog_ring.tail = 0; 124 - } 125 - 126 - /** 127 - * ice_fwlog_init - Initialize FW logging configuration 128 - * @hw: pointer to the HW structure 129 - * 130 - * This function should be called on driver initialization during 131 - * ice_init_hw(). 132 - */ 133 - int ice_fwlog_init(struct ice_hw *hw) 134 - { 135 - /* only support fw log commands on PF 0 */ 136 - if (hw->bus.func) 137 - return -EINVAL; 138 - 139 - ice_fwlog_set_supported(hw); 140 - 141 - if (ice_fwlog_supported(hw)) { 142 - int status; 143 - 144 - /* read the current config from the FW and store it */ 145 - status = ice_fwlog_get(hw, &hw->fwlog_cfg); 146 - if (status) 147 - return status; 148 - 149 - hw->fwlog_ring.rings = kcalloc(ICE_FWLOG_RING_SIZE_DFLT, 150 - sizeof(*hw->fwlog_ring.rings), 151 - GFP_KERNEL); 152 - if (!hw->fwlog_ring.rings) { 153 - dev_warn(ice_hw_to_dev(hw), "Unable to allocate memory for FW log rings\n"); 154 - return -ENOMEM; 155 - } 156 - 157 - hw->fwlog_ring.size = ICE_FWLOG_RING_SIZE_DFLT; 158 - hw->fwlog_ring.index = ICE_FWLOG_RING_SIZE_INDEX_DFLT; 159 - 160 - status = ice_fwlog_alloc_ring_buffs(&hw->fwlog_ring); 161 - if (status) { 162 - dev_warn(ice_hw_to_dev(hw), "Unable to allocate memory for FW log ring data buffers\n"); 163 - ice_fwlog_free_ring_buffs(&hw->fwlog_ring); 164 - kfree(hw->fwlog_ring.rings); 165 - return status; 166 - } 167 - 168 - ice_debugfs_fwlog_init(hw->back); 169 - } else { 170 - dev_warn(ice_hw_to_dev(hw), "FW logging is not supported in this NVM image. Please update the NVM to get FW log support\n"); 171 - } 172 - 173 - return 0; 174 - } 175 - 176 - /** 177 - * ice_fwlog_deinit - unroll FW logging configuration 178 - * @hw: pointer to the HW structure 179 - * 180 - * This function should be called in ice_deinit_hw(). 181 - */ 182 - void ice_fwlog_deinit(struct ice_hw *hw) 183 - { 184 - struct ice_pf *pf = hw->back; 185 - int status; 186 - 187 - /* only support fw log commands on PF 0 */ 188 - if (hw->bus.func) 189 - return; 190 - 191 - ice_debugfs_pf_deinit(hw->back); 192 - 193 - /* make sure FW logging is disabled to not put the FW in a weird state 194 - * for the next driver load 195 - */ 196 - hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_ARQ_ENA; 197 - status = ice_fwlog_set(hw, &hw->fwlog_cfg); 198 - if (status) 199 - dev_warn(ice_hw_to_dev(hw), "Unable to turn off FW logging, status: %d\n", 200 - status); 201 - 202 - kfree(pf->ice_debugfs_pf_fwlog_modules); 203 - 204 - pf->ice_debugfs_pf_fwlog_modules = NULL; 205 - 206 - status = ice_fwlog_unregister(hw); 207 - if (status) 208 - dev_warn(ice_hw_to_dev(hw), "Unable to unregister FW logging, status: %d\n", 209 - status); 210 - 211 - if (hw->fwlog_ring.rings) { 212 - ice_fwlog_free_ring_buffs(&hw->fwlog_ring); 213 - kfree(hw->fwlog_ring.rings); 214 - } 215 - } 216 - 217 - /** 218 - * ice_fwlog_supported - Cached for whether FW supports FW logging or not 219 - * @hw: pointer to the HW structure 220 - * 221 - * This will always return false if called before ice_init_hw(), so it must be 222 - * called after ice_init_hw(). 223 - */ 224 - bool ice_fwlog_supported(struct ice_hw *hw) 225 - { 226 - return hw->fwlog_supported; 227 - } 228 - 229 - /** 230 - * ice_aq_fwlog_set - Set FW logging configuration AQ command (0xFF30) 231 - * @hw: pointer to the HW structure 232 - * @entries: entries to configure 233 - * @num_entries: number of @entries 234 - * @options: options from ice_fwlog_cfg->options structure 235 - * @log_resolution: logging resolution 236 - */ 237 - static int 238 - ice_aq_fwlog_set(struct ice_hw *hw, struct ice_fwlog_module_entry *entries, 239 - u16 num_entries, u16 options, u16 log_resolution) 240 - { 241 - struct ice_aqc_fw_log_cfg_resp *fw_modules; 242 - struct ice_aqc_fw_log *cmd; 243 - struct libie_aq_desc desc; 244 - int status; 245 - int i; 246 - 247 - fw_modules = kcalloc(num_entries, sizeof(*fw_modules), GFP_KERNEL); 248 - if (!fw_modules) 249 - return -ENOMEM; 250 - 251 - for (i = 0; i < num_entries; i++) { 252 - fw_modules[i].module_identifier = 253 - cpu_to_le16(entries[i].module_id); 254 - fw_modules[i].log_level = entries[i].log_level; 255 - } 256 - 257 - ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_config); 258 - desc.flags |= cpu_to_le16(LIBIE_AQ_FLAG_RD); 259 - 260 - cmd = libie_aq_raw(&desc); 261 - 262 - cmd->cmd_flags = ICE_AQC_FW_LOG_CONF_SET_VALID; 263 - cmd->ops.cfg.log_resolution = cpu_to_le16(log_resolution); 264 - cmd->ops.cfg.mdl_cnt = cpu_to_le16(num_entries); 265 - 266 - if (options & ICE_FWLOG_OPTION_ARQ_ENA) 267 - cmd->cmd_flags |= ICE_AQC_FW_LOG_CONF_AQ_EN; 268 - if (options & ICE_FWLOG_OPTION_UART_ENA) 269 - cmd->cmd_flags |= ICE_AQC_FW_LOG_CONF_UART_EN; 270 - 271 - status = ice_aq_send_cmd(hw, &desc, fw_modules, 272 - sizeof(*fw_modules) * num_entries, 273 - NULL); 274 - 275 - kfree(fw_modules); 276 - 277 - return status; 278 - } 279 - 280 - /** 281 - * ice_fwlog_set - Set the firmware logging settings 282 - * @hw: pointer to the HW structure 283 - * @cfg: config used to set firmware logging 284 - * 285 - * This function should be called whenever the driver needs to set the firmware 286 - * logging configuration. It can be called on initialization, reset, or during 287 - * runtime. 288 - * 289 - * If the PF wishes to receive FW logging then it must register via 290 - * ice_fwlog_register. Note, that ice_fwlog_register does not need to be called 291 - * for init. 292 - */ 293 - int ice_fwlog_set(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) 294 - { 295 - if (!ice_fwlog_supported(hw)) 296 - return -EOPNOTSUPP; 297 - 298 - return ice_aq_fwlog_set(hw, cfg->module_entries, 299 - ICE_AQC_FW_LOG_ID_MAX, cfg->options, 300 - cfg->log_resolution); 301 - } 302 - 303 - /** 304 - * ice_aq_fwlog_get - Get the current firmware logging configuration (0xFF32) 305 - * @hw: pointer to the HW structure 306 - * @cfg: firmware logging configuration to populate 307 - */ 308 - static int ice_aq_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) 309 - { 310 - struct ice_aqc_fw_log_cfg_resp *fw_modules; 311 - struct ice_aqc_fw_log *cmd; 312 - struct libie_aq_desc desc; 313 - u16 module_id_cnt; 314 - int status; 315 - void *buf; 316 - int i; 317 - 318 - memset(cfg, 0, sizeof(*cfg)); 319 - 320 - buf = kzalloc(ICE_AQ_MAX_BUF_LEN, GFP_KERNEL); 321 - if (!buf) 322 - return -ENOMEM; 323 - 324 - ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_query); 325 - cmd = libie_aq_raw(&desc); 326 - 327 - cmd->cmd_flags = ICE_AQC_FW_LOG_AQ_QUERY; 328 - 329 - status = ice_aq_send_cmd(hw, &desc, buf, ICE_AQ_MAX_BUF_LEN, NULL); 330 - if (status) { 331 - ice_debug(hw, ICE_DBG_FW_LOG, "Failed to get FW log configuration\n"); 332 - goto status_out; 333 - } 334 - 335 - module_id_cnt = le16_to_cpu(cmd->ops.cfg.mdl_cnt); 336 - if (module_id_cnt < ICE_AQC_FW_LOG_ID_MAX) { 337 - ice_debug(hw, ICE_DBG_FW_LOG, "FW returned less than the expected number of FW log module IDs\n"); 338 - } else if (module_id_cnt > ICE_AQC_FW_LOG_ID_MAX) { 339 - ice_debug(hw, ICE_DBG_FW_LOG, "FW returned more than expected number of FW log module IDs, setting module_id_cnt to software expected max %u\n", 340 - ICE_AQC_FW_LOG_ID_MAX); 341 - module_id_cnt = ICE_AQC_FW_LOG_ID_MAX; 342 - } 343 - 344 - cfg->log_resolution = le16_to_cpu(cmd->ops.cfg.log_resolution); 345 - if (cmd->cmd_flags & ICE_AQC_FW_LOG_CONF_AQ_EN) 346 - cfg->options |= ICE_FWLOG_OPTION_ARQ_ENA; 347 - if (cmd->cmd_flags & ICE_AQC_FW_LOG_CONF_UART_EN) 348 - cfg->options |= ICE_FWLOG_OPTION_UART_ENA; 349 - if (cmd->cmd_flags & ICE_AQC_FW_LOG_QUERY_REGISTERED) 350 - cfg->options |= ICE_FWLOG_OPTION_IS_REGISTERED; 351 - 352 - fw_modules = (struct ice_aqc_fw_log_cfg_resp *)buf; 353 - 354 - for (i = 0; i < module_id_cnt; i++) { 355 - struct ice_aqc_fw_log_cfg_resp *fw_module = &fw_modules[i]; 356 - 357 - cfg->module_entries[i].module_id = 358 - le16_to_cpu(fw_module->module_identifier); 359 - cfg->module_entries[i].log_level = fw_module->log_level; 360 - } 361 - 362 - status_out: 363 - kfree(buf); 364 - return status; 365 - } 366 - 367 - /** 368 - * ice_fwlog_get - Get the firmware logging settings 369 - * @hw: pointer to the HW structure 370 - * @cfg: config to populate based on current firmware logging settings 371 - */ 372 - int ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg) 373 - { 374 - if (!ice_fwlog_supported(hw)) 375 - return -EOPNOTSUPP; 376 - 377 - return ice_aq_fwlog_get(hw, cfg); 378 - } 379 - 380 - /** 381 - * ice_aq_fwlog_register - Register PF for firmware logging events (0xFF31) 382 - * @hw: pointer to the HW structure 383 - * @reg: true to register and false to unregister 384 - */ 385 - static int ice_aq_fwlog_register(struct ice_hw *hw, bool reg) 386 - { 387 - struct ice_aqc_fw_log *cmd; 388 - struct libie_aq_desc desc; 389 - 390 - ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_register); 391 - cmd = libie_aq_raw(&desc); 392 - 393 - if (reg) 394 - cmd->cmd_flags = ICE_AQC_FW_LOG_AQ_REGISTER; 395 - 396 - return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 397 - } 398 - 399 - /** 400 - * ice_fwlog_register - Register the PF for firmware logging 401 - * @hw: pointer to the HW structure 402 - * 403 - * After this call the PF will start to receive firmware logging based on the 404 - * configuration set in ice_fwlog_set. 405 - */ 406 - int ice_fwlog_register(struct ice_hw *hw) 407 - { 408 - int status; 409 - 410 - if (!ice_fwlog_supported(hw)) 411 - return -EOPNOTSUPP; 412 - 413 - status = ice_aq_fwlog_register(hw, true); 414 - if (status) 415 - ice_debug(hw, ICE_DBG_FW_LOG, "Failed to register for firmware logging events over ARQ\n"); 416 - else 417 - hw->fwlog_cfg.options |= ICE_FWLOG_OPTION_IS_REGISTERED; 418 - 419 - return status; 420 - } 421 - 422 - /** 423 - * ice_fwlog_unregister - Unregister the PF from firmware logging 424 - * @hw: pointer to the HW structure 425 - */ 426 - int ice_fwlog_unregister(struct ice_hw *hw) 427 - { 428 - int status; 429 - 430 - if (!ice_fwlog_supported(hw)) 431 - return -EOPNOTSUPP; 432 - 433 - status = ice_aq_fwlog_register(hw, false); 434 - if (status) 435 - ice_debug(hw, ICE_DBG_FW_LOG, "Failed to unregister from firmware logging events over ARQ\n"); 436 - else 437 - hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_IS_REGISTERED; 438 - 439 - return status; 440 - } 441 - 442 - /** 443 - * ice_fwlog_set_supported - Set if FW logging is supported by FW 444 - * @hw: pointer to the HW struct 445 - * 446 - * If FW returns success to the ice_aq_fwlog_get call then it supports FW 447 - * logging, else it doesn't. Set the fwlog_supported flag accordingly. 448 - * 449 - * This function is only meant to be called during driver init to determine if 450 - * the FW support FW logging. 451 - */ 452 - void ice_fwlog_set_supported(struct ice_hw *hw) 453 - { 454 - struct ice_fwlog_cfg *cfg; 455 - int status; 456 - 457 - hw->fwlog_supported = false; 458 - 459 - cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); 460 - if (!cfg) 461 - return; 462 - 463 - /* don't call ice_fwlog_get() because that would check to see if FW 464 - * logging is supported which is what the driver is determining now 465 - */ 466 - status = ice_aq_fwlog_get(hw, cfg); 467 - if (status) 468 - ice_debug(hw, ICE_DBG_FW_LOG, "ice_aq_fwlog_get failed, FW logging is not supported on this version of FW, status %d\n", 469 - status); 470 - else 471 - hw->fwlog_supported = true; 472 - 473 - kfree(cfg); 474 - }
-79
drivers/net/ethernet/intel/ice/ice_fwlog.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - /* Copyright (C) 2022, Intel Corporation. */ 3 - 4 - #ifndef _ICE_FWLOG_H_ 5 - #define _ICE_FWLOG_H_ 6 - #include "ice_adminq_cmd.h" 7 - 8 - struct ice_hw; 9 - 10 - /* Only a single log level should be set and all log levels under the set value 11 - * are enabled, e.g. if log level is set to ICE_FW_LOG_LEVEL_VERBOSE, then all 12 - * other log levels are included (except ICE_FW_LOG_LEVEL_NONE) 13 - */ 14 - enum ice_fwlog_level { 15 - ICE_FWLOG_LEVEL_NONE = 0, 16 - ICE_FWLOG_LEVEL_ERROR = 1, 17 - ICE_FWLOG_LEVEL_WARNING = 2, 18 - ICE_FWLOG_LEVEL_NORMAL = 3, 19 - ICE_FWLOG_LEVEL_VERBOSE = 4, 20 - ICE_FWLOG_LEVEL_INVALID, /* all values >= this entry are invalid */ 21 - }; 22 - 23 - struct ice_fwlog_module_entry { 24 - /* module ID for the corresponding firmware logging event */ 25 - u16 module_id; 26 - /* verbosity level for the module_id */ 27 - u8 log_level; 28 - }; 29 - 30 - struct ice_fwlog_cfg { 31 - /* list of modules for configuring log level */ 32 - struct ice_fwlog_module_entry module_entries[ICE_AQC_FW_LOG_ID_MAX]; 33 - /* options used to configure firmware logging */ 34 - u16 options; 35 - #define ICE_FWLOG_OPTION_ARQ_ENA BIT(0) 36 - #define ICE_FWLOG_OPTION_UART_ENA BIT(1) 37 - /* set before calling ice_fwlog_init() so the PF registers for firmware 38 - * logging on initialization 39 - */ 40 - #define ICE_FWLOG_OPTION_REGISTER_ON_INIT BIT(2) 41 - /* set in the ice_fwlog_get() response if the PF is registered for FW 42 - * logging events over ARQ 43 - */ 44 - #define ICE_FWLOG_OPTION_IS_REGISTERED BIT(3) 45 - 46 - /* minimum number of log events sent per Admin Receive Queue event */ 47 - u16 log_resolution; 48 - }; 49 - 50 - struct ice_fwlog_data { 51 - u16 data_size; 52 - u8 *data; 53 - }; 54 - 55 - struct ice_fwlog_ring { 56 - struct ice_fwlog_data *rings; 57 - u16 index; 58 - u16 size; 59 - u16 head; 60 - u16 tail; 61 - }; 62 - 63 - #define ICE_FWLOG_RING_SIZE_INDEX_DFLT 3 64 - #define ICE_FWLOG_RING_SIZE_DFLT 256 65 - #define ICE_FWLOG_RING_SIZE_MAX 512 66 - 67 - bool ice_fwlog_ring_full(struct ice_fwlog_ring *rings); 68 - bool ice_fwlog_ring_empty(struct ice_fwlog_ring *rings); 69 - void ice_fwlog_ring_increment(u16 *item, u16 size); 70 - void ice_fwlog_set_supported(struct ice_hw *hw); 71 - bool ice_fwlog_supported(struct ice_hw *hw); 72 - int ice_fwlog_init(struct ice_hw *hw); 73 - void ice_fwlog_deinit(struct ice_hw *hw); 74 - int ice_fwlog_set(struct ice_hw *hw, struct ice_fwlog_cfg *cfg); 75 - int ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg); 76 - int ice_fwlog_register(struct ice_hw *hw); 77 - int ice_fwlog_unregister(struct ice_hw *hw); 78 - void ice_fwlog_realloc_rings(struct ice_hw *hw, int index); 79 - #endif /* _ICE_FWLOG_H_ */
+3 -40
drivers/net/ethernet/intel/ice/ice_main.c
··· 39 39 MODULE_DESCRIPTION(DRV_SUMMARY); 40 40 MODULE_IMPORT_NS("LIBIE"); 41 41 MODULE_IMPORT_NS("LIBIE_ADMINQ"); 42 + MODULE_IMPORT_NS("LIBIE_FWLOG"); 42 43 MODULE_LICENSE("GPL v2"); 43 44 MODULE_FIRMWARE(ICE_DDP_PKG_FILE); 44 45 ··· 1252 1251 } 1253 1252 1254 1253 /** 1255 - * ice_get_fwlog_data - copy the FW log data from ARQ event 1256 - * @pf: PF that the FW log event is associated with 1257 - * @event: event structure containing FW log data 1258 - */ 1259 - static void 1260 - ice_get_fwlog_data(struct ice_pf *pf, struct ice_rq_event_info *event) 1261 - { 1262 - struct ice_fwlog_data *fwlog; 1263 - struct ice_hw *hw = &pf->hw; 1264 - 1265 - fwlog = &hw->fwlog_ring.rings[hw->fwlog_ring.tail]; 1266 - 1267 - memset(fwlog->data, 0, PAGE_SIZE); 1268 - fwlog->data_size = le16_to_cpu(event->desc.datalen); 1269 - 1270 - memcpy(fwlog->data, event->msg_buf, fwlog->data_size); 1271 - ice_fwlog_ring_increment(&hw->fwlog_ring.tail, hw->fwlog_ring.size); 1272 - 1273 - if (ice_fwlog_ring_full(&hw->fwlog_ring)) { 1274 - /* the rings are full so bump the head to create room */ 1275 - ice_fwlog_ring_increment(&hw->fwlog_ring.head, 1276 - hw->fwlog_ring.size); 1277 - } 1278 - } 1279 - 1280 - /** 1281 1254 * ice_aq_prep_for_event - Prepare to wait for an AdminQ event from firmware 1282 1255 * @pf: pointer to the PF private structure 1283 1256 * @task: intermediate helper storage and identifier for waiting ··· 1541 1566 } 1542 1567 break; 1543 1568 case ice_aqc_opc_fw_logs_event: 1544 - ice_get_fwlog_data(pf, &event); 1569 + libie_get_fwlog_data(&hw->fwlog, event.msg_buf, 1570 + le16_to_cpu(event.desc.datalen)); 1545 1571 break; 1546 1572 case ice_aqc_opc_lldp_set_mib_change: 1547 1573 ice_dcb_process_lldp_set_mib_change(pf, &event); ··· 4627 4651 wake_str = "Unknown\n"; 4628 4652 4629 4653 dev_info(ice_pf_to_dev(pf), "Wake reason: %s", wake_str); 4630 - } 4631 - 4632 - /** 4633 - * ice_pf_fwlog_update_module - update 1 module 4634 - * @pf: pointer to the PF struct 4635 - * @log_level: log_level to use for the @module 4636 - * @module: module to update 4637 - */ 4638 - void ice_pf_fwlog_update_module(struct ice_pf *pf, int log_level, int module) 4639 - { 4640 - struct ice_hw *hw = &pf->hw; 4641 - 4642 - hw->fwlog_cfg.module_entries[module].log_level = log_level; 4643 4654 } 4644 4655 4645 4656 /**
+2 -4
drivers/net/ethernet/intel/ice/ice_type.h
··· 17 17 #include "ice_protocol_type.h" 18 18 #include "ice_sbq_cmd.h" 19 19 #include "ice_vlan_mode.h" 20 - #include "ice_fwlog.h" 20 + #include <linux/net/intel/libie/fwlog.h> 21 21 #include <linux/wait.h> 22 22 #include <net/dscp.h> 23 23 ··· 948 948 u8 fw_patch; /* firmware patch version */ 949 949 u32 fw_build; /* firmware build number */ 950 950 951 - struct ice_fwlog_cfg fwlog_cfg; 952 - bool fwlog_supported; /* does hardware support FW logging? */ 953 - struct ice_fwlog_ring fwlog_ring; 951 + struct libie_fwlog fwlog; 954 952 955 953 /* Device max aggregate bandwidths corresponding to the GL_PWR_MODE_CTL 956 954 * register. Used for determining the ITR/INTRL granularity during
+32
drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c
··· 3921 3921 return err; 3922 3922 } 3923 3923 3924 + static int __fwlog_send_cmd(void *priv, struct libie_aq_desc *desc, void *buf, 3925 + u16 size) 3926 + { 3927 + struct ixgbe_hw *hw = priv; 3928 + 3929 + return ixgbe_aci_send_cmd(hw, desc, buf, size); 3930 + } 3931 + 3932 + int ixgbe_fwlog_init(struct ixgbe_hw *hw) 3933 + { 3934 + struct ixgbe_adapter *adapter = hw->back; 3935 + struct libie_fwlog_api api = { 3936 + .pdev = adapter->pdev, 3937 + .send_cmd = __fwlog_send_cmd, 3938 + .debugfs_root = adapter->ixgbe_dbg_adapter, 3939 + .priv = hw, 3940 + }; 3941 + 3942 + if (hw->mac.type != ixgbe_mac_e610) 3943 + return -EOPNOTSUPP; 3944 + 3945 + return libie_fwlog_init(&hw->fwlog, &api); 3946 + } 3947 + 3948 + void ixgbe_fwlog_deinit(struct ixgbe_hw *hw) 3949 + { 3950 + if (hw->mac.type != ixgbe_mac_e610) 3951 + return; 3952 + 3953 + libie_fwlog_deinit(&hw->fwlog); 3954 + } 3955 + 3924 3956 static const struct ixgbe_mac_operations mac_ops_e610 = { 3925 3957 .init_hw = ixgbe_init_hw_generic, 3926 3958 .start_hw = ixgbe_start_hw_e610,
+2
drivers/net/ethernet/intel/ixgbe/ixgbe_e610.h
··· 96 96 bool last_command, u8 command_flags); 97 97 int ixgbe_nvm_write_activate(struct ixgbe_hw *hw, u16 cmd_flags, 98 98 u8 *response_flags); 99 + int ixgbe_fwlog_init(struct ixgbe_hw *hw); 100 + void ixgbe_fwlog_deinit(struct ixgbe_hw *hw); 99 101 100 102 #endif /* _IXGBE_E610_H_ */
+10
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
··· 172 172 module_param(debug, int, 0); 173 173 MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); 174 174 175 + MODULE_IMPORT_NS("LIBIE_FWLOG"); 175 176 MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver"); 176 177 MODULE_LICENSE("GPL v2"); 177 178 ··· 3355 3354 case ixgbe_aci_opc_temp_tca_event: 3356 3355 e_crit(drv, "%s\n", ixgbe_overheat_msg); 3357 3356 ixgbe_down(adapter); 3357 + break; 3358 + case libie_aqc_opc_fw_logs_event: 3359 + libie_get_fwlog_data(&hw->fwlog, event.msg_buf, 3360 + le16_to_cpu(event.desc.datalen)); 3358 3361 break; 3359 3362 default: 3360 3363 e_warn(hw, "unknown FW async event captured\n"); ··· 12003 11998 ixgbe_devlink_init_regions(adapter); 12004 11999 devl_register(adapter->devlink); 12005 12000 devl_unlock(adapter->devlink); 12001 + 12002 + if (ixgbe_fwlog_init(hw)) 12003 + e_dev_info("Firmware logging not supported\n"); 12004 + 12006 12005 return 0; 12007 12006 12008 12007 err_netdev: ··· 12064 12055 devl_lock(adapter->devlink); 12065 12056 devl_unregister(adapter->devlink); 12066 12057 ixgbe_devlink_destroy_regions(adapter); 12058 + ixgbe_fwlog_deinit(&adapter->hw); 12067 12059 ixgbe_dbg_adapter_exit(adapter); 12068 12060 12069 12061 set_bit(__IXGBE_REMOVING, &adapter->state);
+2
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
··· 7 7 #include <linux/types.h> 8 8 #include <linux/mdio.h> 9 9 #include <linux/netdevice.h> 10 + #include <linux/net/intel/libie/fwlog.h> 10 11 #include "ixgbe_type_e610.h" 11 12 12 13 /* Device IDs */ ··· 3753 3752 struct ixgbe_flash_info flash; 3754 3753 struct ixgbe_hw_dev_caps dev_caps; 3755 3754 struct ixgbe_hw_func_caps func_caps; 3755 + struct libie_fwlog fwlog; 3756 3756 }; 3757 3757 3758 3758 struct ixgbe_info {
+9
drivers/net/ethernet/intel/libie/Kconfig
··· 14 14 help 15 15 Helper functions used by Intel Ethernet drivers for administration 16 16 queue command interface (aka adminq). 17 + 18 + config LIBIE_FWLOG 19 + tristate 20 + select LIBIE_ADMINQ 21 + help 22 + Library to support firmware logging on device that have support 23 + for it. Firmware logging is using admin queue interface to communicate 24 + with the device. Debugfs is a user interface used to config logging 25 + and dump all collected logs.
+4
drivers/net/ethernet/intel/libie/Makefile
··· 8 8 obj-$(CONFIG_LIBIE_ADMINQ) += libie_adminq.o 9 9 10 10 libie_adminq-y := adminq.o 11 + 12 + obj-$(CONFIG_LIBIE_FWLOG) += libie_fwlog.o 13 + 14 + libie_fwlog-y := fwlog.o
+1115
drivers/net/ethernet/intel/libie/fwlog.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2022, Intel Corporation. */ 3 + 4 + #include <linux/debugfs.h> 5 + #include <linux/export.h> 6 + #include <linux/fs.h> 7 + #include <linux/net/intel/libie/fwlog.h> 8 + #include <linux/pci.h> 9 + #include <linux/random.h> 10 + #include <linux/vmalloc.h> 11 + 12 + #define DEFAULT_SYMBOL_NAMESPACE "LIBIE_FWLOG" 13 + 14 + /* create a define that has an extra module that doesn't really exist. this 15 + * is so we can add a module 'all' to easily enable/disable all the modules 16 + */ 17 + #define LIBIE_NR_FW_LOG_MODULES (LIBIE_AQC_FW_LOG_ID_MAX + 1) 18 + 19 + /* the ordering in this array is important. it matches the ordering of the 20 + * values in the FW so the index is the same value as in 21 + * libie_aqc_fw_logging_mod 22 + */ 23 + static const char * const libie_fwlog_module_string[] = { 24 + "general", 25 + "ctrl", 26 + "link", 27 + "link_topo", 28 + "dnl", 29 + "i2c", 30 + "sdp", 31 + "mdio", 32 + "adminq", 33 + "hdma", 34 + "lldp", 35 + "dcbx", 36 + "dcb", 37 + "xlr", 38 + "nvm", 39 + "auth", 40 + "vpd", 41 + "iosf", 42 + "parser", 43 + "sw", 44 + "scheduler", 45 + "txq", 46 + "rsvd", 47 + "post", 48 + "watchdog", 49 + "task_dispatch", 50 + "mng", 51 + "synce", 52 + "health", 53 + "tsdrv", 54 + "pfreg", 55 + "mdlver", 56 + "all", 57 + }; 58 + 59 + /* the ordering in this array is important. it matches the ordering of the 60 + * values in the FW so the index is the same value as in libie_fwlog_level 61 + */ 62 + static const char * const libie_fwlog_level_string[] = { 63 + "none", 64 + "error", 65 + "warning", 66 + "normal", 67 + "verbose", 68 + }; 69 + 70 + static const char * const libie_fwlog_log_size[] = { 71 + "128K", 72 + "256K", 73 + "512K", 74 + "1M", 75 + "2M", 76 + }; 77 + 78 + static bool libie_fwlog_ring_empty(struct libie_fwlog_ring *rings) 79 + { 80 + return rings->head == rings->tail; 81 + } 82 + 83 + static void libie_fwlog_ring_increment(u16 *item, u16 size) 84 + { 85 + *item = (*item + 1) & (size - 1); 86 + } 87 + 88 + static int libie_fwlog_alloc_ring_buffs(struct libie_fwlog_ring *rings) 89 + { 90 + int i, nr_bytes; 91 + u8 *mem; 92 + 93 + nr_bytes = rings->size * LIBIE_AQ_MAX_BUF_LEN; 94 + mem = vzalloc(nr_bytes); 95 + if (!mem) 96 + return -ENOMEM; 97 + 98 + for (i = 0; i < rings->size; i++) { 99 + struct libie_fwlog_data *ring = &rings->rings[i]; 100 + 101 + ring->data_size = LIBIE_AQ_MAX_BUF_LEN; 102 + ring->data = mem; 103 + mem += LIBIE_AQ_MAX_BUF_LEN; 104 + } 105 + 106 + return 0; 107 + } 108 + 109 + static void libie_fwlog_free_ring_buffs(struct libie_fwlog_ring *rings) 110 + { 111 + int i; 112 + 113 + for (i = 0; i < rings->size; i++) { 114 + struct libie_fwlog_data *ring = &rings->rings[i]; 115 + 116 + /* the first ring is the base memory for the whole range so 117 + * free it 118 + */ 119 + if (!i) 120 + vfree(ring->data); 121 + 122 + ring->data = NULL; 123 + ring->data_size = 0; 124 + } 125 + } 126 + 127 + #define LIBIE_FWLOG_INDEX_TO_BYTES(n) ((128 * 1024) << (n)) 128 + /** 129 + * libie_fwlog_realloc_rings - reallocate the FW log rings 130 + * @fwlog: pointer to the fwlog structure 131 + * @index: the new index to use to allocate memory for the log data 132 + * 133 + */ 134 + static void libie_fwlog_realloc_rings(struct libie_fwlog *fwlog, int index) 135 + { 136 + struct libie_fwlog_ring ring; 137 + int status, ring_size; 138 + 139 + /* convert the number of bytes into a number of 4K buffers. externally 140 + * the driver presents the interface to the FW log data as a number of 141 + * bytes because that's easy for users to understand. internally the 142 + * driver uses a ring of buffers because the driver doesn't know where 143 + * the beginning and end of any line of log data is so the driver has 144 + * to overwrite data as complete blocks. when the data is returned to 145 + * the user the driver knows that the data is correct and the FW log 146 + * can be correctly parsed by the tools 147 + */ 148 + ring_size = LIBIE_FWLOG_INDEX_TO_BYTES(index) / LIBIE_AQ_MAX_BUF_LEN; 149 + if (ring_size == fwlog->ring.size) 150 + return; 151 + 152 + /* allocate space for the new rings and buffers then release the 153 + * old rings and buffers. that way if we don't have enough 154 + * memory then we at least have what we had before 155 + */ 156 + ring.rings = kcalloc(ring_size, sizeof(*ring.rings), GFP_KERNEL); 157 + if (!ring.rings) 158 + return; 159 + 160 + ring.size = ring_size; 161 + 162 + status = libie_fwlog_alloc_ring_buffs(&ring); 163 + if (status) { 164 + dev_warn(&fwlog->pdev->dev, "Unable to allocate memory for FW log ring data buffers\n"); 165 + libie_fwlog_free_ring_buffs(&ring); 166 + kfree(ring.rings); 167 + return; 168 + } 169 + 170 + libie_fwlog_free_ring_buffs(&fwlog->ring); 171 + kfree(fwlog->ring.rings); 172 + 173 + fwlog->ring.rings = ring.rings; 174 + fwlog->ring.size = ring.size; 175 + fwlog->ring.index = index; 176 + fwlog->ring.head = 0; 177 + fwlog->ring.tail = 0; 178 + } 179 + 180 + /** 181 + * libie_fwlog_supported - Cached for whether FW supports FW logging or not 182 + * @fwlog: pointer to the fwlog structure 183 + * 184 + * This will always return false if called before libie_init_hw(), so it must be 185 + * called after libie_init_hw(). 186 + */ 187 + static bool libie_fwlog_supported(struct libie_fwlog *fwlog) 188 + { 189 + return fwlog->supported; 190 + } 191 + 192 + /** 193 + * libie_aq_fwlog_set - Set FW logging configuration AQ command (0xFF30) 194 + * @fwlog: pointer to the fwlog structure 195 + * @entries: entries to configure 196 + * @num_entries: number of @entries 197 + * @options: options from libie_fwlog_cfg->options structure 198 + * @log_resolution: logging resolution 199 + */ 200 + static int 201 + libie_aq_fwlog_set(struct libie_fwlog *fwlog, 202 + struct libie_fwlog_module_entry *entries, u16 num_entries, 203 + u16 options, u16 log_resolution) 204 + { 205 + struct libie_aqc_fw_log_cfg_resp *fw_modules; 206 + struct libie_aq_desc desc = {0}; 207 + struct libie_aqc_fw_log *cmd; 208 + int status; 209 + int i; 210 + 211 + fw_modules = kcalloc(num_entries, sizeof(*fw_modules), GFP_KERNEL); 212 + if (!fw_modules) 213 + return -ENOMEM; 214 + 215 + for (i = 0; i < num_entries; i++) { 216 + fw_modules[i].module_identifier = 217 + cpu_to_le16(entries[i].module_id); 218 + fw_modules[i].log_level = entries[i].log_level; 219 + } 220 + 221 + desc.opcode = cpu_to_le16(libie_aqc_opc_fw_logs_config); 222 + desc.flags = cpu_to_le16(LIBIE_AQ_FLAG_SI) | 223 + cpu_to_le16(LIBIE_AQ_FLAG_RD); 224 + 225 + cmd = libie_aq_raw(&desc); 226 + 227 + cmd->cmd_flags = LIBIE_AQC_FW_LOG_CONF_SET_VALID; 228 + cmd->ops.cfg.log_resolution = cpu_to_le16(log_resolution); 229 + cmd->ops.cfg.mdl_cnt = cpu_to_le16(num_entries); 230 + 231 + if (options & LIBIE_FWLOG_OPTION_ARQ_ENA) 232 + cmd->cmd_flags |= LIBIE_AQC_FW_LOG_CONF_AQ_EN; 233 + if (options & LIBIE_FWLOG_OPTION_UART_ENA) 234 + cmd->cmd_flags |= LIBIE_AQC_FW_LOG_CONF_UART_EN; 235 + 236 + status = fwlog->send_cmd(fwlog->priv, &desc, fw_modules, 237 + sizeof(*fw_modules) * num_entries); 238 + 239 + kfree(fw_modules); 240 + 241 + return status; 242 + } 243 + 244 + /** 245 + * libie_fwlog_set - Set the firmware logging settings 246 + * @fwlog: pointer to the fwlog structure 247 + * @cfg: config used to set firmware logging 248 + * 249 + * This function should be called whenever the driver needs to set the firmware 250 + * logging configuration. It can be called on initialization, reset, or during 251 + * runtime. 252 + * 253 + * If the PF wishes to receive FW logging then it must register via 254 + * libie_fwlog_register. Note, that libie_fwlog_register does not need to be called 255 + * for init. 256 + */ 257 + static int libie_fwlog_set(struct libie_fwlog *fwlog, 258 + struct libie_fwlog_cfg *cfg) 259 + { 260 + if (!libie_fwlog_supported(fwlog)) 261 + return -EOPNOTSUPP; 262 + 263 + return libie_aq_fwlog_set(fwlog, cfg->module_entries, 264 + LIBIE_AQC_FW_LOG_ID_MAX, cfg->options, 265 + cfg->log_resolution); 266 + } 267 + 268 + /** 269 + * libie_aq_fwlog_register - Register PF for firmware logging events (0xFF31) 270 + * @fwlog: pointer to the fwlog structure 271 + * @reg: true to register and false to unregister 272 + */ 273 + static int libie_aq_fwlog_register(struct libie_fwlog *fwlog, bool reg) 274 + { 275 + struct libie_aq_desc desc = {0}; 276 + struct libie_aqc_fw_log *cmd; 277 + 278 + desc.opcode = cpu_to_le16(libie_aqc_opc_fw_logs_register); 279 + desc.flags = cpu_to_le16(LIBIE_AQ_FLAG_SI); 280 + cmd = libie_aq_raw(&desc); 281 + 282 + if (reg) 283 + cmd->cmd_flags = LIBIE_AQC_FW_LOG_AQ_REGISTER; 284 + 285 + return fwlog->send_cmd(fwlog->priv, &desc, NULL, 0); 286 + } 287 + 288 + /** 289 + * libie_fwlog_register - Register the PF for firmware logging 290 + * @fwlog: pointer to the fwlog structure 291 + * 292 + * After this call the PF will start to receive firmware logging based on the 293 + * configuration set in libie_fwlog_set. 294 + */ 295 + static int libie_fwlog_register(struct libie_fwlog *fwlog) 296 + { 297 + int status; 298 + 299 + if (!libie_fwlog_supported(fwlog)) 300 + return -EOPNOTSUPP; 301 + 302 + status = libie_aq_fwlog_register(fwlog, true); 303 + if (status) 304 + dev_dbg(&fwlog->pdev->dev, "Failed to register for firmware logging events over ARQ\n"); 305 + else 306 + fwlog->cfg.options |= LIBIE_FWLOG_OPTION_IS_REGISTERED; 307 + 308 + return status; 309 + } 310 + 311 + /** 312 + * libie_fwlog_unregister - Unregister the PF from firmware logging 313 + * @fwlog: pointer to the fwlog structure 314 + */ 315 + static int libie_fwlog_unregister(struct libie_fwlog *fwlog) 316 + { 317 + int status; 318 + 319 + if (!libie_fwlog_supported(fwlog)) 320 + return -EOPNOTSUPP; 321 + 322 + status = libie_aq_fwlog_register(fwlog, false); 323 + if (status) 324 + dev_dbg(&fwlog->pdev->dev, "Failed to unregister from firmware logging events over ARQ\n"); 325 + else 326 + fwlog->cfg.options &= ~LIBIE_FWLOG_OPTION_IS_REGISTERED; 327 + 328 + return status; 329 + } 330 + 331 + /** 332 + * libie_fwlog_print_module_cfg - print current FW logging module configuration 333 + * @cfg: pointer to the fwlog cfg structure 334 + * @module: module to print 335 + * @s: the seq file to put data into 336 + */ 337 + static void 338 + libie_fwlog_print_module_cfg(struct libie_fwlog_cfg *cfg, int module, 339 + struct seq_file *s) 340 + { 341 + struct libie_fwlog_module_entry *entry; 342 + 343 + if (module != LIBIE_AQC_FW_LOG_ID_MAX) { 344 + entry = &cfg->module_entries[module]; 345 + 346 + seq_printf(s, "\tModule: %s, Log Level: %s\n", 347 + libie_fwlog_module_string[entry->module_id], 348 + libie_fwlog_level_string[entry->log_level]); 349 + } else { 350 + int i; 351 + 352 + for (i = 0; i < LIBIE_AQC_FW_LOG_ID_MAX; i++) { 353 + entry = &cfg->module_entries[i]; 354 + 355 + seq_printf(s, "\tModule: %s, Log Level: %s\n", 356 + libie_fwlog_module_string[entry->module_id], 357 + libie_fwlog_level_string[entry->log_level]); 358 + } 359 + } 360 + } 361 + 362 + static int libie_find_module_by_dentry(struct dentry **modules, struct dentry *d) 363 + { 364 + int i, module; 365 + 366 + module = -1; 367 + /* find the module based on the dentry */ 368 + for (i = 0; i < LIBIE_NR_FW_LOG_MODULES; i++) { 369 + if (d == modules[i]) { 370 + module = i; 371 + break; 372 + } 373 + } 374 + 375 + return module; 376 + } 377 + 378 + /** 379 + * libie_debugfs_module_show - read from 'module' file 380 + * @s: the opened file 381 + * @v: pointer to the offset 382 + */ 383 + static int libie_debugfs_module_show(struct seq_file *s, void *v) 384 + { 385 + struct libie_fwlog *fwlog = s->private; 386 + const struct file *filp = s->file; 387 + struct dentry *dentry; 388 + int module; 389 + 390 + dentry = file_dentry(filp); 391 + 392 + module = libie_find_module_by_dentry(fwlog->debugfs_modules, dentry); 393 + if (module < 0) { 394 + dev_info(&fwlog->pdev->dev, "unknown module\n"); 395 + return -EINVAL; 396 + } 397 + 398 + libie_fwlog_print_module_cfg(&fwlog->cfg, module, s); 399 + 400 + return 0; 401 + } 402 + 403 + static int libie_debugfs_module_open(struct inode *inode, struct file *filp) 404 + { 405 + return single_open(filp, libie_debugfs_module_show, inode->i_private); 406 + } 407 + 408 + /** 409 + * libie_debugfs_module_write - write into 'module' file 410 + * @filp: the opened file 411 + * @buf: where to find the user's data 412 + * @count: the length of the user's data 413 + * @ppos: file position offset 414 + */ 415 + static ssize_t 416 + libie_debugfs_module_write(struct file *filp, const char __user *buf, 417 + size_t count, loff_t *ppos) 418 + { 419 + struct libie_fwlog *fwlog = file_inode(filp)->i_private; 420 + struct dentry *dentry = file_dentry(filp); 421 + struct device *dev = &fwlog->pdev->dev; 422 + char user_val[16], *cmd_buf; 423 + int module, log_level, cnt; 424 + 425 + /* don't allow partial writes or invalid input */ 426 + if (*ppos != 0 || count > 8) 427 + return -EINVAL; 428 + 429 + cmd_buf = memdup_user_nul(buf, count); 430 + if (IS_ERR(cmd_buf)) 431 + return PTR_ERR(cmd_buf); 432 + 433 + module = libie_find_module_by_dentry(fwlog->debugfs_modules, dentry); 434 + if (module < 0) { 435 + dev_info(dev, "unknown module\n"); 436 + return -EINVAL; 437 + } 438 + 439 + cnt = sscanf(cmd_buf, "%s", user_val); 440 + if (cnt != 1) 441 + return -EINVAL; 442 + 443 + log_level = sysfs_match_string(libie_fwlog_level_string, user_val); 444 + if (log_level < 0) { 445 + dev_info(dev, "unknown log level '%s'\n", user_val); 446 + return -EINVAL; 447 + } 448 + 449 + if (module != LIBIE_AQC_FW_LOG_ID_MAX) { 450 + fwlog->cfg.module_entries[module].log_level = log_level; 451 + } else { 452 + /* the module 'all' is a shortcut so that we can set 453 + * all of the modules to the same level quickly 454 + */ 455 + int i; 456 + 457 + for (i = 0; i < LIBIE_AQC_FW_LOG_ID_MAX; i++) 458 + fwlog->cfg.module_entries[i].log_level = log_level; 459 + } 460 + 461 + return count; 462 + } 463 + 464 + static const struct file_operations libie_debugfs_module_fops = { 465 + .owner = THIS_MODULE, 466 + .open = libie_debugfs_module_open, 467 + .read = seq_read, 468 + .release = single_release, 469 + .write = libie_debugfs_module_write, 470 + }; 471 + 472 + /** 473 + * libie_debugfs_nr_messages_read - read from 'nr_messages' file 474 + * @filp: the opened file 475 + * @buffer: where to write the data for the user to read 476 + * @count: the size of the user's buffer 477 + * @ppos: file position offset 478 + */ 479 + static ssize_t libie_debugfs_nr_messages_read(struct file *filp, 480 + char __user *buffer, size_t count, 481 + loff_t *ppos) 482 + { 483 + struct libie_fwlog *fwlog = filp->private_data; 484 + char buff[32] = {}; 485 + 486 + snprintf(buff, sizeof(buff), "%d\n", 487 + fwlog->cfg.log_resolution); 488 + 489 + return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff)); 490 + } 491 + 492 + /** 493 + * libie_debugfs_nr_messages_write - write into 'nr_messages' file 494 + * @filp: the opened file 495 + * @buf: where to find the user's data 496 + * @count: the length of the user's data 497 + * @ppos: file position offset 498 + */ 499 + static ssize_t 500 + libie_debugfs_nr_messages_write(struct file *filp, const char __user *buf, 501 + size_t count, loff_t *ppos) 502 + { 503 + struct libie_fwlog *fwlog = filp->private_data; 504 + struct device *dev = &fwlog->pdev->dev; 505 + char user_val[8], *cmd_buf; 506 + s16 nr_messages; 507 + ssize_t ret; 508 + 509 + /* don't allow partial writes or invalid input */ 510 + if (*ppos != 0 || count > 4) 511 + return -EINVAL; 512 + 513 + cmd_buf = memdup_user_nul(buf, count); 514 + if (IS_ERR(cmd_buf)) 515 + return PTR_ERR(cmd_buf); 516 + 517 + ret = sscanf(cmd_buf, "%s", user_val); 518 + if (ret != 1) 519 + return -EINVAL; 520 + 521 + ret = kstrtos16(user_val, 0, &nr_messages); 522 + if (ret) 523 + return ret; 524 + 525 + if (nr_messages < LIBIE_AQC_FW_LOG_MIN_RESOLUTION || 526 + nr_messages > LIBIE_AQC_FW_LOG_MAX_RESOLUTION) { 527 + dev_err(dev, "Invalid FW log number of messages %d, value must be between %d - %d\n", 528 + nr_messages, LIBIE_AQC_FW_LOG_MIN_RESOLUTION, 529 + LIBIE_AQC_FW_LOG_MAX_RESOLUTION); 530 + return -EINVAL; 531 + } 532 + 533 + fwlog->cfg.log_resolution = nr_messages; 534 + 535 + return count; 536 + } 537 + 538 + static const struct file_operations libie_debugfs_nr_messages_fops = { 539 + .owner = THIS_MODULE, 540 + .open = simple_open, 541 + .read = libie_debugfs_nr_messages_read, 542 + .write = libie_debugfs_nr_messages_write, 543 + }; 544 + 545 + /** 546 + * libie_debugfs_enable_read - read from 'enable' file 547 + * @filp: the opened file 548 + * @buffer: where to write the data for the user to read 549 + * @count: the size of the user's buffer 550 + * @ppos: file position offset 551 + */ 552 + static ssize_t libie_debugfs_enable_read(struct file *filp, 553 + char __user *buffer, size_t count, 554 + loff_t *ppos) 555 + { 556 + struct libie_fwlog *fwlog = filp->private_data; 557 + char buff[32] = {}; 558 + 559 + snprintf(buff, sizeof(buff), "%u\n", 560 + (u16)(fwlog->cfg.options & 561 + LIBIE_FWLOG_OPTION_IS_REGISTERED) >> 3); 562 + 563 + return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff)); 564 + } 565 + 566 + /** 567 + * libie_debugfs_enable_write - write into 'enable' file 568 + * @filp: the opened file 569 + * @buf: where to find the user's data 570 + * @count: the length of the user's data 571 + * @ppos: file position offset 572 + */ 573 + static ssize_t 574 + libie_debugfs_enable_write(struct file *filp, const char __user *buf, 575 + size_t count, loff_t *ppos) 576 + { 577 + struct libie_fwlog *fwlog = filp->private_data; 578 + char user_val[8], *cmd_buf; 579 + bool enable; 580 + ssize_t ret; 581 + 582 + /* don't allow partial writes or invalid input */ 583 + if (*ppos != 0 || count > 2) 584 + return -EINVAL; 585 + 586 + cmd_buf = memdup_user_nul(buf, count); 587 + if (IS_ERR(cmd_buf)) 588 + return PTR_ERR(cmd_buf); 589 + 590 + ret = sscanf(cmd_buf, "%s", user_val); 591 + if (ret != 1) 592 + return -EINVAL; 593 + 594 + ret = kstrtobool(user_val, &enable); 595 + if (ret) 596 + goto enable_write_error; 597 + 598 + if (enable) 599 + fwlog->cfg.options |= LIBIE_FWLOG_OPTION_ARQ_ENA; 600 + else 601 + fwlog->cfg.options &= ~LIBIE_FWLOG_OPTION_ARQ_ENA; 602 + 603 + ret = libie_fwlog_set(fwlog, &fwlog->cfg); 604 + if (ret) 605 + goto enable_write_error; 606 + 607 + if (enable) 608 + ret = libie_fwlog_register(fwlog); 609 + else 610 + ret = libie_fwlog_unregister(fwlog); 611 + 612 + if (ret) 613 + goto enable_write_error; 614 + 615 + /* if we get here, nothing went wrong; return count since we didn't 616 + * really write anything 617 + */ 618 + ret = (ssize_t)count; 619 + 620 + enable_write_error: 621 + /* This function always consumes all of the written input, or produces 622 + * an error. Check and enforce this. Otherwise, the write operation 623 + * won't complete properly. 624 + */ 625 + if (WARN_ON(ret != (ssize_t)count && ret >= 0)) 626 + ret = -EIO; 627 + 628 + return ret; 629 + } 630 + 631 + static const struct file_operations libie_debugfs_enable_fops = { 632 + .owner = THIS_MODULE, 633 + .open = simple_open, 634 + .read = libie_debugfs_enable_read, 635 + .write = libie_debugfs_enable_write, 636 + }; 637 + 638 + /** 639 + * libie_debugfs_log_size_read - read from 'log_size' file 640 + * @filp: the opened file 641 + * @buffer: where to write the data for the user to read 642 + * @count: the size of the user's buffer 643 + * @ppos: file position offset 644 + */ 645 + static ssize_t libie_debugfs_log_size_read(struct file *filp, 646 + char __user *buffer, size_t count, 647 + loff_t *ppos) 648 + { 649 + struct libie_fwlog *fwlog = filp->private_data; 650 + char buff[32] = {}; 651 + int index; 652 + 653 + index = fwlog->ring.index; 654 + snprintf(buff, sizeof(buff), "%s\n", libie_fwlog_log_size[index]); 655 + 656 + return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff)); 657 + } 658 + 659 + /** 660 + * libie_debugfs_log_size_write - write into 'log_size' file 661 + * @filp: the opened file 662 + * @buf: where to find the user's data 663 + * @count: the length of the user's data 664 + * @ppos: file position offset 665 + */ 666 + static ssize_t 667 + libie_debugfs_log_size_write(struct file *filp, const char __user *buf, 668 + size_t count, loff_t *ppos) 669 + { 670 + struct libie_fwlog *fwlog = filp->private_data; 671 + struct device *dev = &fwlog->pdev->dev; 672 + char user_val[8], *cmd_buf; 673 + ssize_t ret; 674 + int index; 675 + 676 + /* don't allow partial writes or invalid input */ 677 + if (*ppos != 0 || count > 5) 678 + return -EINVAL; 679 + 680 + cmd_buf = memdup_user_nul(buf, count); 681 + if (IS_ERR(cmd_buf)) 682 + return PTR_ERR(cmd_buf); 683 + 684 + ret = sscanf(cmd_buf, "%s", user_val); 685 + if (ret != 1) 686 + return -EINVAL; 687 + 688 + index = sysfs_match_string(libie_fwlog_log_size, user_val); 689 + if (index < 0) { 690 + dev_info(dev, "Invalid log size '%s'. The value must be one of 128K, 256K, 512K, 1M, 2M\n", 691 + user_val); 692 + ret = -EINVAL; 693 + goto log_size_write_error; 694 + } else if (fwlog->cfg.options & LIBIE_FWLOG_OPTION_IS_REGISTERED) { 695 + dev_info(dev, "FW logging is currently running. Please disable FW logging to change log_size\n"); 696 + ret = -EINVAL; 697 + goto log_size_write_error; 698 + } 699 + 700 + /* free all the buffers and the tracking info and resize */ 701 + libie_fwlog_realloc_rings(fwlog, index); 702 + 703 + /* if we get here, nothing went wrong; return count since we didn't 704 + * really write anything 705 + */ 706 + ret = (ssize_t)count; 707 + 708 + log_size_write_error: 709 + /* This function always consumes all of the written input, or produces 710 + * an error. Check and enforce this. Otherwise, the write operation 711 + * won't complete properly. 712 + */ 713 + if (WARN_ON(ret != (ssize_t)count && ret >= 0)) 714 + ret = -EIO; 715 + 716 + return ret; 717 + } 718 + 719 + static const struct file_operations libie_debugfs_log_size_fops = { 720 + .owner = THIS_MODULE, 721 + .open = simple_open, 722 + .read = libie_debugfs_log_size_read, 723 + .write = libie_debugfs_log_size_write, 724 + }; 725 + 726 + /** 727 + * libie_debugfs_data_read - read from 'data' file 728 + * @filp: the opened file 729 + * @buffer: where to write the data for the user to read 730 + * @count: the size of the user's buffer 731 + * @ppos: file position offset 732 + */ 733 + static ssize_t libie_debugfs_data_read(struct file *filp, char __user *buffer, 734 + size_t count, loff_t *ppos) 735 + { 736 + struct libie_fwlog *fwlog = filp->private_data; 737 + int data_copied = 0; 738 + bool done = false; 739 + 740 + if (libie_fwlog_ring_empty(&fwlog->ring)) 741 + return 0; 742 + 743 + while (!libie_fwlog_ring_empty(&fwlog->ring) && !done) { 744 + struct libie_fwlog_data *log; 745 + u16 cur_buf_len; 746 + 747 + log = &fwlog->ring.rings[fwlog->ring.head]; 748 + cur_buf_len = log->data_size; 749 + if (cur_buf_len >= count) { 750 + done = true; 751 + continue; 752 + } 753 + 754 + if (copy_to_user(buffer, log->data, cur_buf_len)) { 755 + /* if there is an error then bail and return whatever 756 + * the driver has copied so far 757 + */ 758 + done = true; 759 + continue; 760 + } 761 + 762 + data_copied += cur_buf_len; 763 + buffer += cur_buf_len; 764 + count -= cur_buf_len; 765 + *ppos += cur_buf_len; 766 + libie_fwlog_ring_increment(&fwlog->ring.head, fwlog->ring.size); 767 + } 768 + 769 + return data_copied; 770 + } 771 + 772 + /** 773 + * libie_debugfs_data_write - write into 'data' file 774 + * @filp: the opened file 775 + * @buf: where to find the user's data 776 + * @count: the length of the user's data 777 + * @ppos: file position offset 778 + */ 779 + static ssize_t 780 + libie_debugfs_data_write(struct file *filp, const char __user *buf, size_t count, 781 + loff_t *ppos) 782 + { 783 + struct libie_fwlog *fwlog = filp->private_data; 784 + struct device *dev = &fwlog->pdev->dev; 785 + ssize_t ret; 786 + 787 + /* don't allow partial writes */ 788 + if (*ppos != 0) 789 + return 0; 790 + 791 + /* any value is allowed to clear the buffer so no need to even look at 792 + * what the value is 793 + */ 794 + if (!(fwlog->cfg.options & LIBIE_FWLOG_OPTION_IS_REGISTERED)) { 795 + fwlog->ring.head = 0; 796 + fwlog->ring.tail = 0; 797 + } else { 798 + dev_info(dev, "Can't clear FW log data while FW log running\n"); 799 + ret = -EINVAL; 800 + goto nr_buffs_write_error; 801 + } 802 + 803 + /* if we get here, nothing went wrong; return count since we didn't 804 + * really write anything 805 + */ 806 + ret = (ssize_t)count; 807 + 808 + nr_buffs_write_error: 809 + /* This function always consumes all of the written input, or produces 810 + * an error. Check and enforce this. Otherwise, the write operation 811 + * won't complete properly. 812 + */ 813 + if (WARN_ON(ret != (ssize_t)count && ret >= 0)) 814 + ret = -EIO; 815 + 816 + return ret; 817 + } 818 + 819 + static const struct file_operations libie_debugfs_data_fops = { 820 + .owner = THIS_MODULE, 821 + .open = simple_open, 822 + .read = libie_debugfs_data_read, 823 + .write = libie_debugfs_data_write, 824 + }; 825 + 826 + /** 827 + * libie_debugfs_fwlog_init - setup the debugfs directory 828 + * @fwlog: pointer to the fwlog structure 829 + * @root: debugfs root entry on which fwlog director will be registered 830 + */ 831 + static void libie_debugfs_fwlog_init(struct libie_fwlog *fwlog, 832 + struct dentry *root) 833 + { 834 + struct dentry *fw_modules_dir; 835 + struct dentry **fw_modules; 836 + int i; 837 + 838 + /* allocate space for this first because if it fails then we don't 839 + * need to unwind 840 + */ 841 + fw_modules = kcalloc(LIBIE_NR_FW_LOG_MODULES, sizeof(*fw_modules), 842 + GFP_KERNEL); 843 + if (!fw_modules) 844 + return; 845 + 846 + fwlog->debugfs = debugfs_create_dir("fwlog", root); 847 + if (IS_ERR(fwlog->debugfs)) 848 + goto err_create_module_files; 849 + 850 + fw_modules_dir = debugfs_create_dir("modules", fwlog->debugfs); 851 + if (IS_ERR(fw_modules_dir)) 852 + goto err_create_module_files; 853 + 854 + for (i = 0; i < LIBIE_NR_FW_LOG_MODULES; i++) { 855 + fw_modules[i] = debugfs_create_file(libie_fwlog_module_string[i], 856 + 0600, fw_modules_dir, fwlog, 857 + &libie_debugfs_module_fops); 858 + if (IS_ERR(fw_modules[i])) 859 + goto err_create_module_files; 860 + } 861 + 862 + debugfs_create_file("nr_messages", 0600, fwlog->debugfs, fwlog, 863 + &libie_debugfs_nr_messages_fops); 864 + 865 + fwlog->debugfs_modules = fw_modules; 866 + 867 + debugfs_create_file("enable", 0600, fwlog->debugfs, fwlog, 868 + &libie_debugfs_enable_fops); 869 + 870 + debugfs_create_file("log_size", 0600, fwlog->debugfs, fwlog, 871 + &libie_debugfs_log_size_fops); 872 + 873 + debugfs_create_file("data", 0600, fwlog->debugfs, fwlog, 874 + &libie_debugfs_data_fops); 875 + 876 + return; 877 + 878 + err_create_module_files: 879 + debugfs_remove_recursive(fwlog->debugfs); 880 + kfree(fw_modules); 881 + } 882 + 883 + static bool libie_fwlog_ring_full(struct libie_fwlog_ring *rings) 884 + { 885 + u16 head, tail; 886 + 887 + head = rings->head; 888 + tail = rings->tail; 889 + 890 + if (head < tail && (tail - head == (rings->size - 1))) 891 + return true; 892 + else if (head > tail && (tail == (head - 1))) 893 + return true; 894 + 895 + return false; 896 + } 897 + 898 + /** 899 + * libie_aq_fwlog_get - Get the current firmware logging configuration (0xFF32) 900 + * @fwlog: pointer to the fwlog structure 901 + * @cfg: firmware logging configuration to populate 902 + */ 903 + static int libie_aq_fwlog_get(struct libie_fwlog *fwlog, 904 + struct libie_fwlog_cfg *cfg) 905 + { 906 + struct libie_aqc_fw_log_cfg_resp *fw_modules; 907 + struct libie_aq_desc desc = {0}; 908 + struct libie_aqc_fw_log *cmd; 909 + u16 module_id_cnt; 910 + int status; 911 + void *buf; 912 + int i; 913 + 914 + memset(cfg, 0, sizeof(*cfg)); 915 + 916 + buf = kzalloc(LIBIE_AQ_MAX_BUF_LEN, GFP_KERNEL); 917 + if (!buf) 918 + return -ENOMEM; 919 + 920 + desc.opcode = cpu_to_le16(libie_aqc_opc_fw_logs_query); 921 + desc.flags = cpu_to_le16(LIBIE_AQ_FLAG_SI); 922 + cmd = libie_aq_raw(&desc); 923 + 924 + cmd->cmd_flags = LIBIE_AQC_FW_LOG_AQ_QUERY; 925 + 926 + status = fwlog->send_cmd(fwlog->priv, &desc, buf, LIBIE_AQ_MAX_BUF_LEN); 927 + if (status) { 928 + dev_dbg(&fwlog->pdev->dev, "Failed to get FW log configuration\n"); 929 + goto status_out; 930 + } 931 + 932 + module_id_cnt = le16_to_cpu(cmd->ops.cfg.mdl_cnt); 933 + if (module_id_cnt < LIBIE_AQC_FW_LOG_ID_MAX) { 934 + dev_dbg(&fwlog->pdev->dev, "FW returned less than the expected number of FW log module IDs\n"); 935 + } else if (module_id_cnt > LIBIE_AQC_FW_LOG_ID_MAX) { 936 + dev_dbg(&fwlog->pdev->dev, "FW returned more than expected number of FW log module IDs, setting module_id_cnt to software expected max %u\n", 937 + LIBIE_AQC_FW_LOG_ID_MAX); 938 + module_id_cnt = LIBIE_AQC_FW_LOG_ID_MAX; 939 + } 940 + 941 + cfg->log_resolution = le16_to_cpu(cmd->ops.cfg.log_resolution); 942 + if (cmd->cmd_flags & LIBIE_AQC_FW_LOG_CONF_AQ_EN) 943 + cfg->options |= LIBIE_FWLOG_OPTION_ARQ_ENA; 944 + if (cmd->cmd_flags & LIBIE_AQC_FW_LOG_CONF_UART_EN) 945 + cfg->options |= LIBIE_FWLOG_OPTION_UART_ENA; 946 + if (cmd->cmd_flags & LIBIE_AQC_FW_LOG_QUERY_REGISTERED) 947 + cfg->options |= LIBIE_FWLOG_OPTION_IS_REGISTERED; 948 + 949 + fw_modules = (struct libie_aqc_fw_log_cfg_resp *)buf; 950 + 951 + for (i = 0; i < module_id_cnt; i++) { 952 + struct libie_aqc_fw_log_cfg_resp *fw_module = &fw_modules[i]; 953 + 954 + cfg->module_entries[i].module_id = 955 + le16_to_cpu(fw_module->module_identifier); 956 + cfg->module_entries[i].log_level = fw_module->log_level; 957 + } 958 + 959 + status_out: 960 + kfree(buf); 961 + return status; 962 + } 963 + 964 + /** 965 + * libie_fwlog_set_supported - Set if FW logging is supported by FW 966 + * @fwlog: pointer to the fwlog structure 967 + * 968 + * If FW returns success to the libie_aq_fwlog_get call then it supports FW 969 + * logging, else it doesn't. Set the fwlog_supported flag accordingly. 970 + * 971 + * This function is only meant to be called during driver init to determine if 972 + * the FW support FW logging. 973 + */ 974 + static void libie_fwlog_set_supported(struct libie_fwlog *fwlog) 975 + { 976 + struct libie_fwlog_cfg *cfg; 977 + int status; 978 + 979 + fwlog->supported = false; 980 + 981 + cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); 982 + if (!cfg) 983 + return; 984 + 985 + status = libie_aq_fwlog_get(fwlog, cfg); 986 + if (status) 987 + dev_dbg(&fwlog->pdev->dev, "libie_aq_fwlog_get failed, FW logging is not supported on this version of FW, status %d\n", 988 + status); 989 + else 990 + fwlog->supported = true; 991 + 992 + kfree(cfg); 993 + } 994 + 995 + /** 996 + * libie_fwlog_init - Initialize FW logging configuration 997 + * @fwlog: pointer to the fwlog structure 998 + * @api: api structure to init fwlog 999 + * 1000 + * This function should be called on driver initialization during 1001 + * libie_init_hw(). 1002 + */ 1003 + int libie_fwlog_init(struct libie_fwlog *fwlog, struct libie_fwlog_api *api) 1004 + { 1005 + fwlog->api = *api; 1006 + libie_fwlog_set_supported(fwlog); 1007 + 1008 + if (libie_fwlog_supported(fwlog)) { 1009 + int status; 1010 + 1011 + /* read the current config from the FW and store it */ 1012 + status = libie_aq_fwlog_get(fwlog, &fwlog->cfg); 1013 + if (status) 1014 + return status; 1015 + 1016 + fwlog->ring.rings = kcalloc(LIBIE_FWLOG_RING_SIZE_DFLT, 1017 + sizeof(*fwlog->ring.rings), 1018 + GFP_KERNEL); 1019 + if (!fwlog->ring.rings) { 1020 + dev_warn(&fwlog->pdev->dev, "Unable to allocate memory for FW log rings\n"); 1021 + return -ENOMEM; 1022 + } 1023 + 1024 + fwlog->ring.size = LIBIE_FWLOG_RING_SIZE_DFLT; 1025 + fwlog->ring.index = LIBIE_FWLOG_RING_SIZE_INDEX_DFLT; 1026 + 1027 + status = libie_fwlog_alloc_ring_buffs(&fwlog->ring); 1028 + if (status) { 1029 + dev_warn(&fwlog->pdev->dev, "Unable to allocate memory for FW log ring data buffers\n"); 1030 + libie_fwlog_free_ring_buffs(&fwlog->ring); 1031 + kfree(fwlog->ring.rings); 1032 + return status; 1033 + } 1034 + 1035 + libie_debugfs_fwlog_init(fwlog, api->debugfs_root); 1036 + } else { 1037 + dev_warn(&fwlog->pdev->dev, "FW logging is not supported in this NVM image. Please update the NVM to get FW log support\n"); 1038 + } 1039 + 1040 + return 0; 1041 + } 1042 + EXPORT_SYMBOL_GPL(libie_fwlog_init); 1043 + 1044 + /** 1045 + * libie_fwlog_deinit - unroll FW logging configuration 1046 + * @fwlog: pointer to the fwlog structure 1047 + * 1048 + * This function should be called in libie_deinit_hw(). 1049 + */ 1050 + void libie_fwlog_deinit(struct libie_fwlog *fwlog) 1051 + { 1052 + int status; 1053 + 1054 + /* make sure FW logging is disabled to not put the FW in a weird state 1055 + * for the next driver load 1056 + */ 1057 + fwlog->cfg.options &= ~LIBIE_FWLOG_OPTION_ARQ_ENA; 1058 + status = libie_fwlog_set(fwlog, &fwlog->cfg); 1059 + if (status) 1060 + dev_warn(&fwlog->pdev->dev, "Unable to turn off FW logging, status: %d\n", 1061 + status); 1062 + 1063 + kfree(fwlog->debugfs_modules); 1064 + 1065 + fwlog->debugfs_modules = NULL; 1066 + 1067 + status = libie_fwlog_unregister(fwlog); 1068 + if (status) 1069 + dev_warn(&fwlog->pdev->dev, "Unable to unregister FW logging, status: %d\n", 1070 + status); 1071 + 1072 + if (fwlog->ring.rings) { 1073 + libie_fwlog_free_ring_buffs(&fwlog->ring); 1074 + kfree(fwlog->ring.rings); 1075 + } 1076 + } 1077 + EXPORT_SYMBOL_GPL(libie_fwlog_deinit); 1078 + 1079 + /** 1080 + * libie_get_fwlog_data - copy the FW log data from ARQ event 1081 + * @fwlog: fwlog that the FW log event is associated with 1082 + * @buf: event buffer pointer 1083 + * @len: len of event descriptor 1084 + */ 1085 + void libie_get_fwlog_data(struct libie_fwlog *fwlog, u8 *buf, u16 len) 1086 + { 1087 + struct libie_fwlog_data *log; 1088 + 1089 + log = &fwlog->ring.rings[fwlog->ring.tail]; 1090 + 1091 + memset(log->data, 0, PAGE_SIZE); 1092 + log->data_size = len; 1093 + 1094 + memcpy(log->data, buf, log->data_size); 1095 + libie_fwlog_ring_increment(&fwlog->ring.tail, fwlog->ring.size); 1096 + 1097 + if (libie_fwlog_ring_full(&fwlog->ring)) { 1098 + /* the rings are full so bump the head to create room */ 1099 + libie_fwlog_ring_increment(&fwlog->ring.head, fwlog->ring.size); 1100 + } 1101 + } 1102 + EXPORT_SYMBOL_GPL(libie_get_fwlog_data); 1103 + 1104 + void libie_fwlog_reregister(struct libie_fwlog *fwlog) 1105 + { 1106 + if (!(fwlog->cfg.options & LIBIE_FWLOG_OPTION_IS_REGISTERED)) 1107 + return; 1108 + 1109 + if (libie_fwlog_register(fwlog)) 1110 + fwlog->cfg.options &= ~LIBIE_FWLOG_OPTION_IS_REGISTERED; 1111 + } 1112 + EXPORT_SYMBOL_GPL(libie_fwlog_reregister); 1113 + 1114 + MODULE_DESCRIPTION("Intel(R) Ethernet common library"); 1115 + MODULE_LICENSE("GPL");
+90
include/linux/net/intel/libie/adminq.h
··· 9 9 10 10 #define LIBIE_CHECK_STRUCT_LEN(n, X) \ 11 11 static_assert((n) == sizeof(struct X)) 12 + #define LIBIE_AQ_MAX_BUF_LEN 4096 12 13 13 14 /** 14 15 * struct libie_aqc_generic - Generic structure used in adminq communication ··· 223 222 }; 224 223 LIBIE_CHECK_STRUCT_LEN(32, libie_aqc_list_caps_elem); 225 224 225 + /* Admin Queue command opcodes */ 226 + enum libie_adminq_opc { 227 + /* FW Logging Commands */ 228 + libie_aqc_opc_fw_logs_config = 0xFF30, 229 + libie_aqc_opc_fw_logs_register = 0xFF31, 230 + libie_aqc_opc_fw_logs_query = 0xFF32, 231 + libie_aqc_opc_fw_logs_event = 0xFF33, 232 + }; 233 + 234 + enum libie_aqc_fw_logging_mod { 235 + LIBIE_AQC_FW_LOG_ID_GENERAL = 0, 236 + LIBIE_AQC_FW_LOG_ID_CTRL, 237 + LIBIE_AQC_FW_LOG_ID_LINK, 238 + LIBIE_AQC_FW_LOG_ID_LINK_TOPO, 239 + LIBIE_AQC_FW_LOG_ID_DNL, 240 + LIBIE_AQC_FW_LOG_ID_I2C, 241 + LIBIE_AQC_FW_LOG_ID_SDP, 242 + LIBIE_AQC_FW_LOG_ID_MDIO, 243 + LIBIE_AQC_FW_LOG_ID_ADMINQ, 244 + LIBIE_AQC_FW_LOG_ID_HDMA, 245 + LIBIE_AQC_FW_LOG_ID_LLDP, 246 + LIBIE_AQC_FW_LOG_ID_DCBX, 247 + LIBIE_AQC_FW_LOG_ID_DCB, 248 + LIBIE_AQC_FW_LOG_ID_XLR, 249 + LIBIE_AQC_FW_LOG_ID_NVM, 250 + LIBIE_AQC_FW_LOG_ID_AUTH, 251 + LIBIE_AQC_FW_LOG_ID_VPD, 252 + LIBIE_AQC_FW_LOG_ID_IOSF, 253 + LIBIE_AQC_FW_LOG_ID_PARSER, 254 + LIBIE_AQC_FW_LOG_ID_SW, 255 + LIBIE_AQC_FW_LOG_ID_SCHEDULER, 256 + LIBIE_AQC_FW_LOG_ID_TXQ, 257 + LIBIE_AQC_FW_LOG_ID_RSVD, 258 + LIBIE_AQC_FW_LOG_ID_POST, 259 + LIBIE_AQC_FW_LOG_ID_WATCHDOG, 260 + LIBIE_AQC_FW_LOG_ID_TASK_DISPATCH, 261 + LIBIE_AQC_FW_LOG_ID_MNG, 262 + LIBIE_AQC_FW_LOG_ID_SYNCE, 263 + LIBIE_AQC_FW_LOG_ID_HEALTH, 264 + LIBIE_AQC_FW_LOG_ID_TSDRV, 265 + LIBIE_AQC_FW_LOG_ID_PFREG, 266 + LIBIE_AQC_FW_LOG_ID_MDLVER, 267 + LIBIE_AQC_FW_LOG_ID_MAX 268 + }; 269 + 270 + /* Set FW Logging configuration (indirect 0xFF30) 271 + * Register for FW Logging (indirect 0xFF31) 272 + * Query FW Logging (indirect 0xFF32) 273 + * FW Log Event (indirect 0xFF33) 274 + */ 275 + #define LIBIE_AQC_FW_LOG_CONF_UART_EN BIT(0) 276 + #define LIBIE_AQC_FW_LOG_CONF_AQ_EN BIT(1) 277 + #define LIBIE_AQC_FW_LOG_QUERY_REGISTERED BIT(2) 278 + #define LIBIE_AQC_FW_LOG_CONF_SET_VALID BIT(3) 279 + #define LIBIE_AQC_FW_LOG_AQ_REGISTER BIT(0) 280 + #define LIBIE_AQC_FW_LOG_AQ_QUERY BIT(2) 281 + 282 + #define LIBIE_AQC_FW_LOG_MIN_RESOLUTION 1 283 + #define LIBIE_AQC_FW_LOG_MAX_RESOLUTION 128 284 + 285 + struct libie_aqc_fw_log { 286 + u8 cmd_flags; 287 + 288 + u8 rsp_flag; 289 + __le16 fw_rt_msb; 290 + union { 291 + struct { 292 + __le32 fw_rt_lsb; 293 + } sync; 294 + struct { 295 + __le16 log_resolution; 296 + __le16 mdl_cnt; 297 + } cfg; 298 + } ops; 299 + __le32 addr_high; 300 + __le32 addr_low; 301 + }; 302 + 303 + /* Response Buffer for: 304 + * Set Firmware Logging Configuration (0xFF30) 305 + * Query FW Logging (0xFF32) 306 + */ 307 + struct libie_aqc_fw_log_cfg_resp { 308 + __le16 module_identifier; 309 + u8 log_level; 310 + u8 rsvd0; 311 + }; 312 + 226 313 /** 227 314 * struct libie_aq_desc - Admin Queue (AQ) descriptor 228 315 * @flags: LIBIE_AQ_FLAG_* flags ··· 342 253 struct libie_aqc_driver_ver driver_ver; 343 254 struct libie_aqc_req_res res_owner; 344 255 struct libie_aqc_list_caps get_cap; 256 + struct libie_aqc_fw_log fw_log; 345 257 } params; 346 258 }; 347 259 LIBIE_CHECK_STRUCT_LEN(32, libie_aq_desc);
+85
include/linux/net/intel/libie/fwlog.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (C) 2022, Intel Corporation. */ 3 + 4 + #ifndef _LIBIE_FWLOG_H_ 5 + #define _LIBIE_FWLOG_H_ 6 + 7 + #include <linux/net/intel/libie/adminq.h> 8 + 9 + /* Only a single log level should be set and all log levels under the set value 10 + * are enabled, e.g. if log level is set to LIBIE_FW_LOG_LEVEL_VERBOSE, then all 11 + * other log levels are included (except LIBIE_FW_LOG_LEVEL_NONE) 12 + */ 13 + enum libie_fwlog_level { 14 + LIBIE_FWLOG_LEVEL_NONE = 0, 15 + LIBIE_FWLOG_LEVEL_ERROR = 1, 16 + LIBIE_FWLOG_LEVEL_WARNING = 2, 17 + LIBIE_FWLOG_LEVEL_NORMAL = 3, 18 + LIBIE_FWLOG_LEVEL_VERBOSE = 4, 19 + LIBIE_FWLOG_LEVEL_INVALID, /* all values >= this entry are invalid */ 20 + }; 21 + 22 + struct libie_fwlog_module_entry { 23 + /* module ID for the corresponding firmware logging event */ 24 + u16 module_id; 25 + /* verbosity level for the module_id */ 26 + u8 log_level; 27 + }; 28 + 29 + struct libie_fwlog_cfg { 30 + /* list of modules for configuring log level */ 31 + struct libie_fwlog_module_entry module_entries[LIBIE_AQC_FW_LOG_ID_MAX]; 32 + /* options used to configure firmware logging */ 33 + u16 options; 34 + #define LIBIE_FWLOG_OPTION_ARQ_ENA BIT(0) 35 + #define LIBIE_FWLOG_OPTION_UART_ENA BIT(1) 36 + /* set before calling libie_fwlog_init() so the PF registers for 37 + * firmware logging on initialization 38 + */ 39 + #define LIBIE_FWLOG_OPTION_REGISTER_ON_INIT BIT(2) 40 + /* set in the libie_aq_fwlog_get() response if the PF is registered for 41 + * FW logging events over ARQ 42 + */ 43 + #define LIBIE_FWLOG_OPTION_IS_REGISTERED BIT(3) 44 + 45 + /* minimum number of log events sent per Admin Receive Queue event */ 46 + u16 log_resolution; 47 + }; 48 + 49 + struct libie_fwlog_data { 50 + u16 data_size; 51 + u8 *data; 52 + }; 53 + 54 + struct libie_fwlog_ring { 55 + struct libie_fwlog_data *rings; 56 + u16 index; 57 + u16 size; 58 + u16 head; 59 + u16 tail; 60 + }; 61 + 62 + #define LIBIE_FWLOG_RING_SIZE_INDEX_DFLT 3 63 + #define LIBIE_FWLOG_RING_SIZE_DFLT 256 64 + #define LIBIE_FWLOG_RING_SIZE_MAX 512 65 + 66 + struct libie_fwlog { 67 + struct libie_fwlog_cfg cfg; 68 + bool supported; /* does hardware support FW logging? */ 69 + struct libie_fwlog_ring ring; 70 + struct dentry *debugfs; 71 + /* keep track of all the dentrys for FW log modules */ 72 + struct dentry **debugfs_modules; 73 + struct_group_tagged(libie_fwlog_api, api, 74 + struct pci_dev *pdev; 75 + int (*send_cmd)(void *, struct libie_aq_desc *, void *, u16); 76 + void *priv; 77 + struct dentry *debugfs_root; 78 + ); 79 + }; 80 + 81 + int libie_fwlog_init(struct libie_fwlog *fwlog, struct libie_fwlog_api *api); 82 + void libie_fwlog_deinit(struct libie_fwlog *fwlog); 83 + void libie_fwlog_reregister(struct libie_fwlog *fwlog); 84 + void libie_get_fwlog_data(struct libie_fwlog *fwlog, u8 *buf, u16 len); 85 + #endif /* _LIBIE_FWLOG_H_ */