node.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. * Copyright (c) 2004-2011 Atheros Communications Inc.
  3. *
  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.
  7. *
  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.
  15. */
  16. #include "htc.h"
  17. #include "wmi.h"
  18. #include "debug.h"
  19. struct bss *wlan_node_alloc(int wh_size)
  20. {
  21. struct bss *ni;
  22. ni = kzalloc(sizeof(struct bss), GFP_ATOMIC);
  23. if ((ni != NULL) && wh_size) {
  24. ni->ni_buf = kmalloc(wh_size, GFP_ATOMIC);
  25. if (ni->ni_buf == NULL) {
  26. kfree(ni);
  27. return NULL;
  28. }
  29. }
  30. return ni;
  31. }
  32. void wlan_node_free(struct bss *ni)
  33. {
  34. kfree(ni->ni_buf);
  35. kfree(ni);
  36. }
  37. void wlan_setup_node(struct ath6kl_node_table *nt, struct bss *ni,
  38. const u8 *mac_addr)
  39. {
  40. int hash;
  41. memcpy(ni->ni_macaddr, mac_addr, ETH_ALEN);
  42. hash = ATH6KL_NODE_HASH(mac_addr);
  43. ni->ni_refcnt = 1;
  44. ni->ni_tstamp = jiffies_to_msecs(jiffies);
  45. ni->ni_actcnt = WLAN_NODE_INACT_CNT;
  46. spin_lock_bh(&nt->nt_nodelock);
  47. /* insert at the end of the node list */
  48. ni->ni_list_next = NULL;
  49. ni->ni_list_prev = nt->nt_node_last;
  50. if (nt->nt_node_last != NULL)
  51. nt->nt_node_last->ni_list_next = ni;
  52. nt->nt_node_last = ni;
  53. if (nt->nt_node_first == NULL)
  54. nt->nt_node_first = ni;
  55. /* insert into the hash list */
  56. ni->ni_hash_next = nt->nt_hash[hash];
  57. if (ni->ni_hash_next != NULL)
  58. nt->nt_hash[hash]->ni_hash_prev = ni;
  59. ni->ni_hash_prev = NULL;
  60. nt->nt_hash[hash] = ni;
  61. spin_unlock_bh(&nt->nt_nodelock);
  62. }
  63. struct bss *wlan_find_node(struct ath6kl_node_table *nt,
  64. const u8 *mac_addr)
  65. {
  66. struct bss *ni, *found_ni = NULL;
  67. int hash;
  68. spin_lock_bh(&nt->nt_nodelock);
  69. hash = ATH6KL_NODE_HASH(mac_addr);
  70. for (ni = nt->nt_hash[hash]; ni; ni = ni->ni_hash_next) {
  71. if (memcmp(ni->ni_macaddr, mac_addr, ETH_ALEN) == 0) {
  72. ni->ni_refcnt++;
  73. found_ni = ni;
  74. break;
  75. }
  76. }
  77. spin_unlock_bh(&nt->nt_nodelock);
  78. return found_ni;
  79. }
  80. void wlan_node_reclaim(struct ath6kl_node_table *nt, struct bss *ni)
  81. {
  82. int hash;
  83. spin_lock_bh(&nt->nt_nodelock);
  84. if (ni->ni_list_prev == NULL)
  85. /* fix list head */
  86. nt->nt_node_first = ni->ni_list_next;
  87. else
  88. ni->ni_list_prev->ni_list_next = ni->ni_list_next;
  89. if (ni->ni_list_next == NULL)
  90. /* fix list tail */
  91. nt->nt_node_last = ni->ni_list_prev;
  92. else
  93. ni->ni_list_next->ni_list_prev = ni->ni_list_prev;
  94. if (ni->ni_hash_prev == NULL) {
  95. /* first in list so fix the list head */
  96. hash = ATH6KL_NODE_HASH(ni->ni_macaddr);
  97. nt->nt_hash[hash] = ni->ni_hash_next;
  98. } else {
  99. ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next;
  100. }
  101. if (ni->ni_hash_next != NULL)
  102. ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev;
  103. wlan_node_free(ni);
  104. spin_unlock_bh(&nt->nt_nodelock);
  105. }
  106. static void wlan_node_dec_free(struct bss *ni)
  107. {
  108. if ((ni->ni_refcnt--) == 1)
  109. wlan_node_free(ni);
  110. }
  111. void wlan_free_allnodes(struct ath6kl_node_table *nt)
  112. {
  113. struct bss *ni;
  114. while ((ni = nt->nt_node_first) != NULL)
  115. wlan_node_reclaim(nt, ni);
  116. }
  117. void wlan_iterate_nodes(struct ath6kl_node_table *nt,
  118. void (*f) (void *arg, struct bss *), void *arg)
  119. {
  120. struct bss *ni;
  121. spin_lock_bh(&nt->nt_nodelock);
  122. for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
  123. ni->ni_refcnt++;
  124. (*f) (arg, ni);
  125. wlan_node_dec_free(ni);
  126. }
  127. spin_unlock_bh(&nt->nt_nodelock);
  128. }
  129. void wlan_node_table_init(void *wmi, struct ath6kl_node_table *nt)
  130. {
  131. ath6kl_dbg(ATH6KL_DBG_WLAN_NODE, "node table = 0x%lx\n",
  132. (unsigned long)nt);
  133. memset(nt, 0, sizeof(struct ath6kl_node_table));
  134. spin_lock_init(&nt->nt_nodelock);
  135. nt->nt_node_age = WLAN_NODE_INACT_TIMEOUT_MSEC;
  136. }
  137. void wlan_refresh_inactive_nodes(struct ath6kl *ar)
  138. {
  139. struct ath6kl_node_table *nt = &ar->scan_table;
  140. struct bss *bss;
  141. u32 now;
  142. now = jiffies_to_msecs(jiffies);
  143. bss = nt->nt_node_first;
  144. while (bss != NULL) {
  145. /* refresh all nodes except the current bss */
  146. if (memcmp(ar->bssid, bss->ni_macaddr, ETH_ALEN) != 0) {
  147. if (((now - bss->ni_tstamp) > nt->nt_node_age)
  148. || --bss->ni_actcnt == 0) {
  149. wlan_node_reclaim(nt, bss);
  150. }
  151. }
  152. bss = bss->ni_list_next;
  153. }
  154. }
  155. void wlan_node_table_cleanup(struct ath6kl_node_table *nt)
  156. {
  157. wlan_free_allnodes(nt);
  158. }
  159. struct bss *wlan_find_ssid_node(struct ath6kl_node_table *nt, u8 * ssid,
  160. u32 ssid_len, bool is_wpa2, bool match_ssid)
  161. {
  162. struct bss *ni, *found_ni = NULL;
  163. u8 *ie_ssid;
  164. spin_lock_bh(&nt->nt_nodelock);
  165. for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
  166. ie_ssid = ni->ni_cie.ie_ssid;
  167. if ((ie_ssid[1] <= IEEE80211_MAX_SSID_LEN) &&
  168. (memcmp(ssid, &ie_ssid[2], ssid_len) == 0)) {
  169. if (match_ssid ||
  170. (is_wpa2 && ni->ni_cie.ie_rsn != NULL) ||
  171. (!is_wpa2 && ni->ni_cie.ie_wpa != NULL)) {
  172. ni->ni_refcnt++;
  173. found_ni = ni;
  174. break;
  175. }
  176. }
  177. }
  178. spin_unlock_bh(&nt->nt_nodelock);
  179. return found_ni;
  180. }
  181. void wlan_node_return(struct ath6kl_node_table *nt, struct bss *ni)
  182. {
  183. spin_lock_bh(&nt->nt_nodelock);
  184. wlan_node_dec_free(ni);
  185. spin_unlock_bh(&nt->nt_nodelock);
  186. }