mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 16:29:59 +00:00
mac80211: improve chanctx reservation lookup
Use a separate function to look for reservation chanctx. For multi-interface/channel reservation search sematics differ slightly. The new routine allows reservations to be merged with chanctx that are already reserved by other interface(s). Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
0288157b2a
commit
13f348a814
1 changed files with 88 additions and 2 deletions
|
@ -51,6 +51,93 @@ ieee80211_chanctx_reserved_chandef(struct ieee80211_local *local,
|
|||
return compat;
|
||||
}
|
||||
|
||||
static const struct cfg80211_chan_def *
|
||||
ieee80211_chanctx_non_reserved_chandef(struct ieee80211_local *local,
|
||||
struct ieee80211_chanctx *ctx,
|
||||
const struct cfg80211_chan_def *compat)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
lockdep_assert_held(&local->chanctx_mtx);
|
||||
|
||||
list_for_each_entry(sdata, &ctx->assigned_vifs,
|
||||
assigned_chanctx_list) {
|
||||
if (sdata->reserved_chanctx != NULL)
|
||||
continue;
|
||||
|
||||
if (!compat)
|
||||
compat = &sdata->vif.bss_conf.chandef;
|
||||
|
||||
compat = cfg80211_chandef_compatible(
|
||||
&sdata->vif.bss_conf.chandef, compat);
|
||||
if (!compat)
|
||||
break;
|
||||
}
|
||||
|
||||
return compat;
|
||||
}
|
||||
|
||||
static const struct cfg80211_chan_def *
|
||||
ieee80211_chanctx_combined_chandef(struct ieee80211_local *local,
|
||||
struct ieee80211_chanctx *ctx,
|
||||
const struct cfg80211_chan_def *compat)
|
||||
{
|
||||
lockdep_assert_held(&local->chanctx_mtx);
|
||||
|
||||
compat = ieee80211_chanctx_reserved_chandef(local, ctx, compat);
|
||||
if (!compat)
|
||||
return NULL;
|
||||
|
||||
compat = ieee80211_chanctx_non_reserved_chandef(local, ctx, compat);
|
||||
if (!compat)
|
||||
return NULL;
|
||||
|
||||
return compat;
|
||||
}
|
||||
|
||||
static bool
|
||||
ieee80211_chanctx_can_reserve_chandef(struct ieee80211_local *local,
|
||||
struct ieee80211_chanctx *ctx,
|
||||
const struct cfg80211_chan_def *def)
|
||||
{
|
||||
lockdep_assert_held(&local->chanctx_mtx);
|
||||
|
||||
if (ieee80211_chanctx_combined_chandef(local, ctx, def))
|
||||
return true;
|
||||
|
||||
if (!list_empty(&ctx->reserved_vifs) &&
|
||||
ieee80211_chanctx_reserved_chandef(local, ctx, def))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct ieee80211_chanctx *
|
||||
ieee80211_find_reservation_chanctx(struct ieee80211_local *local,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
enum ieee80211_chanctx_mode mode)
|
||||
{
|
||||
struct ieee80211_chanctx *ctx;
|
||||
|
||||
lockdep_assert_held(&local->chanctx_mtx);
|
||||
|
||||
if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
||||
if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
|
||||
continue;
|
||||
|
||||
if (!ieee80211_chanctx_can_reserve_chandef(local, ctx,
|
||||
chandef))
|
||||
continue;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static enum nl80211_chan_width ieee80211_get_sta_bw(struct ieee80211_sta *sta)
|
||||
{
|
||||
switch (sta->bandwidth) {
|
||||
|
@ -771,8 +858,7 @@ int ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
curr_ctx = container_of(conf, struct ieee80211_chanctx, conf);
|
||||
|
||||
/* try to find another context with the chandef we want */
|
||||
new_ctx = ieee80211_find_chanctx(local, chandef, mode);
|
||||
new_ctx = ieee80211_find_reservation_chanctx(local, chandef, mode);
|
||||
if (!new_ctx) {
|
||||
if (curr_ctx->refcount == 1 &&
|
||||
(local->hw.flags & IEEE80211_HW_CHANGE_RUNNING_CHANCTX)) {
|
||||
|
|
Loading…
Reference in a new issue