From 98019abbf97d591eb3f0f2f146e602c131efe0df Mon Sep 17 00:00:00 2001 From: Zong-Zhe Yang Date: Tue, 22 Apr 2025 09:46:13 +0800 Subject: [PATCH] wifi: rtw89: mcc: make GO announce one-time NoA for HW scan process Since FW cannot handle HW scan process and MCC (multi-channel concurrency) mode simultaneously, if a HW scan is requested during MCC, MCC mode will be paused temporarily. Then, the GO role if any might be absent. So, calculate an estimated time for the requested HW scan process and search for existing GO roles to fill one-time NoA. Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250422014620.18421-6-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/fw.c | 79 +++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index ae402d4c3773..4173794e3892 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -7313,11 +7313,87 @@ out: return ret; } +static void rtw89_hw_scan_update_link_beacon_noa(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + u16 tu) +{ + struct ieee80211_p2p_noa_desc noa_desc = {}; + u64 tsf; + int ret; + + ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf); + if (ret) { + rtw89_warn(rtwdev, "%s: failed to get tsf\n", __func__); + return; + } + + noa_desc.start_time = cpu_to_le32(tsf); + noa_desc.interval = cpu_to_le32(ieee80211_tu_to_usec(tu)); + noa_desc.duration = cpu_to_le32(ieee80211_tu_to_usec(tu)); + noa_desc.count = 1; + + rtw89_p2p_noa_renew(rtwvif_link); + rtw89_p2p_noa_append(rtwvif_link, &noa_desc); + rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_link); +} + +static void rtw89_hw_scan_update_beacon_noa(struct rtw89_dev *rtwdev, + const struct cfg80211_scan_request *req) +{ + const struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt; + const struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_mac_chinfo_ax *chinfo_ax; + struct rtw89_mac_chinfo_be *chinfo_be; + struct rtw89_vif_link *rtwvif_link; + struct list_head *pos, *tmp; + struct ieee80211_vif *vif; + struct rtw89_vif *rtwvif; + u16 tu = 0; + + lockdep_assert_wiphy(rtwdev->hw->wiphy); + + list_for_each_safe(pos, tmp, &scan_info->chan_list) { + switch (chip->chip_gen) { + case RTW89_CHIP_AX: + chinfo_ax = list_entry(pos, typeof(*chinfo_ax), list); + tu += chinfo_ax->period; + break; + case RTW89_CHIP_BE: + chinfo_be = list_entry(pos, typeof(*chinfo_be), list); + tu += chinfo_be->period; + break; + default: + rtw89_warn(rtwdev, "%s: invalid chip gen %d\n", + __func__, chip->chip_gen); + return; + } + } + + if (unlikely(tu == 0)) { + rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN, + "%s: cannot estimate needed TU\n", __func__); + return; + } + + list_for_each_entry(rtwvif, &mgnt->active_list, mgnt_entry) { + unsigned int link_id; + + vif = rtwvif_to_vif(rtwvif); + if (vif->type != NL80211_IFTYPE_AP || !vif->p2p) + continue; + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_hw_scan_update_link_beacon_noa(rtwdev, rtwvif_link, tu); + } +} + int rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct ieee80211_scan_request *scan_req) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + enum rtw89_entity_mode mode = rtw89_get_entity_mode(rtwdev); struct cfg80211_scan_request *req = &scan_req->req; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); @@ -7362,6 +7438,9 @@ int rtw89_hw_scan_start(struct rtw89_dev *rtwdev, rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_HW_SCAN); + if (mode == RTW89_ENTITY_MODE_MCC) + rtw89_hw_scan_update_beacon_noa(rtwdev, req); + return 0; } -- 2.50.1