2024-02-06 03:07:17

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH 0/6] wifi: rtw89: adjust channel context stuffs for MCC and MLO

We are going to add MCC for WiFi 7 chips that uses similar flow like
WiFi 6 chips but new firmware H2C commands and events are added, because
these new firmware interfaces will support MCC over MLO as well. Before
that, we are adjusting the channel context stuffs by this patchset. Since
we still not support MLO yet, mostly we are adjusting to support legacy MCC.

Zong-Zhe Yang (6):
wifi: rtw89: drop TIMING_BEACON_ONLY and sync beacon TSF by self
wifi: rtw89: chan: add sub-entity swap function to cover replacing
wifi: rtw89: chan: tweak bitmap recalc ahead before MLO
wifi: rtw89: chan: tweak weight recalc ahead before MLO
wifi: rtw89: chan: move handling from add/remove to assign/unassign
for MLO
wifi: rtw89: chan: MCC take reconfig into account

drivers/net/wireless/realtek/rtw89/chan.c | 204 ++++++++++++------
drivers/net/wireless/realtek/rtw89/chan.h | 5 +
drivers/net/wireless/realtek/rtw89/core.c | 23 +-
drivers/net/wireless/realtek/rtw89/core.h | 9 +-
drivers/net/wireless/realtek/rtw89/mac80211.c | 1 +
5 files changed, 174 insertions(+), 68 deletions(-)

--
2.25.1



2024-02-06 03:07:22

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH 1/6] wifi: rtw89: drop TIMING_BEACON_ONLY and sync beacon TSF by self

From: Zong-Zhe Yang <[email protected]>

Some of our calculation during concurrent mode depend on last beacon
TSF. Originally, we just set IEEE80211_HW_TIMING_BEACON_ONLY and get
what we want from mac80211. But, IEEE80211_HW_TIMING_BEACON_ONLY will
be restricted once we declare MLO.

Since we are about to consider the MLO stuffs, so sync beacon TSF by
ourselves now and unset IEEE80211_HW_TIMING_BEACON_ONLY.

Signed-off-by: Zong-Zhe Yang <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
---
drivers/net/wireless/realtek/rtw89/chan.c | 9 +--------
drivers/net/wireless/realtek/rtw89/core.c | 18 ++++++++++++++----
drivers/net/wireless/realtek/rtw89/core.h | 1 +
drivers/net/wireless/realtek/rtw89/mac80211.c | 1 +
4 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c
index 21449cb9b069..2a95f9db83f9 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.c
+++ b/drivers/net/wireless/realtek/rtw89/chan.c
@@ -320,19 +320,12 @@ int rtw89_iterate_mcc_roles(struct rtw89_dev *rtwdev,
return 0;
}

-/* For now, IEEE80211_HW_TIMING_BEACON_ONLY can make things simple to ensure
- * correctness of MCC calculation logic below. We have noticed that once driver
- * declares WIPHY_FLAG_SUPPORTS_MLO, the use of IEEE80211_HW_TIMING_BEACON_ONLY
- * will be restricted. We will make an alternative in driver when it is ready
- * for MLO.
- */
static u32 rtw89_mcc_get_tbtt_ofst(struct rtw89_dev *rtwdev,
struct rtw89_mcc_role *role, u64 tsf)
{
struct rtw89_vif *rtwvif = role->rtwvif;
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
u32 bcn_intvl_us = ieee80211_tu_to_usec(role->beacon_interval);
- u64 sync_tsf = vif->bss_conf.sync_tsf;
+ u64 sync_tsf = READ_ONCE(rtwvif->sync_bcn_tsf);
u32 remainder;

if (tsf < sync_tsf) {
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 260da86bf04a..de4c37c48f4e 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -1868,6 +1868,17 @@ static void rtw89_core_cancel_6ghz_probe_tx(struct rtw89_dev *rtwdev,
ieee80211_queue_work(rtwdev->hw, &rtwdev->cancel_6ghz_probe_work);
}

+static void rtw89_vif_sync_bcn_tsf(struct rtw89_vif *rtwvif,
+ struct ieee80211_hdr *hdr, size_t len)
+{
+ struct ieee80211_mgmt *mgmt = (typeof(mgmt))hdr;
+
+ if (len < offsetof(typeof(*mgmt), u.beacon.variable))
+ return;
+
+ WRITE_ONCE(rtwvif->sync_bcn_tsf, le64_to_cpu(mgmt->u.beacon.timestamp));
+}
+
static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
@@ -1898,8 +1909,10 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
return;

if (ieee80211_is_beacon(hdr->frame_control)) {
- if (vif->type == NL80211_IFTYPE_STATION)
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ rtw89_vif_sync_bcn_tsf(rtwvif, hdr, skb->len);
rtw89_fw_h2c_rssi_offload(rtwdev, phy_ppdu);
+ }
pkt_stat->beacon_nr++;
}

@@ -4445,9 +4458,6 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
ieee80211_hw_set(hw, WANT_MONITOR_VIF);

- /* ref: description of rtw89_mcc_get_tbtt_ofst() in chan.c */
- ieee80211_hw_set(hw, TIMING_BEACON_ONLY);
-
if (chip->support_bandwidths & BIT(NL80211_CHAN_WIDTH_160))
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);

diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 30cc77ac78c5..927356861cb8 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -3043,6 +3043,7 @@ struct rtw89_vif {
u8 bcn_hit_cond;
u8 hit_rule;
u8 last_noa_nr;
+ u64 sync_bcn_tsf;
bool offchan;
bool trigger;
bool lsig_txop;
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index b61c5be8cae3..31d1ffb16e83 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -449,6 +449,7 @@ static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw,
ether_addr_copy(rtwvif->bssid, conf->bssid);
rtw89_cam_bssid_changed(rtwdev, rtwvif);
rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL);
+ WRITE_ONCE(rtwvif->sync_bcn_tsf, 0);
}

if (changed & BSS_CHANGED_BEACON)
--
2.25.1


2024-02-06 03:07:26

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH 2/6] wifi: rtw89: chan: add sub-entity swap function to cover replacing

From: Zong-Zhe Yang <[email protected]>

Originally, we replaced sub-entity of index 0 with another one in some
cases. However, we will need a swap here in following implementations.
So, we introduce it ahead and change code from replacing to swapping.

Signed-off-by: Zong-Zhe Yang <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
---
drivers/net/wireless/realtek/rtw89/chan.c | 47 +++++++++++++++++------
1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c
index 2a95f9db83f9..11d46878f51e 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.c
+++ b/drivers/net/wireless/realtek/rtw89/chan.c
@@ -1893,6 +1893,41 @@ void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev)
rtw89_queue_chanctx_work(rtwdev);
}

+static void rtw89_swap_sub_entity(struct rtw89_dev *rtwdev,
+ enum rtw89_sub_entity_idx idx1,
+ enum rtw89_sub_entity_idx idx2)
+{
+ struct rtw89_hal *hal = &rtwdev->hal;
+ struct rtw89_sub_entity tmp;
+ struct rtw89_vif *rtwvif;
+ u8 cur;
+
+ if (idx1 == idx2)
+ return;
+
+ hal->sub[idx1].cfg->idx = idx2;
+ hal->sub[idx2].cfg->idx = idx1;
+
+ tmp = hal->sub[idx1];
+ hal->sub[idx1] = hal->sub[idx2];
+ hal->sub[idx2] = tmp;
+
+ rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+ if (!rtwvif->chanctx_assigned)
+ continue;
+ if (rtwvif->sub_entity_idx == idx1)
+ rtwvif->sub_entity_idx = idx2;
+ else if (rtwvif->sub_entity_idx == idx2)
+ rtwvif->sub_entity_idx = idx1;
+ }
+
+ cur = atomic_read(&hal->roc_entity_idx);
+ if (cur == idx1)
+ atomic_set(&hal->roc_entity_idx, idx2);
+ else if (cur == idx2)
+ atomic_set(&hal->roc_entity_idx, idx1);
+}
+
int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
struct ieee80211_chanctx_conf *ctx)
{
@@ -1918,7 +1953,6 @@ void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,
struct rtw89_hal *hal = &rtwdev->hal;
struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
enum rtw89_entity_mode mode;
- struct rtw89_vif *rtwvif;
u8 drop, roll;

drop = cfg->idx;
@@ -1934,16 +1968,7 @@ void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,
/* RTW89_SUB_ENTITY_0 is going to release, and another exists.
* Make another roll down to RTW89_SUB_ENTITY_0 to replace.
*/
- hal->sub[roll].cfg->idx = RTW89_SUB_ENTITY_0;
- hal->sub[RTW89_SUB_ENTITY_0] = hal->sub[roll];
-
- rtw89_for_each_rtwvif(rtwdev, rtwvif) {
- if (rtwvif->sub_entity_idx == roll)
- rtwvif->sub_entity_idx = RTW89_SUB_ENTITY_0;
- }
-
- atomic_cmpxchg(&hal->roc_entity_idx, roll, RTW89_SUB_ENTITY_0);
-
+ rtw89_swap_sub_entity(rtwdev, RTW89_SUB_ENTITY_0, roll);
drop = roll;

out:
--
2.25.1


2024-02-06 03:07:36

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH 4/6] wifi: rtw89: chan: tweak weight recalc ahead before MLO

