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

scsi: lpfc: Add debugfs support for cm framework buffers

Add support via debugfs to report the cm statistics, cm enablement, and rx
monitor information.

Link: https://lore.kernel.org/r/20210816162901.121235-13-jsmart2021@gmail.com
Co-developed-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

James Smart and committed by
Martin K. Petersen
9f778708 7481811c

+234
+2
drivers/scsi/lpfc/lpfc.h
··· 1357 1357 #ifdef LPFC_HDWQ_LOCK_STAT 1358 1358 struct dentry *debug_lockstat; 1359 1359 #endif 1360 + struct dentry *debug_cgn_buffer; 1361 + struct dentry *debug_rx_monitor; 1360 1362 struct dentry *debug_ras_log; 1361 1363 atomic_t nvmeio_trc_cnt; 1362 1364 uint32_t nvmeio_trc_size;
+223
drivers/scsi/lpfc/lpfc_debugfs.c
··· 5429 5429 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); 5430 5430 } 5431 5431 5432 + static int 5433 + lpfc_cgn_buffer_open(struct inode *inode, struct file *file) 5434 + { 5435 + struct lpfc_debug *debug; 5436 + int rc = -ENOMEM; 5437 + 5438 + debug = kmalloc(sizeof(*debug), GFP_KERNEL); 5439 + if (!debug) 5440 + goto out; 5441 + 5442 + debug->buffer = vmalloc(LPFC_CGN_BUF_SIZE); 5443 + if (!debug->buffer) { 5444 + kfree(debug); 5445 + goto out; 5446 + } 5447 + 5448 + debug->i_private = inode->i_private; 5449 + file->private_data = debug; 5450 + 5451 + rc = 0; 5452 + out: 5453 + return rc; 5454 + } 5455 + 5456 + static ssize_t 5457 + lpfc_cgn_buffer_read(struct file *file, char __user *buf, size_t nbytes, 5458 + loff_t *ppos) 5459 + { 5460 + struct lpfc_debug *debug = file->private_data; 5461 + struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 5462 + char *buffer = debug->buffer; 5463 + uint32_t *ptr; 5464 + int cnt, len = 0; 5465 + 5466 + if (!phba->sli4_hba.pc_sli4_params.mi_ver || !phba->cgn_i) { 5467 + len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len, 5468 + "Congestion Mgmt is not supported\n"); 5469 + goto out; 5470 + } 5471 + ptr = (uint32_t *)phba->cgn_i->virt; 5472 + len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len, 5473 + "Congestion Buffer Header\n"); 5474 + /* Dump the first 32 bytes */ 5475 + cnt = 32; 5476 + len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len, 5477 + "000: %08x %08x %08x %08x %08x %08x %08x %08x\n", 5478 + *ptr, *(ptr + 1), *(ptr + 2), *(ptr + 3), 5479 + *(ptr + 4), *(ptr + 5), *(ptr + 6), *(ptr + 7)); 5480 + ptr += 8; 5481 + len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len, 5482 + "Congestion Buffer Data\n"); 5483 + while (cnt < sizeof(struct lpfc_cgn_info)) { 5484 + if (len > (LPFC_CGN_BUF_SIZE - LPFC_DEBUG_OUT_LINE_SZ)) { 5485 + len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len, 5486 + "Truncated . . .\n"); 5487 + break; 5488 + } 5489 + len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len, 5490 + "%03x: %08x %08x %08x %08x " 5491 + "%08x %08x %08x %08x\n", 5492 + cnt, *ptr, *(ptr + 1), *(ptr + 2), 5493 + *(ptr + 3), *(ptr + 4), *(ptr + 5), 5494 + *(ptr + 6), *(ptr + 7)); 5495 + cnt += 32; 5496 + ptr += 8; 5497 + } 5498 + out: 5499 + return simple_read_from_buffer(buf, nbytes, ppos, buffer, len); 5500 + } 5501 + 5502 + static int 5503 + lpfc_cgn_buffer_release(struct inode *inode, struct file *file) 5504 + { 5505 + struct lpfc_debug *debug = file->private_data; 5506 + 5507 + vfree(debug->buffer); 5508 + kfree(debug); 5509 + 5510 + return 0; 5511 + } 5512 + 5513 + static int 5514 + lpfc_rx_monitor_open(struct inode *inode, struct file *file) 5515 + { 5516 + struct lpfc_rx_monitor_debug *debug; 5517 + int rc = -ENOMEM; 5518 + 5519 + debug = kmalloc(sizeof(*debug), GFP_KERNEL); 5520 + if (!debug) 5521 + goto out; 5522 + 5523 + debug->buffer = vmalloc(MAX_DEBUGFS_RX_TABLE_SIZE); 5524 + if (!debug->buffer) { 5525 + kfree(debug); 5526 + goto out; 5527 + } 5528 + 5529 + debug->i_private = inode->i_private; 5530 + file->private_data = debug; 5531 + 5532 + rc = 0; 5533 + out: 5534 + return rc; 5535 + } 5536 + 5537 + static ssize_t 5538 + lpfc_rx_monitor_read(struct file *file, char __user *buf, size_t nbytes, 5539 + loff_t *ppos) 5540 + { 5541 + struct lpfc_rx_monitor_debug *debug = file->private_data; 5542 + struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; 5543 + char *buffer = debug->buffer; 5544 + struct rxtable_entry *entry; 5545 + int i, len = 0, head, tail, last, start; 5546 + 5547 + head = atomic_read(&phba->rxtable_idx_head); 5548 + while (head == LPFC_RXMONITOR_TABLE_IN_USE) { 5549 + /* Table is getting updated */ 5550 + msleep(20); 5551 + head = atomic_read(&phba->rxtable_idx_head); 5552 + } 5553 + 5554 + tail = atomic_xchg(&phba->rxtable_idx_tail, head); 5555 + if (!phba->rxtable || head == tail) { 5556 + len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len, 5557 + "Rxtable is empty\n"); 5558 + goto out; 5559 + } 5560 + last = (head > tail) ? head : LPFC_MAX_RXMONITOR_ENTRY; 5561 + start = tail; 5562 + 5563 + len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len, 5564 + " MaxBPI\t Total Data Cmd Total Data Cmpl " 5565 + " Latency(us) Avg IO Size\tMax IO Size IO cnt " 5566 + "Info BWutil(ms)\n"); 5567 + get_table: 5568 + for (i = start; i < last; i++) { 5569 + entry = &phba->rxtable[i]; 5570 + len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len, 5571 + "%3d:%12lld %12lld\t%12lld\t" 5572 + "%8lldus\t%8lld\t%10lld " 5573 + "%8d %2d %2d(%2d)\n", 5574 + i, entry->max_bytes_per_interval, 5575 + entry->total_bytes, 5576 + entry->rcv_bytes, 5577 + entry->avg_io_latency, 5578 + entry->avg_io_size, 5579 + entry->max_read_cnt, 5580 + entry->io_cnt, 5581 + entry->cmf_info, 5582 + entry->timer_utilization, 5583 + entry->timer_interval); 5584 + } 5585 + 5586 + if (head != last) { 5587 + start = 0; 5588 + last = head; 5589 + goto get_table; 5590 + } 5591 + out: 5592 + return simple_read_from_buffer(buf, nbytes, ppos, buffer, len); 5593 + } 5594 + 5595 + static int 5596 + lpfc_rx_monitor_release(struct inode *inode, struct file *file) 5597 + { 5598 + struct lpfc_rx_monitor_debug *debug = file->private_data; 5599 + 5600 + vfree(debug->buffer); 5601 + kfree(debug); 5602 + 5603 + return 0; 5604 + } 5605 + 5432 5606 #undef lpfc_debugfs_op_disc_trc 5433 5607 static const struct file_operations lpfc_debugfs_op_disc_trc = { 5434 5608 .owner = THIS_MODULE, ··· 5830 5656 .read = lpfc_idiag_extacc_read, 5831 5657 .write = lpfc_idiag_extacc_write, 5832 5658 .release = lpfc_idiag_cmd_release, 5659 + }; 5660 + #undef lpfc_cgn_buffer_op 5661 + static const struct file_operations lpfc_cgn_buffer_op = { 5662 + .owner = THIS_MODULE, 5663 + .open = lpfc_cgn_buffer_open, 5664 + .llseek = lpfc_debugfs_lseek, 5665 + .read = lpfc_cgn_buffer_read, 5666 + .release = lpfc_cgn_buffer_release, 5667 + }; 5668 + 5669 + #undef lpfc_rx_monitor_op 5670 + static const struct file_operations lpfc_rx_monitor_op = { 5671 + .owner = THIS_MODULE, 5672 + .open = lpfc_rx_monitor_open, 5673 + .llseek = lpfc_debugfs_lseek, 5674 + .read = lpfc_rx_monitor_read, 5675 + .release = lpfc_rx_monitor_release, 5833 5676 }; 5834 5677 #endif 5835 5678 ··· 6095 5904 if (!phba->debug_multixri_pools) { 6096 5905 lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 6097 5906 "0527 Cannot create debugfs multixripools\n"); 5907 + goto debug_failed; 5908 + } 5909 + 5910 + /* Congestion Info Buffer */ 5911 + scnprintf(name, sizeof(name), "cgn_buffer"); 5912 + phba->debug_cgn_buffer = 5913 + debugfs_create_file(name, S_IFREG | 0644, 5914 + phba->hba_debugfs_root, 5915 + phba, &lpfc_cgn_buffer_op); 5916 + if (!phba->debug_cgn_buffer) { 5917 + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 5918 + "6527 Cannot create debugfs " 5919 + "cgn_buffer\n"); 5920 + goto debug_failed; 5921 + } 5922 + 5923 + /* RX Monitor */ 5924 + scnprintf(name, sizeof(name), "rx_monitor"); 5925 + phba->debug_rx_monitor = 5926 + debugfs_create_file(name, S_IFREG | 0644, 5927 + phba->hba_debugfs_root, 5928 + phba, &lpfc_rx_monitor_op); 5929 + if (!phba->debug_rx_monitor) { 5930 + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, 5931 + "6528 Cannot create debugfs " 5932 + "rx_monitor\n"); 6098 5933 goto debug_failed; 6099 5934 } 6100 5935 ··· 6551 6334 6552 6335 debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */ 6553 6336 phba->debug_hbqinfo = NULL; 6337 + 6338 + debugfs_remove(phba->debug_cgn_buffer); 6339 + phba->debug_cgn_buffer = NULL; 6340 + 6341 + debugfs_remove(phba->debug_rx_monitor); 6342 + phba->debug_rx_monitor = NULL; 6554 6343 6555 6344 debugfs_remove(phba->debug_ras_log); 6556 6345 phba->debug_ras_log = NULL;
+9
drivers/scsi/lpfc/lpfc_debugfs.h
··· 52 52 /* scsistat output buffer size */ 53 53 #define LPFC_SCSISTAT_SIZE 8192 54 54 55 + /* Congestion Info Buffer size */ 56 + #define LPFC_CGN_BUF_SIZE 8192 57 + 55 58 #define LPFC_DEBUG_OUT_LINE_SZ 80 56 59 57 60 /* ··· 280 277 struct lpfc_idiag_cmd cmd; 281 278 struct lpfc_idiag_offset offset; 282 279 void *ptr_private; 280 + }; 281 + 282 + #define MAX_DEBUGFS_RX_TABLE_SIZE (100 * LPFC_MAX_RXMONITOR_ENTRY) 283 + struct lpfc_rx_monitor_debug { 284 + char *i_private; 285 + char *buffer; 283 286 }; 284 287 285 288 #else