From 669b692247d4516e252c898c0e7366a09d84d1be Mon Sep 17 00:00:00 2001 From: Po-Hao Huang Date: Fri, 17 May 2024 09:33:50 +0800 Subject: wifi: rtw89: fix HW scan not aborting properly There is a length limit on the commands we send to firmware, so dividing to two commands is sometimes required when scanning. When aborting scan, we should not send second scan command to firmware after the first one is finished. This could cause some unexpected errors when we cannot receive firmware events (e.g. in suspend). Another case is scan happens before suspending, ieee80211_do_stop() is called to abort scan and driver indicate scan completion by ieee80211_scan_completed(), which queues event to scan work. But scan work might be late to execute after ieee80211_do_stop(). To correct this, driver indicates ieee80211_scan_completed() before returning, so that ieee80211_do_stop() can flush scan work properly. Fixes: bcbefbd032df ("wifi: rtw89: add wait/completion for abort scan") Cc: stable@vger.kernel.org Co-developed-by: Chih-Kang Chang Signed-off-by: Chih-Kang Chang Signed-off-by: Po-Hao Huang Signed-off-by: Ping-Ke Shih Link: https://msgid.link/20240517013350.11278-1-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/fw.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/realtek/rtw89/fw.c') diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 044a5b90c7f4..f5cd06c35982 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -6245,7 +6245,14 @@ void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) ret = rtw89_hw_scan_offload(rtwdev, vif, false); if (ret) - rtw89_hw_scan_complete(rtwdev, vif, true); + rtw89_warn(rtwdev, "rtw89_hw_scan_offload failed ret %d\n", ret); + + /* Indicate ieee80211_scan_completed() before returning, which is safe + * because scan abort command always waits for completion of + * RTW89_SCAN_END_SCAN_NOTIFY, so that ieee80211_stop() can flush scan + * work properly. + */ + rtw89_hw_scan_complete(rtwdev, vif, true); } static bool rtw89_is_any_vif_connected_or_connecting(struct rtw89_dev *rtwdev) -- cgit v1.2.3-58-ga151 From d5b96a4a31593a609acd564cfa54f269461a33f0 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 17 May 2024 09:36:39 +0800 Subject: wifi: rtw89: correct hardware value of nominal packet padding for WiFi 7 chips The hardware value of 3 for WiFi 7 chips is padding 16 or 20us selected by hardware automatically. Correct the value to resolve interoperability problem. Also define enum to be more readable. Signed-off-by: Ping-Ke Shih Link: https://msgid.link/20240517013639.11643-1-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 7 +++++++ drivers/net/wireless/realtek/rtw89/fw.c | 12 ++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless/realtek/rtw89/fw.c') diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index c0f2afb4888a..523ea9f5e6b1 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -884,6 +884,13 @@ enum rtw89_ps_mode { #define RTW89_BYR_BW_NUM (RTW89_CHANNEL_WIDTH_320 + 1) #define RTW89_PPE_BW_NUM (RTW89_CHANNEL_WIDTH_320 + 1) +enum rtw89_pe_duration { + RTW89_PE_DURATION_0 = 0, + RTW89_PE_DURATION_8 = 1, + RTW89_PE_DURATION_16 = 2, + RTW89_PE_DURATION_16_20 = 3, +}; + enum rtw89_ru_bandwidth { RTW89_RU26 = 0, RTW89_RU52 = 1, diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index f5cd06c35982..1ea2b662fc89 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -2752,11 +2752,11 @@ static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev, ppe8 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK; if (ppe16 != 7 && ppe8 == 7) - pads[i] = 2; + pads[i] = RTW89_PE_DURATION_16; else if (ppe8 != 7) - pads[i] = 1; + pads[i] = RTW89_PE_DURATION_8; else - pads[i] = 0; + pads[i] = RTW89_PE_DURATION_0; } } @@ -2889,11 +2889,11 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev, ppe8 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK; if (ppe16 != 7 && ppe8 == 7) - pads[i] = 2; + pads[i] = RTW89_PE_DURATION_16_20; else if (ppe8 != 7) - pads[i] = 1; + pads[i] = RTW89_PE_DURATION_8; else - pads[i] = 0; + pads[i] = RTW89_PE_DURATION_0; } } -- cgit v1.2.3-58-ga151 From e88c1714b2c7b230c799a00973bdeb374c765c06 Mon Sep 17 00:00:00 2001 From: Po-Hao Huang Date: Wed, 22 May 2024 10:45:31 +0800 Subject: wifi: rtw89: Fix P2P behavior for WiFi 7 chips Previously we used CCK rate when scanning for P2P on WiFi 7 chips. Fix this by explicitly setting the rate to OFDM 6Mbps. Signed-off-by: Po-Hao Huang Signed-off-by: Ping-Ke Shih Link: https://msgid.link/20240522024531.11401-1-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/fw.c | 10 ++++++++++ drivers/net/wireless/realtek/rtw89/fw.h | 4 ++++ 2 files changed, 14 insertions(+) (limited to 'drivers/net/wireless/realtek/rtw89/fw.c') diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 1ea2b662fc89..be39a8468d32 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -4850,6 +4850,7 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, { struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; + struct cfg80211_scan_request *req = rtwvif->scan_req; struct rtw89_h2c_scanofld_be_macc_role *macc_role; struct rtw89_chan *op = &scan_info->op_chan; struct rtw89_h2c_scanofld_be_opch *opch; @@ -4923,6 +4924,15 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, RTW89_H2C_SCANOFLD_BE_W6_CHAN_PROHIB_LOW); h2c->w7 = le32_encode_bits(option->prohib_chan >> 32, RTW89_H2C_SCANOFLD_BE_W7_CHAN_PROHIB_HIGH); + if (req->no_cck) { + h2c->w0 |= le32_encode_bits(true, RTW89_H2C_SCANOFLD_BE_W0_PROBE_WITH_RATE); + h2c->w8 = le32_encode_bits(RTW89_HW_RATE_OFDM6, + RTW89_H2C_SCANOFLD_BE_W8_PROBE_RATE_2GHZ) | + le32_encode_bits(RTW89_HW_RATE_OFDM6, + RTW89_H2C_SCANOFLD_BE_W8_PROBE_RATE_5GHZ) | + le32_encode_bits(RTW89_HW_RATE_OFDM6, + RTW89_H2C_SCANOFLD_BE_W8_PROBE_RATE_6GHZ); + } ptr += sizeof(*h2c); for (i = 0; i < option->num_macc_role; i++) { diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 4151c9d566bd..01fea0b004d3 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -2722,6 +2722,7 @@ struct rtw89_h2c_scanofld_be { #define RTW89_H2C_SCANOFLD_BE_W0_MACID GENMASK(23, 8) #define RTW89_H2C_SCANOFLD_BE_W0_PORT GENMASK(26, 24) #define RTW89_H2C_SCANOFLD_BE_W0_BAND GENMASK(28, 27) +#define RTW89_H2C_SCANOFLD_BE_W0_PROBE_WITH_RATE BIT(29) #define RTW89_H2C_SCANOFLD_BE_W1_NUM_MACC_ROLE GENMASK(7, 0) #define RTW89_H2C_SCANOFLD_BE_W1_NUM_OP GENMASK(15, 8) #define RTW89_H2C_SCANOFLD_BE_W1_NORM_PD GENMASK(31, 16) @@ -2738,6 +2739,9 @@ struct rtw89_h2c_scanofld_be { #define RTW89_H2C_SCANOFLD_BE_W5_MLO_MODE GENMASK(31, 0) #define RTW89_H2C_SCANOFLD_BE_W6_CHAN_PROHIB_LOW GENMASK(31, 0) #define RTW89_H2C_SCANOFLD_BE_W7_CHAN_PROHIB_HIGH GENMASK(31, 0) +#define RTW89_H2C_SCANOFLD_BE_W8_PROBE_RATE_2GHZ GENMASK(7, 0) +#define RTW89_H2C_SCANOFLD_BE_W8_PROBE_RATE_5GHZ GENMASK(15, 8) +#define RTW89_H2C_SCANOFLD_BE_W8_PROBE_RATE_6GHZ GENMASK(23, 16) static inline void RTW89_SET_FWCMD_P2P_MACID(void *cmd, u32 val) { -- cgit v1.2.3-58-ga151 From 8a00f7dfed62f1f74388bbd659e8d69d66886786 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 7 Jun 2024 22:02:51 +0800 Subject: wifi: rtw89: adopt firmware whose version is equal or less but closest Version C of 8922AE hardware will use the same firmware of version B, so extend rule of firmware recognition to allow less but closest firmware version. Originally only accept firmware with matched version. Tested on version A/B/C of 8922AE. Signed-off-by: Ping-Ke Shih Link: https://msgid.link/20240607140251.8295-1-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/fw.c | 34 +++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless/realtek/rtw89/fw.c') diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index be39a8468d32..23204b2706c9 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -462,7 +462,7 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, const u8 *mfw = firmware->data; u32 mfw_len = firmware->size; const struct rtw89_mfw_hdr *mfw_hdr = (const struct rtw89_mfw_hdr *)mfw; - const struct rtw89_mfw_info *mfw_info; + const struct rtw89_mfw_info *mfw_info = NULL, *tmp; int i; if (mfw_hdr->sig != RTW89_MFW_SIG) { @@ -476,15 +476,27 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, } for (i = 0; i < mfw_hdr->fw_nr; i++) { - mfw_info = &mfw_hdr->info[i]; - if (mfw_info->type == type) { - if (mfw_info->cv == rtwdev->hal.cv && !mfw_info->mp) - goto found; - if (type == RTW89_FW_LOGFMT) - goto found; + tmp = &mfw_hdr->info[i]; + if (tmp->type != type) + continue; + + if (type == RTW89_FW_LOGFMT) { + mfw_info = tmp; + goto found; + } + + /* Version order of WiFi firmware in firmware file are not in order, + * pass all firmware to find the equal or less but closest version. + */ + if (tmp->cv <= rtwdev->hal.cv && !tmp->mp) { + if (!mfw_info || mfw_info->cv < tmp->cv) + mfw_info = tmp; } } + if (mfw_info) + goto found; + if (!nowarn) rtw89_err(rtwdev, "no suitable firmware found\n"); return -ENOENT; @@ -606,10 +618,16 @@ int __rtw89_fw_recognize_from_elm(struct rtw89_dev *rtwdev, struct rtw89_hal *hal = &rtwdev->hal; struct rtw89_fw_suit *fw_suit; - if (hal->cv != elm->u.bbmcu.cv) + /* Version of BB MCU is in decreasing order in firmware file, so take + * first equal or less version, which is equal or less but closest version. + */ + if (hal->cv < elm->u.bbmcu.cv) return 1; /* ignore this element */ fw_suit = rtw89_fw_suit_get(rtwdev, type); + if (fw_suit->data) + return 1; /* ignore this element (a firmware is taken already) */ + fw_suit->data = elm->u.bbmcu.contents; fw_suit->size = le32_to_cpu(elm->size); -- cgit v1.2.3-58-ga151 From 0065199f4303bc2b05467e64779d392f9a29d61d Mon Sep 17 00:00:00 2001 From: Chih-Kang Chang Date: Thu, 20 Jun 2024 13:58:19 +0800 Subject: wifi: rtw89: wow: append security header offset for different cipher When creating EAPOL_KEY, SA_QUERY and ARP_RSP packet offload, we need to append security header offset for different cipher as required by the firmware. Only 8852A, 8852B, 8852BT and 8851B need it. Signed-off-by: Chih-Kang Chang Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20240620055825.17592-2-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/fw.c | 67 +++++++++++++++++++------------- drivers/net/wireless/realtek/rtw89/wow.c | 22 +++++++---- drivers/net/wireless/realtek/rtw89/wow.h | 30 ++++++++++++++ 3 files changed, 85 insertions(+), 34 deletions(-) (limited to 'drivers/net/wireless/realtek/rtw89/fw.c') diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 23204b2706c9..3c666fd0f8ed 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -13,22 +13,20 @@ #include "ps.h" #include "reg.h" #include "util.h" +#include "wow.h" struct rtw89_eapol_2_of_2 { - struct ieee80211_hdr_3addr hdr; u8 gtkbody[14]; u8 key_des_ver; u8 rsvd[92]; -} __packed __aligned(2); +} __packed; struct rtw89_sa_query { - struct ieee80211_hdr_3addr hdr; u8 category; u8 action; -} __packed __aligned(2); +} __packed; struct rtw89_arp_rsp { - struct ieee80211_hdr_3addr addr; u8 llc_hdr[sizeof(rfc1042_header)]; __be16 llc_type; struct arphdr arp_hdr; @@ -36,7 +34,7 @@ struct rtw89_arp_rsp { __be32 sender_ip; u8 target_hw[ETH_ALEN]; __be32 target_ip; -} __packed __aligned(2); +} __packed; static const u8 mss_signature[] = {0x4D, 0x53, 0x53, 0x4B, 0x50, 0x4F, 0x4F, 0x4C}; @@ -2197,8 +2195,10 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev, 0x8E, 0x01, 0x03, 0x00, 0x5F, 0x02, 0x03}; struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev); struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct rtw89_eapol_2_of_2 *eapol_pkt; + struct ieee80211_hdr_3addr *hdr; struct sk_buff *skb; u8 key_des_ver; @@ -2211,17 +2211,21 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev, else key_des_ver = 0; - skb = dev_alloc_skb(sizeof(*eapol_pkt)); + skb = dev_alloc_skb(sizeof(*hdr) + sec_hdr_len + sizeof(*eapol_pkt)); if (!skb) return NULL; + hdr = skb_put_zero(skb, sizeof(*hdr)); + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | + IEEE80211_FCTL_TODS | + IEEE80211_FCTL_PROTECTED); + ether_addr_copy(hdr->addr1, bss_conf->bssid); + ether_addr_copy(hdr->addr2, vif->addr); + ether_addr_copy(hdr->addr3, bss_conf->bssid); + + skb_put_zero(skb, sec_hdr_len); + eapol_pkt = skb_put_zero(skb, sizeof(*eapol_pkt)); - eapol_pkt->hdr.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_FCTL_TODS | - IEEE80211_FCTL_PROTECTED); - ether_addr_copy(eapol_pkt->hdr.addr1, bss_conf->bssid); - ether_addr_copy(eapol_pkt->hdr.addr2, vif->addr); - ether_addr_copy(eapol_pkt->hdr.addr3, bss_conf->bssid); memcpy(eapol_pkt->gtkbody, gtkbody, sizeof(gtkbody)); eapol_pkt->key_des_ver = key_des_ver; @@ -2233,20 +2237,26 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, { struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev); + struct ieee80211_hdr_3addr *hdr; struct rtw89_sa_query *sa_query; struct sk_buff *skb; - skb = dev_alloc_skb(sizeof(*sa_query)); + skb = dev_alloc_skb(sizeof(*hdr) + sec_hdr_len + sizeof(*sa_query)); if (!skb) return NULL; + hdr = skb_put_zero(skb, sizeof(*hdr)); + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION | + IEEE80211_FCTL_PROTECTED); + ether_addr_copy(hdr->addr1, bss_conf->bssid); + ether_addr_copy(hdr->addr2, vif->addr); + ether_addr_copy(hdr->addr3, bss_conf->bssid); + + skb_put_zero(skb, sec_hdr_len); + sa_query = skb_put_zero(skb, sizeof(*sa_query)); - sa_query->hdr.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ACTION | - IEEE80211_FCTL_PROTECTED); - ether_addr_copy(sa_query->hdr.addr1, bss_conf->bssid); - ether_addr_copy(sa_query->hdr.addr2, vif->addr); - ether_addr_copy(sa_query->hdr.addr3, bss_conf->bssid); sa_query->category = WLAN_CATEGORY_SA_QUERY; sa_query->action = WLAN_ACTION_SA_QUERY_RESPONSE; @@ -2256,17 +2266,19 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) { + u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev); struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct ieee80211_hdr_3addr *hdr; struct rtw89_arp_rsp *arp_skb; struct arphdr *arp_hdr; struct sk_buff *skb; __le16 fc; - skb = dev_alloc_skb(sizeof(struct rtw89_arp_rsp)); + skb = dev_alloc_skb(sizeof(*hdr) + sec_hdr_len + sizeof(*arp_skb)); if (!skb) return NULL; - arp_skb = skb_put_zero(skb, sizeof(*arp_skb)); + hdr = skb_put_zero(skb, sizeof(*hdr)); if (rtw_wow->ptk_alg) fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS | @@ -2274,11 +2286,14 @@ static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev, else fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS); - arp_skb->addr.frame_control = fc; - ether_addr_copy(arp_skb->addr.addr1, rtwvif->bssid); - ether_addr_copy(arp_skb->addr.addr2, rtwvif->mac_addr); - ether_addr_copy(arp_skb->addr.addr3, rtwvif->bssid); + hdr->frame_control = fc; + ether_addr_copy(hdr->addr1, rtwvif->bssid); + ether_addr_copy(hdr->addr2, rtwvif->mac_addr); + ether_addr_copy(hdr->addr3, rtwvif->bssid); + + skb_put_zero(skb, sec_hdr_len); + arp_skb = skb_put_zero(skb, sizeof(*arp_skb)); memcpy(arp_skb->llc_hdr, rfc1042_header, sizeof(rfc1042_header)); arp_skb->llc_type = htons(ETH_P_ARP); diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c index fa61484c3839..df22a53b8f41 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.c +++ b/drivers/net/wireless/realtek/rtw89/wow.c @@ -27,17 +27,23 @@ void rtw89_wow_parse_akm(struct rtw89_dev *rtwdev, struct sk_buff *skb) rtw_wow->akm = rsn_ie->akm_cipher_suite.type; } +#define RTW89_CIPHER_INFO_DEF(cipher) \ + {WLAN_CIPHER_SUITE_ ## cipher, .fw_alg = RTW89_WOW_FW_ALG_ ## cipher, \ + .len = WLAN_KEY_LEN_ ## cipher} + static const struct rtw89_cipher_info rtw89_cipher_info_defs[] = { - {WLAN_CIPHER_SUITE_WEP40, .fw_alg = 1, .len = WLAN_KEY_LEN_WEP40,}, - {WLAN_CIPHER_SUITE_WEP104, .fw_alg = 2, .len = WLAN_KEY_LEN_WEP104,}, - {WLAN_CIPHER_SUITE_TKIP, .fw_alg = 3, .len = WLAN_KEY_LEN_TKIP,}, - {WLAN_CIPHER_SUITE_CCMP, .fw_alg = 6, .len = WLAN_KEY_LEN_CCMP,}, - {WLAN_CIPHER_SUITE_GCMP, .fw_alg = 8, .len = WLAN_KEY_LEN_GCMP,}, - {WLAN_CIPHER_SUITE_CCMP_256, .fw_alg = 7, .len = WLAN_KEY_LEN_CCMP_256,}, - {WLAN_CIPHER_SUITE_GCMP_256, .fw_alg = 23, .len = WLAN_KEY_LEN_GCMP_256,}, - {WLAN_CIPHER_SUITE_AES_CMAC, .fw_alg = 32, .len = WLAN_KEY_LEN_AES_CMAC,}, + RTW89_CIPHER_INFO_DEF(WEP40), + RTW89_CIPHER_INFO_DEF(WEP104), + RTW89_CIPHER_INFO_DEF(TKIP), + RTW89_CIPHER_INFO_DEF(CCMP), + RTW89_CIPHER_INFO_DEF(GCMP), + RTW89_CIPHER_INFO_DEF(CCMP_256), + RTW89_CIPHER_INFO_DEF(GCMP_256), + RTW89_CIPHER_INFO_DEF(AES_CMAC), }; +#undef RTW89_CIPHER_INFO_DEF + static const struct rtw89_cipher_info *rtw89_cipher_alg_recognize(u32 cipher) { diff --git a/drivers/net/wireless/realtek/rtw89/wow.h b/drivers/net/wireless/realtek/rtw89/wow.h index e595aee0196d..0d90add0e88d 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.h +++ b/drivers/net/wireless/realtek/rtw89/wow.h @@ -35,6 +35,17 @@ enum rtw89_wake_reason { RTW89_WOW_RSN_RX_NLO = 0x55, }; +enum rtw89_fw_alg { + RTW89_WOW_FW_ALG_WEP40 = 0x1, + RTW89_WOW_FW_ALG_WEP104 = 0x2, + RTW89_WOW_FW_ALG_TKIP = 0x3, + RTW89_WOW_FW_ALG_CCMP = 0x6, + RTW89_WOW_FW_ALG_CCMP_256 = 0x7, + RTW89_WOW_FW_ALG_GCMP = 0x8, + RTW89_WOW_FW_ALG_GCMP_256 = 0x9, + RTW89_WOW_FW_ALG_AES_CMAC = 0xa, +}; + struct rtw89_cipher_suite { u8 oui[3]; u8 type; @@ -64,6 +75,25 @@ struct rtw89_set_key_info_iter_data { bool error; }; +static inline int rtw89_wow_get_sec_hdr_len(struct rtw89_dev *rtwdev) +{ + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + + if (!(rtwdev->chip->chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev))) + return 0; + + switch (rtw_wow->ptk_alg) { + case RTW89_WOW_FW_ALG_WEP40: + return 4; + case RTW89_WOW_FW_ALG_TKIP: + case RTW89_WOW_FW_ALG_CCMP: + case RTW89_WOW_FW_ALG_GCMP_256: + return 8; + default: + return 0; + } +} + #ifdef CONFIG_PM int rtw89_wow_suspend(struct rtw89_dev *rtwdev, struct cfg80211_wowlan *wowlan); int rtw89_wow_resume(struct rtw89_dev *rtwdev); -- cgit v1.2.3-58-ga151 From 0e5210217768625b43f099bcaafe627b098655d5 Mon Sep 17 00:00:00 2001 From: Chih-Kang Chang Date: Thu, 20 Jun 2024 13:58:20 +0800 Subject: wifi: rtw89: wow: update WoWLAN reason register for different FW Need to update WoWLAN wakeup reason register after firmware version 0.35.22.0 for RTL8922A, and 0.27.80.0 for RTL8852CE. Signed-off-by: Chih-Kang Chang Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20240620055825.17592-3-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 3 ++- drivers/net/wireless/realtek/rtw89/fw.c | 2 ++ drivers/net/wireless/realtek/rtw89/fw.h | 6 ++++++ drivers/net/wireless/realtek/rtw89/reg.h | 4 ++++ drivers/net/wireless/realtek/rtw89/rtw8851b.c | 6 +++++- drivers/net/wireless/realtek/rtw89/rtw8852a.c | 6 +++++- drivers/net/wireless/realtek/rtw89/rtw8852b.c | 6 +++++- drivers/net/wireless/realtek/rtw89/rtw8852c.c | 6 +++++- drivers/net/wireless/realtek/rtw89/rtw8922a.c | 6 +++++- drivers/net/wireless/realtek/rtw89/wow.c | 7 ++++++- 10 files changed, 45 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless/realtek/rtw89/fw.c') diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index e8ec0246bccd..f1de975c5356 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -4236,7 +4236,7 @@ struct rtw89_chip_info { const u32 *c2h_regs; struct rtw89_reg_def c2h_counter_reg; const struct rtw89_page_regs *page_regs; - u32 wow_reason_reg; + const u32 *wow_reason_reg; bool cfo_src_fd; bool cfo_hw_comp; const struct rtw89_reg_def *dcfo_comp; @@ -4346,6 +4346,7 @@ enum rtw89_fw_feature { RTW89_FW_FEATURE_NO_LPS_PG, RTW89_FW_FEATURE_BEACON_FILTER, RTW89_FW_FEATURE_MACID_PAUSE_SLEEP, + RTW89_FW_FEATURE_WOW_REASON_V1, }; struct rtw89_fw_suit { diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 3c666fd0f8ed..a907d381ac77 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -675,10 +675,12 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = { __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 36, 0, SCAN_OFFLOAD), __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 40, 0, CRASH_TRIGGER), __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 56, 10, BEACON_FILTER), + __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 80, 0, WOW_REASON_V1), __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 30, 0, CRASH_TRIGGER), __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 11, 0, MACID_PAUSE_SLEEP), __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 35, 0, SCAN_OFFLOAD), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 12, 0, BEACON_FILTER), + __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 22, 0, WOW_REASON_V1), }; static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw, diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 01fea0b004d3..c3b4324c621c 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -4659,4 +4659,10 @@ const struct rtw89_rfe_parms * rtw89_load_rfe_data_from_fw(struct rtw89_dev *rtwdev, const struct rtw89_rfe_parms *init); +enum rtw89_wow_wakeup_ver { + RTW89_WOW_REASON_V0, + RTW89_WOW_REASON_V1, + RTW89_WOW_REASON_NUM, +}; + #endif diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index 5a59234301ca..fd81cf863bea 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -311,6 +311,8 @@ #define B_AX_S1_LDO2PWRCUT_F BIT(23) #define B_AX_S0_LDO_VSEL_F_MASK GENMASK(22, 21) +#define R_AX_DBG_WOW 0x0504 + #define R_AX_SEC_CTRL 0x0C00 #define B_AX_SEC_IDMEM_SIZE_CONFIG_MASK GENMASK(17, 16) @@ -4315,6 +4317,8 @@ #define R_BE_WLCPU_PORT_PC 0x03FC +#define R_BE_DBG_WOW 0x0504 + #define R_BE_DCPU_PLATFORM_ENABLE 0x0888 #define B_BE_DCPU_SYM_DPLT_MEM_MUX_EN BIT(10) #define B_BE_DCPU_WARM_EN BIT(9) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c index 78e276f321c2..40cf84a79c46 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -105,6 +105,10 @@ static const u32 rtw8851b_c2h_regs[RTW89_C2HREG_MAX] = { R_AX_C2HREG_DATA3 }; +static const u32 rtw8851b_wow_wakeup_regs[RTW89_WOW_REASON_NUM] = { + R_AX_C2HREG_DATA3 + 3, R_AX_C2HREG_DATA3 + 3, +}; + static const struct rtw89_page_regs rtw8851b_page_regs = { .hci_fc_ctrl = R_AX_HCI_FC_CTRL, .ch_page_ctrl = R_AX_CH_PAGE_CTRL, @@ -2509,7 +2513,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = { .c2h_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_C2H_ENQ_CNT_MASK >> 8}, .c2h_regs = rtw8851b_c2h_regs, .page_regs = &rtw8851b_page_regs, - .wow_reason_reg = R_AX_C2HREG_DATA3 + 3, + .wow_reason_reg = rtw8851b_wow_wakeup_regs, .cfo_src_fd = true, .cfo_hw_comp = true, .dcfo_comp = &rtw8851b_dcfo_comp, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index aebbceea93f8..08e148328c62 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -398,6 +398,10 @@ static const u32 rtw8852a_c2h_regs[RTW89_C2HREG_MAX] = { R_AX_C2HREG_DATA3 }; +static const u32 rtw8852a_wow_wakeup_regs[RTW89_WOW_REASON_NUM] = { + R_AX_C2HREG_DATA3 + 3, R_AX_C2HREG_DATA3 + 3, +}; + static const struct rtw89_page_regs rtw8852a_page_regs = { .hci_fc_ctrl = R_AX_HCI_FC_CTRL, .ch_page_ctrl = R_AX_CH_PAGE_CTRL, @@ -2225,7 +2229,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .c2h_regs = rtw8852a_c2h_regs, .c2h_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_C2H_ENQ_CNT_MASK >> 8}, .page_regs = &rtw8852a_page_regs, - .wow_reason_reg = R_AX_C2HREG_DATA3 + 3, + .wow_reason_reg = rtw8852a_wow_wakeup_regs, .cfo_src_fd = false, .cfo_hw_comp = false, .dcfo_comp = &rtw8852a_dcfo_comp, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index 381c881fee69..24f9fd444ca0 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -76,6 +76,10 @@ static const u32 rtw8852b_c2h_regs[RTW89_C2HREG_MAX] = { R_AX_C2HREG_DATA3 }; +static const u32 rtw8852b_wow_wakeup_regs[RTW89_WOW_REASON_NUM] = { + R_AX_C2HREG_DATA3 + 3, R_AX_C2HREG_DATA3 + 3, +}; + static const struct rtw89_page_regs rtw8852b_page_regs = { .hci_fc_ctrl = R_AX_HCI_FC_CTRL, .ch_page_ctrl = R_AX_CH_PAGE_CTRL, @@ -1026,7 +1030,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .c2h_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_C2H_ENQ_CNT_MASK >> 8}, .c2h_regs = rtw8852b_c2h_regs, .page_regs = &rtw8852b_page_regs, - .wow_reason_reg = R_AX_C2HREG_DATA3 + 3, + .wow_reason_reg = rtw8852b_wow_wakeup_regs, .cfo_src_fd = true, .cfo_hw_comp = true, .dcfo_comp = &rtw8852b_dcfo_comp, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index 544ea1d3b577..193168dc7b6c 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -73,6 +73,10 @@ static const u32 rtw8852c_c2h_regs[RTW89_H2CREG_MAX] = { R_AX_C2HREG_DATA3_V1 }; +static const u32 rtw8852c_wow_wakeup_regs[RTW89_WOW_REASON_NUM] = { + R_AX_C2HREG_DATA3_V1 + 3, R_AX_DBG_WOW, +}; + static const struct rtw89_page_regs rtw8852c_page_regs = { .hci_fc_ctrl = R_AX_HCI_FC_CTRL_V1, .ch_page_ctrl = R_AX_CH_PAGE_CTRL_V1, @@ -3007,7 +3011,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .c2h_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_C2H_ENQ_CNT_MASK >> 8}, .c2h_regs = rtw8852c_c2h_regs, .page_regs = &rtw8852c_page_regs, - .wow_reason_reg = R_AX_C2HREG_DATA3_V1 + 3, + .wow_reason_reg = rtw8852c_wow_wakeup_regs, .cfo_src_fd = false, .cfo_hw_comp = false, .dcfo_comp = &rtw8852c_dcfo_comp, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c index cc4f251caadd..2af568a3264d 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c @@ -85,6 +85,10 @@ static const u32 rtw8922a_c2h_regs[RTW89_H2CREG_MAX] = { R_BE_C2HREG_DATA3 }; +static const u32 rtw8922a_wow_wakeup_regs[RTW89_WOW_REASON_NUM] = { + R_AX_C2HREG_DATA3_V1 + 3, R_BE_DBG_WOW, +}; + static const struct rtw89_page_regs rtw8922a_page_regs = { .hci_fc_ctrl = R_BE_HCI_FC_CTRL, .ch_page_ctrl = R_BE_CH_PAGE_CTRL, @@ -2609,7 +2613,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = { .c2h_counter_reg = {R_BE_UDM1 + 1, B_BE_UDM1_HALMAC_C2H_ENQ_CNT_MASK >> 8}, .c2h_regs = rtw8922a_c2h_regs, .page_regs = &rtw8922a_page_regs, - .wow_reason_reg = R_AX_C2HREG_DATA3_V1 + 3, + .wow_reason_reg = rtw8922a_wow_wakeup_regs, .cfo_src_fd = true, .cfo_hw_comp = true, .dcfo_comp = NULL, diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c index df22a53b8f41..a49265cda98f 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.c +++ b/drivers/net/wireless/realtek/rtw89/wow.c @@ -723,13 +723,18 @@ static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt; - u32 wow_reason_reg = rtwdev->chip->wow_reason_reg; struct cfg80211_wowlan_nd_info nd_info; struct cfg80211_wowlan_wakeup wakeup = { .pattern_idx = -1, }; + u32 wow_reason_reg; u8 reason; + if (RTW89_CHK_FW_FEATURE(WOW_REASON_V1, &rtwdev->fw)) + wow_reason_reg = rtwdev->chip->wow_reason_reg[RTW89_WOW_REASON_V1]; + else + wow_reason_reg = rtwdev->chip->wow_reason_reg[RTW89_WOW_REASON_V0]; + reason = rtw89_read8(rtwdev, wow_reason_reg); switch (reason) { case RTW89_WOW_RSN_RX_DEAUTH: -- cgit v1.2.3-58-ga151 From dda364c345913fe03ddbe4d5ae14a2754c100296 Mon Sep 17 00:00:00 2001 From: Chih-Kang Chang Date: Thu, 20 Jun 2024 13:58:22 +0800 Subject: wifi: rtw89: wow: fix GTK offload H2C skbuff issue We mistakenly put skb too large and that may exceed skb->end. Therefore, we fix it. skbuff: skb_over_panic: text:ffffffffc09e9a9d len:416 put:204 head:ffff8fba04eca780 data:ffff8fba04eca7e0 tail:0x200 end:0x140 dev: ------------[ cut here ]------------ kernel BUG at net/core/skbuff.c:192! invalid opcode: 0000 [#1] PREEMPT SMP PTI CPU: 1 PID: 4747 Comm: kworker/u4:44 Tainted: G O 6.6.30-02659-gc18865c4dfbd #1 86547039b47e46935493f615ee31d0b2d711d35e Hardware name: HP Meep/Meep, BIOS Google_Meep.11297.262.0 03/18/2021 Workqueue: events_unbound async_run_entry_fn RIP: 0010:skb_panic+0x5d/0x60 Code: c6 63 8b 8f bb 4c 0f 45 f6 48 c7 c7 4d 89 8b bb 48 89 ce 44 89 d1 41 56 53 41 53 ff b0 c8 00 00 00 e8 27 5f 23 00 48 83 c4 20 <0f> 0b 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 44 RSP: 0018:ffffaa700144bad0 EFLAGS: 00010282 RAX: 0000000000000089 RBX: 0000000000000140 RCX: 14432c5aad26c900 RDX: 0000000000000000 RSI: 00000000ffffdfff RDI: 0000000000000001 RBP: ffffaa700144bae0 R08: 0000000000000000 R09: ffffaa700144b920 R10: 00000000ffffdfff R11: ffffffffbc28fbc0 R12: ffff8fba4e57a010 R13: 0000000000000000 R14: ffffffffbb8f8b63 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff8fba7bd00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007999c4ad1000 CR3: 000000015503a000 CR4: 0000000000350ee0 Call Trace: ? __die_body+0x1f/0x70 ? die+0x3d/0x60 ? do_trap+0xa4/0x110 ? skb_panic+0x5d/0x60 ? do_error_trap+0x6d/0x90 ? skb_panic+0x5d/0x60 ? handle_invalid_op+0x30/0x40 ? skb_panic+0x5d/0x60 ? exc_invalid_op+0x3c/0x50 ? asm_exc_invalid_op+0x16/0x20 ? skb_panic+0x5d/0x60 skb_put+0x49/0x50 rtw89_fw_h2c_wow_gtk_ofld+0xbd/0x220 [rtw89_core 778b32de31cd1f14df2d6721ae99ba8a83636fa5] rtw89_wow_resume+0x31f/0x540 [rtw89_core 778b32de31cd1f14df2d6721ae99ba8a83636fa5] rtw89_ops_resume+0x2b/0xa0 [rtw89_core 778b32de31cd1f14df2d6721ae99ba8a83636fa5] ieee80211_reconfig+0x84/0x13e0 [mac80211 818a894e3b77da6298269c59ed7cdff065a4ed52] ? __pfx_wiphy_resume+0x10/0x10 [cfg80211 1a793119e2aeb157c4ca4091ff8e1d9ae233b59d] ? dev_printk_emit+0x51/0x70 ? _dev_info+0x6e/0x90 ? __pfx_wiphy_resume+0x10/0x10 [cfg80211 1a793119e2aeb157c4ca4091ff8e1d9ae233b59d] wiphy_resume+0x89/0x180 [cfg80211 1a793119e2aeb157c4ca4091ff8e1d9ae233b59d] ? __pfx_wiphy_resume+0x10/0x10 [cfg80211 1a793119e2aeb157c4ca4091ff8e1d9ae233b59d] dpm_run_callback+0x3c/0x140 device_resume+0x1f9/0x3c0 ? __pfx_dpm_watchdog_handler+0x10/0x10 async_resume+0x1d/0x30 async_run_entry_fn+0x29/0xd0 process_scheduled_works+0x1d8/0x3d0 worker_thread+0x1fc/0x2f0 kthread+0xed/0x110 ? __pfx_worker_thread+0x10/0x10 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x38/0x50 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1b/0x30 Modules linked in: ccm 8021q r8153_ecm cdc_ether usbnet r8152 mii dm_integrity async_xor xor async_tx lz4 lz4_compress zstd zstd_compress zram zsmalloc uinput rfcomm cmac algif_hash rtw89_8922ae(O) algif_skcipher rtw89_8922a(O) af_alg rtw89_pci(O) rtw89_core(O) btusb(O) snd_soc_sst_bxt_da7219_max98357a btbcm(O) snd_soc_hdac_hdmi btintel(O) snd_soc_intel_hda_dsp_common snd_sof_probes btrtl(O) btmtk(O) snd_hda_codec_hdmi snd_soc_dmic uvcvideo videobuf2_vmalloc uvc videobuf2_memops videobuf2_v4l2 videobuf2_common snd_sof_pci_intel_apl snd_sof_intel_hda_common snd_soc_hdac_hda snd_sof_intel_hda soundwire_intel soundwire_generic_allocation snd_sof_intel_hda_mlink soundwire_cadence snd_sof_pci snd_sof_xtensa_dsp mac80211 snd_soc_acpi_intel_match snd_soc_acpi snd_sof snd_sof_utils soundwire_bus snd_soc_max98357a snd_soc_avs snd_soc_hda_codec snd_hda_ext_core snd_intel_dspcfg snd_intel_sdw_acpi snd_soc_da7219 snd_hda_codec snd_hwdep snd_hda_core veth ip6table_nat xt_MASQUERADE xt_cgroup fuse bluetooth ecdh_generic cfg80211 ecc gsmi: Log Shutdown Reason 0x03 ---[ end trace 0000000000000000 ]--- Fixes: ed9a3c0d4dd9 ("wifi: rtw89: wow: construct EAPoL packet for GTK rekey offload") Signed-off-by: Chih-Kang Chang Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20240620055825.17592-5-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/fw.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net/wireless/realtek/rtw89/fw.c') diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index a907d381ac77..e3fc9f168ae5 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -6767,10 +6767,8 @@ int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev, skb_put(skb, len); h2c = (struct rtw89_h2c_wow_gtk_ofld *)skb->data; - if (!enable) { - skb_put_zero(skb, sizeof(*gtk_info)); + if (!enable) goto hdr; - } ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, RTW89_PKT_OFLD_TYPE_EAPOL_KEY, -- cgit v1.2.3-58-ga151 From 792586591f446c688821989a21ea3e65f192e6f1 Mon Sep 17 00:00:00 2001 From: Chih-Kang Chang Date: Thu, 20 Jun 2024 13:58:25 +0800 Subject: wifi: rtw89: add polling for LPS H2C to ensure FW received We add polling after sending LPS H2C to ensure that the Firmware is received and executes RPWM thereafter. Otherwise, if the Firmware executes RPWM without receiving LPS H2C, it will cause beacon loss in WoWLAN mode due to the inability to obtain channel and bandwidth information from H2C. Signed-off-by: Chih-Kang Chang Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20240620055825.17592-8-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/fw.c | 7 +++++++ drivers/net/wireless/realtek/rtw89/reg.h | 2 ++ 2 files changed, 9 insertions(+) (limited to 'drivers/net/wireless/realtek/rtw89/fw.c') diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index e3fc9f168ae5..fbe08c162b93 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -2496,6 +2496,7 @@ int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) struct rtw89_h2c_lps_ch_info *h2c; u32 len = sizeof(*h2c); struct sk_buff *skb; + u32 done; int ret; if (chip->chip_gen != RTW89_CHIP_BE) @@ -2519,12 +2520,18 @@ int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) H2C_CAT_OUTSRC, H2C_CL_OUTSRC_DM, H2C_FUNC_FW_LPS_CH_INFO, 0, 0, len); + rtw89_phy_write32_mask(rtwdev, R_CHK_LPS_STAT, B_CHK_LPS_STAT, 0); ret = rtw89_h2c_tx(rtwdev, skb, false); if (ret) { rtw89_err(rtwdev, "failed to send h2c\n"); goto fail; } + ret = read_poll_timeout(rtw89_phy_read32_mask, done, done, 50, 5000, + true, rtwdev, R_CHK_LPS_STAT, B_CHK_LPS_STAT); + if (ret) + rtw89_warn(rtwdev, "h2c_lps_ch_info done polling timeout\n"); + return 0; fail: dev_kfree_skb_any(skb); diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index c9f6bdc84d03..897884e9667f 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -7818,6 +7818,8 @@ #define B_UPD_P0_EN BIT(31) #define R_EMLSR 0x0044 #define B_EMLSR_PARM GENMASK(27, 12) +#define R_CHK_LPS_STAT 0x0058 +#define B_CHK_LPS_STAT BIT(0) #define R_SPOOF_CG 0x00B4 #define B_SPOOF_CG_EN BIT(17) #define R_CHINFO_SEG 0x00B4 -- cgit v1.2.3-58-ga151