1b2292360Sliuzhongzhu // SPDX-License-Identifier: GPL-2.0+
2b2292360Sliuzhongzhu /* Copyright (c) 2018-2019 Hisilicon Limited. */
3b2292360Sliuzhongzhu 
4b2292360Sliuzhongzhu #include <linux/debugfs.h>
5b2292360Sliuzhongzhu #include <linux/device.h>
6b2292360Sliuzhongzhu 
7b2292360Sliuzhongzhu #include "hnae3.h"
8b2292360Sliuzhongzhu #include "hns3_enet.h"
9b2292360Sliuzhongzhu 
10b2292360Sliuzhongzhu #define HNS3_DBG_READ_LEN 256
11b2292360Sliuzhongzhu 
12b2292360Sliuzhongzhu static struct dentry *hns3_dbgfs_root;
13b2292360Sliuzhongzhu 
14b2292360Sliuzhongzhu static void hns3_dbg_help(struct hnae3_handle *h)
15b2292360Sliuzhongzhu {
16b2292360Sliuzhongzhu 	dev_info(&h->pdev->dev, "available commands\n");
17b2292360Sliuzhongzhu 	dev_info(&h->pdev->dev, "queue info [number]\n");
18b2292360Sliuzhongzhu 	dev_info(&h->pdev->dev, "dump fd tcam\n");
19b2292360Sliuzhongzhu }
20b2292360Sliuzhongzhu 
21b2292360Sliuzhongzhu static ssize_t hns3_dbg_cmd_read(struct file *filp, char __user *buffer,
22b2292360Sliuzhongzhu 				 size_t count, loff_t *ppos)
23b2292360Sliuzhongzhu {
24b2292360Sliuzhongzhu 	int uncopy_bytes;
25b2292360Sliuzhongzhu 	char *buf;
26b2292360Sliuzhongzhu 	int len;
27b2292360Sliuzhongzhu 
28b2292360Sliuzhongzhu 	if (*ppos != 0)
29b2292360Sliuzhongzhu 		return 0;
30b2292360Sliuzhongzhu 
31b2292360Sliuzhongzhu 	if (count < HNS3_DBG_READ_LEN)
32b2292360Sliuzhongzhu 		return -ENOSPC;
33b2292360Sliuzhongzhu 
34b2292360Sliuzhongzhu 	buf = kzalloc(HNS3_DBG_READ_LEN, GFP_KERNEL);
35b2292360Sliuzhongzhu 	if (!buf)
36b2292360Sliuzhongzhu 		return -ENOMEM;
37b2292360Sliuzhongzhu 
38b2292360Sliuzhongzhu 	len = snprintf(buf, HNS3_DBG_READ_LEN, "%s\n",
39b2292360Sliuzhongzhu 		       "Please echo help to cmd to get help information");
40b2292360Sliuzhongzhu 	uncopy_bytes = copy_to_user(buffer, buf, len);
41b2292360Sliuzhongzhu 
42b2292360Sliuzhongzhu 	kfree(buf);
43b2292360Sliuzhongzhu 
44b2292360Sliuzhongzhu 	if (uncopy_bytes)
45b2292360Sliuzhongzhu 		return -EFAULT;
46b2292360Sliuzhongzhu 
47b2292360Sliuzhongzhu 	return (*ppos = len);
48b2292360Sliuzhongzhu }
49b2292360Sliuzhongzhu 
50b2292360Sliuzhongzhu static ssize_t hns3_dbg_cmd_write(struct file *filp, const char __user *buffer,
51b2292360Sliuzhongzhu 				  size_t count, loff_t *ppos)
52b2292360Sliuzhongzhu {
53b2292360Sliuzhongzhu 	struct hnae3_handle *handle = filp->private_data;
54b2292360Sliuzhongzhu 	char *cmd_buf, *cmd_buf_tmp;
55b2292360Sliuzhongzhu 	int uncopied_bytes;
56b2292360Sliuzhongzhu 	int ret = 0;
57b2292360Sliuzhongzhu 
58b2292360Sliuzhongzhu 	if (*ppos != 0)
59b2292360Sliuzhongzhu 		return 0;
60b2292360Sliuzhongzhu 
61b2292360Sliuzhongzhu 	cmd_buf = kzalloc(count + 1, GFP_KERNEL);
62b2292360Sliuzhongzhu 	if (!cmd_buf)
63b2292360Sliuzhongzhu 		return count;
64b2292360Sliuzhongzhu 
65b2292360Sliuzhongzhu 	uncopied_bytes = copy_from_user(cmd_buf, buffer, count);
66b2292360Sliuzhongzhu 	if (uncopied_bytes) {
67b2292360Sliuzhongzhu 		kfree(cmd_buf);
68b2292360Sliuzhongzhu 		return -EFAULT;
69b2292360Sliuzhongzhu 	}
70b2292360Sliuzhongzhu 
71b2292360Sliuzhongzhu 	cmd_buf[count] = '\0';
72b2292360Sliuzhongzhu 
73b2292360Sliuzhongzhu 	cmd_buf_tmp = strchr(cmd_buf, '\n');
74b2292360Sliuzhongzhu 	if (cmd_buf_tmp) {
75b2292360Sliuzhongzhu 		*cmd_buf_tmp = '\0';
76b2292360Sliuzhongzhu 		count = cmd_buf_tmp - cmd_buf + 1;
77b2292360Sliuzhongzhu 	}
78b2292360Sliuzhongzhu 
79b2292360Sliuzhongzhu 	if (strncmp(cmd_buf, "help", 4) == 0)
80b2292360Sliuzhongzhu 		hns3_dbg_help(handle);
81b2292360Sliuzhongzhu 
82b2292360Sliuzhongzhu 	if (ret)
83b2292360Sliuzhongzhu 		hns3_dbg_help(handle);
84b2292360Sliuzhongzhu 
85b2292360Sliuzhongzhu 	kfree(cmd_buf);
86b2292360Sliuzhongzhu 	cmd_buf = NULL;
87b2292360Sliuzhongzhu 
88b2292360Sliuzhongzhu 	return count;
89b2292360Sliuzhongzhu }
90b2292360Sliuzhongzhu 
91b2292360Sliuzhongzhu static const struct file_operations hns3_dbg_cmd_fops = {
92b2292360Sliuzhongzhu 	.owner = THIS_MODULE,
93b2292360Sliuzhongzhu 	.open  = simple_open,
94b2292360Sliuzhongzhu 	.read  = hns3_dbg_cmd_read,
95b2292360Sliuzhongzhu 	.write = hns3_dbg_cmd_write,
96b2292360Sliuzhongzhu };
97b2292360Sliuzhongzhu 
98b2292360Sliuzhongzhu void hns3_dbg_init(struct hnae3_handle *handle)
99b2292360Sliuzhongzhu {
100b2292360Sliuzhongzhu 	const char *name = pci_name(handle->pdev);
101b2292360Sliuzhongzhu 	struct dentry *pfile;
102b2292360Sliuzhongzhu 
103b2292360Sliuzhongzhu 	handle->hnae3_dbgfs = debugfs_create_dir(name, hns3_dbgfs_root);
104b2292360Sliuzhongzhu 	if (!handle->hnae3_dbgfs)
105b2292360Sliuzhongzhu 		return;
106b2292360Sliuzhongzhu 
107b2292360Sliuzhongzhu 	pfile = debugfs_create_file("cmd", 0600, handle->hnae3_dbgfs, handle,
108b2292360Sliuzhongzhu 				    &hns3_dbg_cmd_fops);
109b2292360Sliuzhongzhu 	if (!pfile) {
110b2292360Sliuzhongzhu 		debugfs_remove_recursive(handle->hnae3_dbgfs);
111b2292360Sliuzhongzhu 		handle->hnae3_dbgfs = NULL;
112b2292360Sliuzhongzhu 		dev_warn(&handle->pdev->dev, "create file for %s fail\n",
113b2292360Sliuzhongzhu 			 name);
114b2292360Sliuzhongzhu 	}
115b2292360Sliuzhongzhu }
116b2292360Sliuzhongzhu 
117b2292360Sliuzhongzhu void hns3_dbg_uninit(struct hnae3_handle *handle)
118b2292360Sliuzhongzhu {
119b2292360Sliuzhongzhu 	debugfs_remove_recursive(handle->hnae3_dbgfs);
120b2292360Sliuzhongzhu 	handle->hnae3_dbgfs = NULL;
121b2292360Sliuzhongzhu }
122b2292360Sliuzhongzhu 
123b2292360Sliuzhongzhu void hns3_dbg_register_debugfs(const char *debugfs_dir_name)
124b2292360Sliuzhongzhu {
125b2292360Sliuzhongzhu 	hns3_dbgfs_root = debugfs_create_dir(debugfs_dir_name, NULL);
126b2292360Sliuzhongzhu 	if (!hns3_dbgfs_root) {
127b2292360Sliuzhongzhu 		pr_warn("Register debugfs for %s fail\n", debugfs_dir_name);
128b2292360Sliuzhongzhu 		return;
129b2292360Sliuzhongzhu 	}
130b2292360Sliuzhongzhu }
131b2292360Sliuzhongzhu 
132b2292360Sliuzhongzhu void hns3_dbg_unregister_debugfs(void)
133b2292360Sliuzhongzhu {
134b2292360Sliuzhongzhu 	debugfs_remove_recursive(hns3_dbgfs_root);
135b2292360Sliuzhongzhu 	hns3_dbgfs_root = NULL;
136b2292360Sliuzhongzhu }
137