Skip to content

Commit

Permalink
mac80211: improve chanctx reservation lookup
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Michal Kazior authored and Johannes Berg committed Apr 25, 2014
1 parent 0288157 commit 13f348a
Showing 1 changed file with 88 additions and 2 deletions.
90 changes: 88 additions & 2 deletions net/mac80211/chan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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)) {
Expand Down

0 comments on commit 13f348a

Please sign in to comment.