aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/iface.c89
-rw-r--r--net/mac80211/mlme.c5
2 files changed, 28 insertions, 66 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 810e6764d04f..cc1c68d7dda6 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -370,12 +370,9 @@ static int ieee80211_stop(struct net_device *dev)
370 * (because if we remove a STA after ops->remove_interface() 370 * (because if we remove a STA after ops->remove_interface()
371 * the driver will have removed the vif info already!) 371 * the driver will have removed the vif info already!)
372 * 372 *
373 * We could relax this and only unlink the stations from the 373 * This is relevant only in AP, WDS and mesh modes, since in
374 * hash table and list but keep them on a per-sdata list that 374 * all other modes we've already removed all stations when
375 * will be inserted back again when the interface is brought 375 * disconnecting etc.
376 * up again, but I don't currently see a use case for that,
377 * except with WDS which gets a STA entry created when it is
378 * brought up.
379 */ 376 */
380 sta_info_flush(local, sdata); 377 sta_info_flush(local, sdata);
381 378
@@ -410,11 +407,21 @@ static int ieee80211_stop(struct net_device *dev)
410 struct ieee80211_sub_if_data *vlan, *tmpsdata; 407 struct ieee80211_sub_if_data *vlan, *tmpsdata;
411 struct beacon_data *old_beacon = sdata->u.ap.beacon; 408 struct beacon_data *old_beacon = sdata->u.ap.beacon;
412 409
410 /* sdata_running will return false, so this will disable */
411 ieee80211_bss_info_change_notify(sdata,
412 BSS_CHANGED_BEACON_ENABLED);
413
413 /* remove beacon */ 414 /* remove beacon */
414 rcu_assign_pointer(sdata->u.ap.beacon, NULL); 415 rcu_assign_pointer(sdata->u.ap.beacon, NULL);
415 synchronize_rcu(); 416 synchronize_rcu();
416 kfree(old_beacon); 417 kfree(old_beacon);
417 418
419 /* free all potentially still buffered bcast frames */
420 while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
421 local->total_ps_buffered--;
422 dev_kfree_skb(skb);
423 }
424
418 /* down all dependent devices, that is VLANs */ 425 /* down all dependent devices, that is VLANs */
419 list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, 426 list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans,
420 u.vlan.list) 427 u.vlan.list)
@@ -454,27 +461,6 @@ static int ieee80211_stop(struct net_device *dev)
454 461
455 ieee80211_configure_filter(local); 462 ieee80211_configure_filter(local);
456 break; 463 break;
457 case NL80211_IFTYPE_STATION:
458 del_timer_sync(&sdata->u.mgd.chswitch_timer);
459 del_timer_sync(&sdata->u.mgd.timer);
460 del_timer_sync(&sdata->u.mgd.conn_mon_timer);
461 del_timer_sync(&sdata->u.mgd.bcn_mon_timer);
462 /*
463 * If any of the timers fired while we waited for it, it will
464 * have queued its work. Now the work will be running again
465 * but will not rearm the timer again because it checks
466 * whether the interface is running, which, at this point,
467 * it no longer is.
468 */
469 cancel_work_sync(&sdata->u.mgd.chswitch_work);
470 cancel_work_sync(&sdata->u.mgd.monitor_work);
471 cancel_work_sync(&sdata->u.mgd.beacon_connection_loss_work);
472
473 /* fall through */
474 case NL80211_IFTYPE_ADHOC:
475 if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
476 del_timer_sync(&sdata->u.ibss.timer);
477 /* fall through */
478 case NL80211_IFTYPE_MESH_POINT: 464 case NL80211_IFTYPE_MESH_POINT:
479 if (ieee80211_vif_is_mesh(&sdata->vif)) { 465 if (ieee80211_vif_is_mesh(&sdata->vif)) {
480 /* other_bss and allmulti are always set on mesh 466 /* other_bss and allmulti are always set on mesh
@@ -502,17 +488,19 @@ static int ieee80211_stop(struct net_device *dev)
502 ieee80211_scan_cancel(local); 488 ieee80211_scan_cancel(local);
503 489
504 /* 490 /*
505 * Disable beaconing for AP and mesh, IBSS can't 491 * Disable beaconing here for mesh only, AP and IBSS
506 * still be joined to a network at this point. 492 * are already taken care of.
507 */ 493 */
508 if (sdata->vif.type == NL80211_IFTYPE_AP || 494 if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
509 sdata->vif.type == NL80211_IFTYPE_MESH_POINT) {
510 ieee80211_bss_info_change_notify(sdata, 495 ieee80211_bss_info_change_notify(sdata,
511 BSS_CHANGED_BEACON_ENABLED); 496 BSS_CHANGED_BEACON_ENABLED);
512 }
513 497
514 /* free all remaining keys, there shouldn't be any */ 498 /*
499 * Free all remaining keys, there shouldn't be any,
500 * except maybe group keys in AP more or WDS?
501 */
515 ieee80211_free_keys(sdata); 502 ieee80211_free_keys(sdata);
503
516 drv_remove_interface(local, &sdata->vif); 504 drv_remove_interface(local, &sdata->vif);
517 } 505 }
518 506
@@ -593,8 +581,6 @@ static void ieee80211_teardown_sdata(struct net_device *dev)
593{ 581{
594 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 582 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
595 struct ieee80211_local *local = sdata->local; 583 struct ieee80211_local *local = sdata->local;
596 struct beacon_data *beacon;
597 struct sk_buff *skb;
598 int flushed; 584 int flushed;
599 int i; 585 int i;
600 586
@@ -607,37 +593,8 @@ static void ieee80211_teardown_sdata(struct net_device *dev)
607 __skb_queue_purge(&sdata->fragments[i].skb_list); 593 __skb_queue_purge(&sdata->fragments[i].skb_list);
608 sdata->fragment_next = 0; 594 sdata->fragment_next = 0;
609 595
610 switch (sdata->vif.type) { 596 if (ieee80211_vif_is_mesh(&sdata->vif))
611 case NL80211_IFTYPE_AP: 597 mesh_rmc_free(sdata);
612 beacon = sdata->u.ap.beacon;
613 rcu_assign_pointer(sdata->u.ap.beacon, NULL);
614 synchronize_rcu();
615 kfree(beacon);
616
617 while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
618 local->total_ps_buffered--;
619 dev_kfree_skb(skb);
620 }
621
622 break;
623 case NL80211_IFTYPE_MESH_POINT:
624 if (ieee80211_vif_is_mesh(&sdata->vif))
625 mesh_rmc_free(sdata);
626 break;
627 case NL80211_IFTYPE_ADHOC:
628 if (WARN_ON(sdata->u.ibss.presp))
629 kfree_skb(sdata->u.ibss.presp);
630 break;
631 case NL80211_IFTYPE_STATION:
632 case NL80211_IFTYPE_WDS:
633 case NL80211_IFTYPE_AP_VLAN:
634 case NL80211_IFTYPE_MONITOR:
635 break;
636 case NL80211_IFTYPE_UNSPECIFIED:
637 case NUM_NL80211_IFTYPES:
638 BUG();
639 break;
640 }
641 598
642 flushed = sta_info_flush(local, sdata); 599 flushed = sta_info_flush(local, sdata);
643 WARN_ON(flushed); 600 WARN_ON(flushed);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 0cb429657474..c8694478cde2 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -991,6 +991,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
991 991
992 if (remove_sta) 992 if (remove_sta)
993 sta_info_destroy_addr(sdata, bssid); 993 sta_info_destroy_addr(sdata, bssid);
994
995 del_timer_sync(&sdata->u.mgd.conn_mon_timer);
996 del_timer_sync(&sdata->u.mgd.bcn_mon_timer);
997 del_timer_sync(&sdata->u.mgd.timer);
998 del_timer_sync(&sdata->u.mgd.chswitch_timer);
994} 999}
995 1000
996void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, 1001void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,