blob: 016cee03bf8f7d6c8b5f756e8856ca58aa192caa [file] [log] [blame]
Kiran V1ccee932012-12-12 14:49:46 -08001/*
Gopichand Nakkala0c1331e2013-01-07 22:49:07 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
Kiran V1ccee932012-12-12 14:49:46 -080021
22/**========================================================================
23
24 \file wlan_hdd_tdls.c
25
Chilam NG571c65a2013-01-19 12:27:36 +053026 \brief WLAN Host Device Driver implementation for TDLS
Kiran V1ccee932012-12-12 14:49:46 -080027
Kiran V1ccee932012-12-12 14:49:46 -080028 ========================================================================*/
29
30#include <wlan_hdd_includes.h>
31#include <wlan_hdd_hostapd.h>
32#include <net/cfg80211.h>
33#include <linux/netdevice.h>
34#include <linux/skbuff.h>
Chilam NG571c65a2013-01-19 12:27:36 +053035#include <linux/list.h>
Kiran V1ccee932012-12-12 14:49:46 -080036#include <linux/etherdevice.h>
37#include <net/ieee80211_radiotap.h>
38#include "wlan_hdd_tdls.h"
Chilam NG571c65a2013-01-19 12:27:36 +053039#include "wlan_hdd_cfg80211.h"
Kiran V1ccee932012-12-12 14:49:46 -080040
Chilam NG571c65a2013-01-19 12:27:36 +053041
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080042static struct mutex tdls_lock;
Gopichand Nakkala4327a152013-03-04 23:22:42 -080043static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(tdlsCtx_t *pHddTdlsCtx);
44static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t *pHddTdlsCtx);
45static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx);
Chilam NG571c65a2013-01-19 12:27:36 +053046
Hoonki Lee5a4b2172013-01-29 01:45:53 -080047#ifndef WLAN_FEATURE_TDLS_DEBUG
48#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
49#else
50#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_WARN
51#endif
52
Hoonki Lee387663d2013-02-05 18:08:43 -080053static u8 wlan_hdd_tdls_hash_key (u8 *mac)
Hoonki Leef63df0d2013-01-16 19:29:14 -080054{
55 int i;
Hoonki Lee387663d2013-02-05 18:08:43 -080056 u8 key = 0;
57
58 for (i = 0; i < 6; i++)
59 key ^= mac[i];
60
61 return key;
62}
63
Gopichand Nakkala4327a152013-03-04 23:22:42 -080064static v_VOID_t wlan_hdd_tdls_start_peer_discover_timer(tdlsCtx_t *pHddTdlsCtx,
65 tANI_BOOLEAN mutexLock,
66 v_U32_t discoveryExpiry)
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080067{
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080068 hdd_station_ctx_t *pHddStaCtx;
69
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080070 if ( mutexLock )
71 {
72 if (mutex_lock_interruptible(&tdls_lock))
73 {
74 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
75 "%s: unable to lock list: %d", __func__, __LINE__);
76 return;
77 }
78 }
79 if (NULL == pHddTdlsCtx)
80 {
81 if ( mutexLock )
82 mutex_unlock(&tdls_lock);
83 return;
84 }
85
Gopichand Nakkala4327a152013-03-04 23:22:42 -080086 if (NULL == pHddTdlsCtx->pAdapter)
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080087 {
88 if ( mutexLock )
89 mutex_unlock(&tdls_lock);
90 return;
91 }
92
Gopichand Nakkala4327a152013-03-04 23:22:42 -080093 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pHddTdlsCtx->pAdapter);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080094 if (hdd_connIsConnected( pHddStaCtx ))
95 {
96 vos_timer_start(&pHddTdlsCtx->peerDiscoverTimer, discoveryExpiry);
97 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "beacon rssi: %d",
98 pHddTdlsCtx->ap_rssi);
99 }
100 if ( mutexLock )
101 mutex_unlock(&tdls_lock);
102
103 return;
104}
105
Hoonki Lee387663d2013-02-05 18:08:43 -0800106static v_VOID_t wlan_hdd_tdls_discover_peer_cb( v_PVOID_t userData )
107{
108 int i;
109 struct list_head *head;
110 struct list_head *pos;
Chilam NG571c65a2013-01-19 12:27:36 +0530111 hddTdlsPeer_t *curr_peer;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800112 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800113 tdlsCtx_t *pHddTdlsCtx = (tdlsCtx_t *)userData;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800114 int discover_req_sent = 0;
115 v_U32_t discover_expiry = TDLS_SUB_DISCOVERY_PERIOD;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800116 tANI_BOOLEAN doMutexLock = eANI_BOOLEAN_TRUE;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800117
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800118 if (mutex_lock_interruptible(&tdls_lock))
119 {
120 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
121 "%s: unable to lock list : %d", __func__, __LINE__);
122 return;
123 }
Hoonki Leebfee0342013-01-21 16:43:45 -0800124
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800125 if (NULL == pHddTdlsCtx)
126 {
127 mutex_unlock(&tdls_lock);
128 return;
129 }
Hoonki Leebfee0342013-01-21 16:43:45 -0800130
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800131 if (NULL == pHddTdlsCtx->pAdapter)
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800132 {
133 mutex_unlock(&tdls_lock);
134 return;
135 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800136
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800137 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pHddTdlsCtx->pAdapter);
Hoonki Leef63df0d2013-01-16 19:29:14 -0800138
Hoonki Lee387663d2013-02-05 18:08:43 -0800139 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: ", __func__);
140
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800141 if (0 == pHddTdlsCtx->discovery_peer_cnt)
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800142 pHddTdlsCtx->discovery_peer_cnt = wlan_hdd_get_tdls_discovery_peer_cnt(pHddTdlsCtx);
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800143
Chilam NG571c65a2013-01-19 12:27:36 +0530144 for (i = 0; i < 256; i++) {
Hoonki Lee387663d2013-02-05 18:08:43 -0800145 head = &pHddTdlsCtx->peer_list[i];
Chilam NG571c65a2013-01-19 12:27:36 +0530146
Hoonki Lee387663d2013-02-05 18:08:43 -0800147 list_for_each (pos, head) {
148 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
Chilam NG571c65a2013-01-19 12:27:36 +0530149
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -0800150 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800151 "%d " MAC_ADDRESS_STR " %d %d, %d %d %d %d", i,
152 MAC_ADDR_ARRAY(curr_peer->peerMac),
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800153 curr_peer->discovery_processed,
154 discover_req_sent,
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -0800155 curr_peer->tdls_support,
156 curr_peer->link_status,
157 curr_peer->discovery_attempt,
158 pHddTdlsCtx->threshold_config.discovery_tries_n);
Hoonki Lee387663d2013-02-05 18:08:43 -0800159
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800160 if (discover_req_sent < TDLS_MAX_DISCOVER_REQS_PER_TIMER) {
161 if (!curr_peer->discovery_processed) {
Chilam NG571c65a2013-01-19 12:27:36 +0530162
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800163 curr_peer->discovery_processed = 1;
164 discover_req_sent++;
165 pHddTdlsCtx->discovery_peer_cnt--;
166
167 if ((eTDLS_CAP_UNKNOWN == curr_peer->tdls_support) &&
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800168 (eTDLS_LINK_IDLE == curr_peer->link_status) &&
Gopichand Nakkalab88f6772013-02-27 18:12:56 -0800169 (curr_peer->tx_pkt >=
170 pHddTdlsCtx->threshold_config.tx_packet_n)) {
Gopichand Nakkala273d5a02013-02-19 15:15:09 -0800171
172 if (curr_peer->discovery_attempt <
173 pHddTdlsCtx->threshold_config.discovery_tries_n) {
174
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800175 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800176 "sme_SendTdlsMgmtFrame(%d)", pHddTdlsCtx->pAdapter->sessionId);
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800177
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800178 sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter),
179 pHddTdlsCtx->pAdapter->sessionId,
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800180 curr_peer->peerMac,
181 WLAN_TDLS_DISCOVERY_REQUEST,
182 1, 0, NULL, 0, 0);
Gopichand Nakkala273d5a02013-02-19 15:15:09 -0800183 curr_peer->discovery_attempt++;
184 }
185 else
186 {
187 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
188 "%s: Maximum Discovery retries reached", __func__);
189 curr_peer->tdls_support = eTDLS_CAP_NOT_SUPPORTED;
190 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800191
192 }
193 }
Chilam NG571c65a2013-01-19 12:27:36 +0530194 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800195 else
196 goto exit_loop;
Hoonki Lee387663d2013-02-05 18:08:43 -0800197 }
Hoonki Leef63df0d2013-01-16 19:29:14 -0800198 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800199exit_loop:
Hoonki Leef63df0d2013-01-16 19:29:14 -0800200
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800201 if (0 != pHddTdlsCtx->discovery_peer_cnt) {
202 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
203 "discovery_peer_cnt is %d , Starting SUB_DISCOVERY_TIMER",
204 pHddTdlsCtx->discovery_peer_cnt);
205 discover_expiry = TDLS_SUB_DISCOVERY_PERIOD;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800206 doMutexLock = eANI_BOOLEAN_FALSE;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800207 goto done;
208 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800209 discover_expiry = pHddTdlsCtx->threshold_config.discovery_period_t;
210
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800211 mutex_unlock(&tdls_lock);
212
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800213 wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx);
Chilam NG571c65a2013-01-19 12:27:36 +0530214
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800215 /* Commenting out the following function as it was introducing
216 * a race condition when pHddTdlsCtx is deleted. Also , this
217 * function is consuming more time in the timer callback.
218 * RSSI based trigger needs to revisit this part of the code.
219 */
220
221 /*
222 * wlan_hdd_get_rssi(pAdapter, &pHddTdlsCtx->ap_rssi);
223 */
Chilam NG571c65a2013-01-19 12:27:36 +0530224
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800225done:
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800226 wlan_hdd_tdls_start_peer_discover_timer(pHddTdlsCtx, doMutexLock, discover_expiry);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800227
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800228 if ( !doMutexLock )
229 mutex_unlock(&tdls_lock);
230 return;
Hoonki Leef63df0d2013-01-16 19:29:14 -0800231}
Chilam NG571c65a2013-01-19 12:27:36 +0530232
Hoonki Lee387663d2013-02-05 18:08:43 -0800233static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData )
Chilam NG571c65a2013-01-19 12:27:36 +0530234{
235 int i;
Hoonki Lee387663d2013-02-05 18:08:43 -0800236 struct list_head *head;
237 struct list_head *pos;
Chilam NG571c65a2013-01-19 12:27:36 +0530238 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800239 tdlsCtx_t *pHddTdlsCtx;
Hoonki Leebfee0342013-01-21 16:43:45 -0800240
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800241 if (mutex_lock_interruptible(&tdls_lock))
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800242 {
243 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
244 "%s: unable to lock list", __func__);
245 return;
246 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800247 pHddTdlsCtx = (tdlsCtx_t *)userData;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800248 if (NULL == pHddTdlsCtx)
249 {
250 mutex_unlock(&tdls_lock);
251 return;
252 }
253
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800254 if (NULL == pHddTdlsCtx->pAdapter)
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800255 {
256 mutex_unlock(&tdls_lock);
257 return;
258 }
259
Chilam NG571c65a2013-01-19 12:27:36 +0530260 for (i = 0; i < 256; i++) {
Hoonki Lee387663d2013-02-05 18:08:43 -0800261 head = &pHddTdlsCtx->peer_list[i];
Chilam NG571c65a2013-01-19 12:27:36 +0530262
Hoonki Lee387663d2013-02-05 18:08:43 -0800263 list_for_each (pos, head) {
264 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
Chilam NG571c65a2013-01-19 12:27:36 +0530265
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800266 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
267 "hdd update cb - %d: " MAC_ADDRESS_STR " -> %d link_status -> %d"
268 "tdls_support -> %d", i,
Chilam Ng01120412013-02-19 18:32:21 -0800269 MAC_ADDR_ARRAY(curr_peer->peerMac),
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800270 curr_peer->tx_pkt, curr_peer->link_status, curr_peer->tdls_support);
Hoonki Lee387663d2013-02-05 18:08:43 -0800271
Chilam NG571c65a2013-01-19 12:27:36 +0530272 if (eTDLS_CAP_SUPPORTED == curr_peer->tdls_support) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800273 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800274 "%s: (tx %d, rx %d, config %d) " MAC_ADDRESS_STR " (%d) ",
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800275 __func__, curr_peer->tx_pkt, curr_peer->rx_pkt,
276 pHddTdlsCtx->threshold_config.tx_packet_n,
Chilam Ng01120412013-02-19 18:32:21 -0800277 MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->link_status);
278
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800279 if ((eTDLS_LINK_IDLE == curr_peer->link_status) ||
280 (eTDLS_LINK_DISCOVERING == curr_peer->link_status)){
Chilam NG571c65a2013-01-19 12:27:36 +0530281 if (curr_peer->tx_pkt >=
282 pHddTdlsCtx->threshold_config.tx_packet_n) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800283
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800284 if (HDD_MAX_NUM_TDLS_STA > wlan_hdd_tdlsConnectedPeers(pHddTdlsCtx->pAdapter))
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800285 {
286
287 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "-> Tput trigger TDLS SETUP");
Chilam NG571c65a2013-01-19 12:27:36 +0530288#ifdef CONFIG_TDLS_IMPLICIT
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800289
290 curr_peer->link_status = eTDLS_LINK_DISCOVERING;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800291 sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter),
292 pHddTdlsCtx->pAdapter->sessionId,
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800293 curr_peer->peerMac,
294 WLAN_TDLS_DISCOVERY_REQUEST,
295 1, 0, NULL, 0, 0);
Chilam NG571c65a2013-01-19 12:27:36 +0530296#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800297 }
298 else
299 {
300 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800301 "%s: Maximum peer connected already! %d",
302 __func__, wlan_hdd_tdlsConnectedPeers(pHddTdlsCtx->pAdapter) );
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800303 }
Hoonki Leecdd8e962013-01-20 00:45:46 -0800304 goto next_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530305 }
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800306#ifdef WLAN_FEATURE_TDLS_DEBUG
307 else {
308 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "-> ignored.");
309 }
310#endif
Gopichand Nakkala9f7592a2013-02-27 12:41:50 -0800311 if ((((tANI_S32)curr_peer->rssi >
Hoonki Leecdd8e962013-01-20 00:45:46 -0800312 (tANI_S32)(pHddTdlsCtx->threshold_config.rssi_hysteresis +
Gopichand Nakkala9f7592a2013-02-27 12:41:50 -0800313 pHddTdlsCtx->ap_rssi)) ||
314 ((tANI_S32)(curr_peer->rssi >
315 pHddTdlsCtx->threshold_config.rssi_trigger_threshold))) &&
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800316 (HDD_MAX_NUM_TDLS_STA > wlan_hdd_tdlsConnectedPeers(pHddTdlsCtx->pAdapter))){
Chilam NG571c65a2013-01-19 12:27:36 +0530317
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800318 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
319 "%s: RSSI (peer %d > ap %d + hysteresis %d) triggering to %02x:%02x:%02x:%02x:%02x:%02x ",
320 __func__, (tANI_S32)curr_peer->rssi,
321 pHddTdlsCtx->ap_rssi,
322 (tANI_S32)(pHddTdlsCtx->threshold_config.rssi_hysteresis),
323 curr_peer->peerMac[0], curr_peer->peerMac[1], curr_peer->peerMac[2],
324 curr_peer->peerMac[3], curr_peer->peerMac[4], curr_peer->peerMac[5]);
Chilam NG571c65a2013-01-19 12:27:36 +0530325
326#ifdef CONFIG_TDLS_IMPLICIT
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800327 cfg80211_tdls_oper_request(pHddTdlsCtx->pAdapter->dev,
Chilam NG571c65a2013-01-19 12:27:36 +0530328 curr_peer->peerMac,
329 NL80211_TDLS_SETUP, FALSE,
330 GFP_KERNEL);
331#endif
332 }
333 } else {
Chilam Ng01120412013-02-19 18:32:21 -0800334 if ((tANI_S32)curr_peer->rssi <
335 (tANI_S32)pHddTdlsCtx->threshold_config.rssi_teardown_threshold) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800336
Chilam Ng01120412013-02-19 18:32:21 -0800337 VOS_TRACE( VOS_MODULE_ID_HDD,
338 VOS_TRACE_LEVEL_WARN,
339 "Tear down - low RSSI: " MAC_ADDRESS_STR "!",
340 MAC_ADDR_ARRAY(curr_peer->peerMac));
341#ifdef CONFIG_TDLS_IMPLICIT
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800342 cfg80211_tdls_oper_request(pHddTdlsCtx->pAdapter->dev,
Chilam Ng01120412013-02-19 18:32:21 -0800343 curr_peer->peerMac,
344 NL80211_TDLS_TEARDOWN, FALSE,
345 GFP_KERNEL);
346#endif
Hoonki Leecdd8e962013-01-20 00:45:46 -0800347 goto next_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530348 }
Chilam Ng01120412013-02-19 18:32:21 -0800349
350 if ((curr_peer->tx_pkt <
351 pHddTdlsCtx->threshold_config.idle_packet_n) &&
352 (curr_peer->rx_pkt <
353 pHddTdlsCtx->threshold_config.idle_packet_n)) {
354 if (VOS_TIMER_STATE_RUNNING !=
355 vos_timer_getCurrentState(&curr_peer->peerIdleTimer)) {
356 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
357 "Tx/Rx Idle timer start: " MAC_ADDRESS_STR "!",
358 MAC_ADDR_ARRAY(curr_peer->peerMac));
359 vos_timer_start( &curr_peer->peerIdleTimer,
360 pHddTdlsCtx->threshold_config.idle_timeout_t );
361 }
362 } else {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800363 if (VOS_TIMER_STATE_RUNNING ==
364 vos_timer_getCurrentState(&curr_peer->peerIdleTimer)) {
Chilam Ng01120412013-02-19 18:32:21 -0800365 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
366 "Tx/Rx Idle timer stop: " MAC_ADDRESS_STR "!",
367 MAC_ADDR_ARRAY(curr_peer->peerMac));
368 vos_timer_stop( &curr_peer->peerIdleTimer);
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800369 }
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800370 }
Chilam Ng01120412013-02-19 18:32:21 -0800371
Hoonki Leecdd8e962013-01-20 00:45:46 -0800372// if (curr_peer->rssi <
373// (pHddTdlsCtx->threshold_config.rssi_hysteresis +
374// pHddTdlsCtx->ap_rssi)) {
375//
376//#ifdef CONFIG_TDLS_IMPLICIT
377// cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
378// curr_peer->peerMac,
379// NL80211_TDLS_TEARDOWN, FALSE,
380// GFP_KERNEL);
381//#endif
382// }
Chilam NG571c65a2013-01-19 12:27:36 +0530383 }
Chilam Ng01120412013-02-19 18:32:21 -0800384 } else if (eTDLS_CAP_UNKNOWN == curr_peer->tdls_support) {
385 if (eTDLS_LINK_CONNECTED != curr_peer->link_status) {
386 if (curr_peer->tx_pkt >=
387 pHddTdlsCtx->threshold_config.tx_packet_n) {
Chilam Ng01120412013-02-19 18:32:21 -0800388
389 if (++curr_peer->discovery_attempt <
390 pHddTdlsCtx->threshold_config.discovery_tries_n) {
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800391
392 sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter),
393 pHddTdlsCtx->pAdapter->sessionId,
Gopichand Nakkalab88f6772013-02-27 18:12:56 -0800394 curr_peer->peerMac,
395 WLAN_TDLS_DISCOVERY_REQUEST,
396 1, 0, NULL, 0, 0);
Chilam Ng01120412013-02-19 18:32:21 -0800397 }
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800398 else
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800399 {
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800400 curr_peer->tdls_support = eTDLS_CAP_NOT_SUPPORTED;
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800401 curr_peer->link_status = eTDLS_LINK_IDLE;
402 }
Chilam Ng01120412013-02-19 18:32:21 -0800403
404 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
405 "Tput triggering TDLS discovery: " MAC_ADDRESS_STR "!",
406 MAC_ADDR_ARRAY(curr_peer->peerMac));
407 }
408 }
Chilam NG571c65a2013-01-19 12:27:36 +0530409 }
410
Hoonki Leecdd8e962013-01-20 00:45:46 -0800411next_peer:
Chilam NG571c65a2013-01-19 12:27:36 +0530412 curr_peer->tx_pkt = 0;
Chilam Ng1279e232013-01-25 15:06:52 -0800413 curr_peer->rx_pkt = 0;
Hoonki Lee387663d2013-02-05 18:08:43 -0800414 }
Chilam NG571c65a2013-01-19 12:27:36 +0530415 }
416
417 vos_timer_start( &pHddTdlsCtx->peerUpdateTimer,
418 pHddTdlsCtx->threshold_config.tx_period_t );
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800419 mutex_unlock(&tdls_lock);
Chilam NG571c65a2013-01-19 12:27:36 +0530420}
421
Chilam Ng1279e232013-01-25 15:06:52 -0800422static v_VOID_t wlan_hdd_tdls_idle_cb( v_PVOID_t userData )
423{
Lee Hoonkic1262f22013-01-24 21:59:00 -0800424#ifdef CONFIG_TDLS_IMPLICIT
Chilam Ng1279e232013-01-25 15:06:52 -0800425 hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData;
426
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800427 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800428 "%s: Tx/Rx Idle " MAC_ADDRESS_STR " trigger teardown",
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800429 __func__,
Chilam Ng01120412013-02-19 18:32:21 -0800430 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800431 if (mutex_lock_interruptible(&tdls_lock))
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800432 {
433 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
434 "%s: unable to lock list", __func__);
435 return;
436 }
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800437
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800438 cfg80211_tdls_oper_request(curr_peer->pHddTdlsCtx->pAdapter->dev,
Chilam Ng1279e232013-01-25 15:06:52 -0800439 curr_peer->peerMac,
Hoonki Leea34dd892013-02-05 22:56:02 -0800440 NL80211_TDLS_TEARDOWN,
441 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON,
Chilam Ng1279e232013-01-25 15:06:52 -0800442 GFP_KERNEL);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800443 mutex_unlock(&tdls_lock);
Chilam Ng1279e232013-01-25 15:06:52 -0800444#endif
445}
446
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800447static void wlan_hdd_tdls_free_list(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800448{
449 int i;
450 struct list_head *head;
451 hddTdlsPeer_t *tmp;
452 struct list_head *pos, *q;
453
454 if (NULL == pHddTdlsCtx) return;
455
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800456
457 for (i = 0; i < 256; i++) {
458 head = &pHddTdlsCtx->peer_list[i];
459 list_for_each_safe (pos, q, head) {
460 tmp = list_entry(pos, hddTdlsPeer_t, node);
461 list_del(pos);
462 vos_mem_free(tmp);
463 }
464 }
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800465}
466
Hoonki Lee27511902013-03-14 18:19:06 -0700467int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter)
Chilam Ng01120412013-02-19 18:32:21 -0800468{
Chilam Ng01120412013-02-19 18:32:21 -0800469 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Hoonki Lee27511902013-03-14 18:19:06 -0700470 tdlsCtx_t *pHddTdlsCtx;
Chilam Ng01120412013-02-19 18:32:21 -0800471 int i;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800472 v_U8_t staIdx;
Chilam Ng01120412013-02-19 18:32:21 -0800473
Hoonki Lee27511902013-03-14 18:19:06 -0700474 mutex_init(&tdls_lock);
Chilam Ng01120412013-02-19 18:32:21 -0800475
Hoonki Lee27511902013-03-14 18:19:06 -0700476 if ((FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport) ||
477 (FALSE == sme_IsFeatureSupportedByFW(TDLS)))
478 {
479 pHddCtx->tdls_mode = eTDLS_SUPPORT_NOT_ENABLED;
480 pAdapter->sessionCtx.station.pHddTdlsCtx = NULL;
481 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS not enabled (%d) or FW doesn't support (%d)!",
482 __func__, pHddCtx->cfg_ini->fEnableTDLSSupport,
483 sme_IsFeatureSupportedByFW(TDLS));
484 return 0;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800485 }
486
Hoonki Lee27511902013-03-14 18:19:06 -0700487 pHddTdlsCtx = vos_mem_malloc(sizeof(tdlsCtx_t));
488
489 if (NULL == pHddTdlsCtx) {
490 hddLog(VOS_TRACE_LEVEL_ERROR, "%s malloc failed!", __func__);
491 pAdapter->sessionCtx.station.pHddTdlsCtx = NULL;
492 return -1;
493 }
494
495 pAdapter->sessionCtx.station.pHddTdlsCtx = pHddTdlsCtx;
496
497 /* initialize TDLS global context */
498 pHddCtx->connected_peer_count = 0;
499
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800500 for (staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
501 {
502 pHddCtx->tdlsConnInfo[staIdx].staId = 0;
503 pHddCtx->tdlsConnInfo[staIdx].sessionId = 255;
504 vos_mem_zero(&pHddCtx->tdlsConnInfo[staIdx].peerMac,
505 sizeof(v_MACADDR_t)) ;
Chilam Ng01120412013-02-19 18:32:21 -0800506 }
507
Hoonki Lee27511902013-03-14 18:19:06 -0700508 /* initialize TDLS pAdater context */
509 vos_mem_zero(pHddTdlsCtx, sizeof(tdlsCtx_t));
510
511 pHddTdlsCtx->pAdapter = pAdapter;
512
513 for (i = 0; i < 256; i++)
514 {
515 INIT_LIST_HEAD(&pHddTdlsCtx->peer_list[i]);
516 }
517
Chilam Ng01120412013-02-19 18:32:21 -0800518 vos_timer_init(&pHddTdlsCtx->peerDiscoverTimer,
519 VOS_TIMER_TYPE_SW,
520 wlan_hdd_tdls_discover_peer_cb,
521 pHddTdlsCtx);
522
523 vos_timer_init(&pHddTdlsCtx->peerUpdateTimer,
524 VOS_TIMER_TYPE_SW,
525 wlan_hdd_tdls_update_peer_cb,
526 pHddTdlsCtx);
527
Hoonki Lee27511902013-03-14 18:19:06 -0700528 /* remember configuration even if it is not used right now. it could be used later */
529 pHddTdlsCtx->threshold_config.tx_period_t = pHddCtx->cfg_ini->fTDLSTxStatsPeriod;
530 pHddTdlsCtx->threshold_config.tx_packet_n = pHddCtx->cfg_ini->fTDLSTxPacketThreshold;
531 pHddTdlsCtx->threshold_config.discovery_period_t = pHddCtx->cfg_ini->fTDLSDiscoveryPeriod;
532 pHddTdlsCtx->threshold_config.discovery_tries_n = pHddCtx->cfg_ini->fTDLSMaxDiscoveryAttempt;
533 pHddTdlsCtx->threshold_config.idle_timeout_t = pHddCtx->cfg_ini->fTDLSIdleTimeout;
534 pHddTdlsCtx->threshold_config.idle_packet_n = pHddCtx->cfg_ini->fTDLSIdlePacketThreshold;
535 pHddTdlsCtx->threshold_config.rssi_hysteresis = pHddCtx->cfg_ini->fTDLSRSSIHysteresis;
536 pHddTdlsCtx->threshold_config.rssi_trigger_threshold = pHddCtx->cfg_ini->fTDLSRSSITriggerThreshold;
537 pHddTdlsCtx->threshold_config.rssi_teardown_threshold = pHddCtx->cfg_ini->fTDLSRSSITeardownThreshold;
Chilam NG571c65a2013-01-19 12:27:36 +0530538
Chilam Ng01120412013-02-19 18:32:21 -0800539 if (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger)
Hoonki Lee387663d2013-02-05 18:08:43 -0800540 {
Chilam Ng01120412013-02-19 18:32:21 -0800541 pHddCtx->tdls_mode = eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY;
Hoonki Leebf870f32013-01-19 15:53:30 +0530542 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS Implicit trigger not enabled!", __func__);
Hoonki Leebf870f32013-01-19 15:53:30 +0530543 }
Hoonki Lee27511902013-03-14 18:19:06 -0700544 else
545 {
546 pHddCtx->tdls_mode = eTDLS_SUPPORT_ENABLED;
547 vos_timer_start( &pHddTdlsCtx->peerDiscoverTimer,
548 pHddTdlsCtx->threshold_config.discovery_period_t );
Chilam NG571c65a2013-01-19 12:27:36 +0530549
Hoonki Lee27511902013-03-14 18:19:06 -0700550 vos_timer_start( &pHddTdlsCtx->peerUpdateTimer,
551 pHddTdlsCtx->threshold_config.tx_period_t );
552 }
553
554 return 0;
Chilam NG571c65a2013-01-19 12:27:36 +0530555}
556
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800557void wlan_hdd_tdls_exit(hdd_adapter_t *pAdapter)
Chilam NG571c65a2013-01-19 12:27:36 +0530558{
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800559 tdlsCtx_t *pHddTdlsCtx;
560
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800561 if (mutex_lock_interruptible(&tdls_lock))
562 {
563 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
564 "%s: unable to lock list", __func__);
565 return;
566 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800567
568 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800569 if (NULL == pHddTdlsCtx)
570 {
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800571 mutex_unlock(&tdls_lock);
Hoonki Leebfee0342013-01-21 16:43:45 -0800572 hddLog(VOS_TRACE_LEVEL_WARN, "%s TDLS not enabled, exiting!", __func__);
573 return;
574 }
575
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800576 /* must stop timer here before freeing peer list, because peerIdleTimer is
577 part of peer list structure. */
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800578 wlan_hdd_tdls_timers_destroy(pHddTdlsCtx);
579 wlan_hdd_tdls_free_list(pHddTdlsCtx);
Chilam Nga75d8b62013-01-29 01:35:59 -0800580
581 vos_mem_free(pHddTdlsCtx);
582 pHddTdlsCtx = NULL;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800583 mutex_unlock(&tdls_lock);
Chilam NG571c65a2013-01-19 12:27:36 +0530584}
585
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800586/* stop all the tdls timers running */
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800587static void wlan_hdd_tdls_timers_stop(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800588{
589 int i;
590 struct list_head *head;
591 struct list_head *pos;
592 hddTdlsPeer_t *curr_peer;
593
594 vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer);
595 vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer);
596
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800597
598 for (i = 0; i < 256; i++)
599 {
600 head = &pHddTdlsCtx->peer_list[i];
601
602 list_for_each (pos, head) {
603 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
604
605 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800606 "%s: " MAC_ADDRESS_STR " -> stop idle timer",
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800607 __func__,
Chilam Ng01120412013-02-19 18:32:21 -0800608 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800609 vos_timer_stop ( &curr_peer->peerIdleTimer );
610 }
611 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800612}
613
614/* destroy all the tdls timers running */
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800615static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800616{
617 int i;
618 struct list_head *head;
619 struct list_head *pos;
620 hddTdlsPeer_t *curr_peer;
621
622 vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer);
623 vos_timer_destroy(&pHddTdlsCtx->peerDiscoverTimer);
624 vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer);
625 vos_timer_destroy(&pHddTdlsCtx->peerUpdateTimer);
626
627 for (i = 0; i < 256; i++)
628 {
629 head = &pHddTdlsCtx->peer_list[i];
630
631 list_for_each (pos, head) {
632 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
633
634 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800635 "%s: " MAC_ADDRESS_STR " -> destroy idle timer",
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800636 __func__,
Chilam Ng01120412013-02-19 18:32:21 -0800637 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800638 vos_timer_stop ( &curr_peer->peerIdleTimer );
639 vos_timer_destroy ( &curr_peer->peerIdleTimer );
640 }
641 }
642}
643
Hoonki Lee387663d2013-02-05 18:08:43 -0800644/* if mac address exist, return pointer
645 if mac address doesn't exist, create a list and add, return pointer
646 return NULL if fails to get new mac address
647*/
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800648hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, u8 *mac)
Chilam NG571c65a2013-01-19 12:27:36 +0530649{
Hoonki Lee387663d2013-02-05 18:08:43 -0800650 struct list_head *head;
651 hddTdlsPeer_t *peer;
652 u8 key;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800653 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Chilam NG571c65a2013-01-19 12:27:36 +0530654
Hoonki Lee387663d2013-02-05 18:08:43 -0800655 if (NULL == pHddTdlsCtx)
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800656 {
657 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
658 "%s: pHddTdlsCtx is NULL", __func__);
Hoonki Lee387663d2013-02-05 18:08:43 -0800659 return NULL;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800660 }
Hoonki Leebfee0342013-01-21 16:43:45 -0800661
Hoonki Lee387663d2013-02-05 18:08:43 -0800662 /* if already there, just update */
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800663 peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -0800664 if (peer != NULL)
665 {
666 return peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530667 }
668
Hoonki Lee387663d2013-02-05 18:08:43 -0800669 /* not found, allocate and add the list */
670 peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
671 if (NULL == peer) {
672 hddLog(VOS_TRACE_LEVEL_ERROR, "%s peer malloc failed!", __func__);
673 return NULL;
674 }
Chilam NG571c65a2013-01-19 12:27:36 +0530675
Hoonki Lee387663d2013-02-05 18:08:43 -0800676 key = wlan_hdd_tdls_hash_key(mac);
677 head = &pHddTdlsCtx->peer_list[key];
Chilam NG571c65a2013-01-19 12:27:36 +0530678
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800679 if (mutex_lock_interruptible(&tdls_lock))
Hoonki Lee387663d2013-02-05 18:08:43 -0800680 {
681 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
682 "%s: unable to lock list", __func__);
683 return NULL;
684 }
Chilam NG571c65a2013-01-19 12:27:36 +0530685
Hoonki Lee387663d2013-02-05 18:08:43 -0800686 vos_mem_zero(peer, sizeof(hddTdlsPeer_t));
687 vos_mem_copy(peer->peerMac, mac, sizeof(peer->peerMac));
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800688 peer->pHddTdlsCtx = pHddTdlsCtx;
Hoonki Lee387663d2013-02-05 18:08:43 -0800689
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800690 vos_timer_init(&peer->peerIdleTimer,
691 VOS_TIMER_TYPE_SW,
692 wlan_hdd_tdls_idle_cb,
693 peer);
694
Hoonki Lee387663d2013-02-05 18:08:43 -0800695 list_add_tail(&peer->node, head);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800696 mutex_unlock(&tdls_lock);
Hoonki Lee387663d2013-02-05 18:08:43 -0800697
698 return peer;
699}
700
Hoonki Lee27511902013-03-14 18:19:06 -0700701void wlan_hdd_tdls_set_cap(hdd_adapter_t *pAdapter,
702 u8* mac,
703 tTDLSCapType cap)
704{
705 hddTdlsPeer_t *curr_peer;
706
707 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
708 if (curr_peer == NULL)
709 return;
710
711 curr_peer->tdls_support = cap;
712
713 return;
714}
715
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800716void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer, tTDLSLinkStatus status)
Hoonki Lee387663d2013-02-05 18:08:43 -0800717{
718 if (curr_peer == NULL)
719 return;
720
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800721 hddLog(VOS_TRACE_LEVEL_WARN, "tdls set peer " MAC_ADDRESS_STR " link status to %u",
Chilam Ng01120412013-02-19 18:32:21 -0800722 MAC_ADDR_ARRAY(curr_peer->peerMac), status);
Chilam NG571c65a2013-01-19 12:27:36 +0530723
724 curr_peer->link_status = status;
725
Chilam NG571c65a2013-01-19 12:27:36 +0530726}
727
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800728void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter,
729 u8* mac,
730 tTDLSLinkStatus linkStatus)
731{
732 hddTdlsPeer_t *curr_peer;
733
734 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
735 if (curr_peer == NULL)
736 return;
737
738 curr_peer->link_status= linkStatus;
739
740 return;
741}
742
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800743int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter, u8 *mac)
Chilam NG571c65a2013-01-19 12:27:36 +0530744{
745 hddTdlsPeer_t *curr_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530746
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800747 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -0800748 if (curr_peer == NULL)
749 return -1;
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800750 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
751 "Discovery Response from : " MAC_ADDRESS_STR "link_status -> %d",
752 MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->link_status);
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800753 if (eTDLS_LINK_DISCOVERING == curr_peer->link_status)
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800754 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800755 cfg80211_tdls_oper_request(pAdapter->dev,
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800756 curr_peer->peerMac,
757 NL80211_TDLS_SETUP, FALSE,
758 GFP_KERNEL);
Gopichand Nakkala05922802013-03-14 12:23:19 -0700759 curr_peer->link_status = eTDLS_LINK_DISCOVERED;
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800760 }
761 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
762 "Peer with MAC : " MAC_ADDRESS_STR " transitioned to %d",
763 MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->link_status);
Chilam NG571c65a2013-01-19 12:27:36 +0530764
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800765 curr_peer->tdls_support = eTDLS_CAP_SUPPORTED;
Chilam NG571c65a2013-01-19 12:27:36 +0530766
Hoonki Lee387663d2013-02-05 18:08:43 -0800767 return 0;
Chilam NG571c65a2013-01-19 12:27:36 +0530768}
769
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800770int wlan_hdd_tdls_set_rssi(hdd_adapter_t *pAdapter, u8 *mac, tANI_S8 rxRssi)
Chilam NG571c65a2013-01-19 12:27:36 +0530771{
772 hddTdlsPeer_t *curr_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530773
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800774 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -0800775 if (curr_peer == NULL)
776 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530777
778 curr_peer->rssi = rxRssi;
779
Hoonki Lee387663d2013-02-05 18:08:43 -0800780 return 0;
Chilam NG571c65a2013-01-19 12:27:36 +0530781}
782
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800783int wlan_hdd_tdls_set_responder(hdd_adapter_t *pAdapter, u8 *mac, tANI_U8 responder)
Hoonki Leea34dd892013-02-05 22:56:02 -0800784{
785 hddTdlsPeer_t *curr_peer;
786
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800787 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800788 if (curr_peer == NULL)
Hoonki Leea34dd892013-02-05 22:56:02 -0800789 return -1;
790
791 curr_peer->is_responder = responder;
792
793 return 0;
794}
795
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800796int wlan_hdd_tdls_get_responder(hdd_adapter_t *pAdapter, u8 *mac)
Hoonki Leea34dd892013-02-05 22:56:02 -0800797{
798 hddTdlsPeer_t *curr_peer;
799
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800800 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800801 if (curr_peer == NULL)
Hoonki Leea34dd892013-02-05 22:56:02 -0800802 return -1;
803
804 return (curr_peer->is_responder);
805}
806
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800807int wlan_hdd_tdls_set_signature(hdd_adapter_t *pAdapter, u8 *mac, tANI_U8 uSignature)
Hoonki Lee11f7dda2013-02-14 16:55:44 -0800808{
809 hddTdlsPeer_t *curr_peer;
810
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800811 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee11f7dda2013-02-14 16:55:44 -0800812 if (curr_peer == NULL)
813 return -1;
814
815 curr_peer->signature = uSignature;
816
817 return 0;
818}
819
Hoonki Leea34dd892013-02-05 22:56:02 -0800820
Hoonki Lee387663d2013-02-05 18:08:43 -0800821void wlan_hdd_tdls_extract_da(struct sk_buff *skb, u8 *mac)
Chilam NG571c65a2013-01-19 12:27:36 +0530822{
Chilam NG571c65a2013-01-19 12:27:36 +0530823 memcpy(mac, skb->data, 6);
Chilam NG571c65a2013-01-19 12:27:36 +0530824}
825
Hoonki Lee387663d2013-02-05 18:08:43 -0800826void wlan_hdd_tdls_extract_sa(struct sk_buff *skb, u8 *mac)
Chilam Ng1279e232013-01-25 15:06:52 -0800827{
Chilam Ng1279e232013-01-25 15:06:52 -0800828 memcpy(mac, skb->data+6, 6);
Chilam Ng1279e232013-01-25 15:06:52 -0800829}
830
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800831int wlan_hdd_tdls_increment_pkt_count(hdd_adapter_t *pAdapter, u8 *mac, u8 tx)
Chilam NG571c65a2013-01-19 12:27:36 +0530832{
Hoonki Lee387663d2013-02-05 18:08:43 -0800833 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800834 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam NG571c65a2013-01-19 12:27:36 +0530835
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800836 if (eTDLS_SUPPORT_ENABLED != pHddCtx->tdls_mode)
837 return -1;
Hoonki Leebfee0342013-01-21 16:43:45 -0800838
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800839 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -0800840 if (curr_peer == NULL)
Chilam NG571c65a2013-01-19 12:27:36 +0530841 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530842
Chilam Ng1279e232013-01-25 15:06:52 -0800843 if (tx)
844 curr_peer->tx_pkt++;
845 else
846 curr_peer->rx_pkt++;
Chilam NG571c65a2013-01-19 12:27:36 +0530847
Chilam NG571c65a2013-01-19 12:27:36 +0530848 return 0;
849}
850
Hoonki Lee27511902013-03-14 18:19:06 -0700851static int wlan_hdd_tdls_check_config(tdls_config_params_t *config)
852{
853 if (config->tdls > 2)
854 {
855 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 1st argument %d. <0...2>", __func__, config->tdls);
856 return -1;
857 }
858 if (config->tx_period_t < CFG_TDLS_TX_STATS_PERIOD_MIN ||
859 config->tx_period_t > CFG_TDLS_TX_STATS_PERIOD_MAX)
860 {
861 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 2nd argument %d. <%d...%d>", __func__, config->tx_period_t,
862 CFG_TDLS_TX_STATS_PERIOD_MIN, CFG_TDLS_TX_STATS_PERIOD_MAX);
863 return -1;
864 }
865 if (config->tx_packet_n < CFG_TDLS_TX_PACKET_THRESHOLD_MIN ||
866 config->tx_packet_n > CFG_TDLS_TX_PACKET_THRESHOLD_MAX)
867 {
868 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 3rd argument %d. <%d...%d>", __func__, config->tx_packet_n,
869 CFG_TDLS_TX_PACKET_THRESHOLD_MIN, CFG_TDLS_TX_PACKET_THRESHOLD_MAX);
870 return -1;
871 }
872 if (config->discovery_period_t < CFG_TDLS_DISCOVERY_PERIOD_MIN ||
873 config->discovery_period_t > CFG_TDLS_DISCOVERY_PERIOD_MAX)
874 {
875 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 4th argument %d. <%d...%d>", __func__, config->discovery_period_t,
876 CFG_TDLS_DISCOVERY_PERIOD_MIN, CFG_TDLS_DISCOVERY_PERIOD_MAX);
877 return -1;
878 }
879 if (config->discovery_tries_n < CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MIN ||
880 config->discovery_tries_n > CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MAX)
881 {
882 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 5th argument %d. <%d...%d>", __func__, config->discovery_tries_n,
883 CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MIN, CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MAX);
884 return -1;
885 }
886 if (config->idle_timeout_t < CFG_TDLS_IDLE_TIMEOUT_MIN ||
887 config->idle_timeout_t > CFG_TDLS_IDLE_TIMEOUT_MAX)
888 {
889 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 6th argument %d. <%d...%d>", __func__, config->idle_timeout_t,
890 CFG_TDLS_IDLE_TIMEOUT_MIN, CFG_TDLS_IDLE_TIMEOUT_MAX);
891 return -1;
892 }
893 if (config->idle_packet_n < CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN ||
894 config->idle_packet_n > CFG_TDLS_IDLE_PACKET_THRESHOLD_MAX)
895 {
896 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 7th argument %d. <%d...%d>", __func__, config->idle_packet_n,
897 CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN, CFG_TDLS_IDLE_PACKET_THRESHOLD_MAX);
898 return -1;
899 }
900 if (config->rssi_hysteresis < CFG_TDLS_RSSI_HYSTERESIS_MIN ||
901 config->rssi_hysteresis > CFG_TDLS_RSSI_HYSTERESIS_MAX)
902 {
903 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 8th argument %d. <%d...%d>", __func__, config->rssi_hysteresis,
904 CFG_TDLS_RSSI_HYSTERESIS_MIN, CFG_TDLS_RSSI_HYSTERESIS_MAX);
905 return -1;
906 }
907 if (config->rssi_trigger_threshold < CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MIN ||
908 config->rssi_trigger_threshold > CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MAX)
909 {
910 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 9th argument %d. <%d...%d>", __func__, config->rssi_trigger_threshold,
911 CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MIN, CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MAX);
912 return -1;
913 }
914 if (config->rssi_teardown_threshold < CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN ||
915 config->rssi_teardown_threshold > CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX)
916 {
917 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 10th argument %d. <%d...%d>", __func__, config->rssi_teardown_threshold,
918 CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN, CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX);
919 return -1;
920 }
921 return 0;
922}
923
Chilam Ng01120412013-02-19 18:32:21 -0800924int wlan_hdd_tdls_set_params(struct net_device *dev, tdls_config_params_t *config)
Chilam NG571c65a2013-01-19 12:27:36 +0530925{
Chilam Ng01120412013-02-19 18:32:21 -0800926 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
927 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800928 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Hoonki Lee27511902013-03-14 18:19:06 -0700929 eTDLSSupportMode req_tdls_mode;
Hoonki Leebfee0342013-01-21 16:43:45 -0800930
Hoonki Lee27511902013-03-14 18:19:06 -0700931 if (NULL == pHddTdlsCtx)
932 {
933 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS not enabled!", __func__);
934 return -1;
Chilam Ng01120412013-02-19 18:32:21 -0800935 }
Chilam NG571c65a2013-01-19 12:27:36 +0530936
Hoonki Lee27511902013-03-14 18:19:06 -0700937 if (wlan_hdd_tdls_check_config(config) != 0)
938 {
939 return -1;
940 }
941
942 /* config->tdls is mapped to 0->1, 1->2, 2->3 */
943 req_tdls_mode = config->tdls + 1;
944 if (pHddCtx->tdls_mode == req_tdls_mode)
945 {
946 hddLog(VOS_TRACE_LEVEL_ERROR, "%s already in mode %d", __func__, config->tdls);
947 return -1;
948 }
949
950 /* copy the configuration only when given tdls mode is implicit trigger enable */
951 if (eTDLS_SUPPORT_ENABLED == req_tdls_mode)
952 {
Chilam Ng01120412013-02-19 18:32:21 -0800953 memcpy(&pHddTdlsCtx->threshold_config, config, sizeof(tdls_config_params_t));
954 }
Chilam NG571c65a2013-01-19 12:27:36 +0530955
Chilam Ng01120412013-02-19 18:32:21 -0800956 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
957 "iw set tdls params: %d %d %d %d %d %d %d %d %d %d",
958 config->tdls,
959 config->tx_period_t,
960 config->tx_packet_n,
961 config->discovery_period_t,
962 config->discovery_tries_n,
963 config->idle_timeout_t,
964 config->idle_packet_n,
965 config->rssi_hysteresis,
966 config->rssi_trigger_threshold,
967 config->rssi_teardown_threshold);
Chilam NG571c65a2013-01-19 12:27:36 +0530968
Hoonki Lee27511902013-03-14 18:19:06 -0700969 wlan_hdd_tdls_set_mode(pHddCtx, req_tdls_mode);
Chilam Ng01120412013-02-19 18:32:21 -0800970
Chilam NG571c65a2013-01-19 12:27:36 +0530971 return 0;
972}
973
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800974int wlan_hdd_tdls_set_sta_id(hdd_adapter_t *pAdapter, u8 *mac, u8 staId)
Kiran V1ccee932012-12-12 14:49:46 -0800975{
Hoonki Lee387663d2013-02-05 18:08:43 -0800976 hddTdlsPeer_t *curr_peer;
Kiran V1ccee932012-12-12 14:49:46 -0800977
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800978 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -0800979 if (curr_peer == NULL)
Chilam NG571c65a2013-01-19 12:27:36 +0530980 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530981
Hoonki Lee387663d2013-02-05 18:08:43 -0800982 curr_peer->staId = staId;
Chilam NG571c65a2013-01-19 12:27:36 +0530983
984 return 0;
Kiran V1ccee932012-12-12 14:49:46 -0800985}
986
Hoonki Lee387663d2013-02-05 18:08:43 -0800987/* if peerMac is found, then it returns pointer to hddTdlsPeer_t
988 otherwise, it returns NULL
989*/
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800990hddTdlsPeer_t *wlan_hdd_tdls_find_peer(hdd_adapter_t *pAdapter, u8 *mac)
Kiran V1ccee932012-12-12 14:49:46 -0800991{
Hoonki Lee387663d2013-02-05 18:08:43 -0800992 u8 key;
993 struct list_head *pos;
994 struct list_head *head;
995 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800996 tdlsCtx_t *pHddTdlsCtx;
Hoonki Lee387663d2013-02-05 18:08:43 -0800997
Hoonki Lee387663d2013-02-05 18:08:43 -0800998
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800999 if (mutex_lock_interruptible(&tdls_lock))
Hoonki Lee387663d2013-02-05 18:08:43 -08001000 {
1001 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1002 "%s: unable to lock list", __func__);
1003 return NULL;
1004 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001005 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001006 if (NULL == pHddTdlsCtx)
1007 {
1008 mutex_unlock(&tdls_lock);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001009 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1010 "%s: pHddTdlsCtx is NULL", __func__);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001011 return NULL;
1012 }
1013
1014 key = wlan_hdd_tdls_hash_key(mac);
1015
1016 head = &pHddTdlsCtx->peer_list[key];
Hoonki Lee387663d2013-02-05 18:08:43 -08001017
1018 list_for_each(pos, head) {
1019 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
1020 if (!memcmp(mac, curr_peer->peerMac, 6)) {
1021 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1022 "findTdlsPeer: found staId %d", curr_peer->staId);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001023 mutex_unlock(&tdls_lock);
Hoonki Lee387663d2013-02-05 18:08:43 -08001024 return curr_peer;
1025 }
1026 }
1027
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001028 mutex_unlock(&tdls_lock);
Hoonki Lee387663d2013-02-05 18:08:43 -08001029 return NULL;
1030}
1031
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001032int wlan_hdd_tdls_reset_peer(hdd_adapter_t *pAdapter, u8 *mac)
Hoonki Lee387663d2013-02-05 18:08:43 -08001033{
Chilam Ng01120412013-02-19 18:32:21 -08001034 hdd_context_t *pHddCtx;
Chilam NG571c65a2013-01-19 12:27:36 +05301035 hddTdlsPeer_t *curr_peer;
Kiran V1ccee932012-12-12 14:49:46 -08001036
Chilam Ng01120412013-02-19 18:32:21 -08001037 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1038
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001039 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -08001040 if (curr_peer == NULL)
1041 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +05301042
Gopichand Nakkala901e8922013-03-04 23:45:58 -08001043 curr_peer->link_status = eTDLS_LINK_IDLE;
Hoonki Leecdd8e962013-01-20 00:45:46 -08001044 curr_peer->staId = 0;
Hoonki Lee387663d2013-02-05 18:08:43 -08001045
Chilam Ng01120412013-02-19 18:32:21 -08001046 if(eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) {
Chilam Nga75d8b62013-01-29 01:35:59 -08001047 vos_timer_stop( &curr_peer->peerIdleTimer );
Chilam Nga75d8b62013-01-29 01:35:59 -08001048 }
Hoonki Lee387663d2013-02-05 18:08:43 -08001049 return 0;
Hoonki Leecdd8e962013-01-20 00:45:46 -08001050}
1051
Hoonki Lee27511902013-03-14 18:19:06 -07001052static void wlan_tdd_tdls_reset_tx_rx(tdlsCtx_t *pHddTdlsCtx)
1053{
1054 int i;
1055 struct list_head *head;
1056 hddTdlsPeer_t *tmp;
1057 struct list_head *pos, *q;
1058
1059 if (mutex_lock_interruptible(&tdls_lock))
1060 {
1061 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1062 "%s: unable to lock list", __func__);
1063 return ;
1064 }
1065 if ( NULL == pHddTdlsCtx )
1066 {
1067 mutex_unlock(&tdls_lock);
1068 return ;
1069 }
1070
1071 for (i = 0; i < 256; i++) {
1072 head = &pHddTdlsCtx->peer_list[i];
1073 list_for_each_safe (pos, q, head) {
1074 tmp = list_entry(pos, hddTdlsPeer_t, node);
1075 tmp->tx_pkt = 0;
1076 tmp->rx_pkt = 0;
1077 }
1078 }
1079 mutex_unlock(&tdls_lock);
1080
1081 return ;
1082}
1083
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001084static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001085{
1086 int i;
1087 struct list_head *head;
1088 hddTdlsPeer_t *tmp;
1089 struct list_head *pos, *q;
1090
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001091 if (mutex_lock_interruptible(&tdls_lock))
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001092 {
1093 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1094 "%s: unable to lock list", __func__);
1095 return -1;
1096 }
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001097 if ( NULL == pHddTdlsCtx )
1098 {
1099 mutex_unlock(&tdls_lock);
1100 return -1;
1101 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001102
1103 pHddTdlsCtx->discovery_peer_cnt = 0;
1104
1105 for (i = 0; i < 256; i++) {
1106 head = &pHddTdlsCtx->peer_list[i];
1107 list_for_each_safe (pos, q, head) {
1108 tmp = list_entry(pos, hddTdlsPeer_t, node);
1109 tmp->discovery_processed = 0;
1110 }
1111 }
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001112 mutex_unlock(&tdls_lock);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001113
1114 return 0;
1115}
1116
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001117static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001118{
1119 int i;
1120 struct list_head *head;
1121 struct list_head *pos, *q;
1122 int discovery_peer_cnt=0;
1123 hddTdlsPeer_t *tmp;
1124
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001125 /*
1126 * This function expects the callers to acquire the Mutex.
1127 */
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001128
1129 for (i = 0; i < 256; i++) {
1130 head = &pHddTdlsCtx->peer_list[i];
1131 list_for_each_safe (pos, q, head) {
1132 tmp = list_entry(pos, hddTdlsPeer_t, node);
1133 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -08001134 "%s, %d, " MAC_ADDRESS_STR, __func__, i,
1135 MAC_ADDR_ARRAY(tmp->peerMac));
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001136 discovery_peer_cnt++;
1137 }
1138 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001139 return discovery_peer_cnt;
1140}
1141
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001142tANI_U16 wlan_hdd_tdlsConnectedPeers(hdd_adapter_t *pAdapter)
Lee Hoonkic1262f22013-01-24 21:59:00 -08001143{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001144 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1145
1146 if (NULL == pHddCtx)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001147 return 0;
Lee Hoonkic1262f22013-01-24 21:59:00 -08001148
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001149 return pHddCtx->connected_peer_count;
Lee Hoonkic1262f22013-01-24 21:59:00 -08001150}
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001151
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001152int wlan_hdd_tdls_get_all_peers(hdd_adapter_t *pAdapter, char *buf, int buflen)
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001153{
1154 int i;
1155 int len, init_len;
Hoonki Lee387663d2013-02-05 18:08:43 -08001156 struct list_head *head;
1157 struct list_head *pos;
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001158 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001159 tdlsCtx_t *pHddTdlsCtx;
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001160
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001161
1162 init_len = buflen;
1163 len = snprintf(buf, buflen, "\n%-18s%-3s%-4s%-3s%-5s\n", "MAC", "Id", "cap", "up", "RSSI");
1164 buf += len;
1165 buflen -= len;
1166 /* 1234567890123456789012345678901234567 */
1167 len = snprintf(buf, buflen, "---------------------------------\n");
1168 buf += len;
1169 buflen -= len;
1170
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001171 if (mutex_lock_interruptible(&tdls_lock))
Gopichand Nakkala91b09262013-02-10 14:27:02 -08001172 {
1173 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1174 "%s: unable to lock list", __func__);
1175 return init_len-buflen;
1176 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001177 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001178 if (NULL == pHddTdlsCtx) {
1179 mutex_unlock(&tdls_lock);
1180 len = snprintf(buf, buflen, "TDLS not enabled\n");
1181 return len;
1182 }
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001183 for (i = 0; i < 256; i++) {
Hoonki Lee387663d2013-02-05 18:08:43 -08001184 head = &pHddTdlsCtx->peer_list[i];
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001185
Hoonki Lee387663d2013-02-05 18:08:43 -08001186 list_for_each(pos, head) {
1187 curr_peer= list_entry (pos, hddTdlsPeer_t, node);
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001188
Hoonki Lee387663d2013-02-05 18:08:43 -08001189 if (buflen < 32+1)
1190 break;
1191 len = snprintf(buf, buflen,
Chilam Ng01120412013-02-19 18:32:21 -08001192 MAC_ADDRESS_STR"%3d%4s%3s%5d\n",
1193 MAC_ADDR_ARRAY(curr_peer->peerMac),
Hoonki Lee387663d2013-02-05 18:08:43 -08001194 curr_peer->staId,
1195 (curr_peer->tdls_support == eTDLS_CAP_SUPPORTED) ? "Y":"N",
1196 (curr_peer->link_status == eTDLS_LINK_CONNECTED) ? "Y":"N",
1197 curr_peer->rssi);
1198 buf += len;
1199 buflen -= len;
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001200 }
1201 }
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001202 mutex_unlock(&tdls_lock);
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001203 return init_len-buflen;
1204}
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001205
1206void wlan_hdd_tdls_connection_callback(hdd_adapter_t *pAdapter)
1207{
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001208 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001209 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001210
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001211 if (NULL == pHddTdlsCtx) return;
1212
1213 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1214 "%s, update %d discover %d", __func__,
1215 pHddTdlsCtx->threshold_config.tx_period_t,
1216 pHddTdlsCtx->threshold_config.discovery_period_t);
1217
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001218 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode)
1219 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001220 wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001221
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001222 vos_timer_start(&pHddTdlsCtx->peerDiscoverTimer,
1223 pHddTdlsCtx->threshold_config.discovery_period_t);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001224
1225
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001226 vos_timer_start(&pHddTdlsCtx->peerUpdateTimer,
1227 pHddTdlsCtx->threshold_config.tx_period_t);
1228 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001229
1230}
1231
1232void wlan_hdd_tdls_disconnection_callback(hdd_adapter_t *pAdapter)
1233{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001234 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001235
1236 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s", __func__);
1237
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001238 if (mutex_lock_interruptible(&tdls_lock))
1239 {
1240 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1241 "%s: unable to lock list", __func__);
1242 return;
1243 }
1244 if (NULL == pHddTdlsCtx)
1245 {
1246 mutex_unlock(&tdls_lock);
1247 return;
1248 }
1249
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001250 wlan_hdd_tdls_timers_stop(pHddTdlsCtx);
1251 wlan_hdd_tdls_free_list(pHddTdlsCtx);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001252
1253 mutex_unlock(&tdls_lock);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001254}
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001255
1256void wlan_hdd_tdls_mgmt_completion_callback(hdd_adapter_t *pAdapter, tANI_U32 statusCode)
1257{
1258 pAdapter->mgmtTxCompletionStatus = statusCode;
1259 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s: Mgmt TX Completion %d",
1260 __func__, statusCode);
1261 complete(&pAdapter->tdls_mgmt_comp);
1262}
1263
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001264void wlan_hdd_tdls_increment_peer_count(hdd_adapter_t *pAdapter)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001265{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001266 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001267
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001268 if (NULL == pHddCtx) return;
1269
1270 pHddCtx->connected_peer_count++;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001271}
1272
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001273void wlan_hdd_tdls_decrement_peer_count(hdd_adapter_t *pAdapter)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001274{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001275 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001276
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001277 if (NULL == pHddCtx) return;
1278
1279 if (pHddCtx->connected_peer_count)
1280 pHddCtx->connected_peer_count--;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001281}
1282
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001283void wlan_hdd_tdls_check_bmps(hdd_adapter_t *pAdapter)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001284{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001285 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001286
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001287 if (NULL == pHddCtx) return;
1288
1289 if (0 == pHddCtx->connected_peer_count)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001290 {
1291 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"No TDLS peer connected so Enable BMPS");
1292 hdd_enable_bmps_imps(pHddCtx);
1293 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001294 else if (1 == pHddCtx->connected_peer_count)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001295 {
1296 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"TDLS peer connected so Disable BMPS");
1297 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
1298 }
1299 return;
1300}
1301
1302/* return TRUE if TDLS is ongoing
1303 * mac - if NULL check for all the peer list, otherwise, skip this mac when skip_self is TRUE
1304 * skip_self - if TRUE, skip this mac. otherwise, check all the peer list. if
1305 mac is NULL, this argument is ignored, and check for all the peer list.
1306 */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001307u8 wlan_hdd_tdls_is_progress(hdd_adapter_t *pAdapter, u8 *mac, u8 skip_self)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001308{
1309 int i;
1310 struct list_head *head;
1311 hddTdlsPeer_t *curr_peer;
1312 struct list_head *pos;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001313 tdlsCtx_t *pHddTdlsCtx;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001314
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001315 if (mutex_lock_interruptible(&tdls_lock))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001316 {
1317 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1318 "%s: unable to lock list", __func__);
1319 return FALSE;
1320 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001321 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001322 if (NULL == pHddTdlsCtx)
1323 {
1324 mutex_unlock(&tdls_lock);
1325 return FALSE;
1326 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001327
1328 for (i = 0; i < 256; i++) {
1329 head = &pHddTdlsCtx->peer_list[i];
1330 list_for_each(pos, head) {
1331 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
1332 if (skip_self && mac && !memcmp(mac, curr_peer->peerMac, 6)) {
1333 continue;
1334 }
1335 else
1336 {
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08001337 if (eTDLS_LINK_CONNECTING == curr_peer->link_status)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001338 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07001339 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1340 "%s:" MAC_ADDRESS_STR "is in eTDLS_LINK_CONNECTING",
1341 __func__, MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001342 mutex_unlock(&tdls_lock);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001343 return TRUE;
1344 }
1345 }
1346 }
1347 }
1348
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001349 mutex_unlock(&tdls_lock);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001350 return FALSE;
1351}
Hoonki Lee27511902013-03-14 18:19:06 -07001352
1353static void wlan_hdd_tdls_implicit_disable(tdlsCtx_t *pHddTdlsCtx)
1354{
1355 if (mutex_lock_interruptible(&tdls_lock))
1356 {
1357 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1358 "%s: unable to lock list", __func__);
1359 return;
1360 }
1361
1362 wlan_hdd_tdls_timers_stop(pHddTdlsCtx);
1363
1364 mutex_unlock(&tdls_lock);
1365}
1366
1367static void wlan_hdd_tdls_implicit_enable(tdlsCtx_t *pHddTdlsCtx)
1368{
1369 wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx);
1370 wlan_tdd_tdls_reset_tx_rx(pHddTdlsCtx);
1371
1372 vos_timer_start(&pHddTdlsCtx->peerDiscoverTimer,
1373 pHddTdlsCtx->threshold_config.discovery_period_t);
1374
1375 vos_timer_start(&pHddTdlsCtx->peerUpdateTimer,
1376 pHddTdlsCtx->threshold_config.tx_period_t);
1377}
1378
1379void wlan_hdd_tdls_set_mode(hdd_context_t *pHddCtx, eTDLSSupportMode tdls_mode)
1380{
1381 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1382 VOS_STATUS status;
1383 hdd_adapter_t *pAdapter;
1384 tdlsCtx_t *pHddTdlsCtx;
1385
1386 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s mode %d", __func__, (int)tdls_mode);
1387
1388 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1389
1390 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1391 {
1392 pAdapter = pAdapterNode->pAdapter;
1393 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
1394 if (NULL != pHddTdlsCtx)
1395 {
1396 if(eTDLS_SUPPORT_ENABLED == tdls_mode)
1397 wlan_hdd_tdls_implicit_enable(pHddTdlsCtx);
1398 else if((eTDLS_SUPPORT_DISABLED == tdls_mode) ||
1399 (eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode))
1400 wlan_hdd_tdls_implicit_disable(pHddTdlsCtx);
1401 }
1402 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1403 pAdapterNode = pNext;
1404 }
1405 pHddCtx->tdls_mode_last = pHddCtx->tdls_mode;
1406 pHddCtx->tdls_mode = tdls_mode;
1407}