@@ -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,
@@ -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);
@@ -4685,7 +4685,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];
@@ -2,6 +2,7 @@
/* Copyright(c) 2019-2020 Realtek Corporation
*/
+#include "chan.h"
#include "coex.h"
#include "debug.h"
#include "fw.h"
@@ -5969,6 +5970,64 @@ 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;
+}
+
+enum rtw89_rfk_chan_status
+rtw89_rfk_chan_lookup(struct rtw89_dev *rtwdev,
+ const struct rtw89_rfk_chan_desc *desc,
+ const struct rtw89_chan *target_chan)
+{
+ struct rfk_chan_iter_data iter_data = {
+ .desc = *desc,
+ };
+
+ if (rfk_chan_is_equivalent(desc, target_chan))
+ return RTW89_RFK_CHAN_MATCHED;
+
+ rtw89_iterate_entity_chan(rtwdev, rfk_chan_iter_search, &iter_data);
+ if (iter_data.found)
+ return RTW89_RFK_CHAN_BUSY;
+
+ return RTW89_RFK_CHAN_IDLE;
+}
+EXPORT_SYMBOL(rtw89_rfk_chan_lookup);
+
static void
_rfk_write_rf(struct rtw89_dev *rtwdev, const struct rtw89_reg5_def *def)
{
@@ -715,6 +715,25 @@ enum rtw89_phy_gain_band_be rtw89_subband_to_gain_band_be(enum rtw89_subband sub
}
}
+enum rtw89_rfk_chan_status {
+ RTW89_RFK_CHAN_IDLE,
+ RTW89_RFK_CHAN_BUSY,
+ RTW89_RFK_CHAN_MATCHED,
+};
+
+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 +969,9 @@ 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);
+enum rtw89_rfk_chan_status
+rtw89_rfk_chan_lookup(struct rtw89_dev *rtwdev,
+ const struct rtw89_rfk_chan_desc *desc,
+ const struct rtw89_chan *target_chan);
#endif
@@ -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) = {};
+ enum rtw89_rfk_chan_status status;
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,30 +4086,32 @@ 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);
-
- 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;
- }
-
- goto bottom;
- }
+ chan = rtw89_chan_get(rtwdev, chan_idx);
+
+ for (idx = 0; idx < __RTW89_RFK_CHS_NR_V0; idx++) {
+ struct rtw89_rfk_chan_desc desc = {
+ .ch = rfk_mcc->ch[idx],
+ .has_band = true,
+ .band = rfk_mcc->band[idx],
+ };
+
+ status = rtw89_rfk_chan_lookup(rtwdev, &desc, chan);
+ switch (status) {
+ case RTW89_RFK_CHAN_MATCHED:
+ goto bottom;
+ case RTW89_RFK_CHAN_IDLE:
+ goto fill;
+ case RTW89_RFK_CHAN_BUSY:
+ break;
}
}
- 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;
- }
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "%s: no empty rfk table; force replace the first\n",
+ __func__);
+ idx = 0;
+fill:
rfk_mcc->ch[idx] = chan->channel;
rfk_mcc->band[idx] = chan->band_type;
@@ -256,6 +256,7 @@ static void rtw8922a_chlk_reload(struct rtw89_dev *rtwdev)
{
struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
enum rtw89_sub_entity_idx sub_entity_idx;
+ enum rtw89_rfk_chan_status status;
const struct rtw89_chan *chan;
enum rtw89_entity_mode mode;
u8 s0_tbl, s1_tbl;
@@ -265,19 +266,45 @@ 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 < __RTW89_RFK_CHS_NR_V1; tbl_sel++) {
+ struct rtw89_rfk_chan_desc desc = {
+ .ch = rfk_mcc->ch[tbl_sel],
+ .has_band = true,
+ .band = rfk_mcc->band[tbl_sel],
+ .has_bw = true,
+ .bw = rfk_mcc->bw[tbl_sel],
+ };
+
+ status = rtw89_rfk_chan_lookup(rtwdev, &desc, chan);
+ switch (status) {
+ case RTW89_RFK_CHAN_MATCHED:
+ goto bottom;
+ case RTW89_RFK_CHAN_IDLE:
+ goto fill;
+ case RTW89_RFK_CHAN_BUSY:
+ break;
+ }
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "%s: no empty rfk table; force replace the first\n",
+ __func__);
+ tbl_sel = 0;
+
+fill:
rfk_mcc->ch[tbl_sel] = chan->channel;
rfk_mcc->band[tbl_sel] = chan->band_type;
rfk_mcc->bw[tbl_sel] = chan->band_width;
+
+bottom:
rfk_mcc->table_idx = tbl_sel;
s0_tbl = tbl_sel;