Commit 9f778708 authored by James Smart's avatar James Smart Committed by Martin K. Petersen

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.comCo-developed-by: default avatarJustin Tee <justin.tee@broadcom.com>
Signed-off-by: default avatarJustin Tee <justin.tee@broadcom.com>
Signed-off-by: default avatarJames Smart <jsmart2021@gmail.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 7481811c
......@@ -1357,6 +1357,8 @@ struct lpfc_hba {
#ifdef LPFC_HDWQ_LOCK_STAT
struct dentry *debug_lockstat;
#endif
struct dentry *debug_cgn_buffer;
struct dentry *debug_rx_monitor;
struct dentry *debug_ras_log;
atomic_t nvmeio_trc_cnt;
uint32_t nvmeio_trc_size;
......
......@@ -5429,6 +5429,180 @@ lpfc_idiag_extacc_read(struct file *file, char __user *buf, size_t nbytes,
return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
}
static int
lpfc_cgn_buffer_open(struct inode *inode, struct file *file)
{
struct lpfc_debug *debug;
int rc = -ENOMEM;
debug = kmalloc(sizeof(*debug), GFP_KERNEL);
if (!debug)
goto out;
debug->buffer = vmalloc(LPFC_CGN_BUF_SIZE);
if (!debug->buffer) {
kfree(debug);
goto out;
}
debug->i_private = inode->i_private;
file->private_data = debug;
rc = 0;
out:
return rc;
}
static ssize_t
lpfc_cgn_buffer_read(struct file *file, char __user *buf, size_t nbytes,
loff_t *ppos)
{
struct lpfc_debug *debug = file->private_data;
struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
char *buffer = debug->buffer;
uint32_t *ptr;
int cnt, len = 0;
if (!phba->sli4_hba.pc_sli4_params.mi_ver || !phba->cgn_i) {
len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
"Congestion Mgmt is not supported\n");
goto out;
}
ptr = (uint32_t *)phba->cgn_i->virt;
len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
"Congestion Buffer Header\n");
/* Dump the first 32 bytes */
cnt = 32;
len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
"000: %08x %08x %08x %08x %08x %08x %08x %08x\n",
*ptr, *(ptr + 1), *(ptr + 2), *(ptr + 3),
*(ptr + 4), *(ptr + 5), *(ptr + 6), *(ptr + 7));
ptr += 8;
len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
"Congestion Buffer Data\n");
while (cnt < sizeof(struct lpfc_cgn_info)) {
if (len > (LPFC_CGN_BUF_SIZE - LPFC_DEBUG_OUT_LINE_SZ)) {
len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
"Truncated . . .\n");
break;
}
len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
"%03x: %08x %08x %08x %08x "
"%08x %08x %08x %08x\n",
cnt, *ptr, *(ptr + 1), *(ptr + 2),
*(ptr + 3), *(ptr + 4), *(ptr + 5),
*(ptr + 6), *(ptr + 7));
cnt += 32;
ptr += 8;
}
out:
return simple_read_from_buffer(buf, nbytes, ppos, buffer, len);
}
static int
lpfc_cgn_buffer_release(struct inode *inode, struct file *file)
{
struct lpfc_debug *debug = file->private_data;
vfree(debug->buffer);
kfree(debug);
return 0;
}
static int
lpfc_rx_monitor_open(struct inode *inode, struct file *file)
{
struct lpfc_rx_monitor_debug *debug;
int rc = -ENOMEM;
debug = kmalloc(sizeof(*debug), GFP_KERNEL);
if (!debug)
goto out;
debug->buffer = vmalloc(MAX_DEBUGFS_RX_TABLE_SIZE);
if (!debug->buffer) {
kfree(debug);
goto out;
}
debug->i_private = inode->i_private;
file->private_data = debug;
rc = 0;
out:
return rc;
}
static ssize_t
lpfc_rx_monitor_read(struct file *file, char __user *buf, size_t nbytes,
loff_t *ppos)
{
struct lpfc_rx_monitor_debug *debug = file->private_data;
struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
char *buffer = debug->buffer;
struct rxtable_entry *entry;
int i, len = 0, head, tail, last, start;
head = atomic_read(&phba->rxtable_idx_head);
while (head == LPFC_RXMONITOR_TABLE_IN_USE) {
/* Table is getting updated */
msleep(20);
head = atomic_read(&phba->rxtable_idx_head);
}
tail = atomic_xchg(&phba->rxtable_idx_tail, head);
if (!phba->rxtable || head == tail) {
len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len,
"Rxtable is empty\n");
goto out;
}
last = (head > tail) ? head : LPFC_MAX_RXMONITOR_ENTRY;
start = tail;
len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len,
" MaxBPI\t Total Data Cmd Total Data Cmpl "
" Latency(us) Avg IO Size\tMax IO Size IO cnt "
"Info BWutil(ms)\n");
get_table:
for (i = start; i < last; i++) {
entry = &phba->rxtable[i];
len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len,
"%3d:%12lld %12lld\t%12lld\t"
"%8lldus\t%8lld\t%10lld "
"%8d %2d %2d(%2d)\n",
i, entry->max_bytes_per_interval,
entry->total_bytes,
entry->rcv_bytes,
entry->avg_io_latency,
entry->avg_io_size,
entry->max_read_cnt,
entry->io_cnt,
entry->cmf_info,
entry->timer_utilization,
entry->timer_interval);
}
if (head != last) {
start = 0;
last = head;
goto get_table;
}
out:
return simple_read_from_buffer(buf, nbytes, ppos, buffer, len);
}
static int
lpfc_rx_monitor_release(struct inode *inode, struct file *file)
{
struct lpfc_rx_monitor_debug *debug = file->private_data;
vfree(debug->buffer);
kfree(debug);
return 0;
}
#undef lpfc_debugfs_op_disc_trc
static const struct file_operations lpfc_debugfs_op_disc_trc = {
.owner = THIS_MODULE,
......@@ -5657,6 +5831,23 @@ static const struct file_operations lpfc_idiag_op_extAcc = {
.write = lpfc_idiag_extacc_write,
.release = lpfc_idiag_cmd_release,
};
#undef lpfc_cgn_buffer_op
static const struct file_operations lpfc_cgn_buffer_op = {
.owner = THIS_MODULE,
.open = lpfc_cgn_buffer_open,
.llseek = lpfc_debugfs_lseek,
.read = lpfc_cgn_buffer_read,
.release = lpfc_cgn_buffer_release,
};
#undef lpfc_rx_monitor_op
static const struct file_operations lpfc_rx_monitor_op = {
.owner = THIS_MODULE,
.open = lpfc_rx_monitor_open,
.llseek = lpfc_debugfs_lseek,
.read = lpfc_rx_monitor_read,
.release = lpfc_rx_monitor_release,
};
#endif
/* lpfc_idiag_mbxacc_dump_bsg_mbox - idiag debugfs dump bsg mailbox command
......@@ -5907,6 +6098,32 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
goto debug_failed;
}
/* Congestion Info Buffer */
scnprintf(name, sizeof(name), "cgn_buffer");
phba->debug_cgn_buffer =
debugfs_create_file(name, S_IFREG | 0644,
phba->hba_debugfs_root,
phba, &lpfc_cgn_buffer_op);
if (!phba->debug_cgn_buffer) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
"6527 Cannot create debugfs "
"cgn_buffer\n");
goto debug_failed;
}
/* RX Monitor */
scnprintf(name, sizeof(name), "rx_monitor");
phba->debug_rx_monitor =
debugfs_create_file(name, S_IFREG | 0644,
phba->hba_debugfs_root,
phba, &lpfc_rx_monitor_op);
if (!phba->debug_rx_monitor) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
"6528 Cannot create debugfs "
"rx_monitor\n");
goto debug_failed;
}
/* RAS log */
snprintf(name, sizeof(name), "ras_log");
phba->debug_ras_log =
......@@ -6335,6 +6552,12 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */
phba->debug_hbqinfo = NULL;
debugfs_remove(phba->debug_cgn_buffer);
phba->debug_cgn_buffer = NULL;
debugfs_remove(phba->debug_rx_monitor);
phba->debug_rx_monitor = NULL;
debugfs_remove(phba->debug_ras_log);
phba->debug_ras_log = NULL;
......
......@@ -52,6 +52,9 @@
/* scsistat output buffer size */
#define LPFC_SCSISTAT_SIZE 8192
/* Congestion Info Buffer size */
#define LPFC_CGN_BUF_SIZE 8192
#define LPFC_DEBUG_OUT_LINE_SZ 80
/*
......@@ -279,6 +282,12 @@ struct lpfc_idiag {
void *ptr_private;
};
#define MAX_DEBUGFS_RX_TABLE_SIZE (100 * LPFC_MAX_RXMONITOR_ENTRY)
struct lpfc_rx_monitor_debug {
char *i_private;
char *buffer;
};
#else
#define lpfc_nvmeio_data(phba, fmt, arg...) \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment