aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r--net/mac80211/iface.c44
1 files changed, 35 insertions, 9 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 8336fee68d3e..46082125f3e1 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -65,7 +65,7 @@ static int ieee80211_open(struct net_device *dev)
65 struct ieee80211_if_init_conf conf; 65 struct ieee80211_if_init_conf conf;
66 u32 changed = 0; 66 u32 changed = 0;
67 int res; 67 int res;
68 bool need_hw_reconfig = 0; 68 u32 hw_reconf_flags = 0;
69 u8 null_addr[ETH_ALEN] = {0}; 69 u8 null_addr[ETH_ALEN] = {0};
70 70
71 /* fail early if user set an invalid address */ 71 /* fail early if user set an invalid address */
@@ -152,7 +152,8 @@ static int ieee80211_open(struct net_device *dev)
152 res = local->ops->start(local_to_hw(local)); 152 res = local->ops->start(local_to_hw(local));
153 if (res) 153 if (res)
154 goto err_del_bss; 154 goto err_del_bss;
155 need_hw_reconfig = 1; 155 /* we're brought up, everything changes */
156 hw_reconf_flags = ~0;
156 ieee80211_led_radio(local, local->hw.conf.radio_enabled); 157 ieee80211_led_radio(local, local->hw.conf.radio_enabled);
157 } 158 }
158 159
@@ -198,8 +199,10 @@ static int ieee80211_open(struct net_device *dev)
198 199
199 /* must be before the call to ieee80211_configure_filter */ 200 /* must be before the call to ieee80211_configure_filter */
200 local->monitors++; 201 local->monitors++;
201 if (local->monitors == 1) 202 if (local->monitors == 1) {
202 local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; 203 local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
204 hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP;
205 }
203 206
204 if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) 207 if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
205 local->fif_fcsfail++; 208 local->fif_fcsfail++;
@@ -226,8 +229,14 @@ static int ieee80211_open(struct net_device *dev)
226 if (res) 229 if (res)
227 goto err_stop; 230 goto err_stop;
228 231
229 if (ieee80211_vif_is_mesh(&sdata->vif)) 232 if (ieee80211_vif_is_mesh(&sdata->vif)) {
233 local->fif_other_bss++;
234 netif_addr_lock_bh(local->mdev);
235 ieee80211_configure_filter(local);
236 netif_addr_unlock_bh(local->mdev);
237
230 ieee80211_start_mesh(sdata); 238 ieee80211_start_mesh(sdata);
239 }
231 changed |= ieee80211_reset_erp_info(sdata); 240 changed |= ieee80211_reset_erp_info(sdata);
232 ieee80211_bss_info_change_notify(sdata, changed); 241 ieee80211_bss_info_change_notify(sdata, changed);
233 ieee80211_enable_keys(sdata); 242 ieee80211_enable_keys(sdata);
@@ -279,8 +288,8 @@ static int ieee80211_open(struct net_device *dev)
279 atomic_inc(&local->iff_promiscs); 288 atomic_inc(&local->iff_promiscs);
280 289
281 local->open_count++; 290 local->open_count++;
282 if (need_hw_reconfig) { 291 if (hw_reconf_flags) {
283 ieee80211_hw_config(local); 292 ieee80211_hw_config(local, hw_reconf_flags);
284 /* 293 /*
285 * set default queue parameters so drivers don't 294 * set default queue parameters so drivers don't
286 * need to initialise the hardware if the hardware 295 * need to initialise the hardware if the hardware
@@ -322,6 +331,7 @@ static int ieee80211_stop(struct net_device *dev)
322 struct ieee80211_local *local = sdata->local; 331 struct ieee80211_local *local = sdata->local;
323 struct ieee80211_if_init_conf conf; 332 struct ieee80211_if_init_conf conf;
324 struct sta_info *sta; 333 struct sta_info *sta;
334 u32 hw_reconf_flags = 0;
325 335
326 /* 336 /*
327 * Stop TX on this interface first. 337 * Stop TX on this interface first.
@@ -405,8 +415,10 @@ static int ieee80211_stop(struct net_device *dev)
405 } 415 }
406 416
407 local->monitors--; 417 local->monitors--;
408 if (local->monitors == 0) 418 if (local->monitors == 0) {
409 local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; 419 local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
420 hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP;
421 }
410 422
411 if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) 423 if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
412 local->fif_fcsfail--; 424 local->fif_fcsfail--;
@@ -450,8 +462,15 @@ static int ieee80211_stop(struct net_device *dev)
450 /* fall through */ 462 /* fall through */
451 case NL80211_IFTYPE_MESH_POINT: 463 case NL80211_IFTYPE_MESH_POINT:
452 if (ieee80211_vif_is_mesh(&sdata->vif)) { 464 if (ieee80211_vif_is_mesh(&sdata->vif)) {
453 /* allmulti is always set on mesh ifaces */ 465 /* other_bss and allmulti are always set on mesh
466 * ifaces */
467 local->fif_other_bss--;
454 atomic_dec(&local->iff_allmultis); 468 atomic_dec(&local->iff_allmultis);
469
470 netif_addr_lock_bh(local->mdev);
471 ieee80211_configure_filter(local);
472 netif_addr_unlock_bh(local->mdev);
473
455 ieee80211_stop_mesh(sdata); 474 ieee80211_stop_mesh(sdata);
456 } 475 }
457 /* fall through */ 476 /* fall through */
@@ -504,8 +523,15 @@ static int ieee80211_stop(struct net_device *dev)
504 523
505 tasklet_disable(&local->tx_pending_tasklet); 524 tasklet_disable(&local->tx_pending_tasklet);
506 tasklet_disable(&local->tasklet); 525 tasklet_disable(&local->tasklet);
526
527 /* no reconfiguring after stop! */
528 hw_reconf_flags = 0;
507 } 529 }
508 530
531 /* do after stop to avoid reconfiguring when we stop anyway */
532 if (hw_reconf_flags)
533 ieee80211_hw_config(local, hw_reconf_flags);
534
509 return 0; 535 return 0;
510} 536}
511 537
@@ -682,7 +708,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
682 ieee80211_setup_sdata(sdata, type); 708 ieee80211_setup_sdata(sdata, type);
683 709
684 /* reset some values that shouldn't be kept across type changes */ 710 /* reset some values that shouldn't be kept across type changes */
685 sdata->bss_conf.basic_rates = 711 sdata->vif.bss_conf.basic_rates =
686 ieee80211_mandatory_rates(sdata->local, 712 ieee80211_mandatory_rates(sdata->local,
687 sdata->local->hw.conf.channel->band); 713 sdata->local->hw.conf.channel->band);
688 sdata->drop_unencrypted = 0; 714 sdata->drop_unencrypted = 0;