xref: /linux/drivers/net/ethernet/intel/ice/ice_debugfs.c (revision eed4edda910fe34dfae8c6bfbcf57f4593a54295)
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 }
668