From: Zong-Zhe Yang <[email protected]>

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 <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
---
drivers/net/wireless/realtek/rtw89/chan.c | 51 ++++++++++++++++++++---
drivers/net/wireless/realtek/rtw89/chan.h | 5 +++
drivers/net/wireless/realtek/rtw89/core.h | 6 ++-
3 files changed, 56 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c
index 6a666a92b59b..57fabc05dab9 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.c
+++ b/drivers/net/wireless/realtek/rtw89/chan.c
@@ -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--;
}
diff --git a/drivers/net/wireless/realtek/rtw89/chan.h b/drivers/net/wireless/realtek/rtw89/chan.h
index 9b98d8f4ee9d..ffa412f281f3 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.h
+++ b/drivers/net/wireless/realtek/rtw89/chan.h
@@ -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;
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 927356861cb8..ba2b298c4a9b 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -4119,6 +4119,7 @@ struct rtw89_tas_info {

struct rtw89_chanctx_cfg {
enum rtw89_sub_entity_idx idx;
+ int ref_count;
};

enum rtw89_chanctx_changes {
@@ -4138,13 +4139,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;
};

--
2.25.1


2024-02-06 03:07:40

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH 5/6] wifi: rtw89: chan: move handling from add/remove to assign/unassign for MLO

From: Zong-Zhe Yang <[email protected]>

After MLO, we will need to consider not only active chanctx but also active
interfaces (roles) to decide entity things. So in advance, we move handling
from chanctx_ops::add/remove to chanctx_ops::assign_vif/unassign_vif. Then,
we can recalculate and aware active interfaces' changes.

For now, behavior should not be really different, since active chanctx and
active interface are one-to-one mapping before MLO.

Signed-off-by: Zong-Zhe Yang <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
---
drivers/net/wireless/realtek/rtw89/chan.c | 75 +++++++++++++----------
drivers/net/wireless/realtek/rtw89/core.c | 5 +-
drivers/net/wireless/realtek/rtw89/core.h | 2 +-
3 files changed, 47 insertions(+), 35 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c
index 57fabc05dab9..71fe0d3ab3b0 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.c
+++ b/drivers/net/wireless/realtek/rtw89/chan.c
@@ -1979,7 +1979,6 @@ int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
return -ENOENT;

rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
- rtw89_set_channel(rtwdev);
cfg->idx = idx;
hal->sub[idx].cfg = cfg;
return 0;
@@ -1990,37 +1989,8 @@ void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,
{
struct rtw89_hal *hal = &rtwdev->hal;
struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
- enum rtw89_entity_mode mode;
- u8 drop, roll;
-
- drop = cfg->idx;
- if (drop != RTW89_SUB_ENTITY_0)
- goto out;
-
- roll = find_next_bit(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY, drop + 1);
-
- /* Follow rtw89_config_default_chandef() when rtw89_entity_recalc(). */
- if (roll == NUM_OF_RTW89_SUB_ENTITY)
- goto out;
-
- /* RTW89_SUB_ENTITY_0 is going to release, and another exists.
- * Make another roll down to RTW89_SUB_ENTITY_0 to replace.
- */
- rtw89_swap_sub_entity(rtwdev, RTW89_SUB_ENTITY_0, roll);
- drop = roll;

-out:
- mode = rtw89_get_entity_mode(rtwdev);
- switch (mode) {
- case RTW89_ENTITY_MODE_MCC:
- rtw89_mcc_stop(rtwdev);
- break;
- default:
- break;
- }
-
- clear_bit(drop, hal->entity_map);
- rtw89_set_channel(rtwdev);
+ clear_bit(cfg->idx, hal->entity_map);
}

