wifi: mt76: connac: add beacon protection support for mt7996

Implement beacon protection feature for mt7996 chipsets, and also do
some cleanup on the set key routine.

Co-developed-by: Rudra Shahi <rudra.shahi@mediatek.com>
Signed-off-by: Rudra Shahi <rudra.shahi@mediatek.com>
Signed-off-by: Allen Ye <allen.ye@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Allen Ye 2023-11-02 18:03:01 +08:00 committed by Felix Fietkau
parent b769f7d8d9
commit eb80e02b2c
5 changed files with 152 additions and 41 deletions

View file

@ -416,6 +416,14 @@ struct sta_rec_he_6g_capa {
u8 rsv[2]; u8 rsv[2];
} __packed; } __packed;
struct sta_rec_pn_info {
__le16 tag;
__le16 len;
u8 pn[6];
u8 tsc_type;
u8 rsv;
} __packed;
struct sec_key { struct sec_key {
u8 cipher_id; u8 cipher_id;
u8 cipher_len; u8 cipher_len;
@ -768,6 +776,7 @@ struct wtbl_raw {
sizeof(struct sta_rec_sec) + \ sizeof(struct sta_rec_sec) + \
sizeof(struct sta_rec_ra_fixed) + \ sizeof(struct sta_rec_ra_fixed) + \
sizeof(struct sta_rec_he_6g_capa) + \ sizeof(struct sta_rec_he_6g_capa) + \
sizeof(struct sta_rec_pn_info) + \
sizeof(struct tlv) + \ sizeof(struct tlv) + \
MT76_CONNAC_WTBL_UPDATE_MAX_SIZE) MT76_CONNAC_WTBL_UPDATE_MAX_SIZE)
@ -798,6 +807,7 @@ enum {
STA_REC_HE_V2 = 0x19, STA_REC_HE_V2 = 0x19,
STA_REC_MLD = 0x20, STA_REC_MLD = 0x20,
STA_REC_EHT = 0x22, STA_REC_EHT = 0x22,
STA_REC_PN_INFO = 0x26,
STA_REC_HDRT = 0x28, STA_REC_HDRT = 0x28,
STA_REC_HDR_TRANS = 0x2B, STA_REC_HDR_TRANS = 0x2B,
STA_REC_MAX_NUM STA_REC_MAX_NUM
@ -1090,6 +1100,13 @@ enum mcu_cipher_type {
MCU_CIPHER_GCMP_256, MCU_CIPHER_GCMP_256,
MCU_CIPHER_WAPI, MCU_CIPHER_WAPI,
MCU_CIPHER_BIP_CMAC_128, 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 { enum {
@ -1310,6 +1327,7 @@ enum {
UNI_BSS_INFO_RATE = 11, UNI_BSS_INFO_RATE = 11,
UNI_BSS_INFO_QBSS = 15, UNI_BSS_INFO_QBSS = 15,
UNI_BSS_INFO_SEC = 16, UNI_BSS_INFO_SEC = 16,
UNI_BSS_INFO_BCN_PROT = 17,
UNI_BSS_INFO_TXCMD = 18, UNI_BSS_INFO_TXCMD = 18,
UNI_BSS_INFO_UAPSD = 19, UNI_BSS_INFO_UAPSD = 19,
UNI_BSS_INFO_PS = 21, UNI_BSS_INFO_PS = 21,
@ -1771,6 +1789,12 @@ mt76_connac_mcu_get_cipher(int cipher)
return MCU_CIPHER_GCMP; return MCU_CIPHER_GCMP;
case WLAN_CIPHER_SUITE_GCMP_256: case WLAN_CIPHER_SUITE_GCMP_256:
return MCU_CIPHER_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: case WLAN_CIPHER_SUITE_SMS4:
return MCU_CIPHER_WAPI; return MCU_CIPHER_WAPI;
default: default:

View file

@ -350,6 +350,8 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256: case WLAN_CIPHER_SUITE_GCMP_256:
case WLAN_CIPHER_SUITE_SMS4: case WLAN_CIPHER_SUITE_SMS4:
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
break; break;
case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104: case WLAN_CIPHER_SUITE_WEP104:
@ -373,9 +375,13 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
} }
mt76_wcid_key_setup(&dev->mt76, wcid, key); 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), if (key->keyidx == 6 || key->keyidx == 7)
&msta->wcid, cmd); 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: out:
mutex_unlock(&dev->mt76.mutex); mutex_unlock(&dev->mt76.mutex);

View file

@ -2171,7 +2171,6 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
static int static int
mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid, mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
struct mt76_connac_sta_key_conf *sta_key_conf,
struct sk_buff *skb, struct sk_buff *skb,
struct ieee80211_key_conf *key, struct ieee80211_key_conf *key,
enum set_key_cmd cmd) enum set_key_cmd cmd)
@ -2192,43 +2191,22 @@ mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
return -EOPNOTSUPP; return -EOPNOTSUPP;
sec_key = &sec->key[0]; 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); sec_key->cipher_len = sizeof(*sec_key);
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_BIP_CMAC_128) { if (cipher == MCU_CIPHER_TKIP) {
sec_key->wlan_idx = cpu_to_le16(wcid->idx); /* Rx/Tx MIC keys are swapped */
sec_key->cipher_id = MCU_CIPHER_AES_CCMP; memcpy(sec_key->key + 16, key->key + 24, 8);
sec_key->key_id = sta_key_conf->keyidx; memcpy(sec_key->key + 24, key->key + 16, 8);
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->n_cipher = 1;
} else { } else {
sec->n_cipher = 0; sec->n_cipher = 0;
} }
@ -2237,7 +2215,6 @@ mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
} }
int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, 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 ieee80211_key_conf *key, int mcu_cmd,
struct mt76_wcid *wcid, enum set_key_cmd cmd) struct mt76_wcid *wcid, enum set_key_cmd cmd)
{ {
@ -2250,13 +2227,99 @@ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
if (IS_ERR(skb)) if (IS_ERR(skb))
return PTR_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) if (ret)
return ret; return ret;
return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true); 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)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt7996_mcu_bcn_prot_tlv *bcn_prot;
struct sk_buff *skb;
struct tlv *tlv;
u8 pn[6] = {};
int len = sizeof(struct bss_req_hdr) +
sizeof(struct mt7996_mcu_bcn_prot_tlv);
int ret;
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, int mt7996_mcu_add_dev_info(struct mt7996_phy *phy,
struct ieee80211_vif *vif, bool enable) struct ieee80211_vif *vif, bool enable)
{ {

View file

@ -345,6 +345,23 @@ struct bss_rate_tlv {
u8 __rsv2[9]; u8 __rsv2[9];
} __packed; } __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 { struct bss_ra_tlv {
__le16 tag; __le16 tag;
__le16 len; __le16 len;

View file

@ -584,9 +584,10 @@ int mt7996_init_debugfs(struct mt7996_phy *phy);
void mt7996_debugfs_rx_fw_monitor(struct mt7996_dev *dev, const void *data, int len); 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); 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, 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 ieee80211_key_conf *key, int mcu_cmd,
struct mt76_wcid *wcid, enum set_key_cmd 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, int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_sta *sta); struct ieee80211_sta *sta);