e8f2bab3ffeef6733c82f117749fcd9faf880874
[openwrt.git] / package / d80211 / src / sta_info.c
1 /*
2  * Copyright 2002-2005, Instant802 Networks, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
8
9 #include <linux/module.h>
10 #include <linux/init.h>
11 #include <linux/kobject.h>
12 #include <linux/netdevice.h>
13 #include <linux/types.h>
14 #include <linux/slab.h>
15 #include <linux/skbuff.h>
16 #include <linux/if_arp.h>
17
18 #include <net/d80211.h>
19 #include "ieee80211_i.h"
20 #include "ieee80211_rate.h"
21 #include "sta_info.h"
22
23
24 /* Caller must hold local->sta_lock */
25 static void sta_info_hash_add(struct ieee80211_local *local,
26                               struct sta_info *sta)
27 {
28         sta->hnext = local->sta_hash[STA_HASH(sta->addr)];
29         local->sta_hash[STA_HASH(sta->addr)] = sta;
30 }
31
32
33 /* Caller must hold local->sta_lock */
34 static void sta_info_hash_del(struct ieee80211_local *local,
35                               struct sta_info *sta)
36 {
37         struct sta_info *s;
38
39         s = local->sta_hash[STA_HASH(sta->addr)];
40         if (!s)
41                 return;
42         if (memcmp(s->addr, sta->addr, ETH_ALEN) == 0) {
43                 local->sta_hash[STA_HASH(sta->addr)] = s->hnext;
44                 return;
45         }
46
47         while (s->hnext && memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0)
48                 s = s->hnext;
49         if (s->hnext)
50                 s->hnext = s->hnext->hnext;
51         else
52                 printk(KERN_ERR "%s: could not remove STA " MAC_FMT " from "
53                        "hash table\n", local->mdev->name, MAC_ARG(sta->addr));
54 }
55
56 static inline struct sta_info *__sta_info_get(struct sta_info *sta)
57 {
58         return kobject_get(&sta->kobj) ? sta : NULL;
59 }
60
61 struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr)
62 {
63         struct sta_info *sta;
64
65         spin_lock_bh(&local->sta_lock);
66         sta = local->sta_hash[STA_HASH(addr)];
67         while (sta) {
68                 if (memcmp(sta->addr, addr, ETH_ALEN) == 0) {
69                         __sta_info_get(sta);
70                         break;
71                 }
72                 sta = sta->hnext;
73         }
74         spin_unlock_bh(&local->sta_lock);
75
76         return sta;
77 }
78 EXPORT_SYMBOL(sta_info_get);
79
80 int sta_info_min_txrate_get(struct ieee80211_local *local)
81 {
82         struct sta_info *sta;
83         int min_txrate = 9999999;
84         int i;
85
86         spin_lock_bh(&local->sta_lock);
87         for (i = 0; i < STA_HASH_SIZE; i++) {
88                 sta = local->sta_hash[i];
89                 while (sta) {
90                         if (sta->txrate < min_txrate)
91                                 min_txrate = sta->txrate;
92                         sta = sta->hnext;
93                 }
94         }
95         spin_unlock_bh(&local->sta_lock);
96         if (min_txrate == 9999999)
97                 min_txrate = 0;
98
99         return min_txrate;
100 }
101
102
103 void sta_info_put(struct sta_info *sta)
104 {
105         kobject_put(&sta->kobj);
106 }
107 EXPORT_SYMBOL(sta_info_put);
108
109 void sta_info_release(struct kobject *kobj)
110 {
111         struct sta_info *sta = container_of(kobj, struct sta_info, kobj);
112         struct ieee80211_local *local = sta->local;
113         struct sk_buff *skb;
114
115         /* free sta structure; it has already been removed from
116          * hash table etc. external structures. Make sure that all
117          * buffered frames are release (one might have been added
118          * after sta_info_free() was called). */
119         while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
120                 local->total_ps_buffered--;
121                 dev_kfree_skb_any(skb);
122         }
123         while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
124                 dev_kfree_skb_any(skb);
125         }
126         rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
127         rate_control_put(sta->rate_ctrl);
128         kfree(sta);
129 }
130
131
132 struct sta_info * sta_info_add(struct ieee80211_local *local,
133                                struct net_device *dev, u8 *addr, gfp_t gfp)
134 {
135         struct sta_info *sta;
136
137         sta = kzalloc(sizeof(*sta), gfp);
138         if (!sta)
139                 return NULL;
140
141         if (kobject_set_name(&sta->kobj, MAC_FMT, MAC_ARG(addr))) {
142                 kfree(sta);
143                 return NULL;
144         }
145         sta->kobj.kset = &local->sta_kset;
146         kobject_init(&sta->kobj);
147
148         sta->rate_ctrl = rate_control_get(local->rate_ctrl);
149         sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, gfp);
150         if (!sta->rate_ctrl_priv) {
151                 rate_control_put(sta->rate_ctrl);
152                 kobject_put(&sta->kobj);
153                 kfree(sta);
154                 return NULL;
155         }
156
157         memcpy(sta->addr, addr, ETH_ALEN);
158         sta->local = local;
159         sta->dev = dev;
160         skb_queue_head_init(&sta->ps_tx_buf);
161         skb_queue_head_init(&sta->tx_filtered);
162         __sta_info_get(sta);    /* sta used by caller, decremented by
163                                  * sta_info_put() */
164         spin_lock_bh(&local->sta_lock);
165         list_add(&sta->list, &local->sta_list);
166         local->num_sta++;
167         sta_info_hash_add(local, sta);
168         spin_unlock_bh(&local->sta_lock);
169         if (local->ops->sta_table_notification)
170                 local->ops->sta_table_notification(local_to_hw(local),
171                                                   local->num_sta);
172         sta->key_idx_compression = HW_KEY_IDX_INVALID;
173
174 #ifdef CONFIG_D80211_VERBOSE_DEBUG
175         printk(KERN_DEBUG "%s: Added STA " MAC_FMT "\n",
176                local->mdev->name, MAC_ARG(addr));
177 #endif /* CONFIG_D80211_VERBOSE_DEBUG */
178
179         if (!in_interrupt()) {
180                 sta->sysfs_registered = 1;
181                 ieee80211_sta_sysfs_add(sta);
182                 rate_control_add_sta_attrs(sta, &sta->kobj);
183         } else {
184                 /* procfs entry adding might sleep, so schedule process context
185                  * task for adding proc entry for STAs that do not yet have
186                  * one. */
187                 schedule_work(&local->sta_proc_add);
188         }
189
190         return sta;
191 }
192
193 static void finish_sta_info_free(struct ieee80211_local *local,
194                                  struct sta_info *sta)
195 {
196 #ifdef CONFIG_D80211_VERBOSE_DEBUG
197         printk(KERN_DEBUG "%s: Removed STA " MAC_FMT "\n",
198                local->mdev->name, MAC_ARG(sta->addr));
199 #endif /* CONFIG_D80211_VERBOSE_DEBUG */
200
201         if (sta->key) {
202                 ieee80211_key_sysfs_remove(sta->key);
203                 ieee80211_key_free(sta->key);
204                 sta->key = NULL;
205         }
206
207         rate_control_remove_sta_attrs(sta, &sta->kobj);
208         ieee80211_sta_sysfs_remove(sta);
209
210         sta_info_put(sta);
211 }
212
213 void sta_info_free(struct sta_info *sta, int locked)
214 {
215         struct sk_buff *skb;
216         struct ieee80211_local *local = sta->local;
217         struct ieee80211_sub_if_data *sdata;
218
219         if (!locked)
220                 spin_lock_bh(&local->sta_lock);
221         sta_info_hash_del(local, sta);
222         list_del(&sta->list);
223         sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
224         if (sta->flags & WLAN_STA_PS) {
225                 sta->flags &= ~WLAN_STA_PS;
226                 if (sdata->bss)
227                         atomic_dec(&sdata->bss->num_sta_ps);
228         }
229         local->num_sta--;
230         sta_info_remove_aid_ptr(sta);
231         if (!locked)
232                 spin_unlock_bh(&local->sta_lock);
233         if (local->ops->sta_table_notification)
234                 local->ops->sta_table_notification(local_to_hw(local),
235                                                   local->num_sta);
236
237         while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
238                 local->total_ps_buffered--;
239                 dev_kfree_skb_any(skb);
240         }
241         while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
242                 dev_kfree_skb_any(skb);
243         }
244
245         if (sta->key) {
246                 if (local->ops->set_key) {
247                         struct ieee80211_key_conf *key;
248                         key = ieee80211_key_data2conf(local, sta->key);
249                         if (key) {
250                                 local->ops->set_key(local_to_hw(local),
251                                                    DISABLE_KEY,
252                                                    sta->addr, key, sta->aid);
253                                 kfree(key);
254                         }
255                 }
256         } else if (sta->key_idx_compression != HW_KEY_IDX_INVALID) {
257                 struct ieee80211_key_conf conf;
258                 memset(&conf, 0, sizeof(conf));
259                 conf.hw_key_idx = sta->key_idx_compression;
260                 conf.alg = ALG_NULL;
261                 conf.flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT;
262                 local->ops->set_key(local_to_hw(local), DISABLE_KEY,
263                                    sta->addr, &conf, sta->aid);
264                 sta->key_idx_compression = HW_KEY_IDX_INVALID;
265         }
266
267         if (in_atomic()) {
268                 list_add(&sta->list, &local->deleted_sta_list);
269                 schedule_work(&local->sta_proc_add);
270         } else
271                 finish_sta_info_free(local, sta);
272 }
273
274
275 static inline int sta_info_buffer_expired(struct ieee80211_local *local,
276                                           struct sta_info *sta,
277                                           struct sk_buff *skb)
278 {
279         struct ieee80211_tx_packet_data *pkt_data;
280         int timeout;
281
282         if (!skb)
283                 return 0;
284
285         pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
286
287         /* Timeout: (2 * listen_interval * beacon_int * 1024 / 1000000) sec */
288         timeout = (sta->listen_interval * local->hw.conf.beacon_int * 32 /
289                    15625) * HZ;
290         if (timeout < STA_TX_BUFFER_EXPIRE)
291                 timeout = STA_TX_BUFFER_EXPIRE;
292         return time_after(jiffies, pkt_data->jiffies + timeout);
293 }
294
295
296 static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
297                                              struct sta_info *sta)
298 {
299         unsigned long flags;
300         struct sk_buff *skb;
301
302         if (skb_queue_empty(&sta->ps_tx_buf))
303                 return;
304
305         for (;;) {
306                 spin_lock_irqsave(&sta->ps_tx_buf.lock, flags);
307                 skb = skb_peek(&sta->ps_tx_buf);
308                 if (sta_info_buffer_expired(local, sta, skb)) {
309                         skb = __skb_dequeue(&sta->ps_tx_buf);
310                         if (skb_queue_empty(&sta->ps_tx_buf))
311                                 sta->flags &= ~WLAN_STA_TIM;
312                 } else
313                         skb = NULL;
314                 spin_unlock_irqrestore(&sta->ps_tx_buf.lock, flags);
315
316                 if (skb) {
317                         local->total_ps_buffered--;
318                         printk(KERN_DEBUG "Buffered frame expired (STA "
319                                MAC_FMT ")\n", MAC_ARG(sta->addr));
320                         dev_kfree_skb(skb);
321                 } else
322                         break;
323         }
324 }
325
326
327 static void sta_info_cleanup(unsigned long data)
328 {
329         struct ieee80211_local *local = (struct ieee80211_local *) data;
330         struct sta_info *sta;
331
332         spin_lock_bh(&local->sta_lock);
333         list_for_each_entry(sta, &local->sta_list, list) {
334                 __sta_info_get(sta);
335                 sta_info_cleanup_expire_buffered(local, sta);
336                 sta_info_put(sta);
337         }
338         spin_unlock_bh(&local->sta_lock);
339
340         local->sta_cleanup.expires = jiffies + STA_INFO_CLEANUP_INTERVAL;
341         add_timer(&local->sta_cleanup);
342 }
343
344
345 static void sta_info_proc_add_task(struct work_struct *work)
346 {
347         struct ieee80211_local *local =
348                 container_of(work, struct ieee80211_local, sta_proc_add);
349         struct sta_info *sta, *tmp;
350
351         while (1) {
352                 spin_lock_bh(&local->sta_lock);
353                 if (!list_empty(&local->deleted_sta_list)) {
354                         sta = list_entry(local->deleted_sta_list.next,
355                                          struct sta_info, list);
356                         list_del(local->deleted_sta_list.next);
357                 } else
358                         sta = NULL;
359                 spin_unlock_bh(&local->sta_lock);
360                 if (!sta)
361                         break;
362                 finish_sta_info_free(local, sta);
363         }
364
365         while (1) {
366                 sta = NULL;
367                 spin_lock_bh(&local->sta_lock);
368                 list_for_each_entry(tmp, &local->sta_list, list) {
369                         if (!tmp->sysfs_registered) {
370                                 sta = tmp;
371                                 __sta_info_get(sta);
372                                 break;
373                         }
374                 }
375                 spin_unlock_bh(&local->sta_lock);
376
377                 if (!sta)
378                         break;
379
380                 sta->sysfs_registered = 1;
381                 ieee80211_sta_sysfs_add(sta);
382                 rate_control_add_sta_attrs(sta, &sta->kobj);
383                 sta_info_put(sta);
384         }
385 }
386
387
388 void sta_info_init(struct ieee80211_local *local)
389 {
390         spin_lock_init(&local->sta_lock);
391         INIT_LIST_HEAD(&local->sta_list);
392         INIT_LIST_HEAD(&local->deleted_sta_list);
393
394         init_timer(&local->sta_cleanup);
395         local->sta_cleanup.expires = jiffies + STA_INFO_CLEANUP_INTERVAL;
396         local->sta_cleanup.data = (unsigned long) local;
397         local->sta_cleanup.function = sta_info_cleanup;
398
399         INIT_WORK(&local->sta_proc_add, sta_info_proc_add_task);
400 }
401
402 int sta_info_start(struct ieee80211_local *local)
403 {
404         int res;
405
406         res = ieee80211_sta_kset_sysfs_register(local);
407         if (res)
408                 return res;
409         add_timer(&local->sta_cleanup);
410         return 0;
411 }
412
413 void sta_info_stop(struct ieee80211_local *local)
414 {
415         struct sta_info *sta, *tmp;
416
417         del_timer(&local->sta_cleanup);
418
419         list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
420                 /* sta_info_free must be called with 0 as the last
421                  * parameter to ensure all sysfs sta entries are
422                  * unregistered. We don't need locking at this
423                  * point. */
424                 sta_info_free(sta, 0);
425         }
426         ieee80211_sta_kset_sysfs_unregister(local);
427 }
428
429
430 void sta_info_remove_aid_ptr(struct sta_info *sta)
431 {
432         struct ieee80211_sub_if_data *sdata;
433
434         if (sta->aid <= 0)
435                 return;
436
437         sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
438
439         if (sdata->local->ops->set_tim)
440                 sdata->local->ops->set_tim(local_to_hw(sdata->local),
441                                           sta->aid, 0);
442         if (sdata->bss)
443                 __bss_tim_clear(sdata->bss, sta->aid);
444 }
445
446
447 /**
448  * sta_info_flush - flush matching STA entries from the STA table
449  * @local: local interface data
450  * @dev: matching rule for the net device (sta->dev) or %NULL to match all STAs
451  */
452 void sta_info_flush(struct ieee80211_local *local, struct net_device *dev)
453 {
454         struct sta_info *sta, *tmp;
455
456         spin_lock_bh(&local->sta_lock);
457         list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
458                 if (!dev || dev == sta->dev)
459                         sta_info_free(sta, 1);
460         spin_unlock_bh(&local->sta_lock);
461 }