blob: e425e6879a1cf4d307240c37b866ffc754945c23 [file] [log] [blame]
developere5e687d2023-08-08 16:05:33 +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/device.h>
9
10#include "firmware.h"
11#include "hpdma.h"
12#include "internal.h"
13#include "mcu.h"
14#include "netsys.h"
15#include "trm.h"
16#include "tunnel.h"
17#include "wdt.h"
18
19static const char *tops_role_name[__TOPS_ROLE_TYPE_MAX] = {
20 [TOPS_ROLE_TYPE_MGMT] = "tops-mgmt",
21 [TOPS_ROLE_TYPE_CLUSTER] = "tops-offload",
22};
23
24static ssize_t mtk_tops_fw_info_show(struct device *dev,
25 struct device_attribute *attr,
26 char *buf)
27{
28 enum tops_role_type rtype;
29 struct tm tm = {0};
30 const char *value;
31 const char *prop;
32 int len = 0;
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 len += snprintf(buf + len, PAGE_SIZE - len,
40 "%s FW information:\n", tops_role_name[rtype]);
41 len += snprintf(buf + len, PAGE_SIZE - len,
42 "Git revision:\t%llx\n",
43 mtk_tops_fw_get_git_commit_id(rtype));
44 len += snprintf(buf + len, PAGE_SIZE - len,
45 "Build date:\t%04ld/%02d/%02d %02d:%02d:%02d\n",
46 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
47 tm.tm_hour, tm.tm_min, tm.tm_sec);
48
49 nattr = mtk_tops_fw_attr_get_num(rtype);
50
51 for (i = 0; i < nattr; i++) {
52 prop = mtk_tops_fw_attr_get_property(rtype, i);
53 if (!prop)
54 continue;
55
56 value = mtk_tops_fw_attr_get_value(rtype, prop);
57
58 len += snprintf(buf + len, PAGE_SIZE - len,
59 "%s:\t%s\n", prop, value);
60 }
61 len += snprintf(buf + len, PAGE_SIZE - len, "\n");
62 }
63
64 return len;
65}
66
67static int mtk_tops_ctrl_fetch_port(const char *buf, int *ofs, u16 *port)
68{
69 int nchar = 0;
70 int ret;
71 u16 p = 0;
72
73 ret = sscanf(buf + *ofs, "%hu %n", &p, &nchar);
74 if (ret != 1)
75 return -EPERM;
76
77 *port = htons(p);
78
79 *ofs += nchar;
80
81 return nchar;
82}
83
84static int mtk_tops_ctrl_fetch_ip(const char *buf, int *ofs, u32 *ip)
85{
86 int nchar = 0;
87 int ret = 0;
88 u8 tmp[4];
89
90 ret = sscanf(buf + *ofs, "%hhu.%hhu.%hhu.%hhu %n",
91 &tmp[3], &tmp[2], &tmp[1], &tmp[0], &nchar);
92 if (ret != 4)
93 return -EPERM;
94
95 *ip = tmp[0] | tmp[1] << 8 | tmp[2] << 16 | tmp[3] << 24;
96
97 *ofs += nchar;
98
99 return nchar;
100}
101
102static int mtk_tops_ctrl_fetch_mac(const char *buf, int *ofs, u8 *mac)
103{
104 int nchar = 0;
105 int ret = 0;
106
107 ret = sscanf(buf + *ofs, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %n",
108 &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5], &nchar);
109 if (ret != 6)
110 return -EPERM;
111
112 *ofs += nchar;
113
114 return 0;
115}
116
117static int mtk_tops_ctrl_add_tnl(const char *buf)
118{
119 struct tops_tnl_params tnl_params = {0};
120 struct tops_tnl_info *tnl_info;
121 struct tops_tnl_type *tnl_type;
122 char tnl_type_name[21] = {0};
123 int ofs = 0;
124 int ret = 0;
125
126 ret = sscanf(buf, "%20s %n", tnl_type_name, &ofs);
127 if (ret != 1)
128 return -EPERM;
129
130 tnl_type = mtk_tops_tnl_type_get_by_name(tnl_type_name);
131 if (unlikely(!tnl_type || !tnl_type->tnl_debug_param_setup))
132 return -ENODEV;
133
134 ret = mtk_tops_ctrl_fetch_mac(buf, &ofs, tnl_params.daddr);
135 if (ret < 0)
136 return ret;
137
138 ret = mtk_tops_ctrl_fetch_mac(buf, &ofs, tnl_params.saddr);
139 if (ret < 0)
140 return ret;
141
142 ret = mtk_tops_ctrl_fetch_ip(buf, &ofs, &tnl_params.dip);
143 if (ret < 0)
144 return ret;
145
146 ret = mtk_tops_ctrl_fetch_ip(buf, &ofs, &tnl_params.sip);
147 if (ret < 0)
148 return ret;
149
150 ret = mtk_tops_ctrl_fetch_port(buf, &ofs, &tnl_params.dport);
151 if (ret < 0)
152 return ret;
153
154 ret = mtk_tops_ctrl_fetch_port(buf, &ofs, &tnl_params.sport);
155 if (ret < 0)
156 return ret;
157
158 ret = tnl_type->tnl_debug_param_setup(buf, &ofs, &tnl_params);
159 if (ret < 0)
160 return ret;
161
162 tnl_params.flag |= TNL_DECAP_ENABLE;
163 tnl_params.flag |= TNL_ENCAP_ENABLE;
164 tnl_params.tops_entry_proto = tnl_type->tops_entry;
165
166 tnl_info = mtk_tops_tnl_info_alloc();
167 if (IS_ERR(tnl_info))
168 return -ENOMEM;
169
170 tnl_info->flag |= TNL_INFO_DEBUG;
171 memcpy(&tnl_info->cache, &tnl_params, sizeof(struct tops_tnl_params));
172
173 mtk_tops_tnl_info_hash(tnl_info);
174
175 mtk_tops_tnl_info_submit(tnl_info);
176
177 return 0;
178}
179
180static ssize_t mtk_tops_tnl_store(struct device *dev,
181 struct device_attribute *attr,
182 const char *buf,
183 size_t count)
184{
185 char cmd[21] = {0};
186 int nchar = 0;
187 int ret = 0;
188
189 ret = sscanf(buf, "%20s %n", cmd, &nchar);
190
191 if (ret != 1)
192 return -EPERM;
193
194 if (!strcmp(cmd, "NEW_TNL")) {
195 ret = mtk_tops_ctrl_add_tnl(buf + nchar);
196 if (ret)
197 return ret;
198 }
199
200 return count;
201}
202
203static int mtk_tops_trm_fetch_setting(const char *buf,
204 int *ofs,
205 char *name,
206 u32 *offset,
207 u32 *size,
208 u8 *enable)
209{
210 int nchar = 0;
211 int ret = 0;
212
213 ret = sscanf(buf + *ofs, "%31s %x %x %hhx %n",
214 name, offset, size, enable, &nchar);
215 if (ret != 4)
216 return -EPERM;
217
218 *ofs += nchar;
219
220 return nchar;
221}
222
223static ssize_t mtk_tops_trm_store(struct device *dev,
224 struct device_attribute *attr,
225 const char *buf,
226 size_t count)
227{
228 char name[TRM_CONFIG_NAME_MAX_LEN] = { 0 };
229 char cmd[21] = { 0 };
230 int nchar = 0;
231 int ret = 0;
232 u32 offset;
233 u8 enable;
234 u32 size;
235
236 ret = sscanf(buf, "%20s %n", cmd, &nchar);
237 if (ret != 1)
238 return -EPERM;
239
240 if (!strcmp(cmd, "trm_dump")) {
241 ret = mtk_trm_dump(TRM_RSN_NULL);
242 if (ret)
243 return ret;
244 } else if (!strcmp(cmd, "trm_cfg_setup")) {
245 ret = mtk_tops_trm_fetch_setting(buf, &nchar,
246 name, &offset, &size, &enable);
247 if (ret < 0)
248 return ret;
249
250 ret = mtk_trm_cfg_setup(name, offset, size, enable);
251 if (ret)
252 return ret;
253 }
254
255 return count;
256}
257
258static ssize_t mtk_tops_wdt_store(struct device *dev,
259 struct device_attribute *attr,
260 const char *buf,
261 size_t count)
262{
263 char cmd[21] = {0};
264 u32 core = 0;
265 u32 i;
266 int ret;
267
268 ret = sscanf(buf, "%20s %x", cmd, &core);
269 if (ret != 2)
270 return -EPERM;
271
272 core &= CORE_TOPS_MASK;
273 if (!strcmp(cmd, "WDT_TO")) {
274 for (i = 0; i < CORE_TOPS_NUM; i++) {
275 if (core & 0x1)
276 mtk_tops_wdt_trigger_timeout(i);
277 core >>= 1;
278 }
279 } else {
280 return -EINVAL;
281 }
282
283 return count;
284}
285
286static DEVICE_ATTR_RO(mtk_tops_fw_info);
287static DEVICE_ATTR_WO(mtk_tops_tnl);
288static DEVICE_ATTR_WO(mtk_tops_trm);
289static DEVICE_ATTR_WO(mtk_tops_wdt);
290
291static struct attribute *mtk_tops_attributes[] = {
292 &dev_attr_mtk_tops_fw_info.attr,
293 &dev_attr_mtk_tops_tnl.attr,
294 &dev_attr_mtk_tops_trm.attr,
295 &dev_attr_mtk_tops_wdt.attr,
296 NULL,
297};
298
299static const struct attribute_group mtk_tops_attr_group = {
300 .name = "mtk_tops",
301 .attrs = mtk_tops_attributes,
302};
303
304int mtk_tops_ctrl_init(struct platform_device *pdev)
305{
306 int ret = 0;
307
308 ret = sysfs_create_group(&pdev->dev.kobj, &mtk_tops_attr_group);
309 if (ret) {
310 TOPS_ERR("create sysfs failed\n");
311 return ret;
312 }
313
314 return ret;
315}
316
317void mtk_tops_ctrl_deinit(struct platform_device *pdev)
318{
319 sysfs_remove_group(&pdev->dev.kobj, &mtk_tops_attr_group);
320}