1*4d7007b4SHiral Patel /* 2*4d7007b4SHiral Patel * Copyright 2012 Cisco Systems, Inc. All rights reserved. 3*4d7007b4SHiral Patel * 4*4d7007b4SHiral Patel * This program is free software; you may redistribute it and/or modify 5*4d7007b4SHiral Patel * it under the terms of the GNU General Public License as published by 6*4d7007b4SHiral Patel * the Free Software Foundation; version 2 of the License. 7*4d7007b4SHiral Patel * 8*4d7007b4SHiral Patel * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 9*4d7007b4SHiral Patel * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 10*4d7007b4SHiral Patel * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 11*4d7007b4SHiral Patel * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 12*4d7007b4SHiral Patel * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 13*4d7007b4SHiral Patel * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14*4d7007b4SHiral Patel * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 15*4d7007b4SHiral Patel * SOFTWARE. 16*4d7007b4SHiral Patel */ 17*4d7007b4SHiral Patel 18*4d7007b4SHiral Patel #include <linux/module.h> 19*4d7007b4SHiral Patel #include <linux/errno.h> 20*4d7007b4SHiral Patel #include <linux/debugfs.h> 21*4d7007b4SHiral Patel #include "fnic.h" 22*4d7007b4SHiral Patel 23*4d7007b4SHiral Patel static struct dentry *fnic_trace_debugfs_root; 24*4d7007b4SHiral Patel static struct dentry *fnic_trace_debugfs_file; 25*4d7007b4SHiral Patel static struct dentry *fnic_trace_enable; 26*4d7007b4SHiral Patel 27*4d7007b4SHiral Patel /* 28*4d7007b4SHiral Patel * fnic_trace_ctrl_open - Open the trace_enable file 29*4d7007b4SHiral Patel * @inode: The inode pointer. 30*4d7007b4SHiral Patel * @file: The file pointer to attach the trace enable/disable flag. 31*4d7007b4SHiral Patel * 32*4d7007b4SHiral Patel * Description: 33*4d7007b4SHiral Patel * This routine opens a debugsfs file trace_enable. 34*4d7007b4SHiral Patel * 35*4d7007b4SHiral Patel * Returns: 36*4d7007b4SHiral Patel * This function returns zero if successful. 37*4d7007b4SHiral Patel */ 38*4d7007b4SHiral Patel static int fnic_trace_ctrl_open(struct inode *inode, struct file *filp) 39*4d7007b4SHiral Patel { 40*4d7007b4SHiral Patel filp->private_data = inode->i_private; 41*4d7007b4SHiral Patel return 0; 42*4d7007b4SHiral Patel } 43*4d7007b4SHiral Patel 44*4d7007b4SHiral Patel /* 45*4d7007b4SHiral Patel * fnic_trace_ctrl_read - Read a trace_enable debugfs file 46*4d7007b4SHiral Patel * @filp: The file pointer to read from. 47*4d7007b4SHiral Patel * @ubuf: The buffer to copy the data to. 48*4d7007b4SHiral Patel * @cnt: The number of bytes to read. 49*4d7007b4SHiral Patel * @ppos: The position in the file to start reading from. 50*4d7007b4SHiral Patel * 51*4d7007b4SHiral Patel * Description: 52*4d7007b4SHiral Patel * This routine reads value of variable fnic_tracing_enabled 53*4d7007b4SHiral Patel * and stores into local @buf. It will start reading file at @ppos and 54*4d7007b4SHiral Patel * copy up to @cnt of data to @ubuf from @buf. 55*4d7007b4SHiral Patel * 56*4d7007b4SHiral Patel * Returns: 57*4d7007b4SHiral Patel * This function returns the amount of data that was read. 58*4d7007b4SHiral Patel */ 59*4d7007b4SHiral Patel static ssize_t fnic_trace_ctrl_read(struct file *filp, 60*4d7007b4SHiral Patel char __user *ubuf, 61*4d7007b4SHiral Patel size_t cnt, loff_t *ppos) 62*4d7007b4SHiral Patel { 63*4d7007b4SHiral Patel char buf[64]; 64*4d7007b4SHiral Patel int len; 65*4d7007b4SHiral Patel len = sprintf(buf, "%u\n", fnic_tracing_enabled); 66*4d7007b4SHiral Patel 67*4d7007b4SHiral Patel return simple_read_from_buffer(ubuf, cnt, ppos, buf, len); 68*4d7007b4SHiral Patel } 69*4d7007b4SHiral Patel 70*4d7007b4SHiral Patel /* 71*4d7007b4SHiral Patel * fnic_trace_ctrl_write - Write to trace_enable debugfs file 72*4d7007b4SHiral Patel * @filp: The file pointer to write from. 73*4d7007b4SHiral Patel * @ubuf: The buffer to copy the data from. 74*4d7007b4SHiral Patel * @cnt: The number of bytes to write. 75*4d7007b4SHiral Patel * @ppos: The position in the file to start writing to. 76*4d7007b4SHiral Patel * 77*4d7007b4SHiral Patel * Description: 78*4d7007b4SHiral Patel * This routine writes data from user buffer @ubuf to buffer @buf and 79*4d7007b4SHiral Patel * sets fnic_tracing_enabled value as per user input. 80*4d7007b4SHiral Patel * 81*4d7007b4SHiral Patel * Returns: 82*4d7007b4SHiral Patel * This function returns the amount of data that was written. 83*4d7007b4SHiral Patel */ 84*4d7007b4SHiral Patel static ssize_t fnic_trace_ctrl_write(struct file *filp, 85*4d7007b4SHiral Patel const char __user *ubuf, 86*4d7007b4SHiral Patel size_t cnt, loff_t *ppos) 87*4d7007b4SHiral Patel { 88*4d7007b4SHiral Patel char buf[64]; 89*4d7007b4SHiral Patel unsigned long val; 90*4d7007b4SHiral Patel int ret; 91*4d7007b4SHiral Patel 92*4d7007b4SHiral Patel if (cnt >= sizeof(buf)) 93*4d7007b4SHiral Patel return -EINVAL; 94*4d7007b4SHiral Patel 95*4d7007b4SHiral Patel if (copy_from_user(&buf, ubuf, cnt)) 96*4d7007b4SHiral Patel return -EFAULT; 97*4d7007b4SHiral Patel 98*4d7007b4SHiral Patel buf[cnt] = 0; 99*4d7007b4SHiral Patel 100*4d7007b4SHiral Patel ret = kstrtoul(buf, 10, &val); 101*4d7007b4SHiral Patel if (ret < 0) 102*4d7007b4SHiral Patel return ret; 103*4d7007b4SHiral Patel 104*4d7007b4SHiral Patel fnic_tracing_enabled = val; 105*4d7007b4SHiral Patel (*ppos)++; 106*4d7007b4SHiral Patel 107*4d7007b4SHiral Patel return cnt; 108*4d7007b4SHiral Patel } 109*4d7007b4SHiral Patel 110*4d7007b4SHiral Patel /* 111*4d7007b4SHiral Patel * fnic_trace_debugfs_open - Open the fnic trace log 112*4d7007b4SHiral Patel * @inode: The inode pointer 113*4d7007b4SHiral Patel * @file: The file pointer to attach the log output 114*4d7007b4SHiral Patel * 115*4d7007b4SHiral Patel * Description: 116*4d7007b4SHiral Patel * This routine is the entry point for the debugfs open file operation. 117*4d7007b4SHiral Patel * It allocates the necessary buffer for the log, fills the buffer from 118*4d7007b4SHiral Patel * the in-memory log and then returns a pointer to that log in 119*4d7007b4SHiral Patel * the private_data field in @file. 120*4d7007b4SHiral Patel * 121*4d7007b4SHiral Patel * Returns: 122*4d7007b4SHiral Patel * This function returns zero if successful. On error it will return 123*4d7007b4SHiral Patel * a negative error value. 124*4d7007b4SHiral Patel */ 125*4d7007b4SHiral Patel static int fnic_trace_debugfs_open(struct inode *inode, 126*4d7007b4SHiral Patel struct file *file) 127*4d7007b4SHiral Patel { 128*4d7007b4SHiral Patel fnic_dbgfs_t *fnic_dbg_prt; 129*4d7007b4SHiral Patel fnic_dbg_prt = kzalloc(sizeof(fnic_dbgfs_t), GFP_KERNEL); 130*4d7007b4SHiral Patel if (!fnic_dbg_prt) 131*4d7007b4SHiral Patel return -ENOMEM; 132*4d7007b4SHiral Patel 133*4d7007b4SHiral Patel fnic_dbg_prt->buffer = vmalloc((3*(trace_max_pages * PAGE_SIZE))); 134*4d7007b4SHiral Patel if (!fnic_dbg_prt->buffer) { 135*4d7007b4SHiral Patel kfree(fnic_dbg_prt); 136*4d7007b4SHiral Patel return -ENOMEM; 137*4d7007b4SHiral Patel } 138*4d7007b4SHiral Patel memset((void *)fnic_dbg_prt->buffer, 0, 139*4d7007b4SHiral Patel (3*(trace_max_pages * PAGE_SIZE))); 140*4d7007b4SHiral Patel fnic_dbg_prt->buffer_len = fnic_get_trace_data(fnic_dbg_prt); 141*4d7007b4SHiral Patel file->private_data = fnic_dbg_prt; 142*4d7007b4SHiral Patel return 0; 143*4d7007b4SHiral Patel } 144*4d7007b4SHiral Patel 145*4d7007b4SHiral Patel /* 146*4d7007b4SHiral Patel * fnic_trace_debugfs_lseek - Seek through a debugfs file 147*4d7007b4SHiral Patel * @file: The file pointer to seek through. 148*4d7007b4SHiral Patel * @offset: The offset to seek to or the amount to seek by. 149*4d7007b4SHiral Patel * @howto: Indicates how to seek. 150*4d7007b4SHiral Patel * 151*4d7007b4SHiral Patel * Description: 152*4d7007b4SHiral Patel * This routine is the entry point for the debugfs lseek file operation. 153*4d7007b4SHiral Patel * The @howto parameter indicates whether @offset is the offset to directly 154*4d7007b4SHiral Patel * seek to, or if it is a value to seek forward or reverse by. This function 155*4d7007b4SHiral Patel * figures out what the new offset of the debugfs file will be and assigns 156*4d7007b4SHiral Patel * that value to the f_pos field of @file. 157*4d7007b4SHiral Patel * 158*4d7007b4SHiral Patel * Returns: 159*4d7007b4SHiral Patel * This function returns the new offset if successful and returns a negative 160*4d7007b4SHiral Patel * error if unable to process the seek. 161*4d7007b4SHiral Patel */ 162*4d7007b4SHiral Patel static loff_t fnic_trace_debugfs_lseek(struct file *file, 163*4d7007b4SHiral Patel loff_t offset, 164*4d7007b4SHiral Patel int howto) 165*4d7007b4SHiral Patel { 166*4d7007b4SHiral Patel fnic_dbgfs_t *fnic_dbg_prt = file->private_data; 167*4d7007b4SHiral Patel loff_t pos = -1; 168*4d7007b4SHiral Patel 169*4d7007b4SHiral Patel switch (howto) { 170*4d7007b4SHiral Patel case 0: 171*4d7007b4SHiral Patel pos = offset; 172*4d7007b4SHiral Patel break; 173*4d7007b4SHiral Patel case 1: 174*4d7007b4SHiral Patel pos = file->f_pos + offset; 175*4d7007b4SHiral Patel break; 176*4d7007b4SHiral Patel case 2: 177*4d7007b4SHiral Patel pos = fnic_dbg_prt->buffer_len - offset; 178*4d7007b4SHiral Patel } 179*4d7007b4SHiral Patel return (pos < 0 || pos > fnic_dbg_prt->buffer_len) ? 180*4d7007b4SHiral Patel -EINVAL : (file->f_pos = pos); 181*4d7007b4SHiral Patel } 182*4d7007b4SHiral Patel 183*4d7007b4SHiral Patel /* 184*4d7007b4SHiral Patel * fnic_trace_debugfs_read - Read a debugfs file 185*4d7007b4SHiral Patel * @file: The file pointer to read from. 186*4d7007b4SHiral Patel * @ubuf: The buffer to copy the data to. 187*4d7007b4SHiral Patel * @nbytes: The number of bytes to read. 188*4d7007b4SHiral Patel * @pos: The position in the file to start reading from. 189*4d7007b4SHiral Patel * 190*4d7007b4SHiral Patel * Description: 191*4d7007b4SHiral Patel * This routine reads data from the buffer indicated in the private_data 192*4d7007b4SHiral Patel * field of @file. It will start reading at @pos and copy up to @nbytes of 193*4d7007b4SHiral Patel * data to @ubuf. 194*4d7007b4SHiral Patel * 195*4d7007b4SHiral Patel * Returns: 196*4d7007b4SHiral Patel * This function returns the amount of data that was read (this could be 197*4d7007b4SHiral Patel * less than @nbytes if the end of the file was reached). 198*4d7007b4SHiral Patel */ 199*4d7007b4SHiral Patel static ssize_t fnic_trace_debugfs_read(struct file *file, 200*4d7007b4SHiral Patel char __user *ubuf, 201*4d7007b4SHiral Patel size_t nbytes, 202*4d7007b4SHiral Patel loff_t *pos) 203*4d7007b4SHiral Patel { 204*4d7007b4SHiral Patel fnic_dbgfs_t *fnic_dbg_prt = file->private_data; 205*4d7007b4SHiral Patel int rc = 0; 206*4d7007b4SHiral Patel rc = simple_read_from_buffer(ubuf, nbytes, pos, 207*4d7007b4SHiral Patel fnic_dbg_prt->buffer, 208*4d7007b4SHiral Patel fnic_dbg_prt->buffer_len); 209*4d7007b4SHiral Patel return rc; 210*4d7007b4SHiral Patel } 211*4d7007b4SHiral Patel 212*4d7007b4SHiral Patel /* 213*4d7007b4SHiral Patel * fnic_trace_debugfs_release - Release the buffer used to store 214*4d7007b4SHiral Patel * debugfs file data 215*4d7007b4SHiral Patel * @inode: The inode pointer 216*4d7007b4SHiral Patel * @file: The file pointer that contains the buffer to release 217*4d7007b4SHiral Patel * 218*4d7007b4SHiral Patel * Description: 219*4d7007b4SHiral Patel * This routine frees the buffer that was allocated when the debugfs 220*4d7007b4SHiral Patel * file was opened. 221*4d7007b4SHiral Patel * 222*4d7007b4SHiral Patel * Returns: 223*4d7007b4SHiral Patel * This function returns zero. 224*4d7007b4SHiral Patel */ 225*4d7007b4SHiral Patel static int fnic_trace_debugfs_release(struct inode *inode, 226*4d7007b4SHiral Patel struct file *file) 227*4d7007b4SHiral Patel { 228*4d7007b4SHiral Patel fnic_dbgfs_t *fnic_dbg_prt = file->private_data; 229*4d7007b4SHiral Patel 230*4d7007b4SHiral Patel vfree(fnic_dbg_prt->buffer); 231*4d7007b4SHiral Patel kfree(fnic_dbg_prt); 232*4d7007b4SHiral Patel return 0; 233*4d7007b4SHiral Patel } 234*4d7007b4SHiral Patel 235*4d7007b4SHiral Patel static const struct file_operations fnic_trace_ctrl_fops = { 236*4d7007b4SHiral Patel .owner = THIS_MODULE, 237*4d7007b4SHiral Patel .open = fnic_trace_ctrl_open, 238*4d7007b4SHiral Patel .read = fnic_trace_ctrl_read, 239*4d7007b4SHiral Patel .write = fnic_trace_ctrl_write, 240*4d7007b4SHiral Patel }; 241*4d7007b4SHiral Patel 242*4d7007b4SHiral Patel static const struct file_operations fnic_trace_debugfs_fops = { 243*4d7007b4SHiral Patel .owner = THIS_MODULE, 244*4d7007b4SHiral Patel .open = fnic_trace_debugfs_open, 245*4d7007b4SHiral Patel .llseek = fnic_trace_debugfs_lseek, 246*4d7007b4SHiral Patel .read = fnic_trace_debugfs_read, 247*4d7007b4SHiral Patel .release = fnic_trace_debugfs_release, 248*4d7007b4SHiral Patel }; 249*4d7007b4SHiral Patel 250*4d7007b4SHiral Patel /* 251*4d7007b4SHiral Patel * fnic_trace_debugfs_init - Initialize debugfs for fnic trace logging 252*4d7007b4SHiral Patel * 253*4d7007b4SHiral Patel * Description: 254*4d7007b4SHiral Patel * When Debugfs is configured this routine sets up the fnic debugfs 255*4d7007b4SHiral Patel * file system. If not already created, this routine will create the 256*4d7007b4SHiral Patel * fnic directory. It will create file trace to log fnic trace buffer 257*4d7007b4SHiral Patel * output into debugfs and it will also create file trace_enable to 258*4d7007b4SHiral Patel * control enable/disable of trace logging into trace buffer. 259*4d7007b4SHiral Patel */ 260*4d7007b4SHiral Patel int fnic_trace_debugfs_init(void) 261*4d7007b4SHiral Patel { 262*4d7007b4SHiral Patel int rc = -1; 263*4d7007b4SHiral Patel fnic_trace_debugfs_root = debugfs_create_dir("fnic", NULL); 264*4d7007b4SHiral Patel if (!fnic_trace_debugfs_root) { 265*4d7007b4SHiral Patel printk(KERN_DEBUG "Cannot create debugfs root\n"); 266*4d7007b4SHiral Patel return rc; 267*4d7007b4SHiral Patel } 268*4d7007b4SHiral Patel fnic_trace_enable = debugfs_create_file("tracing_enable", 269*4d7007b4SHiral Patel S_IFREG|S_IRUGO|S_IWUSR, 270*4d7007b4SHiral Patel fnic_trace_debugfs_root, 271*4d7007b4SHiral Patel NULL, &fnic_trace_ctrl_fops); 272*4d7007b4SHiral Patel 273*4d7007b4SHiral Patel if (!fnic_trace_enable) { 274*4d7007b4SHiral Patel printk(KERN_DEBUG "Cannot create trace_enable file" 275*4d7007b4SHiral Patel " under debugfs"); 276*4d7007b4SHiral Patel return rc; 277*4d7007b4SHiral Patel } 278*4d7007b4SHiral Patel 279*4d7007b4SHiral Patel fnic_trace_debugfs_file = debugfs_create_file("trace", 280*4d7007b4SHiral Patel S_IFREG|S_IRUGO|S_IWUSR, 281*4d7007b4SHiral Patel fnic_trace_debugfs_root, 282*4d7007b4SHiral Patel NULL, 283*4d7007b4SHiral Patel &fnic_trace_debugfs_fops); 284*4d7007b4SHiral Patel 285*4d7007b4SHiral Patel if (!fnic_trace_debugfs_file) { 286*4d7007b4SHiral Patel printk(KERN_DEBUG "Cannot create trace file under debugfs"); 287*4d7007b4SHiral Patel return rc; 288*4d7007b4SHiral Patel } 289*4d7007b4SHiral Patel rc = 0; 290*4d7007b4SHiral Patel return rc; 291*4d7007b4SHiral Patel } 292*4d7007b4SHiral Patel 293*4d7007b4SHiral Patel /* 294*4d7007b4SHiral Patel * fnic_trace_debugfs_terminate - Tear down debugfs infrastructure 295*4d7007b4SHiral Patel * 296*4d7007b4SHiral Patel * Description: 297*4d7007b4SHiral Patel * When Debugfs is configured this routine removes debugfs file system 298*4d7007b4SHiral Patel * elements that are specific to fnic trace logging. 299*4d7007b4SHiral Patel */ 300*4d7007b4SHiral Patel void fnic_trace_debugfs_terminate(void) 301*4d7007b4SHiral Patel { 302*4d7007b4SHiral Patel if (fnic_trace_debugfs_file) { 303*4d7007b4SHiral Patel debugfs_remove(fnic_trace_debugfs_file); 304*4d7007b4SHiral Patel fnic_trace_debugfs_file = NULL; 305*4d7007b4SHiral Patel } 306*4d7007b4SHiral Patel if (fnic_trace_enable) { 307*4d7007b4SHiral Patel debugfs_remove(fnic_trace_enable); 308*4d7007b4SHiral Patel fnic_trace_enable = NULL; 309*4d7007b4SHiral Patel } 310*4d7007b4SHiral Patel if (fnic_trace_debugfs_root) { 311*4d7007b4SHiral Patel debugfs_remove(fnic_trace_debugfs_root); 312*4d7007b4SHiral Patel fnic_trace_debugfs_root = NULL; 313*4d7007b4SHiral Patel } 314*4d7007b4SHiral Patel } 315