void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev,
@@ -2045,7 +2015,8 @@ 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;
+
+ return rtw89_set_channel(rtwdev);
}

void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
@@ -2053,8 +2024,48 @@ void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
struct ieee80211_chanctx_conf *ctx)
{
struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ struct rtw89_entity_weight w = {};
+ enum rtw89_sub_entity_idx roll;
+ enum rtw89_entity_mode cur;

rtwvif->sub_entity_idx = RTW89_SUB_ENTITY_0;
rtwvif->chanctx_assigned = false;
cfg->ref_count--;
+
+ if (cfg->ref_count != 0)
+ goto out;
+
+ if (cfg->idx != RTW89_SUB_ENTITY_0)
+ goto out;
+
+ roll = find_next_bit(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY,
+ cfg->idx + 1);
+ /* Follow rtw89_config_default_chandef() when rtw89_entity_recalc(). */
+ if (roll == NUM_OF_RTW89_SUB_ENTITY)
+ goto out;
+
+ /* RTW89_SUB_ENTITY_0 is going to release, and another exists.
+ * Make another roll down to RTW89_SUB_ENTITY_0 to replace.
+ */
+ rtw89_swap_sub_entity(rtwdev, cfg->idx, roll);
+
+out:
+ rtw89_entity_calculate_weight(rtwdev, &w);
+
+ cur = rtw89_get_entity_mode(rtwdev);
+ switch (cur) {
+ case RTW89_ENTITY_MODE_MCC:
+ /* If still multi-roles, re-plan MCC for chanctx changes.
+ * Otherwise, just stop MCC.
+ */
+ rtw89_mcc_stop(rtwdev);
+ if (w.active_roles == NUM_OF_RTW89_MCC_ROLES)
+ rtw89_mcc_start(rtwdev);
+ break;
+ default:
+ break;
+ }
+
+ rtw89_set_channel(rtwdev);
}
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index de4c37c48f4e..1da01514f171 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -372,7 +372,7 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev)
chip->ops->set_txpwr(rtwdev, chan, phy_idx);
}

-void rtw89_set_channel(struct rtw89_dev *rtwdev)
+int rtw89_set_channel(struct rtw89_dev *rtwdev)
{
struct rtw89_hal *hal = &rtwdev->hal;
const struct rtw89_chip_info *chip = rtwdev->chip;
@@ -399,7 +399,7 @@ void rtw89_set_channel(struct rtw89_dev *rtwdev)
break;
default:
WARN(1, "Invalid ent mode: %d\n", mode);
- return;
+ return -EINVAL;
}

roc_idx = atomic_read(&hal->roc_entity_idx);
@@ -426,6 +426,7 @@ void rtw89_set_channel(struct rtw89_dev *rtwdev)
}

rtw89_set_entity_state(rtwdev, true);
+ return 0;
}

void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index ba2b298c4a9b..c20d21f5b0a6 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -5987,7 +5987,7 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev);
void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef);
void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef,
struct rtw89_chan *chan);
-void rtw89_set_channel(struct rtw89_dev *rtwdev);
+int rtw89_set_channel(struct rtw89_dev *rtwdev);
void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
struct rtw89_chan *chan);
u8 rtw89_core_acquire_bit_map(unsigned long *addr, unsigned long size);
--
2.25.1


2024-02-06 03:07:45

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH 6/6] wifi: rtw89: chan: MCC take reconfig into account

From: Zong-Zhe Yang <[email protected]>

During mac80211 reconfig, chanctx ops of multiple channels might not
be called in order as normal cases. However, we expect the first active
chanctx always to be put at our sub entity index 0. So, if it does not,
we do a swap there. Besides, reconfig won't allocate a new chanctx object.
So, we should reset the reference count when ops add chanctx.

Signed-off-by: Zong-Zhe Yang <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
---
drivers/net/wireless/realtek/rtw89/chan.c | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c
index 71fe0d3ab3b0..7b9baf4db70f 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.c
+++ b/drivers/net/wireless/realtek/rtw89/chan.c
@@ -1980,6 +1980,7 @@ int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,

rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
cfg->idx = idx;
+ cfg->ref_count = 0;
hal->sub[idx].cfg = cfg;
return 0;
}
@@ -2011,11 +2012,23 @@ int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
struct ieee80211_chanctx_conf *ctx)
{
struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
+ struct rtw89_entity_weight w = {};

rtwvif->sub_entity_idx = cfg->idx;
rtwvif->chanctx_assigned = true;
cfg->ref_count++;

+ if (cfg->idx == RTW89_SUB_ENTITY_0)
+ goto out;
+
+ rtw89_entity_calculate_weight(rtwdev, &w);
+ if (w.active_chanctxs != 1)
+ goto out;
+
+ /* put the first active chanctx at RTW89_SUB_ENTITY_0 */
+ rtw89_swap_sub_entity(rtwdev, cfg->idx, RTW89_SUB_ENTITY_0);
+
+out:
return rtw89_set_channel(rtwdev);
}

--
2.25.1


2024-02-06 03:08:43

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH 3/6] wifi: rtw89: chan: tweak bitmap recalc ahead before MLO

From: Zong-Zhe Yang <[email protected]>

Originally, we just declared two sub-entity, and according to rolling
down mechanism, we ensured that index 0 contained sub-entity as long
as there are sub-entity. So, we could use for-loop after deciding the
last index.

But, we are preparing to expand num of sub-entity for MLO. Then, there
won't be just two sub-entity. And, there might be holes between two bits
in the bitmap. So, we cannot simply do for-loop as before. Instead, we
need to follow the set bits.

Signed-off-by: Zong-Zhe Yang <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
---
drivers/net/wireless/realtek/rtw89/chan.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c
index 11d46878f51e..6a666a92b59b 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.c
+++ b/drivers/net/wireless/realtek/rtw89/chan.c
@@ -214,31 +214,32 @@ void rtw89_entity_init(struct rtw89_dev *rtwdev)

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;
enum rtw89_entity_mode mode;
struct rtw89_chan chan;
u8 weight;
- u8 last;
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) {
default:
rtw89_warn(rtwdev, "unknown ent chan weight: %d\n", weight);
- bitmap_zero(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
+ bitmap_zero(recalc_map, NUM_OF_RTW89_SUB_ENTITY);
fallthrough;
case 0:
rtw89_config_default_chandef(rtwdev);
+ set_bit(RTW89_SUB_ENTITY_0, recalc_map);
fallthrough;
case 1:
- last = RTW89_SUB_ENTITY_0;
mode = RTW89_ENTITY_MODE_SCC;
break;
case 2:
- last = RTW89_SUB_ENTITY_1;
mode = rtw89_get_entity_mode(rtwdev);
if (mode == RTW89_ENTITY_MODE_MCC)
break;
@@ -247,7 +248,7 @@ enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
break;
}

- for (idx = 0; idx <= last; idx++) {
+ for_each_set_bit(idx, recalc_map, NUM_OF_RTW89_SUB_ENTITY) {
chandef = rtw89_chandef_get(rtwdev, idx);
rtw89_get_channel_params(chandef, &chan);
if (chan.channel == 0) {
--
2.25.1


2024-02-12 15:44:21

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 1/6] wifi: rtw89: drop TIMING_BEACON_ONLY and sync beacon TSF by self

Ping-Ke Shih <[email protected]> wrote:

> From: Zong-Zhe Yang <[email protected]>
>
> Some of our calculation during concurrent mode depend on last beacon
> TSF. Originally, we just set IEEE80211_HW_TIMING_BEACON_ONLY and get
> what we want from mac80211. But, IEEE80211_HW_TIMING_BEACON_ONLY will
> be restricted once we declare MLO.
>
> Since we are about to consider the MLO stuffs, so sync beacon TSF by
> ourselves now and unset IEEE80211_HW_TIMING_BEACON_ONLY.
>
> Signed-off-by: Zong-Zhe Yang <[email protected]>
> Signed-off-by: Ping-Ke Shih <[email protected]>

6 patches applied to wireless-next.git, thanks.

188045a85614 wifi: rtw89: drop TIMING_BEACON_ONLY and sync beacon TSF by self
4f0beeefcce8 wifi: rtw89: chan: add sub-entity swap function to cover replacing
ab12a3bfbf77 wifi: rtw89: chan: tweak bitmap recalc ahead before MLO
d79fa0a6d8c2 wifi: rtw89: chan: tweak weight recalc ahead before MLO
1ae9fbaf22ee wifi: rtw89: chan: move handling from add/remove to assign/unassign for MLO
162bf67f74c7 wifi: rtw89: chan: MCC take reconfig into account

--
https://patchwork.kernel.org/project/linux-wireless/patch/[email protected]/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches