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