18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2012 Cisco Systems, Inc. All rights reserved. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This program is free software; you may redistribute it and/or modify 58c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License as published by 68c2ecf20Sopenharmony_ci * the Free Software Foundation; version 2 of the License. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 98c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 108c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 118c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 128c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 138c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 148c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 158c2ecf20Sopenharmony_ci * SOFTWARE. 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <linux/module.h> 198c2ecf20Sopenharmony_ci#include <linux/errno.h> 208c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 218c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 228c2ecf20Sopenharmony_ci#include "fnic.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistatic struct dentry *fnic_trace_debugfs_root; 258c2ecf20Sopenharmony_cistatic struct dentry *fnic_trace_debugfs_file; 268c2ecf20Sopenharmony_cistatic struct dentry *fnic_trace_enable; 278c2ecf20Sopenharmony_cistatic struct dentry *fnic_stats_debugfs_root; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic struct dentry *fnic_fc_trace_debugfs_file; 308c2ecf20Sopenharmony_cistatic struct dentry *fnic_fc_rdata_trace_debugfs_file; 318c2ecf20Sopenharmony_cistatic struct dentry *fnic_fc_trace_enable; 328c2ecf20Sopenharmony_cistatic struct dentry *fnic_fc_trace_clear; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistruct fc_trace_flag_type { 358c2ecf20Sopenharmony_ci u8 fc_row_file; 368c2ecf20Sopenharmony_ci u8 fc_normal_file; 378c2ecf20Sopenharmony_ci u8 fnic_trace; 388c2ecf20Sopenharmony_ci u8 fc_trace; 398c2ecf20Sopenharmony_ci u8 fc_clear; 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic struct fc_trace_flag_type *fc_trc_flag; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/* 458c2ecf20Sopenharmony_ci * fnic_debugfs_init - Initialize debugfs for fnic debug logging 468c2ecf20Sopenharmony_ci * 478c2ecf20Sopenharmony_ci * Description: 488c2ecf20Sopenharmony_ci * When Debugfs is configured this routine sets up the fnic debugfs 498c2ecf20Sopenharmony_ci * file system. If not already created, this routine will create the 508c2ecf20Sopenharmony_ci * fnic directory and statistics directory for trace buffer and 518c2ecf20Sopenharmony_ci * stats logging. 528c2ecf20Sopenharmony_ci */ 538c2ecf20Sopenharmony_ciint fnic_debugfs_init(void) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci fnic_trace_debugfs_root = debugfs_create_dir("fnic", NULL); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci fnic_stats_debugfs_root = debugfs_create_dir("statistics", 588c2ecf20Sopenharmony_ci fnic_trace_debugfs_root); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci /* Allocate memory to structure */ 618c2ecf20Sopenharmony_ci fc_trc_flag = (struct fc_trace_flag_type *) 628c2ecf20Sopenharmony_ci vmalloc(sizeof(struct fc_trace_flag_type)); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci if (fc_trc_flag) { 658c2ecf20Sopenharmony_ci fc_trc_flag->fc_row_file = 0; 668c2ecf20Sopenharmony_ci fc_trc_flag->fc_normal_file = 1; 678c2ecf20Sopenharmony_ci fc_trc_flag->fnic_trace = 2; 688c2ecf20Sopenharmony_ci fc_trc_flag->fc_trace = 3; 698c2ecf20Sopenharmony_ci fc_trc_flag->fc_clear = 4; 708c2ecf20Sopenharmony_ci return 0; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci return -ENOMEM; 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci/* 778c2ecf20Sopenharmony_ci * fnic_debugfs_terminate - Tear down debugfs infrastructure 788c2ecf20Sopenharmony_ci * 798c2ecf20Sopenharmony_ci * Description: 808c2ecf20Sopenharmony_ci * When Debugfs is configured this routine removes debugfs file system 818c2ecf20Sopenharmony_ci * elements that are specific to fnic. 828c2ecf20Sopenharmony_ci */ 838c2ecf20Sopenharmony_civoid fnic_debugfs_terminate(void) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci debugfs_remove(fnic_stats_debugfs_root); 868c2ecf20Sopenharmony_ci fnic_stats_debugfs_root = NULL; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci debugfs_remove(fnic_trace_debugfs_root); 898c2ecf20Sopenharmony_ci fnic_trace_debugfs_root = NULL; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci if (fc_trc_flag) 928c2ecf20Sopenharmony_ci vfree(fc_trc_flag); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/* 968c2ecf20Sopenharmony_ci * fnic_trace_ctrl_read - 978c2ecf20Sopenharmony_ci * Read trace_enable ,fc_trace_enable 988c2ecf20Sopenharmony_ci * or fc_trace_clear debugfs file 998c2ecf20Sopenharmony_ci * @filp: The file pointer to read from. 1008c2ecf20Sopenharmony_ci * @ubuf: The buffer to copy the data to. 1018c2ecf20Sopenharmony_ci * @cnt: The number of bytes to read. 1028c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 1038c2ecf20Sopenharmony_ci * 1048c2ecf20Sopenharmony_ci * Description: 1058c2ecf20Sopenharmony_ci * This routine reads value of variable fnic_tracing_enabled or 1068c2ecf20Sopenharmony_ci * fnic_fc_tracing_enabled or fnic_fc_trace_cleared 1078c2ecf20Sopenharmony_ci * and stores into local @buf. 1088c2ecf20Sopenharmony_ci * It will start reading file at @ppos and 1098c2ecf20Sopenharmony_ci * copy up to @cnt of data to @ubuf from @buf. 1108c2ecf20Sopenharmony_ci * 1118c2ecf20Sopenharmony_ci * Returns: 1128c2ecf20Sopenharmony_ci * This function returns the amount of data that was read. 1138c2ecf20Sopenharmony_ci */ 1148c2ecf20Sopenharmony_cistatic ssize_t fnic_trace_ctrl_read(struct file *filp, 1158c2ecf20Sopenharmony_ci char __user *ubuf, 1168c2ecf20Sopenharmony_ci size_t cnt, loff_t *ppos) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci char buf[64]; 1198c2ecf20Sopenharmony_ci int len; 1208c2ecf20Sopenharmony_ci u8 *trace_type; 1218c2ecf20Sopenharmony_ci len = 0; 1228c2ecf20Sopenharmony_ci trace_type = (u8 *)filp->private_data; 1238c2ecf20Sopenharmony_ci if (*trace_type == fc_trc_flag->fnic_trace) 1248c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", fnic_tracing_enabled); 1258c2ecf20Sopenharmony_ci else if (*trace_type == fc_trc_flag->fc_trace) 1268c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", fnic_fc_tracing_enabled); 1278c2ecf20Sopenharmony_ci else if (*trace_type == fc_trc_flag->fc_clear) 1288c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", fnic_fc_trace_cleared); 1298c2ecf20Sopenharmony_ci else 1308c2ecf20Sopenharmony_ci pr_err("fnic: Cannot read to any debugfs file\n"); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci return simple_read_from_buffer(ubuf, cnt, ppos, buf, len); 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci/* 1368c2ecf20Sopenharmony_ci * fnic_trace_ctrl_write - 1378c2ecf20Sopenharmony_ci * Write to trace_enable, fc_trace_enable or 1388c2ecf20Sopenharmony_ci * fc_trace_clear debugfs file 1398c2ecf20Sopenharmony_ci * @filp: The file pointer to write from. 1408c2ecf20Sopenharmony_ci * @ubuf: The buffer to copy the data from. 1418c2ecf20Sopenharmony_ci * @cnt: The number of bytes to write. 1428c2ecf20Sopenharmony_ci * @ppos: The position in the file to start writing to. 1438c2ecf20Sopenharmony_ci * 1448c2ecf20Sopenharmony_ci * Description: 1458c2ecf20Sopenharmony_ci * This routine writes data from user buffer @ubuf to buffer @buf and 1468c2ecf20Sopenharmony_ci * sets fc_trace_enable ,tracing_enable or fnic_fc_trace_cleared 1478c2ecf20Sopenharmony_ci * value as per user input. 1488c2ecf20Sopenharmony_ci * 1498c2ecf20Sopenharmony_ci * Returns: 1508c2ecf20Sopenharmony_ci * This function returns the amount of data that was written. 1518c2ecf20Sopenharmony_ci */ 1528c2ecf20Sopenharmony_cistatic ssize_t fnic_trace_ctrl_write(struct file *filp, 1538c2ecf20Sopenharmony_ci const char __user *ubuf, 1548c2ecf20Sopenharmony_ci size_t cnt, loff_t *ppos) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci char buf[64]; 1578c2ecf20Sopenharmony_ci unsigned long val; 1588c2ecf20Sopenharmony_ci int ret; 1598c2ecf20Sopenharmony_ci u8 *trace_type; 1608c2ecf20Sopenharmony_ci trace_type = (u8 *)filp->private_data; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (cnt >= sizeof(buf)) 1638c2ecf20Sopenharmony_ci return -EINVAL; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci if (copy_from_user(&buf, ubuf, cnt)) 1668c2ecf20Sopenharmony_ci return -EFAULT; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci buf[cnt] = 0; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci ret = kstrtoul(buf, 10, &val); 1718c2ecf20Sopenharmony_ci if (ret < 0) 1728c2ecf20Sopenharmony_ci return ret; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci if (*trace_type == fc_trc_flag->fnic_trace) 1758c2ecf20Sopenharmony_ci fnic_tracing_enabled = val; 1768c2ecf20Sopenharmony_ci else if (*trace_type == fc_trc_flag->fc_trace) 1778c2ecf20Sopenharmony_ci fnic_fc_tracing_enabled = val; 1788c2ecf20Sopenharmony_ci else if (*trace_type == fc_trc_flag->fc_clear) 1798c2ecf20Sopenharmony_ci fnic_fc_trace_cleared = val; 1808c2ecf20Sopenharmony_ci else 1818c2ecf20Sopenharmony_ci pr_err("fnic: cannot write to any debugfs file\n"); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci (*ppos)++; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci return cnt; 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic const struct file_operations fnic_trace_ctrl_fops = { 1898c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 1908c2ecf20Sopenharmony_ci .open = simple_open, 1918c2ecf20Sopenharmony_ci .read = fnic_trace_ctrl_read, 1928c2ecf20Sopenharmony_ci .write = fnic_trace_ctrl_write, 1938c2ecf20Sopenharmony_ci}; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci/* 1968c2ecf20Sopenharmony_ci * fnic_trace_debugfs_open - Open the fnic trace log 1978c2ecf20Sopenharmony_ci * @inode: The inode pointer 1988c2ecf20Sopenharmony_ci * @file: The file pointer to attach the log output 1998c2ecf20Sopenharmony_ci * 2008c2ecf20Sopenharmony_ci * Description: 2018c2ecf20Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. 2028c2ecf20Sopenharmony_ci * It allocates the necessary buffer for the log, fills the buffer from 2038c2ecf20Sopenharmony_ci * the in-memory log and then returns a pointer to that log in 2048c2ecf20Sopenharmony_ci * the private_data field in @file. 2058c2ecf20Sopenharmony_ci * 2068c2ecf20Sopenharmony_ci * Returns: 2078c2ecf20Sopenharmony_ci * This function returns zero if successful. On error it will return 2088c2ecf20Sopenharmony_ci * a negative error value. 2098c2ecf20Sopenharmony_ci */ 2108c2ecf20Sopenharmony_cistatic int fnic_trace_debugfs_open(struct inode *inode, 2118c2ecf20Sopenharmony_ci struct file *file) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci fnic_dbgfs_t *fnic_dbg_prt; 2148c2ecf20Sopenharmony_ci u8 *rdata_ptr; 2158c2ecf20Sopenharmony_ci rdata_ptr = (u8 *)inode->i_private; 2168c2ecf20Sopenharmony_ci fnic_dbg_prt = kzalloc(sizeof(fnic_dbgfs_t), GFP_KERNEL); 2178c2ecf20Sopenharmony_ci if (!fnic_dbg_prt) 2188c2ecf20Sopenharmony_ci return -ENOMEM; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci if (*rdata_ptr == fc_trc_flag->fnic_trace) { 2218c2ecf20Sopenharmony_ci fnic_dbg_prt->buffer = vmalloc(array3_size(3, trace_max_pages, 2228c2ecf20Sopenharmony_ci PAGE_SIZE)); 2238c2ecf20Sopenharmony_ci if (!fnic_dbg_prt->buffer) { 2248c2ecf20Sopenharmony_ci kfree(fnic_dbg_prt); 2258c2ecf20Sopenharmony_ci return -ENOMEM; 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci memset((void *)fnic_dbg_prt->buffer, 0, 2288c2ecf20Sopenharmony_ci 3 * (trace_max_pages * PAGE_SIZE)); 2298c2ecf20Sopenharmony_ci fnic_dbg_prt->buffer_len = fnic_get_trace_data(fnic_dbg_prt); 2308c2ecf20Sopenharmony_ci } else { 2318c2ecf20Sopenharmony_ci fnic_dbg_prt->buffer = 2328c2ecf20Sopenharmony_ci vmalloc(array3_size(3, fnic_fc_trace_max_pages, 2338c2ecf20Sopenharmony_ci PAGE_SIZE)); 2348c2ecf20Sopenharmony_ci if (!fnic_dbg_prt->buffer) { 2358c2ecf20Sopenharmony_ci kfree(fnic_dbg_prt); 2368c2ecf20Sopenharmony_ci return -ENOMEM; 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci memset((void *)fnic_dbg_prt->buffer, 0, 2398c2ecf20Sopenharmony_ci 3 * (fnic_fc_trace_max_pages * PAGE_SIZE)); 2408c2ecf20Sopenharmony_ci fnic_dbg_prt->buffer_len = 2418c2ecf20Sopenharmony_ci fnic_fc_trace_get_data(fnic_dbg_prt, *rdata_ptr); 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci file->private_data = fnic_dbg_prt; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci return 0; 2468c2ecf20Sopenharmony_ci} 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci/* 2498c2ecf20Sopenharmony_ci * fnic_trace_debugfs_lseek - Seek through a debugfs file 2508c2ecf20Sopenharmony_ci * @file: The file pointer to seek through. 2518c2ecf20Sopenharmony_ci * @offset: The offset to seek to or the amount to seek by. 2528c2ecf20Sopenharmony_ci * @howto: Indicates how to seek. 2538c2ecf20Sopenharmony_ci * 2548c2ecf20Sopenharmony_ci * Description: 2558c2ecf20Sopenharmony_ci * This routine is the entry point for the debugfs lseek file operation. 2568c2ecf20Sopenharmony_ci * The @howto parameter indicates whether @offset is the offset to directly 2578c2ecf20Sopenharmony_ci * seek to, or if it is a value to seek forward or reverse by. This function 2588c2ecf20Sopenharmony_ci * figures out what the new offset of the debugfs file will be and assigns 2598c2ecf20Sopenharmony_ci * that value to the f_pos field of @file. 2608c2ecf20Sopenharmony_ci * 2618c2ecf20Sopenharmony_ci * Returns: 2628c2ecf20Sopenharmony_ci * This function returns the new offset if successful and returns a negative 2638c2ecf20Sopenharmony_ci * error if unable to process the seek. 2648c2ecf20Sopenharmony_ci */ 2658c2ecf20Sopenharmony_cistatic loff_t fnic_trace_debugfs_lseek(struct file *file, 2668c2ecf20Sopenharmony_ci loff_t offset, 2678c2ecf20Sopenharmony_ci int howto) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci fnic_dbgfs_t *fnic_dbg_prt = file->private_data; 2708c2ecf20Sopenharmony_ci return fixed_size_llseek(file, offset, howto, 2718c2ecf20Sopenharmony_ci fnic_dbg_prt->buffer_len); 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci/* 2758c2ecf20Sopenharmony_ci * fnic_trace_debugfs_read - Read a debugfs file 2768c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 2778c2ecf20Sopenharmony_ci * @ubuf: The buffer to copy the data to. 2788c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to read. 2798c2ecf20Sopenharmony_ci * @pos: The position in the file to start reading from. 2808c2ecf20Sopenharmony_ci * 2818c2ecf20Sopenharmony_ci * Description: 2828c2ecf20Sopenharmony_ci * This routine reads data from the buffer indicated in the private_data 2838c2ecf20Sopenharmony_ci * field of @file. It will start reading at @pos and copy up to @nbytes of 2848c2ecf20Sopenharmony_ci * data to @ubuf. 2858c2ecf20Sopenharmony_ci * 2868c2ecf20Sopenharmony_ci * Returns: 2878c2ecf20Sopenharmony_ci * This function returns the amount of data that was read (this could be 2888c2ecf20Sopenharmony_ci * less than @nbytes if the end of the file was reached). 2898c2ecf20Sopenharmony_ci */ 2908c2ecf20Sopenharmony_cistatic ssize_t fnic_trace_debugfs_read(struct file *file, 2918c2ecf20Sopenharmony_ci char __user *ubuf, 2928c2ecf20Sopenharmony_ci size_t nbytes, 2938c2ecf20Sopenharmony_ci loff_t *pos) 2948c2ecf20Sopenharmony_ci{ 2958c2ecf20Sopenharmony_ci fnic_dbgfs_t *fnic_dbg_prt = file->private_data; 2968c2ecf20Sopenharmony_ci int rc = 0; 2978c2ecf20Sopenharmony_ci rc = simple_read_from_buffer(ubuf, nbytes, pos, 2988c2ecf20Sopenharmony_ci fnic_dbg_prt->buffer, 2998c2ecf20Sopenharmony_ci fnic_dbg_prt->buffer_len); 3008c2ecf20Sopenharmony_ci return rc; 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci/* 3048c2ecf20Sopenharmony_ci * fnic_trace_debugfs_release - Release the buffer used to store 3058c2ecf20Sopenharmony_ci * debugfs file data 3068c2ecf20Sopenharmony_ci * @inode: The inode pointer 3078c2ecf20Sopenharmony_ci * @file: The file pointer that contains the buffer to release 3088c2ecf20Sopenharmony_ci * 3098c2ecf20Sopenharmony_ci * Description: 3108c2ecf20Sopenharmony_ci * This routine frees the buffer that was allocated when the debugfs 3118c2ecf20Sopenharmony_ci * file was opened. 3128c2ecf20Sopenharmony_ci * 3138c2ecf20Sopenharmony_ci * Returns: 3148c2ecf20Sopenharmony_ci * This function returns zero. 3158c2ecf20Sopenharmony_ci */ 3168c2ecf20Sopenharmony_cistatic int fnic_trace_debugfs_release(struct inode *inode, 3178c2ecf20Sopenharmony_ci struct file *file) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci fnic_dbgfs_t *fnic_dbg_prt = file->private_data; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci vfree(fnic_dbg_prt->buffer); 3228c2ecf20Sopenharmony_ci kfree(fnic_dbg_prt); 3238c2ecf20Sopenharmony_ci return 0; 3248c2ecf20Sopenharmony_ci} 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_cistatic const struct file_operations fnic_trace_debugfs_fops = { 3278c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 3288c2ecf20Sopenharmony_ci .open = fnic_trace_debugfs_open, 3298c2ecf20Sopenharmony_ci .llseek = fnic_trace_debugfs_lseek, 3308c2ecf20Sopenharmony_ci .read = fnic_trace_debugfs_read, 3318c2ecf20Sopenharmony_ci .release = fnic_trace_debugfs_release, 3328c2ecf20Sopenharmony_ci}; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci/* 3358c2ecf20Sopenharmony_ci * fnic_trace_debugfs_init - Initialize debugfs for fnic trace logging 3368c2ecf20Sopenharmony_ci * 3378c2ecf20Sopenharmony_ci * Description: 3388c2ecf20Sopenharmony_ci * When Debugfs is configured this routine sets up the fnic debugfs 3398c2ecf20Sopenharmony_ci * file system. If not already created, this routine will create the 3408c2ecf20Sopenharmony_ci * create file trace to log fnic trace buffer output into debugfs and 3418c2ecf20Sopenharmony_ci * it will also create file trace_enable to control enable/disable of 3428c2ecf20Sopenharmony_ci * trace logging into trace buffer. 3438c2ecf20Sopenharmony_ci */ 3448c2ecf20Sopenharmony_civoid fnic_trace_debugfs_init(void) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci fnic_trace_enable = debugfs_create_file("tracing_enable", 3478c2ecf20Sopenharmony_ci S_IFREG|S_IRUGO|S_IWUSR, 3488c2ecf20Sopenharmony_ci fnic_trace_debugfs_root, 3498c2ecf20Sopenharmony_ci &(fc_trc_flag->fnic_trace), 3508c2ecf20Sopenharmony_ci &fnic_trace_ctrl_fops); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci fnic_trace_debugfs_file = debugfs_create_file("trace", 3538c2ecf20Sopenharmony_ci S_IFREG|S_IRUGO|S_IWUSR, 3548c2ecf20Sopenharmony_ci fnic_trace_debugfs_root, 3558c2ecf20Sopenharmony_ci &(fc_trc_flag->fnic_trace), 3568c2ecf20Sopenharmony_ci &fnic_trace_debugfs_fops); 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci/* 3608c2ecf20Sopenharmony_ci * fnic_trace_debugfs_terminate - Tear down debugfs infrastructure 3618c2ecf20Sopenharmony_ci * 3628c2ecf20Sopenharmony_ci * Description: 3638c2ecf20Sopenharmony_ci * When Debugfs is configured this routine removes debugfs file system 3648c2ecf20Sopenharmony_ci * elements that are specific to fnic trace logging. 3658c2ecf20Sopenharmony_ci */ 3668c2ecf20Sopenharmony_civoid fnic_trace_debugfs_terminate(void) 3678c2ecf20Sopenharmony_ci{ 3688c2ecf20Sopenharmony_ci debugfs_remove(fnic_trace_debugfs_file); 3698c2ecf20Sopenharmony_ci fnic_trace_debugfs_file = NULL; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci debugfs_remove(fnic_trace_enable); 3728c2ecf20Sopenharmony_ci fnic_trace_enable = NULL; 3738c2ecf20Sopenharmony_ci} 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci/* 3768c2ecf20Sopenharmony_ci * fnic_fc_trace_debugfs_init - 3778c2ecf20Sopenharmony_ci * Initialize debugfs for fnic control frame trace logging 3788c2ecf20Sopenharmony_ci * 3798c2ecf20Sopenharmony_ci * Description: 3808c2ecf20Sopenharmony_ci * When Debugfs is configured this routine sets up the fnic_fc debugfs 3818c2ecf20Sopenharmony_ci * file system. If not already created, this routine will create the 3828c2ecf20Sopenharmony_ci * create file trace to log fnic fc trace buffer output into debugfs and 3838c2ecf20Sopenharmony_ci * it will also create file fc_trace_enable to control enable/disable of 3848c2ecf20Sopenharmony_ci * trace logging into trace buffer. 3858c2ecf20Sopenharmony_ci */ 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_civoid fnic_fc_trace_debugfs_init(void) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci fnic_fc_trace_enable = debugfs_create_file("fc_trace_enable", 3908c2ecf20Sopenharmony_ci S_IFREG|S_IRUGO|S_IWUSR, 3918c2ecf20Sopenharmony_ci fnic_trace_debugfs_root, 3928c2ecf20Sopenharmony_ci &(fc_trc_flag->fc_trace), 3938c2ecf20Sopenharmony_ci &fnic_trace_ctrl_fops); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci fnic_fc_trace_clear = debugfs_create_file("fc_trace_clear", 3968c2ecf20Sopenharmony_ci S_IFREG|S_IRUGO|S_IWUSR, 3978c2ecf20Sopenharmony_ci fnic_trace_debugfs_root, 3988c2ecf20Sopenharmony_ci &(fc_trc_flag->fc_clear), 3998c2ecf20Sopenharmony_ci &fnic_trace_ctrl_fops); 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci fnic_fc_rdata_trace_debugfs_file = 4028c2ecf20Sopenharmony_ci debugfs_create_file("fc_trace_rdata", 4038c2ecf20Sopenharmony_ci S_IFREG|S_IRUGO|S_IWUSR, 4048c2ecf20Sopenharmony_ci fnic_trace_debugfs_root, 4058c2ecf20Sopenharmony_ci &(fc_trc_flag->fc_normal_file), 4068c2ecf20Sopenharmony_ci &fnic_trace_debugfs_fops); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci fnic_fc_trace_debugfs_file = 4098c2ecf20Sopenharmony_ci debugfs_create_file("fc_trace", 4108c2ecf20Sopenharmony_ci S_IFREG|S_IRUGO|S_IWUSR, 4118c2ecf20Sopenharmony_ci fnic_trace_debugfs_root, 4128c2ecf20Sopenharmony_ci &(fc_trc_flag->fc_row_file), 4138c2ecf20Sopenharmony_ci &fnic_trace_debugfs_fops); 4148c2ecf20Sopenharmony_ci} 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci/* 4178c2ecf20Sopenharmony_ci * fnic_fc_trace_debugfs_terminate - Tear down debugfs infrastructure 4188c2ecf20Sopenharmony_ci * 4198c2ecf20Sopenharmony_ci * Description: 4208c2ecf20Sopenharmony_ci * When Debugfs is configured this routine removes debugfs file system 4218c2ecf20Sopenharmony_ci * elements that are specific to fnic_fc trace logging. 4228c2ecf20Sopenharmony_ci */ 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_civoid fnic_fc_trace_debugfs_terminate(void) 4258c2ecf20Sopenharmony_ci{ 4268c2ecf20Sopenharmony_ci debugfs_remove(fnic_fc_trace_debugfs_file); 4278c2ecf20Sopenharmony_ci fnic_fc_trace_debugfs_file = NULL; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci debugfs_remove(fnic_fc_rdata_trace_debugfs_file); 4308c2ecf20Sopenharmony_ci fnic_fc_rdata_trace_debugfs_file = NULL; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci debugfs_remove(fnic_fc_trace_enable); 4338c2ecf20Sopenharmony_ci fnic_fc_trace_enable = NULL; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci debugfs_remove(fnic_fc_trace_clear); 4368c2ecf20Sopenharmony_ci fnic_fc_trace_clear = NULL; 4378c2ecf20Sopenharmony_ci} 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci/* 4408c2ecf20Sopenharmony_ci * fnic_reset_stats_open - Open the reset_stats file 4418c2ecf20Sopenharmony_ci * @inode: The inode pointer. 4428c2ecf20Sopenharmony_ci * @file: The file pointer to attach the stats reset flag. 4438c2ecf20Sopenharmony_ci * 4448c2ecf20Sopenharmony_ci * Description: 4458c2ecf20Sopenharmony_ci * This routine opens a debugsfs file reset_stats and stores i_private data 4468c2ecf20Sopenharmony_ci * to debug structure to retrieve later for while performing other 4478c2ecf20Sopenharmony_ci * file oprations. 4488c2ecf20Sopenharmony_ci * 4498c2ecf20Sopenharmony_ci * Returns: 4508c2ecf20Sopenharmony_ci * This function returns zero if successful. 4518c2ecf20Sopenharmony_ci */ 4528c2ecf20Sopenharmony_cistatic int fnic_reset_stats_open(struct inode *inode, struct file *file) 4538c2ecf20Sopenharmony_ci{ 4548c2ecf20Sopenharmony_ci struct stats_debug_info *debug; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci debug = kzalloc(sizeof(struct stats_debug_info), GFP_KERNEL); 4578c2ecf20Sopenharmony_ci if (!debug) 4588c2ecf20Sopenharmony_ci return -ENOMEM; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci debug->i_private = inode->i_private; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci file->private_data = debug; 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci return 0; 4658c2ecf20Sopenharmony_ci} 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci/* 4688c2ecf20Sopenharmony_ci * fnic_reset_stats_read - Read a reset_stats debugfs file 4698c2ecf20Sopenharmony_ci * @filp: The file pointer to read from. 4708c2ecf20Sopenharmony_ci * @ubuf: The buffer to copy the data to. 4718c2ecf20Sopenharmony_ci * @cnt: The number of bytes to read. 4728c2ecf20Sopenharmony_ci * @ppos: The position in the file to start reading from. 4738c2ecf20Sopenharmony_ci * 4748c2ecf20Sopenharmony_ci * Description: 4758c2ecf20Sopenharmony_ci * This routine reads value of variable reset_stats 4768c2ecf20Sopenharmony_ci * and stores into local @buf. It will start reading file at @ppos and 4778c2ecf20Sopenharmony_ci * copy up to @cnt of data to @ubuf from @buf. 4788c2ecf20Sopenharmony_ci * 4798c2ecf20Sopenharmony_ci * Returns: 4808c2ecf20Sopenharmony_ci * This function returns the amount of data that was read. 4818c2ecf20Sopenharmony_ci */ 4828c2ecf20Sopenharmony_cistatic ssize_t fnic_reset_stats_read(struct file *file, 4838c2ecf20Sopenharmony_ci char __user *ubuf, 4848c2ecf20Sopenharmony_ci size_t cnt, loff_t *ppos) 4858c2ecf20Sopenharmony_ci{ 4868c2ecf20Sopenharmony_ci struct stats_debug_info *debug = file->private_data; 4878c2ecf20Sopenharmony_ci struct fnic *fnic = (struct fnic *)debug->i_private; 4888c2ecf20Sopenharmony_ci char buf[64]; 4898c2ecf20Sopenharmony_ci int len; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci len = sprintf(buf, "%u\n", fnic->reset_stats); 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci return simple_read_from_buffer(ubuf, cnt, ppos, buf, len); 4948c2ecf20Sopenharmony_ci} 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci/* 4978c2ecf20Sopenharmony_ci * fnic_reset_stats_write - Write to reset_stats debugfs file 4988c2ecf20Sopenharmony_ci * @filp: The file pointer to write from. 4998c2ecf20Sopenharmony_ci * @ubuf: The buffer to copy the data from. 5008c2ecf20Sopenharmony_ci * @cnt: The number of bytes to write. 5018c2ecf20Sopenharmony_ci * @ppos: The position in the file to start writing to. 5028c2ecf20Sopenharmony_ci * 5038c2ecf20Sopenharmony_ci * Description: 5048c2ecf20Sopenharmony_ci * This routine writes data from user buffer @ubuf to buffer @buf and 5058c2ecf20Sopenharmony_ci * resets cumulative stats of fnic. 5068c2ecf20Sopenharmony_ci * 5078c2ecf20Sopenharmony_ci * Returns: 5088c2ecf20Sopenharmony_ci * This function returns the amount of data that was written. 5098c2ecf20Sopenharmony_ci */ 5108c2ecf20Sopenharmony_cistatic ssize_t fnic_reset_stats_write(struct file *file, 5118c2ecf20Sopenharmony_ci const char __user *ubuf, 5128c2ecf20Sopenharmony_ci size_t cnt, loff_t *ppos) 5138c2ecf20Sopenharmony_ci{ 5148c2ecf20Sopenharmony_ci struct stats_debug_info *debug = file->private_data; 5158c2ecf20Sopenharmony_ci struct fnic *fnic = (struct fnic *)debug->i_private; 5168c2ecf20Sopenharmony_ci struct fnic_stats *stats = &fnic->fnic_stats; 5178c2ecf20Sopenharmony_ci u64 *io_stats_p = (u64 *)&stats->io_stats; 5188c2ecf20Sopenharmony_ci u64 *fw_stats_p = (u64 *)&stats->fw_stats; 5198c2ecf20Sopenharmony_ci char buf[64]; 5208c2ecf20Sopenharmony_ci unsigned long val; 5218c2ecf20Sopenharmony_ci int ret; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci if (cnt >= sizeof(buf)) 5248c2ecf20Sopenharmony_ci return -EINVAL; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci if (copy_from_user(&buf, ubuf, cnt)) 5278c2ecf20Sopenharmony_ci return -EFAULT; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci buf[cnt] = 0; 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci ret = kstrtoul(buf, 10, &val); 5328c2ecf20Sopenharmony_ci if (ret < 0) 5338c2ecf20Sopenharmony_ci return ret; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci fnic->reset_stats = val; 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci if (fnic->reset_stats) { 5388c2ecf20Sopenharmony_ci /* Skip variable is used to avoid descrepancies to Num IOs 5398c2ecf20Sopenharmony_ci * and IO Completions stats. Skip incrementing No IO Compls 5408c2ecf20Sopenharmony_ci * for pending active IOs after reset stats 5418c2ecf20Sopenharmony_ci */ 5428c2ecf20Sopenharmony_ci atomic64_set(&fnic->io_cmpl_skip, 5438c2ecf20Sopenharmony_ci atomic64_read(&stats->io_stats.active_ios)); 5448c2ecf20Sopenharmony_ci memset(&stats->abts_stats, 0, sizeof(struct abort_stats)); 5458c2ecf20Sopenharmony_ci memset(&stats->term_stats, 0, 5468c2ecf20Sopenharmony_ci sizeof(struct terminate_stats)); 5478c2ecf20Sopenharmony_ci memset(&stats->reset_stats, 0, sizeof(struct reset_stats)); 5488c2ecf20Sopenharmony_ci memset(&stats->misc_stats, 0, sizeof(struct misc_stats)); 5498c2ecf20Sopenharmony_ci memset(&stats->vlan_stats, 0, sizeof(struct vlan_stats)); 5508c2ecf20Sopenharmony_ci memset(io_stats_p+1, 0, 5518c2ecf20Sopenharmony_ci sizeof(struct io_path_stats) - sizeof(u64)); 5528c2ecf20Sopenharmony_ci memset(fw_stats_p+1, 0, 5538c2ecf20Sopenharmony_ci sizeof(struct fw_stats) - sizeof(u64)); 5548c2ecf20Sopenharmony_ci ktime_get_real_ts64(&stats->stats_timestamps.last_reset_time); 5558c2ecf20Sopenharmony_ci } 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci (*ppos)++; 5588c2ecf20Sopenharmony_ci return cnt; 5598c2ecf20Sopenharmony_ci} 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci/* 5628c2ecf20Sopenharmony_ci * fnic_reset_stats_release - Release the buffer used to store 5638c2ecf20Sopenharmony_ci * debugfs file data 5648c2ecf20Sopenharmony_ci * @inode: The inode pointer 5658c2ecf20Sopenharmony_ci * @file: The file pointer that contains the buffer to release 5668c2ecf20Sopenharmony_ci * 5678c2ecf20Sopenharmony_ci * Description: 5688c2ecf20Sopenharmony_ci * This routine frees the buffer that was allocated when the debugfs 5698c2ecf20Sopenharmony_ci * file was opened. 5708c2ecf20Sopenharmony_ci * 5718c2ecf20Sopenharmony_ci * Returns: 5728c2ecf20Sopenharmony_ci * This function returns zero. 5738c2ecf20Sopenharmony_ci */ 5748c2ecf20Sopenharmony_cistatic int fnic_reset_stats_release(struct inode *inode, 5758c2ecf20Sopenharmony_ci struct file *file) 5768c2ecf20Sopenharmony_ci{ 5778c2ecf20Sopenharmony_ci struct stats_debug_info *debug = file->private_data; 5788c2ecf20Sopenharmony_ci kfree(debug); 5798c2ecf20Sopenharmony_ci return 0; 5808c2ecf20Sopenharmony_ci} 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci/* 5838c2ecf20Sopenharmony_ci * fnic_stats_debugfs_open - Open the stats file for specific host 5848c2ecf20Sopenharmony_ci * and get fnic stats. 5858c2ecf20Sopenharmony_ci * @inode: The inode pointer. 5868c2ecf20Sopenharmony_ci * @file: The file pointer to attach the specific host statistics. 5878c2ecf20Sopenharmony_ci * 5888c2ecf20Sopenharmony_ci * Description: 5898c2ecf20Sopenharmony_ci * This routine opens a debugsfs file stats of specific host and print 5908c2ecf20Sopenharmony_ci * fnic stats. 5918c2ecf20Sopenharmony_ci * 5928c2ecf20Sopenharmony_ci * Returns: 5938c2ecf20Sopenharmony_ci * This function returns zero if successful. 5948c2ecf20Sopenharmony_ci */ 5958c2ecf20Sopenharmony_cistatic int fnic_stats_debugfs_open(struct inode *inode, 5968c2ecf20Sopenharmony_ci struct file *file) 5978c2ecf20Sopenharmony_ci{ 5988c2ecf20Sopenharmony_ci struct fnic *fnic = inode->i_private; 5998c2ecf20Sopenharmony_ci struct fnic_stats *fnic_stats = &fnic->fnic_stats; 6008c2ecf20Sopenharmony_ci struct stats_debug_info *debug; 6018c2ecf20Sopenharmony_ci int buf_size = 2 * PAGE_SIZE; 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci debug = kzalloc(sizeof(struct stats_debug_info), GFP_KERNEL); 6048c2ecf20Sopenharmony_ci if (!debug) 6058c2ecf20Sopenharmony_ci return -ENOMEM; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci debug->debug_buffer = vmalloc(buf_size); 6088c2ecf20Sopenharmony_ci if (!debug->debug_buffer) { 6098c2ecf20Sopenharmony_ci kfree(debug); 6108c2ecf20Sopenharmony_ci return -ENOMEM; 6118c2ecf20Sopenharmony_ci } 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci debug->buf_size = buf_size; 6148c2ecf20Sopenharmony_ci memset((void *)debug->debug_buffer, 0, buf_size); 6158c2ecf20Sopenharmony_ci debug->buffer_len = fnic_get_stats_data(debug, fnic_stats); 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci file->private_data = debug; 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci return 0; 6208c2ecf20Sopenharmony_ci} 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci/* 6238c2ecf20Sopenharmony_ci * fnic_stats_debugfs_read - Read a debugfs file 6248c2ecf20Sopenharmony_ci * @file: The file pointer to read from. 6258c2ecf20Sopenharmony_ci * @ubuf: The buffer to copy the data to. 6268c2ecf20Sopenharmony_ci * @nbytes: The number of bytes to read. 6278c2ecf20Sopenharmony_ci * @pos: The position in the file to start reading from. 6288c2ecf20Sopenharmony_ci * 6298c2ecf20Sopenharmony_ci * Description: 6308c2ecf20Sopenharmony_ci * This routine reads data from the buffer indicated in the private_data 6318c2ecf20Sopenharmony_ci * field of @file. It will start reading at @pos and copy up to @nbytes of 6328c2ecf20Sopenharmony_ci * data to @ubuf. 6338c2ecf20Sopenharmony_ci * 6348c2ecf20Sopenharmony_ci * Returns: 6358c2ecf20Sopenharmony_ci * This function returns the amount of data that was read (this could be 6368c2ecf20Sopenharmony_ci * less than @nbytes if the end of the file was reached). 6378c2ecf20Sopenharmony_ci */ 6388c2ecf20Sopenharmony_cistatic ssize_t fnic_stats_debugfs_read(struct file *file, 6398c2ecf20Sopenharmony_ci char __user *ubuf, 6408c2ecf20Sopenharmony_ci size_t nbytes, 6418c2ecf20Sopenharmony_ci loff_t *pos) 6428c2ecf20Sopenharmony_ci{ 6438c2ecf20Sopenharmony_ci struct stats_debug_info *debug = file->private_data; 6448c2ecf20Sopenharmony_ci int rc = 0; 6458c2ecf20Sopenharmony_ci rc = simple_read_from_buffer(ubuf, nbytes, pos, 6468c2ecf20Sopenharmony_ci debug->debug_buffer, 6478c2ecf20Sopenharmony_ci debug->buffer_len); 6488c2ecf20Sopenharmony_ci return rc; 6498c2ecf20Sopenharmony_ci} 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci/* 6528c2ecf20Sopenharmony_ci * fnic_stats_stats_release - Release the buffer used to store 6538c2ecf20Sopenharmony_ci * debugfs file data 6548c2ecf20Sopenharmony_ci * @inode: The inode pointer 6558c2ecf20Sopenharmony_ci * @file: The file pointer that contains the buffer to release 6568c2ecf20Sopenharmony_ci * 6578c2ecf20Sopenharmony_ci * Description: 6588c2ecf20Sopenharmony_ci * This routine frees the buffer that was allocated when the debugfs 6598c2ecf20Sopenharmony_ci * file was opened. 6608c2ecf20Sopenharmony_ci * 6618c2ecf20Sopenharmony_ci * Returns: 6628c2ecf20Sopenharmony_ci * This function returns zero. 6638c2ecf20Sopenharmony_ci */ 6648c2ecf20Sopenharmony_cistatic int fnic_stats_debugfs_release(struct inode *inode, 6658c2ecf20Sopenharmony_ci struct file *file) 6668c2ecf20Sopenharmony_ci{ 6678c2ecf20Sopenharmony_ci struct stats_debug_info *debug = file->private_data; 6688c2ecf20Sopenharmony_ci vfree(debug->debug_buffer); 6698c2ecf20Sopenharmony_ci kfree(debug); 6708c2ecf20Sopenharmony_ci return 0; 6718c2ecf20Sopenharmony_ci} 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_cistatic const struct file_operations fnic_stats_debugfs_fops = { 6748c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 6758c2ecf20Sopenharmony_ci .open = fnic_stats_debugfs_open, 6768c2ecf20Sopenharmony_ci .read = fnic_stats_debugfs_read, 6778c2ecf20Sopenharmony_ci .release = fnic_stats_debugfs_release, 6788c2ecf20Sopenharmony_ci}; 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_cistatic const struct file_operations fnic_reset_debugfs_fops = { 6818c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 6828c2ecf20Sopenharmony_ci .open = fnic_reset_stats_open, 6838c2ecf20Sopenharmony_ci .read = fnic_reset_stats_read, 6848c2ecf20Sopenharmony_ci .write = fnic_reset_stats_write, 6858c2ecf20Sopenharmony_ci .release = fnic_reset_stats_release, 6868c2ecf20Sopenharmony_ci}; 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci/* 6898c2ecf20Sopenharmony_ci * fnic_stats_init - Initialize stats struct and create stats file per fnic 6908c2ecf20Sopenharmony_ci * 6918c2ecf20Sopenharmony_ci * Description: 6928c2ecf20Sopenharmony_ci * When Debugfs is configured this routine sets up the stats file per fnic 6938c2ecf20Sopenharmony_ci * It will create file stats and reset_stats under statistics/host# directory 6948c2ecf20Sopenharmony_ci * to log per fnic stats. 6958c2ecf20Sopenharmony_ci */ 6968c2ecf20Sopenharmony_civoid fnic_stats_debugfs_init(struct fnic *fnic) 6978c2ecf20Sopenharmony_ci{ 6988c2ecf20Sopenharmony_ci char name[16]; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "host%d", fnic->lport->host->host_no); 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci fnic->fnic_stats_debugfs_host = debugfs_create_dir(name, 7038c2ecf20Sopenharmony_ci fnic_stats_debugfs_root); 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci fnic->fnic_stats_debugfs_file = debugfs_create_file("stats", 7068c2ecf20Sopenharmony_ci S_IFREG|S_IRUGO|S_IWUSR, 7078c2ecf20Sopenharmony_ci fnic->fnic_stats_debugfs_host, 7088c2ecf20Sopenharmony_ci fnic, 7098c2ecf20Sopenharmony_ci &fnic_stats_debugfs_fops); 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci fnic->fnic_reset_debugfs_file = debugfs_create_file("reset_stats", 7128c2ecf20Sopenharmony_ci S_IFREG|S_IRUGO|S_IWUSR, 7138c2ecf20Sopenharmony_ci fnic->fnic_stats_debugfs_host, 7148c2ecf20Sopenharmony_ci fnic, 7158c2ecf20Sopenharmony_ci &fnic_reset_debugfs_fops); 7168c2ecf20Sopenharmony_ci} 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci/* 7198c2ecf20Sopenharmony_ci * fnic_stats_debugfs_remove - Tear down debugfs infrastructure of stats 7208c2ecf20Sopenharmony_ci * 7218c2ecf20Sopenharmony_ci * Description: 7228c2ecf20Sopenharmony_ci * When Debugfs is configured this routine removes debugfs file system 7238c2ecf20Sopenharmony_ci * elements that are specific to fnic stats. 7248c2ecf20Sopenharmony_ci */ 7258c2ecf20Sopenharmony_civoid fnic_stats_debugfs_remove(struct fnic *fnic) 7268c2ecf20Sopenharmony_ci{ 7278c2ecf20Sopenharmony_ci if (!fnic) 7288c2ecf20Sopenharmony_ci return; 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci debugfs_remove(fnic->fnic_stats_debugfs_file); 7318c2ecf20Sopenharmony_ci fnic->fnic_stats_debugfs_file = NULL; 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci debugfs_remove(fnic->fnic_reset_debugfs_file); 7348c2ecf20Sopenharmony_ci fnic->fnic_reset_debugfs_file = NULL; 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci debugfs_remove(fnic->fnic_stats_debugfs_host); 7378c2ecf20Sopenharmony_ci fnic->fnic_stats_debugfs_host = NULL; 7388c2ecf20Sopenharmony_ci} 739