]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: rtw89: unify the selection logic of RFK table when MCC
authorZong-Zhe Yang <kevin_yang@realtek.com>
Tue, 2 Jul 2024 12:44:52 +0000 (20:44 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Fri, 5 Jul 2024 01:51:34 +0000 (09:51 +0800)
Driver will notify FW the target index of RFK table to use at some
moments. When MCC (multi-channel concurrent), the correctness of the
notification is especially important.

We now unify the selection logic of RFK table as below among chips.
1. check each table if it matches target channel
2. check all tables if any is idle by iterating active channels
3. replace the first table if all are busy unexpectedly

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20240702124452.18747-2-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/chan.c
drivers/net/wireless/realtek/rtw89/chan.h
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/phy.c
drivers/net/wireless/realtek/rtw89/phy.h
drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c

index 3b1997223cc52268d23c67bc3de54ffd27d1eae6..7f90d93dcdc0c0d69b098e05496ff60c5353706c 100644 (file)
@@ -141,6 +141,28 @@ bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
        return band_changed;
 }
 
+int rtw89_iterate_entity_chan(struct rtw89_dev *rtwdev,
+                             int (*iterator)(const struct rtw89_chan *chan,
+                                             void *data),
+                             void *data)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+       const struct rtw89_chan *chan;
+       int ret;
+       u8 idx;
+
+       lockdep_assert_held(&rtwdev->mutex);
+
+       for_each_set_bit(idx,  hal->entity_map, NUM_OF_RTW89_SUB_ENTITY) {
+               chan = rtw89_chan_get(rtwdev, idx);
+               ret = iterator(chan, data);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static void __rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
                                          enum rtw89_sub_entity_idx idx,
                                          const struct cfg80211_chan_def *chandef,
index ffa412f281f327a6de3157a756025c4b4ac5ba9e..5278ff8c513b39afa73a2f6b359aa4e56d2c90e5 100644 (file)
@@ -78,6 +78,10 @@ void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
 bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
                              enum rtw89_sub_entity_idx idx,
                              const struct rtw89_chan *new);
+int rtw89_iterate_entity_chan(struct rtw89_dev *rtwdev,
+                             int (*iterator)(const struct rtw89_chan *chan,
+                                             void *data),
+                             void *data);
 void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
                                 enum rtw89_sub_entity_idx idx,
                                 const struct cfg80211_chan_def *chandef);
index 001da3ad149eae34404db47c5e51ec4c438e7355..11fa003a9788c446181f8ced509dc8acd9e04ad9 100644 (file)
@@ -4695,7 +4695,12 @@ struct rtw89_dack_info {
        bool msbk_timeout[RTW89_DACK_PATH_NR];
 };
 
-#define RTW89_RFK_CHS_NR 3
+enum rtw89_rfk_chs_nrs {
+       __RTW89_RFK_CHS_NR_V0 = 2,
+       __RTW89_RFK_CHS_NR_V1 = 3,
+
+       RTW89_RFK_CHS_NR = __RTW89_RFK_CHS_NR_V1,
+};
 
 struct rtw89_rfk_mcc_info {
        u8 ch[RTW89_RFK_CHS_NR];
index e025f0ed9f59234ce598568603b4339b28bfcb01..ad11d1414874abe2615403c81c005f7715bd63ef 100644 (file)
@@ -2,6 +2,7 @@
 /* Copyright(c) 2019-2020  Realtek Corporation
  */
 
+#include "chan.h"
 #include "coex.h"
 #include "debug.h"
 #include "fw.h"
@@ -6003,6 +6004,74 @@ void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif
                              vif->cfg.aid, phy_idx);
 }
 
