blob: 13c35199f4406dd21a4cb84d8157651f2dcd522b [file] [log] [blame]
developer617abbd2024-04-23 14:50:01 +08001From 3ef17fdd49c8ded3d8aad5fea83fc1ffbf8972a0 Mon Sep 17 00:00:00 2001
2From: Shayne Chen <shayne.chen@mediatek.com>
3Date: Thu, 7 Dec 2023 16:31:56 +0800
4Subject: [PATCH 103/116] wifi: mt76: mt7996: implement mld address translation
5
6Do the MLD to link address translation for EAPOL and management frames
7in driver.
8This is a preliminary patch to add MLO support for mt7996 chipsets.
9
10Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com>
11Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
12Co-developed-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
13Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
14Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
15---
16 mt7996/mac.c | 20 ++++++++++++++++++++
17 mt7996/main.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
18 2 files changed, 66 insertions(+), 3 deletions(-)
19
20diff --git a/mt7996/mac.c b/mt7996/mac.c
21index d6d1c0798..3141fe4e4 100644
22--- a/mt7996/mac.c
23+++ b/mt7996/mac.c
24@@ -895,6 +895,26 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
25 mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
26 pid, qid, 0);
27
28+ /* translate addr3 of EAPOL by driver */
29+ if (unlikely(tx_info->skb->protocol == cpu_to_be16(ETH_P_PAE)) && sta->mlo) {
30+ if (ether_addr_equal(vif->addr, hdr->addr3)) {
31+ struct ieee80211_bss_conf *conf;
32+
33+ conf = rcu_dereference(vif->link_conf[wcid->link_id]);
34+ if (unlikely(!conf))
35+ return -ENOLINK;
36+
37+ memcpy(hdr->addr3, conf->addr, ETH_ALEN);
38+ } else if (ether_addr_equal(sta->addr, hdr->addr3)) {
39+ struct ieee80211_link_sta *link_sta;
40+
41+ link_sta = rcu_dereference(sta->link[wcid->link_id]);
42+ memcpy(hdr->addr3, link_sta->addr, ETH_ALEN);
43+ }
44+
45+ pr_info("EAPOL: a1=%pM, a2=%pM, a3=%pM\n", hdr->addr1, hdr->addr2, hdr->addr3);
46+ }
47+
48 txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
49 for (i = 0; i < nbuf; i++) {
50 u16 len;
51diff --git a/mt7996/main.c b/mt7996/main.c
52index 66972080f..97431ae34 100644
53--- a/mt7996/main.c
54+++ b/mt7996/main.c
55@@ -1308,14 +1308,56 @@ static void mt7996_tx(struct ieee80211_hw *hw,
56
57 rcu_read_lock();
58 if (mvif && msta) {
59+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
60 struct mt7996_bss_conf *mconf;
61 struct mt7996_link_sta *mlink;
62-
63 u8 link_id = u32_get_bits(info->control.flags,
64 IEEE80211_TX_CTRL_MLO_LINK);
65+ struct ieee80211_sta *sta = ieee80211_find_sta(vif, hdr->addr1);
66+
67+ if (link_id >= IEEE80211_LINK_UNSPECIFIED) {
68+ if (sta) {
69+ struct mt7996_sta *peer;
70+
71+ peer = (struct mt7996_sta *)sta->drv_priv;
72+ link_id = peer->pri_link;
73+ } else {
74+ link_id = mvif->master_link_id;
75+ }
76+ }
77
78- if (link_id >= IEEE80211_LINK_UNSPECIFIED)
79- link_id = mvif->master_link_id;
80+ /* translate mld addr to link addr */
81+ if (ieee80211_vif_is_mld(vif)) {
82+ struct ieee80211_bss_conf *conf;
83+ if (sta) {
84+ struct ieee80211_link_sta *link_sta =
85+ rcu_dereference(sta->link[link_id]);
86+
87+ if (!link_sta) {
88+ mlo_dbg(mt7996_hw_phy(mvif->hw), "request TX on invalid link_id=%u, use primary link (id=%u) instead.\n",
89+ link_id, msta->pri_link);
90+ link_id = msta->pri_link;
91+ link_sta = rcu_dereference(sta->link[link_id]);
92+
93+ if (!link_sta) {
94+ mlo_dbg(mt7996_hw_phy(mvif->hw), "primary link became invalid, give up the TX\n");
95+ goto unlock;
96+ }
97+ }
98+
99+ memcpy(hdr->addr1, link_sta->addr, ETH_ALEN);
100+ if (ether_addr_equal(sta->addr, hdr->addr3))
101+ memcpy(hdr->addr3, link_sta->addr, ETH_ALEN);
102+ }
103+
104+ conf = rcu_dereference(vif->link_conf[link_id]);
105+ if (unlikely(!conf))
106+ goto unlock;
107+
108+ memcpy(hdr->addr2, conf->addr, ETH_ALEN);
109+ if (ether_addr_equal(vif->addr, hdr->addr3))
110+ memcpy(hdr->addr3, conf->addr, ETH_ALEN);
111+ }
112
113 mconf = rcu_dereference(mvif->link[link_id]);
114 mlink = rcu_dereference(msta->link[link_id]);
115@@ -1333,6 +1375,7 @@ static void mt7996_tx(struct ieee80211_hw *hw,
116 }
117
118 mt76_tx(mphy, control->sta, wcid, skb);
119+unlock:
120 rcu_read_unlock();
121 }
122
123--
1242.39.2
125