2 * Copyright (c) 2004-2011 Atheros Communications Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 struct bss
*wlan_node_alloc(int wh_size
)
25 ni
= kzalloc(sizeof(struct bss
), GFP_ATOMIC
);
27 if ((ni
!= NULL
) && wh_size
) {
28 ni
->ni_buf
= kmalloc(wh_size
, GFP_ATOMIC
);
29 if (ni
->ni_buf
== NULL
) {
38 void wlan_node_free(struct bss
*ni
)
44 void wlan_setup_node(struct ath6kl_node_table
*nt
, struct bss
*ni
,
49 memcpy(ni
->ni_macaddr
, mac_addr
, ETH_ALEN
);
50 hash
= ATH6KL_NODE_HASH(mac_addr
);
53 ni
->ni_tstamp
= jiffies_to_msecs(jiffies
);
54 ni
->ni_actcnt
= WLAN_NODE_INACT_CNT
;
56 spin_lock_bh(&nt
->nt_nodelock
);
58 /* insert at the end of the node list */
59 ni
->ni_list_next
= NULL
;
60 ni
->ni_list_prev
= nt
->nt_node_last
;
61 if (nt
->nt_node_last
!= NULL
)
62 nt
->nt_node_last
->ni_list_next
= ni
;
64 nt
->nt_node_last
= ni
;
65 if (nt
->nt_node_first
== NULL
)
66 nt
->nt_node_first
= ni
;
68 /* insert into the hash list */
69 ni
->ni_hash_next
= nt
->nt_hash
[hash
];
70 if (ni
->ni_hash_next
!= NULL
)
71 nt
->nt_hash
[hash
]->ni_hash_prev
= ni
;
73 ni
->ni_hash_prev
= NULL
;
74 nt
->nt_hash
[hash
] = ni
;
76 spin_unlock_bh(&nt
->nt_nodelock
);
79 struct bss
*wlan_find_node(struct ath6kl_node_table
*nt
,
82 struct bss
*ni
, *found_ni
= NULL
;
85 spin_lock_bh(&nt
->nt_nodelock
);
87 hash
= ATH6KL_NODE_HASH(mac_addr
);
88 for (ni
= nt
->nt_hash
[hash
]; ni
; ni
= ni
->ni_hash_next
) {
89 if (memcmp(ni
->ni_macaddr
, mac_addr
, ETH_ALEN
) == 0) {
96 spin_unlock_bh(&nt
->nt_nodelock
);
101 void wlan_node_reclaim(struct ath6kl_node_table
*nt
, struct bss
*ni
)
105 spin_lock_bh(&nt
->nt_nodelock
);
107 if (ni
->ni_list_prev
== NULL
)
109 nt
->nt_node_first
= ni
->ni_list_next
;
111 ni
->ni_list_prev
->ni_list_next
= ni
->ni_list_next
;
113 if (ni
->ni_list_next
== NULL
)
115 nt
->nt_node_last
= ni
->ni_list_prev
;
117 ni
->ni_list_next
->ni_list_prev
= ni
->ni_list_prev
;
119 if (ni
->ni_hash_prev
== NULL
) {
120 /* first in list so fix the list head */
121 hash
= ATH6KL_NODE_HASH(ni
->ni_macaddr
);
122 nt
->nt_hash
[hash
] = ni
->ni_hash_next
;
124 ni
->ni_hash_prev
->ni_hash_next
= ni
->ni_hash_next
;
127 if (ni
->ni_hash_next
!= NULL
)
128 ni
->ni_hash_next
->ni_hash_prev
= ni
->ni_hash_prev
;
132 spin_unlock_bh(&nt
->nt_nodelock
);
135 static void wlan_node_dec_free(struct bss
*ni
)
137 if ((ni
->ni_refcnt
--) == 1)
141 void wlan_free_allnodes(struct ath6kl_node_table
*nt
)
145 while ((ni
= nt
->nt_node_first
) != NULL
)
146 wlan_node_reclaim(nt
, ni
);
149 void wlan_iterate_nodes(struct ath6kl_node_table
*nt
, void *arg
)
153 spin_lock_bh(&nt
->nt_nodelock
);
154 for (ni
= nt
->nt_node_first
; ni
; ni
= ni
->ni_list_next
) {
156 ath6kl_cfg80211_scan_node(arg
, ni
);
157 wlan_node_dec_free(ni
);
159 spin_unlock_bh(&nt
->nt_nodelock
);
162 void wlan_node_table_init(struct ath6kl_node_table
*nt
)
164 ath6kl_dbg(ATH6KL_DBG_WLAN_NODE
, "node table = 0x%lx\n",
167 memset(nt
, 0, sizeof(struct ath6kl_node_table
));
169 spin_lock_init(&nt
->nt_nodelock
);
171 nt
->nt_node_age
= WLAN_NODE_INACT_TIMEOUT_MSEC
;
174 void wlan_refresh_inactive_nodes(struct ath6kl
*ar
)
176 struct ath6kl_node_table
*nt
= &ar
->scan_table
;
180 now
= jiffies_to_msecs(jiffies
);
181 bss
= nt
->nt_node_first
;
182 while (bss
!= NULL
) {
183 /* refresh all nodes except the current bss */
184 if (memcmp(ar
->bssid
, bss
->ni_macaddr
, ETH_ALEN
) != 0) {
185 if (((now
- bss
->ni_tstamp
) > nt
->nt_node_age
)
186 || --bss
->ni_actcnt
== 0) {
187 wlan_node_reclaim(nt
, bss
);
190 bss
= bss
->ni_list_next
;
194 void wlan_node_table_cleanup(struct ath6kl_node_table
*nt
)
196 wlan_free_allnodes(nt
);
199 struct bss
*wlan_find_ssid_node(struct ath6kl_node_table
*nt
, u8
* ssid
,
200 u32 ssid_len
, bool is_wpa2
, bool match_ssid
)
202 struct bss
*ni
, *found_ni
= NULL
;
205 spin_lock_bh(&nt
->nt_nodelock
);
207 for (ni
= nt
->nt_node_first
; ni
; ni
= ni
->ni_list_next
) {
209 ie_ssid
= ni
->ni_cie
.ie_ssid
;
211 if ((ie_ssid
[1] <= IEEE80211_MAX_SSID_LEN
) &&
212 (memcmp(ssid
, &ie_ssid
[2], ssid_len
) == 0)) {
215 (is_wpa2
&& ni
->ni_cie
.ie_rsn
!= NULL
) ||
216 (!is_wpa2
&& ni
->ni_cie
.ie_wpa
!= NULL
)) {
224 spin_unlock_bh(&nt
->nt_nodelock
);
229 void wlan_node_return(struct ath6kl_node_table
*nt
, struct bss
*ni
)
231 spin_lock_bh(&nt
->nt_nodelock
);
232 wlan_node_dec_free(ni
);
233 spin_unlock_bh(&nt
->nt_nodelock
);