+static bool rfk_chan_validate_desc(const struct rtw89_rfk_chan_desc *desc)
+{
+       return desc->ch != 0;
+}
+
+static bool rfk_chan_is_equivalent(const struct rtw89_rfk_chan_desc *desc,
+                                  const struct rtw89_chan *chan)
+{
+       if (!rfk_chan_validate_desc(desc))
+               return false;
+
+       if (desc->ch != chan->channel)
+               return false;
+
+       if (desc->has_band && desc->band != chan->band_type)
+               return false;
+
+       if (desc->has_bw && desc->bw != chan->band_width)
+               return false;
+
+       return true;
+}
+
+struct rfk_chan_iter_data {
+       const struct rtw89_rfk_chan_desc desc;
+       unsigned int found;
+};
+
+static int rfk_chan_iter_search(const struct rtw89_chan *chan, void *data)
+{
+       struct rfk_chan_iter_data *iter_data = data;
+
+       if (rfk_chan_is_equivalent(&iter_data->desc, chan))
+               iter_data->found++;
+
+       return 0;
+}
+
+u8 rtw89_rfk_chan_lookup(struct rtw89_dev *rtwdev,
+                        const struct rtw89_rfk_chan_desc *desc, u8 desc_nr,
+                        const struct rtw89_chan *target_chan)
+{
+       int sel = -1;
+       u8 i;
+
+       for (i = 0; i < desc_nr; i++) {
+               struct rfk_chan_iter_data iter_data = {
+                       .desc = desc[i],
+               };
+
+               if (rfk_chan_is_equivalent(&desc[i], target_chan))
+                       return i;
+
+               rtw89_iterate_entity_chan(rtwdev, rfk_chan_iter_search, &iter_data);
+               if (!iter_data.found && sel == -1)
+                       sel = i;
+       }
+
+       if (sel == -1) {
+               rtw89_debug(rtwdev, RTW89_DBG_RFK,
+                           "no idle rfk entry; force replace the first\n");
+               sel = 0;
+       }
+
+       return sel;
+}
+EXPORT_SYMBOL(rtw89_rfk_chan_lookup);
+
 static void
 _rfk_write_rf(struct rtw89_dev *rtwdev, const struct rtw89_reg5_def *def)
 {
index 6e53ac9140fbce86e61d0b78757ab91a88261794..d8df553b9cb005336eb30f7e6c85884bdfeefc40 100644 (file)
@@ -715,6 +715,19 @@ enum rtw89_phy_gain_band_be rtw89_subband_to_gain_band_be(enum rtw89_subband sub
        }
 }
 
