Skip to content

Commit

Permalink
wifi: rtw89: chan: manage active interfaces
Browse files Browse the repository at this point in the history
To set channel well for combination of MCC (multi-channel concurrency) and
impending MLO support, we need a method to manage relation between active
interfaces and channel contexts. If an interface owns at least one active
link, we call it an active interface. We add a list to manage active ones.

Basically, the list follows the active order except for the below case. To
be compatible with legacy behavior, the first interface that owns the first
channel context will put at the first entry in the list when recalculating.

Besides, MCC can also select and fill roles based on the above active list.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20241022083106.149252-4-pkshih@realtek.com
  • Loading branch information
Zong-Zhe Yang authored and Ping-Ke Shih committed Oct 29, 2024
1 parent c39eed4 commit 68ec751
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 13 deletions.
105 changes: 94 additions & 11 deletions drivers/net/wireless/realtek/rtw89/chan.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
#include "ps.h"
#include "util.h"

static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev,
enum rtw89_chanctx_idx idx1,
enum rtw89_chanctx_idx idx2);

static enum rtw89_subband rtw89_get_subband_type(enum rtw89_band band,
u8 center_chan)
{
Expand Down Expand Up @@ -226,11 +230,15 @@ static void rtw89_config_default_chandef(struct rtw89_dev *rtwdev)
void rtw89_entity_init(struct rtw89_dev *rtwdev)
{
struct rtw89_hal *hal = &rtwdev->hal;
struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;

hal->entity_pause = false;
bitmap_zero(hal->entity_map, NUM_OF_RTW89_CHANCTX);
bitmap_zero(hal->changes, NUM_OF_RTW89_CHANCTX_CHANGES);
atomic_set(&hal->roc_chanctx_idx, RTW89_CHANCTX_IDLE);

INIT_LIST_HEAD(&mgnt->active_list);

rtw89_config_default_chandef(rtwdev);
}

Expand Down Expand Up @@ -272,6 +280,71 @@ static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev,
}
}

static void rtw89_normalize_link_chanctx(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link)
{
struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
struct rtw89_vif_link *cur;

if (unlikely(!rtwvif_link->chanctx_assigned))
return;

cur = rtw89_vif_get_link_inst(rtwvif, 0);
if (!cur || !cur->chanctx_assigned)
return;

if (cur == rtwvif_link)
return;

rtw89_swap_chanctx(rtwdev, rtwvif_link->chanctx_idx, cur->chanctx_idx);
}

static void rtw89_entity_recalc_mgnt_roles(struct rtw89_dev *rtwdev)
{
struct rtw89_hal *hal = &rtwdev->hal;
struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
struct rtw89_vif_link *link;
struct rtw89_vif *role;
u8 pos = 0;
int i;

lockdep_assert_held(&rtwdev->mutex);

for (i = 0; i < RTW89_MAX_INTERFACE_NUM; i++)
mgnt->active_roles[i] = NULL;

/* To be consistent with legacy behavior, expect the first active role
* which uses RTW89_CHANCTX_0 to put at position 0, and make its first
* link instance take RTW89_CHANCTX_0. (normalizing)
*/
list_for_each_entry(role, &mgnt->active_list, mgnt_entry) {
for (i = 0; i < role->links_inst_valid_num; i++) {
link = rtw89_vif_get_link_inst(role, i);
if (!link || !link->chanctx_assigned)
continue;

if (link->chanctx_idx == RTW89_CHANCTX_0) {
rtw89_normalize_link_chanctx(rtwdev, link);

list_del(&role->mgnt_entry);
list_add(&role->mgnt_entry, &mgnt->active_list);
break;
}
}
}

list_for_each_entry(role, &mgnt->active_list, mgnt_entry) {
if (unlikely(pos >= RTW89_MAX_INTERFACE_NUM)) {
rtw89_warn(rtwdev,
"%s: active roles are over max iface num\n",
__func__);
break;
}

mgnt->active_roles[pos++] = role;
}
}

enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
{
DECLARE_BITMAP(recalc_map, NUM_OF_RTW89_CHANCTX) = {};
Expand Down Expand Up @@ -327,6 +400,8 @@ enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
rtw89_assign_entity_chan(rtwdev, idx, &chan);
}

rtw89_entity_recalc_mgnt_roles(rtwdev);

if (hal->entity_pause)
return rtw89_get_entity_mode(rtwdev);

Expand Down Expand Up @@ -716,6 +791,7 @@ struct rtw89_mcc_fill_role_selector {
};

static_assert((u8)NUM_OF_RTW89_CHANCTX >= NUM_OF_RTW89_MCC_ROLES);
static_assert(RTW89_MAX_INTERFACE_NUM >= NUM_OF_RTW89_MCC_ROLES);

