diff options
| author | John W. Linville <linville@tuxdriver.com> | 2013-04-22 14:58:14 -0400 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2013-04-22 14:58:14 -0400 |
| commit | 6475cb05ee17870c7c8d44146dbe09044e6db33d (patch) | |
| tree | 68fc82e4b9c4c4a1b261869add66bef3ee054926 /net | |
| parent | e563589f7187699b0217854467d857f53b29cc50 (diff) | |
| parent | 1eb32179f0593051e7536378a879f5bdd108416a (diff) | |
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Diffstat (limited to 'net')
30 files changed, 1231 insertions, 562 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 764dd9a6a072..1a89c80e6407 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
| @@ -1043,6 +1043,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
| 1043 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | 1043 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) |
| 1044 | sta_info_flush_defer(vlan); | 1044 | sta_info_flush_defer(vlan); |
| 1045 | sta_info_flush_defer(sdata); | 1045 | sta_info_flush_defer(sdata); |
| 1046 | synchronize_net(); | ||
| 1046 | rcu_barrier(); | 1047 | rcu_barrier(); |
| 1047 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { | 1048 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { |
| 1048 | sta_info_flush_cleanup(vlan); | 1049 | sta_info_flush_cleanup(vlan); |
| @@ -1052,6 +1053,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
| 1052 | ieee80211_free_keys(sdata); | 1053 | ieee80211_free_keys(sdata); |
| 1053 | 1054 | ||
| 1054 | sdata->vif.bss_conf.enable_beacon = false; | 1055 | sdata->vif.bss_conf.enable_beacon = false; |
| 1056 | sdata->vif.bss_conf.ssid_len = 0; | ||
| 1055 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); | 1057 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); |
| 1056 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 1058 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
| 1057 | 1059 | ||
| @@ -2416,9 +2418,22 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
| 2416 | } | 2418 | } |
| 2417 | 2419 | ||
| 2418 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | 2420 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
| 2421 | struct ieee80211_supported_band *sband = wiphy->bands[i]; | ||
| 2422 | int j; | ||
| 2423 | |||
| 2419 | sdata->rc_rateidx_mask[i] = mask->control[i].legacy; | 2424 | sdata->rc_rateidx_mask[i] = mask->control[i].legacy; |
| 2420 | memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs, | 2425 | memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs, |
| 2421 | sizeof(mask->control[i].mcs)); | 2426 | sizeof(mask->control[i].mcs)); |
| 2427 | |||
| 2428 | sdata->rc_has_mcs_mask[i] = false; | ||
| 2429 | if (!sband) | ||
| 2430 | continue; | ||
| 2431 | |||
| 2432 | for (j = 0; j < IEEE80211_HT_MCS_MASK_LEN; j++) | ||
| 2433 | if (~sdata->rc_rateidx_mcs_mask[i][j]) { | ||
| 2434 | sdata->rc_has_mcs_mask[i] = true; | ||
| 2435 | break; | ||
| 2436 | } | ||
| 2422 | } | 2437 | } |
| 2423 | 2438 | ||
| 2424 | return 0; | 2439 | return 0; |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 7d0baa89c784..03e8d2e3270e 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
| @@ -57,6 +57,22 @@ ieee80211_find_chanctx(struct ieee80211_local *local, | |||
| 57 | return NULL; | 57 | return NULL; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | static bool ieee80211_is_radar_required(struct ieee80211_local *local) | ||
| 61 | { | ||
| 62 | struct ieee80211_sub_if_data *sdata; | ||
| 63 | |||
| 64 | rcu_read_lock(); | ||
| 65 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
| 66 | if (sdata->radar_required) { | ||
| 67 | rcu_read_unlock(); | ||
| 68 | return true; | ||
| 69 | } | ||
| 70 | } | ||
| 71 | rcu_read_unlock(); | ||
| 72 | |||
| 73 | return false; | ||
| 74 | } | ||
| 75 | |||
| 60 | static struct ieee80211_chanctx * | 76 | static struct ieee80211_chanctx * |
| 61 | ieee80211_new_chanctx(struct ieee80211_local *local, | 77 | ieee80211_new_chanctx(struct ieee80211_local *local, |
| 62 | const struct cfg80211_chan_def *chandef, | 78 | const struct cfg80211_chan_def *chandef, |
| @@ -76,6 +92,9 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
| 76 | ctx->conf.rx_chains_static = 1; | 92 | ctx->conf.rx_chains_static = 1; |
| 77 | ctx->conf.rx_chains_dynamic = 1; | 93 | ctx->conf.rx_chains_dynamic = 1; |
| 78 | ctx->mode = mode; | 94 | ctx->mode = mode; |
| 95 | ctx->conf.radar_enabled = ieee80211_is_radar_required(local); | ||
| 96 | if (!local->use_chanctx) | ||
| 97 | local->hw.conf.radar_enabled = ctx->conf.radar_enabled; | ||
| 79 | 98 | ||
| 80 | /* acquire mutex to prevent idle from changing */ | 99 | /* acquire mutex to prevent idle from changing */ |
| 81 | mutex_lock(&local->mtx); | 100 | mutex_lock(&local->mtx); |
| @@ -110,6 +129,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
| 110 | static void ieee80211_free_chanctx(struct ieee80211_local *local, | 129 | static void ieee80211_free_chanctx(struct ieee80211_local *local, |
| 111 | struct ieee80211_chanctx *ctx) | 130 | struct ieee80211_chanctx *ctx) |
| 112 | { | 131 | { |
| 132 | bool check_single_channel = false; | ||
| 113 | lockdep_assert_held(&local->chanctx_mtx); | 133 | lockdep_assert_held(&local->chanctx_mtx); |
| 114 | 134 | ||
| 115 | WARN_ON_ONCE(ctx->refcount != 0); | 135 | WARN_ON_ONCE(ctx->refcount != 0); |
| @@ -119,6 +139,14 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local, | |||
| 119 | chandef->width = NL80211_CHAN_WIDTH_20_NOHT; | 139 | chandef->width = NL80211_CHAN_WIDTH_20_NOHT; |
| 120 | chandef->center_freq1 = chandef->chan->center_freq; | 140 | chandef->center_freq1 = chandef->chan->center_freq; |
| 121 | chandef->center_freq2 = 0; | 141 | chandef->center_freq2 = 0; |
| 142 | |||
| 143 | /* NOTE: Disabling radar is only valid here for | ||
| 144 | * single channel context. To be sure, check it ... | ||
| 145 | */ | ||
| 146 | if (local->hw.conf.radar_enabled) | ||
| 147 | check_single_channel = true; | ||
| 148 | local->hw.conf.radar_enabled = false; | ||
| 149 | |||
| 122 | ieee80211_hw_config(local, 0); | 150 | ieee80211_hw_config(local, 0); |
| 123 | } else { | 151 | } else { |
| 124 | drv_remove_chanctx(local, ctx); | 152 | drv_remove_chanctx(local, ctx); |
| @@ -127,6 +155,9 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local, | |||
| 127 | list_del_rcu(&ctx->list); | 155 | list_del_rcu(&ctx->list); |
| 128 | kfree_rcu(ctx, rcu_head); | 156 | kfree_rcu(ctx, rcu_head); |
| 129 | 157 | ||
| 158 | /* throw a warning if this wasn't the only channel context. */ | ||
| 159 | WARN_ON(check_single_channel && !list_empty(&local->chanctx_list)); | ||
| 160 | |||
| 130 | mutex_lock(&local->mtx); | 161 | mutex_lock(&local->mtx); |
| 131 | ieee80211_recalc_idle(local); | 162 | ieee80211_recalc_idle(local); |
| 132 | mutex_unlock(&local->mtx); | 163 | mutex_unlock(&local->mtx); |
| @@ -238,19 +269,11 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) | |||
| 238 | void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local, | 269 | void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local, |
| 239 | struct ieee80211_chanctx *chanctx) | 270 | struct ieee80211_chanctx *chanctx) |
| 240 | { | 271 | { |
| 241 | struct ieee80211_sub_if_data *sdata; | 272 | bool radar_enabled; |
| 242 | bool radar_enabled = false; | ||
| 243 | 273 | ||
| 244 | lockdep_assert_held(&local->chanctx_mtx); | 274 | lockdep_assert_held(&local->chanctx_mtx); |
| 245 | 275 | ||
| 246 | rcu_read_lock(); | 276 | radar_enabled = ieee80211_is_radar_required(local); |
| 247 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
| 248 | if (sdata->radar_required) { | ||
| 249 | radar_enabled = true; | ||
| 250 | break; | ||
