blob: 754008700dbae4571d207dc7fd322525cb7ab76c [file] [log] [blame]
From 65574c009356434eb5154104a8f65c944446839b Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Wed, 15 May 2024 17:47:33 +0800
Subject: [PATCH 122/193] mtk: mt76: mt7996: do software link addr translation
for EAPOL
Previously, we do HW link address translation for EAPOL addr1 and addr2,
but SW link address translation for EAPOL addr3 due to incompatibility
between HW converting rules and 802.11 EAPOL frames.
This patch adds support for doing pure SW link address translation for
EAPOL, to get rid of ambiguity and could also help on debugging EAPOL
timeout issues.
Note that dma_sync_single_for_cpu/dma_sync_single_for_device is
necessary to sync the changes of address to DMA.
Assign EAPOL's SA/DA to MLD address.
Change-Id: Ibb63beb37f80075da8c0e1535fde74f9710f92f5
Change-Id: I307146d0f88ecca0f0ea592b9157b6a7e8009fbb
Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
mt7996/mac.c | 46 +++++++++++++++++++++++++++++++---------------
1 file changed, 31 insertions(+), 15 deletions(-)
diff --git a/mt7996/mac.c b/mt7996/mac.c
index 901c70e..02045b8 100644
--- a/mt7996/mac.c
+++ b/mt7996/mac.c
@@ -843,7 +843,8 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
txwi[5] = cpu_to_le32(val);
val = MT_TXD6_DAS;
- if ((q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0))
+ if ((q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0) ||
+ unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE)))
val |= MT_TXD6_DIS_MAT;
if (is_mt7996(&dev->mt76))
@@ -951,23 +952,38 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
pid, qid, 0);
- /* translate addr3 of EAPOL by driver */
+ /* Since the rules of HW MLD address translation are not fully compatible
+ * with 802.11 EAPOL frame, we do the translation by software
+ */
if (unlikely(tx_info->skb->protocol == cpu_to_be16(ETH_P_PAE)) && sta->mlo) {
- if (ether_addr_equal(vif->addr, hdr->addr3)) {
- struct ieee80211_bss_conf *conf;
-
- conf = rcu_dereference(vif->link_conf[wcid->link_id]);
- if (unlikely(!conf))
- return -ENOLINK;
-
- memcpy(hdr->addr3, conf->addr, ETH_ALEN);
- } else if (ether_addr_equal(sta->addr, hdr->addr3)) {
- struct ieee80211_link_sta *link_sta;
-
- link_sta = rcu_dereference(sta->link[wcid->link_id]);
- memcpy(hdr->addr3, link_sta->addr, ETH_ALEN);
+ struct ieee80211_bss_conf *conf;
+ struct ieee80211_link_sta *link_sta;
+ __le16 fc = hdr->frame_control;
+
+ conf = rcu_dereference(vif->link_conf[wcid->link_id]);
+ link_sta = rcu_dereference(sta->link[wcid->link_id]);
+ if (!conf || !link_sta)
+ return -ENOLINK;
+
+ dma_sync_single_for_cpu(mdev->dma_dev, tx_info->buf[1].addr,
+ tx_info->buf[1].len, DMA_TO_DEVICE);
+
+ memcpy(hdr->addr1, link_sta->addr, ETH_ALEN);
+ memcpy(hdr->addr2, conf->addr, ETH_ALEN);
+
+ /* EAPOL's SA/DA need to be MLD address in MLO */
+ if (ieee80211_has_a4(fc)) {
+ memcpy(hdr->addr3, sta->addr, ETH_ALEN);
+ memcpy(hdr->addr4, vif->addr, ETH_ALEN);
+ } else if (ieee80211_has_tods(fc)) {
+ memcpy(hdr->addr3, sta->addr, ETH_ALEN);
+ } else if (ieee80211_has_fromds(fc)) {
+ memcpy(hdr->addr3, vif->addr, ETH_ALEN);
}
+ dma_sync_single_for_device(mdev->dma_dev, tx_info->buf[1].addr,
+ tx_info->buf[1].len, DMA_TO_DEVICE);
+
pr_info("EAPOL: a1=%pM, a2=%pM, a3=%pM\n", hdr->addr1, hdr->addr2, hdr->addr3);
}
--
2.45.2