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