mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 18:09:56 +00:00
wifi: mt76: connac: add beacon protection support for mt7996
[ Upstream commiteb80e02b2c] 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> Stable-dep-of:47916693ec("wifi: mt76: mt7925: fix WoW failed in encrypted mode") Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
@@ -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
|
||||||
@@ -1091,6 +1101,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:
|
||||||
|
|||||||
@@ -342,6 +342,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:
|
||||||
@@ -365,8 +367,12 @@ 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)
|
||||||
|
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);
|
&msta->wcid, cmd);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&dev->mt76.mutex);
|
mutex_unlock(&dev->mt76.mutex);
|
||||||
|
|||||||
@@ -2058,7 +2058,6 @@ out:
|
|||||||
|
|
||||||
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)
|
||||||
@@ -2079,27 +2078,13 @@ 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->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->wlan_idx = cpu_to_le16(wcid->idx);
|
||||||
|
sec_key->mgmt_prot = 0;
|
||||||
sec_key->cipher_id = cipher;
|
sec_key->cipher_id = cipher;
|
||||||
|
sec_key->cipher_len = sizeof(*sec_key);
|
||||||
sec_key->key_id = key->keyidx;
|
sec_key->key_id = key->keyidx;
|
||||||
sec_key->key_len = key->keylen;
|
sec_key->key_len = key->keylen;
|
||||||
|
sec_key->need_resp = 0;
|
||||||
memcpy(sec_key->key, key->key, key->keylen);
|
memcpy(sec_key->key, key->key, key->keylen);
|
||||||
|
|
||||||
if (cipher == MCU_CIPHER_TKIP) {
|
if (cipher == MCU_CIPHER_TKIP) {
|
||||||
@@ -2108,14 +2093,7 @@ mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
|
|||||||
memcpy(sec_key->key + 24, key->key + 16, 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;
|
||||||
}
|
}
|
||||||
@@ -2124,7 +2102,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)
|
||||||
{
|
{
|
||||||
@@ -2137,13 +2114,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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -250,6 +250,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;
|
||||||
|
|||||||
@@ -485,9 +485,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);
|
||||||
|
|||||||
Reference in New Issue
Block a user