diff options
| -rw-r--r-- | net/mac80211/sta_info.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 62a5f0889583..ffc1ee6a2ec1 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
| @@ -91,7 +91,7 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
| 91 | return -ENOENT; | 91 | return -ENOENT; |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | static void cleanup_single_sta(struct sta_info *sta) | 94 | static void __cleanup_single_sta(struct sta_info *sta) |
| 95 | { | 95 | { |
| 96 | int ac, i; | 96 | int ac, i; |
| 97 | struct tid_ampdu_tx *tid_tx; | 97 | struct tid_ampdu_tx *tid_tx; |
| @@ -139,7 +139,14 @@ static void cleanup_single_sta(struct sta_info *sta) | |||
| 139 | ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); | 139 | ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); |
| 140 | kfree(tid_tx); | 140 | kfree(tid_tx); |
| 141 | } | 141 | } |
| 142 | } | ||
| 142 | 143 | ||
| 144 | static void cleanup_single_sta(struct sta_info *sta) | ||
| 145 | { | ||
| 146 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
| 147 | struct ieee80211_local *local = sdata->local; | ||
| 148 | |||
| 149 | __cleanup_single_sta(sta); | ||
| 143 | sta_info_free(local, sta); | 150 | sta_info_free(local, sta); |
| 144 | } | 151 | } |
| 145 | 152 | ||
| @@ -488,21 +495,26 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) | |||
| 488 | goto out_err; | 495 | goto out_err; |
| 489 | } | 496 | } |
| 490 | 497 | ||
| 491 | /* notify driver */ | ||
| 492 | err = sta_info_insert_drv_state(local, sdata, sta); | ||
| 493 | if (err) | ||
| 494 | goto out_err; | ||
| 495 | |||
| 496 | local->num_sta++; | 498 | local->num_sta++; |
| 497 | local->sta_generation++; | 499 | local->sta_generation++; |
| 498 | smp_mb(); | 500 | smp_mb(); |
| 499 | 501 | ||
| 502 | /* simplify things and don't accept BA sessions yet */ | ||
| 503 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); | ||
| 504 | |||
| 500 | /* make the station visible */ | 505 | /* make the station visible */ |
| 501 | sta_info_hash_add(local, sta); | 506 | sta_info_hash_add(local, sta); |
| 502 | 507 | ||
| 503 | list_add_rcu(&sta->list, &local->sta_list); | 508 | list_add_rcu(&sta->list, &local->sta_list); |
| 504 | 509 | ||
| 510 | /* notify driver */ | ||
| 511 | err = sta_info_insert_drv_state(local, sdata, sta); | ||
| 512 | if (err) | ||
| 513 | goto out_remove; | ||
| 514 | |||
| 505 | set_sta_flag(sta, WLAN_STA_INSERTED); | 515 | set_sta_flag(sta, WLAN_STA_INSERTED); |
| 516 | /* accept BA sessions now */ | ||
| 517 | clear_sta_flag(sta, WLAN_STA_BLOCK_BA); | ||
| 506 | 518 | ||
| 507 | ieee80211_recalc_min_chandef(sdata); | 519 | ieee80211_recalc_min_chandef(sdata); |
| 508 | ieee80211_sta_debugfs_add(sta); | 520 | ieee80211_sta_debugfs_add(sta); |
| @@ -523,6 +535,12 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) | |||
| 523 | mesh_accept_plinks_update(sdata); | 535 | mesh_accept_plinks_update(sdata); |
| 524 | 536 | ||
| 525 | return 0; | 537 | return 0; |
| 538 | out_remove: | ||
| 539 | sta_info_hash_del(local, sta); | ||
| 540 | list_del_rcu(&sta->list); | ||
| 541 | local->num_sta--; | ||
| 542 | synchronize_net(); | ||
| 543 | __cleanup_single_sta(sta); | ||
| 526 | out_err: | 544 | out_err: |
| 527 | mutex_unlock(&local->sta_mtx); | 545 | mutex_unlock(&local->sta_mtx); |
| 528 | rcu_read_lock(); | 546 | rcu_read_lock(); |
