diff options
-rw-r--r-- | net/mac80211/iface.c | 89 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 5 |
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 | ||
996 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 1001 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |