mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
wifi: mac80211: add and use chanctx usage iteration
In preparation for NAN interfaces using multiple channel contexts, add an iterator macro that iterates all users of a given channel context. The logic during reserved assign/reassign handling the bandwidth in ieee80211_get_chanctx_max_required_bw() is a bit more complicated and should be cleaned up, so it isn't yet converted. Link: https://patch.msgid.link/20251105160431.5aaccc2f127d.I2b7fd0858a263916f43abab49c6d3cc0b5aa16ec@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
@@ -12,18 +12,132 @@
|
|||||||
#include "driver-ops.h"
|
#include "driver-ops.h"
|
||||||
#include "rate.h"
|
#include "rate.h"
|
||||||
|
|
||||||
|
struct ieee80211_chanctx_user_iter {
|
||||||
|
struct ieee80211_chan_req *chanreq;
|
||||||
|
struct ieee80211_sub_if_data *sdata;
|
||||||
|
struct ieee80211_link_data *link;
|
||||||
|
enum nl80211_iftype iftype;
|
||||||
|
bool reserved, radar_required, done;
|
||||||
|
enum {
|
||||||
|
CHANCTX_ITER_POS_ASSIGNED,
|
||||||
|
CHANCTX_ITER_POS_RESERVED,
|
||||||
|
CHANCTX_ITER_POS_DONE,
|
||||||
|
} per_link;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ieee80211_chanctx_iter_type {
|
||||||
|
CHANCTX_ITER_ALL,
|
||||||
|
CHANCTX_ITER_RESERVED,
|
||||||
|
CHANCTX_ITER_ASSIGNED,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ieee80211_chanctx_user_iter_next(struct ieee80211_local *local,
|
||||||
|
struct ieee80211_chanctx *ctx,
|
||||||
|
struct ieee80211_chanctx_user_iter *iter,
|
||||||
|
enum ieee80211_chanctx_iter_type type,
|
||||||
|
bool start)
|
||||||
|
{
|
||||||
|
lockdep_assert_wiphy(local->hw.wiphy);
|
||||||
|
|
||||||
|
if (start) {
|
||||||
|
memset(iter, 0, sizeof(*iter));
|
||||||
|
goto next_interface;
|
||||||
|
}
|
||||||
|
|
||||||
|
next_link:
|
||||||
|
for (int link_id = iter->link ? iter->link->link_id : 0;
|
||||||
|
link_id < ARRAY_SIZE(iter->sdata->link);
|
||||||
|
link_id++) {
|
||||||
|
struct ieee80211_link_data *link;
|
||||||
|
|
||||||
|
link = sdata_dereference(iter->sdata->link[link_id],
|
||||||
|
iter->sdata);
|
||||||
|
if (!link)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (iter->per_link) {
|
||||||
|
case CHANCTX_ITER_POS_ASSIGNED:
|
||||||
|
iter->per_link = CHANCTX_ITER_POS_RESERVED;
|
||||||
|
if (type != CHANCTX_ITER_RESERVED &&
|
||||||
|
rcu_access_pointer(link->conf->chanctx_conf) == &ctx->conf) {
|
||||||
|
iter->link = link;
|
||||||
|
iter->reserved = false;
|
||||||
|
iter->radar_required = link->radar_required;
|
||||||
|
iter->chanreq = &link->conf->chanreq;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fallthrough;
|
||||||
|
case CHANCTX_ITER_POS_RESERVED:
|
||||||
|
iter->per_link = CHANCTX_ITER_POS_DONE;
|
||||||
|
if (type != CHANCTX_ITER_ASSIGNED &&
|
||||||
|
link->reserved_chanctx == ctx) {
|
||||||
|
iter->link = link;
|
||||||
|
iter->reserved = true;
|
||||||
|
iter->radar_required =
|
||||||
|
link->reserved_radar_required;
|
||||||
|
|
||||||
|
iter->chanreq = &link->reserved;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fallthrough;
|
||||||
|
case CHANCTX_ITER_POS_DONE:
|
||||||
|
iter->per_link = CHANCTX_ITER_POS_ASSIGNED;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next_interface:
|
||||||
|
/* next (or first) interface */
|
||||||
|
iter->sdata = list_prepare_entry(iter->sdata, &local->interfaces, list);
|
||||||
|
list_for_each_entry_continue(iter->sdata, &local->interfaces, list) {
|
||||||
|
/* AP_VLAN has a chanctx pointer but follows AP */
|
||||||
|
if (iter->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
iter->link = NULL;
|
||||||
|
iter->per_link = CHANCTX_ITER_POS_ASSIGNED;
|
||||||
|
iter->iftype = iter->sdata->vif.type;
|
||||||
|
goto next_link;
|
||||||
|
}
|
||||||
|
|
||||||
|
iter->done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define for_each_chanctx_user_assigned(local, ctx, iter) \
|
||||||
|
for (ieee80211_chanctx_user_iter_next(local, ctx, iter, \
|
||||||
|
CHANCTX_ITER_ASSIGNED, \
|
||||||
|
true); \
|
||||||
|
!((iter)->done); \
|
||||||
|
ieee80211_chanctx_user_iter_next(local, ctx, iter, \
|
||||||
|
CHANCTX_ITER_ASSIGNED, \
|
||||||
|
false))
|
||||||
|
|
||||||
|
#define for_each_chanctx_user_reserved(local, ctx, iter) \
|
||||||
|
for (ieee80211_chanctx_user_iter_next(local, ctx, iter, \
|
||||||
|
CHANCTX_ITER_RESERVED, \
|
||||||
|
true); \
|
||||||
|
!((iter)->done); \
|
||||||
|
ieee80211_chanctx_user_iter_next(local, ctx, iter, \
|
||||||
|
CHANCTX_ITER_RESERVED, \
|
||||||
|
false))
|
||||||
|
|
||||||
|
#define for_each_chanctx_user_all(local, ctx, iter) \
|
||||||
|
for (ieee80211_chanctx_user_iter_next(local, ctx, iter, \
|
||||||
|
CHANCTX_ITER_ALL, \
|
||||||
|
true); \
|
||||||
|
!((iter)->done); \
|
||||||
|
ieee80211_chanctx_user_iter_next(local, ctx, iter, \
|
||||||
|
CHANCTX_ITER_ALL, \
|
||||||
|
false))
|
||||||
|
|
||||||
static int ieee80211_chanctx_num_assigned(struct ieee80211_local *local,
|
static int ieee80211_chanctx_num_assigned(struct ieee80211_local *local,
|
||||||
struct ieee80211_chanctx *ctx)
|
struct ieee80211_chanctx *ctx)
|
||||||
{
|
{
|
||||||
struct ieee80211_link_data *link;
|
struct ieee80211_chanctx_user_iter iter;
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
|
||||||
lockdep_assert_wiphy(local->hw.wiphy);
|
for_each_chanctx_user_assigned(local, ctx, &iter)
|
||||||
|
num++;
|
||||||
for_each_sdata_link(local, link) {
|
|
||||||
if (rcu_access_pointer(link->conf->chanctx_conf) == &ctx->conf)
|
|
||||||
num++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
@@ -31,15 +145,11 @@ static int ieee80211_chanctx_num_assigned(struct ieee80211_local *local,
|
|||||||
static int ieee80211_chanctx_num_reserved(struct ieee80211_local *local,
|
static int ieee80211_chanctx_num_reserved(struct ieee80211_local *local,
|
||||||
struct ieee80211_chanctx *ctx)
|
struct ieee80211_chanctx *ctx)
|
||||||
{
|
{
|
||||||
struct ieee80211_link_data *link;
|
struct ieee80211_chanctx_user_iter iter;
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
|
||||||
lockdep_assert_wiphy(local->hw.wiphy);
|
for_each_chanctx_user_reserved(local, ctx, &iter)
|
||||||
|
num++;
|
||||||
for_each_sdata_link(local, link) {
|
|
||||||
if (link->reserved_chanctx == ctx)
|
|
||||||
num++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
@@ -47,17 +157,11 @@ static int ieee80211_chanctx_num_reserved(struct ieee80211_local *local,
|
|||||||
int ieee80211_chanctx_refcount(struct ieee80211_local *local,
|
int ieee80211_chanctx_refcount(struct ieee80211_local *local,
|
||||||
struct ieee80211_chanctx *ctx)
|
struct ieee80211_chanctx *ctx)
|
||||||
{
|
{
|
||||||
struct ieee80211_link_data *link;
|
struct ieee80211_chanctx_user_iter iter;
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
|
||||||
lockdep_assert_wiphy(local->hw.wiphy);
|
for_each_chanctx_user_all(local, ctx, &iter)
|
||||||
|
num++;
|
||||||
for_each_sdata_link(local, link) {
|
|
||||||
if (rcu_access_pointer(link->conf->chanctx_conf) == &ctx->conf)
|
|
||||||
num++;
|
|
||||||
if (link->reserved_chanctx == ctx)
|
|
||||||
num++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
@@ -158,18 +262,15 @@ ieee80211_chanctx_reserved_chanreq(struct ieee80211_local *local,
|
|||||||
const struct ieee80211_chan_req *req,
|
const struct ieee80211_chan_req *req,
|
||||||
struct ieee80211_chan_req *tmp)
|
struct ieee80211_chan_req *tmp)
|
||||||
{
|
{
|
||||||
struct ieee80211_link_data *link;
|
struct ieee80211_chanctx_user_iter iter;
|
||||||
|
|
||||||
lockdep_assert_wiphy(local->hw.wiphy);
|
lockdep_assert_wiphy(local->hw.wiphy);
|
||||||
|
|
||||||
if (WARN_ON(!req))
|
if (WARN_ON(!req))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for_each_sdata_link(local, link) {
|
for_each_chanctx_user_reserved(local, ctx, &iter) {
|
||||||
if (link->reserved_chanctx != ctx)
|
req = ieee80211_chanreq_compatible(iter.chanreq, req, tmp);
|
||||||
continue;
|
|
||||||
|
|
||||||
req = ieee80211_chanreq_compatible(&link->reserved, req, tmp);
|
|
||||||
if (!req)
|
if (!req)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -183,21 +284,16 @@ ieee80211_chanctx_non_reserved_chandef(struct ieee80211_local *local,
|
|||||||
const struct ieee80211_chan_req *compat,
|
const struct ieee80211_chan_req *compat,
|
||||||
struct ieee80211_chan_req *tmp)
|
struct ieee80211_chan_req *tmp)
|
||||||
{
|
{
|
||||||
struct ieee80211_link_data *link;
|
|
||||||
const struct ieee80211_chan_req *comp_def = compat;
|
const struct ieee80211_chan_req *comp_def = compat;
|
||||||
|
struct ieee80211_chanctx_user_iter iter;
|
||||||
|
|
||||||
lockdep_assert_wiphy(local->hw.wiphy);
|
lockdep_assert_wiphy(local->hw.wiphy);
|
||||||
|
|
||||||
for_each_sdata_link(local, link) {
|
for_each_chanctx_user_assigned(local, ctx, &iter) {
|
||||||
struct ieee80211_bss_conf *link_conf = link->conf;
|
if (iter.link->reserved_chanctx)
|
||||||
|
|
||||||
if (rcu_access_pointer(link_conf->chanctx_conf) != &ctx->conf)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (link->reserved_chanctx)
|
comp_def = ieee80211_chanreq_compatible(iter.chanreq,
|
||||||
continue;
|
|
||||||
|
|
||||||
comp_def = ieee80211_chanreq_compatible(&link_conf->chanreq,
|
|
||||||
comp_def, tmp);
|
comp_def, tmp);
|
||||||
if (!comp_def)
|
if (!comp_def)
|
||||||
break;
|
break;
|
||||||
@@ -702,17 +798,13 @@ static bool
|
|||||||
ieee80211_chanctx_radar_required(struct ieee80211_local *local,
|
ieee80211_chanctx_radar_required(struct ieee80211_local *local,
|
||||||
struct ieee80211_chanctx *ctx)
|
struct ieee80211_chanctx *ctx)
|
||||||
{
|
{
|
||||||
struct ieee80211_chanctx_conf *conf = &ctx->conf;
|
struct ieee80211_chanctx_user_iter iter;
|
||||||
struct ieee80211_link_data *link;
|
|
||||||
|
|
||||||
lockdep_assert_wiphy(local->hw.wiphy);
|
lockdep_assert_wiphy(local->hw.wiphy);
|
||||||
|
|
||||||
for_each_sdata_link(local, link) {
|
for_each_chanctx_user_assigned(local, ctx, &iter) {
|
||||||
if (rcu_access_pointer(link->conf->chanctx_conf) != conf)
|
if (iter.radar_required)
|
||||||
continue;
|
return true;
|
||||||
if (!link->radar_required)
|
|
||||||
continue;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -829,27 +921,17 @@ void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
|
|||||||
{
|
{
|
||||||
struct ieee80211_chanctx_conf *conf = &ctx->conf;
|
struct ieee80211_chanctx_conf *conf = &ctx->conf;
|
||||||
const struct ieee80211_chan_req *compat = NULL;
|
const struct ieee80211_chan_req *compat = NULL;
|
||||||
struct ieee80211_link_data *link;
|
struct ieee80211_chanctx_user_iter iter;
|
||||||
struct ieee80211_chan_req tmp;
|
struct ieee80211_chan_req tmp;
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
|
|
||||||
lockdep_assert_wiphy(local->hw.wiphy);
|
lockdep_assert_wiphy(local->hw.wiphy);
|
||||||
|
|
||||||
for_each_sdata_link(local, link) {
|
for_each_chanctx_user_assigned(local, ctx, &iter) {
|
||||||
struct ieee80211_bss_conf *link_conf;
|
|
||||||
|
|
||||||
if (link->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
link_conf = link->conf;
|
|
||||||
|
|
||||||
if (rcu_access_pointer(link_conf->chanctx_conf) != conf)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!compat)
|
if (!compat)
|
||||||
compat = &link_conf->chanreq;
|
compat = iter.chanreq;
|
||||||
|
|
||||||
compat = ieee80211_chanreq_compatible(&link_conf->chanreq,
|
compat = ieee80211_chanreq_compatible(iter.chanreq,
|
||||||
compat, &tmp);
|
compat, &tmp);
|
||||||
if (WARN_ON_ONCE(!compat))
|
if (WARN_ON_ONCE(!compat))
|
||||||
return;
|
return;
|
||||||
@@ -862,6 +944,7 @@ void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
|
|||||||
list_for_each_entry(sta, &local->sta_list, list) {
|
list_for_each_entry(sta, &local->sta_list, list) {
|
||||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||||
struct ieee80211_chan_req tdls_chanreq = {};
|
struct ieee80211_chan_req tdls_chanreq = {};
|
||||||
|
struct ieee80211_link_data *link;
|
||||||
int tdls_link_id;
|
int tdls_link_id;
|
||||||
|
|
||||||
if (!sta->uploaded ||
|
if (!sta->uploaded ||
|
||||||
@@ -992,21 +1075,21 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link,
|
|||||||
void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
|
void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
|
||||||
struct ieee80211_chanctx *chanctx)
|
struct ieee80211_chanctx *chanctx)
|
||||||
{
|
{
|
||||||
|
struct ieee80211_chanctx_user_iter iter;
|
||||||
struct ieee80211_sub_if_data *sdata;
|
struct ieee80211_sub_if_data *sdata;
|
||||||
u8 rx_chains_static, rx_chains_dynamic;
|
u8 rx_chains_static, rx_chains_dynamic;
|
||||||
struct ieee80211_link_data *link;
|
|
||||||
|
|
||||||
lockdep_assert_wiphy(local->hw.wiphy);
|
lockdep_assert_wiphy(local->hw.wiphy);
|
||||||
|
|
||||||
rx_chains_static = 1;
|
rx_chains_static = 1;
|
||||||
rx_chains_dynamic = 1;
|
rx_chains_dynamic = 1;
|
||||||
|
|
||||||
for_each_sdata_link(local, link) {
|
for_each_chanctx_user_assigned(local, chanctx, &iter) {
|
||||||
u8 needed_static, needed_dynamic;
|
u8 needed_static, needed_dynamic;
|
||||||
|
|
||||||
switch (link->sdata->vif.type) {
|
switch (iter.iftype) {
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
if (!link->sdata->u.mgd.associated)
|
if (!iter.sdata->u.mgd.associated)
|
||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
case NL80211_IFTYPE_MONITOR:
|
case NL80211_IFTYPE_MONITOR:
|
||||||
@@ -1022,26 +1105,23 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rcu_access_pointer(link->conf->chanctx_conf) != &chanctx->conf)
|
if (iter.iftype == NL80211_IFTYPE_MONITOR) {
|
||||||
continue;
|
|
||||||
|
|
||||||
if (link->sdata->vif.type == NL80211_IFTYPE_MONITOR) {
|
|
||||||
rx_chains_dynamic = rx_chains_static = local->rx_chains;
|
rx_chains_dynamic = rx_chains_static = local->rx_chains;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (link->smps_mode) {
|
switch (iter.link->smps_mode) {
|
||||||
default:
|
default:
|
||||||
WARN_ONCE(1, "Invalid SMPS mode %d\n",
|
WARN_ONCE(1, "Invalid SMPS mode %d\n",
|
||||||
link->smps_mode);
|
iter.link->smps_mode);
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case IEEE80211_SMPS_OFF:
|
case IEEE80211_SMPS_OFF:
|
||||||
needed_static = link->needed_rx_chains;
|
needed_static = iter.link->needed_rx_chains;
|
||||||
needed_dynamic = link->needed_rx_chains;
|
needed_dynamic = iter.link->needed_rx_chains;
|
||||||
break;
|
break;
|
||||||
case IEEE80211_SMPS_DYNAMIC:
|
case IEEE80211_SMPS_DYNAMIC:
|
||||||
needed_static = 1;
|
needed_static = 1;
|
||||||
needed_dynamic = link->needed_rx_chains;
|
needed_dynamic = iter.link->needed_rx_chains;
|
||||||
break;
|
break;
|
||||||
case IEEE80211_SMPS_STATIC:
|
case IEEE80211_SMPS_STATIC:
|
||||||
needed_static = 1;
|
needed_static = 1;
|
||||||
@@ -1513,7 +1593,6 @@ static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local,
|
|||||||
int n_vifs)
|
int n_vifs)
|
||||||
{
|
{
|
||||||
struct ieee80211_vif_chanctx_switch *vif_chsw;
|
struct ieee80211_vif_chanctx_switch *vif_chsw;
|
||||||
struct ieee80211_link_data *link;
|
|
||||||
struct ieee80211_chanctx *ctx, *old_ctx;
|
struct ieee80211_chanctx *ctx, *old_ctx;
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
||||||
@@ -1525,6 +1604,8 @@ static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local,
|
|||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
||||||
|
struct ieee80211_chanctx_user_iter iter;
|
||||||
|
|
||||||
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -1533,18 +1614,15 @@ static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_sdata_link(local, link) {
|
for_each_chanctx_user_reserved(local, ctx, &iter) {
|
||||||
if (link->reserved_chanctx != ctx)
|
if (!ieee80211_link_has_in_place_reservation(iter.link))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!ieee80211_link_has_in_place_reservation(link))
|
old_ctx = ieee80211_link_get_chanctx(iter.link);
|
||||||
continue;
|
vif_chsw[i].vif = &iter.sdata->vif;
|
||||||
|
|
||||||
old_ctx = ieee80211_link_get_chanctx(link);
|
|
||||||
vif_chsw[i].vif = &link->sdata->vif;
|
|
||||||
vif_chsw[i].old_ctx = &old_ctx->conf;
|
vif_chsw[i].old_ctx = &old_ctx->conf;
|
||||||
vif_chsw[i].new_ctx = &ctx->conf;
|
vif_chsw[i].new_ctx = &ctx->conf;
|
||||||
vif_chsw[i].link_conf = link->conf;
|
vif_chsw[i].link_conf = iter.link->conf;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -1621,7 +1699,7 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
||||||
struct ieee80211_link_data *link;
|
struct ieee80211_chanctx_user_iter iter;
|
||||||
|
|
||||||
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
||||||
continue;
|
continue;
|
||||||
@@ -1637,14 +1715,11 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
|
|||||||
n_reserved = 0;
|
n_reserved = 0;
|
||||||
n_ready = 0;
|
n_ready = 0;
|
||||||
|
|
||||||
for_each_sdata_link(local, link) {
|
for_each_chanctx_user_assigned(local, ctx, &iter) {
|
||||||
if (rcu_access_pointer(link->conf->chanctx_conf) != &ctx->conf)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
n_assigned++;
|
n_assigned++;
|
||||||
if (link->reserved_chanctx) {
|
if (iter.link->reserved_chanctx) {
|
||||||
n_reserved++;
|
n_reserved++;
|
||||||
if (link->reserved_ready)
|
if (iter.link->reserved_ready)
|
||||||
n_ready++;
|
n_ready++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1661,15 +1736,12 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx->conf.radar_enabled = false;
|
ctx->conf.radar_enabled = false;
|
||||||
for_each_sdata_link(local, link) {
|
for_each_chanctx_user_reserved(local, ctx, &iter) {
|
||||||
if (link->reserved_chanctx != ctx)
|
if (ieee80211_link_has_in_place_reservation(iter.link) &&
|
||||||
continue;
|
!iter.link->reserved_ready)
|
||||||
|
|
||||||
if (ieee80211_link_has_in_place_reservation(link) &&
|
|
||||||
!link->reserved_ready)
|
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
|
||||||
old_ctx = ieee80211_link_get_chanctx(link);
|
old_ctx = ieee80211_link_get_chanctx(iter.link);
|
||||||
if (old_ctx) {
|
if (old_ctx) {
|
||||||
if (old_ctx->replace_state ==
|
if (old_ctx->replace_state ==
|
||||||
IEEE80211_CHANCTX_WILL_BE_REPLACED)
|
IEEE80211_CHANCTX_WILL_BE_REPLACED)
|
||||||
@@ -1680,7 +1752,7 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
|
|||||||
n_vifs_ctxless++;
|
n_vifs_ctxless++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (link->reserved_radar_required)
|
if (iter.radar_required)
|
||||||
ctx->conf.radar_enabled = true;
|
ctx->conf.radar_enabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1695,7 +1767,7 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
|
|||||||
|
|
||||||
/* update station rate control and min width before switch */
|
/* update station rate control and min width before switch */
|
||||||
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
||||||
struct ieee80211_link_data *link;
|
struct ieee80211_chanctx_user_iter iter;
|
||||||
|
|
||||||
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
||||||
continue;
|
continue;
|
||||||
@@ -1705,15 +1777,12 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_sdata_link(local, link) {
|
for_each_chanctx_user_reserved(local, ctx, &iter) {
|
||||||
if (link->reserved_chanctx != ctx)
|
if (!ieee80211_link_has_in_place_reservation(iter.link))
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!ieee80211_link_has_in_place_reservation(link))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ieee80211_chan_bw_change(local,
|
ieee80211_chan_bw_change(local,
|
||||||
ieee80211_link_get_chanctx(link),
|
ieee80211_link_get_chanctx(iter.link),
|
||||||
true, true);
|
true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1742,7 +1811,7 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
|
|||||||
* context(s).
|
* context(s).
|
||||||
*/
|
*/
|
||||||
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
||||||
struct ieee80211_link_data *link;
|
struct ieee80211_chanctx_user_iter iter;
|
||||||
|
|
||||||
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
||||||
continue;
|
continue;
|
||||||
@@ -1752,14 +1821,12 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_sdata_link(local, link) {
|
for_each_chanctx_user_reserved(local, ctx, &iter) {
|
||||||
struct ieee80211_sub_if_data *sdata = link->sdata;
|
struct ieee80211_link_data *link = iter.link;
|
||||||
|
struct ieee80211_sub_if_data *sdata = iter.sdata;
|
||||||
struct ieee80211_bss_conf *link_conf = link->conf;
|
struct ieee80211_bss_conf *link_conf = link->conf;
|
||||||
u64 changed = 0;
|
u64 changed = 0;
|
||||||
|
|
||||||
if (link->reserved_chanctx != ctx)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!ieee80211_link_has_in_place_reservation(link))
|
if (!ieee80211_link_has_in_place_reservation(link))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -1772,9 +1839,9 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
|
|||||||
|
|
||||||
ieee80211_check_fast_xmit_iface(sdata);
|
ieee80211_check_fast_xmit_iface(sdata);
|
||||||
|
|
||||||
link->radar_required = link->reserved_radar_required;
|
link->radar_required = iter.radar_required;
|
||||||
|
|
||||||
if (link_conf->chanreq.oper.width != link->reserved.oper.width)
|
if (link_conf->chanreq.oper.width != iter.chanreq->oper.width)
|
||||||
changed = BSS_CHANGED_BANDWIDTH;
|
changed = BSS_CHANGED_BANDWIDTH;
|
||||||
|
|
||||||
ieee80211_link_update_chanreq(link, &link->reserved);
|
ieee80211_link_update_chanreq(link, &link->reserved);
|
||||||
@@ -1791,16 +1858,13 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
|
|||||||
ieee80211_recalc_radar_chanctx(local, ctx);
|
ieee80211_recalc_radar_chanctx(local, ctx);
|
||||||
ieee80211_recalc_chanctx_min_def(local, ctx);
|
ieee80211_recalc_chanctx_min_def(local, ctx);
|
||||||
|
|
||||||
for_each_sdata_link(local, link) {
|
for_each_chanctx_user_reserved(local, ctx, &iter) {
|
||||||
if (link->reserved_chanctx != ctx)
|
if (ieee80211_link_get_chanctx(iter.link) != ctx)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ieee80211_link_get_chanctx(link) != ctx)
|
iter.link->reserved_chanctx = NULL;
|
||||||
continue;
|
|
||||||
|
|
||||||
link->reserved_chanctx = NULL;
|
ieee80211_link_chanctx_reservation_complete(iter.link);
|
||||||
|
|
||||||
ieee80211_link_chanctx_reservation_complete(link);
|
|
||||||
ieee80211_chan_bw_change(local, ctx, false, false);
|
ieee80211_chan_bw_change(local, ctx, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1811,9 +1875,8 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
|
|||||||
* reservation for originally requested interface has already
|
* reservation for originally requested interface has already
|
||||||
* succeeded at this point.
|
* succeeded at this point.
|
||||||
*/
|
*/
|
||||||
for_each_sdata_link(local, link) {
|
for_each_chanctx_user_reserved(local, ctx, &iter) {
|
||||||
if (link->reserved_chanctx != ctx)
|
struct ieee80211_link_data *link = iter.link;
|
||||||
continue;
|
|
||||||
|
|
||||||
if (WARN_ON(ieee80211_link_has_in_place_reservation(link)))
|
if (WARN_ON(ieee80211_link_has_in_place_reservation(link)))
|
||||||
continue;
|
continue;
|
||||||
@@ -1858,17 +1921,14 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
||||||
struct ieee80211_link_data *link;
|
struct ieee80211_chanctx_user_iter iter;
|
||||||
|
|
||||||
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for_each_sdata_link(local, link) {
|
for_each_chanctx_user_reserved(local, ctx, &iter) {
|
||||||
if (link->reserved_chanctx != ctx)
|
ieee80211_link_unreserve_chanctx(iter.link);
|
||||||
continue;
|
ieee80211_link_chanctx_reservation_complete(iter.link);
|
||||||
|
|
||||||
ieee80211_link_unreserve_chanctx(link);
|
|
||||||
ieee80211_link_chanctx_reservation_complete(link);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2071,29 +2131,17 @@ ieee80211_chanctx_recheck(struct ieee80211_local *local,
|
|||||||
struct ieee80211_chan_req *tmp)
|
struct ieee80211_chan_req *tmp)
|
||||||
{
|
{
|
||||||
const struct ieee80211_chan_req *ret = req;
|
const struct ieee80211_chan_req *ret = req;
|
||||||
struct ieee80211_link_data *link;
|
struct ieee80211_chanctx_user_iter iter;
|
||||||
|
|
||||||
lockdep_assert_wiphy(local->hw.wiphy);
|
lockdep_assert_wiphy(local->hw.wiphy);
|
||||||
|
|
||||||
for_each_sdata_link(local, link) {
|
for_each_chanctx_user_all(local, ctx, &iter) {
|
||||||
if (link == skip_link)
|
if (iter.link == skip_link)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (rcu_access_pointer(link->conf->chanctx_conf) == &ctx->conf) {
|
ret = ieee80211_chanreq_compatible(ret, iter.chanreq, tmp);
|
||||||
ret = ieee80211_chanreq_compatible(ret,
|
if (!ret)
|
||||||
&link->conf->chanreq,
|
return NULL;
|
||||||
tmp);
|
|
||||||
if (!ret)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (link->reserved_chanctx == ctx) {
|
|
||||||
ret = ieee80211_chanreq_compatible(ret,
|
|
||||||
&link->reserved,
|
|
||||||
tmp);
|
|
||||||
if (!ret)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*tmp = *ret;
|
*tmp = *ret;
|
||||||
|
|||||||
Reference in New Issue
Block a user