+struct rtw89_rfk_chan_desc {
+       /* desc is valid iff ch is non-zero */
+       u8 ch;
+
+       /* To avoid us from extending old chip code every time, each new
+        * field must be defined along with a bool flag in positivte way.
+        */
+       bool has_band;
+       u8 band;
+       bool has_bw;
+       u8 bw;
+};
+
 enum rtw89_rfk_flag {
        RTW89_RFK_F_WRF = 0,
        RTW89_RFK_F_WM = 1,
@@ -950,5 +963,8 @@ enum rtw89_rf_path_bit rtw89_phy_get_kpath(struct rtw89_dev *rtwdev,
                                           enum rtw89_phy_idx phy_idx);
 enum rtw89_rf_path rtw89_phy_get_syn_sel(struct rtw89_dev *rtwdev,
                                         enum rtw89_phy_idx phy_idx);
+u8 rtw89_rfk_chan_lookup(struct rtw89_dev *rtwdev,
+                        const struct rtw89_rfk_chan_desc *desc, u8 desc_nr,
+                        const struct rtw89_chan *target_chan);
 
 #endif
index 654e3e5507cb09dd4f1ae4ca392d1d671264fda3..743f7014bf3e8842532d380fb1f7d078dcbd0a19 100644 (file)
@@ -4070,12 +4070,11 @@ void rtw8852c_set_channel_rf(struct rtw89_dev *rtwdev,
 void rtw8852c_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
 {
        struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
-       DECLARE_BITMAP(map, RTW89_IQK_CHS_NR) = {};
+       struct rtw89_rfk_chan_desc desc[__RTW89_RFK_CHS_NR_V0] = {};
        const struct rtw89_chan *chan;
        enum rtw89_entity_mode mode;
        u8 chan_idx;
        u8 idx;
-       u8 i;
 
        mode = rtw89_get_entity_mode(rtwdev);
        switch (mode) {
@@ -4087,34 +4086,21 @@ void rtw8852c_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_i
                break;
        }
 
-       for (i = 0; i <= chan_idx; i++) {
-               chan = rtw89_chan_get(rtwdev, i);
+       chan = rtw89_chan_get(rtwdev, chan_idx);
 
-               for (idx = 0; idx < RTW89_IQK_CHS_NR; idx++) {
-                       if (rfk_mcc->ch[idx] == chan->channel &&
-                           rfk_mcc->band[idx] == chan->band_type) {
-                               if (i != chan_idx) {
-                                       set_bit(idx, map);
-                                       break;
-                               }
+       for (idx = 0; idx < ARRAY_SIZE(desc); idx++) {
+               struct rtw89_rfk_chan_desc *p = &desc[idx];
 
-                               goto bottom;
-                       }
-               }
-       }
+               p->ch = rfk_mcc->ch[idx];
 
-       idx = find_first_zero_bit(map, RTW89_IQK_CHS_NR);
-       if (idx == RTW89_IQK_CHS_NR) {
-               rtw89_debug(rtwdev, RTW89_DBG_RFK,
-                           "%s: no empty rfk table; force replace the first\n",
-                           __func__);
-               idx = 0;
+               p->has_band = true;
+               p->band = rfk_mcc->band[idx];
        }
 
+       idx = rtw89_rfk_chan_lookup(rtwdev, desc, ARRAY_SIZE(desc), chan);
+
        rfk_mcc->ch[idx] = chan->channel;
        rfk_mcc->band[idx] = chan->band_type;
-
-bottom:
        rfk_mcc->table_idx = idx;
 }
 
index 2a371829268ccbb4295870e3265b65e11e9c26ba..0ebcb06ae84837f92ef27c6b1a36201c7c03116b 100644 (file)
@@ -255,6 +255,7 @@ static void rtw8922a_chlk_ktbl_sel(struct rtw89_dev *rtwdev, u8 kpath, u8 idx)
 static void rtw8922a_chlk_reload(struct rtw89_dev *rtwdev)
 {
        struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
+       struct rtw89_rfk_chan_desc desc[__RTW89_RFK_CHS_NR_V1] = {};
        enum rtw89_sub_entity_idx sub_entity_idx;
        const struct rtw89_chan *chan;
        enum rtw89_entity_mode mode;
@@ -265,16 +266,28 @@ static void rtw8922a_chlk_reload(struct rtw89_dev *rtwdev)
        switch (mode) {
        case RTW89_ENTITY_MODE_MCC_PREPARE:
                sub_entity_idx = RTW89_SUB_ENTITY_1;
-               tbl_sel = 1;
                break;
        default:
                sub_entity_idx = RTW89_SUB_ENTITY_0;
-               tbl_sel = 0;
                break;
        }
 
        chan = rtw89_chan_get(rtwdev, sub_entity_idx);
 
+       for (tbl_sel = 0; tbl_sel < ARRAY_SIZE(desc); tbl_sel++) {
+               struct rtw89_rfk_chan_desc *p = &desc[tbl_sel];
+
+               p->ch = rfk_mcc->ch[tbl_sel];
+
+               p->has_band = true;
+               p->band = rfk_mcc->band[tbl_sel];
+
+               p->has_bw = true;
+               p->bw = rfk_mcc->bw[tbl_sel];
+       }
+
+       tbl_sel = rtw89_rfk_chan_lookup(rtwdev, desc, ARRAY_SIZE(desc), chan);
+
        rfk_mcc->ch[tbl_sel] = chan->channel;
        rfk_mcc->band[tbl_sel] = chan->band_type;
        rfk_mcc->bw[tbl_sel] = chan->band_width;