aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-08-27 06:35:54 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-08-27 13:53:30 -0400
commitb9dcf712d1fb98bf279fcd453a42a763b104961d (patch)
treea09aa20ca2c26dbf9439beca7c8c9a403e70c8b5 /net/mac80211/iface.c
parent2337db8db845ece2d4ab7673a343e285f1bfda85 (diff)
mac80211: clean up ifdown/cleanup paths
There's a lot of redundant code in mac80211's interface cleanup/down, for example freeing AP beacons is done both when the interface is set DOWN as well as when it is torn down, of which only the former has any effect. Also, a bunch of things should be closer to where they matter, like the MLME timers that we should cancel when disassociating, rather than only when the interface is set DOWN. Clean up all this code. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r--net/mac80211/iface.c89
1 files changed, 23 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);