blob: 746cedc3b49ae49cfe05cd0d7776601f3a2a76dd [file] [log] [blame]
From 17651c073f135c837ca0b8d0b3e9ab8c4beef67f 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 134/199] 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.
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 bba16975..020203ec 100644
--- a/mt7996/mac.c
+++ b/mt7996/mac.c
@@ -831,7 +831,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))
@@ -939,23 +940,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.18.0