blob: 9c6e4cb7ee551c2517d03bcc03296f8d351d7634 [file] [log] [blame]
From fe8bcf023b97cb281774611d95745bd2b1c14d9c Mon Sep 17 00:00:00 2001
From: mtk23510 <rudra.shahi@mediatek.com>
Date: Wed, 26 Apr 2023 20:08:10 +0800
Subject: [PATCH 1013/1024] wifi: mt76: mt7996: Beacon protection feature added
Signed-off-by: mtk23510 <rudra.shahi@mediatek.com>
Signed-off-by: Allen.Ye <allen.ye@mediatek.com>
---
mt76_connac_mcu.h | 24 ++++++++
mt7996/main.c | 14 +++--
mt7996/mcu.c | 138 +++++++++++++++++++++++++++++++++-------------
mt7996/mcu.h | 17 ++++++
mt7996/mt7996.h | 3 +-
5 files changed, 153 insertions(+), 43 deletions(-)
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
index 196b4921d..21cae4bf4 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
@@ -416,6 +416,14 @@ struct sta_rec_he_6g_capa {
u8 rsv[2];
} __packed;
+struct sta_rec_pn_info {
+ __le16 tag;
+ __le16 len;
+ u8 pn[6];
+ u8 tsc_type;
+ u8 rsv;
+} __packed;
+
struct sec_key {
u8 cipher_id;
u8 cipher_len;
@@ -768,6 +776,7 @@ struct wtbl_raw {
sizeof(struct sta_rec_sec) + \
sizeof(struct sta_rec_ra_fixed) + \
sizeof(struct sta_rec_he_6g_capa) + \
+ sizeof(struct sta_rec_pn_info) + \
sizeof(struct tlv) + \
MT76_CONNAC_WTBL_UPDATE_MAX_SIZE)
@@ -798,6 +807,7 @@ enum {
STA_REC_HE_V2 = 0x19,
STA_REC_MLD = 0x20,
STA_REC_EHT = 0x22,
+ STA_REC_PN_INFO = 0x26,
STA_REC_HDRT = 0x28,
STA_REC_HDR_TRANS = 0x2B,
STA_REC_MAX_NUM
@@ -1091,6 +1101,13 @@ enum mcu_cipher_type {
MCU_CIPHER_GCMP_256,
MCU_CIPHER_WAPI,
MCU_CIPHER_BIP_CMAC_128,
+ MCU_CIPHER_BIP_CMAC_256,
+ MCU_CIPHER_BCN_PROT_CMAC_128,
+ MCU_CIPHER_BCN_PROT_CMAC_256,
+ MCU_CIPHER_BCN_PROT_GMAC_128,
+ MCU_CIPHER_BCN_PROT_GMAC_256,
+ MCU_CIPHER_BIP_GMAC_128,
+ MCU_CIPHER_BIP_GMAC_256,
};
enum {
@@ -1316,6 +1333,7 @@ enum {
UNI_BSS_INFO_RATE = 11,
UNI_BSS_INFO_QBSS = 15,
UNI_BSS_INFO_SEC = 16,
+ UNI_BSS_INFO_BCN_PROT = 17,
UNI_BSS_INFO_TXCMD = 18,
UNI_BSS_INFO_UAPSD = 19,
UNI_BSS_INFO_PS = 21,
@@ -1776,6 +1794,12 @@ mt76_connac_mcu_get_cipher(int cipher)
return MCU_CIPHER_GCMP;
case WLAN_CIPHER_SUITE_GCMP_256:
return MCU_CIPHER_GCMP_256;
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+ return MCU_CIPHER_BIP_GMAC_128;
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+ return MCU_CIPHER_BIP_GMAC_256;
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+ return MCU_CIPHER_BIP_CMAC_256;
case WLAN_CIPHER_SUITE_SMS4:
return MCU_CIPHER_WAPI;
default:
diff --git a/mt7996/main.c b/mt7996/main.c
index f2e2de850..d8c8a5fac 100644
--- a/mt7996/main.c
+++ b/mt7996/main.c
@@ -368,8 +368,10 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
/* fall back to sw encryption for unsupported ciphers */
switch (key->cipher) {
case WLAN_CIPHER_SUITE_AES_CMAC:
- wcid_keyidx = &wcid->hw_key_idx2;
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+ wcid_keyidx = &wcid->hw_key_idx2;
break;
case WLAN_CIPHER_SUITE_TKIP:
case WLAN_CIPHER_SUITE_CCMP:
@@ -400,9 +402,13 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
}
mt76_wcid_key_setup(&dev->mt76, wcid, key);
- err = mt7996_mcu_add_key(&dev->mt76, vif, &msta->bip,
- key, MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
- &msta->wcid, cmd);
+
+ if (key->keyidx == 6 || key->keyidx == 7)
+ err = mt7996_mcu_bcn_prot_enable(dev, vif, key);
+ else
+ err = mt7996_mcu_add_key(&dev->mt76, vif, key,
+ MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
+ &msta->wcid, cmd);
out:
mutex_unlock(&dev->mt76.mutex);
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
index 802b21685..22417e410 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
@@ -2155,7 +2155,6 @@ out:
static int
mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
- struct mt76_connac_sta_key_conf *sta_key_conf,
struct sk_buff *skb,
struct ieee80211_key_conf *key,
enum set_key_cmd cmd)
@@ -2176,43 +2175,22 @@ mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
return -EOPNOTSUPP;
sec_key = &sec->key[0];
+ sec_key->wlan_idx = cpu_to_le16(wcid->idx);
+ sec_key->mgmt_prot = 0;
+ sec_key->cipher_id = cipher;
sec_key->cipher_len = sizeof(*sec_key);
-
- if (cipher == MCU_CIPHER_BIP_CMAC_128) {
- sec_key->wlan_idx = cpu_to_le16(wcid->idx);
- sec_key->cipher_id = MCU_CIPHER_AES_CCMP;
- sec_key->key_id = sta_key_conf->keyidx;
- sec_key->key_len = 16;
- memcpy(sec_key->key, sta_key_conf->key, 16);
-
- sec_key = &sec->key[1];
- sec_key->wlan_idx = cpu_to_le16(wcid->idx);
- sec_key->cipher_id = MCU_CIPHER_BIP_CMAC_128;
- sec_key->cipher_len = sizeof(*sec_key);
- sec_key->key_len = 16;
- memcpy(sec_key->key, key->key, 16);
- sec->n_cipher = 2;
- } else {
- sec_key->wlan_idx = cpu_to_le16(wcid->idx);
- sec_key->cipher_id = cipher;
- sec_key->key_id = key->keyidx;
- sec_key->key_len = key->keylen;
- memcpy(sec_key->key, key->key, key->keylen);
-
- if (cipher == MCU_CIPHER_TKIP) {
- /* Rx/Tx MIC keys are swapped */
- memcpy(sec_key->key + 16, key->key + 24, 8);
- memcpy(sec_key->key + 24, key->key + 16, 8);
- }
-
- /* store key_conf for BIP batch update */
- if (cipher == MCU_CIPHER_AES_CCMP) {
- memcpy(sta_key_conf->key, key->key, key->keylen);
- sta_key_conf->keyidx = key->keyidx;
- }
-
- sec->n_cipher = 1;
+ sec_key->key_id = key->keyidx;
+ sec_key->key_len = key->keylen;
+ sec_key->need_resp = 0;
+ memcpy(sec_key->key, key->key, key->keylen);
+
+ if (cipher == MCU_CIPHER_TKIP) {
+ /* Rx/Tx MIC keys are swapped */
+ memcpy(sec_key->key + 16, key->key + 24, 8);
+ memcpy(sec_key->key + 24, key->key + 16, 8);
}
+
+ sec->n_cipher = 1;
} else {
sec->n_cipher = 0;
}
@@ -2221,7 +2199,6 @@ mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
}
int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
- struct mt76_connac_sta_key_conf *sta_key_conf,
struct ieee80211_key_conf *key, int mcu_cmd,
struct mt76_wcid *wcid, enum set_key_cmd cmd)
{
@@ -2234,13 +2211,98 @@ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
if (IS_ERR(skb))
return PTR_ERR(skb);
- ret = mt7996_mcu_sta_key_tlv(wcid, sta_key_conf, skb, key, cmd);
+ ret = mt7996_mcu_sta_key_tlv(wcid, skb, key, cmd);
if (ret)
return ret;
return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
}
+static int mt7996_mcu_get_pn(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ u8 *pn)
+{
+#define TSC_TYPE_BIGTK_PN 2
+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ struct sta_rec_pn_info *pn_info;
+ struct sk_buff *skb, *rskb;
+ struct tlv *tlv;
+ int ret;
+
+ skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, &mvif->sta.wcid);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_PN_INFO, sizeof(*pn_info));
+ pn_info = (struct sta_rec_pn_info *)tlv;
+
+ pn_info->tsc_type = TSC_TYPE_BIGTK_PN;
+ ret = mt76_mcu_skb_send_and_get_msg(&dev->mt76, skb,
+ MCU_WM_UNI_CMD_QUERY(STA_REC_UPDATE), true, &rskb);
+ if (ret)
+ return ret;
+
+ skb_pull(rskb, 4);
+
+ pn_info = (struct sta_rec_pn_info *)rskb->data;
+ if (le16_to_cpu(pn_info->tag) == STA_REC_PN_INFO)
+ memcpy(pn, pn_info->pn, 6);
+
+ dev_kfree_skb(rskb);
+ return 0;
+}
+
+int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ struct ieee80211_key_conf *key)
+{
+ int len = sizeof(struct bss_req_hdr) + sizeof(struct mt7996_mcu_bcn_prot_tlv);
+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ int ret;
+ struct mt7996_mcu_bcn_prot_tlv *bcn_prot;
+ struct sk_buff *skb;
+ struct tlv *tlv;
+ u8 pn[6] = {0};
+
+ skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, len);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_BCN_PROT,
+ sizeof(*bcn_prot));
+
+ bcn_prot = (struct mt7996_mcu_bcn_prot_tlv *)tlv;
+
+ ret = mt7996_mcu_get_pn(dev, vif, pn);
+ if (ret) {
+ dev_kfree_skb(skb);
+ return ret;
+ }
+
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_CMAC_128;
+ break;
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+ bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_128;
+ break;
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+ bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_256;
+ break;
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+ default:
+ dev_err(dev->mt76.dev, "Not supported Bigtk Cipher\n");
+ dev_kfree_skb(skb);
+ return -EOPNOTSUPP;
+ }
+
+ pn[0]++;
+ memcpy(bcn_prot->pn, pn, 6);
+ bcn_prot->enable = BP_SW_MODE;
+ memcpy(bcn_prot->key, key->key, WLAN_MAX_KEY_LEN);
+ bcn_prot->key_id = key->keyidx;
+
+ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
+ MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
+}
int mt7996_mcu_add_dev_info(struct mt7996_phy *phy,
struct ieee80211_vif *vif, bool enable)
{
diff --git a/mt7996/mcu.h b/mt7996/mcu.h
index 1d7748771..512d8543b 100644
--- a/mt7996/mcu.h
+++ b/mt7996/mcu.h
@@ -313,6 +313,23 @@ struct bss_rate_tlv {
u8 __rsv2[9];
} __packed;
+enum {
+ BP_DISABLE,
+ BP_SW_MODE,
+ BP_HW_MODE,
+};
+
+struct mt7996_mcu_bcn_prot_tlv {
+ __le16 tag;
+ __le16 len;
+ u8 pn[6];
+ u8 enable;
+ u8 cipher_id;
+ u8 key[WLAN_MAX_KEY_LEN];
+ u8 key_id;
+ u8 __rsv[3];
+} __packed;
+
struct bss_ra_tlv {
__le16 tag;
__le16 len;
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
index 99d4659f1..b75523ff4 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
@@ -654,9 +654,10 @@ int mt7996_init_debugfs(struct mt7996_phy *phy);
void mt7996_debugfs_rx_fw_monitor(struct mt7996_dev *dev, const void *data, int len);
bool mt7996_debugfs_rx_log(struct mt7996_dev *dev, const void *data, int len);
int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
- struct mt76_connac_sta_key_conf *sta_key_conf,
struct ieee80211_key_conf *key, int mcu_cmd,
struct mt76_wcid *wcid, enum set_key_cmd cmd);
+int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ struct ieee80211_key_conf *key);
int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
--
2.39.2