1*61d8658bSDupuis, Chad /* 2*61d8658bSDupuis, Chad * QLogic FCoE Offload Driver 3*61d8658bSDupuis, Chad * Copyright (c) 2016 QLogic Corporation 4*61d8658bSDupuis, Chad * 5*61d8658bSDupuis, Chad * This software is available under the terms of the GNU General Public License 6*61d8658bSDupuis, Chad * (GPL) Version 2, available from the file COPYING in the main directory of 7*61d8658bSDupuis, Chad * this source tree. 8*61d8658bSDupuis, Chad */ 9*61d8658bSDupuis, Chad #ifdef CONFIG_DEBUG_FS 10*61d8658bSDupuis, Chad 11*61d8658bSDupuis, Chad #include <linux/uaccess.h> 12*61d8658bSDupuis, Chad #include <linux/debugfs.h> 13*61d8658bSDupuis, Chad #include <linux/module.h> 14*61d8658bSDupuis, Chad 15*61d8658bSDupuis, Chad #include "qedf.h" 16*61d8658bSDupuis, Chad #include "qedf_dbg.h" 17*61d8658bSDupuis, Chad 18*61d8658bSDupuis, Chad static struct dentry *qedf_dbg_root; 19*61d8658bSDupuis, Chad 20*61d8658bSDupuis, Chad /** 21*61d8658bSDupuis, Chad * qedf_dbg_host_init - setup the debugfs file for the pf 22*61d8658bSDupuis, Chad * @pf: the pf that is starting up 23*61d8658bSDupuis, Chad **/ 24*61d8658bSDupuis, Chad void 25*61d8658bSDupuis, Chad qedf_dbg_host_init(struct qedf_dbg_ctx *qedf, 26*61d8658bSDupuis, Chad struct qedf_debugfs_ops *dops, 27*61d8658bSDupuis, Chad struct file_operations *fops) 28*61d8658bSDupuis, Chad { 29*61d8658bSDupuis, Chad char host_dirname[32]; 30*61d8658bSDupuis, Chad struct dentry *file_dentry = NULL; 31*61d8658bSDupuis, Chad 32*61d8658bSDupuis, Chad QEDF_INFO(qedf, QEDF_LOG_DEBUGFS, "Creating debugfs host node\n"); 33*61d8658bSDupuis, Chad /* create pf dir */ 34*61d8658bSDupuis, Chad sprintf(host_dirname, "host%u", qedf->host_no); 35*61d8658bSDupuis, Chad qedf->bdf_dentry = debugfs_create_dir(host_dirname, qedf_dbg_root); 36*61d8658bSDupuis, Chad if (!qedf->bdf_dentry) 37*61d8658bSDupuis, Chad return; 38*61d8658bSDupuis, Chad 39*61d8658bSDupuis, Chad /* create debugfs files */ 40*61d8658bSDupuis, Chad while (dops) { 41*61d8658bSDupuis, Chad if (!(dops->name)) 42*61d8658bSDupuis, Chad break; 43*61d8658bSDupuis, Chad 44*61d8658bSDupuis, Chad file_dentry = debugfs_create_file(dops->name, 0600, 45*61d8658bSDupuis, Chad qedf->bdf_dentry, qedf, 46*61d8658bSDupuis, Chad fops); 47*61d8658bSDupuis, Chad if (!file_dentry) { 48*61d8658bSDupuis, Chad QEDF_INFO(qedf, QEDF_LOG_DEBUGFS, 49*61d8658bSDupuis, Chad "Debugfs entry %s creation failed\n", 50*61d8658bSDupuis, Chad dops->name); 51*61d8658bSDupuis, Chad debugfs_remove_recursive(qedf->bdf_dentry); 52*61d8658bSDupuis, Chad return; 53*61d8658bSDupuis, Chad } 54*61d8658bSDupuis, Chad dops++; 55*61d8658bSDupuis, Chad fops++; 56*61d8658bSDupuis, Chad } 57*61d8658bSDupuis, Chad } 58*61d8658bSDupuis, Chad 59*61d8658bSDupuis, Chad /** 60*61d8658bSDupuis, Chad * qedf_dbg_host_exit - clear out the pf's debugfs entries 61*61d8658bSDupuis, Chad * @pf: the pf that is stopping 62*61d8658bSDupuis, Chad **/ 63*61d8658bSDupuis, Chad void 64*61d8658bSDupuis, Chad qedf_dbg_host_exit(struct qedf_dbg_ctx *qedf) 65*61d8658bSDupuis, Chad { 66*61d8658bSDupuis, Chad QEDF_INFO(qedf, QEDF_LOG_DEBUGFS, "Destroying debugfs host " 67*61d8658bSDupuis, Chad "entry\n"); 68*61d8658bSDupuis, Chad /* remove debugfs entries of this PF */ 69*61d8658bSDupuis, Chad debugfs_remove_recursive(qedf->bdf_dentry); 70*61d8658bSDupuis, Chad qedf->bdf_dentry = NULL; 71*61d8658bSDupuis, Chad } 72*61d8658bSDupuis, Chad 73*61d8658bSDupuis, Chad /** 74*61d8658bSDupuis, Chad * qedf_dbg_init - start up debugfs for the driver 75*61d8658bSDupuis, Chad **/ 76*61d8658bSDupuis, Chad void 77*61d8658bSDupuis, Chad qedf_dbg_init(char *drv_name) 78*61d8658bSDupuis, Chad { 79*61d8658bSDupuis, Chad QEDF_INFO(NULL, QEDF_LOG_DEBUGFS, "Creating debugfs root node\n"); 80*61d8658bSDupuis, Chad 81*61d8658bSDupuis, Chad /* create qed dir in root of debugfs. NULL means debugfs root */ 82*61d8658bSDupuis, Chad qedf_dbg_root = debugfs_create_dir(drv_name, NULL); 83*61d8658bSDupuis, Chad if (!qedf_dbg_root) 84*61d8658bSDupuis, Chad QEDF_INFO(NULL, QEDF_LOG_DEBUGFS, "Init of debugfs " 85*61d8658bSDupuis, Chad "failed\n"); 86*61d8658bSDupuis, Chad } 87*61d8658bSDupuis, Chad 88*61d8658bSDupuis, Chad /** 89*61d8658bSDupuis, Chad * qedf_dbg_exit - clean out the driver's debugfs entries 90*61d8658bSDupuis, Chad **/ 91*61d8658bSDupuis, Chad void 92*61d8658bSDupuis, Chad qedf_dbg_exit(void) 93*61d8658bSDupuis, Chad { 94*61d8658bSDupuis, Chad QEDF_INFO(NULL, QEDF_LOG_DEBUGFS, "Destroying debugfs root " 95*61d8658bSDupuis, Chad "entry\n"); 96*61d8658bSDupuis, Chad 97*61d8658bSDupuis, Chad /* remove qed dir in root of debugfs */ 98*61d8658bSDupuis, Chad debugfs_remove_recursive(qedf_dbg_root); 99*61d8658bSDupuis, Chad qedf_dbg_root = NULL; 100*61d8658bSDupuis, Chad } 101*61d8658bSDupuis, Chad 102*61d8658bSDupuis, Chad struct qedf_debugfs_ops qedf_debugfs_ops[] = { 103*61d8658bSDupuis, Chad { "fp_int", NULL }, 104*61d8658bSDupuis, Chad { "io_trace", NULL }, 105*61d8658bSDupuis, Chad { "debug", NULL }, 106*61d8658bSDupuis, Chad { "stop_io_on_error", NULL}, 107*61d8658bSDupuis, Chad { "driver_stats", NULL}, 108*61d8658bSDupuis, Chad { "clear_stats", NULL}, 109*61d8658bSDupuis, Chad { "offload_stats", NULL}, 110*61d8658bSDupuis, Chad /* This must be last */ 111*61d8658bSDupuis, Chad { NULL, NULL } 112*61d8658bSDupuis, Chad }; 113*61d8658bSDupuis, Chad 114*61d8658bSDupuis, Chad DECLARE_PER_CPU(struct qedf_percpu_iothread_s, qedf_percpu_iothreads); 115*61d8658bSDupuis, Chad 116*61d8658bSDupuis, Chad static ssize_t 117*61d8658bSDupuis, Chad qedf_dbg_fp_int_cmd_read(struct file *filp, char __user *buffer, size_t count, 118*61d8658bSDupuis, Chad loff_t *ppos) 119*61d8658bSDupuis, Chad { 120*61d8658bSDupuis, Chad size_t cnt = 0; 121*61d8658bSDupuis, Chad int id; 122*61d8658bSDupuis, Chad struct qedf_fastpath *fp = NULL; 123*61d8658bSDupuis, Chad struct qedf_dbg_ctx *qedf_dbg = 124*61d8658bSDupuis, Chad (struct qedf_dbg_ctx *)filp->private_data; 125*61d8658bSDupuis, Chad struct qedf_ctx *qedf = container_of(qedf_dbg, 126*61d8658bSDupuis, Chad struct qedf_ctx, dbg_ctx); 127*61d8658bSDupuis, Chad 128*61d8658bSDupuis, Chad QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "entered\n"); 129*61d8658bSDupuis, Chad 130*61d8658bSDupuis, Chad cnt = sprintf(buffer, "\nFastpath I/O completions\n\n"); 131*61d8658bSDupuis, Chad 132*61d8658bSDupuis, Chad for (id = 0; id < qedf->num_queues; id++) { 133*61d8658bSDupuis, Chad fp = &(qedf->fp_array[id]); 134*61d8658bSDupuis, Chad if (fp->sb_id == QEDF_SB_ID_NULL) 135*61d8658bSDupuis, Chad continue; 136*61d8658bSDupuis, Chad cnt += sprintf((buffer + cnt), "#%d: %lu\n", id, 137*61d8658bSDupuis, Chad fp->completions); 138*61d8658bSDupuis, Chad } 139*61d8658bSDupuis, Chad 140*61d8658bSDupuis, Chad cnt = min_t(int, count, cnt - *ppos); 141*61d8658bSDupuis, Chad *ppos += cnt; 142*61d8658bSDupuis, Chad return cnt; 143*61d8658bSDupuis, Chad } 144*61d8658bSDupuis, Chad 145*61d8658bSDupuis, Chad static ssize_t 146*61d8658bSDupuis, Chad qedf_dbg_fp_int_cmd_write(struct file *filp, const char __user *buffer, 147*61d8658bSDupuis, Chad size_t count, loff_t *ppos) 148*61d8658bSDupuis, Chad { 149*61d8658bSDupuis, Chad if (!count || *ppos) 150*61d8658bSDupuis, Chad return 0; 151*61d8658bSDupuis, Chad 152*61d8658bSDupuis, Chad return count; 153*61d8658bSDupuis, Chad } 154*61d8658bSDupuis, Chad 155*61d8658bSDupuis, Chad static ssize_t 156*61d8658bSDupuis, Chad qedf_dbg_debug_cmd_read(struct file *filp, char __user *buffer, size_t count, 157*61d8658bSDupuis, Chad loff_t *ppos) 158*61d8658bSDupuis, Chad { 159*61d8658bSDupuis, Chad int cnt; 160*61d8658bSDupuis, Chad struct qedf_dbg_ctx *qedf = 161*61d8658bSDupuis, Chad (struct qedf_dbg_ctx *)filp->private_data; 162*61d8658bSDupuis, Chad 163*61d8658bSDupuis, Chad QEDF_INFO(qedf, QEDF_LOG_DEBUGFS, "entered\n"); 164*61d8658bSDupuis, Chad cnt = sprintf(buffer, "debug mask = 0x%x\n", qedf_debug); 165*61d8658bSDupuis, Chad 166*61d8658bSDupuis, Chad cnt = min_t(int, count, cnt - *ppos); 167*61d8658bSDupuis, Chad *ppos += cnt; 168*61d8658bSDupuis, Chad return cnt; 169*61d8658bSDupuis, Chad } 170*61d8658bSDupuis, Chad 171*61d8658bSDupuis, Chad static ssize_t 172*61d8658bSDupuis, Chad qedf_dbg_debug_cmd_write(struct file *filp, const char __user *buffer, 173*61d8658bSDupuis, Chad size_t count, loff_t *ppos) 174*61d8658bSDupuis, Chad { 175*61d8658bSDupuis, Chad uint32_t val; 176*61d8658bSDupuis, Chad void *kern_buf; 177*61d8658bSDupuis, Chad int rval; 178*61d8658bSDupuis, Chad struct qedf_dbg_ctx *qedf = 179*61d8658bSDupuis, Chad (struct qedf_dbg_ctx *)filp->private_data; 180*61d8658bSDupuis, Chad 181*61d8658bSDupuis, Chad if (!count || *ppos) 182*61d8658bSDupuis, Chad return 0; 183*61d8658bSDupuis, Chad 184*61d8658bSDupuis, Chad kern_buf = memdup_user(buffer, count); 185*61d8658bSDupuis, Chad if (IS_ERR(kern_buf)) 186*61d8658bSDupuis, Chad return PTR_ERR(kern_buf); 187*61d8658bSDupuis, Chad 188*61d8658bSDupuis, Chad rval = kstrtouint(kern_buf, 10, &val); 189*61d8658bSDupuis, Chad kfree(kern_buf); 190*61d8658bSDupuis, Chad if (rval) 191*61d8658bSDupuis, Chad return rval; 192*61d8658bSDupuis, Chad 193*61d8658bSDupuis, Chad if (val == 1) 194*61d8658bSDupuis, Chad qedf_debug = QEDF_DEFAULT_LOG_MASK; 195*61d8658bSDupuis, Chad else 196*61d8658bSDupuis, Chad qedf_debug = val; 197*61d8658bSDupuis, Chad 198*61d8658bSDupuis, Chad QEDF_INFO(qedf, QEDF_LOG_DEBUGFS, "Setting debug=0x%x.\n", val); 199*61d8658bSDupuis, Chad return count; 200*61d8658bSDupuis, Chad } 201*61d8658bSDupuis, Chad 202*61d8658bSDupuis, Chad static ssize_t 203*61d8658bSDupuis, Chad qedf_dbg_stop_io_on_error_cmd_read(struct file *filp, char __user *buffer, 204*61d8658bSDupuis, Chad size_t count, loff_t *ppos) 205*61d8658bSDupuis, Chad { 206*61d8658bSDupuis, Chad int cnt; 207*61d8658bSDupuis, Chad struct qedf_dbg_ctx *qedf_dbg = 208*61d8658bSDupuis, Chad (struct qedf_dbg_ctx *)filp->private_data; 209*61d8658bSDupuis, Chad struct qedf_ctx *qedf = container_of(qedf_dbg, 210*61d8658bSDupuis, Chad struct qedf_ctx, dbg_ctx); 211*61d8658bSDupuis, Chad 212*61d8658bSDupuis, Chad QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "entered\n"); 213*61d8658bSDupuis, Chad cnt = sprintf(buffer, "%s\n", 214*61d8658bSDupuis, Chad qedf->stop_io_on_error ? "true" : "false"); 215*61d8658bSDupuis, Chad 216*61d8658bSDupuis, Chad cnt = min_t(int, count, cnt - *ppos); 217*61d8658bSDupuis, Chad *ppos += cnt; 218*61d8658bSDupuis, Chad return cnt; 219*61d8658bSDupuis, Chad } 220*61d8658bSDupuis, Chad 221*61d8658bSDupuis, Chad static ssize_t 222*61d8658bSDupuis, Chad qedf_dbg_stop_io_on_error_cmd_write(struct file *filp, 223*61d8658bSDupuis, Chad const char __user *buffer, size_t count, 224*61d8658bSDupuis, Chad loff_t *ppos) 225*61d8658bSDupuis, Chad { 226*61d8658bSDupuis, Chad void *kern_buf; 227*61d8658bSDupuis, Chad struct qedf_dbg_ctx *qedf_dbg = 228*61d8658bSDupuis, Chad (struct qedf_dbg_ctx *)filp->private_data; 229*61d8658bSDupuis, Chad struct qedf_ctx *qedf = container_of(qedf_dbg, struct qedf_ctx, 230*61d8658bSDupuis, Chad dbg_ctx); 231*61d8658bSDupuis, Chad 232*61d8658bSDupuis, Chad QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "entered\n"); 233*61d8658bSDupuis, Chad 234*61d8658bSDupuis, Chad if (!count || *ppos) 235*61d8658bSDupuis, Chad return 0; 236*61d8658bSDupuis, Chad 237*61d8658bSDupuis, Chad kern_buf = memdup_user(buffer, 6); 238*61d8658bSDupuis, Chad if (IS_ERR(kern_buf)) 239*61d8658bSDupuis, Chad return PTR_ERR(kern_buf); 240*61d8658bSDupuis, Chad 241*61d8658bSDupuis, Chad if (strncmp(kern_buf, "false", 5) == 0) 242*61d8658bSDupuis, Chad qedf->stop_io_on_error = false; 243*61d8658bSDupuis, Chad else if (strncmp(kern_buf, "true", 4) == 0) 244*61d8658bSDupuis, Chad qedf->stop_io_on_error = true; 245*61d8658bSDupuis, Chad else if (strncmp(kern_buf, "now", 3) == 0) 246*61d8658bSDupuis, Chad /* Trigger from user to stop all I/O on this host */ 247*61d8658bSDupuis, Chad set_bit(QEDF_DBG_STOP_IO, &qedf->flags); 248*61d8658bSDupuis, Chad 249*61d8658bSDupuis, Chad kfree(kern_buf); 250*61d8658bSDupuis, Chad return count; 251*61d8658bSDupuis, Chad } 252*61d8658bSDupuis, Chad 253*61d8658bSDupuis, Chad static int 254*61d8658bSDupuis, Chad qedf_io_trace_show(struct seq_file *s, void *unused) 255*61d8658bSDupuis, Chad { 256*61d8658bSDupuis, Chad int i, idx = 0; 257*61d8658bSDupuis, Chad struct qedf_ctx *qedf = s->private; 258*61d8658bSDupuis, Chad struct qedf_dbg_ctx *qedf_dbg = &qedf->dbg_ctx; 259*61d8658bSDupuis, Chad struct qedf_io_log *io_log; 260*61d8658bSDupuis, Chad unsigned long flags; 261*61d8658bSDupuis, Chad 262*61d8658bSDupuis, Chad if (!qedf_io_tracing) { 263*61d8658bSDupuis, Chad seq_puts(s, "I/O tracing not enabled.\n"); 264*61d8658bSDupuis, Chad goto out; 265*61d8658bSDupuis, Chad } 266*61d8658bSDupuis, Chad 267*61d8658bSDupuis, Chad QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "entered\n"); 268*61d8658bSDupuis, Chad 269*61d8658bSDupuis, Chad spin_lock_irqsave(&qedf->io_trace_lock, flags); 270*61d8658bSDupuis, Chad idx = qedf->io_trace_idx; 271*61d8658bSDupuis, Chad for (i = 0; i < QEDF_IO_TRACE_SIZE; i++) { 272*61d8658bSDupuis, Chad io_log = &qedf->io_trace_buf[idx]; 273*61d8658bSDupuis, Chad seq_printf(s, "%d:", io_log->direction); 274*61d8658bSDupuis, Chad seq_printf(s, "0x%x:", io_log->task_id); 275*61d8658bSDupuis, Chad seq_printf(s, "0x%06x:", io_log->port_id); 276*61d8658bSDupuis, Chad seq_printf(s, "%d:", io_log->lun); 277*61d8658bSDupuis, Chad seq_printf(s, "0x%02x:", io_log->op); 278*61d8658bSDupuis, Chad seq_printf(s, "0x%02x%02x%02x%02x:", io_log->lba[0], 279*61d8658bSDupuis, Chad io_log->lba[1], io_log->lba[2], io_log->lba[3]); 280*61d8658bSDupuis, Chad seq_printf(s, "%d:", io_log->bufflen); 281*61d8658bSDupuis, Chad seq_printf(s, "%d:", io_log->sg_count); 282*61d8658bSDupuis, Chad seq_printf(s, "0x%08x:", io_log->result); 283*61d8658bSDupuis, Chad seq_printf(s, "%lu:", io_log->jiffies); 284*61d8658bSDupuis, Chad seq_printf(s, "%d:", io_log->refcount); 285*61d8658bSDupuis, Chad seq_printf(s, "%d:", io_log->req_cpu); 286*61d8658bSDupuis, Chad seq_printf(s, "%d:", io_log->int_cpu); 287*61d8658bSDupuis, Chad seq_printf(s, "%d:", io_log->rsp_cpu); 288*61d8658bSDupuis, Chad seq_printf(s, "%d\n", io_log->sge_type); 289*61d8658bSDupuis, Chad 290*61d8658bSDupuis, Chad idx++; 291*61d8658bSDupuis, Chad if (idx == QEDF_IO_TRACE_SIZE) 292*61d8658bSDupuis, Chad idx = 0; 293*61d8658bSDupuis, Chad } 294*61d8658bSDupuis, Chad spin_unlock_irqrestore(&qedf->io_trace_lock, flags); 295*61d8658bSDupuis, Chad 296*61d8658bSDupuis, Chad out: 297*61d8658bSDupuis, Chad return 0; 298*61d8658bSDupuis, Chad } 299*61d8658bSDupuis, Chad 300*61d8658bSDupuis, Chad static int 301*61d8658bSDupuis, Chad qedf_dbg_io_trace_open(struct inode *inode, struct file *file) 302*61d8658bSDupuis, Chad { 303*61d8658bSDupuis, Chad struct qedf_dbg_ctx *qedf_dbg = inode->i_private; 304*61d8658bSDupuis, Chad struct qedf_ctx *qedf = container_of(qedf_dbg, 305*61d8658bSDupuis, Chad struct qedf_ctx, dbg_ctx); 306*61d8658bSDupuis, Chad 307*61d8658bSDupuis, Chad return single_open(file, qedf_io_trace_show, qedf); 308*61d8658bSDupuis, Chad } 309*61d8658bSDupuis, Chad 310*61d8658bSDupuis, Chad static int 311*61d8658bSDupuis, Chad qedf_driver_stats_show(struct seq_file *s, void *unused) 312*61d8658bSDupuis, Chad { 313*61d8658bSDupuis, Chad struct qedf_ctx *qedf = s->private; 314*61d8658bSDupuis, Chad struct qedf_rport *fcport; 315*61d8658bSDupuis, Chad struct fc_rport_priv *rdata; 316*61d8658bSDupuis, Chad 317*61d8658bSDupuis, Chad seq_printf(s, "cmg_mgr free io_reqs: %d\n", 318*61d8658bSDupuis, Chad atomic_read(&qedf->cmd_mgr->free_list_cnt)); 319*61d8658bSDupuis, Chad seq_printf(s, "slow SGEs: %d\n", qedf->slow_sge_ios); 320*61d8658bSDupuis, Chad seq_printf(s, "single SGEs: %d\n", qedf->single_sge_ios); 321*61d8658bSDupuis, Chad seq_printf(s, "fast SGEs: %d\n\n", qedf->fast_sge_ios); 322*61d8658bSDupuis, Chad 323*61d8658bSDupuis, Chad seq_puts(s, "Offloaded ports:\n\n"); 324*61d8658bSDupuis, Chad 325*61d8658bSDupuis, Chad rcu_read_lock(); 326*61d8658bSDupuis, Chad list_for_each_entry_rcu(fcport, &qedf->fcports, peers) { 327*61d8658bSDupuis, Chad rdata = fcport->rdata; 328*61d8658bSDupuis, Chad if (rdata == NULL) 329*61d8658bSDupuis, Chad continue; 330*61d8658bSDupuis, Chad seq_printf(s, "%06x: free_sqes: %d, num_active_ios: %d\n", 331*61d8658bSDupuis, Chad rdata->ids.port_id, atomic_read(&fcport->free_sqes), 332*61d8658bSDupuis, Chad atomic_read(&fcport->num_active_ios)); 333*61d8658bSDupuis, Chad } 334*61d8658bSDupuis, Chad rcu_read_unlock(); 335*61d8658bSDupuis, Chad 336*61d8658bSDupuis, Chad return 0; 337*61d8658bSDupuis, Chad } 338*61d8658bSDupuis, Chad 339*61d8658bSDupuis, Chad static int 340*61d8658bSDupuis, Chad qedf_dbg_driver_stats_open(struct inode *inode, struct file *file) 341*61d8658bSDupuis, Chad { 342*61d8658bSDupuis, Chad struct qedf_dbg_ctx *qedf_dbg = inode->i_private; 343*61d8658bSDupuis, Chad struct qedf_ctx *qedf = container_of(qedf_dbg, 344*61d8658bSDupuis, Chad struct qedf_ctx, dbg_ctx); 345*61d8658bSDupuis, Chad 346*61d8658bSDupuis, Chad return single_open(file, qedf_driver_stats_show, qedf); 347*61d8658bSDupuis, Chad } 348*61d8658bSDupuis, Chad 349*61d8658bSDupuis, Chad static ssize_t 350*61d8658bSDupuis, Chad qedf_dbg_clear_stats_cmd_read(struct file *filp, char __user *buffer, 351*61d8658bSDupuis, Chad size_t count, loff_t *ppos) 352*61d8658bSDupuis, Chad { 353*61d8658bSDupuis, Chad int cnt = 0; 354*61d8658bSDupuis, Chad 355*61d8658bSDupuis, Chad /* Essentially a read stub */ 356*61d8658bSDupuis, Chad cnt = min_t(int, count, cnt - *ppos); 357*61d8658bSDupuis, Chad *ppos += cnt; 358*61d8658bSDupuis, Chad return cnt; 359*61d8658bSDupuis, Chad } 360*61d8658bSDupuis, Chad 361*61d8658bSDupuis, Chad static ssize_t 362*61d8658bSDupuis, Chad qedf_dbg_clear_stats_cmd_write(struct file *filp, 363*61d8658bSDupuis, Chad const char __user *buffer, size_t count, 364*61d8658bSDupuis, Chad loff_t *ppos) 365*61d8658bSDupuis, Chad { 366*61d8658bSDupuis, Chad struct qedf_dbg_ctx *qedf_dbg = 367*61d8658bSDupuis, Chad (struct qedf_dbg_ctx *)filp->private_data; 368*61d8658bSDupuis, Chad struct qedf_ctx *qedf = container_of(qedf_dbg, struct qedf_ctx, 369*61d8658bSDupuis, Chad dbg_ctx); 370*61d8658bSDupuis, Chad 371*61d8658bSDupuis, Chad QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "Clearing stat counters.\n"); 372*61d8658bSDupuis, Chad 373*61d8658bSDupuis, Chad if (!count || *ppos) 374*61d8658bSDupuis, Chad return 0; 375*61d8658bSDupuis, Chad 376*61d8658bSDupuis, Chad /* Clear stat counters exposed by 'stats' node */ 377*61d8658bSDupuis, Chad qedf->slow_sge_ios = 0; 378*61d8658bSDupuis, Chad qedf->single_sge_ios = 0; 379*61d8658bSDupuis, Chad qedf->fast_sge_ios = 0; 380*61d8658bSDupuis, Chad 381*61d8658bSDupuis, Chad return count; 382*61d8658bSDupuis, Chad } 383*61d8658bSDupuis, Chad 384*61d8658bSDupuis, Chad static int 385*61d8658bSDupuis, Chad qedf_offload_stats_show(struct seq_file *s, void *unused) 386*61d8658bSDupuis, Chad { 387*61d8658bSDupuis, Chad struct qedf_ctx *qedf = s->private; 388*61d8658bSDupuis, Chad struct qed_fcoe_stats *fw_fcoe_stats; 389*61d8658bSDupuis, Chad 390*61d8658bSDupuis, Chad fw_fcoe_stats = kmalloc(sizeof(struct qed_fcoe_stats), GFP_KERNEL); 391*61d8658bSDupuis, Chad if (!fw_fcoe_stats) { 392*61d8658bSDupuis, Chad QEDF_ERR(&(qedf->dbg_ctx), "Could not allocate memory for " 393*61d8658bSDupuis, Chad "fw_fcoe_stats.\n"); 394*61d8658bSDupuis, Chad goto out; 395*61d8658bSDupuis, Chad } 396*61d8658bSDupuis, Chad 397*61d8658bSDupuis, Chad /* Query firmware for offload stats */ 398*61d8658bSDupuis, Chad qed_ops->get_stats(qedf->cdev, fw_fcoe_stats); 399*61d8658bSDupuis, Chad 400*61d8658bSDupuis, Chad seq_printf(s, "fcoe_rx_byte_cnt=%llu\n" 401*61d8658bSDupuis, Chad "fcoe_rx_data_pkt_cnt=%llu\n" 402*61d8658bSDupuis, Chad "fcoe_rx_xfer_pkt_cnt=%llu\n" 403*61d8658bSDupuis, Chad "fcoe_rx_other_pkt_cnt=%llu\n" 404*61d8658bSDupuis, Chad "fcoe_silent_drop_pkt_cmdq_full_cnt=%u\n" 405*61d8658bSDupuis, Chad "fcoe_silent_drop_pkt_crc_error_cnt=%u\n" 406*61d8658bSDupuis, Chad "fcoe_silent_drop_pkt_task_invalid_cnt=%u\n" 407*61d8658bSDupuis, Chad "fcoe_silent_drop_total_pkt_cnt=%u\n" 408*61d8658bSDupuis, Chad "fcoe_silent_drop_pkt_rq_full_cnt=%u\n" 409*61d8658bSDupuis, Chad "fcoe_tx_byte_cnt=%llu\n" 410*61d8658bSDupuis, Chad "fcoe_tx_data_pkt_cnt=%llu\n" 411*61d8658bSDupuis, Chad "fcoe_tx_xfer_pkt_cnt=%llu\n" 412*61d8658bSDupuis, Chad "fcoe_tx_other_pkt_cnt=%llu\n", 413*61d8658bSDupuis, Chad fw_fcoe_stats->fcoe_rx_byte_cnt, 414*61d8658bSDupuis, Chad fw_fcoe_stats->fcoe_rx_data_pkt_cnt, 415*61d8658bSDupuis, Chad fw_fcoe_stats->fcoe_rx_xfer_pkt_cnt, 416*61d8658bSDupuis, Chad fw_fcoe_stats->fcoe_rx_other_pkt_cnt, 417*61d8658bSDupuis, Chad fw_fcoe_stats->fcoe_silent_drop_pkt_cmdq_full_cnt, 418*61d8658bSDupuis, Chad fw_fcoe_stats->fcoe_silent_drop_pkt_crc_error_cnt, 419*61d8658bSDupuis, Chad fw_fcoe_stats->fcoe_silent_drop_pkt_task_invalid_cnt, 420*61d8658bSDupuis, Chad fw_fcoe_stats->fcoe_silent_drop_total_pkt_cnt, 421*61d8658bSDupuis, Chad fw_fcoe_stats->fcoe_silent_drop_pkt_rq_full_cnt, 422*61d8658bSDupuis, Chad fw_fcoe_stats->fcoe_tx_byte_cnt, 423*61d8658bSDupuis, Chad fw_fcoe_stats->fcoe_tx_data_pkt_cnt, 424*61d8658bSDupuis, Chad fw_fcoe_stats->fcoe_tx_xfer_pkt_cnt, 425*61d8658bSDupuis, Chad fw_fcoe_stats->fcoe_tx_other_pkt_cnt); 426*61d8658bSDupuis, Chad 427*61d8658bSDupuis, Chad kfree(fw_fcoe_stats); 428*61d8658bSDupuis, Chad out: 429*61d8658bSDupuis, Chad return 0; 430*61d8658bSDupuis, Chad } 431*61d8658bSDupuis, Chad 432*61d8658bSDupuis, Chad static int 433*61d8658bSDupuis, Chad qedf_dbg_offload_stats_open(struct inode *inode, struct file *file) 434*61d8658bSDupuis, Chad { 435*61d8658bSDupuis, Chad struct qedf_dbg_ctx *qedf_dbg = inode->i_private; 436*61d8658bSDupuis, Chad struct qedf_ctx *qedf = container_of(qedf_dbg, 437*61d8658bSDupuis, Chad struct qedf_ctx, dbg_ctx); 438*61d8658bSDupuis, Chad 439*61d8658bSDupuis, Chad return single_open(file, qedf_offload_stats_show, qedf); 440*61d8658bSDupuis, Chad } 441*61d8658bSDupuis, Chad 442*61d8658bSDupuis, Chad 443*61d8658bSDupuis, Chad const struct file_operations qedf_dbg_fops[] = { 444*61d8658bSDupuis, Chad qedf_dbg_fileops(qedf, fp_int), 445*61d8658bSDupuis, Chad qedf_dbg_fileops_seq(qedf, io_trace), 446*61d8658bSDupuis, Chad qedf_dbg_fileops(qedf, debug), 447*61d8658bSDupuis, Chad qedf_dbg_fileops(qedf, stop_io_on_error), 448*61d8658bSDupuis, Chad qedf_dbg_fileops_seq(qedf, driver_stats), 449*61d8658bSDupuis, Chad qedf_dbg_fileops(qedf, clear_stats), 450*61d8658bSDupuis, Chad qedf_dbg_fileops_seq(qedf, offload_stats), 451*61d8658bSDupuis, Chad /* This must be last */ 452*61d8658bSDupuis, Chad { NULL, NULL }, 453*61d8658bSDupuis, Chad }; 454*61d8658bSDupuis, Chad 455*61d8658bSDupuis, Chad #else /* CONFIG_DEBUG_FS */ 456*61d8658bSDupuis, Chad void qedf_dbg_host_init(struct qedf_dbg_ctx *); 457*61d8658bSDupuis, Chad void qedf_dbg_host_exit(struct qedf_dbg_ctx *); 458*61d8658bSDupuis, Chad void qedf_dbg_init(char *); 459*61d8658bSDupuis, Chad void qedf_dbg_exit(void); 460*61d8658bSDupuis, Chad #endif /* CONFIG_DEBUG_FS */ 461