[][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/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;
 	}