blob: 8b427382fa86fee73005f0b8703ce0f93023485f [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
Chilam Nga75d8b62013-01-29 01:35:59 -080042static tdlsCtx_t *pHddTdlsCtx;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080043static struct mutex tdls_lock;
Gopichand Nakkalac3694582013-02-13 20:51:22 -080044static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(void);
45static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(void);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080046static void wlan_hdd_tdls_timers_destroy(void);
Chilam NG571c65a2013-01-19 12:27:36 +053047
Hoonki Lee5a4b2172013-01-29 01:45:53 -080048#ifndef WLAN_FEATURE_TDLS_DEBUG
49#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
50#else
51#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_WARN
52#endif
53
Hoonki Lee387663d2013-02-05 18:08:43 -080054static u8 wlan_hdd_tdls_hash_key (u8 *mac)
Hoonki Leef63df0d2013-01-16 19:29:14 -080055{
56 int i;
Hoonki Lee387663d2013-02-05 18:08:43 -080057 u8 key = 0;
58
59 for (i = 0; i < 6; i++)
60 key ^= mac[i];
61
62 return key;
63}
64
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080065static v_VOID_t wlan_hdd_tdls_start_peer_discover_timer(tANI_BOOLEAN mutexLock, v_U32_t discoveryExpiry)
66{
67 hdd_adapter_t *pAdapter;
68 hdd_context_t *pHddCtx;
69 hdd_station_ctx_t *pHddStaCtx;
70
71
72 if ( mutexLock )
73 {
74 if (mutex_lock_interruptible(&tdls_lock))
75 {
76 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
77 "%s: unable to lock list: %d", __func__, __LINE__);
78 return;
79 }
80 }
81 if (NULL == pHddTdlsCtx)
82 {
83 if ( mutexLock )
84 mutex_unlock(&tdls_lock);
85 return;
86 }
87
88 pAdapter = WLAN_HDD_GET_PRIV_PTR(pHddTdlsCtx->dev);
89
90 if (NULL == pAdapter)
91 {
92 if ( mutexLock )
93 mutex_unlock(&tdls_lock);
94 return;
95 }
96
97 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
98 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
99 if (hdd_connIsConnected( pHddStaCtx ))
100 {
101 vos_timer_start(&pHddTdlsCtx->peerDiscoverTimer, discoveryExpiry);
102 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "beacon rssi: %d",
103 pHddTdlsCtx->ap_rssi);
104 }
105 if ( mutexLock )
106 mutex_unlock(&tdls_lock);
107
108 return;
109}
110
Hoonki Lee387663d2013-02-05 18:08:43 -0800111static v_VOID_t wlan_hdd_tdls_discover_peer_cb( v_PVOID_t userData )
112{
113 int i;
114 struct list_head *head;
115 struct list_head *pos;
Chilam NG571c65a2013-01-19 12:27:36 +0530116 hddTdlsPeer_t *curr_peer;
Hoonki Leebfee0342013-01-21 16:43:45 -0800117 hdd_adapter_t *pAdapter;
118 hdd_context_t *pHddCtx;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800119 hdd_station_ctx_t *pHddStaCtx;
120 int discover_req_sent = 0;
121 v_U32_t discover_expiry = TDLS_SUB_DISCOVERY_PERIOD;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800122 tANI_BOOLEAN doMutexLock = eANI_BOOLEAN_TRUE;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800123
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800124 if (mutex_lock_interruptible(&tdls_lock))
125 {
126 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
127 "%s: unable to lock list : %d", __func__, __LINE__);
128 return;
129 }
Hoonki Leebfee0342013-01-21 16:43:45 -0800130
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800131 if (NULL == pHddTdlsCtx)
132 {
133 mutex_unlock(&tdls_lock);
134 return;
135 }
Hoonki Leebfee0342013-01-21 16:43:45 -0800136
137 pAdapter = WLAN_HDD_GET_PRIV_PTR(pHddTdlsCtx->dev);
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800138
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800139 if (NULL == pAdapter)
140 {
141 mutex_unlock(&tdls_lock);
142 return;
143 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800144
145 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Hoonki Leebfee0342013-01-21 16:43:45 -0800146 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Hoonki Leef63df0d2013-01-16 19:29:14 -0800147
Hoonki Lee387663d2013-02-05 18:08:43 -0800148 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: ", __func__);
149
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800150 if (0 == pHddTdlsCtx->discovery_peer_cnt)
151 pHddTdlsCtx->discovery_peer_cnt = wlan_hdd_get_tdls_discovery_peer_cnt();
152
Chilam NG571c65a2013-01-19 12:27:36 +0530153 for (i = 0; i < 256; i++) {
Hoonki Lee387663d2013-02-05 18:08:43 -0800154 head = &pHddTdlsCtx->peer_list[i];
Chilam NG571c65a2013-01-19 12:27:36 +0530155
Hoonki Lee387663d2013-02-05 18:08:43 -0800156 list_for_each (pos, head) {
157 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
Chilam NG571c65a2013-01-19 12:27:36 +0530158
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -0800159 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800160 "%d " MAC_ADDRESS_STR " %d %d, %d %d %d %d", i,
161 MAC_ADDR_ARRAY(curr_peer->peerMac),
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800162 curr_peer->discovery_processed,
163 discover_req_sent,
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -0800164 curr_peer->tdls_support,
165 curr_peer->link_status,
166 curr_peer->discovery_attempt,
167 pHddTdlsCtx->threshold_config.discovery_tries_n);
Hoonki Lee387663d2013-02-05 18:08:43 -0800168
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800169 if (discover_req_sent < TDLS_MAX_DISCOVER_REQS_PER_TIMER) {
170 if (!curr_peer->discovery_processed) {
Chilam NG571c65a2013-01-19 12:27:36 +0530171
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800172 curr_peer->discovery_processed = 1;
173 discover_req_sent++;
174 pHddTdlsCtx->discovery_peer_cnt--;
175
176 if ((eTDLS_CAP_UNKNOWN == curr_peer->tdls_support) &&
Gopichand Nakkalab88f6772013-02-27 18:12:56 -0800177 (eTDLS_LINK_NOT_CONNECTED == curr_peer->link_status) &&
178 (curr_peer->tx_pkt >=
179 pHddTdlsCtx->threshold_config.tx_packet_n)) {
Gopichand Nakkala273d5a02013-02-19 15:15:09 -0800180
181 if (curr_peer->discovery_attempt <
182 pHddTdlsCtx->threshold_config.discovery_tries_n) {
183
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800184 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala273d5a02013-02-19 15:15:09 -0800185 "sme_SendTdlsMgmtFrame(%d)", pAdapter->sessionId);
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800186
187 sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter),
188 pAdapter->sessionId,
189 curr_peer->peerMac,
190 WLAN_TDLS_DISCOVERY_REQUEST,
191 1, 0, NULL, 0, 0);
Gopichand Nakkala273d5a02013-02-19 15:15:09 -0800192 curr_peer->discovery_attempt++;
193 }
194 else
195 {
196 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
197 "%s: Maximum Discovery retries reached", __func__);
198 curr_peer->tdls_support = eTDLS_CAP_NOT_SUPPORTED;
199 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800200
201 }
202 }
Chilam NG571c65a2013-01-19 12:27:36 +0530203 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800204 else
205 goto exit_loop;
Hoonki Lee387663d2013-02-05 18:08:43 -0800206 }
Hoonki Leef63df0d2013-01-16 19:29:14 -0800207 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800208exit_loop:
Hoonki Leef63df0d2013-01-16 19:29:14 -0800209
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800210 if (0 != pHddTdlsCtx->discovery_peer_cnt) {
211 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
212 "discovery_peer_cnt is %d , Starting SUB_DISCOVERY_TIMER",
213 pHddTdlsCtx->discovery_peer_cnt);
214 discover_expiry = TDLS_SUB_DISCOVERY_PERIOD;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800215 doMutexLock = eANI_BOOLEAN_FALSE;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800216 goto done;
217 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800218 discover_expiry = pHddTdlsCtx->threshold_config.discovery_period_t;
219
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800220 mutex_unlock(&tdls_lock);
221
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800222 wlan_hdd_tdls_peer_reset_discovery_processed();
Chilam NG571c65a2013-01-19 12:27:36 +0530223
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800224 /* Commenting out the following function as it was introducing
225 * a race condition when pHddTdlsCtx is deleted. Also , this
226 * function is consuming more time in the timer callback.
227 * RSSI based trigger needs to revisit this part of the code.
228 */
229
230 /*
231 * wlan_hdd_get_rssi(pAdapter, &pHddTdlsCtx->ap_rssi);
232 */
Chilam NG571c65a2013-01-19 12:27:36 +0530233
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800234done:
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800235 wlan_hdd_tdls_start_peer_discover_timer(doMutexLock, discover_expiry);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800236
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800237 if ( !doMutexLock )
238 mutex_unlock(&tdls_lock);
239 return;
Hoonki Leef63df0d2013-01-16 19:29:14 -0800240}
Chilam NG571c65a2013-01-19 12:27:36 +0530241
Hoonki Lee387663d2013-02-05 18:08:43 -0800242static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData )
Chilam NG571c65a2013-01-19 12:27:36 +0530243{
244 int i;
Hoonki Lee387663d2013-02-05 18:08:43 -0800245 struct list_head *head;
246 struct list_head *pos;
Chilam NG571c65a2013-01-19 12:27:36 +0530247 hddTdlsPeer_t *curr_peer;
248
Hoonki Leebfee0342013-01-21 16:43:45 -0800249
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800250 if (mutex_lock_interruptible(&tdls_lock))
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800251 {
252 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
253 "%s: unable to lock list", __func__);
254 return;
255 }
256
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800257 if (NULL == pHddTdlsCtx)
258 {
259 mutex_unlock(&tdls_lock);
260 return;
261 }
262
Chilam NG571c65a2013-01-19 12:27:36 +0530263 for (i = 0; i < 256; i++) {
Hoonki Lee387663d2013-02-05 18:08:43 -0800264 head = &pHddTdlsCtx->peer_list[i];
Chilam NG571c65a2013-01-19 12:27:36 +0530265
Hoonki Lee387663d2013-02-05 18:08:43 -0800266 list_for_each (pos, head) {
267 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
Chilam NG571c65a2013-01-19 12:27:36 +0530268
Hoonki Lee387663d2013-02-05 18:08:43 -0800269 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Chilam Ng01120412013-02-19 18:32:21 -0800270 "hdd update cb - %d: " MAC_ADDRESS_STR " -> %d\n", i,
271 MAC_ADDR_ARRAY(curr_peer->peerMac),
Hoonki Lee387663d2013-02-05 18:08:43 -0800272 curr_peer->tx_pkt);
273
Chilam NG571c65a2013-01-19 12:27:36 +0530274 if (eTDLS_CAP_SUPPORTED == curr_peer->tdls_support) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800275 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800276 "%s: (tx %d, rx %d, config %d) " MAC_ADDRESS_STR " (%d) ",
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800277 __func__, curr_peer->tx_pkt, curr_peer->rx_pkt,
278 pHddTdlsCtx->threshold_config.tx_packet_n,
Chilam Ng01120412013-02-19 18:32:21 -0800279 MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->link_status);
280
Chilam NG571c65a2013-01-19 12:27:36 +0530281 if (eTDLS_LINK_CONNECTED != curr_peer->link_status) {
282 if (curr_peer->tx_pkt >=
283 pHddTdlsCtx->threshold_config.tx_packet_n) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800284
Gopichand Nakkala9f7592a2013-02-27 12:41:50 -0800285 if (HDD_MAX_NUM_TDLS_STA > wlan_hdd_tdlsConnectedPeers() &&
286 (FALSE == curr_peer->isTDLSInProgress))
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800287 {
288
289 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "-> Tput trigger TDLS SETUP");
Chilam NG571c65a2013-01-19 12:27:36 +0530290#ifdef CONFIG_TDLS_IMPLICIT
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800291 cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
292 curr_peer->peerMac,
293 NL80211_TDLS_SETUP, FALSE,
294 GFP_KERNEL);
Chilam NG571c65a2013-01-19 12:27:36 +0530295#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800296 }
297 else
298 {
299 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalab88f6772013-02-27 18:12:56 -0800300 "%s: Skip Tput trigger due to isTDLSInProgress %u or connected_peer_count %d",
301 __func__, curr_peer->isTDLSInProgress, wlan_hdd_tdlsConnectedPeers() );
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800302 }
Hoonki Leecdd8e962013-01-20 00:45:46 -0800303 goto next_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530304 }
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800305#ifdef WLAN_FEATURE_TDLS_DEBUG
306 else {
307 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "-> ignored.");
308 }
309#endif
Gopichand Nakkala9f7592a2013-02-27 12:41:50 -0800310 if ((((tANI_S32)curr_peer->rssi >
Hoonki Leecdd8e962013-01-20 00:45:46 -0800311 (tANI_S32)(pHddTdlsCtx->threshold_config.rssi_hysteresis +
Gopichand Nakkala9f7592a2013-02-27 12:41:50 -0800312 pHddTdlsCtx->ap_rssi)) ||
313 ((tANI_S32)(curr_peer->rssi >
314 pHddTdlsCtx->threshold_config.rssi_trigger_threshold))) &&
315 (HDD_MAX_NUM_TDLS_STA > wlan_hdd_tdlsConnectedPeers())
316 && (FALSE == curr_peer->isTDLSInProgress)) {
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
327 cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
328 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
342 cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
343 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) {
388 hdd_adapter_t *pAdapter;
Chilam Ng01120412013-02-19 18:32:21 -0800389
390 pAdapter = WLAN_HDD_GET_PRIV_PTR(pHddTdlsCtx->dev);
Chilam Ng01120412013-02-19 18:32:21 -0800391
392 if (++curr_peer->discovery_attempt <
393 pHddTdlsCtx->threshold_config.discovery_tries_n) {
394 curr_peer->tdls_support = eTDLS_CAP_NOT_SUPPORTED;
Gopichand Nakkalab88f6772013-02-27 18:12:56 -0800395 sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter),
396 pAdapter->sessionId,
397 curr_peer->peerMac,
398 WLAN_TDLS_DISCOVERY_REQUEST,
399 1, 0, NULL, 0, 0);
Chilam Ng01120412013-02-19 18:32:21 -0800400 }
401
402 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
403 "Tput triggering TDLS discovery: " MAC_ADDRESS_STR "!",
404 MAC_ADDR_ARRAY(curr_peer->peerMac));
405 }
406 }
Chilam NG571c65a2013-01-19 12:27:36 +0530407 }
408
Hoonki Leecdd8e962013-01-20 00:45:46 -0800409next_peer:
Chilam NG571c65a2013-01-19 12:27:36 +0530410 curr_peer->tx_pkt = 0;
Chilam Ng1279e232013-01-25 15:06:52 -0800411 curr_peer->rx_pkt = 0;
Hoonki Lee387663d2013-02-05 18:08:43 -0800412 }
Chilam NG571c65a2013-01-19 12:27:36 +0530413 }
414
415 vos_timer_start( &pHddTdlsCtx->peerUpdateTimer,
416 pHddTdlsCtx->threshold_config.tx_period_t );
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800417 mutex_unlock(&tdls_lock);
Chilam NG571c65a2013-01-19 12:27:36 +0530418}
419
Chilam Ng1279e232013-01-25 15:06:52 -0800420static v_VOID_t wlan_hdd_tdls_idle_cb( v_PVOID_t userData )
421{
Lee Hoonkic1262f22013-01-24 21:59:00 -0800422#ifdef CONFIG_TDLS_IMPLICIT
Chilam Ng1279e232013-01-25 15:06:52 -0800423 hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData;
424
Chilam Ng1279e232013-01-25 15:06:52 -0800425
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800426 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800427 "%s: Tx/Rx Idle " MAC_ADDRESS_STR " trigger teardown",
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800428 __func__,
Chilam Ng01120412013-02-19 18:32:21 -0800429 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800430 if (mutex_lock_interruptible(&tdls_lock))
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800431 {
432 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
433 "%s: unable to lock list", __func__);
434 return;
435 }
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800436
Chilam Ng1279e232013-01-25 15:06:52 -0800437 cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
438 curr_peer->peerMac,
Hoonki Leea34dd892013-02-05 22:56:02 -0800439 NL80211_TDLS_TEARDOWN,
440 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON,
Chilam Ng1279e232013-01-25 15:06:52 -0800441 GFP_KERNEL);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800442 mutex_unlock(&tdls_lock);
Chilam Ng1279e232013-01-25 15:06:52 -0800443#endif
444}
445
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800446static void wlan_hdd_tdls_free_list(void)
447{
448 int i;
449 struct list_head *head;
450 hddTdlsPeer_t *tmp;
451 struct list_head *pos, *q;
452
453 if (NULL == pHddTdlsCtx) return;
454
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800455
456 for (i = 0; i < 256; i++) {
457 head = &pHddTdlsCtx->peer_list[i];
458 list_for_each_safe (pos, q, head) {
459 tmp = list_entry(pos, hddTdlsPeer_t, node);
460 list_del(pos);
461 vos_mem_free(tmp);
462 }
463 }
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800464}
465
Chilam Ng01120412013-02-19 18:32:21 -0800466static int wlan_hdd_tdls_core_init(struct net_device *dev, tdls_config_params_t *config)
467{
468 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
469 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
470 int i;
471
472 if (NULL == pHddTdlsCtx) {
473 pHddTdlsCtx = vos_mem_malloc(sizeof(tdlsCtx_t));
474
475 if (NULL == pHddTdlsCtx) {
476 hddLog(VOS_TRACE_LEVEL_ERROR, "%s malloc failed!", __func__);
477 return -1;
478 }
479
480 vos_mem_zero(pHddTdlsCtx, sizeof(tdlsCtx_t));
481
482 if (NULL == config) {
483 if (eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY != pHddCtx->tdls_mode) {
484 pHddTdlsCtx->threshold_config.tx_period_t =
485 pHddCtx->cfg_ini->fTDLSTxStatsPeriod;
486 pHddTdlsCtx->threshold_config.tx_packet_n =
487 pHddCtx->cfg_ini->fTDLSTxPacketThreshold;
488 pHddTdlsCtx->threshold_config.discovery_period_t =
489 pHddCtx->cfg_ini->fTDLSDiscoveryPeriod;
490 pHddTdlsCtx->threshold_config.discovery_tries_n =
491 pHddCtx->cfg_ini->fTDLSMaxDiscoveryAttempt;
492 pHddTdlsCtx->threshold_config.idle_timeout_t =
493 pHddCtx->cfg_ini->fTDLSIdleTimeout;
494 pHddTdlsCtx->threshold_config.idle_packet_n =
495 pHddCtx->cfg_ini->fTDLSIdlePacketThreshold;
496 pHddTdlsCtx->threshold_config.rssi_hysteresis =
497 pHddCtx->cfg_ini->fTDLSRSSIHysteresis;
498 pHddTdlsCtx->threshold_config.rssi_trigger_threshold =
499 pHddCtx->cfg_ini->fTDLSRSSITriggerThreshold;
500 pHddTdlsCtx->threshold_config.rssi_teardown_threshold =
501 pHddCtx->cfg_ini->fTDLSRSSITeardownThreshold;
502 }
503 } else {
504 memcpy(&pHddTdlsCtx->threshold_config, config,
505 sizeof(tdls_config_params_t));
506 }
507
Chilam Ng01120412013-02-19 18:32:21 -0800508 for (i = 0; i < 256; i++)
509 {
510 INIT_LIST_HEAD(&pHddTdlsCtx->peer_list[i]);
511 }
512
513 pHddTdlsCtx->dev = dev;
514 }
515
516 vos_timer_init(&pHddTdlsCtx->peerDiscoverTimer,
517 VOS_TIMER_TYPE_SW,
518 wlan_hdd_tdls_discover_peer_cb,
519 pHddTdlsCtx);
520
521 vos_timer_init(&pHddTdlsCtx->peerUpdateTimer,
522 VOS_TIMER_TYPE_SW,
523 wlan_hdd_tdls_update_peer_cb,
524 pHddTdlsCtx);
525
526 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) {
527 vos_timer_start( &pHddTdlsCtx->peerDiscoverTimer,
528 pHddTdlsCtx->threshold_config.discovery_period_t );
529
530 vos_timer_start( &pHddTdlsCtx->peerUpdateTimer,
531 pHddTdlsCtx->threshold_config.tx_period_t );
532 }
533
534 return 0;
535}
536
Chilam NG571c65a2013-01-19 12:27:36 +0530537int wlan_hdd_tdls_init(struct net_device *dev)
538{
Hoonki Leebf870f32013-01-19 15:53:30 +0530539 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
540 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Chilam NG571c65a2013-01-19 12:27:36 +0530541
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -0800542 mutex_init(&tdls_lock);
543
Hoonki Lee387663d2013-02-05 18:08:43 -0800544 if (FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport)
Hoonki Leebf870f32013-01-19 15:53:30 +0530545 {
Chilam Ng01120412013-02-19 18:32:21 -0800546 pHddCtx->tdls_mode = eTDLS_SUPPORT_DISABLED;
Hoonki Leebf870f32013-01-19 15:53:30 +0530547 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS not enabled!", __func__);
Hoonki Lee387663d2013-02-05 18:08:43 -0800548 return 0;
Hoonki Leebf870f32013-01-19 15:53:30 +0530549 }
550
Chilam Ng01120412013-02-19 18:32:21 -0800551 pHddCtx->tdls_mode = eTDLS_SUPPORT_ENABLED;
Chilam NG571c65a2013-01-19 12:27:36 +0530552
Chilam Ng01120412013-02-19 18:32:21 -0800553 if (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger)
Hoonki Lee387663d2013-02-05 18:08:43 -0800554 {
Chilam Ng01120412013-02-19 18:32:21 -0800555 pHddCtx->tdls_mode = eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY;
Hoonki Leebf870f32013-01-19 15:53:30 +0530556 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS Implicit trigger not enabled!", __func__);
Hoonki Leebf870f32013-01-19 15:53:30 +0530557 }
Chilam NG571c65a2013-01-19 12:27:36 +0530558
Chilam Ng01120412013-02-19 18:32:21 -0800559 return wlan_hdd_tdls_core_init(dev, NULL);
Chilam NG571c65a2013-01-19 12:27:36 +0530560}
561
562void wlan_hdd_tdls_exit()
563{
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800564 if (mutex_lock_interruptible(&tdls_lock))
565 {
566 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
567 "%s: unable to lock list", __func__);
568 return;
569 }
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800570 if (NULL == pHddTdlsCtx)
571 {
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800572 mutex_unlock(&tdls_lock);
Hoonki Leebfee0342013-01-21 16:43:45 -0800573 hddLog(VOS_TRACE_LEVEL_WARN, "%s TDLS not enabled, exiting!", __func__);
574 return;
575 }
576
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800577 /* must stop timer here before freeing peer list, because peerIdleTimer is
578 part of peer list structure. */
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800579 wlan_hdd_tdls_timers_destroy();
Hoonki Lee387663d2013-02-05 18:08:43 -0800580 wlan_hdd_tdls_free_list();
Chilam Nga75d8b62013-01-29 01:35:59 -0800581
582 vos_mem_free(pHddTdlsCtx);
583 pHddTdlsCtx = NULL;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800584 mutex_unlock(&tdls_lock);
Chilam NG571c65a2013-01-19 12:27:36 +0530585}
586
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800587/* stop all the tdls timers running */
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800588static void wlan_hdd_tdls_timers_stop(void)
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800589{
590 int i;
591 struct list_head *head;
592 struct list_head *pos;
593 hddTdlsPeer_t *curr_peer;
594
595 vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer);
596 vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer);
597
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800598
599 for (i = 0; i < 256; i++)
600 {
601 head = &pHddTdlsCtx->peer_list[i];
602
603 list_for_each (pos, head) {
604 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
605
606 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800607 "%s: " MAC_ADDRESS_STR " -> stop idle timer",
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800608 __func__,
Chilam Ng01120412013-02-19 18:32:21 -0800609 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800610 vos_timer_stop ( &curr_peer->peerIdleTimer );
611 }
612 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800613}
614
615/* destroy all the tdls timers running */
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800616static void wlan_hdd_tdls_timers_destroy(void)
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800617{
618 int i;
619 struct list_head *head;
620 struct list_head *pos;
621 hddTdlsPeer_t *curr_peer;
622
623 vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer);
624 vos_timer_destroy(&pHddTdlsCtx->peerDiscoverTimer);
625 vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer);
626 vos_timer_destroy(&pHddTdlsCtx->peerUpdateTimer);
627
628 for (i = 0; i < 256; i++)
629 {
630 head = &pHddTdlsCtx->peer_list[i];
631
632 list_for_each (pos, head) {
633 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
634
635 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800636 "%s: " MAC_ADDRESS_STR " -> destroy idle timer",
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800637 __func__,
Chilam Ng01120412013-02-19 18:32:21 -0800638 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800639 vos_timer_stop ( &curr_peer->peerIdleTimer );
640 vos_timer_destroy ( &curr_peer->peerIdleTimer );
641 }
642 }
643}
644
Hoonki Lee387663d2013-02-05 18:08:43 -0800645/* if mac address exist, return pointer
646 if mac address doesn't exist, create a list and add, return pointer
647 return NULL if fails to get new mac address
648*/
649hddTdlsPeer_t *wlan_hdd_tdls_get_peer(u8 *mac)
Chilam NG571c65a2013-01-19 12:27:36 +0530650{
Hoonki Lee387663d2013-02-05 18:08:43 -0800651 struct list_head *head;
652 hddTdlsPeer_t *peer;
653 u8 key;
Chilam NG571c65a2013-01-19 12:27:36 +0530654
Hoonki Lee387663d2013-02-05 18:08:43 -0800655 if (NULL == pHddTdlsCtx)
656 return NULL;
Hoonki Leebfee0342013-01-21 16:43:45 -0800657
Hoonki Lee387663d2013-02-05 18:08:43 -0800658 /* if already there, just update */
659 peer = wlan_hdd_tdls_find_peer(mac);
660 if (peer != NULL)
661 {
662 return peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530663 }
664
Hoonki Lee387663d2013-02-05 18:08:43 -0800665 /* not found, allocate and add the list */
666 peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
667 if (NULL == peer) {
668 hddLog(VOS_TRACE_LEVEL_ERROR, "%s peer malloc failed!", __func__);
669 return NULL;
670 }
Chilam NG571c65a2013-01-19 12:27:36 +0530671
Hoonki Lee387663d2013-02-05 18:08:43 -0800672 key = wlan_hdd_tdls_hash_key(mac);
673 head = &pHddTdlsCtx->peer_list[key];
Chilam NG571c65a2013-01-19 12:27:36 +0530674
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800675 if (mutex_lock_interruptible(&tdls_lock))
Hoonki Lee387663d2013-02-05 18:08:43 -0800676 {
677 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
678 "%s: unable to lock list", __func__);
679 return NULL;
680 }
Chilam NG571c65a2013-01-19 12:27:36 +0530681
Hoonki Lee387663d2013-02-05 18:08:43 -0800682 vos_mem_zero(peer, sizeof(hddTdlsPeer_t));
683 vos_mem_copy(peer->peerMac, mac, sizeof(peer->peerMac));
684
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800685 vos_timer_init(&peer->peerIdleTimer,
686 VOS_TIMER_TYPE_SW,
687 wlan_hdd_tdls_idle_cb,
688 peer);
689
Hoonki Lee387663d2013-02-05 18:08:43 -0800690 list_add_tail(&peer->node, head);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800691 mutex_unlock(&tdls_lock);
Hoonki Lee387663d2013-02-05 18:08:43 -0800692
693 return peer;
694}
695
696void wlan_hdd_tdls_set_link_status(hddTdlsPeer_t *curr_peer, int status)
697{
698 if (curr_peer == NULL)
699 return;
700
Chilam Ng01120412013-02-19 18:32:21 -0800701 hddLog(VOS_TRACE_LEVEL_WARN, "tdls set peer " MAC_ADDRESS_STR " link status to %d",
702 MAC_ADDR_ARRAY(curr_peer->peerMac), status);
Chilam NG571c65a2013-01-19 12:27:36 +0530703
704 curr_peer->link_status = status;
705
Chilam NG571c65a2013-01-19 12:27:36 +0530706}
707
708int wlan_hdd_tdls_set_cap(u8 *mac, int cap)
709{
710 hddTdlsPeer_t *curr_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530711
Hoonki Leebfee0342013-01-21 16:43:45 -0800712 if (NULL == pHddTdlsCtx) return -1;
713
Hoonki Lee387663d2013-02-05 18:08:43 -0800714 curr_peer = wlan_hdd_tdls_get_peer(mac);
715 if (curr_peer == NULL)
716 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530717
718 curr_peer->tdls_support = cap;
719
Hoonki Lee387663d2013-02-05 18:08:43 -0800720 return 0;
Chilam NG571c65a2013-01-19 12:27:36 +0530721}
722
723int wlan_hdd_tdls_set_rssi(u8 *mac, tANI_S8 rxRssi)
724{
725 hddTdlsPeer_t *curr_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530726
Hoonki Leebfee0342013-01-21 16:43:45 -0800727 if (NULL == pHddTdlsCtx) return -1;
728
Hoonki Lee387663d2013-02-05 18:08:43 -0800729 curr_peer = wlan_hdd_tdls_get_peer(mac);
730 if (curr_peer == NULL)
731 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530732
733 curr_peer->rssi = rxRssi;
734
Hoonki Lee387663d2013-02-05 18:08:43 -0800735 return 0;
Chilam NG571c65a2013-01-19 12:27:36 +0530736}
737
Hoonki Leea34dd892013-02-05 22:56:02 -0800738int wlan_hdd_tdls_set_responder(u8 *mac, tANI_U8 responder)
739{
740 hddTdlsPeer_t *curr_peer;
741
742 if (NULL == pHddTdlsCtx) return -1;
743
744 curr_peer = wlan_hdd_tdls_get_peer(mac);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800745 if (curr_peer == NULL)
Hoonki Leea34dd892013-02-05 22:56:02 -0800746 return -1;
747
748 curr_peer->is_responder = responder;
749
750 return 0;
751}
752
753int wlan_hdd_tdls_get_responder(u8 *mac)
754{
755 hddTdlsPeer_t *curr_peer;
756
757 if (NULL == pHddTdlsCtx) return -1;
758
759 curr_peer = wlan_hdd_tdls_find_peer(mac);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800760 if (curr_peer == NULL)
Hoonki Leea34dd892013-02-05 22:56:02 -0800761 return -1;
762
763 return (curr_peer->is_responder);
764}
765
Hoonki Lee11f7dda2013-02-14 16:55:44 -0800766int wlan_hdd_tdls_set_signature(u8 *mac, tANI_U8 uSignature)
767{
768 hddTdlsPeer_t *curr_peer;
769
770 if (NULL == pHddTdlsCtx) return -1;
771
772 curr_peer = wlan_hdd_tdls_get_peer(mac);
773 if (curr_peer == NULL)
774 return -1;
775
776 curr_peer->signature = uSignature;
777
778 return 0;
779}
780
Hoonki Leea34dd892013-02-05 22:56:02 -0800781
Hoonki Lee387663d2013-02-05 18:08:43 -0800782void wlan_hdd_tdls_extract_da(struct sk_buff *skb, u8 *mac)
Chilam NG571c65a2013-01-19 12:27:36 +0530783{
Chilam NG571c65a2013-01-19 12:27:36 +0530784 memcpy(mac, skb->data, 6);
Chilam NG571c65a2013-01-19 12:27:36 +0530785}
786
Hoonki Lee387663d2013-02-05 18:08:43 -0800787void wlan_hdd_tdls_extract_sa(struct sk_buff *skb, u8 *mac)
Chilam Ng1279e232013-01-25 15:06:52 -0800788{
Chilam Ng1279e232013-01-25 15:06:52 -0800789 memcpy(mac, skb->data+6, 6);
Chilam Ng1279e232013-01-25 15:06:52 -0800790}
791
Hoonki Lee387663d2013-02-05 18:08:43 -0800792int wlan_hdd_tdls_increment_pkt_count(u8 *mac, u8 tx)
Chilam NG571c65a2013-01-19 12:27:36 +0530793{
Hoonki Lee387663d2013-02-05 18:08:43 -0800794 hddTdlsPeer_t *curr_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530795
Hoonki Leebfee0342013-01-21 16:43:45 -0800796 if (NULL == pHddTdlsCtx) return -1;
797
Hoonki Lee387663d2013-02-05 18:08:43 -0800798 curr_peer = wlan_hdd_tdls_get_peer(mac);
799 if (curr_peer == NULL)
Chilam NG571c65a2013-01-19 12:27:36 +0530800 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530801
Chilam Ng1279e232013-01-25 15:06:52 -0800802 if (tx)
803 curr_peer->tx_pkt++;
804 else
805 curr_peer->rx_pkt++;
Chilam NG571c65a2013-01-19 12:27:36 +0530806
Chilam NG571c65a2013-01-19 12:27:36 +0530807 return 0;
808}
809
Chilam Ng01120412013-02-19 18:32:21 -0800810int wlan_hdd_tdls_set_params(struct net_device *dev, tdls_config_params_t *config)
Chilam NG571c65a2013-01-19 12:27:36 +0530811{
Chilam Ng01120412013-02-19 18:32:21 -0800812 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
813 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Hoonki Leebfee0342013-01-21 16:43:45 -0800814
Chilam Ng01120412013-02-19 18:32:21 -0800815 if ((eTDLS_SUPPORT_DISABLED == config->tdls) &&
816 ((NULL == pHddTdlsCtx) ||
817 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))) return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530818
Chilam Ng01120412013-02-19 18:32:21 -0800819 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) {
820 vos_timer_stop( &pHddTdlsCtx->peerDiscoverTimer);
821 vos_timer_stop( &pHddTdlsCtx->peerUpdateTimer);
822 }
Chilam NG571c65a2013-01-19 12:27:36 +0530823
Chilam Ng01120412013-02-19 18:32:21 -0800824 if (eTDLS_SUPPORT_DISABLED != pHddCtx->tdls_mode) {
825 memcpy(&pHddTdlsCtx->threshold_config, config, sizeof(tdls_config_params_t));
826 }
Chilam NG571c65a2013-01-19 12:27:36 +0530827
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800828 wlan_hdd_tdls_peer_reset_discovery_processed();
829
Chilam Ng01120412013-02-19 18:32:21 -0800830 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
831 "iw set tdls params: %d %d %d %d %d %d %d %d %d %d",
832 config->tdls,
833 config->tx_period_t,
834 config->tx_packet_n,
835 config->discovery_period_t,
836 config->discovery_tries_n,
837 config->idle_timeout_t,
838 config->idle_packet_n,
839 config->rssi_hysteresis,
840 config->rssi_trigger_threshold,
841 config->rssi_teardown_threshold);
Chilam NG571c65a2013-01-19 12:27:36 +0530842
Chilam Ng01120412013-02-19 18:32:21 -0800843 pHddCtx->tdls_mode = config->tdls;
844
845 if (eTDLS_SUPPORT_DISABLED == config->tdls) {
846 wlan_hdd_tdls_exit();
847 } else {
848 wlan_hdd_tdls_core_init(dev, config);
849 }
850
Chilam NG571c65a2013-01-19 12:27:36 +0530851 return 0;
852}
853
Hoonki Lee387663d2013-02-05 18:08:43 -0800854int wlan_hdd_tdls_set_sta_id(u8 *mac, u8 staId)
Kiran V1ccee932012-12-12 14:49:46 -0800855{
Hoonki Lee387663d2013-02-05 18:08:43 -0800856 hddTdlsPeer_t *curr_peer;
Kiran V1ccee932012-12-12 14:49:46 -0800857
Hoonki Leebfee0342013-01-21 16:43:45 -0800858 if (NULL == pHddTdlsCtx) return -1;
859
Hoonki Lee387663d2013-02-05 18:08:43 -0800860 curr_peer = wlan_hdd_tdls_get_peer(mac);
861 if (curr_peer == NULL)
Chilam NG571c65a2013-01-19 12:27:36 +0530862 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530863
Hoonki Lee387663d2013-02-05 18:08:43 -0800864 curr_peer->staId = staId;
Chilam NG571c65a2013-01-19 12:27:36 +0530865
866 return 0;
Kiran V1ccee932012-12-12 14:49:46 -0800867}
868
Hoonki Lee387663d2013-02-05 18:08:43 -0800869/* if peerMac is found, then it returns pointer to hddTdlsPeer_t
870 otherwise, it returns NULL
871*/
872hddTdlsPeer_t *wlan_hdd_tdls_find_peer(u8 *mac)
Kiran V1ccee932012-12-12 14:49:46 -0800873{
Hoonki Lee387663d2013-02-05 18:08:43 -0800874 u8 key;
875 struct list_head *pos;
876 struct list_head *head;
877 hddTdlsPeer_t *curr_peer;
878
Hoonki Lee387663d2013-02-05 18:08:43 -0800879
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800880 if (mutex_lock_interruptible(&tdls_lock))
Hoonki Lee387663d2013-02-05 18:08:43 -0800881 {
882 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
883 "%s: unable to lock list", __func__);
884 return NULL;
885 }
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800886 if (NULL == pHddTdlsCtx)
887 {
888 mutex_unlock(&tdls_lock);
889 return NULL;
890 }
891
892 key = wlan_hdd_tdls_hash_key(mac);
893
894 head = &pHddTdlsCtx->peer_list[key];
Hoonki Lee387663d2013-02-05 18:08:43 -0800895
896 list_for_each(pos, head) {
897 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
898 if (!memcmp(mac, curr_peer->peerMac, 6)) {
899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
900 "findTdlsPeer: found staId %d", curr_peer->staId);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800901 mutex_unlock(&tdls_lock);
Hoonki Lee387663d2013-02-05 18:08:43 -0800902 return curr_peer;
903 }
904 }
905
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800906 mutex_unlock(&tdls_lock);
Hoonki Lee387663d2013-02-05 18:08:43 -0800907 return NULL;
908}
909
910int wlan_hdd_tdls_reset_peer(u8 *mac)
911{
Chilam Ng01120412013-02-19 18:32:21 -0800912 hdd_adapter_t *pAdapter;
913 hdd_context_t *pHddCtx;
Chilam NG571c65a2013-01-19 12:27:36 +0530914 hddTdlsPeer_t *curr_peer;
Kiran V1ccee932012-12-12 14:49:46 -0800915
Hoonki Leebfee0342013-01-21 16:43:45 -0800916 if (NULL == pHddTdlsCtx) return -1;
917
Chilam Ng01120412013-02-19 18:32:21 -0800918 pAdapter = WLAN_HDD_GET_PRIV_PTR(pHddTdlsCtx->dev);
919 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
920
Hoonki Lee387663d2013-02-05 18:08:43 -0800921 curr_peer = wlan_hdd_tdls_get_peer(mac);
922 if (curr_peer == NULL)
923 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530924
Hoonki Leecdd8e962013-01-20 00:45:46 -0800925 curr_peer->link_status = eTDLS_LINK_NOT_CONNECTED;
926 curr_peer->staId = 0;
927 curr_peer->rssi = -120;
Hoonki Lee387663d2013-02-05 18:08:43 -0800928
Chilam Ng01120412013-02-19 18:32:21 -0800929 if(eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) {
Chilam Nga75d8b62013-01-29 01:35:59 -0800930 vos_timer_stop( &curr_peer->peerIdleTimer );
Chilam Nga75d8b62013-01-29 01:35:59 -0800931 }
Hoonki Lee387663d2013-02-05 18:08:43 -0800932 return 0;
Hoonki Leecdd8e962013-01-20 00:45:46 -0800933}
934
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800935static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(void)
936{
937 int i;
938 struct list_head *head;
939 hddTdlsPeer_t *tmp;
940 struct list_head *pos, *q;
941
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800942 if (mutex_lock_interruptible(&tdls_lock))
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800943 {
944 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
945 "%s: unable to lock list", __func__);
946 return -1;
947 }
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800948 if ( NULL == pHddTdlsCtx )
949 {
950 mutex_unlock(&tdls_lock);
951 return -1;
952 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800953
954 pHddTdlsCtx->discovery_peer_cnt = 0;
955
956 for (i = 0; i < 256; i++) {
957 head = &pHddTdlsCtx->peer_list[i];
958 list_for_each_safe (pos, q, head) {
959 tmp = list_entry(pos, hddTdlsPeer_t, node);
960 tmp->discovery_processed = 0;
961 }
962 }
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800963 mutex_unlock(&tdls_lock);
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800964
965 return 0;
966}
967
968static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(void)
969{
970 int i;
971 struct list_head *head;
972 struct list_head *pos, *q;
973 int discovery_peer_cnt=0;
974 hddTdlsPeer_t *tmp;
975
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800976 /*
977 * This function expects the callers to acquire the Mutex.
978 */
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800979
980 for (i = 0; i < 256; i++) {
981 head = &pHddTdlsCtx->peer_list[i];
982 list_for_each_safe (pos, q, head) {
983 tmp = list_entry(pos, hddTdlsPeer_t, node);
984 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800985 "%s, %d, " MAC_ADDRESS_STR, __func__, i,
986 MAC_ADDR_ARRAY(tmp->peerMac));
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800987 discovery_peer_cnt++;
988 }
989 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800990 return discovery_peer_cnt;
991}
992
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800993tANI_U16 wlan_hdd_tdlsConnectedPeers(void)
Lee Hoonkic1262f22013-01-24 21:59:00 -0800994{
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800995 if (NULL == pHddTdlsCtx)
996 return 0;
Lee Hoonkic1262f22013-01-24 21:59:00 -0800997
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800998 return pHddTdlsCtx->connected_peer_count;
Lee Hoonkic1262f22013-01-24 21:59:00 -0800999}
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001000
1001int wlan_hdd_tdls_get_all_peers(char *buf, int buflen)
1002{
1003 int i;
1004 int len, init_len;
Hoonki Lee387663d2013-02-05 18:08:43 -08001005 struct list_head *head;
1006 struct list_head *pos;
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001007 hddTdlsPeer_t *curr_peer;
1008
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001009
1010 init_len = buflen;
1011 len = snprintf(buf, buflen, "\n%-18s%-3s%-4s%-3s%-5s\n", "MAC", "Id", "cap", "up", "RSSI");
1012 buf += len;
1013 buflen -= len;
1014 /* 1234567890123456789012345678901234567 */
1015 len = snprintf(buf, buflen, "---------------------------------\n");
1016 buf += len;
1017 buflen -= len;
1018
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001019 if (mutex_lock_interruptible(&tdls_lock))
Gopichand Nakkala91b09262013-02-10 14:27:02 -08001020 {
1021 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1022 "%s: unable to lock list", __func__);
1023 return init_len-buflen;
1024 }
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001025 if (NULL == pHddTdlsCtx) {
1026 mutex_unlock(&tdls_lock);
1027 len = snprintf(buf, buflen, "TDLS not enabled\n");
1028 return len;
1029 }
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001030 for (i = 0; i < 256; i++) {
Hoonki Lee387663d2013-02-05 18:08:43 -08001031 head = &pHddTdlsCtx->peer_list[i];
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001032
Hoonki Lee387663d2013-02-05 18:08:43 -08001033 list_for_each(pos, head) {
1034 curr_peer= list_entry (pos, hddTdlsPeer_t, node);
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001035
Hoonki Lee387663d2013-02-05 18:08:43 -08001036 if (buflen < 32+1)
1037 break;
1038 len = snprintf(buf, buflen,
Chilam Ng01120412013-02-19 18:32:21 -08001039 MAC_ADDRESS_STR"%3d%4s%3s%5d\n",
1040 MAC_ADDR_ARRAY(curr_peer->peerMac),
Hoonki Lee387663d2013-02-05 18:08:43 -08001041 curr_peer->staId,
1042 (curr_peer->tdls_support == eTDLS_CAP_SUPPORTED) ? "Y":"N",
1043 (curr_peer->link_status == eTDLS_LINK_CONNECTED) ? "Y":"N",
1044 curr_peer->rssi);
1045 buf += len;
1046 buflen -= len;
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001047 }
1048 }
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001049 mutex_unlock(&tdls_lock);
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001050 return init_len-buflen;
1051}
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001052
1053void wlan_hdd_tdls_connection_callback(hdd_adapter_t *pAdapter)
1054{
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001055 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1056
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001057 if (NULL == pHddTdlsCtx) return;
1058
1059 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1060 "%s, update %d discover %d", __func__,
1061 pHddTdlsCtx->threshold_config.tx_period_t,
1062 pHddTdlsCtx->threshold_config.discovery_period_t);
1063
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001064 pHddTdlsCtx->connected_peer_count = 0;
1065
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001066 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode)
1067 {
1068 wlan_hdd_tdls_peer_reset_discovery_processed();
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001069
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001070 vos_timer_start(&pHddTdlsCtx->peerDiscoverTimer,
1071 pHddTdlsCtx->threshold_config.discovery_period_t);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001072
1073
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001074 vos_timer_start(&pHddTdlsCtx->peerUpdateTimer,
1075 pHddTdlsCtx->threshold_config.tx_period_t);
1076 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001077
1078}
1079
1080void wlan_hdd_tdls_disconnection_callback(hdd_adapter_t *pAdapter)
1081{
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001082
1083 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s", __func__);
1084
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001085 if (mutex_lock_interruptible(&tdls_lock))
1086 {
1087 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1088 "%s: unable to lock list", __func__);
1089 return;
1090 }
1091 if (NULL == pHddTdlsCtx)
1092 {
1093 mutex_unlock(&tdls_lock);
1094 return;
1095 }
1096
1097
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001098 wlan_hdd_tdls_timers_stop();
1099 wlan_hdd_tdls_free_list();
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001100
1101 mutex_unlock(&tdls_lock);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001102}
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001103
1104void wlan_hdd_tdls_mgmt_completion_callback(hdd_adapter_t *pAdapter, tANI_U32 statusCode)
1105{
1106 pAdapter->mgmtTxCompletionStatus = statusCode;
1107 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s: Mgmt TX Completion %d",
1108 __func__, statusCode);
1109 complete(&pAdapter->tdls_mgmt_comp);
1110}
1111
1112void wlan_hdd_tdls_increment_peer_count(void)
1113{
1114 if (NULL == pHddTdlsCtx) return;
1115
1116 pHddTdlsCtx->connected_peer_count++;
1117}
1118
1119void wlan_hdd_tdls_decrement_peer_count(void)
1120{
1121 if (NULL == pHddTdlsCtx) return;
1122
1123 if (pHddTdlsCtx->connected_peer_count)
1124 pHddTdlsCtx->connected_peer_count--;
1125}
1126
1127void wlan_hdd_tdls_check_bmps(hdd_context_t *pHddCtx)
1128{
1129 if (NULL == pHddTdlsCtx) return;
1130
1131 if (0 == pHddTdlsCtx->connected_peer_count)
1132 {
1133 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"No TDLS peer connected so Enable BMPS");
1134 hdd_enable_bmps_imps(pHddCtx);
1135 }
1136 else if (1 == pHddTdlsCtx->connected_peer_count)
1137 {
1138 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"TDLS peer connected so Disable BMPS");
1139 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
1140 }
1141 return;
1142}
1143
1144/* return TRUE if TDLS is ongoing
1145 * mac - if NULL check for all the peer list, otherwise, skip this mac when skip_self is TRUE
1146 * skip_self - if TRUE, skip this mac. otherwise, check all the peer list. if
1147 mac is NULL, this argument is ignored, and check for all the peer list.
1148 */
1149u8 wlan_hdd_tdls_is_progress(u8 *mac, u8 skip_self)
1150{
1151 int i;
1152 struct list_head *head;
1153 hddTdlsPeer_t *curr_peer;
1154 struct list_head *pos;
1155
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001156 if (mutex_lock_interruptible(&tdls_lock))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001157 {
1158 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1159 "%s: unable to lock list", __func__);
1160 return FALSE;
1161 }
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001162 if (NULL == pHddTdlsCtx)
1163 {
1164 mutex_unlock(&tdls_lock);
1165 return FALSE;
1166 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001167
1168 for (i = 0; i < 256; i++) {
1169 head = &pHddTdlsCtx->peer_list[i];
1170 list_for_each(pos, head) {
1171 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
1172 if (skip_self && mac && !memcmp(mac, curr_peer->peerMac, 6)) {
1173 continue;
1174 }
1175 else
1176 {
1177 if (curr_peer->isTDLSInProgress)
1178 {
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001179 mutex_unlock(&tdls_lock);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001180 return TRUE;
1181 }
1182 }
1183 }
1184 }
1185
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001186 mutex_unlock(&tdls_lock);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001187 return FALSE;
1188}
1189
1190void wlan_hdd_tdls_set_connection_progress(u8* mac, u8 isProgress)
1191{
1192 hddTdlsPeer_t *curr_peer;
1193
1194 if (NULL == pHddTdlsCtx) return;
1195
1196 curr_peer = wlan_hdd_tdls_find_peer(mac);
1197 if (curr_peer == NULL)
1198 return;
1199
1200 curr_peer->isTDLSInProgress = isProgress;
1201
1202 return;
1203}