diff options
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 44 |
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; |