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
,
150 void (*f
) (void *arg
, struct bss
*), void *arg
)
154 spin_lock_bh(&nt
->nt_nodelock
);
155 for (ni
= nt
->nt_node_first
; ni
; ni
= ni
->ni_list_next
) {
158 wlan_node_dec_free(ni
);
160 spin_unlock_bh(&nt
->nt_nodelock
);
163 void wlan_node_table_init(void *wmi
, struct ath6kl_node_table
*nt
)
165 ath6kl_dbg(ATH6KL_DBG_WLAN_NODE
, "node table = 0x%lx\n",
168 memset(nt
, 0, sizeof(struct ath6kl_node_table
));
170 spin_lock_init(&nt
->nt_nodelock
);
172 nt
->nt_node_age
= WLAN_NODE_INACT_TIMEOUT_MSEC
;
175 void wlan_refresh_inactive_nodes(struct ath6kl
*ar
)
177 struct ath6kl_node_table
*nt
= &ar
->scan_table
;
179 u8 my_bssid
[ETH_ALEN
];
182 ath6kl_wmi_get_current_bssid(ar
->wmi
, my_bssid
);
184 now
= jiffies_to_msecs(jiffies
);
185 bss
= nt
->nt_node_first
;
186 while (bss
!= NULL
) {
187 /* refresh all nodes except the current bss */
188 if (memcmp(my_bssid
, bss
->ni_macaddr
, sizeof(my_bssid
)) != 0) {
189 if (((now
- bss
->ni_tstamp
) > nt
->nt_node_age
)
190 || --bss
->ni_actcnt
== 0) {
191 wlan_node_reclaim(nt
, bss
);
194 bss
= bss
->ni_list_next
;
198 void wlan_node_table_cleanup(struct ath6kl_node_table
*nt
)
200 wlan_free_allnodes(nt
);
203 struct bss
*wlan_find_ssid_node(struct ath6kl_node_table
*nt
, u8
* ssid
,
204 u32 ssid_len
, bool is_wpa2
, bool match_ssid
)
206 struct bss
*ni
, *found_ni
= NULL
;
209 spin_lock_bh(&nt
->nt_nodelock
);
211 for (ni
= nt
->nt_node_first
; ni
; ni
= ni
->ni_list_next
) {
213 ie_ssid
= ni
->ni_cie
.ie_ssid
;
215 if ((ie_ssid
[1] <= IEEE80211_MAX_SSID_LEN
) &&
216 (memcmp(ssid
, &ie_ssid
[2], ssid_len
) == 0)) {
219 (is_wpa2
&& ni
->ni_cie
.ie_rsn
!= NULL
) ||
220 (!is_wpa2
&& ni
->ni_cie
.ie_wpa
!= NULL
)) {
228 spin_unlock_bh(&nt
->nt_nodelock
);
233 void wlan_node_return(struct ath6kl_node_table
*nt
, struct bss
*ni
)
235 spin_lock_bh(&nt
->nt_nodelock
);
236 wlan_node_dec_free(ni
);
237 spin_unlock_bh(&nt
->nt_nodelock
);