[][MAC80211][app][atenl: support mt7986]
[Description]
Add support for mt7986 and rework commands.
[Release-log]
N/A
Change-Id: Ibeb9a0bf260dca17dfae249929af0eac2a6b51f4
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6050196
diff --git a/feed/atenl/files/ated.sh b/feed/atenl/files/ated.sh
index 71d139f..0fa8950 100755
--- a/feed/atenl/files/ated.sh
+++ b/feed/atenl/files/ated.sh
@@ -32,7 +32,7 @@
killall atenl > /dev/null 2>&1
fi
-eval "${cmd}" > /dev/null 2>&1 &
+eval "${cmd}"
if [[ ! -z "${ori_inf}" ]]; then
echo "if_name: ${ori_inf}"
fi
diff --git a/feed/atenl/src/atenl.h b/feed/atenl/src/atenl.h
index a3ce244..4078825 100644
--- a/feed/atenl/src/atenl.h
+++ b/feed/atenl/src/atenl.h
@@ -15,9 +15,8 @@
#include "nl.h"
#include "util.h"
+#include "debug.h"
-/* #define CONFIG_ATENL_DEBUG 1 */
-/* #define CONFIG_ATENL_DEBUG_VERBOSE 1 */
#define BRIDGE_NAME "br-lan"
#define ETH_P_RACFG 0x2880
#define RACFG_PKT_MAX_SIZE 1600
@@ -28,14 +27,6 @@
#define RACFG_CMD_TYPE_ETHREQ BIT(3)
#define RACFG_CMD_TYPE_PLATFORM_MODULE GENMASK(4, 3)
-#define atenl_info(fmt, ...) printf(fmt, __VA_ARGS__)
-#define atenl_err(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
-#ifdef CONFIG_ATENL_DEBUG
-#define atenl_dbg(fmt, ...) atenl_info(fmt, __VA_ARGS__)
-#else
-#define atenl_dbg(fmt, ...)
-#endif
-
#define set_band_val(_an, _band, _field, _val) \
_an->anb[_band]._field = (_val)
#define get_band_val(_an, _band, _field) \
@@ -68,6 +59,8 @@
enum atenl_rf_mode rf_mode;
bool use_tx_time;
+ u32 tx_time;
+ u32 tx_mpdu_len;
bool reset_tx_cnt;
bool reset_rx_cnt;
@@ -76,19 +69,18 @@
struct atenl_rx_stat rx_stat;
};
-#define MAX_BAND_NUM 4
+#define MAX_BAND_NUM 3
struct atenl {
struct atenl_band anb[MAX_BAND_NUM];
u16 chip_id;
-
+ u16 adie_id;
+ u8 sub_chip_id;
u8 cur_band;
u8 mac_addr[ETH_ALEN];
bool unicast;
int sock_eth;
- int pipefd[2];
- int child_pid;
const char *mtd_part;
u32 mtd_offset;
@@ -97,6 +89,10 @@
u16 eeprom_size;
bool cmd_mode;
+
+ /* intermediate data */
+ u8 ibf_mcs;
+ u8 ibf_ant;
};
struct atenl_cmd_hdr {
@@ -131,7 +127,9 @@
HQA_CMD_SET_CFG,
HQA_CMD_SET_RU,
HQA_CMD_SET_BAND,
+ HQA_CMD_SET_EEPROM_TO_FW,
HQA_CMD_READ_MAC_BBP_REG,
+ HQA_CMD_READ_MAC_BBP_REG_QA,
HQA_CMD_READ_RF_REG,
HQA_CMD_READ_EEPROM_BULK,
HQA_CMD_READ_TEMPERATURE,
@@ -186,16 +184,24 @@
struct atenl_data {
u8 buf[RACFG_PKT_MAX_SIZE];
int len;
+ u16 cmd_id;
+ u8 ext_id;
enum atenl_cmd cmd;
- u32 ext_id;
enum atenl_ext_cmd ext_cmd;
};
-struct atenl_cmd_ops {
- u16 resp_len;
+struct atenl_ops {
int (*ops)(struct atenl *an, struct atenl_data *data);
+ u8 cmd;
+ u8 flags;
+ u16 cmd_id;
+ u16 resp_len;
};
+#define ATENL_OPS_FLAG_EXT_CMD BIT(0)
+#define ATENL_OPS_FLAG_LEGACY BIT(1)
+#define ATENL_OPS_FLAG_SKIP BIT(2)
+
static inline struct atenl_cmd_hdr * atenl_hdr(struct atenl_data *data)
{
u8 *hqa_data = (u8 *)data->buf + ETH_HLEN;
@@ -203,18 +209,6 @@
return (struct atenl_cmd_hdr *)hqa_data;
}
-static inline void
-atenl_dbg_print_data(struct atenl_data *data, const char *func_name, u32 len)
-{
-#ifdef CONFIG_ATENL_DEBUG_VERBOSE
- u32 *tmp = (u32 *)data->buf;
- int i;
-
- for (i = 0; i < DIV_ROUND_UP(len, 4); i++)
- atenl_dbg("%s: [%d] = 0x%08x\n", func_name, i, tmp[i]);
-#endif
-}
-
enum atenl_phy_type {
ATENL_PHY_TYPE_CCK,
ATENL_PHY_TYPE_OFDM,
@@ -374,8 +368,7 @@
int atenl_eth_init(struct atenl *an);
int atenl_eth_recv(struct atenl *an, struct atenl_data *data);
int atenl_eth_send(struct atenl *an, struct atenl_data *data);
-int atenl_hqa_recv(struct atenl *an, struct atenl_data *data);
-int atenl_hqa_proc_cmd(struct atenl *an, struct atenl_data *data);
+int atenl_hqa_proc_cmd(struct atenl *an);
int atenl_nl_process(struct atenl *an, struct atenl_data *data);
int atenl_nl_process_many(struct atenl *an, struct atenl_data *data);
int atenl_nl_check_mtd(struct atenl *an);
@@ -384,6 +377,7 @@
int atenl_nl_update_buffer_mode(struct atenl *an);
int atenl_nl_set_state(struct atenl *an, u8 band,
enum mt76_testmode_state state);
+int atenl_nl_set_aid(struct atenl *an, u8 band, u8 aid);
int atenl_eeprom_init(struct atenl *an, u8 phy_idx);
void atenl_eeprom_close(struct atenl *an);
int atenl_eeprom_write_mtd(struct atenl *an);
@@ -392,5 +386,7 @@
u16 atenl_get_center_channel(u8 bw, u8 ch_band, u16 ctrl_ch);
int atenl_reg_read(struct atenl *an, u32 offset, u32 *res);
int atenl_reg_write(struct atenl *an, u32 offset, u32 val);
+int atenl_rf_read(struct atenl *an, u32 wf_sel, u32 offset, u32 *res);
+int atenl_rf_write(struct atenl *an, u32 wf_sel, u32 offset, u32 val);
#endif
diff --git a/feed/atenl/src/debug.h b/feed/atenl/src/debug.h
new file mode 100644
index 0000000..7621887
--- /dev/null
+++ b/feed/atenl/src/debug.h
@@ -0,0 +1,31 @@
+/* Copyright (C) 2021-2022 Mediatek Inc. */
+#ifndef __ATENL_DEBUG_H
+#define __ATENL_DEBUG_H
+
+/* #define CONFIG_ATENL_DEBUG 1 */
+/* #define CONFIG_ATENL_DEBUG_VERBOSE 1 */
+
+#define atenl_info(fmt, ...) (void)fprintf(stdout, fmt, ##__VA_ARGS__)
+#define atenl_err(fmt, ...) (void)fprintf(stderr, fmt, ##__VA_ARGS__)
+#ifdef CONFIG_ATENL_DEBUG
+#define atenl_dbg(fmt, ...) atenl_info(fmt, ##__VA_ARGS__)
+#else
+#define atenl_dbg(fmt, ...)
+#endif
+
+static inline void
+atenl_dbg_print_data(const void *data, const char *func_name, u32 len)
+{
+#ifdef CONFIG_ATENL_DEBUG_VERBOSE
+ u32 *tmp = (u32 *)data;
+ int i;
+
+ for (i = 0; i < DIV_ROUND_UP(len, 4); i++)
+ atenl_dbg("%s: [%d] = 0x%08x\n", func_name, i, tmp[i]);
+#endif
+}
+
+/* #define debug_print(fmt, ...) \ */
+/* do { if (DEBUG) fprintf(stderr, fmt, __VA_ARGS__); } while (0) */
+
+#endif
diff --git a/feed/atenl/src/eeprom.c b/feed/atenl/src/eeprom.c
index feec9ea..ee77ed7 100644
--- a/feed/atenl/src/eeprom.c
+++ b/feed/atenl/src/eeprom.c
@@ -36,14 +36,15 @@
static int
atenl_flash_create_file(struct atenl *an)
{
+#define READ_LEN_LIMIT 20000
char buf[1024];
- ssize_t len;
+ ssize_t len, limit = 0;
FILE *f;
int fd, ret;
f = mtd_open(an->mtd_part);
if (!f) {
- fprintf(stderr, "Failed to open MTD device\n");
+ atenl_err("Failed to open MTD device\n");
return -1;
}
@@ -56,8 +57,13 @@
retry:
w = write(fd, buf, len);
- if (w > 0)
+ if (w > 0) {
+ limit += len;
+
+ if (limit >= READ_LEN_LIMIT)
+ break;
continue;
+ }
if (errno == EINTR)
goto retry;
@@ -143,9 +149,9 @@
if (!atenl_eeprom_file_exists()) {
if (flash_mode)
- atenl_dbg("[%d]%s: init eeprom with flash mode\n", getpid(), __func__);
+ atenl_dbg("%s: init eeprom with flash mode\n", __func__);
else
- atenl_dbg("[%d]%s: init eeprom with efuse mode\n", getpid(), __func__);
+ atenl_dbg("%s: init eeprom with efuse mode\n", __func__);
if (flash_mode)
return atenl_flash_create_file(an);
@@ -161,6 +167,46 @@
}
static void
+atenl_eeprom_init_chip_id(struct atenl *an)
+{
+ an->chip_id = *(u16 *)an->eeprom_data;
+
+ if (is_mt7915(an)) {
+ an->adie_id = 0x7975;
+ } else if (is_mt7916(an)) {
+ an->adie_id = 0x7976;
+ } else if (is_mt7986(an)) {
+ bool is_7975 = false;
+ u32 val;
+ u8 sub_id;
+
+ atenl_reg_read(an, 0x18050000, &val);
+
+ switch (val & 0xf) {
+ case MT7975_ONE_ADIE_SINGLE_BAND:
+ is_7975 = true;
+ /* fallthrough */
+ case MT7976_ONE_ADIE_SINGLE_BAND:
+ sub_id = 0xa;
+ break;
+ case MT7976_ONE_ADIE_DBDC:
+ sub_id = 0x7;
+ break;
+ case MT7975_DUAL_ADIE_DBDC:
+ is_7975 = true;
+ /* fallthrough */
+ case MT7976_DUAL_ADIE_DBDC:
+ default:
+ sub_id = 0xf;
+ break;
+ }
+
+ an->sub_chip_id = sub_id;
+ an->adie_id = is_7975 ? 0x7975 : 0x7976;
+ }
+}
+
+static void
atenl_eeprom_init_max_size(struct atenl *an)
{
switch (an->chip_id) {
@@ -284,7 +330,7 @@
}
an->eeprom_fd = eeprom_fd;
- an->chip_id = *(u16 *)an->eeprom_data;
+ atenl_eeprom_init_chip_id(an);
atenl_eeprom_init_max_size(an);
atenl_eeprom_init_band_cap(an);
atenl_eeprom_init_antenna_cap(an);
@@ -301,7 +347,7 @@
munmap(an->eeprom_data, EEPROM_PART_SIZE);
close(an->eeprom_fd);
- if (!an->cmd_mode && an->child_pid) {
+ if (!an->cmd_mode) {
if (remove(eeprom_file))
perror("remove");
}
@@ -328,7 +374,7 @@
ret = execvp("mtd", cmd);
if (ret < 0) {
- fprintf(stderr, "%s: execl error\n", __func__);
+ atenl_err("%s: exec error\n", __func__);
exit(0);
}
} else {
@@ -338,7 +384,7 @@
return 0;
}
-/* Directly read some value from driver's eeprom.
+/* Directly read values from driver's eeprom.
* It's usally used to get calibrated data from driver.
*/
int atenl_eeprom_read_from_driver(struct atenl *an, u32 offset, int len)
@@ -401,7 +447,7 @@
char *s = strchr(cmd, ' ');
if (!s) {
- fprintf(stderr, "eeprom: please type a correct command\n");
+ atenl_err("eeprom: please type a correct command\n");
return;
}
diff --git a/feed/atenl/src/eth.c b/feed/atenl/src/eth.c
index a58add3..54a8d2c 100644
--- a/feed/atenl/src/eth.c
+++ b/feed/atenl/src/eth.c
@@ -43,25 +43,31 @@
int atenl_eth_recv(struct atenl *an, struct atenl_data *data)
{
- char buf[RACFG_PKT_MAX_SIZE];
- int len = recvfrom(an->sock_eth, buf, sizeof(buf), 0, NULL, NULL);
- struct ethhdr *hdr = (struct ethhdr *)buf;
+ struct ethhdr *hdr;
+ int len;
- atenl_dbg("[%d]%s: recv len = %d\n", getpid(), __func__, len);
+ len = recvfrom(an->sock_eth, data->buf, sizeof(data->buf), 0, NULL, NULL);
- if (len >= ETH_HLEN + RACFG_HLEN) {
- if (hdr->h_proto == htons(ETH_P_RACFG) &&
- (ether_addr_equal(an->mac_addr, hdr->h_dest) ||
- is_broadcast_ether_addr(hdr->h_dest))) {
- data->len = len;
- memcpy(data->buf, buf, len);
+ if (len < ETH_HLEN + RACFG_HLEN) {
+ atenl_err("packet len is too short: %d\n", len);
+ return -EINVAL;
+ }
+
+ hdr = (struct ethhdr *)data->buf;
+ if (hdr->h_proto != htons(ETH_P_RACFG)) {
+ atenl_err("invalid protocol type\n");
+ return -EINVAL;
+ }
- return 0;
- }
+ if (!ether_addr_equal(an->mac_addr, hdr->h_dest) &&
+ !is_broadcast_ether_addr(hdr->h_dest)) {
+ atenl_err("invalid dest MAC\n");
+ return -EINVAL;
}
- atenl_err("%s: packet len is too short\n", __func__);
- return -EINVAL;
+ data->len = len;
+
+ return 0;
}
int atenl_eth_send(struct atenl *an, struct atenl_data *data)
@@ -81,11 +87,11 @@
if (len < 60)
len = 60;
else if (len > 1514) {
- atenl_err("%s: response ethernet length is too long\n", __func__);
+ atenl_err("response ethernet length is too long\n");
return -1;
}
- atenl_dbg_print_data(data, __func__, len);
+ atenl_dbg_print_data(data->buf, __func__, len);
addr.sll_family = PF_PACKET;
addr.sll_protocol = htons(ETH_P_RACFG);
@@ -103,7 +109,5 @@
return ret;
}
- atenl_dbg("[%d]%s: send length = %d\n", getpid(), __func__, len);
-
return 0;
}
diff --git a/feed/atenl/src/hqa.c b/feed/atenl/src/hqa.c
index 2196fe2..eabfce5 100644
--- a/feed/atenl/src/hqa.c
+++ b/feed/atenl/src/hqa.c
@@ -200,31 +200,7 @@
{
struct atenl_cmd_hdr *hdr = atenl_hdr(data);
- if (is_mt7986(an)) {
- u32 sub_id, val;
- int ret;
-
- ret = atenl_reg_read(an, 0x18050000, &val);
- if (ret)
- return ret;
-
- switch (val & 0xf) {
- case MT7975_ONE_ADIE_SINGLE_BAND:
- case MT7976_ONE_ADIE_SINGLE_BAND:
- sub_id = htonl(0xa);
- break;
- case MT7976_ONE_ADIE_DBDC:
- sub_id = htonl(0x7);
- break;
- case MT7975_DUAL_ADIE_DBDC:
- case MT7976_DUAL_ADIE_DBDC:
- default:
- sub_id = htonl(0xf);
- break;
- }
-
- memcpy(hdr->data + 2, &sub_id, 4);
- }
+ *(u32 *)(hdr->data + 2) = htonl(an->sub_chip_id);
return 0;
}
@@ -266,13 +242,12 @@
struct atenl_cmd_hdr *hdr = atenl_hdr(data);
enum atenl_cmd cmd = data->cmd;
u32 *v = (u32 *)hdr->data;
- u32 offset = ntohl(v[0]);
+ u32 offset = ntohl(v[0]), res;
int ret;
if (cmd == HQA_CMD_READ_MAC_BBP_REG) {
u16 num = ntohs(*(u16 *)(hdr->data + 4));
u32 *ptr = (u32 *)(hdr->data + 2);
- u32 res;
int i;
if (num > SHRT_MAX) {
@@ -289,6 +264,13 @@
res = htonl(res);
memcpy(ptr + i, &res, 4);
}
+ } else if (cmd == HQA_CMD_READ_MAC_BBP_REG_QA) {
+ ret = atenl_reg_read(an, offset, &res);
+ if (ret)
+ goto out;
+
+ res = htonl(res);
+ memcpy(hdr->data + 2, &res, 4);
} else {
u32 val = ntohl(v[1]);
@@ -305,6 +287,49 @@
}
static int
+atenl_hqa_rf_reg(struct atenl *an, struct atenl_data *data)
+{
+ struct atenl_cmd_hdr *hdr = atenl_hdr(data);
+ enum atenl_cmd cmd = data->cmd;
+ u32 *v = (u32 *)hdr->data;
+ u32 wf_sel = ntohl(v[0]);
+ u32 offset = ntohl(v[1]);
+ u32 num = ntohl(v[2]);
+ int ret, i;
+
+ if (cmd == HQA_CMD_READ_RF_REG) {
+ u32 *ptr = (u32 *)(hdr->data + 2);
+ u32 res;
+
+ hdr->len = htons(2 + num * 4);
+ for (i = 0; i < num && i < sizeof(hdr->data) / 4; i++) {
+ ret = atenl_rf_read(an, wf_sel, offset + i * 4, &res);
+ if (ret)
+ goto out;
+
+ res = htonl(res);
+ memcpy(ptr + i, &res, 4);
+ }
+ } else {
+ u32 *ptr = (u32 *)(hdr->data + 12);
+
+ for (i = 0; i < num && i < sizeof(hdr->data) / 4; i++) {
+ u32 val = ntohl(ptr[i]);
+
+ ret = atenl_rf_write(an, wf_sel, offset + i * 4, val);
+ if (ret)
+ goto out;
+ }
+ }
+
+ ret = 0;
+out:
+ memset(hdr->data, 0, 2);
+
+ return ret;
+}
+
+static int
atenl_hqa_eeprom_bulk(struct atenl *an, struct atenl_data *data)
{
struct atenl_cmd_hdr *hdr = atenl_hdr(data);
@@ -448,12 +473,6 @@
}
static int
-atenl_hqa_skip(struct atenl *an, struct atenl_data *data)
-{
- return 0;
-}
-
-static int
atenl_hqa_check_efuse_mode(struct atenl *an, struct atenl_data *data)
{
struct atenl_cmd_hdr *hdr = atenl_hdr(data);
@@ -587,7 +606,7 @@
if (snprintf_error(sizeof(cmd), ret))
return;
- atenl_dbg("[%d]%s: cmd: %s\n", getpid(), __func__, cmd);
+ atenl_dbg("%s: cmd: %s\n", __func__, cmd);
system(cmd);
}
@@ -692,6 +711,8 @@
*(u32 *)(hdr->data + 2) = data->ext_id;
+ atenl_nl_set_aid(an, band, 0);
+
return 0;
}
@@ -712,314 +733,504 @@
return 0;
}
-static inline enum atenl_cmd atenl_get_cmd_by_id(u16 cmd_idx)
-{
-#define CMD_ID_GROUP GENMASK(15, 8)
- u8 group = FIELD_GET(CMD_ID_GROUP, cmd_idx);
-
- if (cmd_idx == 0x1600)
- return HQA_CMD_EXT;
-
- if (group == 0x10) {
- switch (cmd_idx) {
- case 0x1000:
- return HQA_CMD_OPEN_ADAPTER;
- case 0x1001:
- return HQA_CMD_CLOSE_ADAPTER;
- case 0x100b:
- return HQA_CMD_SET_TX_PATH;
- case 0x100c:
- return HQA_CMD_SET_RX_PATH;
- case 0x1011:
- return HQA_CMD_SET_TX_POWER;
- case 0x1018:
- return HQA_CMD_SET_TX_POWER_MANUAL;
- case 0x100d:
- return HQA_CMD_LEGACY;
- default:
- break;
- }
- } else if (group == 0x11) {
- switch (cmd_idx) {
- case 0x1104:
- return HQA_CMD_SET_TX_BW;
- case 0x1105:
- return HQA_CMD_SET_TX_PKT_BW;
- case 0x1106:
- return HQA_CMD_SET_TX_PRI_BW;
- case 0x1107:
- return HQA_CMD_SET_FREQ_OFFSET;
- case 0x1109:
- return HQA_CMD_SET_TSSI;
- case 0x110d:
- return HQA_CMD_ANT_SWAP_CAP;
- case 0x1101:
- case 0x1102:
- return HQA_CMD_LEGACY;
- default:
- break;
- }
- } else if (group == 0x12) {
- switch (cmd_idx) {
- case 0x1200:
- return HQA_CMD_RESET_TX_RX_COUNTER;
- default:
- break;
- }
- } else if (group == 0x13) {
- switch (cmd_idx) {
- case 0x1301:
- return HQA_CMD_WRITE_MAC_BBP_REG;
- case 0x1302:
- return HQA_CMD_READ_MAC_BBP_REG;
- case 0x1307:
- return HQA_CMD_READ_EEPROM_BULK;
- case 0x1306:
- case 0x1308:
- return HQA_CMD_WRITE_EEPROM_BULK;
- case 0x1309:
- return HQA_CMD_CHECK_EFUSE_MODE;
- case 0x130a:
- return HQA_CMD_GET_EFUSE_FREE_BLOCK;
- case 0x130d:
- return HQA_CMD_GET_TX_POWER;
- case 0x130e:
- return HQA_CMD_SET_CFG;
- case 0x130f:
- return HQA_CMD_GET_FREQ_OFFSET;
- case 0x1311:
- return HQA_CMD_CONTINUOUS_TX;
- case 0x1312:
- return HQA_CMD_SET_RX_PKT_LEN;
- case 0x1313:
- return HQA_CMD_GET_TX_INFO;
- case 0x1314:
- return HQA_CMD_GET_CFG;
- case 0x131f:
- return HQA_CMD_UNKNOWN;
- case 0x131a:
- return HQA_CMD_GET_TX_TONE_POWER;
- default:
- break;
- }
- } else if (group == 0x14) {
- switch (cmd_idx) {
- case 0x1401:
- return HQA_CMD_READ_TEMPERATURE;
- default:
- break;
- }
- } else if (group == 0x15) {
- switch (cmd_idx) {
- case 0x1500:
- return HQA_CMD_GET_FW_INFO;
- case 0x1505:
- return HQA_CMD_SET_TSSI;
- case 0x1509:
- return HQA_CMD_SET_RF_MODE;
- case 0x1511:
- return HQA_CMD_WRITE_BUFFER_DONE;
- case 0x1514:
- return HQA_CMD_GET_CHIP_ID;
- case 0x151b:
- return HQA_CMD_GET_SUB_CHIP_ID;
- case 0x151c:
- return HQA_CMD_GET_RX_INFO;
- case 0x151e:
- return HQA_CMD_GET_RF_CAP;
- case 0x1522:
- return HQA_CMD_CHECK_EFUSE_MODE_TYPE;
- case 0x1523:
- return HQA_CMD_CHECK_EFUSE_MODE_NATIVE;
- case 0x152d:
- return HQA_CMD_GET_BAND;
- case 0x1594:
- return HQA_CMD_SET_RU;
- case 0x1502:
- case 0x150b:
- return HQA_CMD_LEGACY;
- default:
- break;
- }
- }
-
- return HQA_CMD_ERR;
-}
-
-static inline enum atenl_ext_cmd atenl_get_ext_cmd(u16 ext_cmd_idx)
-{
-#define EXT_CMD_ID_GROUP GENMASK(7, 4)
- u8 ext_group = FIELD_GET(EXT_CMD_ID_GROUP, ext_cmd_idx);
-
- if (ext_group == 0) {
- switch (ext_cmd_idx) {
- case 0x1:
- return HQA_EXT_CMD_SET_CHANNEL;
- case 0x2:
- return HQA_EXT_CMD_SET_TX;
- case 0x3:
- return HQA_EXT_CMD_START_TX;
- case 0x4:
- return HQA_EXT_CMD_START_RX;
- case 0x5:
- return HQA_EXT_CMD_STOP_TX;
- case 0x6:
- return HQA_EXT_CMD_STOP_RX;
- case 0x8:
- return HQA_EXT_CMD_IBF_SET_VAL;
- case 0x9:
- return HQA_EXT_CMD_IBF_GET_STATUS;
- case 0xc:
- return HQA_EXT_CMD_IBF_PROF_UPDATE_ALL;
- default:
- break;
- }
- } else if (ext_group == 1) {
- } else if (ext_group == 2) {
- switch (ext_cmd_idx) {
- case 0x26:
- return HQA_EXT_CMD_SET_TX_TIME_OPT;
- case 0x27:
- return HQA_EXT_CMD_OFF_CH_SCAN;
- default:
- break;
- }
- }
-
- return HQA_EXT_CMD_UNSPEC;
-}
-
-#define ATENL_GROUP(_cmd, _resp_len, _ops) \
- [HQA_CMD_##_cmd] = { .resp_len=_resp_len, .ops=_ops }
-static const struct atenl_cmd_ops atenl_ops[] = {
- ATENL_GROUP(OPEN_ADAPTER, 2, atenl_hqa_adapter),
- ATENL_GROUP(CLOSE_ADAPTER, 2, atenl_hqa_adapter),
- ATENL_GROUP(SET_TX_PATH, 2, atenl_nl_process),
- ATENL_GROUP(SET_RX_PATH, 2, atenl_nl_process),
- ATENL_GROUP(SET_TX_POWER, 2, atenl_nl_process),
- ATENL_GROUP(SET_TX_POWER_MANUAL, 2, atenl_hqa_skip),
- ATENL_GROUP(SET_TX_BW, 2, atenl_hqa_skip),
- ATENL_GROUP(SET_TX_PKT_BW, 2, atenl_hqa_skip),
- ATENL_GROUP(SET_TX_PRI_BW, 2, atenl_hqa_skip),
- ATENL_GROUP(SET_FREQ_OFFSET, 2, atenl_nl_process),
- ATENL_GROUP(ANT_SWAP_CAP, 6, atenl_hqa_skip),
- ATENL_GROUP(RESET_TX_RX_COUNTER, 2, atenl_hqa_reset_counter),
- ATENL_GROUP(WRITE_MAC_BBP_REG, 2, atenl_hqa_mac_bbp_reg),
- ATENL_GROUP(READ_MAC_BBP_REG, 0, atenl_hqa_mac_bbp_reg),
- ATENL_GROUP(READ_EEPROM_BULK, 0, atenl_hqa_eeprom_bulk),
- ATENL_GROUP(WRITE_EEPROM_BULK, 2, atenl_hqa_eeprom_bulk),
- ATENL_GROUP(CHECK_EFUSE_MODE, 6, atenl_hqa_check_efuse_mode),
- ATENL_GROUP(GET_EFUSE_FREE_BLOCK, 6, atenl_hqa_get_efuse_free_block),
- ATENL_GROUP(GET_TX_POWER, 10, atenl_hqa_get_tx_power),
- ATENL_GROUP(GET_FREQ_OFFSET, 6, atenl_hqa_get_freq_offset), /*TODO: MCU CMD, read eeprom?*/
- ATENL_GROUP(CONTINUOUS_TX, 6, atenl_nl_process),
- ATENL_GROUP(SET_RX_PKT_LEN, 2, atenl_hqa_skip),
- ATENL_GROUP(GET_TX_INFO, 10, atenl_nl_process),
- ATENL_GROUP(GET_CFG, 6, atenl_hqa_get_cfg), /*TODO*/
- ATENL_GROUP(GET_TX_TONE_POWER, 6, atenl_hqa_skip),
- ATENL_GROUP(SET_CFG, 2, atenl_nl_process),
- ATENL_GROUP(READ_TEMPERATURE, 6, atenl_hqa_read_temperature),
- ATENL_GROUP(GET_FW_INFO, 32, atenl_hqa_skip), /* TODO: check format */
- ATENL_GROUP(SET_TSSI, 2, atenl_nl_process),
- ATENL_GROUP(SET_RF_MODE, 2, atenl_hqa_set_rf_mode),
- ATENL_GROUP(WRITE_BUFFER_DONE, 2, atenl_hqa_eeprom_bulk),
- ATENL_GROUP(GET_CHIP_ID, 6, atenl_hqa_get_chip_id),
- ATENL_GROUP(GET_SUB_CHIP_ID, 6, atenl_hqa_get_sub_chip_id),
- ATENL_GROUP(GET_RX_INFO, 0, atenl_nl_process),
- ATENL_GROUP(GET_RF_CAP, 10, atenl_hqa_get_rf_cap),
- ATENL_GROUP(CHECK_EFUSE_MODE_TYPE, 6, atenl_hqa_check_efuse_mode),
- ATENL_GROUP(CHECK_EFUSE_MODE_NATIVE, 6, atenl_hqa_check_efuse_mode),
- ATENL_GROUP(GET_BAND, 6, atenl_hqa_get_band),
- ATENL_GROUP(SET_RU, 2, atenl_nl_process_many),
-
- ATENL_GROUP(LEGACY, 2, atenl_hqa_skip),
- ATENL_GROUP(UNKNOWN, 1024, atenl_hqa_skip),
+/* should be placed in order for binary search */
+static const struct atenl_ops hqa_ops[] = {
+ {
+ .cmd = HQA_CMD_OPEN_ADAPTER,
+ .cmd_id = 0x1000,
+ .resp_len = 2,
+ .ops = atenl_hqa_adapter,
+ },
+ {
+ .cmd = HQA_CMD_CLOSE_ADAPTER,
+ .cmd_id = 0x1001,
+ .resp_len = 2,
+ .ops = atenl_hqa_adapter,
+ },
+ {
+ .cmd = HQA_CMD_SET_TX_PATH,
+ .cmd_id = 0x100b,
+ .resp_len = 2,
+ .ops = atenl_nl_process,
+ },
+ {
+ .cmd = HQA_CMD_SET_RX_PATH,
+ .cmd_id = 0x100c,
+ .resp_len = 2,
+ .ops = atenl_nl_process,
+ },
+ {
+ .cmd = HQA_CMD_LEGACY,
+ .cmd_id = 0x100d,
+ .resp_len = 2,
+ .flags = ATENL_OPS_FLAG_SKIP,
+ },
+ {
+ .cmd = HQA_CMD_SET_TX_POWER,
+ .cmd_id = 0x1011,
+ .resp_len = 2,
+ .ops = atenl_nl_process,
+ },
+ {
+ .cmd = HQA_CMD_SET_TX_POWER_MANUAL,
+ .cmd_id = 0x1018,
+ .resp_len = 2,
+ .flags = ATENL_OPS_FLAG_SKIP,
+ },
+ {
+ .cmd = HQA_CMD_LEGACY,
+ .cmd_id = 0x1101,
+ .resp_len = 2,
+ .flags = ATENL_OPS_FLAG_SKIP,
+ },
+ {
+ .cmd = HQA_CMD_LEGACY,
+ .cmd_id = 0x1102,
+ .resp_len = 2,
+ .flags = ATENL_OPS_FLAG_SKIP,
+ },
+ {
+ .cmd = HQA_CMD_SET_TX_BW,
+ .cmd_id = 0x1104,
+ .resp_len = 2,
+ .flags = ATENL_OPS_FLAG_SKIP,
+ },
+ {
+ .cmd = HQA_CMD_SET_TX_PKT_BW,
+ .cmd_id = 0x1105,
+ .resp_len = 2,
+ .flags = ATENL_OPS_FLAG_SKIP,
+ },
+ {
+ .cmd = HQA_CMD_SET_TX_PRI_BW,
+ .cmd_id = 0x1106,
+ .resp_len = 2,
+ .flags = ATENL_OPS_FLAG_SKIP,
+ },
+ {
+ .cmd = HQA_CMD_SET_FREQ_OFFSET,
+ .cmd_id = 0x1107,
+ .resp_len = 2,
+ .ops = atenl_nl_process,
+ },
+ {
+ .cmd = HQA_CMD_SET_TSSI,
+ .cmd_id = 0x1109,
+ .resp_len = 2,
+ .ops = atenl_nl_process,
+ },
+ {
+ .cmd = HQA_CMD_SET_EEPROM_TO_FW,
+ .cmd_id = 0x110c,
+ .resp_len = 2,
+ .flags = ATENL_OPS_FLAG_SKIP,
+ },
+ {
+ .cmd = HQA_CMD_ANT_SWAP_CAP,
+ .cmd_id = 0x110d,
+ .resp_len = 6,
+ .flags = ATENL_OPS_FLAG_SKIP,
+ },
+ {
+ .cmd = HQA_CMD_RESET_TX_RX_COUNTER,
+ .cmd_id = 0x1200,
+ .resp_len = 2,
+ .ops = atenl_hqa_reset_counter,
+ },
+ {
+ .cmd = HQA_CMD_READ_MAC_BBP_REG_QA,
+ .cmd_id = 0x1300,
+ .resp_len = 6,
+ .ops = atenl_hqa_mac_bbp_reg,
+ },
+ {
+ .cmd = HQA_CMD_WRITE_MAC_BBP_REG,
+ .cmd_id = 0x1301,
+ .resp_len = 2,
+ .ops = atenl_hqa_mac_bbp_reg,
+ },
+ {
+ .cmd = HQA_CMD_READ_MAC_BBP_REG,
+ .cmd_id = 0x1302,
+ .ops = atenl_hqa_mac_bbp_reg,
+ },
+ {
+ .cmd = HQA_CMD_READ_RF_REG,
+ .cmd_id = 0x1303,
+ .ops = atenl_hqa_rf_reg,
+ },
+ {
+ .cmd = HQA_CMD_WRITE_RF_REG,
+ .cmd_id = 0x1304,
+ .resp_len = 2,
+ .ops = atenl_hqa_rf_reg,
+ },
+ {
+ .cmd = HQA_CMD_WRITE_EEPROM_BULK,
+ .cmd_id = 0x1306,
+ .resp_len = 2,
+ .ops = atenl_hqa_eeprom_bulk,
+ },
+ {
+ .cmd = HQA_CMD_READ_EEPROM_BULK,
+ .cmd_id = 0x1307,
+ .ops = atenl_hqa_eeprom_bulk,
+ },
+ {
+ .cmd = HQA_CMD_WRITE_EEPROM_BULK,
+ .cmd_id = 0x1308,
+ .resp_len = 2,
+ .ops = atenl_hqa_eeprom_bulk,
+ },
+ {
+ .cmd = HQA_CMD_CHECK_EFUSE_MODE,
+ .cmd_id = 0x1309,
+ .resp_len = 6,
+ .ops = atenl_hqa_check_efuse_mode,
+ },
+ {
+ .cmd = HQA_CMD_GET_EFUSE_FREE_BLOCK,
+ .cmd_id = 0x130a,
+ .resp_len = 6,
+ .ops = atenl_hqa_get_efuse_free_block,
+ },
+ {
+ .cmd = HQA_CMD_GET_TX_POWER,
+ .cmd_id = 0x130d,
+ .resp_len = 10,
+ .ops = atenl_hqa_get_tx_power,
+ },
+ {
+ .cmd = HQA_CMD_SET_CFG,
+ .cmd_id = 0x130e,
+ .resp_len = 2,
+ .ops = atenl_nl_process,
+ },
+ {
+ .cmd = HQA_CMD_GET_FREQ_OFFSET,
+ .cmd_id = 0x130f,
+ .resp_len = 6,
+ .ops = atenl_hqa_get_freq_offset,
+ },
+ {
+ .cmd = HQA_CMD_CONTINUOUS_TX,
+ .cmd_id = 0x1311,
+ .resp_len = 6,
+ .ops = atenl_nl_process,
+ },
+ {
+ .cmd = HQA_CMD_SET_RX_PKT_LEN,
+ .cmd_id = 0x1312,
+ .resp_len = 2,
+ .flags = ATENL_OPS_FLAG_SKIP,
+ },
+ {
+ .cmd = HQA_CMD_GET_TX_INFO,
+ .cmd_id = 0x1313,
+ .resp_len = 10,
+ .ops = atenl_nl_process,
+ },
+ {
+ .cmd = HQA_CMD_GET_CFG,
+ .cmd_id = 0x1314,
+ .resp_len = 6,
+ .ops = atenl_hqa_get_cfg,
+ },
+ {
+ .cmd = HQA_CMD_GET_TX_TONE_POWER,
+ .cmd_id = 0x131a,
+ .resp_len = 6,
+ .flags = ATENL_OPS_FLAG_SKIP,
+ },
+ {
+ .cmd = HQA_CMD_UNKNOWN,
+ .cmd_id = 0x131f,
+ .resp_len = 1024,
+ .flags = ATENL_OPS_FLAG_SKIP,
+ },
+ {
+ .cmd = HQA_CMD_READ_TEMPERATURE,
+ .cmd_id = 0x1401,
+ .resp_len = 6,
+ .ops = atenl_hqa_read_temperature,
+ },
+ {
+ .cmd = HQA_CMD_GET_FW_INFO,
+ .cmd_id = 0x1500,
+ .resp_len = 32,
+ .flags = ATENL_OPS_FLAG_SKIP,
+ },
+ {
+ .cmd_id = 0x1502,
+ .flags = ATENL_OPS_FLAG_LEGACY,
+ },
+ {
+ .cmd = HQA_CMD_SET_TSSI,
+ .cmd_id = 0x1505,
+ .resp_len = 2,
+ .ops = atenl_nl_process,
+ },
+ {
+ .cmd = HQA_CMD_SET_RF_MODE,
+ .cmd_id = 0x1509,
+ .resp_len = 2,
+ .ops = atenl_hqa_set_rf_mode,
+ },
+ {
+ .cmd_id = 0x150b,
+ .flags = ATENL_OPS_FLAG_LEGACY,
+ },
+ {
+ .cmd = HQA_CMD_WRITE_BUFFER_DONE,
+ .cmd_id = 0x1511,
+ .resp_len = 2,
+ .ops = atenl_hqa_eeprom_bulk,
+ },
+ {
+ .cmd = HQA_CMD_GET_CHIP_ID,
+ .cmd_id = 0x1514,
+ .resp_len = 6,
+ .ops = atenl_hqa_get_chip_id,
+ },
+ {
+ .cmd = HQA_CMD_GET_SUB_CHIP_ID,
+ .cmd_id = 0x151b,
+ .resp_len = 6,
+ .ops = atenl_hqa_get_sub_chip_id,
+ },
+ {
+ .cmd = HQA_CMD_GET_RX_INFO,
+ .cmd_id = 0x151c,
+ .ops = atenl_nl_process,
+ },
+ {
+ .cmd = HQA_CMD_GET_RF_CAP,
+ .cmd_id = 0x151e,
+ .resp_len = 10,
+ .ops = atenl_hqa_get_rf_cap,
+ },
+ {
+ .cmd = HQA_CMD_CHECK_EFUSE_MODE_TYPE,
+ .cmd_id = 0x1522,
+ .resp_len = 6,
+ .ops = atenl_hqa_check_efuse_mode,
+ },
+ {
+ .cmd = HQA_CMD_CHECK_EFUSE_MODE_NATIVE,
+ .cmd_id = 0x1523,
+ .resp_len = 6,
+ .ops = atenl_hqa_check_efuse_mode,
+ },
+ {
+ .cmd = HQA_CMD_GET_BAND,
+ .cmd_id = 0x152d,
+ .resp_len = 6,
+ .ops = atenl_hqa_get_band,
+ },
+ {
+ .cmd = HQA_CMD_SET_RU,
+ .cmd_id = 0x1594,
+ .resp_len = 2,
+ .ops = atenl_nl_process_many,
+ },
};
-#undef ATENL_GROUP
-#define ATENL_EXT(_cmd, _resp_len, _ops) \
- [HQA_EXT_CMD_##_cmd] = { .resp_len=_resp_len, .ops=_ops }
-static const struct atenl_cmd_ops atenl_ext_ops[] = {
- ATENL_EXT(SET_CHANNEL, 6, atenl_hqa_set_channel),
- ATENL_EXT(SET_TX, 6, atenl_nl_process),
- ATENL_EXT(START_TX, 6, atenl_nl_process),
- ATENL_EXT(STOP_TX, 6, atenl_nl_process),
- ATENL_EXT(START_RX, 6, atenl_nl_process),
- ATENL_EXT(STOP_RX, 6, atenl_nl_process),
- ATENL_EXT(SET_TX_TIME_OPT, 6, atenl_hqa_tx_time_option),
- ATENL_EXT(OFF_CH_SCAN, 6, atenl_nl_process),
- ATENL_EXT(IBF_SET_VAL, 6, atenl_nl_process),
- ATENL_EXT(IBF_GET_STATUS, 10, atenl_nl_process),
- ATENL_EXT(IBF_PROF_UPDATE_ALL, 6, atenl_nl_process_many),
+static const struct atenl_ops hqa_ops_ext[] = {
+ {
+ .cmd = HQA_EXT_CMD_SET_CHANNEL,
+ .cmd_id = 0x01,
+ .resp_len = 6,
+ .ops = atenl_hqa_set_channel,
+ .flags = ATENL_OPS_FLAG_EXT_CMD,
+ },
+ {
+ .cmd = HQA_EXT_CMD_SET_TX,
+ .cmd_id = 0x02,
+ .resp_len = 6,
+ .ops = atenl_nl_process,
+ .flags = ATENL_OPS_FLAG_EXT_CMD,
+ },
+ {
+ .cmd = HQA_EXT_CMD_START_TX,
+ .cmd_id = 0x03,
+ .resp_len = 6,
+ .ops = atenl_nl_process,
+ .flags = ATENL_OPS_FLAG_EXT_CMD,
+ },
+ {
+ .cmd = HQA_EXT_CMD_START_RX,
+ .cmd_id = 0x04,
+ .resp_len = 6,
+ .ops = atenl_nl_process,
+ .flags = ATENL_OPS_FLAG_EXT_CMD,
+ },
+ {
+ .cmd = HQA_EXT_CMD_STOP_TX,
+ .cmd_id = 0x05,
+ .resp_len = 6,
+ .ops = atenl_nl_process,
+ .flags = ATENL_OPS_FLAG_EXT_CMD,
+ },
+ {
+ .cmd = HQA_EXT_CMD_STOP_RX,
+ .cmd_id = 0x06,
+ .resp_len = 6,
+ .ops = atenl_nl_process,
+ .flags = ATENL_OPS_FLAG_EXT_CMD,
+ },
+ {
+ .cmd = HQA_EXT_CMD_IBF_SET_VAL,
+ .cmd_id = 0x08,
+ .resp_len = 6,
+ .ops = atenl_nl_process,
+ .flags = ATENL_OPS_FLAG_EXT_CMD,
+ },
+ {
+ .cmd = HQA_EXT_CMD_IBF_GET_STATUS,
+ .cmd_id = 0x09,
+ .resp_len = 10,
+ .ops = atenl_nl_process,
+ .flags = ATENL_OPS_FLAG_EXT_CMD,
+ },
+ {
+ .cmd = HQA_EXT_CMD_IBF_PROF_UPDATE_ALL,
+ .cmd_id = 0x0c,
+ .resp_len = 6,
+ .ops = atenl_nl_process,
+ .flags = ATENL_OPS_FLAG_EXT_CMD,
+ },
+ {
+ .cmd = HQA_EXT_CMD_SET_TX_TIME_OPT,
+ .cmd_id = 0x26,
+ .resp_len = 6,
+ .ops = atenl_hqa_tx_time_option,
+ .flags = ATENL_OPS_FLAG_EXT_CMD,
+ },
+ {
+ .cmd = HQA_EXT_CMD_OFF_CH_SCAN,
+ .cmd_id = 0x27,
+ .resp_len = 6,
+ .ops = atenl_nl_process,
+ .flags = ATENL_OPS_FLAG_EXT_CMD,
+ },
};
-#undef ATENL_EXT
-int atenl_hqa_recv(struct atenl *an, struct atenl_data *data)
+static const struct atenl_ops *
+atenl_get_ops(struct atenl_data *data)
{
+ const struct atenl_ops *group;
struct atenl_cmd_hdr *hdr = atenl_hdr(data);
- u16 cmd_type = ntohs(hdr->cmd_type);
- int fd = an->pipefd[PIPE_WRITE];
- int ret;
+ u16 cmd_id = ntohs(hdr->cmd_id), id = cmd_id;
+ int size, low = 0, high;
- if (ntohl(hdr->magic_no) != RACFG_MAGIC_NO)
- return -EINVAL;
-
- if (FIELD_GET(RACFG_CMD_TYPE_MASK, cmd_type) != RACFG_CMD_TYPE_ETHREQ &&
- FIELD_GET(RACFG_CMD_TYPE_MASK, cmd_type) != RACFG_CMD_TYPE_PLATFORM_MODULE) {
- atenl_err("[%d]%s: cmd type error = 0x%x\n", getpid(), __func__, cmd_type);
- return -EINVAL;
+ switch (cmd_id) {
+ case 0x1600:
+ group = hqa_ops_ext;
+ size = ARRAY_SIZE(hqa_ops_ext);
+ break;
+ default:
+ group = hqa_ops;
+ size = ARRAY_SIZE(hqa_ops);
+ break;
}
+ if (group[0].flags & ATENL_OPS_FLAG_EXT_CMD)
+ id = ntohl(*(u32 *)hdr->data);
+
- atenl_dbg("[%d]%s: recv cmd type = 0x%x, id = 0x%x\n",
- getpid(), __func__, cmd_type, ntohs(hdr->cmd_id));
+ /* binary search */
+ high = size - 1;
+ while (low <= high) {
+ int mid = low + (high - low) / 2;
- ret = write(fd, data, data->len);
- if (ret < 0) {
- perror("pipe write");
- return ret;
+ if (group[mid].cmd_id == id)
+ return &group[mid];
+ else if (group[mid].cmd_id > id)
+ high = mid - 1;
+ else
+ low = mid + 1;
}
- return 0;
+ return NULL;
}
-int atenl_hqa_proc_cmd(struct atenl *an, struct atenl_data *data)
+static int
+atenl_hqa_handler(struct atenl *an, struct atenl_data *data)
{
struct atenl_cmd_hdr *hdr = atenl_hdr(data);
- const struct atenl_cmd_ops *ops;
+ const struct atenl_ops *ops = NULL;
u16 cmd_id = ntohs(hdr->cmd_id);
u16 status = 0;
- data->cmd = atenl_get_cmd_by_id(cmd_id);
- if (data->cmd == HQA_CMD_ERR) {
- atenl_err("Unknown command id: 0x%04x\n", cmd_id);
+ atenl_dbg("handle command: 0x%x\n", cmd_id);
+
+ ops = atenl_get_ops(data);
+ if (!ops || (!ops->ops && !ops->flags)) {
+ atenl_err("Unknown command id: 0x%x\n", cmd_id);
goto done;
}
- if (data->cmd == HQA_CMD_EXT) {
- data->ext_id = ntohl(*(u32 *)hdr->data);
- data->ext_cmd = atenl_get_ext_cmd(data->ext_id);
- if (data->ext_cmd == HQA_EXT_CMD_UNSPEC) {
- atenl_err("Unknown ext command id: 0x%04x\n", data->ext_id);
- goto done;
- }
-
- ops = &atenl_ext_ops[data->ext_cmd];
- } else {
- ops = &atenl_ops[data->cmd];
+ data->cmd = ops->cmd;
+ data->cmd_id = ops->cmd_id;
+ if (ops->flags & ATENL_OPS_FLAG_EXT_CMD) {
+ data->ext_cmd = ops->cmd;
+ data->ext_id = ops->cmd_id;
}
+ if (ops->flags & ATENL_OPS_FLAG_SKIP)
+ goto done;
+
- atenl_dbg_print_data(data, __func__,
+ atenl_dbg_print_data(data->buf, __func__,
ntohs(hdr->len) + ETH_HLEN + RACFG_HLEN);
if (ops->ops)
status = htons(ops->ops(an, data));
if (ops->resp_len)
hdr->len = htons(ops->resp_len);
- *(u16 *)hdr->data = status;
-
done:
+ *(u16 *)hdr->data = status;
data->len = ntohs(hdr->len) + ETH_HLEN + RACFG_HLEN;
hdr->cmd_type |= ~htons(RACFG_CMD_TYPE_MASK);
return 0;
}
+
+int atenl_hqa_proc_cmd(struct atenl *an)
+{
+ struct atenl_data *data;
+ struct atenl_cmd_hdr *hdr;
+ u16 cmd_type;
+ int ret = -EINVAL;
+
+ data = calloc(1, sizeof(struct atenl_data));
+ if (!data)
+ return -ENOMEM;
+
+ ret = atenl_eth_recv(an, data);
+ if (ret)
+ goto out;
+
+ hdr = atenl_hdr(data);
+ if (ntohl(hdr->magic_no) != RACFG_MAGIC_NO)
+ goto out;
+
+ cmd_type = ntohs(hdr->cmd_type);
+ if (FIELD_GET(RACFG_CMD_TYPE_MASK, cmd_type) != RACFG_CMD_TYPE_ETHREQ &&
+ FIELD_GET(RACFG_CMD_TYPE_MASK, cmd_type) != RACFG_CMD_TYPE_PLATFORM_MODULE) {
+ atenl_err("cmd type error = 0x%x\n", cmd_type);
+ goto out;
+ }
+
+ ret = atenl_hqa_handler(an, data);
+ if (ret)
+ goto out;
+
+ ret = atenl_eth_send(an, data);
+ if (ret)
+ goto out;
+
+ ret = 0;
+out:
+ free(data);
+
+ return ret;
+}
diff --git a/feed/atenl/src/main.c b/feed/atenl/src/main.c
index ec0a320..9667da3 100644
--- a/feed/atenl/src/main.c
+++ b/feed/atenl/src/main.c
@@ -58,7 +58,7 @@
static void usage(void)
{
- fprintf(stderr, "Usage:\n");
+ printf("Usage:\n");
printf(" %s [-u] [-i phyX]\n", progname);
printf("options:\n"
" -h = show help text\n"
@@ -70,13 +70,12 @@
exit(EXIT_FAILURE);
}
-static int atenl_parent_work(struct atenl *an)
+static void atenl_handler_run(struct atenl *an)
{
- int sock_eth = an->sock_eth;
- int count, ret = 0;
+ int count, sock_eth = an->sock_eth;
fd_set readfds;
- atenl_info("[%d]%s: start for receiving HQA commands\n", getpid(), __func__);
+ atenl_info("Start atenl HQA command handler\n");
while (atenl_enable) {
FD_ZERO(&readfds);
@@ -85,92 +84,18 @@
if (count < 0) {
atenl_err("%s: select failed, %s\n", __func__, strerror(errno));
- continue;
} else if (count == 0) {
usleep(1000);
- continue;
} else {
- if (FD_ISSET(sock_eth, &readfds)) {
- struct atenl_data *data = calloc(1, sizeof(struct atenl_data));
-
- ret = atenl_eth_recv(an, data);
- if (ret) {
- kill(an->child_pid, SIGUSR1);
- return ret;
- }
-
- ret = atenl_hqa_recv(an, data);
- if (ret < 0) {
- kill(an->child_pid, SIGUSR1);
- return ret;
- }
-
- free(data);
- }
+ if (!FD_ISSET(sock_eth, &readfds))
+ continue;
+ atenl_hqa_proc_cmd(an);
}
}
- atenl_info("[%d]%s: parent work end\n", getpid(), __func__);
-
- return ret;
+ atenl_dbg("HQA command handler end\n");
}
-static int atenl_child_work(struct atenl *an)
-{
- int rfd = an->pipefd[PIPE_READ], count;
- int ret = 0;
- fd_set readfds;
-
- atenl_info("[%d]%s: start for sending back results\n", getpid(), __func__);
-
- while (atenl_enable) {
- struct atenl_data *data = calloc(1, sizeof(struct atenl_data));
-
- FD_ZERO(&readfds);
- FD_SET(rfd, &readfds);
-
- count = select(FD_SETSIZE, &readfds, NULL, NULL, NULL);
-
- if (count < 0) {
- atenl_err("%s: select failed, %s\n", __func__, strerror(errno));
- continue;
- } else if (count == 0) {
- usleep(1000);
- continue;
- } else {
- if (FD_ISSET(rfd, &readfds)) {
- count = read(rfd, data->buf, RACFG_PKT_MAX_SIZE);
- atenl_dbg("[%d]PIPE Read %d bytes\n", getpid(), count);
-
- if (count < 0) {
- atenl_info("%s: %s\n", __func__, strerror(errno));
- } else if (count == 0) {
- continue;
- } else {
- int ret;
-
- ret = atenl_hqa_proc_cmd(an, data);
- if (ret) {
- kill(getppid(), SIGUSR2);
- goto out;
- }
-
- ret = atenl_eth_send(an, data);
- if (ret) {
- kill(getppid(), SIGUSR2);
- goto out;
- }
- }
- }
- }
- }
-
-out:
- atenl_info("[%d]%s: child work end\n", getpid(), __func__);
-
- return ret;
-}
-
int main(int argc, char **argv)
{
int opt, phy_idx, ret = 0;
@@ -191,8 +116,7 @@
switch (opt) {
case 'h':
usage();
- free(an);
- return 0;
+ goto out;
case 'i':
phy = optarg;
break;
@@ -204,16 +128,15 @@
cmd = optarg;
break;
default:
- fprintf(stderr, "Not supported option\n");
- break;
+ atenl_err("Not supported option: %c\n", opt);
+ goto out;
}
}
phy_idx = phy_lookup_idx(phy);
if (phy_idx < 0 || phy_idx > UCHAR_MAX) {
- fprintf(stderr, "Could not find phy '%s'\n", phy);
- free(an);
- return 2;
+ atenl_err("Could not find phy '%s'\n", phy);
+ goto out;
}
if (cmd) {
@@ -226,8 +149,6 @@
/* background ourself */
if (!fork()) {
- pid_t pid;
-
ret = atenl_eeprom_init(an, phy_idx);
if (ret)
goto out;
@@ -236,28 +157,7 @@
if (ret)
goto out;
- ret = pipe(an->pipefd);
- if (ret) {
- perror("Pipe");
- goto out;
- }
-
- pid = fork();
- an->child_pid = pid;
- if (pid < 0) {
- perror("Fork");
- ret = pid;
- goto out;
- } else if (pid == 0) {
- close(an->pipefd[PIPE_WRITE]);
- atenl_child_work(an);
- } else {
- int status;
-
- close(an->pipefd[PIPE_READ]);
- atenl_parent_work(an);
- waitpid(pid, &status, 0);
- }
+ atenl_handler_run(an);
} else {
usleep(800000);
}
diff --git a/feed/atenl/src/nl.c b/feed/atenl/src/nl.c
index e1d0d0f..368ffbd 100644
--- a/feed/atenl/src/nl.c
+++ b/feed/atenl/src/nl.c
@@ -214,28 +214,25 @@
u8 *addr1 = hdr->data + 36;
u8 *addr2 = addr1 + ETH_ALEN;
u8 *addr3 = addr2 + ETH_ALEN;
- u8 default_addr[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
+ u8 def_mac[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
void *ptr, *a;
+ if (get_band_val(an, an->cur_band, use_tx_time))
+ set_band_val(an, an->cur_band, tx_time, ntohl(v[7]));
+ else
+ set_band_val(an, an->cur_band, tx_mpdu_len, ntohl(v[7]));
+
ptr = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
if (!ptr)
return -ENOMEM;
- if (get_band_val(an, an->cur_band, use_tx_time))
- nla_put_u32(msg, MT76_TM_ATTR_TX_TIME, ntohl(v[7]));
- else
- nla_put_u32(msg, MT76_TM_ATTR_TX_LENGTH, ntohl(v[7]));
-
a = nla_nest_start(msg, MT76_TM_ATTR_MAC_ADDRS);
if (!a)
return -ENOMEM;
- if (is_multicast_ether_addr(addr1))
- nla_put(msg, 0, ETH_ALEN, default_addr);
- else
- nla_put(msg, 0, ETH_ALEN, addr1);
- nla_put(msg, 1, ETH_ALEN, addr2);
- nla_put(msg, 2, ETH_ALEN, addr3);
+ nla_put(msg, 0, ETH_ALEN, use_default_addr(addr1) ? def_mac : addr1);
+ nla_put(msg, 1, ETH_ALEN, use_default_addr(addr2) ? def_mac : addr2);
+ nla_put(msg, 2, ETH_ALEN, use_default_addr(addr3) ? def_mac : addr3);
nla_nest_end(msg, a);
@@ -288,6 +285,13 @@
nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_LDPC, ntohl(v[8]));
nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_NSS, ntohl(v[15]));
+ if (get_band_val(an, band, use_tx_time))
+ nla_put_u32(msg, MT76_TM_ATTR_TX_TIME,
+ get_band_val(an, band, tx_time));
+ else
+ nla_put_u32(msg, MT76_TM_ATTR_TX_LENGTH,
+ get_band_val(an, band, tx_mpdu_len));
+
/* for chips after 7915, tx need to use at least wcid = 1 */
if (!is_mt7915(an) && !aid)
aid = 1;
@@ -405,7 +409,7 @@
nla_nest_end(msg, ptr);
- memcpy(hdr->data + 2, &data->ext_id, 4);
+ *(u32 *)(hdr->data + 2) = data->ext_id;
return 0;
}
@@ -421,7 +425,7 @@
nl_attr = unl_find_attr(&nl_priv->unl, msg, NL80211_ATTR_TESTDATA);
if (!nl_attr) {
- fprintf(stderr, "Testdata attribute not found\n");
+ atenl_err("Testdata attribute not found\n");
return NL_SKIP;
}
@@ -572,7 +576,7 @@
nl_attr = unl_find_attr(&nl_priv->unl, msg, NL80211_ATTR_TESTDATA);
if (!nl_attr) {
- fprintf(stderr, "Testdata attribute not found\n");
+ atenl_err("Testdata attribute not found\n");
return NL_SKIP;
}
@@ -585,9 +589,10 @@
rx_cur.len_mismatch = nla_get_u64(tb2[MT76_TM_STATS_ATTR_RX_LEN_MISMATCH]);
rx_cur.ok_cnt = rx_cur.total - rx_cur.err_cnt - rx_cur.len_mismatch;
- if (!anb->reset_rx_cnt) {
+ if (!anb->reset_rx_cnt ||
+ get_band_val(an, an->cur_band, cur_state) == MT76_TM_STATE_RX_FRAMES) {
#define RX_COUNT_DIFF(_field) \
- rx_diff._field = (rx_cur._field) - (anb->rx_stat._field)
+ rx_diff._field = (rx_cur._field) - (anb->rx_stat._field);
RX_COUNT_DIFF(total);
RX_COUNT_DIFF(err_cnt);
RX_COUNT_DIFF(len_mismatch);
@@ -691,7 +696,7 @@
char buf[10];
if (unl_genl_init(&nl_priv->unl, "nl80211") < 0) {
- fprintf(stderr, "Failed to connect to nl80211\n");
+ atenl_err("Failed to connect to nl80211\n");
return 2;
}
@@ -728,8 +733,107 @@
return 0;
}
-static int atenl_nl_ibf_set_val(struct atenl *an, struct atenl_data *data,
- struct atenl_nl_priv *nl_priv)
+static int
+atenl_nl_ibf_init(struct atenl *an, u8 band)
+{
+ struct atenl_nl_priv nl_priv = {};
+ struct nl_msg *msg;
+ void *ptr, *a;
+ int ret;
+
+ if (unl_genl_init(&nl_priv.unl, "nl80211") < 0) {
+ atenl_err("Failed to connect to nl80211\n");
+ return 2;
+ }
+
+ msg = unl_genl_msg(&nl_priv.unl, NL80211_CMD_TESTMODE, false);
+ nla_put_u32(msg, NL80211_ATTR_WIPHY, get_band_val(an, band, phy_idx));
+
+ ptr = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
+ if (!ptr) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_MODE, MT76_TM_TX_MODE_HT);
+ nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_IDX, an->ibf_mcs);
+ nla_put_u8(msg, MT76_TM_ATTR_TX_ANTENNA, an->ibf_ant);
+ nla_put_u8(msg, MT76_TM_ATTR_TXBF_ACT, MT76_TM_TXBF_ACT_INIT);
+
+ a = nla_nest_start(msg, MT76_TM_ATTR_TXBF_PARAM);
+ if (!a) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ nla_put_u16(msg, 0, 1);
+ nla_nest_end(msg, a);
+
+ nla_nest_end(msg, ptr);
+
+ ret = unl_genl_request(&nl_priv.unl, msg, NULL, NULL);
+
+out:
+ unl_free(&nl_priv.unl);
+ return ret;
+}
+
+static int
+atenl_nl_ibf_e2p_update(struct atenl *an)
+{
+ struct atenl_nl_priv nl_priv = {};
+ struct nl_msg *msg;
+ void *ptr, *a;
+ int ret;
+
+ if (unl_genl_init(&nl_priv.unl, "nl80211") < 0) {
+ atenl_err("Failed to connect to nl80211\n");
+ return 2;
+ }
+
+ msg = unl_genl_msg(&nl_priv.unl, NL80211_CMD_TESTMODE, false);
+ nla_put_u32(msg, NL80211_ATTR_WIPHY, get_band_val(an, an->cur_band, phy_idx));
+
+ ptr = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
+ if (!ptr) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ nla_put_u8(msg, MT76_TM_ATTR_TXBF_ACT, MT76_TM_TXBF_ACT_E2P_UPDATE);
+ a = nla_nest_start(msg, MT76_TM_ATTR_TXBF_PARAM);
+ if (!a) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ nla_put_u16(msg, 0, 0);
+ nla_nest_end(msg, a);
+
+ nla_nest_end(msg, ptr);
+
+ ret = unl_genl_request(&nl_priv.unl, msg, NULL, NULL);
+
+out:
+ unl_free(&nl_priv.unl);
+ return ret;
+}
+
+static void
+atenl_get_ibf_cal_result(struct atenl *an)
+{
+ u16 offset;
+
+ if (an->adie_id == 0x7975)
+ offset = 0x651;
+ else if (an->adie_id == 0x7976)
+ offset = 0x60a;
+
+ /* per group size = 40, for group 0-8 */
+ atenl_eeprom_read_from_driver(an, offset, 40 * 9);
+}
+
+static int
+atenl_nl_ibf_set_val(struct atenl *an, struct atenl_data *data,
+ struct atenl_nl_priv *nl_priv)
{
#define MT_IBF(_act) MT76_TM_TXBF_ACT_##_act
static const u8 bf_act_map[] = {
@@ -744,6 +848,7 @@
u32 *v = (u32 *)(hdr->data + 4);
u32 action = ntohl(v[0]);
u16 val[8];
+ u8 tmp_ant;
void *ptr, *a;
char cmd[64];
int i;
@@ -759,24 +864,15 @@
return -ENOMEM;
switch (action) {
- case TXBF_ACT_INIT:
- nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_MODE, MT76_TM_TX_MODE_HT);
- nla_put_u8(msg, MT76_TM_ATTR_AID, 1);
- nla_put_u8(msg, MT76_TM_ATTR_TXBF_ACT, MT76_TM_TXBF_ACT_INIT);
-
- a = nla_nest_start(msg, MT76_TM_ATTR_TXBF_PARAM);
- if (!a)
- return -ENOMEM;
- nla_put_u16(msg, 0, 1);
- if (!val[0])
- nla_put_u16(msg, 1, 1); /* init */
- nla_nest_end(msg, a);
- break;
case TXBF_ACT_CHANNEL:
- sprintf(cmd, "iw dev mon%d set channel %u HT20",
- get_band_val(an, an->cur_band, phy_idx), val[0]);
- system(cmd);
- printf("%s: %s", __func__, cmd);
+ an->cur_band = val[1];
+ /* a sanity to prevent script band idx error */
+ if (val[0] > 14)
+ an->cur_band = 1;
+ atenl_nl_ibf_init(an, an->cur_band);
+ atenl_set_channel(an, 0, an->cur_band, val[0], 0, 0);
+
+ nla_put_u8(msg, MT76_TM_ATTR_AID, 0);
nla_put_u8(msg, MT76_TM_ATTR_TXBF_ACT, MT76_TM_TXBF_ACT_UPDATE_CH);
a = nla_nest_start(msg, MT76_TM_ATTR_TXBF_PARAM);
if (!a)
@@ -785,10 +881,14 @@
nla_nest_end(msg, a);
break;
case TXBF_ACT_MCS:
- nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_IDX, val[0]);
- nla_put_u8(msg, MT76_TM_ATTR_TX_ANTENNA, (1 << DIV_ROUND_UP(val[0], 8)) - 1);
- break;
- case TXBF_ACT_POWER:
+ tmp_ant = (1 << DIV_ROUND_UP(val[0], 8)) - 1 ?: 1;
+ /* sometimes the correct band idx will be set after this action,
+ * so maintain a temp variable to allow mcs update in anthor action.
+ */
+ an->ibf_mcs = val[0];
+ an->ibf_ant = tmp_ant;
+ nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_IDX, an->ibf_mcs);
+ nla_put_u8(msg, MT76_TM_ATTR_TX_ANTENNA, an->ibf_ant);
break;
case TXBF_ACT_TX_ANT:
nla_put_u8(msg, MT76_TM_ATTR_TX_ANTENNA, val[0]);
@@ -801,8 +901,9 @@
break;
case TXBF_ACT_TX_PKT:
nla_put_u8(msg, MT76_TM_ATTR_AID, val[1]);
- nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, 10000000);
nla_put_u8(msg, MT76_TM_ATTR_TXBF_ACT, MT76_TM_TXBF_ACT_TX_PREP);
+ nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, 10000000);
+ nla_put_u32(msg, MT76_TM_ATTR_TX_LENGTH, 1024);
a = nla_nest_start(msg, MT76_TM_ATTR_TXBF_PARAM);
if (!a)
return -ENOMEM;
@@ -814,6 +915,7 @@
atenl_set_attr_state(an, msg, an->cur_band, MT76_TM_STATE_TX_FRAMES);
break;
case TXBF_ACT_IBF_PHASE_COMP:
+ nla_put_u8(msg, MT76_TM_ATTR_AID, 1);
case TXBF_ACT_IBF_PROF_UPDATE:
case TXBF_ACT_EBF_PROF_UPDATE:
case TXBF_ACT_IBF_PHASE_CAL:
@@ -827,8 +929,8 @@
nla_nest_end(msg, a);
break;
case TXBF_ACT_IBF_PHASE_E2P_UPDATE:
- atenl_eeprom_read_from_driver(an, 0x651, 0x28 * 9);
- atenl_eeprom_write_mtd(an);
+ atenl_nl_ibf_e2p_update(an);
+ atenl_get_ibf_cal_result(an);
nla_put_u8(msg, MT76_TM_ATTR_AID, 0);
nla_put_u8(msg, MT76_TM_ATTR_TXBF_ACT, MT76_TM_TXBF_ACT_INIT);
@@ -839,13 +941,15 @@
nla_put_u16(msg, 0, 0);
nla_nest_end(msg, a);
break;
+ case TXBF_ACT_INIT:
+ case TXBF_ACT_POWER:
default:
break;
}
nla_nest_end(msg, ptr);
- memcpy(hdr->data + 2, &data->ext_id, 4);
+ *(u32 *)(hdr->data + 2) = data->ext_id;
return unl_genl_request(&nl_priv->unl, msg, NULL, NULL);
}
@@ -857,7 +961,7 @@
struct atenl_cmd_hdr *hdr = atenl_hdr(data);
u32 status = htonl(1);
- memcpy(hdr->data + 2, &data->ext_id, 4);
+ *(u32 *)(hdr->data + 2) = data->ext_id;
memcpy(hdr->data + 6, &status, 4);
return 0;
@@ -878,7 +982,7 @@
int j;
if (unl_genl_init(&nl_priv->unl, "nl80211") < 0) {
- fprintf(stderr, "Failed to connect to nl80211\n");
+ atenl_err("Failed to connect to nl80211\n");
return 2;
}
@@ -907,7 +1011,7 @@
unl_free(&nl_priv->unl);
}
- memcpy(hdr->data + 2, &data->ext_id, 4);
+ *(u32 *)(hdr->data + 2) = data->ext_id;
return 0;
}
@@ -954,7 +1058,7 @@
ops = &nl_ops[data->cmd];
if (unl_genl_init(&nl_priv.unl, "nl80211") < 0) {
- fprintf(stderr, "Failed to connect to nl80211\n");
+ atenl_err("Failed to connect to nl80211\n");
return -1;
}
@@ -973,7 +1077,7 @@
}
if (ret)
- atenl_err("command process error: %d (%d)\n", data->cmd, data->ext_cmd);
+ atenl_err("command process error: 0x%x (0x%x)\n", data->cmd_id, data->ext_id);
unl_free(&nl_priv.unl);
@@ -1005,7 +1109,7 @@
void *ptr;
if (unl_genl_init(&nl_priv.unl, "nl80211") < 0) {
- fprintf(stderr, "Failed to connect to nl80211\n");
+ atenl_err("Failed to connect to nl80211\n");
return 2;
}
@@ -1027,6 +1131,35 @@
return 0;
}
+int atenl_nl_set_aid(struct atenl *an, u8 band, u8 aid)
+{
+ struct atenl_nl_priv nl_priv = {};
+ struct nl_msg *msg;
+ void *ptr;
+
+ if (unl_genl_init(&nl_priv.unl, "nl80211") < 0) {
+ atenl_err("Failed to connect to nl80211\n");
+ return 2;
+ }
+
+ msg = unl_genl_msg(&nl_priv.unl, NL80211_CMD_TESTMODE, false);
+ nla_put_u32(msg, NL80211_ATTR_WIPHY, get_band_val(an, band, phy_idx));
+
+ ptr = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
+ if (!ptr)
+ return -ENOMEM;
+
+ nla_put_u8(msg, MT76_TM_ATTR_AID, aid);
+
+ nla_nest_end(msg, ptr);
+
+ unl_genl_request(&nl_priv.unl, msg, NULL, NULL);
+
+ unl_free(&nl_priv.unl);
+
+ return 0;
+}
+
static int atenl_nl_check_mtd_cb(struct nl_msg *msg, void *arg)
{
struct atenl_nl_priv *nl_priv = (struct atenl_nl_priv *)arg;
@@ -1054,7 +1187,7 @@
struct nl_msg *msg;
if (unl_genl_init(&nl_priv.unl, "nl80211") < 0) {
- fprintf(stderr, "Failed to connect to nl80211\n");
+ atenl_err("Failed to connect to nl80211\n");
return 2;
}
@@ -1075,7 +1208,7 @@
int i;
if (unl_genl_init(&nl_priv.unl, "nl80211") < 0) {
- fprintf(stderr, "Failed to connect to nl80211\n");
+ atenl_err("Failed to connect to nl80211\n");
return 2;
}
@@ -1120,7 +1253,7 @@
void *ptr;
if (unl_genl_init(&nl_priv.unl, "nl80211") < 0) {
- fprintf(stderr, "Failed to connect to nl80211\n");
+ atenl_err("Failed to connect to nl80211\n");
return 2;
}
@@ -1150,7 +1283,7 @@
void *ptr;
if (unl_genl_init(&nl_priv.unl, "nl80211") < 0) {
- fprintf(stderr, "Failed to connect to nl80211\n");
+ atenl_err("Failed to connect to nl80211\n");
return 2;
}
diff --git a/feed/atenl/src/nl.h b/feed/atenl/src/nl.h
index 2a0685d..0f21578 100644
--- a/feed/atenl/src/nl.h
+++ b/feed/atenl/src/nl.h
@@ -78,25 +78,23 @@
MT76_TM_ATTR_DRV_DATA,
MT76_TM_ATTR_MAC_ADDRS,
+ MT76_TM_ATTR_AID,
+ MT76_TM_ATTR_RU_ALLOC,
+ MT76_TM_ATTR_RU_IDX,
MT76_TM_ATTR_EEPROM_ACTION,
MT76_TM_ATTR_EEPROM_OFFSET,
MT76_TM_ATTR_EEPROM_VAL,
MT76_TM_ATTR_CFG,
+ MT76_TM_ATTR_TXBF_ACT,
+ MT76_TM_ATTR_TXBF_PARAM,
MT76_TM_ATTR_OFF_CH_SCAN_CH,
MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH,
MT76_TM_ATTR_OFF_CH_SCAN_BW,
MT76_TM_ATTR_OFF_CH_SCAN_PATH,
- MT76_TM_ATTR_AID,
- MT76_TM_ATTR_RU_ALLOC,
- MT76_TM_ATTR_RU_IDX,
-
- MT76_TM_ATTR_TXBF_ACT,
- MT76_TM_ATTR_TXBF_PARAM,
-
/* keep last */
NUM_MT76_TM_ATTRS,
MT76_TM_ATTR_MAX = NUM_MT76_TM_ATTRS - 1,
@@ -233,6 +231,7 @@
MT76_TM_TXBF_ACT_EBF_PROF_UPDATE,
MT76_TM_TXBF_ACT_PHASE_CAL,
MT76_TM_TXBF_ACT_PROF_UPDATE_ALL,
+ MT76_TM_TXBF_ACT_E2P_UPDATE,
/* keep last */
NUM_MT76_TM_TXBF_ACT,
diff --git a/feed/atenl/src/util.c b/feed/atenl/src/util.c
index 1b10663..b224040 100644
--- a/feed/atenl/src/util.c
+++ b/feed/atenl/src/util.c
@@ -103,3 +103,115 @@
return ret;
}
+
+int atenl_rf_read(struct atenl *an, u32 wf_sel, u32 offset, u32 *res)
+{
+ char dir[64], buf[16];
+ unsigned long val;
+ int fd, ret;
+ u32 regidx;
+
+ /* merge wf_sel and offset into regidx */
+ regidx = FIELD_PREP(GENMASK(31, 28), wf_sel) |
+ FIELD_PREP(GENMASK(27, 0), offset);
+
+ /* write regidx */
+ ret = snprintf(dir, sizeof(dir),
+ "/sys/kernel/debug/ieee80211/phy%d/mt76/regidx",
+ get_band_val(an, 0, phy_idx));
+ if (snprintf_error(sizeof(dir), ret))
+ return ret;
+
+ fd = open(dir, O_WRONLY);
+ if (fd < 0)
+ return fd;
+
+ ret = snprintf(buf, sizeof(buf), "0x%x", regidx);
+ if (snprintf_error(sizeof(buf), ret))
+ goto out;
+
+ lseek(fd, 0, SEEK_SET);
+ write(fd, buf, sizeof(buf));
+ close(fd);
+
+ /* read from rf_regval */
+ ret = snprintf(dir, sizeof(dir),
+ "/sys/kernel/debug/ieee80211/phy%d/mt76/rf_regval",
+ get_band_val(an, 0, phy_idx));
+ if (snprintf_error(sizeof(dir), ret))
+ return ret;
+
+ fd = open(dir, O_RDONLY);
+ if (fd < 0)
+ return fd;
+
+ ret = read(fd, buf, sizeof(buf) - 1);
+ if (ret < 0)
+ goto out;
+ buf[ret] = 0;
+
+ val = strtoul(buf, NULL, 16);
+ if (val > (u32) -1)
+ return -EINVAL;
+
+ *res = val;
+ ret = 0;
+out:
+ close(fd);
+
+ return ret;
+}
+
+int atenl_rf_write(struct atenl *an, u32 wf_sel, u32 offset, u32 val)
+{
+ char dir[64], buf[16];
+ int fd, ret;
+ u32 regidx;
+
+ /* merge wf_sel and offset into regidx */
+ regidx = FIELD_PREP(GENMASK(31, 28), wf_sel) |
+ FIELD_PREP(GENMASK(27, 0), offset);
+
+ /* write regidx */
+ ret = snprintf(dir, sizeof(dir),
+ "/sys/kernel/debug/ieee80211/phy%d/mt76/regidx",
+ get_band_val(an, 0, phy_idx));
+ if (snprintf_error(sizeof(dir), ret))
+ return ret;
+
+ fd = open(dir, O_WRONLY);
+ if (fd < 0)
+ return fd;
+
+ ret = snprintf(buf, sizeof(buf), "0x%x", regidx);
+ if (snprintf_error(sizeof(buf), ret))
+ goto out;
+
+ lseek(fd, 0, SEEK_SET);
+ write(fd, buf, sizeof(buf));
+ close(fd);
+
+ /* write value into rf_val */
+ ret = snprintf(dir, sizeof(dir),
+ "/sys/kernel/debug/ieee80211/phy%d/mt76/rf_regval",
+ get_band_val(an, 0, phy_idx));
+ if (snprintf_error(sizeof(dir), ret))
+ return ret;
+
+ fd = open(dir, O_WRONLY);
+ if (fd < 0)
+ return fd;
+
+ ret = snprintf(buf, sizeof(buf), "0x%x", val);
+ if (snprintf_error(sizeof(buf), ret))
+ goto out;
+ buf[ret] = 0;
+
+ lseek(fd, 0, SEEK_SET);
+ write(fd, buf, sizeof(buf));
+ ret = 0;
+out:
+ close(fd);
+
+ return ret;
+}
diff --git a/feed/atenl/src/util.h b/feed/atenl/src/util.h
index a02b956..45c97b5 100644
--- a/feed/atenl/src/util.h
+++ b/feed/atenl/src/util.h
@@ -43,6 +43,10 @@
({ \
(typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
})
+#define FIELD_PREP(_mask, _val) \
+ ({ \
+ ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \
+ })
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
@@ -78,6 +82,24 @@
return 0x01 & addr[0];
}
+static inline bool is_unicast_ether_addr(const u8 *addr)
+{
+ return !is_multicast_ether_addr(addr);
+}
+
+static inline bool is_zero_ether_addr(const u8 *addr)
+{
+ return (*(const u16 *)(addr + 0) |
+ *(const u16 *)(addr + 2) |
+ *(const u16 *)(addr + 4)) == 0;
+}
+
+static inline bool use_default_addr(const u8 *addr)
+{
+ return !is_unicast_ether_addr(addr) ||
+ is_zero_ether_addr(addr);
+}
+
static inline void eth_broadcast_addr(u8 *addr)
{
memset(addr, 0xff, ETH_ALEN);