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