diff options
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r-- | net/mac80211/sta_info.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 396a94806de9..71f370dd24bc 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -116,14 +116,15 @@ struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr) | |||
116 | return sta; | 116 | return sta; |
117 | } | 117 | } |
118 | 118 | ||
119 | struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, | 119 | struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, |
120 | struct net_device *dev) | 120 | int idx) |
121 | { | 121 | { |
122 | struct ieee80211_local *local = sdata->local; | ||
122 | struct sta_info *sta; | 123 | struct sta_info *sta; |
123 | int i = 0; | 124 | int i = 0; |
124 | 125 | ||
125 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 126 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
126 | if (dev && dev != sta->sdata->dev) | 127 | if (sdata != sta->sdata) |
127 | continue; | 128 | continue; |
128 | if (i < idx) { | 129 | if (i < idx) { |
129 | ++i; | 130 | ++i; |
@@ -147,8 +148,10 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, | |||
147 | static void __sta_info_free(struct ieee80211_local *local, | 148 | static void __sta_info_free(struct ieee80211_local *local, |
148 | struct sta_info *sta) | 149 | struct sta_info *sta) |
149 | { | 150 | { |
150 | rate_control_free_sta(sta); | 151 | if (sta->rate_ctrl) { |
151 | rate_control_put(sta->rate_ctrl); | 152 | rate_control_free_sta(sta); |
153 | rate_control_put(sta->rate_ctrl); | ||
154 | } | ||
152 | 155 | ||
153 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 156 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
154 | printk(KERN_DEBUG "%s: Destroyed STA %pM\n", | 157 | printk(KERN_DEBUG "%s: Destroyed STA %pM\n", |
@@ -276,6 +279,23 @@ static void sta_unblock(struct work_struct *wk) | |||
276 | ieee80211_sta_ps_deliver_poll_response(sta); | 279 | ieee80211_sta_ps_deliver_poll_response(sta); |
277 | } | 280 | } |
278 | 281 | ||
282 | static int sta_prepare_rate_control(struct ieee80211_local *local, | ||
283 | struct sta_info *sta, gfp_t gfp) | ||
284 | { | ||
285 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) | ||
286 | return 0; | ||
287 | |||
288 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); | ||
289 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, | ||
290 | &sta->sta, gfp); | ||
291 | if (!sta->rate_ctrl_priv) { | ||
292 | rate_control_put(sta->rate_ctrl); | ||
293 | return -ENOMEM; | ||
294 | } | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
279 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | 299 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, |
280 | u8 *addr, gfp_t gfp) | 300 | u8 *addr, gfp_t gfp) |
281 | { | 301 | { |
@@ -295,11 +315,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
295 | sta->local = local; | 315 | sta->local = local; |
296 | sta->sdata = sdata; | 316 | sta->sdata = sdata; |
297 | 317 | ||
298 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); | 318 | if (sta_prepare_rate_control(local, sta, gfp)) { |
299 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, | ||
300 | &sta->sta, gfp); | ||
301 | if (!sta->rate_ctrl_priv) { | ||
302 | rate_control_put(sta->rate_ctrl); | ||
303 | kfree(sta); | 319 | kfree(sta); |
304 | return NULL; | 320 | return NULL; |
305 | } | 321 | } |