1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 2012 Cisco Systems, Inc. All rights reserved.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * This program is free software; you may redistribute it and/or modify
5*4882a593Smuzhiyun * it under the terms of the GNU General Public License as published by
6*4882a593Smuzhiyun * the Free Software Foundation; version 2 of the License.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
9*4882a593Smuzhiyun * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
10*4882a593Smuzhiyun * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
11*4882a593Smuzhiyun * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
12*4882a593Smuzhiyun * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
13*4882a593Smuzhiyun * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
14*4882a593Smuzhiyun * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
15*4882a593Smuzhiyun * SOFTWARE.
16*4882a593Smuzhiyun */
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #include <linux/module.h>
19*4882a593Smuzhiyun #include <linux/errno.h>
20*4882a593Smuzhiyun #include <linux/debugfs.h>
21*4882a593Smuzhiyun #include <linux/vmalloc.h>
22*4882a593Smuzhiyun #include "fnic.h"
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun static struct dentry *fnic_trace_debugfs_root;
25*4882a593Smuzhiyun static struct dentry *fnic_trace_debugfs_file;
26*4882a593Smuzhiyun static struct dentry *fnic_trace_enable;
27*4882a593Smuzhiyun static struct dentry *fnic_stats_debugfs_root;
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun static struct dentry *fnic_fc_trace_debugfs_file;
30*4882a593Smuzhiyun static struct dentry *fnic_fc_rdata_trace_debugfs_file;
31*4882a593Smuzhiyun static struct dentry *fnic_fc_trace_enable;
32*4882a593Smuzhiyun static struct dentry *fnic_fc_trace_clear;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun struct fc_trace_flag_type {
35*4882a593Smuzhiyun u8 fc_row_file;
36*4882a593Smuzhiyun u8 fc_normal_file;
37*4882a593Smuzhiyun u8 fnic_trace;
38*4882a593Smuzhiyun u8 fc_trace;
39*4882a593Smuzhiyun u8 fc_clear;
40*4882a593Smuzhiyun };
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun static struct fc_trace_flag_type *fc_trc_flag;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun /*
45*4882a593Smuzhiyun * fnic_debugfs_init - Initialize debugfs for fnic debug logging
46*4882a593Smuzhiyun *
47*4882a593Smuzhiyun * Description:
48*4882a593Smuzhiyun * When Debugfs is configured this routine sets up the fnic debugfs
49*4882a593Smuzhiyun * file system. If not already created, this routine will create the
50*4882a593Smuzhiyun * fnic directory and statistics directory for trace buffer and
51*4882a593Smuzhiyun * stats logging.
52*4882a593Smuzhiyun */
fnic_debugfs_init(void)53*4882a593Smuzhiyun int fnic_debugfs_init(void)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun fnic_trace_debugfs_root = debugfs_create_dir("fnic", NULL);
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun fnic_stats_debugfs_root = debugfs_create_dir("statistics",
58*4882a593Smuzhiyun fnic_trace_debugfs_root);
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /* Allocate memory to structure */
61*4882a593Smuzhiyun fc_trc_flag = (struct fc_trace_flag_type *)
62*4882a593Smuzhiyun vmalloc(sizeof(struct fc_trace_flag_type));
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun if (fc_trc_flag) {
65*4882a593Smuzhiyun fc_trc_flag->fc_row_file = 0;
66*4882a593Smuzhiyun fc_trc_flag->fc_normal_file = 1;
67*4882a593Smuzhiyun fc_trc_flag->fnic_trace = 2;
68*4882a593Smuzhiyun fc_trc_flag->fc_trace = 3;
69*4882a593Smuzhiyun fc_trc_flag->fc_clear = 4;
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun return 0;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun /*
76*4882a593Smuzhiyun * fnic_debugfs_terminate - Tear down debugfs infrastructure
77*4882a593Smuzhiyun *
78*4882a593Smuzhiyun * Description:
79*4882a593Smuzhiyun * When Debugfs is configured this routine removes debugfs file system
80*4882a593Smuzhiyun * elements that are specific to fnic.
81*4882a593Smuzhiyun */
fnic_debugfs_terminate(void)82*4882a593Smuzhiyun void fnic_debugfs_terminate(void)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun debugfs_remove(fnic_stats_debugfs_root);
85*4882a593Smuzhiyun fnic_stats_debugfs_root = NULL;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun debugfs_remove(fnic_trace_debugfs_root);
88*4882a593Smuzhiyun fnic_trace_debugfs_root = NULL;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun if (fc_trc_flag)
91*4882a593Smuzhiyun vfree(fc_trc_flag);
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun /*
95*4882a593Smuzhiyun * fnic_trace_ctrl_read -
96*4882a593Smuzhiyun * Read trace_enable ,fc_trace_enable
97*4882a593Smuzhiyun * or fc_trace_clear debugfs file
98*4882a593Smuzhiyun * @filp: The file pointer to read from.
99*4882a593Smuzhiyun * @ubuf: The buffer to copy the data to.
100*4882a593Smuzhiyun * @cnt: The number of bytes to read.
101*4882a593Smuzhiyun * @ppos: The position in the file to start reading from.
102*4882a593Smuzhiyun *
103*4882a593Smuzhiyun * Description:
104*4882a593Smuzhiyun * This routine reads value of variable fnic_tracing_enabled or
105*4882a593Smuzhiyun * fnic_fc_tracing_enabled or fnic_fc_trace_cleared
106*4882a593Smuzhiyun * and stores into local @buf.
107*4882a593Smuzhiyun * It will start reading file at @ppos and
108*4882a593Smuzhiyun * copy up to @cnt of data to @ubuf from @buf.
109*4882a593Smuzhiyun *
110*4882a593Smuzhiyun * Returns:
111*4882a593Smuzhiyun * This function returns the amount of data that was read.
112*4882a593Smuzhiyun */
fnic_trace_ctrl_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)113*4882a593Smuzhiyun static ssize_t fnic_trace_ctrl_read(struct file *filp,
114*4882a593Smuzhiyun char __user *ubuf,
115*4882a593Smuzhiyun size_t cnt, loff_t *ppos)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun char buf[64];
118*4882a593Smuzhiyun int len;
119*4882a593Smuzhiyun u8 *trace_type;
120*4882a593Smuzhiyun len = 0;
121*4882a593Smuzhiyun trace_type = (u8 *)filp->private_data;
122*4882a593Smuzhiyun if (*trace_type == fc_trc_flag->fnic_trace)
123*4882a593Smuzhiyun len = sprintf(buf, "%d\n", fnic_tracing_enabled);
124*4882a593Smuzhiyun else if (*trace_type == fc_trc_flag->fc_trace)
125*4882a593Smuzhiyun len = sprintf(buf, "%d\n", fnic_fc_tracing_enabled);
126*4882a593Smuzhiyun else if (*trace_type == fc_trc_flag->fc_clear)
127*4882a593Smuzhiyun len = sprintf(buf, "%d\n", fnic_fc_trace_cleared);
128*4882a593Smuzhiyun else
129*4882a593Smuzhiyun pr_err("fnic: Cannot read to any debugfs file\n");
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun return simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun /*
135*4882a593Smuzhiyun * fnic_trace_ctrl_write -
136*4882a593Smuzhiyun * Write to trace_enable, fc_trace_enable or
137*4882a593Smuzhiyun * fc_trace_clear debugfs file
138*4882a593Smuzhiyun * @filp: The file pointer to write from.
139*4882a593Smuzhiyun * @ubuf: The buffer to copy the data from.
140*4882a593Smuzhiyun * @cnt: The number of bytes to write.
141*4882a593Smuzhiyun * @ppos: The position in the file to start writing to.
142*4882a593Smuzhiyun *
143*4882a593Smuzhiyun * Description:
144*4882a593Smuzhiyun * This routine writes data from user buffer @ubuf to buffer @buf and
145*4882a593Smuzhiyun * sets fc_trace_enable ,tracing_enable or fnic_fc_trace_cleared
146*4882a593Smuzhiyun * value as per user input.
147*4882a593Smuzhiyun *
148*4882a593Smuzhiyun * Returns:
149*4882a593Smuzhiyun * This function returns the amount of data that was written.
150*4882a593Smuzhiyun */
fnic_trace_ctrl_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos)151*4882a593Smuzhiyun static ssize_t fnic_trace_ctrl_write(struct file *filp,
152*4882a593Smuzhiyun const char __user *ubuf,
153*4882a593Smuzhiyun size_t cnt, loff_t *ppos)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun char buf[64];
156*4882a593Smuzhiyun unsigned long val;
157*4882a593Smuzhiyun int ret;
158*4882a593Smuzhiyun u8 *trace_type;
159*4882a593Smuzhiyun trace_type = (u8 *)filp->private_data;
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun if (cnt >= sizeof(buf))
162*4882a593Smuzhiyun return -EINVAL;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun if (copy_from_user(&buf, ubuf, cnt))
165*4882a593Smuzhiyun return -EFAULT;
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun buf[cnt] = 0;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun ret = kstrtoul(buf, 10, &val);
170*4882a593Smuzhiyun if (ret < 0)
171*4882a593Smuzhiyun return ret;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun if (*trace_type == fc_trc_flag->fnic_trace)
174*4882a593Smuzhiyun fnic_tracing_enabled = val;
175*4882a593Smuzhiyun else if (*trace_type == fc_trc_flag->fc_trace)
176*4882a593Smuzhiyun fnic_fc_tracing_enabled = val;
177*4882a593Smuzhiyun else if (*trace_type == fc_trc_flag->fc_clear)
178*4882a593Smuzhiyun fnic_fc_trace_cleared = val;
179*4882a593Smuzhiyun else
180*4882a593Smuzhiyun pr_err("fnic: cannot write to any debugfs file\n");
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun (*ppos)++;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun return cnt;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun static const struct file_operations fnic_trace_ctrl_fops = {
188*4882a593Smuzhiyun .owner = THIS_MODULE,
189*4882a593Smuzhiyun .open = simple_open,
190*4882a593Smuzhiyun .read = fnic_trace_ctrl_read,
191*4882a593Smuzhiyun .write = fnic_trace_ctrl_write,
192*4882a593Smuzhiyun };
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun /*
195*4882a593Smuzhiyun * fnic_trace_debugfs_open - Open the fnic trace log
196*4882a593Smuzhiyun * @inode: The inode pointer
197*4882a593Smuzhiyun * @file: The file pointer to attach the log output
198*4882a593Smuzhiyun *
199*4882a593Smuzhiyun * Description:
200*4882a593Smuzhiyun * This routine is the entry point for the debugfs open file operation.
201*4882a593Smuzhiyun * It allocates the necessary buffer for the log, fills the buffer from
202*4882a593Smuzhiyun * the in-memory log and then returns a pointer to that log in
203*4882a593Smuzhiyun * the private_data field in @file.
204*4882a593Smuzhiyun *
205*4882a593Smuzhiyun * Returns:
206*4882a593Smuzhiyun * This function returns zero if successful. On error it will return
207*4882a593Smuzhiyun * a negative error value.
208*4882a593Smuzhiyun */
fnic_trace_debugfs_open(struct inode * inode,struct file * file)209*4882a593Smuzhiyun static int fnic_trace_debugfs_open(struct inode *inode,
210*4882a593Smuzhiyun struct file *file)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun fnic_dbgfs_t *fnic_dbg_prt;
213*4882a593Smuzhiyun u8 *rdata_ptr;
214*4882a593Smuzhiyun rdata_ptr = (u8 *)inode->i_private;
215*4882a593Smuzhiyun fnic_dbg_prt = kzalloc(sizeof(fnic_dbgfs_t), GFP_KERNEL);
216*4882a593Smuzhiyun if (!fnic_dbg_prt)
217*4882a593Smuzhiyun return -ENOMEM;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun if (*rdata_ptr == fc_trc_flag->fnic_trace) {
220*4882a593Smuzhiyun fnic_dbg_prt->buffer = vmalloc(array3_size(3, trace_max_pages,
221*4882a593Smuzhiyun PAGE_SIZE));
222*4882a593Smuzhiyun if (!fnic_dbg_prt->buffer) {
223*4882a593Smuzhiyun kfree(fnic_dbg_prt);
224*4882a593Smuzhiyun return -ENOMEM;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun memset((void *)fnic_dbg_prt->buffer, 0,
227*4882a593Smuzhiyun 3 * (trace_max_pages * PAGE_SIZE));
228*4882a593Smuzhiyun fnic_dbg_prt->buffer_len = fnic_get_trace_data(fnic_dbg_prt);
229*4882a593Smuzhiyun } else {
230*4882a593Smuzhiyun fnic_dbg_prt->buffer =
231*4882a593Smuzhiyun vmalloc(array3_size(3, fnic_fc_trace_max_pages,
232*4882a593Smuzhiyun PAGE_SIZE));
233*4882a593Smuzhiyun if (!fnic_dbg_prt->buffer) {
234*4882a593Smuzhiyun kfree(fnic_dbg_prt);
235*4882a593Smuzhiyun return -ENOMEM;
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun memset((void *)fnic_dbg_prt->buffer, 0,
238*4882a593Smuzhiyun 3 * (fnic_fc_trace_max_pages * PAGE_SIZE));
239*4882a593Smuzhiyun fnic_dbg_prt->buffer_len =
240*4882a593Smuzhiyun fnic_fc_trace_get_data(fnic_dbg_prt, *rdata_ptr);
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun file->private_data = fnic_dbg_prt;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun return 0;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun /*
248*4882a593Smuzhiyun * fnic_trace_debugfs_lseek - Seek through a debugfs file
249*4882a593Smuzhiyun * @file: The file pointer to seek through.
250*4882a593Smuzhiyun * @offset: The offset to seek to or the amount to seek by.
251*4882a593Smuzhiyun * @howto: Indicates how to seek.
252*4882a593Smuzhiyun *
253*4882a593Smuzhiyun * Description:
254*4882a593Smuzhiyun * This routine is the entry point for the debugfs lseek file operation.
255*4882a593Smuzhiyun * The @howto parameter indicates whether @offset is the offset to directly
256*4882a593Smuzhiyun * seek to, or if it is a value to seek forward or reverse by. This function
257*4882a593Smuzhiyun * figures out what the new offset of the debugfs file will be and assigns
258*4882a593Smuzhiyun * that value to the f_pos field of @file.
259*4882a593Smuzhiyun *
260*4882a593Smuzhiyun * Returns:
261*4882a593Smuzhiyun * This function returns the new offset if successful and returns a negative
262*4882a593Smuzhiyun * error if unable to process the seek.
263*4882a593Smuzhiyun */
fnic_trace_debugfs_lseek(struct file * file,loff_t offset,int howto)264*4882a593Smuzhiyun static loff_t fnic_trace_debugfs_lseek(struct file *file,
265*4882a593Smuzhiyun loff_t offset,
266*4882a593Smuzhiyun int howto)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun fnic_dbgfs_t *fnic_dbg_prt = file->private_data;
269*4882a593Smuzhiyun return fixed_size_llseek(file, offset, howto,
270*4882a593Smuzhiyun fnic_dbg_prt->buffer_len);
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun /*
274*4882a593Smuzhiyun * fnic_trace_debugfs_read - Read a debugfs file
275*4882a593Smuzhiyun * @file: The file pointer to read from.
276*4882a593Smuzhiyun * @ubuf: The buffer to copy the data to.
277*4882a593Smuzhiyun * @nbytes: The number of bytes to read.
278*4882a593Smuzhiyun * @pos: The position in the file to start reading from.
279*4882a593Smuzhiyun *
280*4882a593Smuzhiyun * Description:
281*4882a593Smuzhiyun * This routine reads data from the buffer indicated in the private_data
282*4882a593Smuzhiyun * field of @file. It will start reading at @pos and copy up to @nbytes of
283*4882a593Smuzhiyun * data to @ubuf.
284*4882a593Smuzhiyun *
285*4882a593Smuzhiyun * Returns:
286*4882a593Smuzhiyun * This function returns the amount of data that was read (this could be
287*4882a593Smuzhiyun * less than @nbytes if the end of the file was reached).
288*4882a593Smuzhiyun */
fnic_trace_debugfs_read(struct file * file,char __user * ubuf,size_t nbytes,loff_t * pos)289*4882a593Smuzhiyun static ssize_t fnic_trace_debugfs_read(struct file *file,
290*4882a593Smuzhiyun char __user *ubuf,
291*4882a593Smuzhiyun size_t nbytes,
292*4882a593Smuzhiyun loff_t *pos)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun fnic_dbgfs_t *fnic_dbg_prt = file->private_data;
295*4882a593Smuzhiyun int rc = 0;
296*4882a593Smuzhiyun rc = simple_read_from_buffer(ubuf, nbytes, pos,
297*4882a593Smuzhiyun fnic_dbg_prt->buffer,
298*4882a593Smuzhiyun fnic_dbg_prt->buffer_len);
299*4882a593Smuzhiyun return rc;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun /*
303*4882a593Smuzhiyun * fnic_trace_debugfs_release - Release the buffer used to store
304*4882a593Smuzhiyun * debugfs file data
305*4882a593Smuzhiyun * @inode: The inode pointer
306*4882a593Smuzhiyun * @file: The file pointer that contains the buffer to release
307*4882a593Smuzhiyun *
308*4882a593Smuzhiyun * Description:
309*4882a593Smuzhiyun * This routine frees the buffer that was allocated when the debugfs
310*4882a593Smuzhiyun * file was opened.
311*4882a593Smuzhiyun *
312*4882a593Smuzhiyun * Returns:
313*4882a593Smuzhiyun * This function returns zero.
314*4882a593Smuzhiyun */
fnic_trace_debugfs_release(struct inode * inode,struct file * file)315*4882a593Smuzhiyun static int fnic_trace_debugfs_release(struct inode *inode,
316*4882a593Smuzhiyun struct file *file)
317*4882a593Smuzhiyun {
318*4882a593Smuzhiyun fnic_dbgfs_t *fnic_dbg_prt = file->private_data;
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun vfree(fnic_dbg_prt->buffer);
321*4882a593Smuzhiyun kfree(fnic_dbg_prt);
322*4882a593Smuzhiyun return 0;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun static const struct file_operations fnic_trace_debugfs_fops = {
326*4882a593Smuzhiyun .owner = THIS_MODULE,
327*4882a593Smuzhiyun .open = fnic_trace_debugfs_open,
328*4882a593Smuzhiyun .llseek = fnic_trace_debugfs_lseek,
329*4882a593Smuzhiyun .read = fnic_trace_debugfs_read,
330*4882a593Smuzhiyun .release = fnic_trace_debugfs_release,
331*4882a593Smuzhiyun };
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun /*
334*4882a593Smuzhiyun * fnic_trace_debugfs_init - Initialize debugfs for fnic trace logging
335*4882a593Smuzhiyun *
336*4882a593Smuzhiyun * Description:
337*4882a593Smuzhiyun * When Debugfs is configured this routine sets up the fnic debugfs
338*4882a593Smuzhiyun * file system. If not already created, this routine will create the
339*4882a593Smuzhiyun * create file trace to log fnic trace buffer output into debugfs and
340*4882a593Smuzhiyun * it will also create file trace_enable to control enable/disable of
341*4882a593Smuzhiyun * trace logging into trace buffer.
342*4882a593Smuzhiyun */
fnic_trace_debugfs_init(void)343*4882a593Smuzhiyun void fnic_trace_debugfs_init(void)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun fnic_trace_enable = debugfs_create_file("tracing_enable",
346*4882a593Smuzhiyun S_IFREG|S_IRUGO|S_IWUSR,
347*4882a593Smuzhiyun fnic_trace_debugfs_root,
348*4882a593Smuzhiyun &(fc_trc_flag->fnic_trace),
349*4882a593Smuzhiyun &fnic_trace_ctrl_fops);
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun fnic_trace_debugfs_file = debugfs_create_file("trace",
352*4882a593Smuzhiyun S_IFREG|S_IRUGO|S_IWUSR,
353*4882a593Smuzhiyun fnic_trace_debugfs_root,
354*4882a593Smuzhiyun &(fc_trc_flag->fnic_trace),
355*4882a593Smuzhiyun &fnic_trace_debugfs_fops);
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun /*
359*4882a593Smuzhiyun * fnic_trace_debugfs_terminate - Tear down debugfs infrastructure
360*4882a593Smuzhiyun *
361*4882a593Smuzhiyun * Description:
362*4882a593Smuzhiyun * When Debugfs is configured this routine removes debugfs file system
363*4882a593Smuzhiyun * elements that are specific to fnic trace logging.
364*4882a593Smuzhiyun */
fnic_trace_debugfs_terminate(void)365*4882a593Smuzhiyun void fnic_trace_debugfs_terminate(void)
366*4882a593Smuzhiyun {
367*4882a593Smuzhiyun debugfs_remove(fnic_trace_debugfs_file);
368*4882a593Smuzhiyun fnic_trace_debugfs_file = NULL;
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun debugfs_remove(fnic_trace_enable);
371*4882a593Smuzhiyun fnic_trace_enable = NULL;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun /*
375*4882a593Smuzhiyun * fnic_fc_trace_debugfs_init -
376*4882a593Smuzhiyun * Initialize debugfs for fnic control frame trace logging
377*4882a593Smuzhiyun *
378*4882a593Smuzhiyun * Description:
379*4882a593Smuzhiyun * When Debugfs is configured this routine sets up the fnic_fc debugfs
380*4882a593Smuzhiyun * file system. If not already created, this routine will create the
381*4882a593Smuzhiyun * create file trace to log fnic fc trace buffer output into debugfs and
382*4882a593Smuzhiyun * it will also create file fc_trace_enable to control enable/disable of
383*4882a593Smuzhiyun * trace logging into trace buffer.
384*4882a593Smuzhiyun */
385*4882a593Smuzhiyun
fnic_fc_trace_debugfs_init(void)386*4882a593Smuzhiyun void fnic_fc_trace_debugfs_init(void)
387*4882a593Smuzhiyun {
388*4882a593Smuzhiyun fnic_fc_trace_enable = debugfs_create_file("fc_trace_enable",
389*4882a593Smuzhiyun S_IFREG|S_IRUGO|S_IWUSR,
390*4882a593Smuzhiyun fnic_trace_debugfs_root,
391*4882a593Smuzhiyun &(fc_trc_flag->fc_trace),
392*4882a593Smuzhiyun &fnic_trace_ctrl_fops);
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun fnic_fc_trace_clear = debugfs_create_file("fc_trace_clear",
395*4882a593Smuzhiyun S_IFREG|S_IRUGO|S_IWUSR,
396*4882a593Smuzhiyun fnic_trace_debugfs_root,
397*4882a593Smuzhiyun &(fc_trc_flag->fc_clear),
398*4882a593Smuzhiyun &fnic_trace_ctrl_fops);
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun fnic_fc_rdata_trace_debugfs_file =
401*4882a593Smuzhiyun debugfs_create_file("fc_trace_rdata",
402*4882a593Smuzhiyun S_IFREG|S_IRUGO|S_IWUSR,
403*4882a593Smuzhiyun fnic_trace_debugfs_root,
404*4882a593Smuzhiyun &(fc_trc_flag->fc_normal_file),
405*4882a593Smuzhiyun &fnic_trace_debugfs_fops);
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun fnic_fc_trace_debugfs_file =
408*4882a593Smuzhiyun debugfs_create_file("fc_trace",
409*4882a593Smuzhiyun S_IFREG|S_IRUGO|S_IWUSR,
410*4882a593Smuzhiyun fnic_trace_debugfs_root,
411*4882a593Smuzhiyun &(fc_trc_flag->fc_row_file),
412*4882a593Smuzhiyun &fnic_trace_debugfs_fops);
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun /*
416*4882a593Smuzhiyun * fnic_fc_trace_debugfs_terminate - Tear down debugfs infrastructure
417*4882a593Smuzhiyun *
418*4882a593Smuzhiyun * Description:
419*4882a593Smuzhiyun * When Debugfs is configured this routine removes debugfs file system
420*4882a593Smuzhiyun * elements that are specific to fnic_fc trace logging.
421*4882a593Smuzhiyun */
422*4882a593Smuzhiyun
fnic_fc_trace_debugfs_terminate(void)423*4882a593Smuzhiyun void fnic_fc_trace_debugfs_terminate(void)
424*4882a593Smuzhiyun {
425*4882a593Smuzhiyun debugfs_remove(fnic_fc_trace_debugfs_file);
426*4882a593Smuzhiyun fnic_fc_trace_debugfs_file = NULL;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun debugfs_remove(fnic_fc_rdata_trace_debugfs_file);
429*4882a593Smuzhiyun fnic_fc_rdata_trace_debugfs_file = NULL;
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun debugfs_remove(fnic_fc_trace_enable);
432*4882a593Smuzhiyun fnic_fc_trace_enable = NULL;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun debugfs_remove(fnic_fc_trace_clear);
435*4882a593Smuzhiyun fnic_fc_trace_clear = NULL;
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun /*
439*4882a593Smuzhiyun * fnic_reset_stats_open - Open the reset_stats file
440*4882a593Smuzhiyun * @inode: The inode pointer.
441*4882a593Smuzhiyun * @file: The file pointer to attach the stats reset flag.
442*4882a593Smuzhiyun *
443*4882a593Smuzhiyun * Description:
444*4882a593Smuzhiyun * This routine opens a debugsfs file reset_stats and stores i_private data
445*4882a593Smuzhiyun * to debug structure to retrieve later for while performing other
446*4882a593Smuzhiyun * file oprations.
447*4882a593Smuzhiyun *
448*4882a593Smuzhiyun * Returns:
449*4882a593Smuzhiyun * This function returns zero if successful.
450*4882a593Smuzhiyun */
fnic_reset_stats_open(struct inode * inode,struct file * file)451*4882a593Smuzhiyun static int fnic_reset_stats_open(struct inode *inode, struct file *file)
452*4882a593Smuzhiyun {
453*4882a593Smuzhiyun struct stats_debug_info *debug;
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun debug = kzalloc(sizeof(struct stats_debug_info), GFP_KERNEL);
456*4882a593Smuzhiyun if (!debug)
457*4882a593Smuzhiyun return -ENOMEM;
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun debug->i_private = inode->i_private;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun file->private_data = debug;
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun return 0;
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun /*
467*4882a593Smuzhiyun * fnic_reset_stats_read - Read a reset_stats debugfs file
468*4882a593Smuzhiyun * @filp: The file pointer to read from.
469*4882a593Smuzhiyun * @ubuf: The buffer to copy the data to.
470*4882a593Smuzhiyun * @cnt: The number of bytes to read.
471*4882a593Smuzhiyun * @ppos: The position in the file to start reading from.
472*4882a593Smuzhiyun *
473*4882a593Smuzhiyun * Description:
474*4882a593Smuzhiyun * This routine reads value of variable reset_stats
475*4882a593Smuzhiyun * and stores into local @buf. It will start reading file at @ppos and
476*4882a593Smuzhiyun * copy up to @cnt of data to @ubuf from @buf.
477*4882a593Smuzhiyun *
478*4882a593Smuzhiyun * Returns:
479*4882a593Smuzhiyun * This function returns the amount of data that was read.
480*4882a593Smuzhiyun */
fnic_reset_stats_read(struct file * file,char __user * ubuf,size_t cnt,loff_t * ppos)481*4882a593Smuzhiyun static ssize_t fnic_reset_stats_read(struct file *file,
482*4882a593Smuzhiyun char __user *ubuf,
483*4882a593Smuzhiyun size_t cnt, loff_t *ppos)
484*4882a593Smuzhiyun {
485*4882a593Smuzhiyun struct stats_debug_info *debug = file->private_data;
486*4882a593Smuzhiyun struct fnic *fnic = (struct fnic *)debug->i_private;
487*4882a593Smuzhiyun char buf[64];
488*4882a593Smuzhiyun int len;
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun len = sprintf(buf, "%u\n", fnic->reset_stats);
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun return simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun /*
496*4882a593Smuzhiyun * fnic_reset_stats_write - Write to reset_stats debugfs file
497*4882a593Smuzhiyun * @filp: The file pointer to write from.
498*4882a593Smuzhiyun * @ubuf: The buffer to copy the data from.
499*4882a593Smuzhiyun * @cnt: The number of bytes to write.
500*4882a593Smuzhiyun * @ppos: The position in the file to start writing to.
501*4882a593Smuzhiyun *
502*4882a593Smuzhiyun * Description:
503*4882a593Smuzhiyun * This routine writes data from user buffer @ubuf to buffer @buf and
504*4882a593Smuzhiyun * resets cumulative stats of fnic.
505*4882a593Smuzhiyun *
506*4882a593Smuzhiyun * Returns:
507*4882a593Smuzhiyun * This function returns the amount of data that was written.
508*4882a593Smuzhiyun */
fnic_reset_stats_write(struct file * file,const char __user * ubuf,size_t cnt,loff_t * ppos)509*4882a593Smuzhiyun static ssize_t fnic_reset_stats_write(struct file *file,
510*4882a593Smuzhiyun const char __user *ubuf,
511*4882a593Smuzhiyun size_t cnt, loff_t *ppos)
512*4882a593Smuzhiyun {
513*4882a593Smuzhiyun struct stats_debug_info *debug = file->private_data;
514*4882a593Smuzhiyun struct fnic *fnic = (struct fnic *)debug->i_private;
515*4882a593Smuzhiyun struct fnic_stats *stats = &fnic->fnic_stats;
516*4882a593Smuzhiyun u64 *io_stats_p = (u64 *)&stats->io_stats;
517*4882a593Smuzhiyun u64 *fw_stats_p = (u64 *)&stats->fw_stats;
518*4882a593Smuzhiyun char buf[64];
519*4882a593Smuzhiyun unsigned long val;
520*4882a593Smuzhiyun int ret;
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun if (cnt >= sizeof(buf))
523*4882a593Smuzhiyun return -EINVAL;
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun if (copy_from_user(&buf, ubuf, cnt))
526*4882a593Smuzhiyun return -EFAULT;
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun buf[cnt] = 0;
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun ret = kstrtoul(buf, 10, &val);
531*4882a593Smuzhiyun if (ret < 0)
532*4882a593Smuzhiyun return ret;
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun fnic->reset_stats = val;
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun if (fnic->reset_stats) {
537*4882a593Smuzhiyun /* Skip variable is used to avoid descrepancies to Num IOs
538*4882a593Smuzhiyun * and IO Completions stats. Skip incrementing No IO Compls
539*4882a593Smuzhiyun * for pending active IOs after reset stats
540*4882a593Smuzhiyun */
541*4882a593Smuzhiyun atomic64_set(&fnic->io_cmpl_skip,
542*4882a593Smuzhiyun atomic64_read(&stats->io_stats.active_ios));
543*4882a593Smuzhiyun memset(&stats->abts_stats, 0, sizeof(struct abort_stats));
544*4882a593Smuzhiyun memset(&stats->term_stats, 0,
545*4882a593Smuzhiyun sizeof(struct terminate_stats));
546*4882a593Smuzhiyun memset(&stats->reset_stats, 0, sizeof(struct reset_stats));
547*4882a593Smuzhiyun memset(&stats->misc_stats, 0, sizeof(struct misc_stats));
548*4882a593Smuzhiyun memset(&stats->vlan_stats, 0, sizeof(struct vlan_stats));
549*4882a593Smuzhiyun memset(io_stats_p+1, 0,
550*4882a593Smuzhiyun sizeof(struct io_path_stats) - sizeof(u64));
551*4882a593Smuzhiyun memset(fw_stats_p+1, 0,
552*4882a593Smuzhiyun sizeof(struct fw_stats) - sizeof(u64));
553*4882a593Smuzhiyun ktime_get_real_ts64(&stats->stats_timestamps.last_reset_time);
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun (*ppos)++;
557*4882a593Smuzhiyun return cnt;
558*4882a593Smuzhiyun }
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun /*
561*4882a593Smuzhiyun * fnic_reset_stats_release - Release the buffer used to store
562*4882a593Smuzhiyun * debugfs file data
563*4882a593Smuzhiyun * @inode: The inode pointer
564*4882a593Smuzhiyun * @file: The file pointer that contains the buffer to release
565*4882a593Smuzhiyun *
566*4882a593Smuzhiyun * Description:
567*4882a593Smuzhiyun * This routine frees the buffer that was allocated when the debugfs
568*4882a593Smuzhiyun * file was opened.
569*4882a593Smuzhiyun *
570*4882a593Smuzhiyun * Returns:
571*4882a593Smuzhiyun * This function returns zero.
572*4882a593Smuzhiyun */
fnic_reset_stats_release(struct inode * inode,struct file * file)573*4882a593Smuzhiyun static int fnic_reset_stats_release(struct inode *inode,
574*4882a593Smuzhiyun struct file *file)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun struct stats_debug_info *debug = file->private_data;
577*4882a593Smuzhiyun kfree(debug);
578*4882a593Smuzhiyun return 0;
579*4882a593Smuzhiyun }
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun /*
582*4882a593Smuzhiyun * fnic_stats_debugfs_open - Open the stats file for specific host
583*4882a593Smuzhiyun * and get fnic stats.
584*4882a593Smuzhiyun * @inode: The inode pointer.
585*4882a593Smuzhiyun * @file: The file pointer to attach the specific host statistics.
586*4882a593Smuzhiyun *
587*4882a593Smuzhiyun * Description:
588*4882a593Smuzhiyun * This routine opens a debugsfs file stats of specific host and print
589*4882a593Smuzhiyun * fnic stats.
590*4882a593Smuzhiyun *
591*4882a593Smuzhiyun * Returns:
592*4882a593Smuzhiyun * This function returns zero if successful.
593*4882a593Smuzhiyun */
fnic_stats_debugfs_open(struct inode * inode,struct file * file)594*4882a593Smuzhiyun static int fnic_stats_debugfs_open(struct inode *inode,
595*4882a593Smuzhiyun struct file *file)
596*4882a593Smuzhiyun {
597*4882a593Smuzhiyun struct fnic *fnic = inode->i_private;
598*4882a593Smuzhiyun struct fnic_stats *fnic_stats = &fnic->fnic_stats;
599*4882a593Smuzhiyun struct stats_debug_info *debug;
600*4882a593Smuzhiyun int buf_size = 2 * PAGE_SIZE;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun debug = kzalloc(sizeof(struct stats_debug_info), GFP_KERNEL);
603*4882a593Smuzhiyun if (!debug)
604*4882a593Smuzhiyun return -ENOMEM;
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun debug->debug_buffer = vmalloc(buf_size);
607*4882a593Smuzhiyun if (!debug->debug_buffer) {
608*4882a593Smuzhiyun kfree(debug);
609*4882a593Smuzhiyun return -ENOMEM;
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun debug->buf_size = buf_size;
613*4882a593Smuzhiyun memset((void *)debug->debug_buffer, 0, buf_size);
614*4882a593Smuzhiyun debug->buffer_len = fnic_get_stats_data(debug, fnic_stats);
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun file->private_data = debug;
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun return 0;
619*4882a593Smuzhiyun }
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun /*
622*4882a593Smuzhiyun * fnic_stats_debugfs_read - Read a debugfs file
623*4882a593Smuzhiyun * @file: The file pointer to read from.
624*4882a593Smuzhiyun * @ubuf: The buffer to copy the data to.
625*4882a593Smuzhiyun * @nbytes: The number of bytes to read.
626*4882a593Smuzhiyun * @pos: The position in the file to start reading from.
627*4882a593Smuzhiyun *
628*4882a593Smuzhiyun * Description:
629*4882a593Smuzhiyun * This routine reads data from the buffer indicated in the private_data
630*4882a593Smuzhiyun * field of @file. It will start reading at @pos and copy up to @nbytes of
631*4882a593Smuzhiyun * data to @ubuf.
632*4882a593Smuzhiyun *
633*4882a593Smuzhiyun * Returns:
634*4882a593Smuzhiyun * This function returns the amount of data that was read (this could be
635*4882a593Smuzhiyun * less than @nbytes if the end of the file was reached).
636*4882a593Smuzhiyun */
fnic_stats_debugfs_read(struct file * file,char __user * ubuf,size_t nbytes,loff_t * pos)637*4882a593Smuzhiyun static ssize_t fnic_stats_debugfs_read(struct file *file,
638*4882a593Smuzhiyun char __user *ubuf,
639*4882a593Smuzhiyun size_t nbytes,
640*4882a593Smuzhiyun loff_t *pos)
641*4882a593Smuzhiyun {
642*4882a593Smuzhiyun struct stats_debug_info *debug = file->private_data;
643*4882a593Smuzhiyun int rc = 0;
644*4882a593Smuzhiyun rc = simple_read_from_buffer(ubuf, nbytes, pos,
645*4882a593Smuzhiyun debug->debug_buffer,
646*4882a593Smuzhiyun debug->buffer_len);
647*4882a593Smuzhiyun return rc;
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun /*
651*4882a593Smuzhiyun * fnic_stats_stats_release - Release the buffer used to store
652*4882a593Smuzhiyun * debugfs file data
653*4882a593Smuzhiyun * @inode: The inode pointer
654*4882a593Smuzhiyun * @file: The file pointer that contains the buffer to release
655*4882a593Smuzhiyun *
656*4882a593Smuzhiyun * Description:
657*4882a593Smuzhiyun * This routine frees the buffer that was allocated when the debugfs
658*4882a593Smuzhiyun * file was opened.
659*4882a593Smuzhiyun *
660*4882a593Smuzhiyun * Returns:
661*4882a593Smuzhiyun * This function returns zero.
662*4882a593Smuzhiyun */
fnic_stats_debugfs_release(struct inode * inode,struct file * file)663*4882a593Smuzhiyun static int fnic_stats_debugfs_release(struct inode *inode,
664*4882a593Smuzhiyun struct file *file)
665*4882a593Smuzhiyun {
666*4882a593Smuzhiyun struct stats_debug_info *debug = file->private_data;
667*4882a593Smuzhiyun vfree(debug->debug_buffer);
668*4882a593Smuzhiyun kfree(debug);
669*4882a593Smuzhiyun return 0;
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun static const struct file_operations fnic_stats_debugfs_fops = {
673*4882a593Smuzhiyun .owner = THIS_MODULE,
674*4882a593Smuzhiyun .open = fnic_stats_debugfs_open,
675*4882a593Smuzhiyun .read = fnic_stats_debugfs_read,
676*4882a593Smuzhiyun .release = fnic_stats_debugfs_release,
677*4882a593Smuzhiyun };
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun static const struct file_operations fnic_reset_debugfs_fops = {
680*4882a593Smuzhiyun .owner = THIS_MODULE,
681*4882a593Smuzhiyun .open = fnic_reset_stats_open,
682*4882a593Smuzhiyun .read = fnic_reset_stats_read,
683*4882a593Smuzhiyun .write = fnic_reset_stats_write,
684*4882a593Smuzhiyun .release = fnic_reset_stats_release,
685*4882a593Smuzhiyun };
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun /*
688*4882a593Smuzhiyun * fnic_stats_init - Initialize stats struct and create stats file per fnic
689*4882a593Smuzhiyun *
690*4882a593Smuzhiyun * Description:
691*4882a593Smuzhiyun * When Debugfs is configured this routine sets up the stats file per fnic
692*4882a593Smuzhiyun * It will create file stats and reset_stats under statistics/host# directory
693*4882a593Smuzhiyun * to log per fnic stats.
694*4882a593Smuzhiyun */
fnic_stats_debugfs_init(struct fnic * fnic)695*4882a593Smuzhiyun void fnic_stats_debugfs_init(struct fnic *fnic)
696*4882a593Smuzhiyun {
697*4882a593Smuzhiyun char name[16];
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun snprintf(name, sizeof(name), "host%d", fnic->lport->host->host_no);
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun fnic->fnic_stats_debugfs_host = debugfs_create_dir(name,
702*4882a593Smuzhiyun fnic_stats_debugfs_root);
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun fnic->fnic_stats_debugfs_file = debugfs_create_file("stats",
705*4882a593Smuzhiyun S_IFREG|S_IRUGO|S_IWUSR,
706*4882a593Smuzhiyun fnic->fnic_stats_debugfs_host,
707*4882a593Smuzhiyun fnic,
708*4882a593Smuzhiyun &fnic_stats_debugfs_fops);
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun fnic->fnic_reset_debugfs_file = debugfs_create_file("reset_stats",
711*4882a593Smuzhiyun S_IFREG|S_IRUGO|S_IWUSR,
712*4882a593Smuzhiyun fnic->fnic_stats_debugfs_host,
713*4882a593Smuzhiyun fnic,
714*4882a593Smuzhiyun &fnic_reset_debugfs_fops);
715*4882a593Smuzhiyun }
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun /*
718*4882a593Smuzhiyun * fnic_stats_debugfs_remove - Tear down debugfs infrastructure of stats
719*4882a593Smuzhiyun *
720*4882a593Smuzhiyun * Description:
721*4882a593Smuzhiyun * When Debugfs is configured this routine removes debugfs file system
722*4882a593Smuzhiyun * elements that are specific to fnic stats.
723*4882a593Smuzhiyun */
fnic_stats_debugfs_remove(struct fnic * fnic)724*4882a593Smuzhiyun void fnic_stats_debugfs_remove(struct fnic *fnic)
725*4882a593Smuzhiyun {
726*4882a593Smuzhiyun if (!fnic)
727*4882a593Smuzhiyun return;
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun debugfs_remove(fnic->fnic_stats_debugfs_file);
730*4882a593Smuzhiyun fnic->fnic_stats_debugfs_file = NULL;
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun debugfs_remove(fnic->fnic_reset_debugfs_file);
733*4882a593Smuzhiyun fnic->fnic_reset_debugfs_file = NULL;
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun debugfs_remove(fnic->fnic_stats_debugfs_host);
736*4882a593Smuzhiyun fnic->fnic_stats_debugfs_host = NULL;
737*4882a593Smuzhiyun }
738