blob: d2c40cfbf86e3aa9903fb6470cc24c2b62fa8476 [file] [log] [blame]
developerb45f35c2023-12-04 09:51:36 +08001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) 2023 Mediatek Inc. All Rights Reserved.
4 *
5 * Author: Ren-Ting Wang <ren-ting.wang@mediatek.com>
6 */
7
8#include <linux/debugfs.h>
9#include <linux/inet.h>
10#include <linux/uaccess.h>
11
12#include "tops/debugfs.h"
13#include "tops/firmware.h"
14#include "tops/internal.h"
15#include "tops/mcu.h"
16#include "tops/trm.h"
17#include "tops/tunnel.h"
18#include "tops/wdt.h"
19
20static const char *tops_role_name[__TOPS_ROLE_TYPE_MAX] = {
21 [TOPS_ROLE_TYPE_MGMT] = "tops-mgmt",
22 [TOPS_ROLE_TYPE_CLUSTER] = "tops-offload",
23};
24
25static struct dentry *tops_fw_debugfs_root;
26
27static int tops_fw_info_show(struct seq_file *s, void *private)
28{
29 enum tops_role_type rtype;
30 struct tm tm = {0};
31 const char *value;
32 const char *prop;
33 u32 nattr;
34 u32 i;
35
36 for (rtype = TOPS_ROLE_TYPE_MGMT; rtype < __TOPS_ROLE_TYPE_MAX; rtype++) {
37 mtk_tops_fw_get_built_date(rtype, &tm);
38
39 seq_printf(s, "%s FW information:\n", tops_role_name[rtype]);
40 seq_printf(s, "Git revision:\t%llx\n",
41 mtk_tops_fw_get_git_commit_id(rtype));
42 seq_printf(s, "Build date:\t%04ld/%02d/%02d %02d:%02d:%02d\n",
43 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
44 tm.tm_hour, tm.tm_min, tm.tm_sec);
45
46 nattr = mtk_tops_fw_attr_get_num(rtype);
47
48 for (i = 0; i < nattr; i++) {
49 prop = mtk_tops_fw_attr_get_property(rtype, i);
50 if (!prop)
51 continue;
52
53 value = mtk_tops_fw_attr_get_value(rtype, prop);
54
55 seq_printf(s, "%s:\t%s\n", prop, value);
56 }
57 seq_puts(s, "\n");
58 }
59
60 return 0;
61}
62
63static int tops_tnl_show(struct seq_file *s, void *private)
64{
65 struct tops_tnl_info *tnl_info;
66 struct tops_tnl_params *tnl_params;
67 u32 i;
68
69 for (i = 0; i < CONFIG_TOPS_TNL_NUM; i++) {
70 tnl_info = mtk_tops_tnl_info_get_by_idx(i);
71 if (IS_ERR(tnl_info))
72 /* tunnel not enabled */
73 continue;
74
75 tnl_params = &tnl_info->tnl_params;
76 if (!tnl_info->tnl_type || !tnl_info->tnl_type->tnl_param_dump)
77 continue;
78
79 seq_printf(s, "Tunnel Index: %02u\n", i);
80
81 mtk_tops_mac_param_dump(s, &tnl_params->params);
82
83 mtk_tops_network_param_dump(s, &tnl_params->params);
84
85 mtk_tops_transport_param_dump(s, &tnl_params->params);
86
87 tnl_info->tnl_type->tnl_param_dump(s, &tnl_params->params);
88
89 seq_printf(s, "\tTOPS Entry: %02u CLS Entry: %02u CDRT: %02u Flag: 0x%x\n",
90 tnl_params->tops_entry_proto,
91 tnl_params->cls_entry,
92 tnl_params->cdrt,
93 tnl_params->flag);
94 }
95
96 return 0;
97}
98
99static int tops_tnl_open(struct inode *inode, struct file *file)
100{
101 return single_open(file, tops_tnl_show, file->private_data);
102}
103
104static int tops_tnl_add_new_tnl(const char *buf)
105{
106 struct tops_tnl_params tnl_params;
107 struct tops_params *params;
108 struct tops_tnl_info *tnl_info;
109 struct tops_tnl_type *tnl_type;
110 char proto[DEBUG_PROTO_LEN];
111 int ofs = 0;
112 int ret = 0;
113
114 memset(&tnl_params, 0, sizeof(struct tops_tnl_params));
115 memset(proto, 0, sizeof(proto));
116
117 params = &tnl_params.params;
118
119 ret = mtk_tops_debug_param_setup(buf, &ofs, params);
120 if (ret)
121 return ret;
122
123 ret = mtk_tops_debug_param_proto_peek(buf, ofs, proto);
124 if (ret < 0)
125 return ret;
126
127 ofs += ret;
128
129 tnl_type = mtk_tops_tnl_type_get_by_name(proto);
130 if (!tnl_type || !tnl_type->tnl_debug_param_setup)
131 return -ENODEV;
132
133 ret = tnl_type->tnl_debug_param_setup(buf, &ofs, params);
134 if (ret < 0)
135 return ret;
136
137 tnl_params.flag |= TNL_DECAP_ENABLE;
138 tnl_params.flag |= TNL_ENCAP_ENABLE;
139 tnl_params.tops_entry_proto = tnl_type->tnl_proto_type;
140
141 tnl_info = mtk_tops_tnl_info_alloc(tnl_type);
142 if (IS_ERR(tnl_info))
143 return -ENOMEM;
144
145 tnl_info->flag |= TNL_INFO_DEBUG;
146 memcpy(&tnl_info->cache, &tnl_params, sizeof(struct tops_tnl_params));
147
148 mtk_tops_tnl_info_hash(tnl_info);
149
150 mtk_tops_tnl_info_submit(tnl_info);
151
152 return 0;
153}
154
155static ssize_t tops_tnl_write(struct file *file, const char __user *buffer,
156 size_t count, loff_t *data)
157{
158 char cmd[21] = {0};
159 char buf[512];
160 int nchar = 0;
161 int ret = 0;
162
163 if (count > sizeof(buf))
164 return -ENOMEM;
165
166 if (copy_from_user(buf, buffer, count))
167 return -EFAULT;
168
169 buf[count] = '\0';
170
171 ret = sscanf(buf, "%20s %n", cmd, &nchar);
172
173 if (ret != 1)
174 return -EPERM;
175
176 if (!strcmp(cmd, "NEW_TNL")) {
177 ret = tops_tnl_add_new_tnl(buf + nchar);
178 if (ret)
179 return ret;
180 } else {
181 return -EINVAL;
182 }
183
184 return count;
185}
186
187DEFINE_SHOW_ATTRIBUTE(tops_fw_info);
188
189static const struct file_operations tops_tnl_fops = {
190 .open = tops_tnl_open,
191 .read = seq_read,
192 .write = tops_tnl_write,
193 .llseek = seq_lseek,
194 .release = single_release,
195};
196
197int mtk_tops_debugfs_init(struct platform_device *pdev)
198{
199 tops_fw_debugfs_root = debugfs_create_dir("fw", tops_debugfs_root);
200
201 debugfs_create_file("firmware_info", 0400, tops_fw_debugfs_root, NULL,
202 &tops_fw_info_fops);
203
204 debugfs_create_file("tunnel", 0444, tops_fw_debugfs_root, NULL,
205 &tops_tnl_fops);
206
207 return 0;
208}
209
210void mtk_tops_debugfs_deinit(struct platform_device *pdev)
211{
212 debugfs_remove_recursive(tops_fw_debugfs_root);
213}