wifi: mt76: mt7925: fix WoW failed in encrypted mode
When in suspend mode, WoW (Wake-on-WLAN) fails to wake the system remotely
due to incorrect encryption mode settings. For the new mt7925 chipset, the
old STA_REC_KEY_V2 command will send incorrect parameters to the firmware.
Therefore, STA_REC_KEY_V3 has been introduced as a replacement for it.
Fixes: c948b5da6b ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips")
Signed-off-by: Ming Yen Hsieh <mingyen.hsieh@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
committed by
Felix Fietkau
parent
6864bc734a
commit
47916693ec
@@ -808,6 +808,7 @@ enum {
|
||||
STA_REC_MLD = 0x20,
|
||||
STA_REC_EHT = 0x22,
|
||||
STA_REC_PN_INFO = 0x26,
|
||||
STA_REC_KEY_V3 = 0x27,
|
||||
STA_REC_HDRT = 0x28,
|
||||
STA_REC_HDR_TRANS = 0x2B,
|
||||
STA_REC_MAX_NUM
|
||||
|
||||
@@ -359,6 +359,7 @@ mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
mvif->sta.wcid.phy_idx = mvif->mt76.band_idx;
|
||||
mvif->sta.wcid.hw_key_idx = -1;
|
||||
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
|
||||
mvif->sta.vif = mvif;
|
||||
mt76_wcid_init(&mvif->sta.wcid);
|
||||
|
||||
mt7925_mac_wtbl_update(dev, idx,
|
||||
@@ -526,7 +527,7 @@ static int mt7925_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
if (cmd == SET_KEY && !mvif->mt76.cipher) {
|
||||
struct mt792x_phy *phy = mt792x_hw_phy(hw);
|
||||
|
||||
mvif->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher);
|
||||
mvif->mt76.cipher = mt7925_mcu_get_cipher(key->cipher);
|
||||
mt7925_mcu_add_bss_info(phy, mvif->mt76.ctx, vif, sta, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -921,61 +921,67 @@ mt7925_mcu_sta_key_tlv(struct mt76_wcid *wcid,
|
||||
struct ieee80211_key_conf *key,
|
||||
enum set_key_cmd cmd)
|
||||
{
|
||||
struct mt792x_sta *msta = container_of(wcid, struct mt792x_sta, wcid);
|
||||
struct sta_rec_sec_uni *sec;
|
||||
struct mt792x_vif *mvif = msta->vif;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_vif *vif;
|
||||
struct tlv *tlv;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_KEY_V2, sizeof(*sec));
|
||||
sta = msta == &mvif->sta ?
|
||||
NULL :
|
||||
container_of((void *)msta, struct ieee80211_sta, drv_priv);
|
||||
vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_KEY_V3, sizeof(*sec));
|
||||
sec = (struct sta_rec_sec_uni *)tlv;
|
||||
sec->add = cmd;
|
||||
sec->bss_idx = mvif->mt76.idx;
|
||||
sec->is_authenticator = 0;
|
||||
sec->mgmt_prot = 0;
|
||||
sec->wlan_idx = (u8)wcid->idx;
|
||||
|
||||
if (sta) {
|
||||
sec->tx_key = 1;
|
||||
sec->key_type = 1;
|
||||
memcpy(sec->peer_addr, sta->addr, ETH_ALEN);
|
||||
} else {
|
||||
memcpy(sec->peer_addr, vif->bss_conf.bssid, ETH_ALEN);
|
||||
}
|
||||
|
||||
if (cmd == SET_KEY) {
|
||||
struct sec_key_uni *sec_key;
|
||||
u8 cipher;
|
||||
|
||||
cipher = mt76_connac_mcu_get_cipher(key->cipher);
|
||||
if (cipher == MCU_CIPHER_NONE)
|
||||
sec->add = 1;
|
||||
cipher = mt7925_mcu_get_cipher(key->cipher);
|
||||
if (cipher == CONNAC3_CIPHER_NONE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
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;
|
||||
if (cipher == CONNAC3_CIPHER_BIP_CMAC_128) {
|
||||
sec->cipher_id = CONNAC3_CIPHER_BIP_CMAC_128;
|
||||
sec->key_id = sta_key_conf->keyidx;
|
||||
sec->key_len = 32;
|
||||
memcpy(sec->key, sta_key_conf->key, 16);
|
||||
memcpy(sec->key + 16, key->key, 16);
|
||||
} 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);
|
||||
sec->cipher_id = cipher;
|
||||
sec->key_id = key->keyidx;
|
||||
sec->key_len = key->keylen;
|
||||
memcpy(sec->key, key->key, key->keylen);
|
||||
|
||||
if (cipher == MCU_CIPHER_TKIP) {
|
||||
if (cipher == CONNAC3_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);
|
||||
memcpy(sec->key + 16, key->key + 24, 8);
|
||||
memcpy(sec->key + 24, key->key + 16, 8);
|
||||
}
|
||||
|
||||
/* store key_conf for BIP batch update */
|
||||
if (cipher == MCU_CIPHER_AES_CCMP) {
|
||||
if (cipher == CONNAC3_CIPHER_AES_CCMP) {
|
||||
memcpy(sta_key_conf->key, key->key, key->keylen);
|
||||
sta_key_conf->keyidx = key->keyidx;
|
||||
}
|
||||
|
||||
sec->n_cipher = 1;
|
||||
}
|
||||
} else {
|
||||
sec->n_cipher = 0;
|
||||
sec->add = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2122,21 +2128,21 @@ mt7925_mcu_bss_sec_tlv(struct sk_buff *skb, struct ieee80211_vif *vif)
|
||||
sec = (struct bss_sec_tlv *)tlv;
|
||||
|
||||
switch (mvif->cipher) {
|
||||
case MCU_CIPHER_GCMP_256:
|
||||
case MCU_CIPHER_GCMP:
|
||||
case CONNAC3_CIPHER_GCMP_256:
|
||||
case CONNAC3_CIPHER_GCMP:
|
||||
sec->mode = MODE_WPA3_SAE;
|
||||
sec->status = 8;
|
||||
break;
|
||||
case MCU_CIPHER_AES_CCMP:
|
||||
case CONNAC3_CIPHER_AES_CCMP:
|
||||
sec->mode = MODE_WPA2_PSK;
|
||||
sec->status = 6;
|
||||
break;
|
||||
case MCU_CIPHER_TKIP:
|
||||
case CONNAC3_CIPHER_TKIP:
|
||||
sec->mode = MODE_WPA2_PSK;
|
||||
sec->status = 4;
|
||||
break;
|
||||
case MCU_CIPHER_WEP104:
|
||||
case MCU_CIPHER_WEP40:
|
||||
case CONNAC3_CIPHER_WEP104:
|
||||
case CONNAC3_CIPHER_WEP40:
|
||||
sec->mode = MODE_SHARED;
|
||||
sec->status = 0;
|
||||
break;
|
||||
|
||||
@@ -159,6 +159,20 @@ enum {
|
||||
UNI_EVENT_SCAN_DONE_NLO = 3,
|
||||
};
|
||||
|
||||
enum connac3_mcu_cipher_type {
|
||||
CONNAC3_CIPHER_NONE = 0,
|
||||
CONNAC3_CIPHER_WEP40 = 1,
|
||||
CONNAC3_CIPHER_TKIP = 2,
|
||||
CONNAC3_CIPHER_AES_CCMP = 4,
|
||||
CONNAC3_CIPHER_WEP104 = 5,
|
||||
CONNAC3_CIPHER_BIP_CMAC_128 = 6,
|
||||
CONNAC3_CIPHER_WEP128 = 7,
|
||||
CONNAC3_CIPHER_WAPI = 8,
|
||||
CONNAC3_CIPHER_CCMP_256 = 10,
|
||||
CONNAC3_CIPHER_GCMP = 11,
|
||||
CONNAC3_CIPHER_GCMP_256 = 12,
|
||||
};
|
||||
|
||||
struct mt7925_mcu_scan_chinfo_event {
|
||||
u8 nr_chan;
|
||||
u8 alpha2[3];
|
||||
@@ -383,25 +397,22 @@ struct sta_rec_eht {
|
||||
u8 _rsv2[3];
|
||||
} __packed;
|
||||
|
||||
struct sec_key_uni {
|
||||
__le16 wlan_idx;
|
||||
u8 mgmt_prot;
|
||||
u8 cipher_id;
|
||||
u8 cipher_len;
|
||||
u8 key_id;
|
||||
u8 key_len;
|
||||
u8 need_resp;
|
||||
u8 key[32];
|
||||
} __packed;
|
||||
|
||||
struct sta_rec_sec_uni {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 add;
|
||||
u8 n_cipher;
|
||||
u8 rsv[2];
|
||||
|
||||
struct sec_key_uni key[2];
|
||||
u8 tx_key;
|
||||
u8 key_type;
|
||||
u8 is_authenticator;
|
||||
u8 peer_addr[6];
|
||||
u8 bss_idx;
|
||||
u8 cipher_id;
|
||||
u8 key_id;
|
||||
u8 key_len;
|
||||
u8 wlan_idx;
|
||||
u8 mgmt_prot;
|
||||
u8 key[32];
|
||||
u8 key_rsc[16];
|
||||
} __packed;
|
||||
|
||||
struct sta_rec_hdr_trans {
|
||||
@@ -441,7 +452,7 @@ struct sta_rec_mld {
|
||||
sizeof(struct sta_rec_bfee) + \
|
||||
sizeof(struct sta_rec_phy) + \
|
||||
sizeof(struct sta_rec_ra) + \
|
||||
sizeof(struct sta_rec_sec) + \
|
||||
sizeof(struct sta_rec_sec_uni) + \
|
||||
sizeof(struct sta_rec_ra_fixed) + \
|
||||
sizeof(struct sta_rec_he_6g_capa) + \
|
||||
sizeof(struct sta_rec_eht) + \
|
||||
@@ -510,6 +521,33 @@ struct mt7925_wow_pattern_tlv {
|
||||
u8 rsv[4];
|
||||
} __packed;
|
||||
|
||||
static inline enum connac3_mcu_cipher_type
|
||||
mt7925_mcu_get_cipher(int cipher)
|
||||
{
|
||||
switch (cipher) {
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
return CONNAC3_CIPHER_WEP40;
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
return CONNAC3_CIPHER_WEP104;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
return CONNAC3_CIPHER_TKIP;
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
return CONNAC3_CIPHER_BIP_CMAC_128;
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
return CONNAC3_CIPHER_AES_CCMP;
|
||||
case WLAN_CIPHER_SUITE_CCMP_256:
|
||||
return CONNAC3_CIPHER_CCMP_256;
|
||||
case WLAN_CIPHER_SUITE_GCMP:
|
||||
return CONNAC3_CIPHER_GCMP;
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
return CONNAC3_CIPHER_GCMP_256;
|
||||
case WLAN_CIPHER_SUITE_SMS4:
|
||||
return CONNAC3_CIPHER_WAPI;
|
||||
default:
|
||||
return CONNAC3_CIPHER_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
int mt7925_mcu_set_dbdc(struct mt76_phy *phy);
|
||||
int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_scan_request *scan_req);
|
||||
|
||||
Reference in New Issue
Block a user