| From a20311a499edde8f5b8e6b4bced55bd5e0f25884 Mon Sep 17 00:00:00 2001 |
| From: mtk23510 <rudra.shahi@mediatek.com> |
| Date: Wed, 26 Apr 2023 20:08:10 +0800 |
| Subject: [PATCH 46/98] 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 762ac29..42eb64c 100644 |
| --- a/mt76_connac_mcu.h |
| +++ b/mt76_connac_mcu.h |
| @@ -418,6 +418,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; |
| @@ -770,6 +778,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) |
| |
| @@ -800,6 +809,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 |
| @@ -1093,6 +1103,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 { |
| @@ -1319,6 +1336,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, |
| @@ -1779,6 +1797,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 7d1bd42..0ea006c 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 695d5f0..1a1c732 100644 |
| --- a/mt7996/mcu.c |
| +++ b/mt7996/mcu.c |
| @@ -2118,7 +2118,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) |
| @@ -2139,43 +2138,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; |
| } |
| @@ -2184,7 +2162,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) |
| { |
| @@ -2197,13 +2174,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 c5c0a44..7808c35 100644 |
| --- a/mt7996/mcu.h |
| +++ b/mt7996/mcu.h |
| @@ -310,6 +310,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 80a10bf..9f99d13 100644 |
| --- a/mt7996/mt7996.h |
| +++ b/mt7996/mt7996.h |
| @@ -712,9 +712,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.18.0 |
| |