]> Git Repo - J-linux.git/blob - drivers/net/ethernet/intel/ice/ice_debugfs.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / net / ethernet / intel / ice / ice_debugfs.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2022, Intel Corporation. */
3
4 #include <linux/fs.h>
5 #include <linux/debugfs.h>
6 #include <linux/random.h>
7 #include <linux/vmalloc.h>
8 #include "ice.h"
9
10 static struct dentry *ice_debugfs_root;
11
12 /* create a define that has an extra module that doesn't really exist. this
13  * is so we can add a module 'all' to easily enable/disable all the modules
14  */
15 #define ICE_NR_FW_LOG_MODULES (ICE_AQC_FW_LOG_ID_MAX + 1)
16
17 /* the ordering in this array is important. it matches the ordering of the
18  * values in the FW so the index is the same value as in ice_aqc_fw_logging_mod
19  */
20 static const char * const ice_fwlog_module_string[] = {
21         "general",
22         "ctrl",
23         "link",
24         "link_topo",
25         "dnl",
26         "i2c",
27         "sdp",
28         "mdio",
29         "adminq",
30         "hdma",
31         "lldp",
32         "dcbx",
33         "dcb",
34         "xlr",
35         "nvm",
36         "auth",
37         "vpd",
38         "iosf",
39         "parser",
40         "sw",
41         "scheduler",
42         "txq",
43         "rsvd",
44         "post",
45         "watchdog",
46         "task_dispatch",
47         "mng",
48         "synce",
49         "health",
50         "tsdrv",
51         "pfreg",
52         "mdlver",
53         "all",
54 };
55
56 /* the ordering in this array is important. it matches the ordering of the
57  * values in the FW so the index is the same value as in ice_fwlog_level
58  */
59 static const char * const ice_fwlog_level_string[] = {
60         "none",
61         "error",
62         "warning",
63         "normal",
64         "verbose",
65 };
66
67 static const char * const ice_fwlog_log_size[] = {
68         "128K",
69         "256K",
70         "512K",
71         "1M",
72         "2M",
73 };
74
75 /**
76  * ice_fwlog_print_module_cfg - print current FW logging module configuration
77  * @hw: pointer to the HW structure
78  * @module: module to print
79  * @s: the seq file to put data into
80  */
81 static void
82 ice_fwlog_print_module_cfg(struct ice_hw *hw, int module, struct seq_file *s)
83 {
84         struct ice_fwlog_cfg *cfg = &hw->fwlog_cfg;
85         struct ice_fwlog_module_entry *entry;
86
87         if (module != ICE_AQC_FW_LOG_ID_MAX) {
88                 entry = &cfg->module_entries[module];
89
90                 seq_printf(s, "\tModule: %s, Log Level: %s\n",
91                            ice_fwlog_module_string[entry->module_id],
92                            ice_fwlog_level_string[entry->log_level]);
93         } else {
94                 int i;
95
96                 for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) {
97                         entry = &cfg->module_entries[i];
98
99                         seq_printf(s, "\tModule: %s, Log Level: %s\n",
100                                    ice_fwlog_module_string[entry->module_id],
101                                    ice_fwlog_level_string[entry->log_level]);
102                 }
103         }
104 }
105
106 static int ice_find_module_by_dentry(struct ice_pf *pf, struct dentry *d)
107 {
108         int i, module;
109
110         module = -1;
111         /* find the module based on the dentry */
112         for (i = 0; i < ICE_NR_FW_LOG_MODULES; i++) {
113                 if (d == pf->ice_debugfs_pf_fwlog_modules[i]) {
114                         module = i;
115                         break;
116                 }
117         }
118
119         return module;
120 }
121
122 /**
123  * ice_debugfs_module_show - read from 'module' file
124  * @s: the opened file
125  * @v: pointer to the offset
126  */
127 static int ice_debugfs_module_show(struct seq_file *s, void *v)
128 {
129         const struct file *filp = s->file;
130         struct dentry *dentry;
131         struct ice_pf *pf;
132         int module;
133
134         dentry = file_dentry(filp);
135         pf = s->private;
136
137         module = ice_find_module_by_dentry(pf, dentry);
138         if (module < 0) {
139                 dev_info(ice_pf_to_dev(pf), "unknown module\n");
140                 return -EINVAL;
141         }
142
143         ice_fwlog_print_module_cfg(&pf->hw, module, s);
144
145         return 0;
146 }
147
148 static int ice_debugfs_module_open(struct inode *inode, struct file *filp)
149 {
150         return single_open(filp, ice_debugfs_module_show, inode->i_private);
151 }
152
153 /**
154  * ice_debugfs_module_write - write into 'module' file
155  * @filp: the opened file
156  * @buf: where to find the user's data
157  * @count: the length of the user's data
158  * @ppos: file position offset
159  */
160 static ssize_t
161 ice_debugfs_module_write(struct file *filp, const char __user *buf,
162                          size_t count, loff_t *ppos)
163 {
164         struct ice_pf *pf = file_inode(filp)->i_private;
165         struct dentry *dentry = file_dentry(filp);
166         struct device *dev = ice_pf_to_dev(pf);
167         char user_val[16], *cmd_buf;
168         int module, log_level, cnt;
169
170         /* don't allow partial writes or invalid input */
171         if (*ppos != 0 || count > 8)
172                 return -EINVAL;
173
174         cmd_buf = memdup_user_nul(buf, count);
175         if (IS_ERR(cmd_buf))
176                 return PTR_ERR(cmd_buf);
177
178         module = ice_find_module_by_dentry(pf, dentry);
179         if (module < 0) {
180                 dev_info(dev, "unknown module\n");
181                 return -EINVAL;
182         }
183
184         cnt = sscanf(cmd_buf, "%s", user_val);
185         if (cnt != 1)
186                 return -EINVAL;
187
188         log_level = sysfs_match_string(ice_fwlog_level_string, user_val);
189         if (log_level < 0) {
190                 dev_info(dev, "unknown log level '%s'\n", user_val);
191                 return -EINVAL;
192         }
193
194         if (module != ICE_AQC_FW_LOG_ID_MAX) {
195                 ice_pf_fwlog_update_module(pf, log_level, module);
196         } else {
197                 /* the module 'all' is a shortcut so that we can set
198                  * all of the modules to the same level quickly
199                  */
200                 int i;
201
202                 for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++)
203                         ice_pf_fwlog_update_module(pf, log_level, i);
204         }
205
206         return count;
207 }
208
209 static const struct file_operations ice_debugfs_module_fops = {
210         .owner = THIS_MODULE,
211         .open  = ice_debugfs_module_open,
212         .read = seq_read,
213         .release = single_release,
214         .write = ice_debugfs_module_write,
215 };
216
217 /**
218  * ice_debugfs_nr_messages_read - read from 'nr_messages' file
219  * @filp: the opened file
220  * @buffer: where to write the data for the user to read
221  * @count: the size of the user's buffer
222  * @ppos: file position offset
223  */
224 static ssize_t ice_debugfs_nr_messages_read(struct file *filp,
225                                             char __user *buffer, size_t count,
226                                             loff_t *ppos)
227 {
228         struct ice_pf *pf = filp->private_data;
229         struct ice_hw *hw = &pf->hw;
230         char buff[32] = {};
231
232         snprintf(buff, sizeof(buff), "%d\n",
233                  hw->fwlog_cfg.log_resolution);
234
235         return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff));
236 }
237
238 /**
239  * ice_debugfs_nr_messages_write - write into 'nr_messages' file
240  * @filp: the opened file
241  * @buf: where to find the user's data
242  * @count: the length of the user's data
243  * @ppos: file position offset
244  */
245 static ssize_t
246 ice_debugfs_nr_messages_write(struct file *filp, const char __user *buf,
247                               size_t count, loff_t *ppos)
248 {
249         struct ice_pf *pf = filp->private_data;
250         struct device *dev = ice_pf_to_dev(pf);
251         struct ice_hw *hw = &pf->hw;
252         char user_val[8], *cmd_buf;
253         s16 nr_messages;
254         ssize_t ret;
255
256         /* don't allow partial writes or invalid input */
257         if (*ppos != 0 || count > 4)
258                 return -EINVAL;
259
260         cmd_buf = memdup_user_nul(buf, count);
261         if (IS_ERR(cmd_buf))
262                 return PTR_ERR(cmd_buf);
263
264         ret = sscanf(cmd_buf, "%s", user_val);
265         if (ret != 1)
266                 return -EINVAL;
267
268         ret = kstrtos16(user_val, 0, &nr_messages);
269         if (ret)
270                 return ret;
271
272         if (nr_messages < ICE_AQC_FW_LOG_MIN_RESOLUTION ||
273             nr_messages > ICE_AQC_FW_LOG_MAX_RESOLUTION) {
274                 dev_err(dev, "Invalid FW log number of messages %d, value must be between %d - %d\n",
275                         nr_messages, ICE_AQC_FW_LOG_MIN_RESOLUTION,
276                         ICE_AQC_FW_LOG_MAX_RESOLUTION);
277                 return -EINVAL;
278         }
279
280         hw->fwlog_cfg.log_resolution = nr_messages;
281
282         return count;
283 }
284
285 static const struct file_operations ice_debugfs_nr_messages_fops = {
286         .owner = THIS_MODULE,
287         .open  = simple_open,
288         .read = ice_debugfs_nr_messages_read,
289         .write = ice_debugfs_nr_messages_write,
290 };
291
292 /**
293  * ice_debugfs_enable_read - read from 'enable' file
294  * @filp: the opened file
295  * @buffer: where to write the data for the user to read
296  * @count: the size of the user's buffer
297  * @ppos: file position offset
298  */
299 static ssize_t ice_debugfs_enable_read(struct file *filp,
300                                        char __user *buffer, size_t count,
301                                        loff_t *ppos)
302 {
303         struct ice_pf *pf = filp->private_data;
304         struct ice_hw *hw = &pf->hw;
305         char buff[32] = {};
306
307         snprintf(buff, sizeof(buff), "%u\n",
308                  (u16)(hw->fwlog_cfg.options &
309                  ICE_FWLOG_OPTION_IS_REGISTERED) >> 3);
310
311         return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff));
312 }
313
314 /**
315  * ice_debugfs_enable_write - write into 'enable' file
316  * @filp: the opened file
317  * @buf: where to find the user's data
318  * @count: the length of the user's data
319  * @ppos: file position offset
320  */
321 static ssize_t
322 ice_debugfs_enable_write(struct file *filp, const char __user *buf,
323                          size_t count, loff_t *ppos)
324 {
325         struct ice_pf *pf = filp->private_data;
326         struct ice_hw *hw = &pf->hw;
327         char user_val[8], *cmd_buf;
328         bool enable;
329         ssize_t ret;
330
331         /* don't allow partial writes or invalid input */
332         if (*ppos != 0 || count > 2)
333                 return -EINVAL;
334
335         cmd_buf = memdup_user_nul(buf, count);
336         if (IS_ERR(cmd_buf))
337                 return PTR_ERR(cmd_buf);
338
339         ret = sscanf(cmd_buf, "%s", user_val);
340         if (ret != 1)
341                 return -EINVAL;
342
343         ret = kstrtobool(user_val, &enable);
344         if (ret)
345                 goto enable_write_error;
346
347         if (enable)
348                 hw->fwlog_cfg.options |= ICE_FWLOG_OPTION_ARQ_ENA;
349         else
350                 hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_ARQ_ENA;
351
352         ret = ice_fwlog_set(hw, &hw->fwlog_cfg);
353         if (ret)
354                 goto enable_write_error;
355
356         if (enable)
357                 ret = ice_fwlog_register(hw);
358         else
359                 ret = ice_fwlog_unregister(hw);
360
361         if (ret)
362                 goto enable_write_error;
363
364         /* if we get here, nothing went wrong; return count since we didn't
365          * really write anything
366          */
367         ret = (ssize_t)count;
368
369 enable_write_error:
370         /* This function always consumes all of the written input, or produces
371          * an error. Check and enforce this. Otherwise, the write operation
372          * won't complete properly.
373          */
374         if (WARN_ON(ret != (ssize_t)count && ret >= 0))
375                 ret = -EIO;
376
377         return ret;
378 }
379
380 static const struct file_operations ice_debugfs_enable_fops = {
381         .owner = THIS_MODULE,
382         .open  = simple_open,
383         .read = ice_debugfs_enable_read,
384         .write = ice_debugfs_enable_write,
385 };
386
387 /**
388  * ice_debugfs_log_size_read - read from 'log_size' file
389  * @filp: the opened file
390  * @buffer: where to write the data for the user to read
391  * @count: the size of the user's buffer
392  * @ppos: file position offset
393  */
394 static ssize_t ice_debugfs_log_size_read(struct file *filp,
395                                          char __user *buffer, size_t count,
396                                          loff_t *ppos)
397 {
398         struct ice_pf *pf = filp->private_data;
399         struct ice_hw *hw = &pf->hw;
400         char buff[32] = {};
401         int index;
402
403         index = hw->fwlog_ring.index;
404         snprintf(buff, sizeof(buff), "%s\n", ice_fwlog_log_size[index]);
405
406         return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff));
407 }
408
409 /**
410  * ice_debugfs_log_size_write - write into 'log_size' file
411  * @filp: the opened file
412  * @buf: where to find the user's data
413  * @count: the length of the user's data
414  * @ppos: file position offset
415  */
416 static ssize_t
417 ice_debugfs_log_size_write(struct file *filp, const char __user *buf,
418                            size_t count, loff_t *ppos)
419 {
420         struct ice_pf *pf = filp->private_data;
421         struct device *dev = ice_pf_to_dev(pf);
422         struct ice_hw *hw = &pf->hw;
423         char user_val[8], *cmd_buf;
424         ssize_t ret;
425         int index;
426
427         /* don't allow partial writes or invalid input */
428         if (*ppos != 0 || count > 5)
429                 return -EINVAL;
430
431         cmd_buf = memdup_user_nul(buf, count);
432         if (IS_ERR(cmd_buf))
433                 return PTR_ERR(cmd_buf);
434
435         ret = sscanf(cmd_buf, "%s", user_val);
436         if (ret != 1)
437                 return -EINVAL;
438
439         index = sysfs_match_string(ice_fwlog_log_size, user_val);
440         if (index < 0) {
441                 dev_info(dev, "Invalid log size '%s'. The value must be one of 128K, 256K, 512K, 1M, 2M\n",
442                          user_val);
443                 ret = -EINVAL;
444                 goto log_size_write_error;
445         } else if (hw->fwlog_cfg.options & ICE_FWLOG_OPTION_IS_REGISTERED) {
446                 dev_info(dev, "FW logging is currently running. Please disable FW logging to change log_size\n");
447                 ret = -EINVAL;
448                 goto log_size_write_error;
449         }
450
451         /* free all the buffers and the tracking info and resize */
452         ice_fwlog_realloc_rings(hw, index);
453
454         /* if we get here, nothing went wrong; return count since we didn't
455          * really write anything
456          */
457         ret = (ssize_t)count;
458
459 log_size_write_error:
460         /* This function always consumes all of the written input, or produces
461          * an error. Check and enforce this. Otherwise, the write operation
462          * won't complete properly.
463          */
464         if (WARN_ON(ret != (ssize_t)count && ret >= 0))
465                 ret = -EIO;
466
467         return ret;
468 }
469
470 static const struct file_operations ice_debugfs_log_size_fops = {
471         .owner = THIS_MODULE,
472         .open  = simple_open,
473         .read = ice_debugfs_log_size_read,
474         .write = ice_debugfs_log_size_write,
475 };
476
477 /**
478  * ice_debugfs_data_read - read from 'data' file
479  * @filp: the opened file
480  * @buffer: where to write the data for the user to read
481  * @count: the size of the user's buffer
482  * @ppos: file position offset
483  */
484 static ssize_t ice_debugfs_data_read(struct file *filp, char __user *buffer,
485                                      size_t count, loff_t *ppos)
486 {
487         struct ice_pf *pf = filp->private_data;
488         struct ice_hw *hw = &pf->hw;
489         int data_copied = 0;
490         bool done = false;
491
492         if (ice_fwlog_ring_empty(&hw->fwlog_ring))
493                 return 0;
494
495         while (!ice_fwlog_ring_empty(&hw->fwlog_ring) && !done) {
496                 struct ice_fwlog_data *log;
497                 u16 cur_buf_len;
498
499                 log = &hw->fwlog_ring.rings[hw->fwlog_ring.head];
500                 cur_buf_len = log->data_size;
501                 if (cur_buf_len >= count) {
502                         done = true;
503                         continue;
504                 }
505
506                 if (copy_to_user(buffer, log->data, cur_buf_len)) {
507                         /* if there is an error then bail and return whatever
508                          * the driver has copied so far
509                          */
510                         done = true;
511                         continue;
512                 }
513
514                 data_copied += cur_buf_len;
515                 buffer += cur_buf_len;
516                 count -= cur_buf_len;
517                 *ppos += cur_buf_len;
518                 ice_fwlog_ring_increment(&hw->fwlog_ring.head,
519                                          hw->fwlog_ring.size);
520         }
521
522         return data_copied;
523 }
524
525 /**
526  * ice_debugfs_data_write - write into 'data' file
527  * @filp: the opened file
528  * @buf: where to find the user's data
529  * @count: the length of the user's data
530  * @ppos: file position offset
531  */
532 static ssize_t
533 ice_debugfs_data_write(struct file *filp, const char __user *buf, size_t count,
534                        loff_t *ppos)
535 {
536         struct ice_pf *pf = filp->private_data;
537         struct device *dev = ice_pf_to_dev(pf);
538         struct ice_hw *hw = &pf->hw;
539         ssize_t ret;
540
541         /* don't allow partial writes */
542         if (*ppos != 0)
543                 return 0;
544
545         /* any value is allowed to clear the buffer so no need to even look at
546          * what the value is
547          */
548         if (!(hw->fwlog_cfg.options & ICE_FWLOG_OPTION_IS_REGISTERED)) {
549                 hw->fwlog_ring.head = 0;
550                 hw->fwlog_ring.tail = 0;
551         } else {
552                 dev_info(dev, "Can't clear FW log data while FW log running\n");
553                 ret = -EINVAL;
554                 goto nr_buffs_write_error;
555         }
556
557         /* if we get here, nothing went wrong; return count since we didn't
558          * really write anything
559          */
560         ret = (ssize_t)count;
561
562 nr_buffs_write_error:
563         /* This function always consumes all of the written input, or produces
564          * an error. Check and enforce this. Otherwise, the write operation
565          * won't complete properly.
566          */
567         if (WARN_ON(ret != (ssize_t)count && ret >= 0))
568                 ret = -EIO;
569
570         return ret;
571 }
572
573 static const struct file_operations ice_debugfs_data_fops = {
574         .owner = THIS_MODULE,
575         .open  = simple_open,
576         .read = ice_debugfs_data_read,
577         .write = ice_debugfs_data_write,
578 };
579
580 /**
581  * ice_debugfs_fwlog_init - setup the debugfs directory
582  * @pf: the ice that is starting up
583  */
584 void ice_debugfs_fwlog_init(struct ice_pf *pf)
585 {
586         const char *name = pci_name(pf->pdev);
587         struct dentry *fw_modules_dir;
588         struct dentry **fw_modules;
589         int i;
590
591         /* only support fw log commands on PF 0 */
592         if (pf->hw.bus.func)
593                 return;
594
595         /* allocate space for this first because if it fails then we don't
596          * need to unwind
597          */
598         fw_modules = kcalloc(ICE_NR_FW_LOG_MODULES, sizeof(*fw_modules),
599                              GFP_KERNEL);
600         if (!fw_modules)
601                 return;
602
603         pf->ice_debugfs_pf = debugfs_create_dir(name, ice_debugfs_root);
604         if (IS_ERR(pf->ice_debugfs_pf))
605                 goto err_create_module_files;
606
607         pf->ice_debugfs_pf_fwlog = debugfs_create_dir("fwlog",
608                                                       pf->ice_debugfs_pf);
609         if (IS_ERR(pf->ice_debugfs_pf))
610                 goto err_create_module_files;
611
612         fw_modules_dir = debugfs_create_dir("modules",
613                                             pf->ice_debugfs_pf_fwlog);
614         if (IS_ERR(fw_modules_dir))
615                 goto err_create_module_files;
616
617         for (i = 0; i < ICE_NR_FW_LOG_MODULES; i++) {
618                 fw_modules[i] = debugfs_create_file(ice_fwlog_module_string[i],
619                                                     0600, fw_modules_dir, pf,
620                                                     &ice_debugfs_module_fops);
621                 if (IS_ERR(fw_modules[i]))
622                         goto err_create_module_files;
623         }
624
625         debugfs_create_file("nr_messages", 0600,
626                             pf->ice_debugfs_pf_fwlog, pf,
627                             &ice_debugfs_nr_messages_fops);
628
629         pf->ice_debugfs_pf_fwlog_modules = fw_modules;
630
631         debugfs_create_file("enable", 0600, pf->ice_debugfs_pf_fwlog,
632                             pf, &ice_debugfs_enable_fops);
633
634         debugfs_create_file("log_size", 0600, pf->ice_debugfs_pf_fwlog,
635                             pf, &ice_debugfs_log_size_fops);
636
637         debugfs_create_file("data", 0600, pf->ice_debugfs_pf_fwlog,
638                             pf, &ice_debugfs_data_fops);
639
640         return;
641
642 err_create_module_files:
643         debugfs_remove_recursive(pf->ice_debugfs_pf_fwlog);
644         kfree(fw_modules);
645 }
646
647 /**
648  * ice_debugfs_pf_deinit - cleanup PF's debugfs
649  * @pf: pointer to the PF struct
650  */
651 void ice_debugfs_pf_deinit(struct ice_pf *pf)
652 {
653         debugfs_remove_recursive(pf->ice_debugfs_pf);
654         pf->ice_debugfs_pf = NULL;
655 }
656
657 /**
658  * ice_debugfs_init - create root directory for debugfs entries
659  */
660 void ice_debugfs_init(void)
661 {
662         ice_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
663         if (IS_ERR(ice_debugfs_root))
664                 pr_info("init of debugfs failed\n");
665 }
666
667 /**
668  * ice_debugfs_exit - remove debugfs entries
669  */
670 void ice_debugfs_exit(void)
671 {
672         debugfs_remove_recursive(ice_debugfs_root);
673         ice_debugfs_root = NULL;
674 }
This page took 0.064932 seconds and 4 git commands to generate.