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>
This commit is contained in:
parent
7481811c3a
commit
9f77870870
|
@ -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...) \
|
||||
|
|
Loading…
Reference in New Issue