| From a6b712a367b0e76ac5982f846f096ab936138c16 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/223] 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 901c70e5..02045b84 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 |
| |