Skip to content

Commit

Permalink
wifi: rtw89: fix misbehavior of TX beacon in concurrent mode
Browse files Browse the repository at this point in the history
[ Upstream commit 756b312 ]

In concurrent mode, when STA interface is scanning, it causes
AP interface TX beacon on wrong channel. We modified it to scan
with the operating channel when one of the interfaces is already
connected. Additionally, STA interface need to stop scan when AP
interface is starting to avoid TX beacon on wrong channel. Finally,
AP interface need to stop TX beacon when STA interface is scanning
and switching to non-OP channel,This prevent other device to get
beacons on wrong channel.

Signed-off-by: Chih-Kang Chang <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Sasha Levin <[email protected]>
  • Loading branch information
Chih-Kang Chang authored and gregkh committed Feb 5, 2024
1 parent 5b34e76 commit d8bfb29
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 7 deletions.
17 changes: 15 additions & 2 deletions drivers/net/wireless/realtek/rtw89/fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -3912,6 +3912,7 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
rtw89_core_scan_complete(rtwdev, vif, true);
ieee80211_scan_completed(rtwdev->hw, &info);
ieee80211_wake_queues(rtwdev->hw);
rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true);

rtw89_release_pkt_list(rtwdev);
rtwvif = (struct rtw89_vif *)vif->drv_priv;
Expand All @@ -3929,6 +3930,19 @@ void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)
rtw89_hw_scan_complete(rtwdev, vif, true);
}

static bool rtw89_is_any_vif_connected_or_connecting(struct rtw89_dev *rtwdev)
{
struct rtw89_vif *rtwvif;

rtw89_for_each_rtwvif(rtwdev, rtwvif) {
/* This variable implies connected or during attempt to connect */
if (!is_zero_ether_addr(rtwvif->bssid))
return true;
}

return false;
}

int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
bool enable)
{
Expand All @@ -3941,8 +3955,7 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
if (!rtwvif)
return -EINVAL;

/* This variable implies connected or during attempt to connect */
connected = !is_zero_ether_addr(rtwvif->bssid);
connected = rtw89_is_any_vif_connected_or_connecting(rtwdev);
opt.enable = enable;
opt.target_ch_mode = connected;
if (enable) {
Expand Down
29 changes: 24 additions & 5 deletions drivers/net/wireless/realtek/rtw89/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -3833,18 +3833,34 @@ static void rtw89_mac_port_cfg_rx_sync(struct rtw89_dev *rtwdev,
}

static void rtw89_mac_port_cfg_tx_sw(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif)
struct rtw89_vif *rtwvif, bool en)
{
const struct rtw89_port_reg *p = &rtw_port_base;
bool en = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE ||
rtwvif->net_type == RTW89_NET_TYPE_AD_HOC;

if (en)
rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN);
else
rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN);
}

static void rtw89_mac_port_cfg_tx_sw_by_nettype(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif)
{
bool en = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE ||
rtwvif->net_type == RTW89_NET_TYPE_AD_HOC;

rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif, en);
}

void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en)
{
struct rtw89_vif *rtwvif;

rtw89_for_each_rtwvif(rtwdev, rtwvif)
if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE)
rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif, en);
}

static void rtw89_mac_port_cfg_bcn_intv(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif)
{
Expand Down Expand Up @@ -4137,7 +4153,7 @@ int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
rtw89_mac_port_cfg_bcn_prct(rtwdev, rtwvif);
rtw89_mac_port_cfg_rx_sw(rtwdev, rtwvif);
rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif);
rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif);
rtw89_mac_port_cfg_tx_sw_by_nettype(rtwdev, rtwvif);
rtw89_mac_port_cfg_bcn_intv(rtwdev, rtwvif);
rtw89_mac_port_cfg_hiq_win(rtwdev, rtwvif);
rtw89_mac_port_cfg_hiq_dtim(rtwdev, rtwvif);
Expand Down Expand Up @@ -4298,8 +4314,10 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,

switch (reason) {
case RTW89_SCAN_LEAVE_CH_NOTIFY:
if (rtw89_is_op_chan(rtwdev, band, chan))
if (rtw89_is_op_chan(rtwdev, band, chan)) {
rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, false);
ieee80211_stop_queues(rtwdev->hw);
}
return;
case RTW89_SCAN_END_SCAN_NOTIFY:
if (rtwvif && rtwvif->scan_req &&
Expand All @@ -4317,6 +4335,7 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
if (rtw89_is_op_chan(rtwdev, band, chan)) {
rtw89_assign_entity_chan(rtwdev, rtwvif->sub_entity_idx,
&rtwdev->scan_info.op_chan);
rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true);
ieee80211_wake_queues(rtwdev->hw);
} else {
rtw89_chan_create(&new, chan, chan, band,
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/realtek/rtw89/mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,7 @@ int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif);
void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en);
int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *vif);
void rtw89_mac_disable_cpu(struct rtw89_dev *rtwdev);
int rtw89_mac_enable_cpu(struct rtw89_dev *rtwdev, u8 boot_reason, bool dlfw);
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/wireless/realtek/rtw89/mac80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,9 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw,
return -EOPNOTSUPP;
}

if (rtwdev->scanning)
rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);

ether_addr_copy(rtwvif->bssid, vif->bss_conf.bssid);
rtw89_cam_bssid_changed(rtwdev, rtwvif);
rtw89_mac_port_update(rtwdev, rtwvif);
Expand Down

0 comments on commit d8bfb29

Please sign in to comment.