diff options
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r-- | net/mac80211/sta_info.c | 698 |
1 files changed, 523 insertions, 175 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 1f74bd296357..7d4fe4a52929 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -15,21 +15,57 @@ | |||
15 | #include <linux/skbuff.h> | 15 | #include <linux/skbuff.h> |
16 | #include <linux/if_arp.h> | 16 | #include <linux/if_arp.h> |
17 | #include <linux/timer.h> | 17 | #include <linux/timer.h> |
18 | #include <linux/rtnetlink.h> | ||
18 | 19 | ||
19 | #include <net/mac80211.h> | 20 | #include <net/mac80211.h> |
20 | #include "ieee80211_i.h" | 21 | #include "ieee80211_i.h" |
21 | #include "ieee80211_rate.h" | 22 | #include "rate.h" |
22 | #include "sta_info.h" | 23 | #include "sta_info.h" |
23 | #include "debugfs_sta.h" | 24 | #include "debugfs_sta.h" |
25 | #include "mesh.h" | ||
24 | 26 | ||
25 | /* Caller must hold local->sta_lock */ | 27 | /** |
26 | static void sta_info_hash_add(struct ieee80211_local *local, | 28 | * DOC: STA information lifetime rules |
27 | struct sta_info *sta) | 29 | * |
28 | { | 30 | * STA info structures (&struct sta_info) are managed in a hash table |
29 | sta->hnext = local->sta_hash[STA_HASH(sta->addr)]; | 31 | * for faster lookup and a list for iteration. They are managed using |
30 | local->sta_hash[STA_HASH(sta->addr)] = sta; | 32 | * RCU, i.e. access to the list and hash table is protected by RCU. |
31 | } | 33 | * |
32 | 34 | * Upon allocating a STA info structure with sta_info_alloc(), the caller owns | |
35 | * that structure. It must then either destroy it using sta_info_destroy() | ||
36 | * (which is pretty useless) or insert it into the hash table using | ||
37 | * sta_info_insert() which demotes the reference from ownership to a regular | ||
38 | * RCU-protected reference; if the function is called without protection by an | ||
39 | * RCU critical section the reference is instantly invalidated. Note that the | ||
40 | * caller may not do much with the STA info before inserting it, in particular, | ||
41 | * it may not start any mesh peer link management or add encryption keys. | ||
42 | * | ||
43 | * When the insertion fails (sta_info_insert()) returns non-zero), the | ||
44 | * structure will have been freed by sta_info_insert()! | ||
45 | * | ||
46 | * Because there are debugfs entries for each station, and adding those | ||
47 | * must be able to sleep, it is also possible to "pin" a station entry, | ||
48 | * that means it can be removed from the hash table but not be freed. | ||
49 | * See the comment in __sta_info_unlink() for more information, this is | ||
50 | * an internal capability only. | ||
51 | * | ||
52 | * In order to remove a STA info structure, the caller needs to first | ||
53 | * unlink it (sta_info_unlink()) from the list and hash tables and | ||
54 | * then destroy it; sta_info_destroy() will wait for an RCU grace period | ||
55 | * to elapse before actually freeing it. Due to the pinning and the | ||
56 | * possibility of multiple callers trying to remove the same STA info at | ||
57 | * the same time, sta_info_unlink() can clear the STA info pointer it is | ||
58 | * passed to indicate that the STA info is owned by somebody else now. | ||
59 | * | ||
60 | * If sta_info_unlink() did not clear the pointer then the caller owns | ||
61 | * the STA info structure now and is responsible of destroying it with | ||
62 | * a call to sta_info_destroy(). | ||
63 | * | ||
64 | * In all other cases, there is no concept of ownership on a STA entry, | ||
65 | * each structure is owned by the global hash table/list until it is | ||
66 | * removed. All users of the structure need to be RCU protected so that | ||
67 | * the structure won't be freed before they are done using it. | ||
68 | */ | ||
33 | 69 | ||
34 | /* Caller must hold local->sta_lock */ | 70 | /* Caller must hold local->sta_lock */ |
35 | static int sta_info_hash_del(struct ieee80211_local *local, | 71 | static int sta_info_hash_del(struct ieee80211_local *local, |
@@ -41,237 +77,439 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
41 | if (!s) | 77 | if (!s) |
42 | return -ENOENT; | 78 | return -ENOENT; |
43 | if (s == sta) { | 79 | if (s == sta) { |
44 | local->sta_hash[STA_HASH(sta->addr)] = s->hnext; | 80 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], |
81 | s->hnext); | ||
45 | return 0; | 82 | return 0; |
46 | } | 83 | } |
47 | 84 | ||
48 | while (s->hnext && s->hnext != sta) | 85 | while (s->hnext && s->hnext != sta) |
49 | s = s->hnext; | 86 | s = s->hnext; |
50 | if (s->hnext) { | 87 | if (s->hnext) { |
51 | s->hnext = sta->hnext; | 88 | rcu_assign_pointer(s->hnext, sta->hnext); |
52 | return 0; | 89 | return 0; |
53 | } | 90 | } |
54 | 91 | ||
55 | return -ENOENT; | 92 | return -ENOENT; |
56 | } | 93 | } |
57 | 94 | ||
58 | struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr) | 95 | /* protected by RCU */ |
96 | static struct sta_info *__sta_info_find(struct ieee80211_local *local, | ||
97 | u8 *addr) | ||
59 | { | 98 | { |
60 | struct sta_info *sta; | 99 | struct sta_info *sta; |
61 | 100 | ||
62 | read_lock_bh(&local->sta_lock); | 101 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); |
63 | sta = local->sta_hash[STA_HASH(addr)]; | ||
64 | while (sta) { | 102 | while (sta) { |
65 | if (memcmp(sta->addr, addr, ETH_ALEN) == 0) { | 103 | if (compare_ether_addr(sta->addr, addr) == 0) |
66 | __sta_info_get(sta); | ||
67 | break; | 104 | break; |
68 | } | 105 | sta = rcu_dereference(sta->hnext); |
69 | sta = sta->hnext; | ||
70 | } | 106 | } |
71 | read_unlock_bh(&local->sta_lock); | ||
72 | |||
73 | return sta; | 107 | return sta; |
74 | } | 108 | } |
109 | |||
110 | struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr) | ||
111 | { | ||
112 | return __sta_info_find(local, addr); | ||
113 | } | ||
75 | EXPORT_SYMBOL(sta_info_get); | 114 | EXPORT_SYMBOL(sta_info_get); |
76 | 115 | ||
77 | int sta_info_min_txrate_get(struct ieee80211_local *local) | 116 | struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, |
117 | struct net_device *dev) | ||
78 | { | 118 | { |
79 | struct sta_info *sta; | 119 | struct sta_info *sta; |
80 | struct ieee80211_hw_mode *mode; | 120 | int i = 0; |
81 | int min_txrate = 9999999; | 121 | |
82 | int i; | 122 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
83 | 123 | if (dev && dev != sta->sdata->dev) | |
84 | read_lock_bh(&local->sta_lock); | 124 | continue; |
85 | mode = local->oper_hw_mode; | 125 | if (i < idx) { |
86 | for (i = 0; i < STA_HASH_SIZE; i++) { | 126 | ++i; |
87 | sta = local->sta_hash[i]; | 127 | continue; |
88 | while (sta) { | ||
89 | if (sta->txrate < min_txrate) | ||
90 | min_txrate = sta->txrate; | ||
91 | sta = sta->hnext; | ||
92 | } | 128 | } |
129 | return sta; | ||
93 | } | 130 | } |
94 | read_unlock_bh(&local->sta_lock); | ||
95 | if (min_txrate == 9999999) | ||
96 | min_txrate = 0; | ||
97 | 131 | ||
98 | return mode->rates[min_txrate].rate; | 132 | return NULL; |
99 | } | 133 | } |
100 | 134 | ||
135 | /** | ||
136 | * __sta_info_free - internal STA free helper | ||
137 | * | ||
138 | * @sta: STA info to free | ||
139 | * | ||
140 | * This function must undo everything done by sta_info_alloc() | ||
141 | * that may happen before sta_info_insert(). | ||
142 | */ | ||
143 | static void __sta_info_free(struct ieee80211_local *local, | ||
144 | struct sta_info *sta) | ||
145 | { | ||
146 | DECLARE_MAC_BUF(mbuf); | ||
147 | |||
148 | rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv); | ||
149 | rate_control_put(sta->rate_ctrl); | ||
150 | |||
151 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
152 | printk(KERN_DEBUG "%s: Destroyed STA %s\n", | ||
153 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr)); | ||
154 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
101 | 155 | ||
102 | static void sta_info_release(struct kref *kref) | 156 | kfree(sta); |
157 | } | ||
158 | |||
159 | void sta_info_destroy(struct sta_info *sta) | ||
103 | { | 160 | { |
104 | struct sta_info *sta = container_of(kref, struct sta_info, kref); | 161 | struct ieee80211_local *local; |
105 | struct ieee80211_local *local = sta->local; | ||
106 | struct sk_buff *skb; | 162 | struct sk_buff *skb; |
107 | int i; | 163 | int i; |
108 | 164 | ||
109 | /* free sta structure; it has already been removed from | 165 | might_sleep(); |
110 | * hash table etc. external structures. Make sure that all | 166 | |
111 | * buffered frames are release (one might have been added | 167 | if (!sta) |
112 | * after sta_info_free() was called). */ | 168 | return; |
169 | |||
170 | local = sta->local; | ||
171 | |||
172 | rate_control_remove_sta_debugfs(sta); | ||
173 | ieee80211_sta_debugfs_remove(sta); | ||
174 | |||
175 | #ifdef CONFIG_MAC80211_MESH | ||
176 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | ||
177 | mesh_plink_deactivate(sta); | ||
178 | #endif | ||
179 | |||
180 | /* | ||
181 | * We have only unlinked the key, and actually destroying it | ||
182 | * may mean it is removed from hardware which requires that | ||
183 | * the key->sta pointer is still valid, so flush the key todo | ||
184 | * list here. | ||
185 | * | ||
186 | * ieee80211_key_todo() will synchronize_rcu() so after this | ||
187 | * nothing can reference this sta struct any more. | ||
188 | */ | ||
189 | ieee80211_key_todo(); | ||
190 | |||
191 | #ifdef CONFIG_MAC80211_MESH | ||
192 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | ||
193 | del_timer_sync(&sta->plink_timer); | ||
194 | #endif | ||
195 | |||
113 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { | 196 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { |
114 | local->total_ps_buffered--; | 197 | local->total_ps_buffered--; |
115 | dev_kfree_skb_any(skb); | 198 | dev_kfree_skb_any(skb); |
116 | } | 199 | } |
117 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { | 200 | |
201 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) | ||
118 | dev_kfree_skb_any(skb); | 202 | dev_kfree_skb_any(skb); |
203 | |||
204 | for (i = 0; i < STA_TID_NUM; i++) { | ||
205 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); | ||
206 | if (sta->ampdu_mlme.tid_rx[i]) | ||
207 | del_timer_sync(&sta->ampdu_mlme.tid_rx[i]->session_timer); | ||
208 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); | ||
209 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | ||
210 | if (sta->ampdu_mlme.tid_tx[i]) | ||
211 | del_timer_sync(&sta->ampdu_mlme.tid_tx[i]->addba_resp_timer); | ||
212 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | ||
119 | } | 213 | } |
120 | for (i = 0; i < STA_TID_NUM; i++) | 214 | |
121 | del_timer_sync(&sta->ampdu_mlme.tid_rx[i].session_timer); | 215 | __sta_info_free(local, sta); |
122 | rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv); | ||
123 | rate_control_put(sta->rate_ctrl); | ||
124 | kfree(sta); | ||
125 | } | 216 | } |
126 | 217 | ||
127 | 218 | ||
128 | void sta_info_put(struct sta_info *sta) | 219 | /* Caller must hold local->sta_lock */ |
220 | static void sta_info_hash_add(struct ieee80211_local *local, | ||
221 | struct sta_info *sta) | ||
129 | { | 222 | { |
130 | kref_put(&sta->kref, sta_info_release); | 223 | sta->hnext = local->sta_hash[STA_HASH(sta->addr)]; |
224 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], sta); | ||
131 | } | 225 | } |
132 | EXPORT_SYMBOL(sta_info_put); | ||
133 | 226 | ||
134 | 227 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |
135 | struct sta_info * sta_info_add(struct ieee80211_local *local, | 228 | u8 *addr, gfp_t gfp) |
136 | struct net_device *dev, u8 *addr, gfp_t gfp) | ||
137 | { | 229 | { |
230 | struct ieee80211_local *local = sdata->local; | ||
138 | struct sta_info *sta; | 231 | struct sta_info *sta; |
139 | int i; | 232 | int i; |
140 | DECLARE_MAC_BUF(mac); | 233 | DECLARE_MAC_BUF(mbuf); |
141 | 234 | ||
142 | sta = kzalloc(sizeof(*sta), gfp); | 235 | sta = kzalloc(sizeof(*sta), gfp); |
143 | if (!sta) | 236 | if (!sta) |
144 | return NULL; | 237 | return NULL; |
145 | 238 | ||
146 | kref_init(&sta->kref); | 239 | memcpy(sta->addr, addr, ETH_ALEN); |
240 | sta->local = local; | ||
241 | sta->sdata = sdata; | ||
147 | 242 | ||
148 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); | 243 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); |
149 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, gfp); | 244 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, |
245 | gfp); | ||
150 | if (!sta->rate_ctrl_priv) { | 246 | if (!sta->rate_ctrl_priv) { |
151 | rate_control_put(sta->rate_ctrl); | 247 | rate_control_put(sta->rate_ctrl); |
152 | kfree(sta); | 248 | kfree(sta); |
153 | return NULL; | 249 | return NULL; |
154 | } | 250 | } |
155 | 251 | ||
156 | memcpy(sta->addr, addr, ETH_ALEN); | ||
157 | sta->local = local; | ||
158 | sta->dev = dev; | ||
159 | spin_lock_init(&sta->ampdu_mlme.ampdu_rx); | 252 | spin_lock_init(&sta->ampdu_mlme.ampdu_rx); |
253 | spin_lock_init(&sta->ampdu_mlme.ampdu_tx); | ||
160 | for (i = 0; i < STA_TID_NUM; i++) { | 254 | for (i = 0; i < STA_TID_NUM; i++) { |
161 | /* timer_to_tid must be initialized with identity mapping to | 255 | /* timer_to_tid must be initialized with identity mapping to |
162 | * enable session_timer's data differentiation. refer to | 256 | * enable session_timer's data differentiation. refer to |
163 | * sta_rx_agg_session_timer_expired for useage */ | 257 | * sta_rx_agg_session_timer_expired for useage */ |
164 | sta->timer_to_tid[i] = i; | 258 | sta->timer_to_tid[i] = i; |
165 | /* rx timers */ | 259 | /* tid to tx queue: initialize according to HW (0 is valid) */ |
166 | sta->ampdu_mlme.tid_rx[i].session_timer.function = | 260 | sta->tid_to_tx_q[i] = local->hw.queues; |
167 | sta_rx_agg_session_timer_expired; | 261 | /* rx */ |
168 | sta->ampdu_mlme.tid_rx[i].session_timer.data = | 262 | sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE; |
169 | (unsigned long)&sta->timer_to_tid[i]; | 263 | sta->ampdu_mlme.tid_rx[i] = NULL; |
170 | init_timer(&sta->ampdu_mlme.tid_rx[i].session_timer); | 264 | /* tx */ |
265 | sta->ampdu_mlme.tid_state_tx[i] = HT_AGG_STATE_IDLE; | ||
266 | sta->ampdu_mlme.tid_tx[i] = NULL; | ||
267 | sta->ampdu_mlme.addba_req_num[i] = 0; | ||
171 | } | 268 | } |
172 | skb_queue_head_init(&sta->ps_tx_buf); | 269 | skb_queue_head_init(&sta->ps_tx_buf); |
173 | skb_queue_head_init(&sta->tx_filtered); | 270 | skb_queue_head_init(&sta->tx_filtered); |
174 | __sta_info_get(sta); /* sta used by caller, decremented by | 271 | |
175 | * sta_info_put() */ | 272 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
176 | write_lock_bh(&local->sta_lock); | 273 | printk(KERN_DEBUG "%s: Allocated STA %s\n", |
274 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr)); | ||
275 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
276 | |||
277 | #ifdef CONFIG_MAC80211_MESH | ||
278 | sta->plink_state = PLINK_LISTEN; | ||
279 | spin_lock_init(&sta->plink_lock); | ||
280 | init_timer(&sta->plink_timer); | ||
281 | #endif | ||
282 | |||
283 | return sta; | ||
284 | } | ||
285 | |||
286 | int sta_info_insert(struct sta_info *sta) | ||
287 | { | ||
288 | struct ieee80211_local *local = sta->local; | ||
289 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
290 | unsigned long flags; | ||
291 | int err = 0; | ||
292 | DECLARE_MAC_BUF(mac); | ||
293 | |||
294 | /* | ||
295 | * Can't be a WARN_ON because it can be triggered through a race: | ||
296 | * something inserts a STA (on one CPU) without holding the RTNL | ||
297 | * and another CPU turns off the net device. | ||
298 | */ | ||
299 | if (unlikely(!netif_running(sdata->dev))) { | ||
300 | err = -ENETDOWN; | ||
301 | goto out_free; | ||
302 | } | ||
303 | |||
304 | if (WARN_ON(compare_ether_addr(sta->addr, sdata->dev->dev_addr) == 0 || | ||
305 | is_multicast_ether_addr(sta->addr))) { | ||
306 | err = -EINVAL; | ||
307 | goto out_free; | ||
308 | } | ||
309 | |||
310 | spin_lock_irqsave(&local->sta_lock, flags); | ||
311 | /* check if STA exists already */ | ||
312 | if (__sta_info_find(local, sta->addr)) { | ||
313 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
314 | err = -EEXIST; | ||
315 | goto out_free; | ||
316 | } | ||
177 | list_add(&sta->list, &local->sta_list); | 317 | list_add(&sta->list, &local->sta_list); |
178 | local->num_sta++; | 318 | local->num_sta++; |
179 | sta_info_hash_add(local, sta); | 319 | sta_info_hash_add(local, sta); |
180 | if (local->ops->sta_notify) { | ||
181 | struct ieee80211_sub_if_data *sdata; | ||
182 | 320 | ||
183 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 321 | /* notify driver */ |
322 | if (local->ops->sta_notify) { | ||
184 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 323 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) |
185 | sdata = sdata->u.vlan.ap; | 324 | sdata = sdata->u.vlan.ap; |
186 | 325 | ||
187 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 326 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, |
188 | STA_NOTIFY_ADD, addr); | 327 | STA_NOTIFY_ADD, sta->addr); |
189 | } | 328 | } |
190 | write_unlock_bh(&local->sta_lock); | ||
191 | 329 | ||
192 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 330 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
193 | printk(KERN_DEBUG "%s: Added STA %s\n", | 331 | printk(KERN_DEBUG "%s: Inserted STA %s\n", |
194 | wiphy_name(local->hw.wiphy), print_mac(mac, addr)); | 332 | wiphy_name(local->hw.wiphy), print_mac(mac, sta->addr)); |
195 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 333 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
196 | 334 | ||
335 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
336 | |||
197 | #ifdef CONFIG_MAC80211_DEBUGFS | 337 | #ifdef CONFIG_MAC80211_DEBUGFS |
198 | /* debugfs entry adding might sleep, so schedule process | 338 | /* |
339 | * Debugfs entry adding might sleep, so schedule process | ||
199 | * context task for adding entry for STAs that do not yet | 340 | * context task for adding entry for STAs that do not yet |
200 | * have one. */ | 341 | * have one. |
201 | queue_work(local->hw.workqueue, &local->sta_debugfs_add); | 342 | * NOTE: due to auto-freeing semantics this may only be done |
343 | * if the insertion is successful! | ||
344 | */ | ||
345 | schedule_work(&local->sta_debugfs_add); | ||
202 | #endif | 346 | #endif |
203 | 347 | ||
204 | return sta; | 348 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
349 | mesh_accept_plinks_update(sdata); | ||
350 | |||
351 | return 0; | ||
352 | out_free: | ||
353 | BUG_ON(!err); | ||
354 | __sta_info_free(local, sta); | ||
355 | return err; | ||
205 | } | 356 | } |
206 | 357 | ||
207 | /* Caller must hold local->sta_lock */ | 358 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) |
208 | void sta_info_remove(struct sta_info *sta) | ||
209 | { | 359 | { |
210 | struct ieee80211_local *local = sta->local; | 360 | /* |
211 | struct ieee80211_sub_if_data *sdata; | 361 | * This format has been mandated by the IEEE specifications, |
362 | * so this line may not be changed to use the __set_bit() format. | ||
363 | */ | ||
364 | bss->tim[aid / 8] |= (1 << (aid % 8)); | ||
365 | } | ||
212 | 366 | ||
213 | /* don't do anything if we've been removed already */ | 367 | static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid) |
214 | if (sta_info_hash_del(local, sta)) | 368 | { |
215 | return; | 369 | /* |
370 | * This format has been mandated by the IEEE specifications, | ||
371 | * so this line may not be changed to use the __clear_bit() format. | ||
372 | */ | ||
373 | bss->tim[aid / 8] &= ~(1 << (aid % 8)); | ||
374 | } | ||
216 | 375 | ||
217 | list_del(&sta->list); | 376 | static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, |
218 | sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); | 377 | struct sta_info *sta) |
219 | if (sta->flags & WLAN_STA_PS) { | 378 | { |
220 | sta->flags &= ~WLAN_STA_PS; | 379 | if (bss) |
221 | if (sdata->bss) | 380 | __bss_tim_set(bss, sta->aid); |
222 | atomic_dec(&sdata->bss->num_sta_ps); | 381 | if (sta->local->ops->set_tim) { |
382 | sta->local->tim_in_locked_section = true; | ||
383 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1); | ||
384 | sta->local->tim_in_locked_section = false; | ||
223 | } | 385 | } |
224 | local->num_sta--; | 386 | } |
225 | sta_info_remove_aid_ptr(sta); | 387 | |
388 | void sta_info_set_tim_bit(struct sta_info *sta) | ||
389 | { | ||
390 | unsigned long flags; | ||
226 | 391 | ||
392 | spin_lock_irqsave(&sta->local->sta_lock, flags); | ||
393 | __sta_info_set_tim_bit(sta->sdata->bss, sta); | ||
394 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | ||
227 | } | 395 | } |
228 | 396 | ||
229 | void sta_info_free(struct sta_info *sta) | 397 | static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, |
398 | struct sta_info *sta) | ||
230 | { | 399 | { |
231 | struct sk_buff *skb; | 400 | if (bss) |
232 | struct ieee80211_local *local = sta->local; | 401 | __bss_tim_clear(bss, sta->aid); |
233 | DECLARE_MAC_BUF(mac); | 402 | if (sta->local->ops->set_tim) { |
403 | sta->local->tim_in_locked_section = true; | ||
404 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0); | ||
405 | sta->local->tim_in_locked_section = false; | ||
406 | } | ||
407 | } | ||
234 | 408 | ||
235 | might_sleep(); | 409 | void sta_info_clear_tim_bit(struct sta_info *sta) |
410 | { | ||
411 | unsigned long flags; | ||
236 | 412 | ||
237 | write_lock_bh(&local->sta_lock); | 413 | spin_lock_irqsave(&sta->local->sta_lock, flags); |
238 | sta_info_remove(sta); | 414 | __sta_info_clear_tim_bit(sta->sdata->bss, sta); |
239 | write_unlock_bh(&local->sta_lock); | 415 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); |
416 | } | ||
240 | 417 | ||
241 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { | 418 | void __sta_info_unlink(struct sta_info **sta) |
242 | local->total_ps_buffered--; | 419 | { |
243 | dev_kfree_skb(skb); | 420 | struct ieee80211_local *local = (*sta)->local; |
244 | } | 421 | struct ieee80211_sub_if_data *sdata = (*sta)->sdata; |
245 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { | 422 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
246 | dev_kfree_skb(skb); | 423 | DECLARE_MAC_BUF(mbuf); |
424 | #endif | ||
425 | /* | ||
426 | * pull caller's reference if we're already gone. | ||
427 | */ | ||
428 | if (sta_info_hash_del(local, *sta)) { | ||
429 | *sta = NULL; | ||
430 | return; | ||
247 | } | 431 | } |
248 | 432 | ||
249 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 433 | if ((*sta)->key) { |
250 | printk(KERN_DEBUG "%s: Removed STA %s\n", | 434 | ieee80211_key_free((*sta)->key); |
251 | wiphy_name(local->hw.wiphy), print_mac(mac, sta->addr)); | 435 | WARN_ON((*sta)->key); |
252 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 436 | } |
253 | 437 | ||
254 | ieee80211_key_free(sta->key); | 438 | list_del(&(*sta)->list); |
255 | sta->key = NULL; | ||
256 | 439 | ||
257 | if (local->ops->sta_notify) { | 440 | if ((*sta)->flags & WLAN_STA_PS) { |
258 | struct ieee80211_sub_if_data *sdata; | 441 | (*sta)->flags &= ~WLAN_STA_PS; |
442 | if (sdata->bss) | ||
443 | atomic_dec(&sdata->bss->num_sta_ps); | ||
444 | __sta_info_clear_tim_bit(sdata->bss, *sta); | ||
445 | } | ||
259 | 446 | ||
260 | sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); | 447 | local->num_sta--; |
261 | 448 | ||
449 | if (local->ops->sta_notify) { | ||
262 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 450 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) |
263 | sdata = sdata->u.vlan.ap; | 451 | sdata = sdata->u.vlan.ap; |
264 | 452 | ||
265 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 453 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, |
266 | STA_NOTIFY_REMOVE, sta->addr); | 454 | STA_NOTIFY_REMOVE, (*sta)->addr); |
267 | } | 455 | } |
268 | 456 | ||
269 | rate_control_remove_sta_debugfs(sta); | 457 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
270 | ieee80211_sta_debugfs_remove(sta); | 458 | mesh_accept_plinks_update(sdata); |
459 | #ifdef CONFIG_MAC80211_MESH | ||
460 | del_timer(&(*sta)->plink_timer); | ||
461 | #endif | ||
462 | } | ||
271 | 463 | ||
272 | sta_info_put(sta); | 464 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
465 | printk(KERN_DEBUG "%s: Removed STA %s\n", | ||
466 | wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->addr)); | ||
467 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
468 | |||
469 | /* | ||
470 | * Finally, pull caller's reference if the STA is pinned by the | ||
471 | * task that is adding the debugfs entries. In that case, we | ||
472 | * leave the STA "to be freed". | ||
473 | * | ||
474 | * The rules are not trivial, but not too complex either: | ||
475 | * (1) pin_status is only modified under the sta_lock | ||
476 | * (2) STAs may only be pinned under the RTNL so that | ||
477 | * sta_info_flush() is guaranteed to actually destroy | ||
478 | * all STAs that are active for a given interface, this | ||
479 | * is required for correctness because otherwise we | ||
480 | * could notify a driver that an interface is going | ||
481 | * away and only after that (!) notify it about a STA | ||
482 | * on that interface going away. | ||
483 | * (3) sta_info_debugfs_add_work() will set the status | ||
484 | * to PINNED when it found an item that needs a new | ||
485 | * debugfs directory created. In that case, that item | ||
486 | * must not be freed although all *RCU* users are done | ||
487 | * with it. Hence, we tell the caller of _unlink() | ||
488 | * that the item is already gone (as can happen when | ||
489 | * two tasks try to unlink/destroy at the same time) | ||
490 | * (4) We set the pin_status to DESTROY here when we | ||
491 | * find such an item. | ||
492 | * (5) sta_info_debugfs_add_work() will reset the pin_status | ||
493 | * from PINNED to NORMAL when it is done with the item, | ||
494 | * but will check for DESTROY before resetting it in | ||
495 | * which case it will free the item. | ||
496 | */ | ||
497 | if ((*sta)->pin_status == STA_INFO_PIN_STAT_PINNED) { | ||
498 | (*sta)->pin_status = STA_INFO_PIN_STAT_DESTROY; | ||
499 | *sta = NULL; | ||
500 | return; | ||
501 | } | ||
273 | } | 502 | } |
274 | 503 | ||
504 | void sta_info_unlink(struct sta_info **sta) | ||
505 | { | ||
506 | struct ieee80211_local *local = (*sta)->local; | ||
507 | unsigned long flags; | ||
508 | |||
509 | spin_lock_irqsave(&local->sta_lock, flags); | ||
510 | __sta_info_unlink(sta); | ||
511 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
512 | } | ||
275 | 513 | ||
276 | static inline int sta_info_buffer_expired(struct ieee80211_local *local, | 514 | static inline int sta_info_buffer_expired(struct ieee80211_local *local, |
277 | struct sta_info *sta, | 515 | struct sta_info *sta, |
@@ -299,6 +537,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
299 | { | 537 | { |
300 | unsigned long flags; | 538 | unsigned long flags; |
301 | struct sk_buff *skb; | 539 | struct sk_buff *skb; |
540 | struct ieee80211_sub_if_data *sdata; | ||
302 | DECLARE_MAC_BUF(mac); | 541 | DECLARE_MAC_BUF(mac); |
303 | 542 | ||
304 | if (skb_queue_empty(&sta->ps_tx_buf)) | 543 | if (skb_queue_empty(&sta->ps_tx_buf)) |
@@ -307,21 +546,23 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
307 | for (;;) { | 546 | for (;;) { |
308 | spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); | 547 | spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); |
309 | skb = skb_peek(&sta->ps_tx_buf); | 548 | skb = skb_peek(&sta->ps_tx_buf); |
310 | if (sta_info_buffer_expired(local, sta, skb)) { | 549 | if (sta_info_buffer_expired(local, sta, skb)) |
311 | skb = __skb_dequeue(&sta->ps_tx_buf); | 550 | skb = __skb_dequeue(&sta->ps_tx_buf); |
312 | if (skb_queue_empty(&sta->ps_tx_buf)) | 551 | else |
313 | sta->flags &= ~WLAN_STA_TIM; | ||
314 | } else | ||
315 | skb = NULL; | 552 | skb = NULL; |
316 | spin_unlock_irqrestore(&sta->ps_tx_buf.lock, flags); | 553 | spin_unlock_irqrestore(&sta->ps_tx_buf.lock, flags); |
317 | 554 | ||
318 | if (skb) { | 555 | if (!skb) |
319 | local->total_ps_buffered--; | ||
320 | printk(KERN_DEBUG "Buffered frame expired (STA " | ||
321 | "%s)\n", print_mac(mac, sta->addr)); | ||
322 | dev_kfree_skb(skb); | ||
323 | } else | ||
324 | break; | 556 | break; |
557 | |||
558 | sdata = sta->sdata; | ||
559 | local->total_ps_buffered--; | ||
560 | printk(KERN_DEBUG "Buffered frame expired (STA " | ||
561 | "%s)\n", print_mac(mac, sta->addr)); | ||
562 | dev_kfree_skb(skb); | ||
563 | |||
564 | if (skb_queue_empty(&sta->ps_tx_buf)) | ||
565 | sta_info_clear_tim_bit(sta); | ||
325 | } | 566 | } |
326 | } | 567 | } |
327 | 568 | ||
@@ -331,13 +572,10 @@ static void sta_info_cleanup(unsigned long data) | |||
331 | struct ieee80211_local *local = (struct ieee80211_local *) data; | 572 | struct ieee80211_local *local = (struct ieee80211_local *) data; |
332 | struct sta_info *sta; | 573 | struct sta_info *sta; |
333 | 574 | ||
334 | read_lock_bh(&local->sta_lock); | 575 | rcu_read_lock(); |
335 | list_for_each_entry(sta, &local->sta_list, list) { | 576 | list_for_each_entry_rcu(sta, &local->sta_list, list) |
336 | __sta_info_get(sta); | ||
337 | sta_info_cleanup_expire_buffered(local, sta); | 577 | sta_info_cleanup_expire_buffered(local, sta); |
338 | sta_info_put(sta); | 578 | rcu_read_unlock(); |
339 | } | ||
340 | read_unlock_bh(&local->sta_lock); | ||
341 | 579 | ||
342 | local->sta_cleanup.expires = | 580 | local->sta_cleanup.expires = |
343 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); | 581 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); |
@@ -345,38 +583,106 @@ static void sta_info_cleanup(unsigned long data) | |||
345 | } | 583 | } |
346 | 584 | ||
347 | #ifdef CONFIG_MAC80211_DEBUGFS | 585 | #ifdef CONFIG_MAC80211_DEBUGFS |
348 | static void sta_info_debugfs_add_task(struct work_struct *work) | 586 | /* |
587 | * See comment in __sta_info_unlink, | ||
588 | * caller must hold local->sta_lock. | ||
589 | */ | ||
590 | static void __sta_info_pin(struct sta_info *sta) | ||
591 | { | ||
592 | WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_NORMAL); | ||
593 | sta->pin_status = STA_INFO_PIN_STAT_PINNED; | ||
594 | } | ||
595 | |||
596 | /* | ||
597 | * See comment in __sta_info_unlink, returns sta if it | ||
598 | * needs to be destroyed. | ||
599 | */ | ||
600 | static struct sta_info *__sta_info_unpin(struct sta_info *sta) | ||
601 | { | ||
602 | struct sta_info *ret = NULL; | ||
603 | unsigned long flags; | ||
604 | |||
605 | spin_lock_irqsave(&sta->local->sta_lock, flags); | ||
606 | WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_DESTROY && | ||
607 | sta->pin_status != STA_INFO_PIN_STAT_PINNED); | ||
608 | if (sta->pin_status == STA_INFO_PIN_STAT_DESTROY) | ||
609 | ret = sta; | ||
610 | sta->pin_status = STA_INFO_PIN_STAT_NORMAL; | ||
611 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | ||
612 | |||
613 | return ret; | ||
614 | } | ||
615 | |||
616 | static void sta_info_debugfs_add_work(struct work_struct *work) | ||
349 | { | 617 | { |
350 | struct ieee80211_local *local = | 618 | struct ieee80211_local *local = |
351 | container_of(work, struct ieee80211_local, sta_debugfs_add); | 619 | container_of(work, struct ieee80211_local, sta_debugfs_add); |
352 | struct sta_info *sta, *tmp; | 620 | struct sta_info *sta, *tmp; |
621 | unsigned long flags; | ||
353 | 622 | ||
623 | /* We need to keep the RTNL across the whole pinned status. */ | ||
624 | rtnl_lock(); | ||
354 | while (1) { | 625 | while (1) { |
355 | sta = NULL; | 626 | sta = NULL; |
356 | read_lock_bh(&local->sta_lock); | 627 | |
628 | spin_lock_irqsave(&local->sta_lock, flags); | ||
357 | list_for_each_entry(tmp, &local->sta_list, list) { | 629 | list_for_each_entry(tmp, &local->sta_list, list) { |
358 | if (!tmp->debugfs.dir) { | 630 | if (!tmp->debugfs.dir) { |
359 | sta = tmp; | 631 | sta = tmp; |
360 | __sta_info_get(sta); | 632 | __sta_info_pin(sta); |
361 | break; | 633 | break; |
362 | } | 634 | } |
363 | } | 635 | } |
364 | read_unlock_bh(&local->sta_lock); | 636 | spin_unlock_irqrestore(&local->sta_lock, flags); |
365 | 637 | ||
366 | if (!sta) | 638 | if (!sta) |
367 | break; | 639 | break; |
368 | 640 | ||
369 | ieee80211_sta_debugfs_add(sta); | 641 | ieee80211_sta_debugfs_add(sta); |
370 | rate_control_add_sta_debugfs(sta); | 642 | rate_control_add_sta_debugfs(sta); |
371 | sta_info_put(sta); | 643 | |
644 | sta = __sta_info_unpin(sta); | ||
645 | sta_info_destroy(sta); | ||
372 | } | 646 | } |
647 | rtnl_unlock(); | ||
373 | } | 648 | } |
374 | #endif | 649 | #endif |
375 | 650 | ||
651 | static void __ieee80211_run_pending_flush(struct ieee80211_local *local) | ||
652 | { | ||
653 | struct sta_info *sta; | ||
654 | unsigned long flags; | ||
655 | |||
656 | ASSERT_RTNL(); | ||
657 | |||
658 | spin_lock_irqsave(&local->sta_lock, flags); | ||
659 | while (!list_empty(&local->sta_flush_list)) { | ||
660 | sta = list_first_entry(&local->sta_flush_list, | ||
661 | struct sta_info, list); | ||
662 | list_del(&sta->list); | ||
663 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
664 | sta_info_destroy(sta); | ||
665 | spin_lock_irqsave(&local->sta_lock, flags); | ||
666 | } | ||
667 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
668 | } | ||
669 | |||
670 | static void ieee80211_sta_flush_work(struct work_struct *work) | ||
671 | { | ||
672 | struct ieee80211_local *local = | ||
673 | container_of(work, struct ieee80211_local, sta_flush_work); | ||
674 | |||
675 | rtnl_lock(); | ||
676 | __ieee80211_run_pending_flush(local); | ||
677 | rtnl_unlock(); | ||
678 | } | ||
679 | |||
376 | void sta_info_init(struct ieee80211_local *local) | 680 | void sta_info_init(struct ieee80211_local *local) |
377 | { | 681 | { |
378 | rwlock_init(&local->sta_lock); | 682 | spin_lock_init(&local->sta_lock); |
379 | INIT_LIST_HEAD(&local->sta_list); | 683 | INIT_LIST_HEAD(&local->sta_list); |
684 | INIT_LIST_HEAD(&local->sta_flush_list); | ||
685 | INIT_WORK(&local->sta_flush_work, ieee80211_sta_flush_work); | ||
380 | 686 | ||
381 | setup_timer(&local->sta_cleanup, sta_info_cleanup, | 687 | setup_timer(&local->sta_cleanup, sta_info_cleanup, |
382 | (unsigned long)local); | 688 | (unsigned long)local); |
@@ -384,7 +690,7 @@ void sta_info_init(struct ieee80211_local *local) | |||
384 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); | 690 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); |
385 | 691 | ||
386 | #ifdef CONFIG_MAC80211_DEBUGFS | 692 | #ifdef CONFIG_MAC80211_DEBUGFS |
387 | INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_task); | 693 | INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_work); |
388 | #endif | 694 | #endif |
389 | } | 695 | } |
390 | 696 | ||
@@ -397,47 +703,89 @@ int sta_info_start(struct ieee80211_local *local) | |||
397 | void sta_info_stop(struct ieee80211_local *local) | 703 | void sta_info_stop(struct ieee80211_local *local) |
398 | { | 704 | { |
399 | del_timer(&local->sta_cleanup); | 705 | del_timer(&local->sta_cleanup); |
706 | cancel_work_sync(&local->sta_flush_work); | ||
707 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
708 | /* | ||
709 | * Make sure the debugfs adding work isn't pending after this | ||
710 | * because we're about to be destroyed. It doesn't matter | ||
711 | * whether it ran or not since we're going to flush all STAs | ||
712 | * anyway. | ||
713 | */ | ||
714 | cancel_work_sync(&local->sta_debugfs_add); | ||
715 | #endif | ||
716 | |||
717 | rtnl_lock(); | ||
400 | sta_info_flush(local, NULL); | 718 | sta_info_flush(local, NULL); |
719 | __ieee80211_run_pending_flush(local); | ||
720 | rtnl_unlock(); | ||
401 | } | 721 | } |
402 | 722 | ||
403 | void sta_info_remove_aid_ptr(struct sta_info *sta) | 723 | /** |
724 | * sta_info_flush - flush matching STA entries from the STA table | ||
725 | * | ||
726 | * Returns the number of removed STA entries. | ||
727 | * | ||
728 | * @local: local interface data | ||
729 | * @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs | ||
730 | */ | ||
731 | int sta_info_flush(struct ieee80211_local *local, | ||
732 | struct ieee80211_sub_if_data *sdata) | ||
404 | { | 733 | { |
405 | struct ieee80211_sub_if_data *sdata; | 734 | struct sta_info *sta, *tmp; |
735 | LIST_HEAD(tmp_list); | ||
736 | int ret = 0; | ||
737 | unsigned long flags; | ||
406 | 738 | ||
407 | if (sta->aid <= 0) | 739 | might_sleep(); |
408 | return; | 740 | ASSERT_RTNL(); |
741 | |||
742 | spin_lock_irqsave(&local->sta_lock, flags); | ||
743 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { | ||
744 | if (!sdata || sdata == sta->sdata) { | ||
745 | __sta_info_unlink(&sta); | ||
746 | if (sta) { | ||
747 | list_add_tail(&sta->list, &tmp_list); | ||
748 | ret++; | ||
749 | } | ||
750 | } | ||
751 | } | ||
752 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
409 | 753 | ||
410 | sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); | 754 | list_for_each_entry_safe(sta, tmp, &tmp_list, list) |
755 | sta_info_destroy(sta); | ||
411 | 756 | ||
412 | if (sdata->local->ops->set_tim) | 757 | return ret; |
413 | sdata->local->ops->set_tim(local_to_hw(sdata->local), | ||
414 | sta->aid, 0); | ||
415 | if (sdata->bss) | ||
416 | __bss_tim_clear(sdata->bss, sta->aid); | ||
417 | } | 758 | } |
418 | 759 | ||
419 | |||
420 | /** | 760 | /** |
421 | * sta_info_flush - flush matching STA entries from the STA table | 761 | * sta_info_flush_delayed - flush matching STA entries from the STA table |
422 | * @local: local interface data | 762 | * |
423 | * @dev: matching rule for the net device (sta->dev) or %NULL to match all STAs | 763 | * This function unlinks all stations for a given interface and queues |
764 | * them for freeing. Note that the workqueue function scheduled here has | ||
765 | * to run before any new keys can be added to the system to avoid set_key() | ||
766 | * callback ordering issues. | ||
767 | * | ||
768 | * @sdata: the interface | ||
424 | */ | 769 | */ |
425 | void sta_info_flush(struct ieee80211_local *local, struct net_device *dev) | 770 | void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata) |
426 | { | 771 | { |
772 | struct ieee80211_local *local = sdata->local; | ||
427 | struct sta_info *sta, *tmp; | 773 | struct sta_info *sta, *tmp; |
428 | LIST_HEAD(tmp_list); | 774 | unsigned long flags; |
429 | 775 | bool work = false; | |
430 | write_lock_bh(&local->sta_lock); | 776 | |
431 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) | 777 | spin_lock_irqsave(&local->sta_lock, flags); |
432 | if (!dev || dev == sta->dev) { | 778 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { |
433 | __sta_info_get(sta); | 779 | if (sdata == sta->sdata) { |
434 | sta_info_remove(sta); | 780 | __sta_info_unlink(&sta); |
435 | list_add_tail(&sta->list, &tmp_list); | 781 | if (sta) { |
782 | list_add_tail(&sta->list, | ||
783 | &local->sta_flush_list); | ||
784 | work = true; | ||
785 | } | ||
436 | } | 786 | } |
437 | write_unlock_bh(&local->sta_lock); | ||
438 | |||
439 | list_for_each_entry_safe(sta, tmp, &tmp_list, list) { | ||
440 | sta_info_free(sta); | ||
441 | sta_info_put(sta); | ||
442 | } | 787 | } |
788 | if (work) | ||
789 | schedule_work(&local->sta_flush_work); | ||
790 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
443 | } | 791 | } |