1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2022, Intel Corporation. */ 3 4 #include <linux/fs.h> 5 #include <linux/debugfs.h> 6 #include <linux/random.h> 7 #include <linux/vmalloc.h> 8 #include "ice.h" 9 10 static struct dentry *ice_debugfs_root; 11 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 /* the order in this array is important. it matches the ordering of the 68 * values in the FW so the index is the same value as in ice_fwlog_level 69 */ 70 static const char * const ice_fwlog_log_size[] = { 71 "128K", 72 "256K", 73 "512K", 74 "1M", 75 "2M", 76 }; 77 78 /** 79 * ice_fwlog_print_module_cfg - print current FW logging module configuration 80 * @hw: pointer to the HW structure 81 * @module: module to print 82 * @s: the seq file to put data into 83 */ 84 static void 85 ice_fwlog_print_module_cfg(struct ice_hw *hw, int module, struct seq_file *s) 86 { 87 struct ice_fwlog_cfg *cfg = &hw->fwlog_cfg; 88 struct ice_fwlog_module_entry *entry; 89 90 if (module != ICE_AQC_FW_LOG_ID_MAX) { 91 entry = &cfg->module_entries[module]; 92 93 seq_printf(s, "\tModule: %s, Log Level: %s\n", 94 ice_fwlog_module_string[entry->module_id], 95 ice_fwlog_level_string[entry->log_level]); 96 } else { 97 int i; 98 99 for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) { 100 entry = &cfg->module_entries[i]; 101 102 seq_printf(s, "\tModule: %s, Log Level: %s\n", 103 ice_fwlog_module_string[entry->module_id], 104 ice_fwlog_level_string[entry->log_level]); 105 } 106 } 107 } 108 109 static int ice_find_module_by_dentry(struct ice_pf *pf, struct dentry *d) 110 { 111 int i, module; 112 113 module = -1; 114 /* find the module based on the dentry */ 115 for (i = 0; i < ICE_NR_FW_LOG_MODULES; i++) { 116 if (d == pf->ice_debugfs_pf_fwlog_modules[i]) { 117 module = i; 118 break; 119 } 120 } 121 122 return module; 123 } 124 125 /** 126 * ice_debugfs_module_show - read from 'module' file 127 * @s: the opened file 128 * @v: pointer to the offset 129 */ 130 static int ice_debugfs_module_show(struct seq_file *s, void *v) 131 { 132 const struct file *filp = s->file; 133 struct dentry *dentry; 134 struct ice_pf *pf; 135 int module; 136 137 dentry = file_dentry(filp); 138 pf = s->private; 139 140 module = ice_find_module_by_dentry(pf, dentry); 141 if (module < 0) { 142 dev_info(ice_pf_to_dev(pf), "unknown module\n"); 143 return -EINVAL; 144 } 145 146 ice_fwlog_print_module_cfg(&pf->hw, module, s); 147 148 return 0; 149 } 150 151 static int ice_debugfs_module_open(struct inode *inode, struct file *filp) 152 { 153 return single_open(filp, ice_debugfs_module_show, inode->i_private); 154 } 155 156 /** 157 * ice_debugfs_module_write - write into 'module' file 158 * @filp: the opened file 159 * @buf: where to find the user's data 160 * @count: the length of the user's data 161 * @ppos: file position offset 162 */ 163 static ssize_t 164 ice_debugfs_module_write(struct file *filp, const char __user *buf, 165 size_t count, loff_t *ppos) 166 { 167 struct ice_pf *pf = file_inode(filp)->i_private; 168 struct dentry *dentry = file_dentry(filp); 169 struct device *dev = ice_pf_to_dev(pf); 170 char user_val[16], *cmd_buf; 171 int module, log_level, cnt; 172 173 /* don't allow partial writes or invalid input */ 174 if (*ppos != 0 || count > 8) 175 return -EINVAL; 176 177 cmd_buf = memdup_user(buf, count); 178 if (IS_ERR(cmd_buf)) 179 return PTR_ERR(cmd_buf); 180 181 module = ice_find_module_by_dentry(pf, dentry); 182 if (module < 0) { 183 dev_info(dev, "unknown module\n"); 184 return -EINVAL; 185 } 186 187 cnt = sscanf(cmd_buf, "%s", user_val); 188 if (cnt != 1) 189 return -EINVAL; 190 191 log_level = sysfs_match_string(ice_fwlog_level_string, user_val); 192 if (log_level < 0) { 193 dev_info(dev, "unknown log level '%s'\n", user_val); 194 return -EINVAL; 195 } 196 197 if (module != ICE_AQC_FW_LOG_ID_MAX) { 198 ice_pf_fwlog_update_module(pf, log_level, module); 199 } else { 200 /* the module 'all' is a shortcut so that we can set 201 * all of the modules to the same level quickly 202 */ 203 int i; 204 205 for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) 206 ice_pf_fwlog_update_module(pf, log_level, i); 207 } 208 209 return count; 210 } 211 212 static const struct file_operations ice_debugfs_module_fops = { 213 .owner = THIS_MODULE, 214 .open = ice_debugfs_module_open, 215 .read = seq_read, 216 .release = single_release, 217 .write = ice_debugfs_module_write, 218 }; 219 220 /** 221 * ice_debugfs_nr_messages_read - read from 'nr_messages' file 222 * @filp: the opened file 223 * @buffer: where to write the data for the user to read 224 * @count: the size of the user's buffer 225 * @ppos: file position offset 226 */ 227 static ssize_t ice_debugfs_nr_messages_read(struct file *filp, 228 char __user *buffer, size_t count, 229 loff_t *ppos) 230 { 231 struct ice_pf *pf = filp->private_data; 232 struct ice_hw *hw = &pf->hw; 233 char buff[32] = {}; 234 235 snprintf(buff, sizeof(buff), "%d\n", 236 hw->fwlog_cfg.log_resolution); 237 238 return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff)); 239 } 240 241 /** 242 * ice_debugfs_nr_messages_write - write into 'nr_messages' file 243 * @filp: the opened file 244 * @buf: where to find the user's data 245 * @count: the length of the user's data 246 * @ppos: file position offset 247 */ 248 static ssize_t 249 ice_debugfs_nr_messages_write(struct file *filp, const char __user *buf, 250 size_t count, loff_t *ppos) 251 { 252 struct ice_pf *pf = filp->private_data; 253 struct device *dev = ice_pf_to_dev(pf); 254 struct ice_hw *hw = &pf->hw; 255 char user_val[8], *cmd_buf; 256 s16 nr_messages; 257 ssize_t ret; 258 259 /* don't allow partial writes or invalid input */ 260 if (*ppos != 0 || count > 4) 261 return -EINVAL; 262 263 cmd_buf = memdup_user(buf, count); 264 if (IS_ERR(cmd_buf)) 265 return PTR_ERR(cmd_buf); 266 267 ret = sscanf(cmd_buf, "%s", user_val); 268 if (ret != 1) 269 return -EINVAL; 270 271 ret = kstrtos16(user_val, 0, &nr_messages); 272 if (ret) 273 return ret; 274 275 if (nr_messages < ICE_AQC_FW_LOG_MIN_RESOLUTION || 276 nr_messages > ICE_AQC_FW_LOG_MAX_RESOLUTION) { 277 dev_err(dev, "Invalid FW log number of messages %d, value must be between %d - %d\n", 278 nr_messages, ICE_AQC_FW_LOG_MIN_RESOLUTION, 279 ICE_AQC_FW_LOG_MAX_RESOLUTION); 280 return -EINVAL; 281 } 282 283 hw->fwlog_cfg.log_resolution = nr_messages; 284 285 return count; 286 } 287 288 static const struct file_operations ice_debugfs_nr_messages_fops = { 289 .owner = THIS_MODULE, 290 .open = simple_open, 291 .read = ice_debugfs_nr_messages_read, 292 .write = ice_debugfs_nr_messages_write, 293 }; 294 295 /** 296 * ice_debugfs_enable_read - read from 'enable' file 297 * @filp: the opened file 298 * @buffer: where to write the data for the user to read 299 * @count: the size of the user's buffer 300 * @ppos: file position offset 301 */ 302 static ssize_t ice_debugfs_enable_read(struct file *filp, 303 char __user *buffer, size_t count, 304 loff_t *ppos) 305 { 306 struct ice_pf *pf = filp->private_data; 307 struct ice_hw *hw = &pf->hw; 308 char buff[32] = {}; 309 310 snprintf(buff, sizeof(buff), "%u\n", 311 (u16)(hw->fwlog_cfg.options & 312 ICE_FWLOG_OPTION_IS_REGISTERED) >> 3); 313 314 return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff)); 315 } 316 317 /** 318 * ice_debugfs_enable_write - write into 'enable' file 319 * @filp: the opened file 320 * @buf: where to find the user's data 321 * @count: the length of the user's data 322 * @ppos: file position offset 323 */ 324 static ssize_t 325 ice_debugfs_enable_write(struct file *filp, const char __user *buf, 326 size_t count, loff_t *ppos) 327 { 328 struct ice_pf *pf = filp->private_data; 329 struct ice_hw *hw = &pf->hw; 330 char user_val[8], *cmd_buf; 331 bool enable; 332 ssize_t ret; 333 334 /* don't allow partial writes or invalid input */ 335 if (*ppos != 0 || count > 2) 336 return -EINVAL; 337 338 cmd_buf = memdup_user(buf, count); 339 if (IS_ERR(cmd_buf)) 340 return PTR_ERR(cmd_buf); 341 342 ret = sscanf(cmd_buf, "%s", user_val); 343 if (ret != 1) 344 return -EINVAL; 345 346 ret = kstrtobool(user_val, &enable); 347 if (ret) 348 goto enable_write_error; 349 350 if (enable) 351 hw->fwlog_cfg.options |= ICE_FWLOG_OPTION_ARQ_ENA; 352 else 353 hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_ARQ_ENA; 354 355 ret = ice_fwlog_set(hw, &hw->fwlog_cfg); 356 if (ret) 357 goto enable_write_error; 358 359 if (enable) 360 ret = ice_fwlog_register(hw); 361 else 362 ret = ice_fwlog_unregister(hw); 363 364 if (ret) 365 goto enable_write_error; 366 367 /* if we get here, nothing went wrong; return count since we didn't 368 * really write anything 369 */ 370 ret = (ssize_t)count; 371 372 enable_write_error: 373 /* This function always consumes all of the written input, or produces 374 * an error. Check and enforce this. Otherwise, the write operation 375 * won't complete properly. 376 */ 377 if (WARN_ON(ret != (ssize_t)count && ret >= 0)) 378 ret = -EIO; 379 380 return ret; 381 } 382 383 static const struct file_operations ice_debugfs_enable_fops = { 384 .owner = THIS_MODULE, 385 .open = simple_open, 386 .read = ice_debugfs_enable_read, 387 .write = ice_debugfs_enable_write, 388 }; 389 390 /** 391 * ice_debugfs_log_size_read - read from 'log_size' file 392 * @filp: the opened file 393 * @buffer: where to write the data for the user to read 394 * @count: the size of the user's buffer 395 * @ppos: file position offset 396 */ 397 static ssize_t ice_debugfs_log_size_read(struct file *filp, 398 char __user *buffer, size_t count, 399 loff_t *ppos) 400 { 401 struct ice_pf *pf = filp->private_data; 402 struct ice_hw *hw = &pf->hw; 403 char buff[32] = {}; 404 int index; 405 406 index = hw->fwlog_ring.index; 407 snprintf(buff, sizeof(buff), "%s\n", ice_fwlog_log_size[index]); 408 409 return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff)); 410 } 411 412 /** 413 * ice_debugfs_log_size_write - write into 'log_size' file 414 * @filp: the opened file 415 * @buf: where to find the user's data 416 * @count: the length of the user's data 417 * @ppos: file position offset 418 */ 419 static ssize_t 420 ice_debugfs_log_size_write(struct file *filp, const char __user *buf, 421 size_t count, loff_t *ppos) 422 { 423 struct ice_pf *pf = filp->private_data; 424 struct device *dev = ice_pf_to_dev(pf); 425 struct ice_hw *hw = &pf->hw; 426 char user_val[8], *cmd_buf; 427 ssize_t ret; 428 int index; 429 430 /* don't allow partial writes or invalid input */ 431 if (*ppos != 0 || count > 5) 432 return -EINVAL; 433 434 cmd_buf = memdup_user(buf, count); 435 if (IS_ERR(cmd_buf)) 436 return PTR_ERR(cmd_buf); 437 438 ret = sscanf(cmd_buf, "%s", user_val); 439 if (ret != 1) 440 return -EINVAL; 441 442 index = sysfs_match_string(ice_fwlog_log_size, user_val); 443 if (index < 0) { 444 dev_info(dev, "Invalid log size '%s'. The value must be one of 128K, 256K, 512K, 1M, 2M\n", 445 user_val); 446 ret = -EINVAL; 447 goto log_size_write_error; 448 } else if (hw->fwlog_cfg.options & ICE_FWLOG_OPTION_IS_REGISTERED) { 449 dev_info(dev, "FW logging is currently running. Please disable FW logging to change log_size\n"); 450 ret = -EINVAL; 451 goto log_size_write_error; 452 } 453 454 /* free all the buffers and the tracking info and resize */ 455 ice_fwlog_realloc_rings(hw, index); 456 457 /* if we get here, nothing went wrong; return count since we didn't 458 * really write anything 459 */ 460 ret = (ssize_t)count; 461 462 log_size_write_error: 463 /* This function always consumes all of the written input, or produces 464 * an error. Check and enforce this. Otherwise, the write operation 465 * won't complete properly. 466 */ 467 if (WARN_ON(ret != (ssize_t)count && ret >= 0)) 468 ret = -EIO; 469 470 return ret; 471 } 472 473 static const struct file_operations ice_debugfs_log_size_fops = { 474 .owner = THIS_MODULE, 475 .open = simple_open, 476 .read = ice_debugfs_log_size_read, 477 .write = ice_debugfs_log_size_write, 478 }; 479 480 /** 481 * ice_debugfs_data_read - read from 'data' file 482 * @filp: the opened file 483 * @buffer: where to write the data for the user to read 484 * @count: the size of the user's buffer 485 * @ppos: file position offset 486 */ 487 static ssize_t ice_debugfs_data_read(struct file *filp, char __user *buffer, 488 size_t count, loff_t *ppos) 489 { 490 struct ice_pf *pf = filp->private_data; 491 struct ice_hw *hw = &pf->hw; 492 int data_copied = 0; 493 bool done = false; 494 495 if (ice_fwlog_ring_empty(&hw->fwlog_ring)) 496 return 0; 497 498 while (!ice_fwlog_ring_empty(&hw->fwlog_ring) && !done) { 499 struct ice_fwlog_data *log; 500 u16 cur_buf_len; 501 502 log = &hw->fwlog_ring.rings[hw->fwlog_ring.head]; 503 cur_buf_len = log->data_size; 504 if (cur_buf_len >= count) { 505 done = true; 506 continue; 507 } 508 509 if (copy_to_user(buffer, log->data, cur_buf_len)) { 510 /* if there is an error then bail and return whatever 511 * the driver has copied so far 512 */ 513 done = true; 514 continue; 515 } 516 517 data_copied += cur_buf_len; 518 buffer += cur_buf_len; 519 count -= cur_buf_len; 520 *ppos += cur_buf_len; 521 ice_fwlog_ring_increment(&hw->fwlog_ring.head, 522 hw->fwlog_ring.size); 523 } 524 525 return data_copied; 526 } 527 528 /** 529 * ice_debugfs_data_write - write into 'data' file 530 * @filp: the opened file 531 * @buf: where to find the user's data 532 * @count: the length of the user's data 533 * @ppos: file position offset 534 */ 535 static ssize_t 536 ice_debugfs_data_write(struct file *filp, const char __user *buf, size_t count, 537 loff_t *ppos) 538 { 539 struct ice_pf *pf = filp->private_data; 540 struct device *dev = ice_pf_to_dev(pf); 541 struct ice_hw *hw = &pf->hw; 542 ssize_t ret; 543 544 /* don't allow partial writes */ 545 if (*ppos != 0) 546 return 0; 547 548 /* any value is allowed to clear the buffer so no need to even look at 549 * what the value is 550 */ 551 if (!(hw->fwlog_cfg.options & ICE_FWLOG_OPTION_IS_REGISTERED)) { 552 hw->fwlog_ring.head = 0; 553 hw->fwlog_ring.tail = 0; 554 } else { 555 dev_info(dev, "Can't clear FW log data while FW log running\n"); 556 ret = -EINVAL; 557 goto nr_buffs_write_error; 558 } 559 560 /* if we get here, nothing went wrong; return count since we didn't 561 * really write anything 562 */ 563 ret = (ssize_t)count; 564 565 nr_buffs_write_error: 566 /* This function always consumes all of the written input, or produces 567 * an error. Check and enforce this. Otherwise, the write operation 568 * won't complete properly. 569 */ 570 if (WARN_ON(ret != (ssize_t)count && ret >= 0)) 571 ret = -EIO; 572 573 return ret; 574 } 575 576 static const struct file_operations ice_debugfs_data_fops = { 577 .owner = THIS_MODULE, 578 .open = simple_open, 579 .read = ice_debugfs_data_read, 580 .write = ice_debugfs_data_write, 581 }; 582 583 /** 584 * ice_debugfs_fwlog_init - setup the debugfs directory 585 * @pf: the ice that is starting up 586 */ 587 void ice_debugfs_fwlog_init(struct ice_pf *pf) 588 { 589 const char *name = pci_name(pf->pdev); 590 struct dentry *fw_modules_dir; 591 struct dentry **fw_modules; 592 int i; 593 594 /* only support fw log commands on PF 0 */ 595 if (pf->hw.bus.func) 596 return; 597 598 /* allocate space for this first because if it fails then we don't 599 * need to unwind 600 */ 601 fw_modules = kcalloc(ICE_NR_FW_LOG_MODULES, sizeof(*fw_modules), 602 GFP_KERNEL); 603 if (!fw_modules) 604 return; 605 606 pf->ice_debugfs_pf = debugfs_create_dir(name, ice_debugfs_root); 607 if (IS_ERR(pf->ice_debugfs_pf)) 608 goto err_create_module_files; 609 610 pf->ice_debugfs_pf_fwlog = debugfs_create_dir("fwlog", 611 pf->ice_debugfs_pf); 612 if (IS_ERR(pf->ice_debugfs_pf)) 613 goto err_create_module_files; 614 615 fw_modules_dir = debugfs_create_dir("modules", 616 pf->ice_debugfs_pf_fwlog); 617 if (IS_ERR(fw_modules_dir)) 618 goto err_create_module_files; 619 620 for (i = 0; i < ICE_NR_FW_LOG_MODULES; i++) { 621 fw_modules[i] = debugfs_create_file(ice_fwlog_module_string[i], 622 0600, fw_modules_dir, pf, 623 &ice_debugfs_module_fops); 624 if (IS_ERR(fw_modules[i])) 625 goto err_create_module_files; 626 } 627 628 debugfs_create_file("nr_messages", 0600, 629 pf->ice_debugfs_pf_fwlog, pf, 630 &ice_debugfs_nr_messages_fops); 631 632 pf->ice_debugfs_pf_fwlog_modules = fw_modules; 633 634 debugfs_create_file("enable", 0600, pf->ice_debugfs_pf_fwlog, 635 pf, &ice_debugfs_enable_fops); 636 637 debugfs_create_file("log_size", 0600, pf->ice_debugfs_pf_fwlog, 638 pf, &ice_debugfs_log_size_fops); 639 640 debugfs_create_file("data", 0600, pf->ice_debugfs_pf_fwlog, 641 pf, &ice_debugfs_data_fops); 642 643 return; 644 645 err_create_module_files: 646 debugfs_remove_recursive(pf->ice_debugfs_pf_fwlog); 647 kfree(fw_modules); 648 } 649 650 /** 651 * ice_debugfs_init - create root directory for debugfs entries 652 */ 653 void ice_debugfs_init(void) 654 { 655 ice_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); 656 if (IS_ERR(ice_debugfs_root)) 657 pr_info("init of debugfs failed\n"); 658 } 659 660 /** 661 * ice_debugfs_exit - remove debugfs entries 662 */ 663 void ice_debugfs_exit(void) 664 { 665 debugfs_remove_recursive(ice_debugfs_root); 666 ice_debugfs_root = NULL; 667 } 668