blob: 2f2504317ab1d9df1622f8a936d958a11504c378 [file] [log] [blame]
developer3abe1ad2022-01-24 11:13:32 +08001/* Copyright (C) 2021-2022 Mediatek Inc. */
2#include "atenl.h"
3
4#define CHAN(_ch, _freq, _ch_80, _ch_160, ...) { \
5 .ch = _ch, \
6 .freq = _freq, \
7 .ch_80 = _ch_80, \
8 .ch_160 = _ch_160, \
9 __VA_ARGS__ \
10}
11
12struct atenl_channel {
13 /* ctrl ch */
14 u16 ch;
15 u16 freq;
16 /* center ch */
17 u16 ch_80;
18 u16 ch_160;
developer77215642023-05-15 13:52:35 +080019 u16 ch_320_1;
20 u16 ch_320_2;
developer3abe1ad2022-01-24 11:13:32 +080021 /* only use for channels that don't have 80 but has 40 */
22 u16 ch_40;
23};
24
25static const struct atenl_channel atenl_channels_5ghz[] = {
26 CHAN(8, 5040, 0, 0),
27 CHAN(12, 5060, 0, 0),
28 CHAN(16, 5080, 0, 0),
29
30 CHAN(36, 5180, 42, 50),
31 CHAN(40, 5200, 42, 50),
32 CHAN(44, 5220, 42, 50),
33 CHAN(48, 5240, 42, 50),
34
35 CHAN(52, 5260, 58, 50),
36 CHAN(56, 5280, 58, 50),
37 CHAN(60, 5300, 58, 50),
38 CHAN(64, 5320, 58, 50),
39
40 CHAN(68, 5340, 0, 0),
41 CHAN(80, 5400, 0, 0),
42 CHAN(84, 5420, 0, 0),
43 CHAN(88, 5440, 0, 0),
44 CHAN(92, 5460, 0, 0),
45 CHAN(96, 5480, 0, 0),
46
47 CHAN(100, 5500, 106, 114),
48 CHAN(104, 5520, 106, 114),
49 CHAN(108, 5540, 106, 114),
50 CHAN(112, 5560, 106, 114),
51 CHAN(116, 5580, 122, 114),
52 CHAN(120, 5600, 122, 114),
53 CHAN(124, 5620, 122, 114),
54 CHAN(128, 5640, 122, 114),
55
56 CHAN(132, 5660, 138, 0),
57 CHAN(136, 5680, 138, 0),
58 CHAN(140, 5700, 138, 0),
59 CHAN(144, 5720, 138, 0),
60
61 CHAN(149, 5745, 155, 0),
62 CHAN(153, 5765, 155, 0),
63 CHAN(157, 5785, 155, 0),
64 CHAN(161, 5805, 155, 0),
65 CHAN(165, 5825, 0, 0, .ch_40 = 167),
66 CHAN(169, 5845, 0, 0, .ch_40 = 167),
67 CHAN(173, 5865, 0, 0),
68
69 CHAN(184, 4920, 0, 0),
70 CHAN(188, 4940, 0, 0),
71 CHAN(192, 4960, 0, 0),
72 CHAN(196, 4980, 0, 0),
73};
74
75static const struct atenl_channel atenl_channels_6ghz[] = {
76 /* UNII-5 */
developer77215642023-05-15 13:52:35 +080077 CHAN(1, 5955, 7, 15, .ch_320_1 = 31),
78 CHAN(5, 5975, 7, 15, .ch_320_1 = 31),
79 CHAN(9, 5995, 7, 15, .ch_320_1 = 31),
80 CHAN(13, 6015, 7, 15, .ch_320_1 = 31),
81 CHAN(17, 6035, 23, 15, .ch_320_1 = 31),
82 CHAN(21, 6055, 23, 15, .ch_320_1 = 31),
83 CHAN(25, 6075, 23, 15, .ch_320_1 = 31),
84 CHAN(29, 6095, 23, 15, .ch_320_1 = 31),
85 CHAN(33, 6115, 39, 47, .ch_320_1 = 31, .ch_320_2 = 63),
86 CHAN(37, 6135, 39, 47, .ch_320_1 = 31, .ch_320_2 = 63),
87 CHAN(41, 6155, 39, 47, .ch_320_1 = 31, .ch_320_2 = 63),
88 CHAN(45, 6175, 39, 47, .ch_320_1 = 31, .ch_320_2 = 63),
89 CHAN(49, 6195, 55, 47, .ch_320_1 = 31, .ch_320_2 = 63),
90 CHAN(53, 6215, 55, 47, .ch_320_1 = 31, .ch_320_2 = 63),
91 CHAN(57, 6235, 55, 47, .ch_320_1 = 31, .ch_320_2 = 63),
92 CHAN(61, 6255, 55, 47, .ch_320_1 = 31, .ch_320_2 = 63),
93 CHAN(65, 6275, 71, 79, .ch_320_1 = 95, .ch_320_2 = 63),
94 CHAN(69, 6295, 71, 79, .ch_320_1 = 95, .ch_320_2 = 63),
95 CHAN(73, 6315, 71, 79, .ch_320_1 = 95, .ch_320_2 = 63),
96 CHAN(77, 6335, 71, 79, .ch_320_1 = 95, .ch_320_2 = 63),
97 CHAN(81, 6355, 87, 79, .ch_320_1 = 95, .ch_320_2 = 63),
98 CHAN(85, 6375, 87, 79, .ch_320_1 = 95, .ch_320_2 = 63),
99 CHAN(89, 6395, 87, 79, .ch_320_1 = 95, .ch_320_2 = 63),
100 CHAN(93, 6415, 87, 79, .ch_320_1 = 95, .ch_320_2 = 63),
developer3abe1ad2022-01-24 11:13:32 +0800101 /* UNII-6 */
developer77215642023-05-15 13:52:35 +0800102 CHAN(97, 6435, 103, 111, .ch_320_1 = 95, .ch_320_2 = 127),
103 CHAN(101, 6455, 103, 111, .ch_320_1 = 95, .ch_320_2 = 127),
104 CHAN(105, 6475, 103, 111, .ch_320_1 = 95, .ch_320_2 = 127),
105 CHAN(109, 6495, 103, 111, .ch_320_1 = 95, .ch_320_2 = 127),
106 CHAN(113, 6515, 119, 111, .ch_320_1 = 95, .ch_320_2 = 127),
107 CHAN(117, 6535, 119, 111, .ch_320_1 = 95, .ch_320_2 = 127),
developer3abe1ad2022-01-24 11:13:32 +0800108 /* UNII-7 */
developer77215642023-05-15 13:52:35 +0800109 CHAN(121, 6555, 119, 111, .ch_320_1 = 95, .ch_320_2 = 127),
110 CHAN(125, 6575, 119, 111, .ch_320_1 = 95, .ch_320_2 = 127),
111 CHAN(129, 6595, 135, 143, .ch_320_1 = 159, .ch_320_2 = 127),
112 CHAN(133, 6615, 135, 143, .ch_320_1 = 159, .ch_320_2 = 127),
113 CHAN(137, 6635, 135, 143, .ch_320_1 = 159, .ch_320_2 = 127),
114 CHAN(141, 6655, 135, 143, .ch_320_1 = 159, .ch_320_2 = 127),
115 CHAN(145, 6675, 151, 143, .ch_320_1 = 159, .ch_320_2 = 127),
116 CHAN(149, 6695, 151, 143, .ch_320_1 = 159, .ch_320_2 = 127),
117 CHAN(153, 6715, 151, 143, .ch_320_1 = 159, .ch_320_2 = 127),
118 CHAN(157, 6735, 151, 143, .ch_320_1 = 159, .ch_320_2 = 127),
119 CHAN(161, 6755, 167, 175, .ch_320_1 = 159, .ch_320_2 = 191),
120 CHAN(165, 6775, 167, 175, .ch_320_1 = 159, .ch_320_2 = 191),
121 CHAN(169, 6795, 167, 175, .ch_320_1 = 159, .ch_320_2 = 191),
122 CHAN(173, 6815, 167, 175, .ch_320_1 = 159, .ch_320_2 = 191),
123 CHAN(177, 6835, 183, 175, .ch_320_1 = 159, .ch_320_2 = 191),
124 CHAN(181, 6855, 183, 175, .ch_320_1 = 159, .ch_320_2 = 191),
125 CHAN(185, 6875, 183, 175, .ch_320_1 = 159, .ch_320_2 = 191),
developer3abe1ad2022-01-24 11:13:32 +0800126 /* UNII-8 */
developer77215642023-05-15 13:52:35 +0800127 CHAN(189, 6895, 183, 175, .ch_320_1 = 159, .ch_320_2 = 191),
128 CHAN(193, 6915, 199, 207, .ch_320_2 = 191),
129 CHAN(197, 6935, 199, 207, .ch_320_2 = 191),
130 CHAN(201, 6955, 199, 207, .ch_320_2 = 191),
131 CHAN(205, 6975, 199, 207, .ch_320_2 = 191),
132 CHAN(209, 6995, 215, 207, .ch_320_2 = 191),
133 CHAN(213, 7015, 215, 207, .ch_320_2 = 191),
134 CHAN(217, 7035, 215, 207, .ch_320_2 = 191),
135 CHAN(221, 7055, 215, 207, .ch_320_2 = 191),
developer3abe1ad2022-01-24 11:13:32 +0800136 CHAN(225, 7075, 0, 0, .ch_40 = 227),
137 CHAN(229, 7095, 0, 0, .ch_40 = 227),
138 CHAN(233, 7115, 0, 0),
139};
140
141static int
142atenl_hqa_adapter(struct atenl *an, struct atenl_data *data)
143{
144 char cmd[64];
145 u8 i;
146
147 for (i = 0; i < MAX_BAND_NUM; i++) {
148 u8 phy = get_band_val(an, i, phy_idx);
149
150 if (!get_band_val(an, i, valid))
151 continue;
152
153 if (data->cmd == HQA_CMD_OPEN_ADAPTER) {
154 sprintf(cmd, "iw phy phy%u interface add mon%u type monitor", phy, phy);
155 system(cmd);
156 sprintf(cmd, "iw dev wlan%u del", phy);
157 system(cmd);
158 sprintf(cmd, "ifconfig mon%u up", phy);
159 system(cmd);
160 /* set a special-defined country */
161 sprintf(cmd, "iw reg set VV");
162 system(cmd);
developer3abe1ad2022-01-24 11:13:32 +0800163 } else {
164 atenl_nl_set_state(an, i, MT76_TM_STATE_OFF);
165 sprintf(cmd, "iw reg set 00");
166 system(cmd);
167 sprintf(cmd, "iw dev mon%u del", phy);
168 system(cmd);
169 sprintf(cmd, "iw phy phy%u interface add wlan%u type managed", phy, phy);
170 system(cmd);
171 }
172 }
173
developer77215642023-05-15 13:52:35 +0800174 for (i = 0; i < MAX_BAND_NUM; i++)
175 atenl_nl_set_state(an, i, MT76_TM_STATE_IDLE);
176
developer3abe1ad2022-01-24 11:13:32 +0800177 return 0;
178}
179
180static int
181atenl_hqa_set_rf_mode(struct atenl *an, struct atenl_data *data)
182{
183 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
184
185 /* The testmode rf mode change applies to all bands */
186 set_band_val(an, 0, rf_mode, ntohl(*(u32 *)hdr->data));
187 set_band_val(an, 1, rf_mode, ntohl(*(u32 *)hdr->data));
188
189 return 0;
190}
191
192static int
193atenl_hqa_get_chip_id(struct atenl *an, struct atenl_data *data)
194{
195 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
196
197 *(u32 *)(hdr->data + 2) = htonl(an->chip_id);
198
199 return 0;
200}
201
202static int
203atenl_hqa_get_sub_chip_id(struct atenl *an, struct atenl_data *data)
204{
205 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
206
developer5698c9c2022-05-30 16:40:23 +0800207 *(u32 *)(hdr->data + 2) = htonl(an->sub_chip_id);
developer3abe1ad2022-01-24 11:13:32 +0800208
209 return 0;
210}
211
212static int
213atenl_hqa_get_rf_cap(struct atenl *an, struct atenl_data *data)
214{
215 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
216 u32 band = ntohl(*(u32 *)hdr->data);
217 struct atenl_band *anb;
218
219 if (band >= MAX_BAND_NUM)
220 return -EINVAL;
221
222 anb = &an->anb[band];
223 /* fill tx and rx ant */
224 *(u32 *)(hdr->data + 2) = htonl(__builtin_popcount(anb->chainmask));
225 *(u32 *)(hdr->data + 2 + 4) = *(u32 *)(hdr->data + 2);
226
227 return 0;
228}
229
230static int
231atenl_hqa_reset_counter(struct atenl *an, struct atenl_data *data)
232{
233 struct atenl_band *anb = &an->anb[an->cur_band];
234
235 anb->reset_tx_cnt = true;
236 anb->reset_rx_cnt = true;
237
238 memset(&anb->rx_stat, 0, sizeof(anb->rx_stat));
239
240 return 0;
241}
242
243static int
244atenl_hqa_mac_bbp_reg(struct atenl *an, struct atenl_data *data)
245{
246 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
247 enum atenl_cmd cmd = data->cmd;
248 u32 *v = (u32 *)hdr->data;
developer5698c9c2022-05-30 16:40:23 +0800249 u32 offset = ntohl(v[0]), res;
developer3abe1ad2022-01-24 11:13:32 +0800250 int ret;
251
252 if (cmd == HQA_CMD_READ_MAC_BBP_REG) {
253 u16 num = ntohs(*(u16 *)(hdr->data + 4));
254 u32 *ptr = (u32 *)(hdr->data + 2);
developer3abe1ad2022-01-24 11:13:32 +0800255 int i;
256
257 if (num > SHRT_MAX) {
258 ret = -EINVAL;
259 goto out;
260 }
261
262 hdr->len = htons(2 + num * 4);
263 for (i = 0; i < num && i < sizeof(hdr->data) / 4; i++) {
264 ret = atenl_reg_read(an, offset + i * 4, &res);
265 if (ret)
266 goto out;
267
268 res = htonl(res);
269 memcpy(ptr + i, &res, 4);
270 }
developer5698c9c2022-05-30 16:40:23 +0800271 } else if (cmd == HQA_CMD_READ_MAC_BBP_REG_QA) {
272 ret = atenl_reg_read(an, offset, &res);
273 if (ret)
274 goto out;
275
276 res = htonl(res);
277 memcpy(hdr->data + 2, &res, 4);
developer3abe1ad2022-01-24 11:13:32 +0800278 } else {
279 u32 val = ntohl(v[1]);
280
281 ret = atenl_reg_write(an, offset, val);
282 if (ret)
283 goto out;
284 }
285
286 ret = 0;
287out:
288 memset(hdr->data, 0, 2);
289
290 return ret;
291}
292
293static int
developer5698c9c2022-05-30 16:40:23 +0800294atenl_hqa_rf_reg(struct atenl *an, struct atenl_data *data)
295{
296 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
297 enum atenl_cmd cmd = data->cmd;
298 u32 *v = (u32 *)hdr->data;
299 u32 wf_sel = ntohl(v[0]);
300 u32 offset = ntohl(v[1]);
301 u32 num = ntohl(v[2]);
302 int ret, i;
303
304 if (cmd == HQA_CMD_READ_RF_REG) {
305 u32 *ptr = (u32 *)(hdr->data + 2);
306 u32 res;
307
308 hdr->len = htons(2 + num * 4);
309 for (i = 0; i < num && i < sizeof(hdr->data) / 4; i++) {
310 ret = atenl_rf_read(an, wf_sel, offset + i * 4, &res);
311 if (ret)
312 goto out;
313
314 res = htonl(res);
315 memcpy(ptr + i, &res, 4);
316 }
317 } else {
318 u32 *ptr = (u32 *)(hdr->data + 12);
319
320 for (i = 0; i < num && i < sizeof(hdr->data) / 4; i++) {
321 u32 val = ntohl(ptr[i]);
322
323 ret = atenl_rf_write(an, wf_sel, offset + i * 4, val);
324 if (ret)
325 goto out;
326 }
327 }
328
329 ret = 0;
330out:
331 memset(hdr->data, 0, 2);
332
333 return ret;
334}
335
336static int
developer3abe1ad2022-01-24 11:13:32 +0800337atenl_hqa_eeprom_bulk(struct atenl *an, struct atenl_data *data)
338{
339 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
340 enum atenl_cmd cmd = data->cmd;
341
342 if (cmd == HQA_CMD_WRITE_BUFFER_DONE) {
343 u32 buf_mode = ntohl(*(u32 *)hdr->data);
344
345 switch (buf_mode) {
346 case E2P_EFUSE_MODE:
developer9b7cdad2022-03-10 14:24:55 +0800347 atenl_nl_write_efuse_all(an);
developer3abe1ad2022-01-24 11:13:32 +0800348 break;
349 default:
350 break;
351 }
352 } else {
353 u16 *v = (u16 *)hdr->data;
354 u16 offset = ntohs(v[0]), len = ntohs(v[1]);
355 u16 val;
356 size_t i;
357
358 if (offset >= an->eeprom_size || (len > sizeof(hdr->data) - 2))
359 return -EINVAL;
360
361 if (cmd == HQA_CMD_READ_EEPROM_BULK) {
362 hdr->len = htons(len + 2);
363 for (i = 0; i < len; i += 2) {
364 if (offset + i >= an->eeprom_size)
365 val = 0;
366 else
367 val = ntohs(*(u16 *)(an->eeprom_data + offset + i));
368 *(u16 *)(hdr->data + 2 + i) = val;
369 }
370 } else { /* write eeprom */
developer3abe1ad2022-01-24 11:13:32 +0800371 for (i = 0; i < DIV_ROUND_UP(len, 2); i++) {
372 val = ntohs(v[i + 2]);
373 memcpy(&an->eeprom_data[offset + i * 2], &val, 2);
374 }
developer3abe1ad2022-01-24 11:13:32 +0800375 }
376 }
377
378 return 0;
379}
380
381static int
382atenl_hqa_get_efuse_free_block(struct atenl *an, struct atenl_data *data)
383{
384 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
385 u32 free_block = htonl(0x14);
386
387 /* TODO */
388 *(u32 *)(hdr->data + 2) = free_block;
389
390 return 0;
391}
392
393static int
394atenl_hqa_get_band(struct atenl *an, struct atenl_data *data)
395{
396 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
397 u32 band = ntohl(*(u32 *)hdr->data);
398
399 if (band >= MAX_BAND_NUM)
400 return -EINVAL;
401
402 *(u32 *)(hdr->data + 2) = htonl(an->anb[band].cap);
403
404 return 0;
405}
406
407static int
408atenl_hqa_get_tx_power(struct atenl *an, struct atenl_data *data)
409{
410 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
411 u32 tx_power = htonl(28);
412
413 memcpy(hdr->data + 6, &tx_power, 4);
414
415 return 0;
416}
417
418static int
419atenl_hqa_get_freq_offset(struct atenl *an, struct atenl_data *data)
420{
421 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
422 u32 freq_offset = htonl(10);
423
424 /* TODO */
425 memcpy(hdr->data + 2, &freq_offset, 4);
426
427 return 0;
428}
429
430static int
431atenl_hqa_get_cfg(struct atenl *an, struct atenl_data *data)
432{
433 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
434 u32 val = htonl(1);
435
436 /* TODO */
437 memcpy(hdr->data + 2, &val, 4);
438
439 return 0;
440}
441
442static int
443atenl_hqa_read_temperature(struct atenl *an, struct atenl_data *data)
444{
445 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
446 char buf[64], *str;
447 int fd, ret;
448 u32 temp;
449 u8 phy_idx = get_band_val(an, an->cur_band, phy_idx);
450
451 ret = snprintf(buf, sizeof(buf),
452 "/sys/class/ieee80211/phy%u/hwmon%u/temp1_input",
453 phy_idx, phy_idx);
454 if (snprintf_error(sizeof(buf), ret))
455 return -1;
456
457 fd = open(buf, O_RDONLY);
458 if (fd < 0)
459 return fd;
460
461 ret = read(fd, buf, sizeof(buf) - 1);
462 if (ret < 0)
463 goto out;
464 buf[ret] = 0;
465
466 str = strchr(buf, ':');
467 str += 2;
468 temp = strtol(str, NULL, 10);
469 /* unit conversion */
470 *(u32 *)(hdr->data + 2) = htonl(temp / 1000);
471
472 ret = 0;
473out:
474 close(fd);
475
476 return ret;
477}
478
479static int
developer3abe1ad2022-01-24 11:13:32 +0800480atenl_hqa_check_efuse_mode(struct atenl *an, struct atenl_data *data)
481{
482 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
483 bool flash_mode = an->mtd_part != NULL;
484 enum atenl_cmd cmd = data->cmd;
485 u32 mode;
486
487 switch (cmd) {
488 case HQA_CMD_CHECK_EFUSE_MODE:
489 mode = flash_mode ? 0 : 1;
490 break;
491 case HQA_CMD_CHECK_EFUSE_MODE_TYPE:
492 mode = flash_mode ? E2P_FLASH_MODE : E2P_BIN_MODE;
493 break;
494 case HQA_CMD_CHECK_EFUSE_MODE_NATIVE:
495 mode = flash_mode ? E2P_FLASH_MODE : E2P_EFUSE_MODE;
496 break;
497 default:
498 mode = E2P_BIN_MODE;
499 break;
500 }
501
502 *(u32 *)(hdr->data + 2) = htonl(mode);
503
504 return 0;
505}
506
507static inline u16
508atenl_get_freq_by_channel(u8 ch_band, u16 ch)
509{
510 u16 base;
511
512 if (ch_band == CH_BAND_6GHZ) {
513 base = 5950;
514 } else if (ch_band == CH_BAND_5GHZ) {
515 if (ch >= 184)
516 return 4920 + (ch - 184) * 5;
517
518 base = 5000;
519 } else {
520 base = 2407;
521 }
522
523 return base + ch * 5;
524}
525
526u16 atenl_get_center_channel(u8 bw, u8 ch_band, u16 ctrl_ch)
527{
528 const struct atenl_channel *chan = NULL;
529 const struct atenl_channel *ch_list;
530 u16 center_ch;
531 u8 ch_num;
532 int i;
533
534 if (ch_band == CH_BAND_2GHZ || bw <= TEST_CBW_40MHZ)
535 return 0;
536
537 if (ch_band == CH_BAND_6GHZ) {
538 ch_list = atenl_channels_6ghz;
539 ch_num = ARRAY_SIZE(atenl_channels_6ghz);
540 } else {
541 ch_list = atenl_channels_5ghz;
542 ch_num = ARRAY_SIZE(atenl_channels_5ghz);
543 }
544
545 for (i = 0; i < ch_num; i++) {
546 if (ctrl_ch == ch_list[i].ch) {
547 chan = &ch_list[i];
548 break;
549 }
550 }
551
552 if (!chan)
553 return 0;
554
555 switch (bw) {
556 case TEST_CBW_160MHZ:
557 center_ch = chan->ch_160;
558 break;
559 case TEST_CBW_80MHZ:
560 center_ch = chan->ch_80;
561 break;
562 default:
563 center_ch = 0;
564 break;
565 }
566
567 return center_ch;
568}
569
570static void atenl_get_bw_string(u8 bw, char *buf)
571{
572 switch (bw) {
developer77215642023-05-15 13:52:35 +0800573 case TEST_CBW_320MHZ:
574 sprintf(buf, "320");
575 break;
developer3abe1ad2022-01-24 11:13:32 +0800576 case TEST_CBW_160MHZ:
577 sprintf(buf, "160");
578 break;
579 case TEST_CBW_80MHZ:
580 sprintf(buf, "80");
581 break;
582 case TEST_CBW_40MHZ:
583 sprintf(buf, "40");
584 break;
585 default:
586 sprintf(buf, "20");
587 break;
588 }
589}
590
591void atenl_set_channel(struct atenl *an, u8 bw, u8 ch_band,
592 u16 ch, u16 center_ch1, u16 center_ch2)
593{
594 char bw_str[8] = {};
595 char cmd[128];
596 u16 freq = atenl_get_freq_by_channel(ch_band, ch);
597 u16 freq_center1 = atenl_get_freq_by_channel(ch_band, center_ch1);
598 int ret;
599
600 if (bw > TEST_CBW_MAX)
601 return;
602
603 atenl_get_bw_string(bw, bw_str);
604
605 if (bw == TEST_CBW_20MHZ)
606 ret = snprintf(cmd, sizeof(cmd), "iw dev mon%d set freq %u %s",
607 get_band_val(an, an->cur_band, phy_idx),
608 freq, bw_str);
609 else
610 ret = snprintf(cmd, sizeof(cmd), "iw dev mon%d set freq %u %s %u",
611 get_band_val(an, an->cur_band, phy_idx),
612 freq, bw_str, freq_center1);
613 if (snprintf_error(sizeof(cmd), ret))
614 return;
615
developer5698c9c2022-05-30 16:40:23 +0800616 atenl_dbg("%s: cmd: %s\n", __func__, cmd);
developer3abe1ad2022-01-24 11:13:32 +0800617
618 system(cmd);
619}
620
621static int
622atenl_hqa_set_channel(struct atenl *an, struct atenl_data *data)
623{
624 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
625 u32 *v = (u32 *)hdr->data;
626 u8 band = ntohl(v[2]);
627 u16 ch1 = ntohl(v[3]); /* center */
628 u16 ch2 = ntohl(v[4]);
629 u8 bw = ntohl(v[5]);
630 u8 pri_sel = ntohl(v[7]);
631 u8 ch_band = ntohl(v[9]);
632 u16 ctrl_ch = 0;
633
634 if (band >= MAX_BAND_NUM)
635 return -EINVAL;
636
developer77215642023-05-15 13:52:35 +0800637 if ((bw == TEST_CBW_320MHZ && pri_sel > 15) ||
638 (bw == TEST_CBW_160MHZ && pri_sel > 7) ||
developer3abe1ad2022-01-24 11:13:32 +0800639 (bw == TEST_CBW_80MHZ && pri_sel > 3) ||
640 (bw == TEST_CBW_40MHZ && pri_sel > 1)) {
641 atenl_err("%s: ctrl channel select error\n", __func__);
642 return -EINVAL;
643 }
644
645 an->cur_band = band;
646
647 if (ch_band == CH_BAND_2GHZ) {
648 ctrl_ch = ch1;
649 switch (bw) {
650 case TEST_CBW_40MHZ:
651 if (pri_sel == 1)
652 ctrl_ch += 2;
653 else
654 ctrl_ch -= 2;
655 break;
656 default:
657 break;
658 }
659
660 atenl_set_channel(an, bw, CH_BAND_2GHZ, ctrl_ch, ch1, 0);
661 } else {
662 const struct atenl_channel *chan = NULL;
663 const struct atenl_channel *ch_list;
664 u8 ch_num;
665 int i;
666
667 if (ch_band == CH_BAND_6GHZ) {
668 ch_list = atenl_channels_6ghz;
669 ch_num = ARRAY_SIZE(atenl_channels_6ghz);
670 } else {
671 ch_list = atenl_channels_5ghz;
672 ch_num = ARRAY_SIZE(atenl_channels_5ghz);
673 }
674
developer77215642023-05-15 13:52:35 +0800675 if (bw == TEST_CBW_320MHZ) {
676 for (i = 0; i < ch_num; i++) {
677 if (ch1 == ch_list[i].ch_320_1) {
678 chan = &ch_list[i];
679 break;
680 } else if (ch1 == ch_list[i].ch_320_2) {
681 chan = &ch_list[i];
682 break;
683 }
684 }
685 } else if (bw == TEST_CBW_160MHZ) {
developer3abe1ad2022-01-24 11:13:32 +0800686 for (i = 0; i < ch_num; i++) {
687 if (ch1 == ch_list[i].ch_160) {
688 chan = &ch_list[i];
689 break;
690 } else if (ch1 < ch_list[i].ch_160) {
691 chan = &ch_list[i - 1];
692 break;
693 }
694 }
695 } else if (bw == TEST_CBW_80MHZ) {
696 for (i = 0; i < ch_num; i++) {
697 if (ch1 == ch_list[i].ch_80) {
698 chan = &ch_list[i];
699 break;
700 } else if (ch1 < ch_list[i].ch_80) {
701 chan = &ch_list[i - 1];
702 break;
703 }
704 }
705 } else {
706 for (i = 0; i < ch_num; i++) {
707 if (ch1 <= ch_list[i].ch) {
708 if (ch1 == ch_list[i].ch)
709 chan = &ch_list[i];
710 else
711 chan = &ch_list[i - 1];
712 break;
713 }
714 }
715 }
716
717 if (!chan)
718 return -EINVAL;
719
720 if (bw != TEST_CBW_20MHZ) {
721 chan += pri_sel;
722 if (chan > &ch_list[ch_num - 1])
723 return -EINVAL;
724 }
725 ctrl_ch = chan->ch;
726
727 atenl_set_channel(an, bw, ch_band, ctrl_ch, ch1, ch2);
728 }
729
730 *(u32 *)(hdr->data + 2) = data->ext_id;
731
developer5698c9c2022-05-30 16:40:23 +0800732 atenl_nl_set_aid(an, band, 0);
733
developer3abe1ad2022-01-24 11:13:32 +0800734 return 0;
735}
736
737static int
738atenl_hqa_tx_time_option(struct atenl *an, struct atenl_data *data)
739{
740 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
741 u32 *v = (u32 *)hdr->data;
742 u8 band = ntohl(v[1]);
743 u32 option = ntohl(v[2]);
744
745 if (band >= MAX_BAND_NUM)
746 return -EINVAL;
747
748 set_band_val(an, band, use_tx_time, !!option);
749 *(u32 *)(hdr->data + 2) = data->ext_id;
750
751 return 0;
752}
753
developer5698c9c2022-05-30 16:40:23 +0800754/* should be placed in order for binary search */
755static const struct atenl_ops hqa_ops[] = {
756 {
757 .cmd = HQA_CMD_OPEN_ADAPTER,
758 .cmd_id = 0x1000,
759 .resp_len = 2,
760 .ops = atenl_hqa_adapter,
761 },
762 {
763 .cmd = HQA_CMD_CLOSE_ADAPTER,
764 .cmd_id = 0x1001,
765 .resp_len = 2,
766 .ops = atenl_hqa_adapter,
767 },
768 {
769 .cmd = HQA_CMD_SET_TX_PATH,
770 .cmd_id = 0x100b,
771 .resp_len = 2,
772 .ops = atenl_nl_process,
773 },
774 {
775 .cmd = HQA_CMD_SET_RX_PATH,
776 .cmd_id = 0x100c,
777 .resp_len = 2,
778 .ops = atenl_nl_process,
779 },
780 {
781 .cmd = HQA_CMD_LEGACY,
782 .cmd_id = 0x100d,
783 .resp_len = 2,
784 .flags = ATENL_OPS_FLAG_SKIP,
785 },
786 {
787 .cmd = HQA_CMD_SET_TX_POWER,
788 .cmd_id = 0x1011,
789 .resp_len = 2,
790 .ops = atenl_nl_process,
791 },
792 {
793 .cmd = HQA_CMD_SET_TX_POWER_MANUAL,
794 .cmd_id = 0x1018,
795 .resp_len = 2,
796 .flags = ATENL_OPS_FLAG_SKIP,
797 },
798 {
799 .cmd = HQA_CMD_LEGACY,
800 .cmd_id = 0x1101,
801 .resp_len = 2,
802 .flags = ATENL_OPS_FLAG_SKIP,
803 },
804 {
805 .cmd = HQA_CMD_LEGACY,
806 .cmd_id = 0x1102,
807 .resp_len = 2,
808 .flags = ATENL_OPS_FLAG_SKIP,
809 },
810 {
811 .cmd = HQA_CMD_SET_TX_BW,
812 .cmd_id = 0x1104,
813 .resp_len = 2,
814 .flags = ATENL_OPS_FLAG_SKIP,
815 },
816 {
817 .cmd = HQA_CMD_SET_TX_PKT_BW,
818 .cmd_id = 0x1105,
819 .resp_len = 2,
820 .flags = ATENL_OPS_FLAG_SKIP,
821 },
822 {
823 .cmd = HQA_CMD_SET_TX_PRI_BW,
824 .cmd_id = 0x1106,
825 .resp_len = 2,
826 .flags = ATENL_OPS_FLAG_SKIP,
827 },
828 {
829 .cmd = HQA_CMD_SET_FREQ_OFFSET,
830 .cmd_id = 0x1107,
831 .resp_len = 2,
832 .ops = atenl_nl_process,
833 },
834 {
835 .cmd = HQA_CMD_SET_TSSI,
836 .cmd_id = 0x1109,
837 .resp_len = 2,
838 .ops = atenl_nl_process,
839 },
840 {
841 .cmd = HQA_CMD_SET_EEPROM_TO_FW,
842 .cmd_id = 0x110c,
843 .resp_len = 2,
844 .flags = ATENL_OPS_FLAG_SKIP,
845 },
846 {
847 .cmd = HQA_CMD_ANT_SWAP_CAP,
848 .cmd_id = 0x110d,
849 .resp_len = 6,
850 .flags = ATENL_OPS_FLAG_SKIP,
851 },
852 {
853 .cmd = HQA_CMD_RESET_TX_RX_COUNTER,
854 .cmd_id = 0x1200,
855 .resp_len = 2,
856 .ops = atenl_hqa_reset_counter,
857 },
858 {
859 .cmd = HQA_CMD_READ_MAC_BBP_REG_QA,
860 .cmd_id = 0x1300,
861 .resp_len = 6,
862 .ops = atenl_hqa_mac_bbp_reg,
863 },
864 {
865 .cmd = HQA_CMD_WRITE_MAC_BBP_REG,
866 .cmd_id = 0x1301,
867 .resp_len = 2,
868 .ops = atenl_hqa_mac_bbp_reg,
869 },
870 {
871 .cmd = HQA_CMD_READ_MAC_BBP_REG,
872 .cmd_id = 0x1302,
873 .ops = atenl_hqa_mac_bbp_reg,
874 },
875 {
876 .cmd = HQA_CMD_READ_RF_REG,
877 .cmd_id = 0x1303,
878 .ops = atenl_hqa_rf_reg,
879 },
880 {
881 .cmd = HQA_CMD_WRITE_RF_REG,
882 .cmd_id = 0x1304,
883 .resp_len = 2,
884 .ops = atenl_hqa_rf_reg,
885 },
886 {
887 .cmd = HQA_CMD_WRITE_EEPROM_BULK,
888 .cmd_id = 0x1306,
889 .resp_len = 2,
890 .ops = atenl_hqa_eeprom_bulk,
891 },
892 {
893 .cmd = HQA_CMD_READ_EEPROM_BULK,
894 .cmd_id = 0x1307,
895 .ops = atenl_hqa_eeprom_bulk,
896 },
897 {
898 .cmd = HQA_CMD_WRITE_EEPROM_BULK,
899 .cmd_id = 0x1308,
900 .resp_len = 2,
901 .ops = atenl_hqa_eeprom_bulk,
902 },
903 {
904 .cmd = HQA_CMD_CHECK_EFUSE_MODE,
905 .cmd_id = 0x1309,
906 .resp_len = 6,
907 .ops = atenl_hqa_check_efuse_mode,
908 },
909 {
910 .cmd = HQA_CMD_GET_EFUSE_FREE_BLOCK,
911 .cmd_id = 0x130a,
912 .resp_len = 6,
913 .ops = atenl_hqa_get_efuse_free_block,
914 },
915 {
916 .cmd = HQA_CMD_GET_TX_POWER,
917 .cmd_id = 0x130d,
918 .resp_len = 10,
919 .ops = atenl_hqa_get_tx_power,
920 },
921 {
922 .cmd = HQA_CMD_SET_CFG,
923 .cmd_id = 0x130e,
924 .resp_len = 2,
925 .ops = atenl_nl_process,
926 },
927 {
928 .cmd = HQA_CMD_GET_FREQ_OFFSET,
929 .cmd_id = 0x130f,
930 .resp_len = 6,
931 .ops = atenl_hqa_get_freq_offset,
932 },
933 {
934 .cmd = HQA_CMD_CONTINUOUS_TX,
935 .cmd_id = 0x1311,
936 .resp_len = 6,
937 .ops = atenl_nl_process,
938 },
939 {
940 .cmd = HQA_CMD_SET_RX_PKT_LEN,
941 .cmd_id = 0x1312,
942 .resp_len = 2,
943 .flags = ATENL_OPS_FLAG_SKIP,
944 },
945 {
946 .cmd = HQA_CMD_GET_TX_INFO,
947 .cmd_id = 0x1313,
948 .resp_len = 10,
949 .ops = atenl_nl_process,
950 },
951 {
952 .cmd = HQA_CMD_GET_CFG,
953 .cmd_id = 0x1314,
954 .resp_len = 6,
955 .ops = atenl_hqa_get_cfg,
956 },
957 {
958 .cmd = HQA_CMD_GET_TX_TONE_POWER,
959 .cmd_id = 0x131a,
960 .resp_len = 6,
961 .flags = ATENL_OPS_FLAG_SKIP,
962 },
963 {
964 .cmd = HQA_CMD_UNKNOWN,
965 .cmd_id = 0x131f,
966 .resp_len = 1024,
967 .flags = ATENL_OPS_FLAG_SKIP,
968 },
969 {
970 .cmd = HQA_CMD_READ_TEMPERATURE,
971 .cmd_id = 0x1401,
972 .resp_len = 6,
973 .ops = atenl_hqa_read_temperature,
974 },
975 {
976 .cmd = HQA_CMD_GET_FW_INFO,
977 .cmd_id = 0x1500,
978 .resp_len = 32,
979 .flags = ATENL_OPS_FLAG_SKIP,
980 },
981 {
982 .cmd_id = 0x1502,
983 .flags = ATENL_OPS_FLAG_LEGACY,
984 },
985 {
986 .cmd = HQA_CMD_SET_TSSI,
987 .cmd_id = 0x1505,
988 .resp_len = 2,
989 .ops = atenl_nl_process,
990 },
991 {
992 .cmd = HQA_CMD_SET_RF_MODE,
993 .cmd_id = 0x1509,
994 .resp_len = 2,
995 .ops = atenl_hqa_set_rf_mode,
996 },
997 {
998 .cmd_id = 0x150b,
999 .flags = ATENL_OPS_FLAG_LEGACY,
1000 },
1001 {
1002 .cmd = HQA_CMD_WRITE_BUFFER_DONE,
1003 .cmd_id = 0x1511,
1004 .resp_len = 2,
1005 .ops = atenl_hqa_eeprom_bulk,
1006 },
1007 {
1008 .cmd = HQA_CMD_GET_CHIP_ID,
1009 .cmd_id = 0x1514,
1010 .resp_len = 6,
1011 .ops = atenl_hqa_get_chip_id,
1012 },
1013 {
1014 .cmd = HQA_CMD_GET_SUB_CHIP_ID,
1015 .cmd_id = 0x151b,
1016 .resp_len = 6,
1017 .ops = atenl_hqa_get_sub_chip_id,
1018 },
1019 {
1020 .cmd = HQA_CMD_GET_RX_INFO,
1021 .cmd_id = 0x151c,
1022 .ops = atenl_nl_process,
1023 },
1024 {
1025 .cmd = HQA_CMD_GET_RF_CAP,
1026 .cmd_id = 0x151e,
1027 .resp_len = 10,
1028 .ops = atenl_hqa_get_rf_cap,
1029 },
1030 {
1031 .cmd = HQA_CMD_CHECK_EFUSE_MODE_TYPE,
1032 .cmd_id = 0x1522,
1033 .resp_len = 6,
1034 .ops = atenl_hqa_check_efuse_mode,
1035 },
1036 {
1037 .cmd = HQA_CMD_CHECK_EFUSE_MODE_NATIVE,
1038 .cmd_id = 0x1523,
1039 .resp_len = 6,
1040 .ops = atenl_hqa_check_efuse_mode,
1041 },
1042 {
1043 .cmd = HQA_CMD_GET_BAND,
1044 .cmd_id = 0x152d,
1045 .resp_len = 6,
1046 .ops = atenl_hqa_get_band,
1047 },
1048 {
1049 .cmd = HQA_CMD_SET_RU,
1050 .cmd_id = 0x1594,
1051 .resp_len = 2,
1052 .ops = atenl_nl_process_many,
1053 },
developer3abe1ad2022-01-24 11:13:32 +08001054};
developer3abe1ad2022-01-24 11:13:32 +08001055
developer5698c9c2022-05-30 16:40:23 +08001056static const struct atenl_ops hqa_ops_ext[] = {
1057 {
1058 .cmd = HQA_EXT_CMD_SET_CHANNEL,
1059 .cmd_id = 0x01,
1060 .resp_len = 6,
1061 .ops = atenl_hqa_set_channel,
1062 .flags = ATENL_OPS_FLAG_EXT_CMD,
1063 },
1064 {
1065 .cmd = HQA_EXT_CMD_SET_TX,
1066 .cmd_id = 0x02,
1067 .resp_len = 6,
1068 .ops = atenl_nl_process,
1069 .flags = ATENL_OPS_FLAG_EXT_CMD,
1070 },
1071 {
1072 .cmd = HQA_EXT_CMD_START_TX,
1073 .cmd_id = 0x03,
1074 .resp_len = 6,
1075 .ops = atenl_nl_process,
1076 .flags = ATENL_OPS_FLAG_EXT_CMD,
1077 },
1078 {
1079 .cmd = HQA_EXT_CMD_START_RX,
1080 .cmd_id = 0x04,
1081 .resp_len = 6,
1082 .ops = atenl_nl_process,
1083 .flags = ATENL_OPS_FLAG_EXT_CMD,
1084 },
1085 {
1086 .cmd = HQA_EXT_CMD_STOP_TX,
1087 .cmd_id = 0x05,
1088 .resp_len = 6,
1089 .ops = atenl_nl_process,
1090 .flags = ATENL_OPS_FLAG_EXT_CMD,
1091 },
1092 {
1093 .cmd = HQA_EXT_CMD_STOP_RX,
1094 .cmd_id = 0x06,
1095 .resp_len = 6,
1096 .ops = atenl_nl_process,
1097 .flags = ATENL_OPS_FLAG_EXT_CMD,
1098 },
1099 {
1100 .cmd = HQA_EXT_CMD_IBF_SET_VAL,
1101 .cmd_id = 0x08,
1102 .resp_len = 6,
1103 .ops = atenl_nl_process,
1104 .flags = ATENL_OPS_FLAG_EXT_CMD,
1105 },
1106 {
1107 .cmd = HQA_EXT_CMD_IBF_GET_STATUS,
1108 .cmd_id = 0x09,
1109 .resp_len = 10,
1110 .ops = atenl_nl_process,
1111 .flags = ATENL_OPS_FLAG_EXT_CMD,
1112 },
1113 {
1114 .cmd = HQA_EXT_CMD_IBF_PROF_UPDATE_ALL,
1115 .cmd_id = 0x0c,
1116 .resp_len = 6,
1117 .ops = atenl_nl_process,
1118 .flags = ATENL_OPS_FLAG_EXT_CMD,
1119 },
1120 {
1121 .cmd = HQA_EXT_CMD_SET_TX_TIME_OPT,
1122 .cmd_id = 0x26,
1123 .resp_len = 6,
1124 .ops = atenl_hqa_tx_time_option,
1125 .flags = ATENL_OPS_FLAG_EXT_CMD,
1126 },
1127 {
1128 .cmd = HQA_EXT_CMD_OFF_CH_SCAN,
1129 .cmd_id = 0x27,
1130 .resp_len = 6,
1131 .ops = atenl_nl_process,
1132 .flags = ATENL_OPS_FLAG_EXT_CMD,
1133 },
developer3abe1ad2022-01-24 11:13:32 +08001134};
developer3abe1ad2022-01-24 11:13:32 +08001135
developer5698c9c2022-05-30 16:40:23 +08001136static const struct atenl_ops *
1137atenl_get_ops(struct atenl_data *data)
developer3abe1ad2022-01-24 11:13:32 +08001138{
developer5698c9c2022-05-30 16:40:23 +08001139 const struct atenl_ops *group;
developer3abe1ad2022-01-24 11:13:32 +08001140 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
developer5698c9c2022-05-30 16:40:23 +08001141 u16 cmd_id = ntohs(hdr->cmd_id), id = cmd_id;
1142 int size, low = 0, high;
developer3abe1ad2022-01-24 11:13:32 +08001143
developer5698c9c2022-05-30 16:40:23 +08001144 switch (cmd_id) {
1145 case 0x1600:
1146 group = hqa_ops_ext;
1147 size = ARRAY_SIZE(hqa_ops_ext);
1148 break;
1149 default:
1150 group = hqa_ops;
1151 size = ARRAY_SIZE(hqa_ops);
1152 break;
developer3abe1ad2022-01-24 11:13:32 +08001153 }
1154
developer5698c9c2022-05-30 16:40:23 +08001155 if (group[0].flags & ATENL_OPS_FLAG_EXT_CMD)
1156 id = ntohl(*(u32 *)hdr->data);
1157
1158 /* binary search */
1159 high = size - 1;
1160 while (low <= high) {
1161 int mid = low + (high - low) / 2;
developer3abe1ad2022-01-24 11:13:32 +08001162
developer5698c9c2022-05-30 16:40:23 +08001163 if (group[mid].cmd_id == id)
1164 return &group[mid];
1165 else if (group[mid].cmd_id > id)
1166 high = mid - 1;
1167 else
1168 low = mid + 1;
developer3abe1ad2022-01-24 11:13:32 +08001169 }
1170
developer5698c9c2022-05-30 16:40:23 +08001171 return NULL;
developer3abe1ad2022-01-24 11:13:32 +08001172}
1173
developer5698c9c2022-05-30 16:40:23 +08001174static int
1175atenl_hqa_handler(struct atenl *an, struct atenl_data *data)
developer3abe1ad2022-01-24 11:13:32 +08001176{
1177 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
developer5698c9c2022-05-30 16:40:23 +08001178 const struct atenl_ops *ops = NULL;
developer3abe1ad2022-01-24 11:13:32 +08001179 u16 cmd_id = ntohs(hdr->cmd_id);
1180 u16 status = 0;
1181
developer5698c9c2022-05-30 16:40:23 +08001182 atenl_dbg("handle command: 0x%x\n", cmd_id);
1183
1184 ops = atenl_get_ops(data);
1185 if (!ops || (!ops->ops && !ops->flags)) {
1186 atenl_err("Unknown command id: 0x%x\n", cmd_id);
developer3abe1ad2022-01-24 11:13:32 +08001187 goto done;
1188 }
1189
developer5698c9c2022-05-30 16:40:23 +08001190 data->cmd = ops->cmd;
1191 data->cmd_id = ops->cmd_id;
1192 if (ops->flags & ATENL_OPS_FLAG_EXT_CMD) {
1193 data->ext_cmd = ops->cmd;
1194 data->ext_id = ops->cmd_id;
developer3abe1ad2022-01-24 11:13:32 +08001195 }
1196
developer5698c9c2022-05-30 16:40:23 +08001197 if (ops->flags & ATENL_OPS_FLAG_SKIP)
1198 goto done;
1199
1200 atenl_dbg_print_data(data->buf, __func__,
developer3abe1ad2022-01-24 11:13:32 +08001201 ntohs(hdr->len) + ETH_HLEN + RACFG_HLEN);
1202 if (ops->ops)
1203 status = htons(ops->ops(an, data));
1204 if (ops->resp_len)
1205 hdr->len = htons(ops->resp_len);
1206
developer3abe1ad2022-01-24 11:13:32 +08001207done:
developer5698c9c2022-05-30 16:40:23 +08001208 *(u16 *)hdr->data = status;
developer3abe1ad2022-01-24 11:13:32 +08001209 data->len = ntohs(hdr->len) + ETH_HLEN + RACFG_HLEN;
1210 hdr->cmd_type |= ~htons(RACFG_CMD_TYPE_MASK);
1211
1212 return 0;
1213}
developer5698c9c2022-05-30 16:40:23 +08001214
1215int atenl_hqa_proc_cmd(struct atenl *an)
1216{
1217 struct atenl_data *data;
1218 struct atenl_cmd_hdr *hdr;
1219 u16 cmd_type;
1220 int ret = -EINVAL;
1221
1222 data = calloc(1, sizeof(struct atenl_data));
1223 if (!data)
1224 return -ENOMEM;
1225
1226 ret = atenl_eth_recv(an, data);
1227 if (ret)
1228 goto out;
1229
1230 hdr = atenl_hdr(data);
1231 if (ntohl(hdr->magic_no) != RACFG_MAGIC_NO)
1232 goto out;
1233
1234 cmd_type = ntohs(hdr->cmd_type);
1235 if (FIELD_GET(RACFG_CMD_TYPE_MASK, cmd_type) != RACFG_CMD_TYPE_ETHREQ &&
1236 FIELD_GET(RACFG_CMD_TYPE_MASK, cmd_type) != RACFG_CMD_TYPE_PLATFORM_MODULE) {
1237 atenl_err("cmd type error = 0x%x\n", cmd_type);
1238 goto out;
1239 }
1240
1241 ret = atenl_hqa_handler(an, data);
1242 if (ret)
1243 goto out;
1244
1245 ret = atenl_eth_send(an, data);
1246 if (ret)
1247 goto out;
1248
1249 ret = 0;
1250out:
1251 free(data);
1252
1253 return ret;
1254}