aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/sta_info.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-01-12 03:31:10 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-01-30 15:41:25 -0500
commit83d5cc012441531ab0bf6f99881958e964e9cf11 (patch)
treeb36a127cd4d735f5b4a0b7fbfbdd3714bceca44f /net/mac80211/sta_info.c
parentc037b8367c7e2b775a99d74037f5df014d2fbf06 (diff)
mac80211: station state transition error handling
In the future, when we start notifying drivers, state transitions could potentially fail. To make it easier to distinguish between programming bugs and driver failures: * rename sta_info_move_state() to sta_info_pre_move_state() which can only be called before the station is inserted (and check this with a new station flag). * rename sta_info_move_state_checked() to just plain sta_info_move_state(), as it will be the regular function that can fail for more than just one reason (bad transition or an error from the driver) This makes the programming model easier -- one of the functions can only be called before insertion and can't fail, the other can fail. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r--net/mac80211/sta_info.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index f28fa02b6e54..df8f0a2f0dee 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -403,6 +403,8 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
403 sta_info_hash_add(local, sta); 403 sta_info_hash_add(local, sta);
404 404
405 list_add(&sta->list, &local->sta_list); 405 list_add(&sta->list, &local->sta_list);
406
407 set_sta_flag(sta, WLAN_STA_INSERTED);
406 } else { 408 } else {
407 sta->dummy = false; 409 sta->dummy = false;
408 } 410 }
@@ -707,7 +709,7 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
707 return have_buffered; 709 return have_buffered;
708} 710}
709 711
710static int __must_check __sta_info_destroy(struct sta_info *sta) 712int __must_check __sta_info_destroy(struct sta_info *sta)
711{ 713{
712 struct ieee80211_local *local; 714 struct ieee80211_local *local;
713 struct ieee80211_sub_if_data *sdata; 715 struct ieee80211_sub_if_data *sdata;
@@ -722,6 +724,8 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
722 local = sta->local; 724 local = sta->local;
723 sdata = sta->sdata; 725 sdata = sta->sdata;
724 726
727 lockdep_assert_held(&local->sta_mtx);
728
725 /* 729 /*
726 * Before removing the station from the driver and 730 * Before removing the station from the driver and
727 * rate control, it might still start new aggregation 731 * rate control, it might still start new aggregation
@@ -763,8 +767,13 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
763 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 767 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
764 RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); 768 RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
765 769
766 while (sta->sta_state > IEEE80211_STA_NONE) 770 while (sta->sta_state > IEEE80211_STA_NONE) {
767 sta_info_move_state(sta, sta->sta_state - 1); 771 int err = sta_info_move_state(sta, sta->sta_state - 1);
772 if (err) {
773 WARN_ON_ONCE(1);
774 break;
775 }
776 }
768 777
769 if (sta->uploaded) { 778 if (sta->uploaded) {
770 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 779 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
@@ -1391,8 +1400,8 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta,
1391} 1400}
1392EXPORT_SYMBOL(ieee80211_sta_set_buffered); 1401EXPORT_SYMBOL(ieee80211_sta_set_buffered);
1393 1402
1394int sta_info_move_state_checked(struct sta_info *sta, 1403int sta_info_move_state(struct sta_info *sta,
1395 enum ieee80211_sta_state new_state) 1404 enum ieee80211_sta_state new_state)
1396{ 1405{
1397 might_sleep(); 1406 might_sleep();
1398 1407