improve dependency handling, fix some package makefile bugs
[10.03/openwrt.git] / target / linux / package / ieee80211-dscape / 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/config.h>
10 #include <linux/version.h>
11 #include <linux/module.h>
12 #include <linux/init.h>
13 #include <linux/netdevice.h>
14 #include <linux/types.h>
15 #include <linux/slab.h>
16 #include <linux/skbuff.h>
17 #include <linux/if_arp.h>
18
19 #include <net/ieee80211.h>
20 #include "ieee80211_i.h"
21 #include "ieee80211_proc.h"
22 #include "rate_control.h"
23
24
25 /* Caller must hold local->sta_lock */
26 static void sta_info_hash_add(struct ieee80211_local *local,
27                               struct sta_info *sta)
28 {
29         sta->hnext = local->sta_hash[STA_HASH(sta->addr)];
30         local->sta_hash[STA_HASH(sta->addr)] = sta;
31 }
32
33
34 /* Caller must hold local->sta_lock */
35 static void sta_info_hash_del(struct ieee80211_local *local,
36                               struct sta_info *sta)
37 {
38         struct sta_info *s;
39
40         s = local->sta_hash[STA_HASH(sta->addr)];
41         if (s == NULL)
42                 return;
43         if (memcmp(s->addr, sta->addr, ETH_ALEN) == 0) {
44                 local->sta_hash[STA_HASH(sta->addr)] = s->hnext;
45                 return;
46         }
47
48         while (s->hnext != NULL &&
49                memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0)
50                 s = s->hnext;
51         if (s->hnext != NULL)
52                 s->hnext = s->hnext->hnext;
53         else
54                 printk(KERN_ERR "%s: could not remove STA " MACSTR " from "
55                        "hash table\n", local->mdev->name, MAC2STR(sta->addr));
56 }
57
58
59 struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr)
60 {
61         struct sta_info *sta;
62
63         spin_lock_bh(&local->sta_lock);
64         sta = local->sta_hash[STA_HASH(addr)];
65         while (sta) {
66                 if (memcmp(sta->addr, addr, ETH_ALEN) == 0) {
67                         atomic_inc(&sta->users);
68                         break;
69                 }
70                 sta = sta->hnext;
71         }
72         spin_unlock_bh(&local->sta_lock);
73
74         return sta;
75 }
76
77
78 int sta_info_min_txrate_get(struct ieee80211_local *local)
79 {
80         struct sta_info *sta;
81         int min_txrate = 9999999;
82         int i;
83
84         spin_lock_bh(&local->sta_lock);
85         for (i = 0; i < STA_HASH_SIZE; i++) {
86                 sta = local->sta_hash[i];
87                 while (sta) {
88                         if (sta->txrate < min_txrate)
89                                 min_txrate = sta->txrate;
90                         sta = sta->hnext;
91                 }
92         }
93         spin_unlock_bh(&local->sta_lock);
94         if (min_txrate == 9999999)
95                 min_txrate = 0;
96
97         return min_txrate;
98 }
99
100
101 void sta_info_release(struct ieee80211_local *local, struct sta_info *sta)
102 {
103         struct sk_buff *skb;
104
105         if (!atomic_dec_and_test(&sta->users))
106                 return;
107
108         /* free sta structure; it has already been removed from
109          * hash table etc. external structures. Make sure that all
110          * buffered frames are release (one might have been added
111          * after sta_info_free() was called). */
112         while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
113                 local->total_ps_buffered--;
114                 dev_kfree_skb_any(skb);
115         }
116         while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
117                 dev_kfree_skb_any(skb);
118         }
119         rate_control_free_sta(local, sta->rate_ctrl_priv);
120         kfree(sta);
121 }
122
123
124 struct sta_info * sta_info_add(struct ieee80211_local *local,
125                                struct net_device *dev, u8 *addr)
126 {
127         struct sta_info *sta;
128
129         sta = kmalloc(sizeof(*sta), GFP_ATOMIC);
130         if (!sta)
131                 return NULL;
132
133         memset(sta, 0, sizeof(*sta));
134
135         sta->rate_ctrl_priv = rate_control_alloc_sta(local);
136         if (sta->rate_ctrl_priv == NULL) {
137                 kfree(sta);
138                 return NULL;
139         }
140
141         memcpy(sta->addr, addr, ETH_ALEN);
142         sta->dev = dev;
143         skb_queue_head_init(&sta->ps_tx_buf);
144         skb_queue_head_init(&sta->tx_filtered);
145         atomic_inc(&sta->users); /* sta in hashlist etc, decremented by
146                                   * sta_info_free() */
147         atomic_inc(&sta->users); /* sta used by caller, decremented by
148                                   * sta_info_release() */
149         spin_lock_bh(&local->sta_lock);
150         list_add(&sta->list, &local->sta_list);
151         local->num_sta++;
152         sta_info_hash_add(local, sta);
153         spin_unlock_bh(&local->sta_lock);
154         if (local->hw->sta_table_notification)
155                 local->hw->sta_table_notification(local->mdev, local->num_sta);
156         sta->key_idx_compression = HW_KEY_IDX_INVALID;
157
158 #ifdef CONFIG_IEEE80211_VERBOSE_DEBUG
159         printk(KERN_DEBUG "%s: Added STA " MACSTR "\n",
160                dev->name, MAC2STR(addr));
161 #endif /* CONFIG_IEEE80211_VERBOSE_DEBUG */
162
163         if (!in_interrupt()) {
164                 ieee80211_proc_init_sta(local, sta);
165         } else {
166                 /* procfs entry adding might sleep, so schedule process context
167                  * task for adding proc entry for STAs that do not yet have
168                  * one. */
169                 schedule_work(&local->sta_proc_add);
170         }
171
172         return sta;
173 }
174
175
176 void sta_info_free(struct ieee80211_local *local, struct sta_info *sta,
177                    int locked)
178 {
179         struct sk_buff *skb;
180         struct ieee80211_sub_if_data *sdata;
181
182         if (!locked)
183                 spin_lock_bh(&local->sta_lock);
184         sta_info_hash_del(local, sta);
185         list_del(&sta->list);
186         sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
187         if (sta->flags & WLAN_STA_PS) {
188                 sta->flags &= ~WLAN_STA_PS;
189                 if (sdata->bss)
190                         atomic_dec(&sdata->bss->num_sta_ps);
191         }
192         local->num_sta--;
193         sta_info_remove_aid_ptr(sta);
194         if (!locked)
195                 spin_unlock_bh(&local->sta_lock);
196         if (local->hw->sta_table_notification)
197                 local->hw->sta_table_notification(local->mdev, local->num_sta);
198
199         while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
200                 local->total_ps_buffered--;
201                 dev_kfree_skb_any(skb);
202         }
203         while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
204                 dev_kfree_skb_any(skb);
205         }
206
207         if (sta->key) {
208                 if (local->hw->set_key) {
209                         struct ieee80211_key_conf *key;
210                         key = ieee80211_key_data2conf(local, sta->key);
211                         if (key) {
212                                 local->hw->set_key(local->mdev, DISABLE_KEY,
213                                                    sta->addr, key, sta->aid);
214                                 kfree(key);
215                         }
216                 }
217                 kfree(sta->key);
218                 sta->key = NULL;
219         } else if (sta->key_idx_compression != HW_KEY_IDX_INVALID) {
220                 struct ieee80211_key_conf conf;
221                 memset(&conf, 0, sizeof(conf));
222                 conf.hw_key_idx = sta->key_idx_compression;
223                 conf.alg = ALG_NULL;
224                 conf.force_sw_encrypt = 1;
225                 local->hw->set_key(local->mdev, DISABLE_KEY, sta->addr, &conf,
226                                    sta->aid);
227                 sta->key_idx_compression = HW_KEY_IDX_INVALID;
228         }
229
230 #ifdef CONFIG_IEEE80211_VERBOSE_DEBUG
231         printk(KERN_DEBUG "%s: Removed STA " MACSTR "\n",
232                local->mdev->name, MAC2STR(sta->addr));
233 #endif /* CONFIG_IEEE80211_VERBOSE_DEBUG */
234
235         ieee80211_proc_deinit_sta(local, sta);
236
237         if (atomic_read(&sta->users) != 1) {
238                 /* This is OK, but printed for debugging. The station structure
239                  * will be removed when the other user of the data calls
240                  * sta_info_release(). */
241                 printk(KERN_DEBUG "%s: STA " MACSTR " users count %d when "
242                        "removing it\n", local->mdev->name, MAC2STR(sta->addr),
243                        atomic_read(&sta->users));
244         }
245
246         sta_info_release(local, sta);
247 }
248
249
250 static inline int sta_info_buffer_expired(struct sk_buff *skb)
251 {
252         struct ieee80211_tx_packet_data *pkt_data;
253         if (!skb)
254                 return 0;
255
256         /* TODO: this could be improved by passing STA listen interval into
257          * the kernel driver and expiring frames after 2 x listen_interval x
258          * beacon interval */
259
260         pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
261
262         if (pkt_data->magic != IEEE80211_CB_MAGIC)
263                 return 1;
264
265         return time_after(jiffies, pkt_data->jiffies + STA_TX_BUFFER_EXPIRE);
266 }
267
268
269 static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
270                                              struct sta_info *sta)
271 {
272         unsigned long flags;
273         struct sk_buff *skb;
274
275         if (skb_queue_empty(&sta->ps_tx_buf))
276                 return;
277
278         for (;;) {
279                 spin_lock_irqsave(&sta->ps_tx_buf.lock, flags);
280                 skb = skb_peek(&sta->ps_tx_buf);
281                 if (sta_info_buffer_expired(skb))
282                         skb = __skb_dequeue(&sta->ps_tx_buf);
283                 else
284                         skb = NULL;
285                 spin_unlock_irqrestore(&sta->ps_tx_buf.lock, flags);
286
287                 if (skb) {
288                         local->total_ps_buffered--;
289                         printk(KERN_DEBUG "Buffered frame expired (STA "
290                                MACSTR ")\n", MAC2STR(sta->addr));
291                         dev_kfree_skb(skb);
292                 } else
293                         break;
294         }
295 }
296
297
298 static void sta_info_cleanup(unsigned long data)
299 {
300         struct ieee80211_local *local = (struct ieee80211_local *) data;
301         struct list_head *ptr;
302
303         spin_lock_bh(&local->sta_lock);
304         ptr = local->sta_list.next;
305         while (ptr && ptr != &local->sta_list) {
306                 struct sta_info *sta = (struct sta_info *) ptr;
307                 atomic_inc(&sta->users);
308                 sta_info_cleanup_expire_buffered(local, sta);
309                 sta_info_release(local, sta);
310                 ptr = ptr->next;
311         }
312         spin_unlock_bh(&local->sta_lock);
313
314         local->sta_cleanup.expires = jiffies + STA_INFO_CLEANUP_INTERVAL;
315         add_timer(&local->sta_cleanup);
316 }
317
318
319 static void sta_info_proc_add_task(void *data)
320 {
321         struct ieee80211_local *local = data;
322         struct list_head *ptr;
323         struct sta_info *sta;
324         int max_adds = 100;
325
326         while (max_adds > 0) {
327                 sta = NULL;
328                 spin_lock_bh(&local->sta_lock);
329                 list_for_each(ptr, &local->sta_list) {
330                         sta = list_entry(ptr, struct sta_info, list);
331                         if (!sta->proc_entry_added) {
332                                 atomic_inc(&sta->users);
333                                 break;
334                         }
335                         sta = NULL;
336                 }
337                 spin_unlock_bh(&local->sta_lock);
338
339                 if (!sta)
340                         break;
341
342                 ieee80211_proc_init_sta(local, sta);
343                 atomic_dec(&sta->users);
344
345                 max_adds--;
346         }
347 }
348
349
350 void sta_info_init(struct ieee80211_local *local)
351 {
352         spin_lock_init(&local->sta_lock);
353         INIT_LIST_HEAD(&local->sta_list);
354
355         init_timer(&local->sta_cleanup);
356         local->sta_cleanup.expires = jiffies + STA_INFO_CLEANUP_INTERVAL;
357         local->sta_cleanup.data = (unsigned long) local;
358         local->sta_cleanup.function = sta_info_cleanup;
359
360         INIT_WORK(&local->sta_proc_add, sta_info_proc_add_task, local);
361 }
362
363 void sta_info_start(struct ieee80211_local *local)
364 {
365         add_timer(&local->sta_cleanup);
366 }
367
368 void sta_info_stop(struct ieee80211_local *local)
369 {
370         struct list_head *ptr;
371
372         del_timer(&local->sta_cleanup);
373
374         ptr = local->sta_list.next;
375         while (ptr && ptr != &local->sta_list) {
376                 struct sta_info *sta = (struct sta_info *) ptr;
377                 ptr = ptr->next;
378                 sta_info_free(local, sta, 0);
379         }
380 }
381
382
383 void sta_info_remove_aid_ptr(struct sta_info *sta)
384 {
385         struct ieee80211_sub_if_data *sdata;
386
387         sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
388         if (sta->aid <= 0 || !sdata->bss)
389                 return;
390
391         sdata->bss->sta_aid[sta->aid - 1] = NULL;
392         if (sta->aid == sdata->bss->max_aid) {
393                 while (sdata->bss->max_aid > 0 &&
394                        sdata->bss->sta_aid[sdata->bss->max_aid - 1] == NULL)
395                         sdata->bss->max_aid--;
396         }
397 }
398
399
400 /**
401  * sta_info_flush - flush matching STA entries from the STA table
402  * @local: local interface data
403  * @dev: matching rule for the net device (sta->dev) or %NULL to match all STAs
404  */
405 void sta_info_flush(struct ieee80211_local *local, struct net_device *dev)
406 {
407         struct list_head *ptr, *n;
408
409         spin_lock_bh(&local->sta_lock);
410
411         list_for_each_safe(ptr, n, &local->sta_list) {
412                 struct sta_info *sta = list_entry(ptr, struct sta_info, list);
413                 if (dev == NULL || dev == sta->dev)
414                         sta_info_free(local, sta, 1);
415         }
416         spin_unlock_bh(&local->sta_lock);
417 }