Skip to content

Commit 96fbb84

Browse files
Po-Hao HuangKalle Valo
authored andcommitted
wifi: rtw88: handle station mode concurrent scan with AP mode
This patch allows vifs sharing same hardware with the AP mode vif to do scan, do note that this could lead to packet loss or disconnection of the AP's clients. Since we don't have chanctx, update scan info upon set channel so bandwidth changes won't go unnoticed and get misconfigured after scan. Download beacon just before scan starts to allow hardware to get proper content to do beaconing. Last, beacons should only be transmitted in AP's operating channel. Turn related beacon functions off while we're in other channels so the receiving stations won't get confused. Signed-off-by: Po-Hao Huang <phhuang@realtek.com> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Signed-off-by: Kalle Valo <kvalo@kernel.org> Link: https://lore.kernel.org/r/20230414121323.18008-1-pkshih@realtek.com
1 parent a1b8015 commit 96fbb84

4 files changed

Lines changed: 55 additions & 2 deletions

File tree

drivers/net/wireless/realtek/rtw88/fw.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2160,6 +2160,12 @@ int rtw_hw_scan_offload(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
21602160
}
21612161
rtw_fw_set_scan_offload(rtwdev, &cs_option, rtwvif, &chan_list);
21622162
out:
2163+
if (rtwdev->ap_active) {
2164+
ret = rtw_download_beacon(rtwdev);
2165+
if (ret)
2166+
rtw_err(rtwdev, "HW scan download beacon failed\n");
2167+
}
2168+
21632169
return ret;
21642170
}
21652171

@@ -2251,6 +2257,7 @@ void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb)
22512257
if (rtw_is_op_chan(rtwdev, chan)) {
22522258
rtw_store_op_chan(rtwdev, false);
22532259
ieee80211_wake_queues(rtwdev->hw);
2260+
rtw_core_enable_beacon(rtwdev, true);
22542261
}
22552262
} else if (id == RTW_SCAN_NOTIFY_ID_PRESWITCH) {
22562263
if (IS_CH_5G_BAND(chan)) {
@@ -2269,8 +2276,10 @@ void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb)
22692276
* if next channel is non-op channel.
22702277
*/
22712278
if (!rtw_is_op_chan(rtwdev, chan) &&
2272-
rtw_is_op_chan(rtwdev, hal->current_channel))
2279+
rtw_is_op_chan(rtwdev, hal->current_channel)) {
2280+
rtw_core_enable_beacon(rtwdev, false);
22732281
ieee80211_stop_queues(rtwdev->hw);
2282+
}
22742283
}
22752284

22762285
rtw_dbg(rtwdev, RTW_DBG_HW_SCAN,

drivers/net/wireless/realtek/rtw88/mac80211.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
404404
if (changed & BSS_CHANGED_BSSID) {
405405
ether_addr_copy(rtwvif->bssid, conf->bssid);
406406
config |= PORT_SET_BSSID;
407-
if (is_zero_ether_addr(rtwvif->bssid))
407+
if (!rtw_core_check_sta_active(rtwdev))
408408
rtw_clear_op_chan(rtwdev);
409409
else
410410
rtw_store_op_chan(rtwdev, true);
@@ -452,6 +452,7 @@ static int rtw_ops_start_ap(struct ieee80211_hw *hw,
452452

453453
mutex_lock(&rtwdev->mutex);
454454
rtwdev->ap_active = true;
455+
rtw_store_op_chan(rtwdev, true);
455456
chip->ops->phy_calibration(rtwdev);
456457
mutex_unlock(&rtwdev->mutex);
457458

@@ -466,6 +467,8 @@ static void rtw_ops_stop_ap(struct ieee80211_hw *hw,
466467

467468
mutex_lock(&rtwdev->mutex);
468469
rtwdev->ap_active = false;
470+
if (!rtw_core_check_sta_active(rtwdev))
471+
rtw_clear_op_chan(rtwdev);
469472
mutex_unlock(&rtwdev->mutex);
470473
}
471474

drivers/net/wireless/realtek/rtw88/main.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,9 @@ void rtw_set_channel(struct rtw_dev *rtwdev)
830830

831831
rtw_update_channel(rtwdev, center_chan, primary_chan, band, bandwidth);
832832

833+
if (rtwdev->scan_info.op_chan)
834+
rtw_store_op_chan(rtwdev, true);
835+
833836
chip->ops->set_channel(rtwdev, center_chan, bandwidth,
834837
hal->current_primary_channel_index);
835838

@@ -2330,6 +2333,42 @@ void rtw_core_port_switch(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
23302333
rtw_iterate_vifs(rtwdev, rtw_port_switch_iter, &iter_data);
23312334
}
23322335

2336+
static void rtw_check_sta_active_iter(void *data, u8 *mac,
2337+
struct ieee80211_vif *vif)
2338+
{
2339+
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
2340+
bool *active = data;
2341+
2342+
if (*active)
2343+
return;
2344+
2345+
if (vif->type != NL80211_IFTYPE_STATION)
2346+
return;
2347+
2348+
if (vif->cfg.assoc || !is_zero_ether_addr(rtwvif->bssid))
2349+
*active = true;
2350+
}
2351+
2352+
bool rtw_core_check_sta_active(struct rtw_dev *rtwdev)
2353+
{
2354+
bool sta_active = false;
2355+
2356+
rtw_iterate_vifs(rtwdev, rtw_check_sta_active_iter, &sta_active);
2357+
2358+
return rtwdev->ap_active || sta_active;
2359+
}
2360+
2361+
void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable)
2362+
{
2363+
if (!rtwdev->ap_active)
2364+
return;
2365+
2366+
if (enable)
2367+
rtw_write32_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
2368+
else
2369+
rtw_write32_clr(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
2370+
}
2371+
23332372
MODULE_AUTHOR("Realtek Corporation");
23342373
MODULE_DESCRIPTION("Realtek 802.11ac wireless core module");
23352374
MODULE_LICENSE("Dual BSD/GPL");

drivers/net/wireless/realtek/rtw88/main.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2201,4 +2201,6 @@ void rtw_update_channel(struct rtw_dev *rtwdev, u8 center_channel,
22012201
u8 primary_channel, enum rtw_supported_band band,
22022202
enum rtw_bandwidth bandwidth);
22032203
void rtw_core_port_switch(struct rtw_dev *rtwdev, struct ieee80211_vif *vif);
2204+
bool rtw_core_check_sta_active(struct rtw_dev *rtwdev);
2205+
void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable);
22042206
#endif

0 commit comments

Comments
 (0)