Commit 5bcae31d authored by Michal Kazior's avatar Michal Kazior Committed by Johannes Berg

mac80211: implement multi-vif in-place reservations

Multi-vif in-place reservations happen when
it is impossible to allocate more channel contexts
as indicated by interface combinations.

Such reservations are not finalized until all
assigned interfaces are ready.

This still doesn't handle all possible cases
(i.e. degradation of number of channels) properly.
Signed-off-by: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 633e2713
...@@ -1606,12 +1606,6 @@ struct ieee80211_tx_control { ...@@ -1606,12 +1606,6 @@ struct ieee80211_tx_control {
* is not enabled the default action is to disconnect when getting the * is not enabled the default action is to disconnect when getting the
* CSA frame. * CSA frame.
* *
* @IEEE80211_HW_CHANGE_RUNNING_CHANCTX: The hardware can change a
* channel context on-the-fly. This is needed for channel switch
* on single-channel hardware. It can also be used as an
* optimization in certain channel switch cases with
* multi-channel.
*
* @IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS: The HW supports scanning on all bands * @IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS: The HW supports scanning on all bands
* in one command, mac80211 doesn't have to run separate scans per band. * in one command, mac80211 doesn't have to run separate scans per band.
*/ */
...@@ -1645,7 +1639,7 @@ enum ieee80211_hw_flags { ...@@ -1645,7 +1639,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_TIMING_BEACON_ONLY = 1<<26, IEEE80211_HW_TIMING_BEACON_ONLY = 1<<26,
IEEE80211_HW_SUPPORTS_HT_CCK_RATES = 1<<27, IEEE80211_HW_SUPPORTS_HT_CCK_RATES = 1<<27,
IEEE80211_HW_CHANCTX_STA_CSA = 1<<28, IEEE80211_HW_CHANCTX_STA_CSA = 1<<28,
IEEE80211_HW_CHANGE_RUNNING_CHANCTX = 1<<29, /* bit 29 unused */
IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS = 1<<30, IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS = 1<<30,
}; };
......
This diff is collapsed.
...@@ -701,6 +701,24 @@ enum ieee80211_chanctx_mode { ...@@ -701,6 +701,24 @@ enum ieee80211_chanctx_mode {
IEEE80211_CHANCTX_EXCLUSIVE IEEE80211_CHANCTX_EXCLUSIVE
}; };
/**
* enum ieee80211_chanctx_replace_state - channel context replacement state
*
* This is used for channel context in-place reservations that require channel
* context switch/swap.
*
* @IEEE80211_CHANCTX_REPLACE_NONE: no replacement is taking place
* @IEEE80211_CHANCTX_WILL_BE_REPLACED: this channel context will be replaced
* by a (not yet registered) channel context pointed by %replace_ctx.
* @IEEE80211_CHANCTX_REPLACES_OTHER: this (not yet registered) channel context
* replaces an existing channel context pointed to by %replace_ctx.
*/
enum ieee80211_chanctx_replace_state {
IEEE80211_CHANCTX_REPLACE_NONE,
IEEE80211_CHANCTX_WILL_BE_REPLACED,
IEEE80211_CHANCTX_REPLACES_OTHER,
};
struct ieee80211_chanctx { struct ieee80211_chanctx {
struct list_head list; struct list_head list;
struct rcu_head rcu_head; struct rcu_head rcu_head;
...@@ -708,6 +726,9 @@ struct ieee80211_chanctx { ...@@ -708,6 +726,9 @@ struct ieee80211_chanctx {
struct list_head assigned_vifs; struct list_head assigned_vifs;
struct list_head reserved_vifs; struct list_head reserved_vifs;
enum ieee80211_chanctx_replace_state replace_state;
struct ieee80211_chanctx *replace_ctx;
enum ieee80211_chanctx_mode mode; enum ieee80211_chanctx_mode mode;
bool driver_present; bool driver_present;
...@@ -778,6 +799,7 @@ struct ieee80211_sub_if_data { ...@@ -778,6 +799,7 @@ struct ieee80211_sub_if_data {
struct ieee80211_chanctx *reserved_chanctx; struct ieee80211_chanctx *reserved_chanctx;
struct cfg80211_chan_def reserved_chandef; struct cfg80211_chan_def reserved_chandef;
bool reserved_radar_required; bool reserved_radar_required;
bool reserved_ready;
/* used to reconfigure hardware SM PS */ /* used to reconfigure hardware SM PS */
struct work_struct recalc_smps; struct work_struct recalc_smps;
...@@ -1820,9 +1842,9 @@ ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata, ...@@ -1820,9 +1842,9 @@ ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata,
enum ieee80211_chanctx_mode mode, enum ieee80211_chanctx_mode mode,
bool radar_required); bool radar_required);
int __must_check int __must_check
ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata, ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata);
u32 *changed);
int ieee80211_vif_unreserve_chanctx(struct ieee80211_sub_if_data *sdata); int ieee80211_vif_unreserve_chanctx(struct ieee80211_sub_if_data *sdata);
int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local);
int __must_check int __must_check
ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata, ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
......
...@@ -1698,7 +1698,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) ...@@ -1698,7 +1698,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
if (local->use_chanctx) { if (local->use_chanctx) {
mutex_lock(&local->chanctx_mtx); mutex_lock(&local->chanctx_mtx);
list_for_each_entry(ctx, &local->chanctx_list, list) list_for_each_entry(ctx, &local->chanctx_list, list)
WARN_ON(drv_add_chanctx(local, ctx)); if (ctx->replace_state !=
IEEE80211_CHANCTX_REPLACES_OTHER)
WARN_ON(drv_add_chanctx(local, ctx));
mutex_unlock(&local->chanctx_mtx); mutex_unlock(&local->chanctx_mtx);
list_for_each_entry(sdata, &local->interfaces, list) { list_for_each_entry(sdata, &local->interfaces, list) {
...@@ -2972,6 +2974,8 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, ...@@ -2972,6 +2974,8 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
num[iftype] = 1; num[iftype] = 1;
list_for_each_entry(ctx, &local->chanctx_list, list) { list_for_each_entry(ctx, &local->chanctx_list, list) {
if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
continue;
if (ctx->conf.radar_enabled) if (ctx->conf.radar_enabled)
radar_detect |= BIT(ctx->conf.def.width); radar_detect |= BIT(ctx->conf.def.width);
if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) { if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) {
...@@ -3030,6 +3034,9 @@ int ieee80211_max_num_channels(struct ieee80211_local *local) ...@@ -3030,6 +3034,9 @@ int ieee80211_max_num_channels(struct ieee80211_local *local)
lockdep_assert_held(&local->chanctx_mtx); lockdep_assert_held(&local->chanctx_mtx);
list_for_each_entry(ctx, &local->chanctx_list, list) { list_for_each_entry(ctx, &local->chanctx_list, list) {
if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
continue;
num_different_channels++; num_different_channels++;
if (ctx->conf.radar_enabled) if (ctx->conf.radar_enabled)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment