From 4bcef86b13316511bb336a26140fc4130c3a65a2 Mon Sep 17 00:00:00 2001 From: Kuan-Chung Chen Date: Fri, 6 Jun 2025 10:02:57 +0800 Subject: [PATCH 01/16] wifi: rtw89: 8852c: increase beacon loss to 6 seconds Intermittent beacon loss from a specific AP causes the connection to be lost. Increasing the beacon loss count can make the connection more stable. Signed-off-by: Kuan-Chung Chen Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250606020302.16873-2-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/fw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 00b65b2995cff..36147040c35b0 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -838,6 +838,7 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = { __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(RTL8852C, ge, 0, 27, 128, 0, BEACON_LOSS_COUNT_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), -- 2.51.0 From 29dc4c560219ef0b2fa667d5f1f1e8df11e38f5a Mon Sep 17 00:00:00 2001 From: Zong-Zhe Yang Date: Fri, 6 Jun 2025 10:02:58 +0800 Subject: [PATCH 02/16] wifi: rtw89: fw: add RFE type to RF TSSI H2C command Append a new field for RFE (RF Front End) type to RF TSSI H2C command. FW has forward compatibility when handling this H2C command, so just need to consider backward cases in FW point of view. | old FW | new FW ------------------------------ old driver | O | X ------------------------------ new driver | O | O Currently only RTL8922A uses this RF TSSI H2C command. Increase its FW format max and will let new FW binary align with it. Then, old driver won't load new FW. Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250606020302.16873-3-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/fw.c | 2 ++ drivers/net/wireless/realtek/rtw89/fw.h | 1 + drivers/net/wireless/realtek/rtw89/rtw8922a.c | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 36147040c35b0..1d37ea7f1391d 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -6032,6 +6032,7 @@ fail: int rtw89_fw_h2c_rf_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan, enum rtw89_tssi_mode tssi_mode) { + struct rtw89_efuse *efuse = &rtwdev->efuse; struct rtw89_hal *hal = &rtwdev->hal; struct rtw89_h2c_rf_tssi *h2c; u32 len = sizeof(*h2c); @@ -6054,6 +6055,7 @@ int rtw89_fw_h2c_rf_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, h2c->hwtx_en = true; h2c->cv = hal->cv; h2c->tssi_mode = tssi_mode; + h2c->rfe_type = efuse->rfe_type; rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(rtwdev, phy_idx, chan, h2c); rtw89_phy_rfk_tssi_fill_fwcmd_tmeter_tbl(rtwdev, phy_idx, chan, h2c); diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 0fcc824e41be6..2fc2d1d61e299 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -4435,6 +4435,7 @@ struct rtw89_h2c_rf_tssi { u8 pg_thermal[2]; u8 ftable[2][128]; u8 tssi_mode; + u8 rfe_type; } __packed; struct rtw89_h2c_rf_iqk { diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c index 1d0f6e7df497d..680168f314666 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c @@ -15,7 +15,7 @@ #include "sar.h" #include "util.h" -#define RTW8922A_FW_FORMAT_MAX 3 +#define RTW8922A_FW_FORMAT_MAX 4 #define RTW8922A_FW_BASENAME "rtw89/rtw8922a_fw" #define RTW8922A_MODULE_FIRMWARE \ RTW8922A_FW_BASENAME "-" __stringify(RTW8922A_FW_FORMAT_MAX) ".bin" -- 2.51.0 From b9b8828fdf8c5871ee2e7e701c907547285ff311 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 6 Jun 2025 10:02:59 +0800 Subject: [PATCH 03/16] wifi: rtw89: rfk: support IQK firmware command v1 Add new IQK firmware command format v1 (with suffix), and rename original command format to v0 for older firmware. Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250606020302.16873-4-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 1 + drivers/net/wireless/realtek/rtw89/fw.c | 30 +++++++++++++++++++++-- drivers/net/wireless/realtek/rtw89/fw.h | 13 +++++++++- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index ddd207326503b..c79164757bd97 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -4514,6 +4514,7 @@ enum rtw89_fw_feature { RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V0, RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V1, RTW89_FW_FEATURE_RFK_RXDCK_V0, + RTW89_FW_FEATURE_RFK_IQK_V0, RTW89_FW_FEATURE_NO_WOW_CPU_IO_RX, RTW89_FW_FEATURE_NOTIFY_AP_INFO, RTW89_FW_FEATURE_CH_INFO_BE_V0, diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 1d37ea7f1391d..0547eb11d3782 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -845,6 +845,7 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = { __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 21, 0, SCAN_OFFLOAD_BE_V0), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 12, 0, BEACON_FILTER), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 22, 0, WOW_REASON_V1), + __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 28, 0, RFK_IQK_V0), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 31, 0, RFK_PRE_NOTIFY_V0), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 31, 0, LPS_CH_INFO), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 42, 0, RFK_RXDCK_V0), @@ -6080,22 +6081,47 @@ fail: int rtw89_fw_h2c_rf_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan) { + struct rtw89_hal *hal = &rtwdev->hal; + struct rtw89_h2c_rf_iqk_v0 *h2c_v0; struct rtw89_h2c_rf_iqk *h2c; u32 len = sizeof(*h2c); struct sk_buff *skb; + u8 ver = U8_MAX; int ret; + if (RTW89_CHK_FW_FEATURE(RFK_IQK_V0, &rtwdev->fw)) { + len = sizeof(*h2c_v0); + ver = 0; + } + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); if (!skb) { rtw89_err(rtwdev, "failed to alloc skb for h2c RF IQK\n"); return -ENOMEM; } skb_put(skb, len); + + if (ver == 0) { + h2c_v0 = (struct rtw89_h2c_rf_iqk_v0 *)skb->data; + + h2c_v0->phy_idx = cpu_to_le32(phy_idx); + h2c_v0->dbcc = cpu_to_le32(rtwdev->dbcc_en); + + goto done; + } + h2c = (struct rtw89_h2c_rf_iqk *)skb->data; - h2c->phy_idx = cpu_to_le32(phy_idx); - h2c->dbcc = cpu_to_le32(rtwdev->dbcc_en); + h2c->len = sizeof(*h2c); + h2c->ktype = 0; + h2c->phy = phy_idx; + h2c->kpath = rtw89_phy_get_kpath(rtwdev, phy_idx); + h2c->band = chan->band_type; + h2c->bw = chan->band_width; + h2c->ch = chan->channel; + h2c->cv = hal->cv; +done: rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK, H2C_FUNC_RFK_IQK_OFFLOAD, 0, 0, len); diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 2fc2d1d61e299..d4815bcce91bc 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -4438,11 +4438,22 @@ struct rtw89_h2c_rf_tssi { u8 rfe_type; } __packed; -struct rtw89_h2c_rf_iqk { +struct rtw89_h2c_rf_iqk_v0 { __le32 phy_idx; __le32 dbcc; } __packed; +struct rtw89_h2c_rf_iqk { + u8 len; + u8 ktype; + u8 phy; + u8 kpath; + u8 band; + u8 bw; + u8 ch; + u8 cv; +} __packed; + struct rtw89_h2c_rf_dpk { u8 len; u8 phy; -- 2.51.0 From b0efb82651afce32999ebeba1f48ad2c5f53a356 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 6 Jun 2025 10:03:00 +0800 Subject: [PATCH 04/16] wifi: rtw89: mac: add dummy handler of MAC C2H event class 27 The newer firmware add new C2H event class 27, which is to report WiFi role status. Since rtw89 doesn't use the status yet, add a dummy handler to avoid warning: rtw89_8922ae 0000:03:00.0: MAC c2h class 27 func 0 not support Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250606020302.16873-5-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/mac.c | 1 + drivers/net/wireless/realtek/rtw89/mac.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index 9f0e30e750092..4bd5e2728ce5c 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -5717,6 +5717,7 @@ void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, handler = rtw89_mac_c2h_ap_handler[func]; break; case RTW89_MAC_C2H_CLASS_FWDBG: + case RTW89_MAC_C2H_CLASS_ROLE: return; default: rtw89_info(rtwdev, "MAC c2h class %d not support\n", class); diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index 8013c852d5bed..c1cbc53b16a7b 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -469,6 +469,7 @@ enum rtw89_mac_c2h_class { RTW89_MAC_C2H_CLASS_MLO = 0xc, RTW89_MAC_C2H_CLASS_MRC = 0xe, RTW89_MAC_C2H_CLASS_AP = 0x18, + RTW89_MAC_C2H_CLASS_ROLE = 0x1b, RTW89_MAC_C2H_CLASS_MAX, }; -- 2.51.0 From d310eaf4ad51ad738c31848483abb2f45834819a Mon Sep 17 00:00:00 2001 From: Kuan-Chung Chen Date: Fri, 6 Jun 2025 10:04:08 +0800 Subject: [PATCH 05/16] wifi: rtw89: add chip_ops::chan_to_rf18_val to get code of RF register value The RF 0x18 register stores radio frequency domain parameters, including band, center channel and bandwidth. This information is used in RF domain. Add a chip_ops to retrieve the RF 0x18 value, which allows driver to query for a specific channel. No logic is changed. Signed-off-by: Kuan-Chung Chen Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250606020408.17035-1-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 13 +++++ drivers/net/wireless/realtek/rtw89/rtw8851b.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852a.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852b.c | 1 + .../net/wireless/realtek/rtw89/rtw8852bt.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852c.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8922a.c | 43 +++++++++++++++ .../net/wireless/realtek/rtw89/rtw8922a_rfk.c | 52 ++----------------- 8 files changed, 66 insertions(+), 47 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index c79164757bd97..c93d3ea2b0a41 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3646,6 +3646,8 @@ struct rtw89_chip_ops { enum rtw89_phy_idx phy_idx); int (*init_txpwr_unit)(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); u8 (*get_thermal)(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path); + u32 (*chan_to_rf18_val)(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan); void (*ctrl_btg_bt_rx)(struct rtw89_dev *rtwdev, bool en, enum rtw89_phy_idx phy_idx); void (*query_ppdu)(struct rtw89_dev *rtwdev, @@ -6882,6 +6884,17 @@ static inline u8 rtw89_chip_get_thermal(struct rtw89_dev *rtwdev, return chip->ops->get_thermal(rtwdev, rf_path); } +static inline u32 rtw89_chip_chan_to_rf18_val(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (!chip->ops->chan_to_rf18_val) + return 0; + + return chip->ops->chan_to_rf18_val(rtwdev, chan); +} + static inline void rtw89_chip_query_ppdu(struct rtw89_dev *rtwdev, struct rtw89_rx_phy_ppdu *phy_ppdu, struct ieee80211_rx_status *status) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c index fafa200a9c8de..39df1a255095e 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -2402,6 +2402,7 @@ static const struct rtw89_chip_ops rtw8851b_chip_ops = { .set_txpwr_ctrl = rtw8851b_set_txpwr_ctrl, .init_txpwr_unit = rtw8851b_init_txpwr_unit, .get_thermal = rtw8851b_get_thermal, + .chan_to_rf18_val = NULL, .ctrl_btg_bt_rx = rtw8851b_ctrl_btg_bt_rx, .query_ppdu = rtw8851b_query_ppdu, .convert_rpl_to_rssi = NULL, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index cd5987fc52d7d..dc4eab2e79199 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -2128,6 +2128,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = { .set_txpwr_ctrl = rtw8852a_set_txpwr_ctrl, .init_txpwr_unit = rtw8852a_init_txpwr_unit, .get_thermal = rtw8852a_get_thermal, + .chan_to_rf18_val = NULL, .ctrl_btg_bt_rx = rtw8852a_ctrl_btg_bt_rx, .query_ppdu = rtw8852a_query_ppdu, .convert_rpl_to_rssi = NULL, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index dacdb384de2cf..1f1e10f2b39d7 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -755,6 +755,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = { .set_txpwr_ctrl = rtw8852bx_set_txpwr_ctrl, .init_txpwr_unit = rtw8852bx_init_txpwr_unit, .get_thermal = rtw8852bx_get_thermal, + .chan_to_rf18_val = NULL, .ctrl_btg_bt_rx = rtw8852bx_ctrl_btg_bt_rx, .query_ppdu = rtw8852bx_query_ppdu, .convert_rpl_to_rssi = rtw8852bx_convert_rpl_to_rssi, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c index 289dce688d720..4c34f50379087 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c @@ -689,6 +689,7 @@ static const struct rtw89_chip_ops rtw8852bt_chip_ops = { .set_txpwr_ctrl = rtw8852bx_set_txpwr_ctrl, .init_txpwr_unit = rtw8852bx_init_txpwr_unit, .get_thermal = rtw8852bx_get_thermal, + .chan_to_rf18_val = NULL, .ctrl_btg_bt_rx = rtw8852bx_ctrl_btg_bt_rx, .query_ppdu = rtw8852bx_query_ppdu, .convert_rpl_to_rssi = rtw8852bx_convert_rpl_to_rssi, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index 2a6143a8d256b..b39add1b798c0 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -2948,6 +2948,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { .set_txpwr_ctrl = rtw8852c_set_txpwr_ctrl, .init_txpwr_unit = rtw8852c_init_txpwr_unit, .get_thermal = rtw8852c_get_thermal, + .chan_to_rf18_val = NULL, .ctrl_btg_bt_rx = rtw8852c_ctrl_btg_bt_rx, .query_ppdu = rtw8852c_query_ppdu, .convert_rpl_to_rssi = NULL, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c index 680168f314666..ca32ccb001074 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c @@ -2390,6 +2390,48 @@ static u8 rtw8922a_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_p return clamp_t(int, th, 0, U8_MAX); } +static u32 rtw8922a_chan_to_rf18_val(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan) +{ + u32 val = u32_encode_bits(chan->channel, RR_CFGCH_CH); + + switch (chan->band_type) { + case RTW89_BAND_2G: + default: + break; + case RTW89_BAND_5G: + val |= u32_encode_bits(CFGCH_BAND1_5G, RR_CFGCH_BAND1) | + u32_encode_bits(CFGCH_BAND0_5G, RR_CFGCH_BAND0); + break; + case RTW89_BAND_6G: + val |= u32_encode_bits(CFGCH_BAND1_6G, RR_CFGCH_BAND1) | + u32_encode_bits(CFGCH_BAND0_6G, RR_CFGCH_BAND0); + break; + } + + switch (chan->band_width) { + case RTW89_CHANNEL_WIDTH_5: + case RTW89_CHANNEL_WIDTH_10: + case RTW89_CHANNEL_WIDTH_20: + default: + break; + case RTW89_CHANNEL_WIDTH_40: + val |= u32_encode_bits(CFGCH_BW_V2_40M, RR_CFGCH_BW_V2); + break; + case RTW89_CHANNEL_WIDTH_80: + val |= u32_encode_bits(CFGCH_BW_V2_80M, RR_CFGCH_BW_V2); + break; + case RTW89_CHANNEL_WIDTH_160: + val |= u32_encode_bits(CFGCH_BW_V2_160M, RR_CFGCH_BW_V2); + break; + case RTW89_CHANNEL_WIDTH_320: + val |= u32_encode_bits(CFGCH_BW_V2_320M, RR_CFGCH_BW_V2); + break; + } + + return val; +} + static void rtw8922a_btc_set_rfe(struct rtw89_dev *rtwdev) { union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo; @@ -2761,6 +2803,7 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = { .set_txpwr_ctrl = rtw8922a_set_txpwr_ctrl, .init_txpwr_unit = NULL, .get_thermal = rtw8922a_get_thermal, + .chan_to_rf18_val = rtw8922a_chan_to_rf18_val, .ctrl_btg_bt_rx = rtw8922a_ctrl_btg_bt_rx, .query_ppdu = rtw8922a_query_ppdu, .convert_rpl_to_rssi = rtw8922a_convert_rpl_to_rssi, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c index 1659ea64ade11..fce094c7ce939 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c @@ -36,8 +36,7 @@ void rtw8922a_tssi_cont_en_phyidx(struct rtw89_dev *rtwdev, bool en, u8 phy_idx) static void rtw8922a_ctl_band_ch_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, - u8 central_ch, enum rtw89_band band, - enum rtw89_bandwidth bw) + const struct rtw89_chan *chan) { const u32 rf_addr[2] = {RR_CFGCH, RR_CFGCH_V1}; struct rtw89_hal *hal = &rtwdev->hal; @@ -73,49 +72,9 @@ void rtw8922a_ctl_band_ch_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, return; } - rf_reg[path][i] &= ~(RR_CFGCH_BAND1 | RR_CFGCH_BW | + rf_reg[path][i] &= ~(RR_CFGCH_BAND1 | RR_CFGCH_BW_V2 | RR_CFGCH_BAND0 | RR_CFGCH_CH); - rf_reg[path][i] |= u32_encode_bits(central_ch, RR_CFGCH_CH); - - switch (band) { - case RTW89_BAND_2G: - default: - break; - case RTW89_BAND_5G: - rf_reg[path][i] |= - u32_encode_bits(CFGCH_BAND1_5G, RR_CFGCH_BAND1) | - u32_encode_bits(CFGCH_BAND0_5G, RR_CFGCH_BAND0); - break; - case RTW89_BAND_6G: - rf_reg[path][i] |= - u32_encode_bits(CFGCH_BAND1_6G, RR_CFGCH_BAND1) | - u32_encode_bits(CFGCH_BAND0_6G, RR_CFGCH_BAND0); - break; - } - - switch (bw) { - case RTW89_CHANNEL_WIDTH_5: - case RTW89_CHANNEL_WIDTH_10: - case RTW89_CHANNEL_WIDTH_20: - default: - break; - case RTW89_CHANNEL_WIDTH_40: - rf_reg[path][i] |= - u32_encode_bits(CFGCH_BW_V2_40M, RR_CFGCH_BW_V2); - break; - case RTW89_CHANNEL_WIDTH_80: - rf_reg[path][i] |= - u32_encode_bits(CFGCH_BW_V2_80M, RR_CFGCH_BW_V2); - break; - case RTW89_CHANNEL_WIDTH_160: - rf_reg[path][i] |= - u32_encode_bits(CFGCH_BW_V2_160M, RR_CFGCH_BW_V2); - break; - case RTW89_CHANNEL_WIDTH_320: - rf_reg[path][i] |= - u32_encode_bits(CFGCH_BW_V2_320M, RR_CFGCH_BW_V2); - break; - } + rf_reg[path][i] |= rtw89_chip_chan_to_rf18_val(rtwdev, chan); rtw89_write_rf(rtwdev, path, rf_addr[i], RFREG_MASK, rf_reg[path][i]); @@ -126,7 +85,7 @@ void rtw8922a_ctl_band_ch_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, if (hal->cv != CHIP_CAV) return; - if (band == RTW89_BAND_2G) { + if (chan->band_type == RTW89_BAND_2G) { rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x80000); rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x00003); rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD1, RFREG_MASK, 0x0c990); @@ -145,8 +104,7 @@ void rtw8922a_set_channel_rf(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, enum rtw89_phy_idx phy_idx) { - rtw8922a_ctl_band_ch_bw(rtwdev, phy_idx, chan->channel, chan->band_type, - chan->band_width); + rtw8922a_ctl_band_ch_bw(rtwdev, phy_idx, chan); } enum _rf_syn_pow { -- 2.51.0 From 389e578dd2803099f78d2ec1fe680d0fb0f3f66c Mon Sep 17 00:00:00 2001 From: Kuan-Chung Chen Date: Fri, 6 Jun 2025 10:04:37 +0800 Subject: [PATCH 06/16] wifi: rtw89: 8922a: pass channel information when enter LPS Newer firmware requires the driver to pass channel information when switching from normal mode to low power mode; otherwise it will result in poor RX beacon performance. Signed-off-by: Kuan-Chung Chen Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250606020437.17160-1-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/fw.c | 59 +++++++++++++++++++++++++ drivers/net/wireless/realtek/rtw89/fw.h | 8 ++++ drivers/net/wireless/realtek/rtw89/ps.c | 2 + 3 files changed, 69 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 0547eb11d3782..95865eafb2cd6 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -5919,6 +5919,65 @@ fail: } EXPORT_SYMBOL(rtw89_fw_h2c_rf_ntfy_mcc); +int rtw89_fw_h2c_rf_ps_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_h2c_rf_ps_info *h2c; + const struct rtw89_chan *chan; + u32 len = sizeof(*h2c); + unsigned int link_id; + struct sk_buff *skb; + int ret; + u8 path; + u32 val; + + if (chip->chip_gen != RTW89_CHIP_BE) + return 0; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for h2c rf ps info\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_rf_ps_info *)skb->data; + h2c->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode); + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + path = rtw89_phy_get_syn_sel(rtwdev, rtwvif_link->phy_idx); + val = rtw89_chip_chan_to_rf18_val(rtwdev, chan); + + if (path >= chip->rf_path_num) { + rtw89_err(rtwdev, "unsupported rf path (%d)\n", path); + ret = -ENOENT; + goto fail; + } + + h2c->rf18[path] = cpu_to_le32(val); + h2c->pri_ch[path] = chan->primary_channel; + } + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_NOTIFY, + H2C_FUNC_OUTSRC_RF_PS_INFO, 0, 0, + sizeof(*h2c)); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} +EXPORT_SYMBOL(rtw89_fw_h2c_rf_ps_info); + int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index d4815bcce91bc..14f55b10be2ea 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -4337,6 +4337,7 @@ enum rtw89_mrc_h2c_func { #define H2C_CL_OUTSRC_RF_REG_B 0x9 #define H2C_CL_OUTSRC_RF_FW_NOTIFY 0xa #define H2C_FUNC_OUTSRC_RF_GET_MCCCH 0x2 +#define H2C_FUNC_OUTSRC_RF_PS_INFO 0x10 #define H2C_CL_OUTSRC_RF_FW_RFK 0xb enum rtw89_rfk_offload_h2c_func { @@ -4361,6 +4362,12 @@ struct rtw89_fw_h2c_rf_get_mccch { #define NUM_OF_RTW89_FW_RFK_PATH 2 #define NUM_OF_RTW89_FW_RFK_TBL 3 +struct rtw89_h2c_rf_ps_info { + __le32 rf18[NUM_OF_RTW89_FW_RFK_PATH]; + __le32 mlo_mode; + u8 pri_ch[NUM_OF_RTW89_FW_RFK_PATH]; +} __packed; + struct rtw89_fw_h2c_rfk_pre_info_common { struct { __le32 ch[NUM_OF_RTW89_FW_RFK_PATH][NUM_OF_RTW89_FW_RFK_TBL]; @@ -4744,6 +4751,7 @@ int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev, struct rtw89_fw_h2c_rf_reg_info *info, u16 len, u8 page); int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev); +int rtw89_fw_h2c_rf_ps_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); int rtw89_fw_h2c_rf_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c index 8e4fe73e7d775..c255c2f9b9458 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.c +++ b/drivers/net/wireless/realtek/rtw89/ps.c @@ -137,6 +137,8 @@ void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, can_ps_mode = false; } + rtw89_fw_h2c_rf_ps_info(rtwdev, rtwvif); + if (RTW89_CHK_FW_FEATURE(LPS_CH_INFO, &rtwdev->fw)) rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif); else -- 2.51.0 From 57d6be36cf422e259955d72d994fd1fb668104f8 Mon Sep 17 00:00:00 2001 From: Bitterblue Smith Date: Sat, 7 Jun 2025 20:59:53 +0300 Subject: [PATCH 07/16] wifi: rtw88: Rename the RTW_WCPU_11{AC,N} enums The RTW_WCPU_11AC and RTW_WCPU_11N enums are used to identify two types of microcontrollers used in Realtek chips, but these names are misleading. The "11AC" type was also used in 11n devices (e.g. RTL8733BU, not supported by rtw88), and the "11N" type was also used in 11ac devices (RTL8821AU, RTL8812AU). Rename RTW_WCPU_11AC to RTW_WCPU_3081 and RTW_WCPU_11N to RTW_WCPU_8051. (8051 is well known. It's less clear what 3081 is, but the out of tree drivers use this name.) Signed-off-by: Bitterblue Smith Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/bfb1099c-db52-4b25-b111-17ab712e9404@gmail.com --- drivers/net/wireless/realtek/rtw88/fw.c | 8 +++---- drivers/net/wireless/realtek/rtw88/mac.c | 22 +++++++++---------- drivers/net/wireless/realtek/rtw88/main.c | 2 +- drivers/net/wireless/realtek/rtw88/main.h | 12 +++++----- drivers/net/wireless/realtek/rtw88/pci.c | 12 +++++----- drivers/net/wireless/realtek/rtw88/rtw8703b.c | 2 +- drivers/net/wireless/realtek/rtw88/rtw8723d.c | 2 +- drivers/net/wireless/realtek/rtw88/rtw8812a.c | 2 +- drivers/net/wireless/realtek/rtw88/rtw8814a.c | 2 +- drivers/net/wireless/realtek/rtw88/rtw8821a.c | 2 +- drivers/net/wireless/realtek/rtw88/rtw8821c.c | 2 +- drivers/net/wireless/realtek/rtw88/rtw8822b.c | 2 +- drivers/net/wireless/realtek/rtw88/rtw8822c.c | 2 +- drivers/net/wireless/realtek/rtw88/sdio.c | 8 +++---- 14 files changed, 40 insertions(+), 40 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 4fc78b8820803..c68a9fff68082 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -521,7 +521,7 @@ rtw_fw_send_general_info(struct rtw_dev *rtwdev) u8 h2c_pkt[H2C_PKT_SIZE] = {0}; u16 total_size = H2C_PKT_HDR_SIZE + 4; - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return; rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_GENERAL_INFO); @@ -544,7 +544,7 @@ rtw_fw_send_phydm_info(struct rtw_dev *rtwdev) u16 total_size = H2C_PKT_HDR_SIZE + 8; u8 fw_rf_type = 0; - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return; if (hal->rf_type == RF_1T1R) @@ -1480,7 +1480,7 @@ int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, bckp[2] = rtw_read8(rtwdev, REG_BCN_CTRL); - if (rtw_chip_wcpu_11n(rtwdev)) { + if (rtw_chip_wcpu_8051(rtwdev)) { rtw_write32_set(rtwdev, REG_DWBCN0_CTRL, BIT_BCN_VALID); } else { pg_addr &= BIT_MASK_BCN_HEAD_1_V1; @@ -1509,7 +1509,7 @@ int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, goto restore; } - if (rtw_chip_wcpu_11n(rtwdev)) { + if (rtw_chip_wcpu_8051(rtwdev)) { bcn_valid_addr = REG_DWBCN0_CTRL; bcn_valid_mask = BIT_BCN_VALID; } else { diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c index f66d1b302dc50..011b81c82f3ba 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.c +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -41,7 +41,7 @@ void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw, } rtw_write32(rtwdev, REG_WMAC_TRXPTCL_CTL, value32); - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return; value32 = rtw_read32(rtwdev, REG_AFE_CTRL1) & ~(BIT_MAC_CLK_SEL); @@ -67,7 +67,7 @@ static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev) rtw_write8(rtwdev, REG_RSV_CTRL, 0); - if (rtw_chip_wcpu_11n(rtwdev)) { + if (rtw_chip_wcpu_8051(rtwdev)) { if (rtw_read32(rtwdev, REG_SYS_CFG1) & BIT_LDO) rtw_write8(rtwdev, REG_LDO_SWR_CTRL, LDO_SEL); else @@ -278,7 +278,7 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) bool cur_pwr; int ret; - if (rtw_chip_wcpu_11ac(rtwdev)) { + if (rtw_chip_wcpu_3081(rtwdev)) { rpwm = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr); /* Check FW still exist or not */ @@ -369,7 +369,7 @@ static int __rtw_mac_init_system_cfg_legacy(struct rtw_dev *rtwdev) static int rtw_mac_init_system_cfg(struct rtw_dev *rtwdev) { - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return __rtw_mac_init_system_cfg_legacy(rtwdev); return __rtw_mac_init_system_cfg(rtwdev); @@ -981,7 +981,7 @@ out: static int _rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) { - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return __rtw_download_firmware_legacy(rtwdev, fw); return __rtw_download_firmware(rtwdev, fw); @@ -1122,7 +1122,7 @@ static int txdma_queue_mapping(struct rtw_dev *rtwdev) rtw_write8(rtwdev, REG_CR, 0); rtw_write8(rtwdev, REG_CR, MAC_TRX_ENABLE); - if (rtw_chip_wcpu_11ac(rtwdev)) + if (rtw_chip_wcpu_3081(rtwdev)) rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL); if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) { @@ -1145,7 +1145,7 @@ int rtw_set_trx_fifo_info(struct rtw_dev *rtwdev) /* config rsvd page num */ fifo->rsvd_drv_pg_num = chip->rsvd_drv_pg_num; fifo->txff_pg_num = chip->txff_size / chip->page_size; - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num; else fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num + @@ -1163,7 +1163,7 @@ int rtw_set_trx_fifo_info(struct rtw_dev *rtwdev) fifo->rsvd_boundary = fifo->txff_pg_num - fifo->rsvd_pg_num; cur_pg_addr = fifo->txff_pg_num; - if (rtw_chip_wcpu_11ac(rtwdev)) { + if (rtw_chip_wcpu_3081(rtwdev)) { cur_pg_addr -= csi_buf_pg_num; fifo->rsvd_csibuf_addr = cur_pg_addr; cur_pg_addr -= RSVD_PG_FW_TXBUF_NUM; @@ -1292,7 +1292,7 @@ static int priority_queue_cfg(struct rtw_dev *rtwdev) pubq_num = fifo->acq_pg_num - pg_tbl->hq_num - pg_tbl->lq_num - pg_tbl->nq_num - pg_tbl->exq_num - pg_tbl->gapq_num; - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return __priority_queue_cfg_legacy(rtwdev, pg_tbl, pubq_num); else return __priority_queue_cfg(rtwdev, pg_tbl, pubq_num); @@ -1308,7 +1308,7 @@ static int init_h2c(struct rtw_dev *rtwdev) u32 h2cq_free; u32 wp, rp; - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return 0; h2cq_addr = fifo->rsvd_h2cq_addr << TX_PAGE_SIZE_SHIFT; @@ -1375,7 +1375,7 @@ static int rtw_drv_info_cfg(struct rtw_dev *rtwdev) u8 value8; rtw_write8(rtwdev, REG_RX_DRVINFO_SZ, PHY_STATUS_SIZE); - if (rtw_chip_wcpu_11ac(rtwdev)) { + if (rtw_chip_wcpu_3081(rtwdev)) { value8 = rtw_read8(rtwdev, REG_TRXFF_BNDY + 1); value8 &= 0xF0; /* For rxdesc len = 0 issue */ diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 26b1479d35213..3ec3689fae3db 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -1766,7 +1766,7 @@ static void __update_firmware_info_legacy(struct rtw_dev *rtwdev, static void update_firmware_info(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) { - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) __update_firmware_info_legacy(rtwdev, fw); else __update_firmware_info(rtwdev, fw); diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index b0f1fabe95545..89b72d2a9f993 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -1173,8 +1173,8 @@ struct rtw_pwr_track_tbl { }; enum rtw_wlan_cpu { - RTW_WCPU_11AC, - RTW_WCPU_11N, + RTW_WCPU_3081, + RTW_WCPU_8051, }; enum rtw_fw_fifo_sel { @@ -2166,14 +2166,14 @@ static inline void rtw_chip_efuse_grant_off(struct rtw_dev *rtwdev) rtwdev->chip->ops->efuse_grant(rtwdev, false); } -static inline bool rtw_chip_wcpu_11n(struct rtw_dev *rtwdev) +static inline bool rtw_chip_wcpu_8051(struct rtw_dev *rtwdev) { - return rtwdev->chip->wlan_cpu == RTW_WCPU_11N; + return rtwdev->chip->wlan_cpu == RTW_WCPU_8051; } -static inline bool rtw_chip_wcpu_11ac(struct rtw_dev *rtwdev) +static inline bool rtw_chip_wcpu_3081(struct rtw_dev *rtwdev) { - return rtwdev->chip->wlan_cpu == RTW_WCPU_11AC; + return rtwdev->chip->wlan_cpu == RTW_WCPU_3081; } static inline bool rtw_chip_has_rx_ldpc(struct rtw_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index 6655de2b9726e..56b16186d3aa4 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -405,7 +405,7 @@ static void rtw_pci_reset_buf_desc(struct rtw_dev *rtwdev) dma = rtwpci->tx_rings[RTW_TX_QUEUE_BCN].r.dma; rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_BCNQ, dma); - if (!rtw_chip_wcpu_11n(rtwdev)) { + if (!rtw_chip_wcpu_8051(rtwdev)) { len = rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.len; dma = rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.dma; rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.rp = 0; @@ -467,7 +467,7 @@ static void rtw_pci_reset_buf_desc(struct rtw_dev *rtwdev) rtw_write32(rtwdev, RTK_PCI_TXBD_RWPTR_CLR, 0xffffffff); /* reset H2C Queue index in a single write */ - if (rtw_chip_wcpu_11ac(rtwdev)) + if (rtw_chip_wcpu_3081(rtwdev)) rtw_write32_set(rtwdev, RTK_PCI_TXBD_H2CQ_CSR, BIT_CLR_H2CQ_HOST_IDX | BIT_CLR_H2CQ_HW_IDX); } @@ -487,7 +487,7 @@ static void rtw_pci_enable_interrupt(struct rtw_dev *rtwdev, rtw_write32(rtwdev, RTK_PCI_HIMR0, rtwpci->irq_mask[0] & ~imr0_unmask); rtw_write32(rtwdev, RTK_PCI_HIMR1, rtwpci->irq_mask[1]); - if (rtw_chip_wcpu_11ac(rtwdev)) + if (rtw_chip_wcpu_3081(rtwdev)) rtw_write32(rtwdev, RTK_PCI_HIMR3, rtwpci->irq_mask[3]); rtwpci->irq_enabled = true; @@ -507,7 +507,7 @@ static void rtw_pci_disable_interrupt(struct rtw_dev *rtwdev, rtw_write32(rtwdev, RTK_PCI_HIMR0, 0); rtw_write32(rtwdev, RTK_PCI_HIMR1, 0); - if (rtw_chip_wcpu_11ac(rtwdev)) + if (rtw_chip_wcpu_3081(rtwdev)) rtw_write32(rtwdev, RTK_PCI_HIMR3, 0); rtwpci->irq_enabled = false; @@ -1125,7 +1125,7 @@ static void rtw_pci_irq_recognized(struct rtw_dev *rtwdev, irq_status[0] = rtw_read32(rtwdev, RTK_PCI_HISR0); irq_status[1] = rtw_read32(rtwdev, RTK_PCI_HISR1); - if (rtw_chip_wcpu_11ac(rtwdev)) + if (rtw_chip_wcpu_3081(rtwdev)) irq_status[3] = rtw_read32(rtwdev, RTK_PCI_HISR3); else irq_status[3] = 0; @@ -1134,7 +1134,7 @@ static void rtw_pci_irq_recognized(struct rtw_dev *rtwdev, irq_status[3] &= rtwpci->irq_mask[3]; rtw_write32(rtwdev, RTK_PCI_HISR0, irq_status[0]); rtw_write32(rtwdev, RTK_PCI_HISR1, irq_status[1]); - if (rtw_chip_wcpu_11ac(rtwdev)) + if (rtw_chip_wcpu_3081(rtwdev)) rtw_write32(rtwdev, RTK_PCI_HISR3, irq_status[3]); spin_unlock_irqrestore(&rtwpci->hwirq_lock, flags); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8703b.c b/drivers/net/wireless/realtek/rtw88/rtw8703b.c index 9e6700c43a631..03475af973b52 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c @@ -1882,7 +1882,7 @@ const struct rtw_chip_info rtw8703b_hw_spec = { .id = RTW_CHIP_TYPE_8703B, .fw_name = "rtw88/rtw8703b_fw.bin", - .wlan_cpu = RTW_WCPU_11N, + .wlan_cpu = RTW_WCPU_8051, .tx_pkt_desc_sz = 40, .tx_buf_desc_sz = 16, .rx_pkt_desc_sz = 24, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c index 31876e708f9ef..bf69f5b06ce26 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c @@ -2116,7 +2116,7 @@ const struct rtw_chip_info rtw8723d_hw_spec = { .ops = &rtw8723d_ops, .id = RTW_CHIP_TYPE_8723D, .fw_name = "rtw88/rtw8723d_fw.bin", - .wlan_cpu = RTW_WCPU_11N, + .wlan_cpu = RTW_WCPU_8051, .tx_pkt_desc_sz = 40, .tx_buf_desc_sz = 16, .rx_pkt_desc_sz = 24, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a.c b/drivers/net/wireless/realtek/rtw88/rtw8812a.c index c2ef41767ff93..03b441639611f 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8812a.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8812a.c @@ -1038,7 +1038,7 @@ const struct rtw_chip_info rtw8812a_hw_spec = { .ops = &rtw8812a_ops, .id = RTW_CHIP_TYPE_8812A, .fw_name = "rtw88/rtw8812a_fw.bin", - .wlan_cpu = RTW_WCPU_11N, + .wlan_cpu = RTW_WCPU_8051, .tx_pkt_desc_sz = 40, .tx_buf_desc_sz = 16, .rx_pkt_desc_sz = 24, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8814a.c b/drivers/net/wireless/realtek/rtw88/rtw8814a.c index 44dd3090484b8..4a1f850d05c87 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8814a.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8814a.c @@ -2180,7 +2180,7 @@ const struct rtw_chip_info rtw8814a_hw_spec = { .ops = &rtw8814a_ops, .id = RTW_CHIP_TYPE_8814A, .fw_name = "rtw88/rtw8814a_fw.bin", - .wlan_cpu = RTW_WCPU_11AC, + .wlan_cpu = RTW_WCPU_3081, .tx_pkt_desc_sz = 40, .tx_buf_desc_sz = 16, .rx_pkt_desc_sz = 24, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a.c b/drivers/net/wireless/realtek/rtw88/rtw8821a.c index 413aec694c33a..1d02ea400b2e6 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821a.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821a.c @@ -1138,7 +1138,7 @@ const struct rtw_chip_info rtw8821a_hw_spec = { .ops = &rtw8821a_ops, .id = RTW_CHIP_TYPE_8821A, .fw_name = "rtw88/rtw8821a_fw.bin", - .wlan_cpu = RTW_WCPU_11N, + .wlan_cpu = RTW_WCPU_8051, .tx_pkt_desc_sz = 40, .tx_buf_desc_sz = 16, .rx_pkt_desc_sz = 24, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c index 413130a30ca91..a2a358d6033f6 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c @@ -1973,7 +1973,7 @@ const struct rtw_chip_info rtw8821c_hw_spec = { .ops = &rtw8821c_ops, .id = RTW_CHIP_TYPE_8821C, .fw_name = "rtw88/rtw8821c_fw.bin", - .wlan_cpu = RTW_WCPU_11AC, + .wlan_cpu = RTW_WCPU_3081, .tx_pkt_desc_sz = 48, .tx_buf_desc_sz = 16, .rx_pkt_desc_sz = 24, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index ab199eaea3c76..9c31c859ccbac 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -2513,7 +2513,7 @@ const struct rtw_chip_info rtw8822b_hw_spec = { .ops = &rtw8822b_ops, .id = RTW_CHIP_TYPE_8822B, .fw_name = "rtw88/rtw8822b_fw.bin", - .wlan_cpu = RTW_WCPU_11AC, + .wlan_cpu = RTW_WCPU_3081, .tx_pkt_desc_sz = 48, .tx_buf_desc_sz = 16, .rx_pkt_desc_sz = 24, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 017d959de3ce7..f813ce10172d7 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -5332,7 +5332,7 @@ const struct rtw_chip_info rtw8822c_hw_spec = { .ops = &rtw8822c_ops, .id = RTW_CHIP_TYPE_8822C, .fw_name = "rtw88/rtw8822c_fw.bin", - .wlan_cpu = RTW_WCPU_11AC, + .wlan_cpu = RTW_WCPU_3081, .tx_pkt_desc_sz = 48, .tx_buf_desc_sz = 16, .rx_pkt_desc_sz = 24, diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c index e733ed846123e..cc2d4fef35879 100644 --- a/drivers/net/wireless/realtek/rtw88/sdio.c +++ b/drivers/net/wireless/realtek/rtw88/sdio.c @@ -547,7 +547,7 @@ static int rtw_sdio_check_free_txpg(struct rtw_dev *rtwdev, u8 queue, { unsigned int pages_free, pages_needed; - if (rtw_chip_wcpu_11n(rtwdev)) { + if (rtw_chip_wcpu_8051(rtwdev)) { u32 free_txpg; free_txpg = rtw_sdio_read32(rtwdev, REG_SDIO_FREE_TXPG); @@ -1030,7 +1030,7 @@ static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev) u32 rx_len, hisr, total_rx_bytes = 0; do { - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) rx_len = rtw_read16(rtwdev, REG_SDIO_RX0_REQ_LEN); else rx_len = rtw_read32(rtwdev, REG_SDIO_RX0_REQ_LEN); @@ -1042,7 +1042,7 @@ static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev) total_rx_bytes += rx_len; - if (rtw_chip_wcpu_11n(rtwdev)) { + if (rtw_chip_wcpu_8051(rtwdev)) { /* Stop if no more RX requests are pending, even if * rx_len could be greater than zero in the next * iteration. This is needed because the RX buffer may @@ -1054,7 +1054,7 @@ static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev) */ hisr = rtw_read32(rtwdev, REG_SDIO_HISR); } else { - /* RTW_WCPU_11AC chips have improved hardware or + /* RTW_WCPU_3081 chips have improved hardware or * firmware and can use rx_len unconditionally. */ hisr = REG_SDIO_HISR_RX_REQUEST; -- 2.51.0 From 793905c70a56255b04e7cff82b01a300fff822be Mon Sep 17 00:00:00 2001 From: Bitterblue Smith Date: Sat, 7 Jun 2025 21:01:38 +0300 Subject: [PATCH 08/16] wifi: rtw88: Enable AP and adhoc modes for SDIO again AP mode can be enabled again for SDIO now that the problem was fixed in commit b2effcdc2379 ("wifi: rtw88: sdio: map mgmt frames to queue TX_DESC_QSEL_MGMT") and commit fc5f5a0ec463 ("wifi: rtw88: sdio: call rtw_sdio_indicate_tx_status unconditionally"). Signed-off-by: Bitterblue Smith Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/5ac60c1c-9cc8-41b8-871c-a067e74f70ea@gmail.com --- drivers/net/wireless/realtek/rtw88/main.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 3ec3689fae3db..97756bdf57b27 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -2219,7 +2219,6 @@ EXPORT_SYMBOL(rtw_core_deinit); int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) { - bool sta_mode_only = rtwdev->hci.type == RTW_HCI_TYPE_SDIO; struct rtw_hal *hal = &rtwdev->hal; int max_tx_headroom = 0; int ret; @@ -2249,12 +2248,9 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) ieee80211_hw_set(hw, TX_AMSDU); ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); - if (sta_mode_only) - hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - else - hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_ADHOC); + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->available_antennas_tx = hal->antenna_tx; hw->wiphy->available_antennas_rx = hal->antenna_rx; @@ -2265,7 +2261,7 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) hw->wiphy->max_scan_ssids = RTW_SCAN_MAX_SSIDS; hw->wiphy->max_scan_ie_len = rtw_get_max_scan_ie_len(rtwdev); - if (!sta_mode_only && rtwdev->chip->id == RTW_CHIP_TYPE_8822C) { + if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C) { hw->wiphy->iface_combinations = rtw_iface_combs; hw->wiphy->n_iface_combinations = ARRAY_SIZE(rtw_iface_combs); } -- 2.51.0 From 2baacfe833460fee2f54b2c7270d632c98052cdc Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 10 Jun 2025 11:22:23 +0200 Subject: [PATCH 09/16] wifi: rtlwifi: avoid stack size warning for _read_eeprom_info txpower_info_{2g,5g} are too big to fit on the stack, but in most of the rtlwifi variants this stays below the warning limit for stack frames. In rtl8192ee and a few others, I see a case where clang decides to fully inline this into rtl92ee_read_eeprom_info, triggering this warning: drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c:2178:6: error: stack frame size (1312) exceeds limit (1280) in 'rtl92ee_read_eeprom_info' [-Werror,-Wframe-larger-than] Mark _rtl92ee_read_txpower_info_from_hwpg() as noinline_for_stack to and mark _rtl92ee_get_chnl_group() as __always_inline to make clang behave the same way as gcc. Inlining _rtl92ee_get_chnl_group helps let the compiler see that the index is always in range. The same change appears to be necessary in all rtlwifi variants. A more thorough approach would be to avoid the use of the two structures on the stack entirely and combine them with the struct rtl_efuse data that is dynamically allocated and holds the same information. Signed-off-by: Arnd Bergmann Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250610092240.2639751-1-arnd@kernel.org --- drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c | 6 +++--- drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c | 6 +++--- drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c | 6 +++--- drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c | 7 ++++--- drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c | 6 +++--- drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c | 6 +++--- drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c | 6 +++--- 7 files changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c index 27f6c35ba0f9f..4092018452cb3 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c @@ -1738,9 +1738,9 @@ static void read_power_value_fromprom(struct ieee80211_hw *hw, } } -static void _rtl88ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) +static noinline_for_stack void +_rtl88ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c index 0bc915723b939..5ca6b49e73c72 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c @@ -1412,9 +1412,9 @@ void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, rtl92ce_enable_interrupt(hw); } -static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) +static noinline_for_stack void +_rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c index 0195c9a3e9e86..ec5d558609fee 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c @@ -95,9 +95,9 @@ static void _rtl92cu_phy_param_tab_init(struct ieee80211_hw *hw) } } -static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) +static noinline_for_stack void +_rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c index d4da5cdc84143..48a3c94606bef 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c @@ -1731,7 +1731,7 @@ void rtl92ee_update_interrupt_mask(struct ieee80211_hw *hw, rtl92ee_enable_interrupt(hw); } -static u8 _rtl92ee_get_chnl_group(u8 chnl) +static __always_inline u8 _rtl92ee_get_chnl_group(u8 chnl) { u8 group = 0; @@ -2009,8 +2009,9 @@ static void _rtl8192ee_read_power_value_fromprom(struct ieee80211_hw *hw, } } -static void _rtl92ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, u8 *hwinfo) +static noinline_for_stack void +_rtl92ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *efu = rtl_efuse(rtl_priv(hw)); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c index 6991713a66d01..21b827f519b64 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c @@ -1381,9 +1381,9 @@ static u8 _rtl8723e_get_chnl_group(u8 chnl) return group; } -static void _rtl8723e_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) +static noinline_for_stack void +_rtl8723e_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c index bcfc53af4c1a1..e1f8112188949 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c @@ -1935,9 +1935,9 @@ static void _rtl8723be_read_power_value_fromprom(struct ieee80211_hw *hw, } } -static void _rtl8723be_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) +static noinline_for_stack void +_rtl8723be_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c index f4b232f038a93..8c51f4d368202 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c @@ -2782,9 +2782,9 @@ static void _rtl8812ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); } #endif -static void _rtl8821ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) +static noinline_for_stack void +_rtl8821ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -- 2.51.0 From 9b550b98f0da3ba80e63c431e0cf4d7ae32c865b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 11 Jun 2025 14:55:21 +0100 Subject: [PATCH 10/16] wifi: rtlwifi: rtl8821ae: make the read-only array params static const Don't populate the read-only array params on the stack at run time, instead make it static const. Signed-off-by: Colin Ian King Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250611135521.172521-1-colin.i.king@gmail.com --- drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c index 8c51f4d368202..a5a34b5edcfdb 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c @@ -3064,10 +3064,12 @@ static void _rtl8821ae_read_adapter_info(struct ieee80211_hw *hw, bool b_pseudo_ struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - int params[] = {RTL_EEPROM_ID, EEPROM_VID, EEPROM_DID, - EEPROM_SVID, EEPROM_SMID, EEPROM_MAC_ADDR, - EEPROM_CHANNELPLAN, EEPROM_VERSION, EEPROM_CUSTOMER_ID, - COUNTRY_CODE_WORLD_WIDE_13}; + static const int params[] = { + RTL_EEPROM_ID, EEPROM_VID, EEPROM_DID, + EEPROM_SVID, EEPROM_SMID, EEPROM_MAC_ADDR, + EEPROM_CHANNELPLAN, EEPROM_VERSION, EEPROM_CUSTOMER_ID, + COUNTRY_CODE_WORLD_WIDE_13 + }; u8 *hwinfo; if (b_pseudo_test) { -- 2.51.0 From 76b3e5078d76f0eeadb7aacf9845399f8473da0d Mon Sep 17 00:00:00 2001 From: Thomas Fourier Date: Fri, 13 Jun 2025 09:38:36 +0200 Subject: [PATCH 11/16] wifi: rtlwifi: fix possible skb memory leak in _rtl_pci_init_one_rxdesc() When `dma_mapping_error()` is true, if a new `skb` has been allocated, then it must be de-allocated. Compile tested only Signed-off-by: Thomas Fourier Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250613074014.69856-2-fourier.thomas@gmail.com --- drivers/net/wireless/realtek/rtlwifi/pci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index 898f597f70a96..472072630f8d4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -572,8 +572,11 @@ remap: dma_map_single(&rtlpci->pdev->dev, skb_tail_pointer(skb), rtlpci->rxbuffersize, DMA_FROM_DEVICE); bufferaddress = *((dma_addr_t *)skb->cb); - if (dma_mapping_error(&rtlpci->pdev->dev, bufferaddress)) + if (dma_mapping_error(&rtlpci->pdev->dev, bufferaddress)) { + if (!new_skb) + kfree_skb(skb); return 0; + } rtlpci->rx_ring[rxring_idx].rx_buf[desc_idx] = skb; if (rtlpriv->use_new_trx_flow) { /* skb->cb may be 64 bit address */ -- 2.51.0 From dbaf5c3aa952ad0dcf5c21431bd534cff1cfad1f Mon Sep 17 00:00:00 2001 From: Zong-Zhe Yang Date: Tue, 10 Jun 2025 21:00:23 +0800 Subject: [PATCH 12/16] wifi: rtw89: extend HW scan of WiFi 6 chips for extra OP chan when concurrency HW scan flow has considered the timing when to get back op for the scanning interface. But, when concurrency, there are two interfaces with connection. The OP channel of another one was not back originally. It then easily lead to connection loss when scanning during concurrency. So, HW scan flow is extended to deal with second OP channel. And, H2C command is also extended to fill second MAC ID. The changes mentioned above are done for WiFi 6 chips first. HW scan has different handling architectures including FW and driver on WiFi 7 chips. Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250610130034.14692-2-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 8 ++ drivers/net/wireless/realtek/rtw89/fw.c | 136 +++++++++++++++++++--- drivers/net/wireless/realtek/rtw89/fw.h | 7 +- drivers/net/wireless/realtek/rtw89/mac.c | 66 +++++++++-- 4 files changed, 191 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index c93d3ea2b0a41..dca76b1c10294 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -4524,6 +4524,7 @@ enum rtw89_fw_feature { RTW89_FW_FEATURE_NO_PHYCAP_P1, RTW89_FW_FEATURE_NO_POWER_DIFFERENCE, RTW89_FW_FEATURE_BEACON_LOSS_COUNT_V1, + RTW89_FW_FEATURE_SCAN_OFFLOAD_EXTRA_OP, }; struct rtw89_fw_suit { @@ -5451,11 +5452,18 @@ struct rtw89_early_h2c { u16 h2c_len; }; +struct rtw89_hw_scan_extra_op { + bool set; + u8 macid; + struct rtw89_chan chan; +}; + struct rtw89_hw_scan_info { struct rtw89_vif_link *scanning_vif; struct list_head pkt_list[NUM_NL80211_BANDS]; struct list_head chan_list; struct rtw89_chan op_chan; + struct rtw89_hw_scan_extra_op extra_op; bool connected; bool abort; }; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 95865eafb2cd6..06fb97a05a897 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -5363,6 +5363,7 @@ static int rtw89_fw_h2c_scan_list_offload_ax(struct rtw89_dev *rtwdev, int ch_num, struct list_head *chan_list) { + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; struct rtw89_h2c_chinfo_elem *elem; struct rtw89_mac_chinfo_ax *ch_info; @@ -5405,6 +5406,10 @@ int rtw89_fw_h2c_scan_list_offload_ax(struct rtw89_dev *rtwdev, int ch_num, le32_encode_bits(ch_info->tx_null, RTW89_H2C_CHINFO_W1_TX_NULL) | le32_encode_bits(ch_info->rand_seq_num, RTW89_H2C_CHINFO_W1_RANDOM); + if (scan_info->extra_op.set) + elem->w1 |= le32_encode_bits(ch_info->macid_tx, + RTW89_H2C_CHINFO_W1_MACID_TX); + elem->w2 = le32_encode_bits(ch_info->pkt_id[0], RTW89_H2C_CHINFO_W2_PKT0) | le32_encode_bits(ch_info->pkt_id[1], RTW89_H2C_CHINFO_W2_PKT1) | le32_encode_bits(ch_info->pkt_id[2], RTW89_H2C_CHINFO_W2_PKT2) | @@ -5545,6 +5550,7 @@ int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool wowlan) { + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; struct rtw89_chan *op = &rtwdev->scan_info.op_chan; enum rtw89_scan_mode scan_mode = RTW89_SCAN_IMMEDIATE; @@ -5604,6 +5610,10 @@ int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, h2c->tsf_low = le32_encode_bits(lower_32_bits(tsf), RTW89_H2C_SCANOFLD_W4_TSF_LOW); + if (scan_info->extra_op.set) + h2c->w6 = le32_encode_bits(scan_info->extra_op.macid, + RTW89_H2C_SCANOFLD_W6_SECOND_MACID); + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD, H2C_FUNC_SCANOFLD, 1, 1, @@ -6933,6 +6943,7 @@ static void rtw89_hw_scan_add_chan_ax(struct rtw89_dev *rtwdev, int chan_type, { struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; + const struct rtw89_hw_scan_extra_op *ext = &scan_info->extra_op; struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct ieee80211_scan_ies *ies = rtwvif->scan_ies; struct cfg80211_scan_request *req = rtwvif->scan_req; @@ -7003,6 +7014,15 @@ static void rtw89_hw_scan_add_chan_ax(struct rtw89_dev *rtwdev, int chan_type, case RTW89_CHAN_ACTIVE: ch_info->pause_data = true; break; + case RTW89_CHAN_EXTRA_OP: + ch_info->central_ch = ext->chan.channel; + ch_info->pri_ch = ext->chan.primary_channel; + ch_info->ch_band = ext->chan.band_type; + ch_info->bw = ext->chan.band_width; + ch_info->tx_null = true; + ch_info->num_pkt = 0; + ch_info->macid_tx = true; + break; default: rtw89_err(rtwdev, "Channel type out of bound\n"); } @@ -7161,10 +7181,45 @@ out: return ret; } +static int rtw89_hw_scan_add_op_types_ax(struct rtw89_dev *rtwdev, + enum rtw89_chan_type type, + struct list_head *chan_list, + struct cfg80211_scan_request *req, + int *off_chan_time) +{ + struct rtw89_mac_chinfo_ax *tmp; + + tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + switch (type) { + case RTW89_CHAN_OPERATE: + tmp->period = req->duration_mandatory ? + req->duration : RTW89_CHANNEL_TIME; + *off_chan_time = 0; + break; + case RTW89_CHAN_EXTRA_OP: + tmp->period = RTW89_CHANNEL_TIME_EXTRA_OP; + /* still calc @off_chan_time for scan op */ + *off_chan_time += tmp->period; + break; + default: + kfree(tmp); + return -EINVAL; + } + + rtw89_hw_scan_add_chan_ax(rtwdev, type, 0, tmp); + list_add_tail(&tmp->list, chan_list); + + return 0; +} + int rtw89_hw_scan_prep_chan_list_ax(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; + const struct rtw89_hw_scan_extra_op *ext = &scan_info->extra_op; struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct cfg80211_scan_request *req = rtwvif->scan_req; struct rtw89_mac_chinfo_ax *ch_info, *tmp; @@ -7207,22 +7262,28 @@ int rtw89_hw_scan_prep_chan_list_ax(struct rtw89_dev *rtwdev, type = RTW89_CHAN_ACTIVE; rtw89_hw_scan_add_chan_ax(rtwdev, type, req->n_ssids, ch_info); - if (scan_info->connected && - off_chan_time + ch_info->period > RTW89_OFF_CHAN_TIME) { - tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); - if (!tmp) { - ret = -ENOMEM; - kfree(ch_info); - goto out; - } + if (!(scan_info->connected && + off_chan_time + ch_info->period > RTW89_OFF_CHAN_TIME)) + goto next; - type = RTW89_CHAN_OPERATE; - tmp->period = req->duration_mandatory ? - req->duration : RTW89_CHANNEL_TIME; - rtw89_hw_scan_add_chan_ax(rtwdev, type, 0, tmp); - list_add_tail(&tmp->list, &chan_list); - off_chan_time = 0; + ret = rtw89_hw_scan_add_op_types_ax(rtwdev, RTW89_CHAN_OPERATE, + &chan_list, req, &off_chan_time); + if (ret) { + kfree(ch_info); + goto out; } + + if (!ext->set) + goto next; + + ret = rtw89_hw_scan_add_op_types_ax(rtwdev, RTW89_CHAN_EXTRA_OP, + &chan_list, req, &off_chan_time); + if (ret) { + kfree(ch_info); + goto out; + } + +next: list_add_tail(&ch_info->list, &chan_list); off_chan_time += ch_info->period; } @@ -7524,6 +7585,47 @@ static void rtw89_hw_scan_update_beacon_noa(struct rtw89_dev *rtwdev, } } +static void rtw89_hw_scan_set_extra_op_info(struct rtw89_dev *rtwdev, + struct rtw89_vif *scan_rtwvif, + const struct rtw89_chan *scan_op) +{ + struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt; + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; + struct rtw89_hw_scan_extra_op *ext = &scan_info->extra_op; + struct rtw89_vif *tmp; + + ext->set = false; + if (!RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD_EXTRA_OP, &rtwdev->fw)) + return; + + list_for_each_entry(tmp, &mgnt->active_list, mgnt_entry) { + const struct rtw89_chan *tmp_chan; + struct rtw89_vif_link *tmp_link; + + if (tmp == scan_rtwvif) + continue; + + tmp_link = rtw89_vif_get_link_inst(tmp, 0); + if (unlikely(!tmp_link)) { + rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN, + "hw scan: no HW-0 link for extra op\n"); + continue; + } + + tmp_chan = rtw89_chan_get(rtwdev, tmp_link->chanctx_idx); + *ext = (struct rtw89_hw_scan_extra_op){ + .set = true, + .macid = tmp_link->mac_id, + .chan = *tmp_chan, + }; + + rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN, + "hw scan: extra op: center %d primary %d\n", + ext->chan.channel, ext->chan.primary_channel); + break; + } +} + int rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct ieee80211_scan_request *scan_req) @@ -7546,6 +7648,12 @@ int rtw89_hw_scan_start(struct rtw89_dev *rtwdev, /* clone op and keep it during scan */ rtwdev->scan_info.op_chan = *chan; + rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN, + "hw scan: op: center %d primary %d\n", + chan->channel, chan->primary_channel); + + rtw89_hw_scan_set_extra_op_info(rtwdev, rtwvif, chan); + rtwdev->scan_info.connected = rtw89_is_any_vif_connected_or_connecting(rtwdev); rtwdev->scan_info.scanning_vif = rtwvif_link; rtwdev->scan_info.abort = false; diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 14f55b10be2ea..36abf1b592400 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -237,6 +237,7 @@ enum rtw89_chan_type { RTW89_CHAN_OPERATE = 0, RTW89_CHAN_ACTIVE, RTW89_CHAN_DFS, + RTW89_CHAN_EXTRA_OP, }; enum rtw89_p2pps_action { @@ -316,6 +317,7 @@ struct rtw89_fw_macid_pause_sleep_grp { #define RTW89_H2C_MAX_SIZE 2048 #define RTW89_CHANNEL_TIME 45 #define RTW89_CHANNEL_TIME_6G 20 +#define RTW89_CHANNEL_TIME_EXTRA_OP 30 #define RTW89_DFS_CHAN_TIME 105 #define RTW89_OFF_CHAN_TIME 100 #define RTW89_DWELL_TIME 20 @@ -352,7 +354,8 @@ struct rtw89_mac_chinfo_ax { u8 tx_null:1; u8 rand_seq_num:1; u8 cfg_tx_pwr:1; - u8 rsvd0: 4; + u8 macid_tx: 1; + u8 rsvd0: 3; u8 pkt_id[RTW89_SCANOFLD_MAX_SSID]; u16 tx_pwr_idx; u8 rsvd1; @@ -2674,6 +2677,7 @@ struct rtw89_h2c_chinfo_elem { #define RTW89_H2C_CHINFO_W1_TX_NULL BIT(25) #define RTW89_H2C_CHINFO_W1_RANDOM BIT(26) #define RTW89_H2C_CHINFO_W1_CFG_TX BIT(27) +#define RTW89_H2C_CHINFO_W1_MACID_TX BIT(29) #define RTW89_H2C_CHINFO_W2_PKT0 GENMASK(7, 0) #define RTW89_H2C_CHINFO_W2_PKT1 GENMASK(15, 8) #define RTW89_H2C_CHINFO_W2_PKT2 GENMASK(23, 16) @@ -2773,6 +2777,7 @@ struct rtw89_h2c_scanofld { #define RTW89_H2C_SCANOFLD_W2_SLOW_PD GENMASK(23, 16) #define RTW89_H2C_SCANOFLD_W3_TSF_HIGH GENMASK(31, 0) #define RTW89_H2C_SCANOFLD_W4_TSF_LOW GENMASK(31, 0) +#define RTW89_H2C_SCANOFLD_W6_SECOND_MACID GENMASK(31, 24) struct rtw89_h2c_scanofld_be_macc_role { __le32 w0; diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index 4bd5e2728ce5c..8ec86e1fa9d6e 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -4388,7 +4388,33 @@ static void rtw89_mac_port_cfg_tx_sw_by_nettype(struct rtw89_dev *rtwdev, rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en); } -void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en) +static void rtw89_mac_enable_ap_bcn_by_chan(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + const struct rtw89_chan *to_match, + bool en) +{ + const struct rtw89_chan *chan; + + if (rtwvif_link->net_type != RTW89_NET_TYPE_AP_MODE) + return; + + if (!to_match) + goto doit; + + /* @to_match may not be in the same domain as return of calling + * rtw89_chan_get(). So, cannot compare their addresses directly. + */ + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + if (chan->channel != to_match->channel) + return; + +doit: + rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en); +} + +static void rtw89_mac_enable_aps_bcn_by_chan(struct rtw89_dev *rtwdev, + const struct rtw89_chan *to_match, + bool en) { struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; @@ -4396,8 +4422,13 @@ void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en) rtw89_for_each_rtwvif(rtwdev, rtwvif) rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) - if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) - rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en); + rtw89_mac_enable_ap_bcn_by_chan(rtwdev, rtwvif_link, + to_match, en); +} + +void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en) +{ + rtw89_mac_enable_aps_bcn_by_chan(rtwdev, NULL, en); } static void rtw89_mac_port_cfg_bcn_intv(struct rtw89_dev *rtwdev, @@ -4891,11 +4922,22 @@ rtw89_mac_c2h_macid_pause(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len { } -static bool rtw89_is_op_chan(struct rtw89_dev *rtwdev, u8 band, u8 channel) +static const struct rtw89_chan * +rtw89_hw_scan_search_op_chan(struct rtw89_dev *rtwdev, u8 band, u8 channel) { + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; const struct rtw89_chan *op = &rtwdev->scan_info.op_chan; - return band == op->band_type && channel == op->primary_channel; + if (band == op->band_type && channel == op->primary_channel) + return op; + + if (scan_info->extra_op.set) { + op = &scan_info->extra_op.chan; + if (band == op->band_type && channel == op->primary_channel) + return op; + } + + return NULL; } static void @@ -4905,6 +4947,7 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, const struct rtw89_c2h_scanofld *c2h = (const struct rtw89_c2h_scanofld *)skb->data; struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; + const struct rtw89_chan *op_chan; struct rtw89_vif *rtwvif; struct rtw89_chan new; u16 actual_period, expect_period; @@ -4960,8 +5003,9 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, switch (reason) { case RTW89_SCAN_LEAVE_OP_NOTIFY: case RTW89_SCAN_LEAVE_CH_NOTIFY: - if (rtw89_is_op_chan(rtwdev, band, chan)) { - rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, false); + op_chan = rtw89_hw_scan_search_op_chan(rtwdev, band, chan); + if (op_chan) { + rtw89_mac_enable_aps_bcn_by_chan(rtwdev, op_chan, false); ieee80211_stop_queues(rtwdev->hw); } return; @@ -4982,10 +5026,10 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, break; case RTW89_SCAN_ENTER_OP_NOTIFY: case RTW89_SCAN_ENTER_CH_NOTIFY: - if (rtw89_is_op_chan(rtwdev, band, chan)) { - rtw89_assign_entity_chan(rtwdev, rtwvif_link->chanctx_idx, - &rtwdev->scan_info.op_chan); - rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true); + op_chan = rtw89_hw_scan_search_op_chan(rtwdev, band, chan); + if (op_chan) { + rtw89_assign_entity_chan(rtwdev, rtwvif_link->chanctx_idx, op_chan); + rtw89_mac_enable_aps_bcn_by_chan(rtwdev, op_chan, true); ieee80211_wake_queues(rtwdev->hw); } else { rtw89_chan_create(&new, chan, chan, band, -- 2.51.0 From 519defe4e8c83a418649c367158f6f8c38439d0a Mon Sep 17 00:00:00 2001 From: Chih-Kang Chang Date: Tue, 10 Jun 2025 21:00:24 +0800 Subject: [PATCH 13/16] wifi: rtw89: mcc: update format of RF notify MCC H2C command The RF notify MCC H2C command format of 8852C different from other chip, therefore add v0 format to update it. Signed-off-by: Chih-Kang Chang Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250610130034.14692-3-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 1 + drivers/net/wireless/realtek/rtw89/fw.c | 38 +++++++++++++++++------ drivers/net/wireless/realtek/rtw89/fw.h | 8 +++++ 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index dca76b1c10294..8c2a71ecfc0d2 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -4525,6 +4525,7 @@ enum rtw89_fw_feature { RTW89_FW_FEATURE_NO_POWER_DIFFERENCE, RTW89_FW_FEATURE_BEACON_LOSS_COUNT_V1, RTW89_FW_FEATURE_SCAN_OFFLOAD_EXTRA_OP, + RTW89_FW_FEATURE_RFK_NTFY_MCC_V0, }; struct rtw89_fw_suit { diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 06fb97a05a897..cde22f692dc29 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -833,6 +833,7 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = { __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 91, 0, SCAN_OFFLOAD), __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 110, 0, BEACON_FILTER), __CFG_FW_FEAT(RTL8852C, le, 0, 27, 33, 0, NO_DEEP_PS), + __CFG_FW_FEAT(RTL8852C, ge, 0, 0, 0, 0, RFK_NTFY_MCC_V0), __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 34, 0, TX_WAKE), __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 36, 0, SCAN_OFFLOAD), __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 40, 0, CRASH_TRIGGER), @@ -5889,31 +5890,48 @@ fail: int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev) { struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data; + struct rtw89_fw_h2c_rf_get_mccch_v0 *mccch_v0; struct rtw89_fw_h2c_rf_get_mccch *mccch; + u32 len = sizeof(*mccch); struct sk_buff *skb; + u8 ver = U8_MAX; int ret; u8 idx; - skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, sizeof(*mccch)); + if (RTW89_CHK_FW_FEATURE(RFK_NTFY_MCC_V0, &rtwdev->fw)) { + len = sizeof(*mccch_v0); + ver = 0; + } + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); if (!skb) { rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_ctrl\n"); return -ENOMEM; } - skb_put(skb, sizeof(*mccch)); - mccch = (struct rtw89_fw_h2c_rf_get_mccch *)skb->data; + skb_put(skb, len); idx = rfk_mcc->table_idx; - mccch->ch_0 = cpu_to_le32(rfk_mcc->ch[0]); - mccch->ch_1 = cpu_to_le32(rfk_mcc->ch[1]); - mccch->band_0 = cpu_to_le32(rfk_mcc->band[0]); - mccch->band_1 = cpu_to_le32(rfk_mcc->band[1]); - mccch->current_channel = cpu_to_le32(rfk_mcc->ch[idx]); - mccch->current_band_type = cpu_to_le32(rfk_mcc->band[idx]); + if (ver == 0) { + mccch_v0 = (struct rtw89_fw_h2c_rf_get_mccch_v0 *)skb->data; + mccch_v0->ch_0 = cpu_to_le32(rfk_mcc->ch[0]); + mccch_v0->ch_1 = cpu_to_le32(rfk_mcc->ch[1]); + mccch_v0->band_0 = cpu_to_le32(rfk_mcc->band[0]); + mccch_v0->band_1 = cpu_to_le32(rfk_mcc->band[1]); + mccch_v0->current_band_type = cpu_to_le32(rfk_mcc->band[idx]); + mccch_v0->current_channel = cpu_to_le32(rfk_mcc->ch[idx]); + } else { + mccch = (struct rtw89_fw_h2c_rf_get_mccch *)skb->data; + mccch->ch_0_0 = cpu_to_le32(rfk_mcc->ch[0]); + mccch->ch_0_1 = cpu_to_le32(rfk_mcc->ch[0]); + mccch->ch_1_0 = cpu_to_le32(rfk_mcc->ch[1]); + mccch->ch_1_1 = cpu_to_le32(rfk_mcc->ch[1]); + mccch->current_channel = cpu_to_le32(rfk_mcc->ch[idx]); + } rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_NOTIFY, H2C_FUNC_OUTSRC_RF_GET_MCCCH, 0, 0, - sizeof(*mccch)); + len); ret = rtw89_h2c_tx(rtwdev, skb, false); if (ret) { diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 36abf1b592400..f9d5bcbc7c7e7 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -4356,6 +4356,14 @@ enum rtw89_rfk_offload_h2c_func { }; struct rtw89_fw_h2c_rf_get_mccch { + __le32 ch_0_0; + __le32 ch_0_1; + __le32 ch_1_0; + __le32 ch_1_1; + __le32 current_channel; +} __packed; + +struct rtw89_fw_h2c_rf_get_mccch_v0 { __le32 ch_0; __le32 ch_1; __le32 band_0; -- 2.51.0 From f70fe6eab088bb431d75cc411e7ac0f98c2bd734 Mon Sep 17 00:00:00 2001 From: Chih-Kang Chang Date: Tue, 10 Jun 2025 21:00:25 +0800 Subject: [PATCH 14/16] wifi: rtw89: mcc: correct frequency when MCC The frequency get from PPDU status set as center channel during MCC, but we need to report to mac80211 as primary channel. Therefore, we use the chanctx information in software to instead it. Signed-off-by: Chih-Kang Chang Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250610130034.14692-4-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.c | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 0a4c420000b85..4252717b15842 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -2478,6 +2478,41 @@ static void rtw89_core_update_rx_freq_from_ie(struct rtw89_dev *rtwdev, rx_status->freq = ieee80211_channel_to_frequency(chan, rx_status->band); } +static void rtw89_core_correct_mcc_chan(struct rtw89_dev *rtwdev, + struct rtw89_rx_desc_info *desc_info, + struct ieee80211_rx_status *rx_status, + struct rtw89_rx_phy_ppdu *phy_ppdu) +{ + enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + const struct rtw89_chan *chan; + u8 mac_id = desc_info->mac_id; + enum rtw89_entity_mode mode; + enum nl80211_band band; + + mode = rtw89_get_entity_mode(rtwdev); + if (likely(mode != RTW89_ENTITY_MODE_MCC)) + return; + + if (chip_gen == RTW89_CHIP_BE && phy_ppdu) + mac_id = phy_ppdu->mac_id; + + rcu_read_lock(); + + rtwsta_link = rtw89_assoc_link_rcu_dereference(rtwdev, mac_id); + if (!rtwsta_link) + goto out; + + rtwvif_link = rtwsta_link->rtwvif_link; + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + band = rtw89_hw_to_nl80211_band(chan->band_type); + rx_status->freq = ieee80211_channel_to_frequency(chan->primary_channel, band); + +out: + rcu_read_unlock(); +} + static void rtw89_core_rx_to_mac80211(struct rtw89_dev *rtwdev, struct rtw89_rx_phy_ppdu *phy_ppdu, struct rtw89_rx_desc_info *desc_info, @@ -2496,6 +2531,7 @@ static void rtw89_core_rx_to_mac80211(struct rtw89_dev *rtwdev, rtw89_core_update_radiotap(rtwdev, skb_ppdu, rx_status); rtw89_core_validate_rx_signal(rx_status); rtw89_core_update_rx_freq_from_ie(rtwdev, skb_ppdu, rx_status); + rtw89_core_correct_mcc_chan(rtwdev, desc_info, rx_status, phy_ppdu); /* In low power mode, it does RX in thread context. */ local_bh_disable(); -- 2.51.0 From 95ee7464d374343115b5e7ec226f2bab2e4012f2 Mon Sep 17 00:00:00 2001 From: Chih-Kang Chang Date: Tue, 10 Jun 2025 21:00:26 +0800 Subject: [PATCH 15/16] wifi: rtw89: mcc: adjust beacon filter when MCC and detect connection MCC needs to wait at most 300ms to start. Additionally, if scanning happens before MCC starts, it will miss some beacons, which might cause beacon loss. Therefore, we reset beacon filter when MCC start to let hardware reset beacon loss counter. Additionally, GO is forbid to enter courtesy mode might cause STA beacon loss. Therefore, disable beacon filter when GO+STA. However, In WiFi 7 chip, even when GC+STA enable courtesy mode, the beacon might loss because switching to courtesy timeslot will disable TX/RX. If the TOB(time offset behind) or TOA(time offset ahead) is too close to the edge of timeslot, the beacon might not be received. Therefore, disable beacon filter when GC+STA in WiFi 7 chip. Because disabling the beacon filter might prevent disconnection when the AP power-off without sending a deauth. Therefore, driver TX QOS nulldata periodically to detect the AP status, and the connection is terminated if no ACK is received for 6 seconds. Signed-off-by: Chih-Kang Chang Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250610130034.14692-5-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/chan.c | 50 +++++++++++++++++++++++ drivers/net/wireless/realtek/rtw89/chan.h | 3 ++ drivers/net/wireless/realtek/rtw89/core.c | 12 +++--- drivers/net/wireless/realtek/rtw89/core.h | 3 ++ 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c index b2bc650a911bc..2575aa174b05f 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.c +++ b/drivers/net/wireless/realtek/rtw89/chan.c @@ -2184,6 +2184,18 @@ static void rtw89_mcc_stop_beacon_noa(struct rtw89_dev *rtwdev) rtw89_mcc_handle_beacon_noa(rtwdev, false); } +static bool rtw89_mcc_ignore_bcn(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role) +{ + enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen; + + if (role->is_go) + return true; + else if (chip_gen == RTW89_CHIP_BE && role->is_gc) + return true; + else + return false; +} + static int rtw89_mcc_start(struct rtw89_dev *rtwdev) { struct rtw89_mcc_info *mcc = &rtwdev->mcc; @@ -2207,6 +2219,15 @@ static int rtw89_mcc_start(struct rtw89_dev *rtwdev) else mcc->mode = RTW89_MCC_MODE_GC_STA; + if (rtw89_mcc_ignore_bcn(rtwdev, ref)) { + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, false); + } else if (rtw89_mcc_ignore_bcn(rtwdev, aux)) { + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, false); + } else { + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, true); + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, true); + } + rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC sel mode: %d\n", mcc->mode); mcc->group = RTW89_MCC_DFLT_GROUP; @@ -2369,15 +2390,44 @@ static int rtw89_mcc_update(struct rtw89_dev *rtwdev) return 0; } +static void rtw89_mcc_detect_connection(struct rtw89_dev *rtwdev, + struct rtw89_mcc_role *role) +{ + struct ieee80211_vif *vif; + int ret; + + ret = rtw89_core_send_nullfunc(rtwdev, role->rtwvif_link, true, false, + RTW89_MCC_PROBE_TIMEOUT); + if (ret) + role->probe_count++; + else + role->probe_count = 0; + + if (role->probe_count < RTW89_MCC_PROBE_MAX_TRIES) + return; + + rtw89_debug(rtwdev, RTW89_DBG_CHAN, + "MCC can not detect AP\n", role->rtwvif_link->mac_id); + vif = rtwvif_link_to_vif(role->rtwvif_link); + ieee80211_connection_loss(vif); +} + static void rtw89_mcc_track(struct rtw89_dev *rtwdev) { struct rtw89_mcc_info *mcc = &rtwdev->mcc; struct rtw89_mcc_config *config = &mcc->config; struct rtw89_mcc_pattern *pattern = &config->pattern; + struct rtw89_mcc_role *ref = &mcc->role_ref; + struct rtw89_mcc_role *aux = &mcc->role_aux; u16 tolerance; u16 bcn_ofst; u16 diff; + if (rtw89_mcc_ignore_bcn(rtwdev, ref)) + rtw89_mcc_detect_connection(rtwdev, aux); + else if (rtw89_mcc_ignore_bcn(rtwdev, aux)) + rtw89_mcc_detect_connection(rtwdev, ref); + if (mcc->mode != RTW89_MCC_MODE_GC_STA) return; diff --git a/drivers/net/wireless/realtek/rtw89/chan.h b/drivers/net/wireless/realtek/rtw89/chan.h index 9c5e61ccab88f..6036f3ca6f675 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.h +++ b/drivers/net/wireless/realtek/rtw89/chan.h @@ -19,6 +19,9 @@ #define RTW89_MCC_MIN_RX_BCN_TIME 10 #define RTW89_MCC_DFLT_BCN_OFST_TIME 40 +#define RTW89_MCC_PROBE_TIMEOUT 100 +#define RTW89_MCC_PROBE_MAX_TRIES 3 + #define RTW89_MCC_MIN_GO_DURATION \ (RTW89_MCC_EARLY_TX_BCN_TIME + RTW89_MCC_MIN_RX_BCN_TIME) diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 4252717b15842..e7e2315d1867c 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -3367,8 +3367,8 @@ static void rtw89_core_handle_sta_pending_tx(struct rtw89_dev *rtwdev, rtwvif_link); } -static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link, bool qos, bool ps) +int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool qos, bool ps, int timeout) { struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); int link_id = ieee80211_vif_is_mld(vif) ? rtwvif_link->link_id : -1; @@ -3416,7 +3416,7 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, rcu_read_unlock(); return rtw89_core_tx_kick_off_and_wait(rtwdev, skb, qsel, - RTW89_ROC_TX_TIMEOUT); + timeout); out: rcu_read_unlock(); @@ -3453,7 +3453,8 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) pause_parm.trigger = rtwvif_link; rtw89_chanctx_pause(rtwdev, &pause_parm); - ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, true); + ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, true, + RTW89_ROC_TX_TIMEOUT); if (ret) rtw89_debug(rtwdev, RTW89_DBG_TXRX, "roc send null-1 failed: %d\n", ret); @@ -3513,7 +3514,8 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) roc->state = RTW89_ROC_IDLE; rtw89_config_roc_chandef(rtwdev, rtwvif_link, NULL); rtw89_chanctx_proceed(rtwdev, NULL); - ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, false); + ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, false, + RTW89_ROC_TX_TIMEOUT); if (ret) rtw89_debug(rtwdev, RTW89_DBG_TXRX, "roc send null-0 failed: %d\n", ret); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 8c2a71ecfc0d2..84c0d58147475 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -5685,6 +5685,7 @@ struct rtw89_mcc_role { /* byte-array in LE order for FW */ u8 macid_bitmap[BITS_TO_BYTES(RTW89_MAX_MAC_ID_NUM)]; + u8 probe_count; u16 duration; /* TU */ u16 beacon_interval; /* TU */ @@ -7342,6 +7343,8 @@ int rtw89_core_start(struct rtw89_dev *rtwdev); void rtw89_core_stop(struct rtw89_dev *rtwdev); void rtw89_core_update_beacon_work(struct wiphy *wiphy, struct wiphy_work *work); void rtw89_core_csa_beacon_work(struct wiphy *wiphy, struct wiphy_work *work); +int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool qos, bool ps, int timeout); void rtw89_roc_work(struct wiphy *wiphy, struct wiphy_work *work); void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); -- 2.51.0 From 182c7ff8b87e4edbb2227ede39ae0952da7a0f4a Mon Sep 17 00:00:00 2001 From: Chih-Kang Chang Date: Tue, 10 Jun 2025 21:00:27 +0800 Subject: [PATCH 16/16] wifi: rtw89: mcc: stop TX during MCC prepare Stop TX during the MCC configuration period to prevent packet leakage. The stop time is defined as 'start_tsf - tsf', which means the duration from when MCC configuration begins until MCC starts. Signed-off-by: Chih-Kang Chang Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250610130034.14692-6-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/chan.c | 35 +++++++++++++++++++++++ drivers/net/wireless/realtek/rtw89/chan.h | 2 ++ drivers/net/wireless/realtek/rtw89/core.c | 2 ++ drivers/net/wireless/realtek/rtw89/core.h | 2 ++ 4 files changed, 41 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c index 2575aa174b05f..7539bba2e0948 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.c +++ b/drivers/net/wireless/realtek/rtw89/chan.c @@ -1602,6 +1602,35 @@ static bool rtw89_mcc_duration_decision_on_bt(struct rtw89_dev *rtwdev) return false; } +void rtw89_mcc_prepare_done_work(struct wiphy *wiphy, struct wiphy_work *work) +{ + struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, + mcc_prepare_done_work.work); + + lockdep_assert_wiphy(wiphy); + + ieee80211_wake_queues(rtwdev->hw); +} + +static void rtw89_mcc_prepare(struct rtw89_dev *rtwdev, bool start) +{ + struct rtw89_mcc_info *mcc = &rtwdev->mcc; + struct rtw89_mcc_config *config = &mcc->config; + + if (start) { + ieee80211_stop_queues(rtwdev->hw); + + wiphy_delayed_work_queue(rtwdev->hw->wiphy, + &rtwdev->mcc_prepare_done_work, + usecs_to_jiffies(config->prepare_delay)); + } else { + wiphy_delayed_work_queue(rtwdev->hw->wiphy, + &rtwdev->mcc_prepare_done_work, 0); + wiphy_delayed_work_flush(rtwdev->hw->wiphy, + &rtwdev->mcc_prepare_done_work); + } +} + static int rtw89_mcc_fill_start_tsf(struct rtw89_dev *rtwdev) { struct rtw89_mcc_info *mcc = &rtwdev->mcc; @@ -1637,6 +1666,8 @@ static int rtw89_mcc_fill_start_tsf(struct rtw89_dev *rtwdev) config->start_tsf = start_tsf; config->start_tsf_in_aux_domain = tsf_aux + start_tsf - tsf; + config->prepare_delay = start_tsf - tsf; + return 0; } @@ -2247,6 +2278,8 @@ static int rtw89_mcc_start(struct rtw89_dev *rtwdev) rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_START); rtw89_mcc_start_beacon_noa(rtwdev); + + rtw89_mcc_prepare(rtwdev, true); return 0; } @@ -2335,6 +2368,8 @@ static void rtw89_mcc_stop(struct rtw89_dev *rtwdev, rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_STOP); rtw89_mcc_stop_beacon_noa(rtwdev); + + rtw89_mcc_prepare(rtwdev, false); } static int rtw89_mcc_update(struct rtw89_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw89/chan.h b/drivers/net/wireless/realtek/rtw89/chan.h index 6036f3ca6f675..5f10f3955e5c4 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.h +++ b/drivers/net/wireless/realtek/rtw89/chan.h @@ -133,6 +133,8 @@ const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev, #define rtw89_mgnt_chan_get(rtwdev, link_index) \ __rtw89_mgnt_chan_get(rtwdev, __func__, link_index) +void rtw89_mcc_prepare_done_work(struct wiphy *wiphy, struct wiphy_work *work); + int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev, struct ieee80211_chanctx_conf *ctx); void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev, diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index e7e2315d1867c..130e89743991b 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -4884,6 +4884,7 @@ void rtw89_core_stop(struct rtw89_dev *rtwdev) wiphy_delayed_work_cancel(wiphy, &rtwdev->coex_bt_devinfo_work); wiphy_delayed_work_cancel(wiphy, &rtwdev->coex_rfk_chk_work); wiphy_delayed_work_cancel(wiphy, &rtwdev->cfo_track_work); + wiphy_delayed_work_cancel(wiphy, &rtwdev->mcc_prepare_done_work); cancel_delayed_work_sync(&rtwdev->forbid_ba_work); wiphy_delayed_work_cancel(wiphy, &rtwdev->antdiv_work); @@ -5110,6 +5111,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev) wiphy_delayed_work_init(&rtwdev->coex_bt_devinfo_work, rtw89_coex_bt_devinfo_work); wiphy_delayed_work_init(&rtwdev->coex_rfk_chk_work, rtw89_coex_rfk_chk_work); wiphy_delayed_work_init(&rtwdev->cfo_track_work, rtw89_phy_cfo_track_work); + wiphy_delayed_work_init(&rtwdev->mcc_prepare_done_work, rtw89_mcc_prepare_done_work); INIT_DELAYED_WORK(&rtwdev->forbid_ba_work, rtw89_forbid_ba_work); wiphy_delayed_work_init(&rtwdev->antdiv_work, rtw89_phy_antdiv_work); rtwdev->txq_wq = alloc_workqueue("rtw89_tx_wq", WQ_UNBOUND | WQ_HIGHPRI, 0); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 84c0d58147475..ce2f133138266 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -5742,6 +5742,7 @@ struct rtw89_mcc_config { struct rtw89_mcc_sync sync; u64 start_tsf; u64 start_tsf_in_aux_domain; + u64 prepare_delay; u16 mcc_interval; /* TU */ u16 beacon_offset; /* TU */ }; @@ -5872,6 +5873,7 @@ struct rtw89_dev { struct wiphy_delayed_work coex_bt_devinfo_work; struct wiphy_delayed_work coex_rfk_chk_work; struct wiphy_delayed_work cfo_track_work; + struct wiphy_delayed_work mcc_prepare_done_work; struct delayed_work forbid_ba_work; struct wiphy_delayed_work antdiv_work; struct rtw89_ppdu_sts_info ppdu_sts; -- 2.51.0