162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * QLogic iSCSI Offload Driver 462306a36Sopenharmony_ci * Copyright (c) 2016 Cavium Inc. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include "qedi.h" 862306a36Sopenharmony_ci#include "qedi_dbg.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/uaccess.h> 1162306a36Sopenharmony_ci#include <linux/debugfs.h> 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ciint qedi_do_not_recover; 1562306a36Sopenharmony_cistatic struct dentry *qedi_dbg_root; 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_civoid 1862306a36Sopenharmony_ciqedi_dbg_host_init(struct qedi_dbg_ctx *qedi, 1962306a36Sopenharmony_ci const struct qedi_debugfs_ops *dops, 2062306a36Sopenharmony_ci const struct file_operations *fops) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci char host_dirname[32]; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci sprintf(host_dirname, "host%u", qedi->host_no); 2562306a36Sopenharmony_ci qedi->bdf_dentry = debugfs_create_dir(host_dirname, qedi_dbg_root); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci while (dops) { 2862306a36Sopenharmony_ci if (!(dops->name)) 2962306a36Sopenharmony_ci break; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci debugfs_create_file(dops->name, 0600, qedi->bdf_dentry, qedi, 3262306a36Sopenharmony_ci fops); 3362306a36Sopenharmony_ci dops++; 3462306a36Sopenharmony_ci fops++; 3562306a36Sopenharmony_ci } 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_civoid 3962306a36Sopenharmony_ciqedi_dbg_host_exit(struct qedi_dbg_ctx *qedi) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci debugfs_remove_recursive(qedi->bdf_dentry); 4262306a36Sopenharmony_ci qedi->bdf_dentry = NULL; 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_civoid 4662306a36Sopenharmony_ciqedi_dbg_init(char *drv_name) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci qedi_dbg_root = debugfs_create_dir(drv_name, NULL); 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_civoid 5262306a36Sopenharmony_ciqedi_dbg_exit(void) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci debugfs_remove_recursive(qedi_dbg_root); 5562306a36Sopenharmony_ci qedi_dbg_root = NULL; 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic ssize_t 5962306a36Sopenharmony_ciqedi_dbg_do_not_recover_enable(struct qedi_dbg_ctx *qedi_dbg) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci if (!qedi_do_not_recover) 6262306a36Sopenharmony_ci qedi_do_not_recover = 1; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci QEDI_INFO(qedi_dbg, QEDI_LOG_DEBUGFS, "do_not_recover=%d\n", 6562306a36Sopenharmony_ci qedi_do_not_recover); 6662306a36Sopenharmony_ci return 0; 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic ssize_t 7062306a36Sopenharmony_ciqedi_dbg_do_not_recover_disable(struct qedi_dbg_ctx *qedi_dbg) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci if (qedi_do_not_recover) 7362306a36Sopenharmony_ci qedi_do_not_recover = 0; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci QEDI_INFO(qedi_dbg, QEDI_LOG_DEBUGFS, "do_not_recover=%d\n", 7662306a36Sopenharmony_ci qedi_do_not_recover); 7762306a36Sopenharmony_ci return 0; 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic struct qedi_list_of_funcs qedi_dbg_do_not_recover_ops[] = { 8162306a36Sopenharmony_ci { "enable", qedi_dbg_do_not_recover_enable }, 8262306a36Sopenharmony_ci { "disable", qedi_dbg_do_not_recover_disable }, 8362306a36Sopenharmony_ci { NULL, NULL } 8462306a36Sopenharmony_ci}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ciconst struct qedi_debugfs_ops qedi_debugfs_ops[] = { 8762306a36Sopenharmony_ci { "gbl_ctx", NULL }, 8862306a36Sopenharmony_ci { "do_not_recover", qedi_dbg_do_not_recover_ops}, 8962306a36Sopenharmony_ci { "io_trace", NULL }, 9062306a36Sopenharmony_ci { NULL, NULL } 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic ssize_t 9462306a36Sopenharmony_ciqedi_dbg_do_not_recover_cmd_write(struct file *filp, const char __user *buffer, 9562306a36Sopenharmony_ci size_t count, loff_t *ppos) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci size_t cnt = 0; 9862306a36Sopenharmony_ci struct qedi_dbg_ctx *qedi_dbg = 9962306a36Sopenharmony_ci (struct qedi_dbg_ctx *)filp->private_data; 10062306a36Sopenharmony_ci struct qedi_list_of_funcs *lof = qedi_dbg_do_not_recover_ops; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci if (*ppos) 10362306a36Sopenharmony_ci return 0; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci while (lof) { 10662306a36Sopenharmony_ci if (!(lof->oper_str)) 10762306a36Sopenharmony_ci break; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci if (!strncmp(lof->oper_str, buffer, strlen(lof->oper_str))) { 11062306a36Sopenharmony_ci cnt = lof->oper_func(qedi_dbg); 11162306a36Sopenharmony_ci break; 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci lof++; 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci return (count - cnt); 11762306a36Sopenharmony_ci} 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic ssize_t 12062306a36Sopenharmony_ciqedi_dbg_do_not_recover_cmd_read(struct file *filp, char __user *buffer, 12162306a36Sopenharmony_ci size_t count, loff_t *ppos) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci size_t cnt = 0; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci if (*ppos) 12662306a36Sopenharmony_ci return 0; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci cnt = sprintf(buffer, "do_not_recover=%d\n", qedi_do_not_recover); 12962306a36Sopenharmony_ci cnt = min_t(int, count, cnt - *ppos); 13062306a36Sopenharmony_ci *ppos += cnt; 13162306a36Sopenharmony_ci return cnt; 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic int 13562306a36Sopenharmony_ciqedi_gbl_ctx_show(struct seq_file *s, void *unused) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci struct qedi_fastpath *fp = NULL; 13862306a36Sopenharmony_ci struct qed_sb_info *sb_info = NULL; 13962306a36Sopenharmony_ci struct status_block *sb = NULL; 14062306a36Sopenharmony_ci struct global_queue *que = NULL; 14162306a36Sopenharmony_ci int id; 14262306a36Sopenharmony_ci u16 prod_idx; 14362306a36Sopenharmony_ci struct qedi_ctx *qedi = s->private; 14462306a36Sopenharmony_ci unsigned long flags; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci seq_puts(s, " DUMP CQ CONTEXT:\n"); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci for (id = 0; id < MIN_NUM_CPUS_MSIX(qedi); id++) { 14962306a36Sopenharmony_ci spin_lock_irqsave(&qedi->hba_lock, flags); 15062306a36Sopenharmony_ci seq_printf(s, "=========FAST CQ PATH [%d] ==========\n", id); 15162306a36Sopenharmony_ci fp = &qedi->fp_array[id]; 15262306a36Sopenharmony_ci sb_info = fp->sb_info; 15362306a36Sopenharmony_ci sb = sb_info->sb_virt; 15462306a36Sopenharmony_ci prod_idx = (sb->pi_array[QEDI_PROTO_CQ_PROD_IDX] & 15562306a36Sopenharmony_ci STATUS_BLOCK_PROD_INDEX_MASK); 15662306a36Sopenharmony_ci seq_printf(s, "SB PROD IDX: %d\n", prod_idx); 15762306a36Sopenharmony_ci que = qedi->global_queues[fp->sb_id]; 15862306a36Sopenharmony_ci seq_printf(s, "DRV CONS IDX: %d\n", que->cq_cons_idx); 15962306a36Sopenharmony_ci seq_printf(s, "CQ complete host memory: %d\n", fp->sb_id); 16062306a36Sopenharmony_ci seq_puts(s, "=========== END ==================\n\n\n"); 16162306a36Sopenharmony_ci spin_unlock_irqrestore(&qedi->hba_lock, flags); 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci return 0; 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_cistatic int 16762306a36Sopenharmony_ciqedi_dbg_gbl_ctx_open(struct inode *inode, struct file *file) 16862306a36Sopenharmony_ci{ 16962306a36Sopenharmony_ci struct qedi_dbg_ctx *qedi_dbg = inode->i_private; 17062306a36Sopenharmony_ci struct qedi_ctx *qedi = container_of(qedi_dbg, struct qedi_ctx, 17162306a36Sopenharmony_ci dbg_ctx); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci return single_open(file, qedi_gbl_ctx_show, qedi); 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic int 17762306a36Sopenharmony_ciqedi_io_trace_show(struct seq_file *s, void *unused) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci int id, idx = 0; 18062306a36Sopenharmony_ci struct qedi_ctx *qedi = s->private; 18162306a36Sopenharmony_ci struct qedi_io_log *io_log; 18262306a36Sopenharmony_ci unsigned long flags; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci seq_puts(s, " DUMP IO LOGS:\n"); 18562306a36Sopenharmony_ci spin_lock_irqsave(&qedi->io_trace_lock, flags); 18662306a36Sopenharmony_ci idx = qedi->io_trace_idx; 18762306a36Sopenharmony_ci for (id = 0; id < QEDI_IO_TRACE_SIZE; id++) { 18862306a36Sopenharmony_ci io_log = &qedi->io_trace_buf[idx]; 18962306a36Sopenharmony_ci seq_printf(s, "iodir-%d:", io_log->direction); 19062306a36Sopenharmony_ci seq_printf(s, "tid-0x%x:", io_log->task_id); 19162306a36Sopenharmony_ci seq_printf(s, "cid-0x%x:", io_log->cid); 19262306a36Sopenharmony_ci seq_printf(s, "lun-%d:", io_log->lun); 19362306a36Sopenharmony_ci seq_printf(s, "op-0x%02x:", io_log->op); 19462306a36Sopenharmony_ci seq_printf(s, "0x%02x%02x%02x%02x:", io_log->lba[0], 19562306a36Sopenharmony_ci io_log->lba[1], io_log->lba[2], io_log->lba[3]); 19662306a36Sopenharmony_ci seq_printf(s, "buflen-%d:", io_log->bufflen); 19762306a36Sopenharmony_ci seq_printf(s, "sgcnt-%d:", io_log->sg_count); 19862306a36Sopenharmony_ci seq_printf(s, "res-0x%08x:", io_log->result); 19962306a36Sopenharmony_ci seq_printf(s, "jif-%lu:", io_log->jiffies); 20062306a36Sopenharmony_ci seq_printf(s, "blk_req_cpu-%d:", io_log->blk_req_cpu); 20162306a36Sopenharmony_ci seq_printf(s, "req_cpu-%d:", io_log->req_cpu); 20262306a36Sopenharmony_ci seq_printf(s, "intr_cpu-%d:", io_log->intr_cpu); 20362306a36Sopenharmony_ci seq_printf(s, "blk_rsp_cpu-%d\n", io_log->blk_rsp_cpu); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci idx++; 20662306a36Sopenharmony_ci if (idx == QEDI_IO_TRACE_SIZE) 20762306a36Sopenharmony_ci idx = 0; 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci spin_unlock_irqrestore(&qedi->io_trace_lock, flags); 21062306a36Sopenharmony_ci return 0; 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_cistatic int 21462306a36Sopenharmony_ciqedi_dbg_io_trace_open(struct inode *inode, struct file *file) 21562306a36Sopenharmony_ci{ 21662306a36Sopenharmony_ci struct qedi_dbg_ctx *qedi_dbg = inode->i_private; 21762306a36Sopenharmony_ci struct qedi_ctx *qedi = container_of(qedi_dbg, struct qedi_ctx, 21862306a36Sopenharmony_ci dbg_ctx); 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci return single_open(file, qedi_io_trace_show, qedi); 22162306a36Sopenharmony_ci} 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ciconst struct file_operations qedi_dbg_fops[] = { 22462306a36Sopenharmony_ci qedi_dbg_fileops_seq(qedi, gbl_ctx), 22562306a36Sopenharmony_ci qedi_dbg_fileops(qedi, do_not_recover), 22662306a36Sopenharmony_ci qedi_dbg_fileops_seq(qedi, io_trace), 22762306a36Sopenharmony_ci { }, 22862306a36Sopenharmony_ci}; 229