26febfb38c
When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: QLogic-Storage-Upstream@cavium.com Cc: "James E.J. Bottomley" <jejb@linux.ibm.com> Cc: "Martin K. Petersen" <martin.petersen@oracle.com> Cc: linux-scsi@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Acked-by: Manish Rangankar <mrangankar@marvell.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
232 lines
5.6 KiB
C
232 lines
5.6 KiB
C
/*
|
|
* QLogic iSCSI Offload Driver
|
|
* Copyright (c) 2016 Cavium Inc.
|
|
*
|
|
* This software is available under the terms of the GNU General Public License
|
|
* (GPL) Version 2, available from the file COPYING in the main directory of
|
|
* this source tree.
|
|
*/
|
|
|
|
#include "qedi.h"
|
|
#include "qedi_dbg.h"
|
|
|
|
#include <linux/uaccess.h>
|
|
#include <linux/debugfs.h>
|
|
#include <linux/module.h>
|
|
|
|
int qedi_do_not_recover;
|
|
static struct dentry *qedi_dbg_root;
|
|
|
|
void
|
|
qedi_dbg_host_init(struct qedi_dbg_ctx *qedi,
|
|
const struct qedi_debugfs_ops *dops,
|
|
const struct file_operations *fops)
|
|
{
|
|
char host_dirname[32];
|
|
|
|
sprintf(host_dirname, "host%u", qedi->host_no);
|
|
qedi->bdf_dentry = debugfs_create_dir(host_dirname, qedi_dbg_root);
|
|
|
|
while (dops) {
|
|
if (!(dops->name))
|
|
break;
|
|
|
|
debugfs_create_file(dops->name, 0600, qedi->bdf_dentry, qedi,
|
|
fops);
|
|
dops++;
|
|
fops++;
|
|
}
|
|
}
|
|
|
|
void
|
|
qedi_dbg_host_exit(struct qedi_dbg_ctx *qedi)
|
|
{
|
|
debugfs_remove_recursive(qedi->bdf_dentry);
|
|
qedi->bdf_dentry = NULL;
|
|
}
|
|
|
|
void
|
|
qedi_dbg_init(char *drv_name)
|
|
{
|
|
qedi_dbg_root = debugfs_create_dir(drv_name, NULL);
|
|
}
|
|
|
|
void
|
|
qedi_dbg_exit(void)
|
|
{
|
|
debugfs_remove_recursive(qedi_dbg_root);
|
|
qedi_dbg_root = NULL;
|
|
}
|
|
|
|
static ssize_t
|
|
qedi_dbg_do_not_recover_enable(struct qedi_dbg_ctx *qedi_dbg)
|
|
{
|
|
if (!qedi_do_not_recover)
|
|
qedi_do_not_recover = 1;
|
|
|
|
QEDI_INFO(qedi_dbg, QEDI_LOG_DEBUGFS, "do_not_recover=%d\n",
|
|
qedi_do_not_recover);
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t
|
|
qedi_dbg_do_not_recover_disable(struct qedi_dbg_ctx *qedi_dbg)
|
|
{
|
|
if (qedi_do_not_recover)
|
|
qedi_do_not_recover = 0;
|
|
|
|
QEDI_INFO(qedi_dbg, QEDI_LOG_DEBUGFS, "do_not_recover=%d\n",
|
|
qedi_do_not_recover);
|
|
return 0;
|
|
}
|
|
|
|
static struct qedi_list_of_funcs qedi_dbg_do_not_recover_ops[] = {
|
|
{ "enable", qedi_dbg_do_not_recover_enable },
|
|
{ "disable", qedi_dbg_do_not_recover_disable },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
const struct qedi_debugfs_ops qedi_debugfs_ops[] = {
|
|
{ "gbl_ctx", NULL },
|
|
{ "do_not_recover", qedi_dbg_do_not_recover_ops},
|
|
{ "io_trace", NULL },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
static ssize_t
|
|
qedi_dbg_do_not_recover_cmd_write(struct file *filp, const char __user *buffer,
|
|
size_t count, loff_t *ppos)
|
|
{
|
|
size_t cnt = 0;
|
|
struct qedi_dbg_ctx *qedi_dbg =
|
|
(struct qedi_dbg_ctx *)filp->private_data;
|
|
struct qedi_list_of_funcs *lof = qedi_dbg_do_not_recover_ops;
|
|
|
|
if (*ppos)
|
|
return 0;
|
|
|
|
while (lof) {
|
|
if (!(lof->oper_str))
|
|
break;
|
|
|
|
if (!strncmp(lof->oper_str, buffer, strlen(lof->oper_str))) {
|
|
cnt = lof->oper_func(qedi_dbg);
|
|
break;
|
|
}
|
|
|
|
lof++;
|
|
}
|
|
return (count - cnt);
|
|
}
|
|
|
|
static ssize_t
|
|
qedi_dbg_do_not_recover_cmd_read(struct file *filp, char __user *buffer,
|
|
size_t count, loff_t *ppos)
|
|
{
|
|
size_t cnt = 0;
|
|
|
|
if (*ppos)
|
|
return 0;
|
|
|
|
cnt = sprintf(buffer, "do_not_recover=%d\n", qedi_do_not_recover);
|
|
cnt = min_t(int, count, cnt - *ppos);
|
|
*ppos += cnt;
|
|
return cnt;
|
|
}
|
|
|
|
static int
|
|
qedi_gbl_ctx_show(struct seq_file *s, void *unused)
|
|
{
|
|
struct qedi_fastpath *fp = NULL;
|
|
struct qed_sb_info *sb_info = NULL;
|
|
struct status_block_e4 *sb = NULL;
|
|
struct global_queue *que = NULL;
|
|
int id;
|
|
u16 prod_idx;
|
|
struct qedi_ctx *qedi = s->private;
|
|
unsigned long flags;
|
|
|
|
seq_puts(s, " DUMP CQ CONTEXT:\n");
|
|
|
|
for (id = 0; id < MIN_NUM_CPUS_MSIX(qedi); id++) {
|
|
spin_lock_irqsave(&qedi->hba_lock, flags);
|
|
seq_printf(s, "=========FAST CQ PATH [%d] ==========\n", id);
|
|
fp = &qedi->fp_array[id];
|
|
sb_info = fp->sb_info;
|
|
sb = sb_info->sb_virt;
|
|
prod_idx = (sb->pi_array[QEDI_PROTO_CQ_PROD_IDX] &
|
|
STATUS_BLOCK_E4_PROD_INDEX_MASK);
|
|
seq_printf(s, "SB PROD IDX: %d\n", prod_idx);
|
|
que = qedi->global_queues[fp->sb_id];
|
|
seq_printf(s, "DRV CONS IDX: %d\n", que->cq_cons_idx);
|
|
seq_printf(s, "CQ complete host memory: %d\n", fp->sb_id);
|
|
seq_puts(s, "=========== END ==================\n\n\n");
|
|
spin_unlock_irqrestore(&qedi->hba_lock, flags);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
qedi_dbg_gbl_ctx_open(struct inode *inode, struct file *file)
|
|
{
|
|
struct qedi_dbg_ctx *qedi_dbg = inode->i_private;
|
|
struct qedi_ctx *qedi = container_of(qedi_dbg, struct qedi_ctx,
|
|
dbg_ctx);
|
|
|
|
return single_open(file, qedi_gbl_ctx_show, qedi);
|
|
}
|
|
|
|
static int
|
|
qedi_io_trace_show(struct seq_file *s, void *unused)
|
|
{
|
|
int id, idx = 0;
|
|
struct qedi_ctx *qedi = s->private;
|
|
struct qedi_io_log *io_log;
|
|
unsigned long flags;
|
|
|
|
seq_puts(s, " DUMP IO LOGS:\n");
|
|
spin_lock_irqsave(&qedi->io_trace_lock, flags);
|
|
idx = qedi->io_trace_idx;
|
|
for (id = 0; id < QEDI_IO_TRACE_SIZE; id++) {
|
|
io_log = &qedi->io_trace_buf[idx];
|
|
seq_printf(s, "iodir-%d:", io_log->direction);
|
|
seq_printf(s, "tid-0x%x:", io_log->task_id);
|
|
seq_printf(s, "cid-0x%x:", io_log->cid);
|
|
seq_printf(s, "lun-%d:", io_log->lun);
|
|
seq_printf(s, "op-0x%02x:", io_log->op);
|
|
seq_printf(s, "0x%02x%02x%02x%02x:", io_log->lba[0],
|
|
io_log->lba[1], io_log->lba[2], io_log->lba[3]);
|
|
seq_printf(s, "buflen-%d:", io_log->bufflen);
|
|
seq_printf(s, "sgcnt-%d:", io_log->sg_count);
|
|
seq_printf(s, "res-0x%08x:", io_log->result);
|
|
seq_printf(s, "jif-%lu:", io_log->jiffies);
|
|
seq_printf(s, "blk_req_cpu-%d:", io_log->blk_req_cpu);
|
|
seq_printf(s, "req_cpu-%d:", io_log->req_cpu);
|
|
seq_printf(s, "intr_cpu-%d:", io_log->intr_cpu);
|
|
seq_printf(s, "blk_rsp_cpu-%d\n", io_log->blk_rsp_cpu);
|
|
|
|
idx++;
|
|
if (idx == QEDI_IO_TRACE_SIZE)
|
|
idx = 0;
|
|
}
|
|
spin_unlock_irqrestore(&qedi->io_trace_lock, flags);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
qedi_dbg_io_trace_open(struct inode *inode, struct file *file)
|
|
{
|
|
struct qedi_dbg_ctx *qedi_dbg = inode->i_private;
|
|
struct qedi_ctx *qedi = container_of(qedi_dbg, struct qedi_ctx,
|
|
dbg_ctx);
|
|
|
|
return single_open(file, qedi_io_trace_show, qedi);
|
|
}
|
|
|
|
const struct file_operations qedi_dbg_fops[] = {
|
|
qedi_dbg_fileops_seq(qedi, gbl_ctx),
|
|
qedi_dbg_fileops(qedi, do_not_recover),
|
|
qedi_dbg_fileops_seq(qedi, io_trace),
|
|
{ },
|
|
};
|