summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZong-Zhe Yang <kevin_yang@realtek.com>2025-04-22 09:46:13 +0800
committerPing-Ke Shih <pkshih@realtek.com>2025-04-28 14:35:36 +0800
commit98019abbf97d591eb3f0f2f146e602c131efe0df (patch)
treee606a34504a98642e789f546b38faafe6082981c
parent57a5fbe39a18e591b33d181bed21518fb9f21d46 (diff)
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 <kevin_yang@realtek.com> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Link: https://patch.msgid.link/20250422014620.18421-6-pkshih@realtek.com
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.c79
1 files changed, 79 insertions, 0 deletions
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;
}