static int rtw89_mcc_fill_role_iterator(struct rtw89_dev *rtwdev,
struct rtw89_mcc_role *mcc_role,
Expand Down Expand Up @@ -745,29 +821,26 @@ static int rtw89_mcc_fill_role_iterator(struct rtw89_dev *rtwdev,

static int rtw89_mcc_fill_all_roles(struct rtw89_dev *rtwdev)
{
struct rtw89_hal *hal = &rtwdev->hal;
struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
struct rtw89_mcc_fill_role_selector sel = {};
struct rtw89_vif_link *rtwvif_link;
struct rtw89_vif *rtwvif;
int ret;
int i;

rtw89_for_each_rtwvif(rtwdev, rtwvif) {
if (!rtw89_vif_is_active_role(rtwvif))
continue;
for (i = 0; i < NUM_OF_RTW89_MCC_ROLES; i++) {
rtwvif = mgnt->active_roles[i];
if (!rtwvif)
break;

rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
if (unlikely(!rtwvif_link)) {
rtw89_err(rtwdev, "mcc fill roles: find no link on HW-0\n");
continue;
}

if (sel.bind_vif[rtwvif_link->chanctx_idx]) {
rtw89_warn(rtwdev,
"MCC skip extra vif <macid %d> on chanctx[%d]\n",
rtwvif_link->mac_id, rtwvif_link->chanctx_idx);
continue;
}

sel.bind_vif[rtwvif_link->chanctx_idx] = rtwvif_link;
sel.bind_vif[i] = rtwvif_link;
}

ret = rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_fill_role_iterator, &sel);
Expand Down Expand Up @@ -2501,12 +2574,18 @@ 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_vif *rtwvif = rtwvif_link->rtwvif;
struct rtw89_hal *hal = &rtwdev->hal;
struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
struct rtw89_entity_weight w = {};

rtwvif_link->chanctx_idx = cfg->idx;
rtwvif_link->chanctx_assigned = true;
cfg->ref_count++;

if (list_empty(&rtwvif->mgnt_entry))
list_add_tail(&rtwvif->mgnt_entry, &mgnt->active_list);

if (cfg->idx == RTW89_CHANCTX_0)
goto out;

Expand All @@ -2526,6 +2605,7 @@ 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_vif *rtwvif = rtwvif_link->rtwvif;
struct rtw89_hal *hal = &rtwdev->hal;
enum rtw89_chanctx_idx roll;
enum rtw89_entity_mode cur;
Expand All @@ -2536,6 +2616,9 @@ void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
rtwvif_link->chanctx_assigned = false;
cfg->ref_count--;

if (!rtw89_vif_is_active_role(rtwvif))
list_del_init(&rtwvif->mgnt_entry);

if (cfg->ref_count != 0)
goto out;

Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/realtek/rtw89/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,13 @@ static const struct ieee80211_iface_combination rtw89_iface_combs[] = {
{
.limits = rtw89_iface_limits,
.n_limits = ARRAY_SIZE(rtw89_iface_limits),
.max_interfaces = 2,
.max_interfaces = RTW89_MAX_INTERFACE_NUM,
.num_different_channels = 1,
},
{
.limits = rtw89_iface_limits_mcc,
.n_limits = ARRAY_SIZE(rtw89_iface_limits_mcc),
.max_interfaces = 2,
.max_interfaces = RTW89_MAX_INTERFACE_NUM,
.num_different_channels = 2,
},
};
Expand Down
10 changes: 10 additions & 0 deletions drivers/net/wireless/realtek/rtw89/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -4635,6 +4635,14 @@ enum rtw89_entity_mode {
RTW89_ENTITY_MODE_UNHANDLED = -ESRCH,
};

#define RTW89_MAX_INTERFACE_NUM 2

/* only valid when running with chanctx_ops */
struct rtw89_entity_mgnt {
struct list_head active_list;
struct rtw89_vif *active_roles[RTW89_MAX_INTERFACE_NUM];
};

struct rtw89_chanctx {
struct cfg80211_chan_def chandef;
struct rtw89_chan chan;
Expand Down Expand Up @@ -4682,6 +4690,7 @@ struct rtw89_hal {
bool entity_active[RTW89_PHY_MAX];
bool entity_pause;
enum rtw89_entity_mode entity_mode;
struct rtw89_entity_mgnt entity_mgnt;

struct rtw89_edcca_bak edcca_bak;
u32 disabled_dm_bitmap; /* bitmap of enum rtw89_dm_type */
Expand Down Expand Up @@ -5636,6 +5645,7 @@ struct rtw89_dev {
struct rtw89_vif {
struct rtw89_dev *rtwdev;
struct list_head list;
struct list_head mgnt_entry;

u8 mac_addr[ETH_ALEN];
__be32 ip_addr;
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/realtek/rtw89/mac80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
if (!rtw89_rtwvif_in_list(rtwdev, rtwvif))
list_add_tail(&rtwvif->list, &rtwdev->rtwvifs_list);

INIT_LIST_HEAD(&rtwvif->mgnt_entry);

ether_addr_copy(rtwvif->mac_addr, vif->addr);

rtwvif->offchan = false;
Expand Down

0 comments on commit 68ec751

Please sign in to comment.