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
3 changed files with 234 additions and 0 deletions
|
@ -1357,6 +1357,8 @@ struct lpfc_hba {
|
||||||
#ifdef LPFC_HDWQ_LOCK_STAT
|
#ifdef LPFC_HDWQ_LOCK_STAT
|
||||||
struct dentry *debug_lockstat;
|
struct dentry *debug_lockstat;
|
||||||
#endif
|
#endif
|
||||||
|
struct dentry *debug_cgn_buffer;
|
||||||
|
struct dentry *debug_rx_monitor;
|
||||||
struct dentry *debug_ras_log;
|
struct dentry *debug_ras_log;
|
||||||
atomic_t nvmeio_trc_cnt;
|
atomic_t nvmeio_trc_cnt;
|
||||||
uint32_t nvmeio_trc_size;
|
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);
|
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
|
#undef lpfc_debugfs_op_disc_trc
|
||||||
static const struct file_operations lpfc_debugfs_op_disc_trc = {
|
static const struct file_operations lpfc_debugfs_op_disc_trc = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
@ -5657,6 +5831,23 @@ static const struct file_operations lpfc_idiag_op_extAcc = {
|
||||||
.write = lpfc_idiag_extacc_write,
|
.write = lpfc_idiag_extacc_write,
|
||||||
.release = lpfc_idiag_cmd_release,
|
.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
|
#endif
|
||||||
|
|
||||||
/* lpfc_idiag_mbxacc_dump_bsg_mbox - idiag debugfs dump bsg mailbox command
|
/* 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;
|
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 */
|
/* RAS log */
|
||||||
snprintf(name, sizeof(name), "ras_log");
|
snprintf(name, sizeof(name), "ras_log");
|
||||||
phba->debug_ras_log =
|
phba->debug_ras_log =
|
||||||
|
@ -6335,6 +6552,12 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
|
||||||
debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */
|
debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */
|
||||||
phba->debug_hbqinfo = NULL;
|
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);
|
debugfs_remove(phba->debug_ras_log);
|
||||||
phba->debug_ras_log = NULL;
|
phba->debug_ras_log = NULL;
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,9 @@
|
||||||
/* scsistat output buffer size */
|
/* scsistat output buffer size */
|
||||||
#define LPFC_SCSISTAT_SIZE 8192
|
#define LPFC_SCSISTAT_SIZE 8192
|
||||||
|
|
||||||
|
/* Congestion Info Buffer size */
|
||||||
|
#define LPFC_CGN_BUF_SIZE 8192
|
||||||
|
|
||||||
#define LPFC_DEBUG_OUT_LINE_SZ 80
|
#define LPFC_DEBUG_OUT_LINE_SZ 80
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -279,6 +282,12 @@ struct lpfc_idiag {
|
||||||
void *ptr_private;
|
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
|
#else
|
||||||
|
|
||||||
#define lpfc_nvmeio_data(phba, fmt, arg...) \
|
#define lpfc_nvmeio_data(phba, fmt, arg...) \
|
||||||
|
|
Loading…
Add table
Reference in a new issue