mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
wifi: mt76: mt7996: fix MLO set key and group key issues
This patch fixes the following key issues:
- Pass correct link BSS to mt7996_mcu_add_key(), and use HW beacon
protection mode for mt7990 chipset
- Do not do group key deletion for GTK and IGTK due to FW design, the
delete key command will delete all group keys of a link BSS
- For deleting BIGTK, FW adds a new flow, but the "sec->add" field
should be filled with "SET_KEY". Note that if BIGTK is not deleted, it
will cause beacon decryption issue when switching from an AP interface
to a station interface
Fixes: 0c45d52276 ("wifi: mt76: mt7996: fix setting beacon protection keys")
Co-developed-by: Allen Ye <allen.ye@mediatek.com>
Signed-off-by: Allen Ye <allen.ye@mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Link: https://patch.msgid.link/20251106064203.1000505-10-shayne.chen@mediatek.com
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
committed by
Felix Fietkau
parent
4fb3b4e7d1
commit
e11be918d9
@@ -795,6 +795,7 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
|
||||
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
__le16 fc = hdr->frame_control, sc = hdr->seq_ctrl;
|
||||
u16 seqno = le16_to_cpu(sc);
|
||||
bool hw_bigtk = false;
|
||||
u8 fc_type, fc_stype;
|
||||
u32 val;
|
||||
|
||||
@@ -820,7 +821,11 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
|
||||
info->flags & IEEE80211_TX_CTL_USE_MINRATE)
|
||||
val |= MT_TXD1_FIXED_RATE;
|
||||
|
||||
if (key && multicast && ieee80211_is_robust_mgmt_frame(skb)) {
|
||||
if (is_mt7990(&dev->mt76) && ieee80211_is_beacon(fc) &&
|
||||
(wcid->hw_key_idx2 == 6 || wcid->hw_key_idx2 == 7))
|
||||
hw_bigtk = true;
|
||||
|
||||
if ((key && multicast && ieee80211_is_robust_mgmt_frame(skb)) || hw_bigtk) {
|
||||
val |= MT_TXD1_BIP;
|
||||
txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
|
||||
}
|
||||
|
||||
@@ -249,12 +249,13 @@ mt7996_set_hw_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
else if (idx == *wcid_keyidx)
|
||||
*wcid_keyidx = -1;
|
||||
|
||||
if (cmd != SET_KEY && sta)
|
||||
/* only do remove key for BIGTK */
|
||||
if (cmd != SET_KEY && !is_bigtk)
|
||||
return 0;
|
||||
|
||||
mt76_wcid_key_setup(&dev->mt76, &msta_link->wcid, key);
|
||||
|
||||
err = mt7996_mcu_add_key(&dev->mt76, vif, key,
|
||||
err = mt7996_mcu_add_key(&dev->mt76, link, key,
|
||||
MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
|
||||
&msta_link->wcid, cmd);
|
||||
|
||||
|
||||
@@ -2530,7 +2530,7 @@ int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
|
||||
}
|
||||
|
||||
static int
|
||||
mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
|
||||
mt7996_mcu_sta_key_tlv(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_key_conf *key,
|
||||
enum set_key_cmd cmd)
|
||||
@@ -2542,7 +2542,10 @@ mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_KEY_V2, sizeof(*sec));
|
||||
sec = (struct sta_rec_sec_uni *)tlv;
|
||||
sec->add = 0;
|
||||
/* due to connac3 FW design, we only do remove key for BIGTK; even for
|
||||
* removal, the field should be filled with SET_KEY
|
||||
*/
|
||||
sec->add = SET_KEY;
|
||||
sec->n_cipher = 1;
|
||||
sec_key = &sec->key[0];
|
||||
sec_key->wlan_idx = cpu_to_le16(wcid->idx);
|
||||
@@ -2582,29 +2585,33 @@ mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||
sec_key->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_256;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
|
||||
if (!is_mt7990(dev))
|
||||
return -EOPNOTSUPP;
|
||||
sec_key->cipher_id = MCU_CIPHER_BCN_PROT_CMAC_256;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
sec_key->bcn_mode = BP_SW_MODE;
|
||||
sec_key->bcn_mode = is_mt7990(dev) ? BP_HW_MODE : BP_SW_MODE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
int mt7996_mcu_add_key(struct mt76_dev *dev, struct mt7996_vif_link *link,
|
||||
struct ieee80211_key_conf *key, int mcu_cmd,
|
||||
struct mt76_wcid *wcid, enum set_key_cmd cmd)
|
||||
{
|
||||
struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
skb = __mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid,
|
||||
MT7996_STA_UPDATE_MAX_SIZE);
|
||||
skb = __mt76_connac_mcu_alloc_sta_req(dev, (struct mt76_vif_link *)link,
|
||||
wcid, MT7996_STA_UPDATE_MAX_SIZE);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
ret = mt7996_mcu_sta_key_tlv(wcid, skb, key, cmd);
|
||||
ret = mt7996_mcu_sta_key_tlv(dev, wcid, skb, key, cmd);
|
||||
if (ret) {
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
@@ -2724,12 +2731,18 @@ mt7996_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb,
|
||||
static void
|
||||
mt7996_mcu_beacon_cont(struct mt7996_dev *dev,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct mt7996_vif_link *link,
|
||||
struct sk_buff *rskb, struct sk_buff *skb,
|
||||
struct bss_bcn_content_tlv *bcn,
|
||||
struct ieee80211_mutable_offsets *offs)
|
||||
{
|
||||
struct mt76_wcid *wcid = &dev->mt76.global_wcid;
|
||||
u8 *buf;
|
||||
u8 *buf, keyidx = link->msta_link.wcid.hw_key_idx2;
|
||||
struct mt76_wcid *wcid;
|
||||
|
||||
if (is_mt7990(&dev->mt76) && (keyidx == 6 || keyidx == 7))
|
||||
wcid = &link->msta_link.wcid;
|
||||
else
|
||||
wcid = &dev->mt76.global_wcid;
|
||||
|
||||
bcn->pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
|
||||
bcn->tim_ie_pos = cpu_to_le16(offs->tim_offset);
|
||||
@@ -2804,7 +2817,7 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, mlink->band_idx);
|
||||
|
||||
mt7996_mcu_beacon_cont(dev, link_conf, rskb, skb, bcn, &offs);
|
||||
mt7996_mcu_beacon_cont(dev, link_conf, link, rskb, skb, bcn, &offs);
|
||||
if (link_conf->bssid_indicator)
|
||||
mt7996_mcu_beacon_mbss(rskb, skb, bcn, &offs);
|
||||
mt7996_mcu_beacon_cntdwn(rskb, skb, &offs, link_conf->csa_active);
|
||||
|
||||
@@ -849,7 +849,7 @@ void mt7996_update_channel(struct mt76_phy *mphy);
|
||||
int mt7996_init_debugfs(struct mt7996_dev *dev);
|
||||
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,
|
||||
int mt7996_mcu_add_key(struct mt76_dev *dev, struct mt7996_vif_link *link,
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user