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 <gary.chang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20250610130034.14692-5-pkshih@realtek.com
This commit is contained in:
Chih-Kang Chang 2025-06-10 21:00:26 +08:00 committed by Ping-Ke Shih
parent f70fe6eab0
commit 95ee7464d3
4 changed files with 63 additions and 5 deletions

View File

@ -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 <macid %d> 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;

View File

@ -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)

View File

@ -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);

View File

@ -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);