wifi: rtw89: chan: tweak weight recalc ahead before MLO
authorZong-Zhe Yang <kevin_yang@realtek.com>
Tue, 6 Feb 2024 03:06:22 +0000 (11:06 +0800)
committerKalle Valo <kvalo@kernel.org>
Mon, 12 Feb 2024 15:37:09 +0000 (17:37 +0200)
Originally, we consider weight only based on how many chanctxs that
mac80211 sets. However, we need to consider both active chanctxs and
active interfaces to distinguish MCC (multiple channel concurrent)
from impending MLO.

Although the logic of handling is extended, for now, behavior might
not be different under current condition.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://msgid.link/20240206030624.23382-5-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/chan.c
drivers/net/wireless/realtek/rtw89/chan.h
drivers/net/wireless/realtek/rtw89/core.h

index 6a666a92b59b0271622f05b4c756c1e05e39efc3..57fabc05dab9dec968ec3d084419d08874657302 100644 (file)
@@ -212,24 +212,51 @@ void rtw89_entity_init(struct rtw89_dev *rtwdev)
        rtw89_config_default_chandef(rtwdev);
 }
 
+static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev,
+                                         struct rtw89_entity_weight *w)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+       const struct rtw89_chanctx_cfg *cfg;
+       struct rtw89_vif *rtwvif;
+       int idx;
+
+       for_each_set_bit(idx, hal->entity_map, NUM_OF_RTW89_SUB_ENTITY) {
+               cfg = hal->sub[idx].cfg;
+               if (!cfg) {
+                       /* doesn't run with chanctx ops; one channel at most */
+                       w->active_chanctxs = 1;
+                       break;
+               }
+
+               if (cfg->ref_count > 0)
+                       w->active_chanctxs++;
+       }
+
+       rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+               if (rtwvif->chanctx_assigned)
+                       w->active_roles++;
+       }
+}
+
 enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
 {
        DECLARE_BITMAP(recalc_map, NUM_OF_RTW89_SUB_ENTITY) = {};
        struct rtw89_hal *hal = &rtwdev->hal;
        const struct cfg80211_chan_def *chandef;
+       struct rtw89_entity_weight w = {};
        enum rtw89_entity_mode mode;
        struct rtw89_chan chan;
-       u8 weight;
        u8 idx;
 
        lockdep_assert_held(&rtwdev->mutex);
 
        bitmap_copy(recalc_map, hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
 
-       weight = bitmap_weight(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
-       switch (weight) {
+       rtw89_entity_calculate_weight(rtwdev, &w);
+       switch (w.active_chanctxs) {
        default:
-               rtw89_warn(rtwdev, "unknown ent chan weight: %d\n", weight);
+               rtw89_warn(rtwdev, "unknown ent chanctxs weight: %d\n",
+                          w.active_chanctxs);
                bitmap_zero(recalc_map, NUM_OF_RTW89_SUB_ENTITY);
                fallthrough;
        case 0:
@@ -239,7 +266,14 @@ enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
        case 1:
                mode = RTW89_ENTITY_MODE_SCC;
                break;
-       case 2:
+       case 2 ... NUM_OF_RTW89_SUB_ENTITY:
+               if (w.active_roles != NUM_OF_RTW89_MCC_ROLES) {
+                       rtw89_debug(rtwdev, RTW89_DBG_CHAN,
+                                   "unhandled ent: %d chanctxs %d roles\n",
+                                   w.active_chanctxs, w.active_roles);
+                       return RTW89_ENTITY_MODE_UNHANDLED;
+               }
+
                mode = rtw89_get_entity_mode(rtwdev);
                if (mode == RTW89_ENTITY_MODE_MCC)
                        break;
@@ -582,6 +616,9 @@ static int rtw89_mcc_fill_all_roles(struct rtw89_dev *rtwdev)
        int ret;
 
        rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+               if (!rtwvif->chanctx_assigned)
+                       continue;
+
                if (sel.bind_vif[rtwvif->sub_entity_idx]) {
                        rtw89_warn(rtwdev,
                                   "MCC skip extra vif <macid %d> on chanctx[%d]\n",
@@ -2007,6 +2044,7 @@ int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
 
        rtwvif->sub_entity_idx = cfg->idx;
        rtwvif->chanctx_assigned = true;
+       cfg->ref_count++;
        return 0;
 }
 
@@ -2014,6 +2052,9 @@ void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
                                    struct rtw89_vif *rtwvif,
                                    struct ieee80211_chanctx_conf *ctx)
 {
+       struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
+
        rtwvif->sub_entity_idx = RTW89_SUB_ENTITY_0;
        rtwvif->chanctx_assigned = false;
+       cfg->ref_count--;
 }
index 9b98d8f4ee9dab417c16fcac93e01afcb0c7edc9..ffa412f281f327a6de3157a756025c4b4ac5ba9e 100644 (file)
@@ -38,6 +38,11 @@ enum rtw89_chanctx_pause_reasons {
        RTW89_CHANCTX_PAUSE_REASON_ROC,
 };
 
+struct rtw89_entity_weight {
+       unsigned int active_chanctxs;
+       unsigned int active_roles;
+};
+
 static inline bool rtw89_get_entity_state(struct rtw89_dev *rtwdev)
 {
        struct rtw89_hal *hal = &rtwdev->hal;
index 75269c1d94cc42bf436c4fc4761b33706c9ad5b9..d98dcf12bef77b39a2140adef76f44d561fa6c19 100644 (file)
@@ -4136,6 +4136,7 @@ struct rtw89_tas_info {
 
 struct rtw89_chanctx_cfg {
        enum rtw89_sub_entity_idx idx;
+       int ref_count;
 };
 
 enum rtw89_chanctx_changes {
@@ -4155,13 +4156,16 @@ enum rtw89_entity_mode {
        RTW89_ENTITY_MODE_MCC,
 
        NUM_OF_RTW89_ENTITY_MODE,
-       RTW89_ENTITY_MODE_INVALID = NUM_OF_RTW89_ENTITY_MODE,
+       RTW89_ENTITY_MODE_INVALID = -EINVAL,
+       RTW89_ENTITY_MODE_UNHANDLED = -ESRCH,
 };
 
 struct rtw89_sub_entity {
        struct cfg80211_chan_def chandef;
        struct rtw89_chan chan;
        struct rtw89_chan_rcd rcd;
+
+       /* only assigned when running with chanctx_ops */
        struct rtw89_chanctx_cfg *cfg;
 };