blob: 0ab884a520bd533d14138512dbc22771988d0a4d [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);
Hoonki Leed37cbb32013-04-20 00:31:14 -070046#ifdef CONFIG_TDLS_IMPLICIT
47static void wlan_hdd_tdls_pre_setup(struct work_struct *work);
48#endif
Chilam NG571c65a2013-01-19 12:27:36 +053049
Hoonki Lee5a4b2172013-01-29 01:45:53 -080050#ifndef WLAN_FEATURE_TDLS_DEBUG
51#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
52#else
53#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_WARN
54#endif
55
Hoonki Lee387663d2013-02-05 18:08:43 -080056static u8 wlan_hdd_tdls_hash_key (u8 *mac)
Hoonki Leef63df0d2013-01-16 19:29:14 -080057{
58 int i;
Hoonki Lee387663d2013-02-05 18:08:43 -080059 u8 key = 0;
60
61 for (i = 0; i < 6; i++)
62 key ^= mac[i];
63
64 return key;
65}
66
Hoonki Leed37cbb32013-04-20 00:31:14 -070067#ifdef CONFIG_TDLS_IMPLICIT
68static void wlan_hdd_tdls_pre_setup_init_work(tdlsCtx_t * pHddTdlsCtx,
69 hddTdlsPeer_t *curr_candidate)
70{
71 if (TDLS_CTX_MAGIC != pHddTdlsCtx->magic)
72 {
73 pHddTdlsCtx->curr_candidate = curr_candidate;
74 pHddTdlsCtx->magic = TDLS_CTX_MAGIC;
75
76 INIT_WORK(&pHddTdlsCtx->implicit_setup, wlan_hdd_tdls_pre_setup);
77 schedule_work(&pHddTdlsCtx->implicit_setup);
78 }
79}
80#endif
81
Gopichand Nakkala4327a152013-03-04 23:22:42 -080082static v_VOID_t wlan_hdd_tdls_start_peer_discover_timer(tdlsCtx_t *pHddTdlsCtx,
83 tANI_BOOLEAN mutexLock,
84 v_U32_t discoveryExpiry)
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080085{
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080086 hdd_station_ctx_t *pHddStaCtx;
87
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080088 if ( mutexLock )
89 {
90 if (mutex_lock_interruptible(&tdls_lock))
91 {
92 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
93 "%s: unable to lock list: %d", __func__, __LINE__);
94 return;
95 }
96 }
97 if (NULL == pHddTdlsCtx)
98 {
99 if ( mutexLock )
100 mutex_unlock(&tdls_lock);
101 return;
102 }
103
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800104 if (NULL == pHddTdlsCtx->pAdapter)
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800105 {
106 if ( mutexLock )
107 mutex_unlock(&tdls_lock);
108 return;
109 }
110
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800111 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pHddTdlsCtx->pAdapter);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700112#ifdef FEATURE_WLAN_TDLS_INTERNAL
Gopichand Nakkala3046fc92013-03-23 13:56:43 -0700113 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
114 &pHddTdlsCtx->peerDiscoverTimer,
115 discoveryExpiry);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700116#endif
Gopichand Nakkala3046fc92013-03-23 13:56:43 -0700117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "beacon rssi: %d",
118 pHddTdlsCtx->ap_rssi);
119
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800120 if ( mutexLock )
121 mutex_unlock(&tdls_lock);
122
123 return;
124}
125
Hoonki Leed37cbb32013-04-20 00:31:14 -0700126#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER
Hoonki Lee387663d2013-02-05 18:08:43 -0800127static v_VOID_t wlan_hdd_tdls_discover_peer_cb( v_PVOID_t userData )
128{
129 int i;
130 struct list_head *head;
131 struct list_head *pos;
Chilam NG571c65a2013-01-19 12:27:36 +0530132 hddTdlsPeer_t *curr_peer;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800133 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800134 tdlsCtx_t *pHddTdlsCtx = (tdlsCtx_t *)userData;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800135 int discover_req_sent = 0;
136 v_U32_t discover_expiry = TDLS_SUB_DISCOVERY_PERIOD;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800137 tANI_BOOLEAN doMutexLock = eANI_BOOLEAN_TRUE;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800138
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800139 if (mutex_lock_interruptible(&tdls_lock))
140 {
141 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
142 "%s: unable to lock list : %d", __func__, __LINE__);
143 return;
144 }
Hoonki Leebfee0342013-01-21 16:43:45 -0800145
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800146 if (NULL == pHddTdlsCtx)
147 {
148 mutex_unlock(&tdls_lock);
149 return;
150 }
Hoonki Leebfee0342013-01-21 16:43:45 -0800151
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800152 if (NULL == pHddTdlsCtx->pAdapter)
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800153 {
154 mutex_unlock(&tdls_lock);
155 return;
156 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800157
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800158 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pHddTdlsCtx->pAdapter);
Hoonki Leef63df0d2013-01-16 19:29:14 -0800159
Hoonki Lee387663d2013-02-05 18:08:43 -0800160 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: ", __func__);
161
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800162 if (0 == pHddTdlsCtx->discovery_peer_cnt)
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800163 pHddTdlsCtx->discovery_peer_cnt = wlan_hdd_get_tdls_discovery_peer_cnt(pHddTdlsCtx);
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800164
Chilam NG571c65a2013-01-19 12:27:36 +0530165 for (i = 0; i < 256; i++) {
Hoonki Lee387663d2013-02-05 18:08:43 -0800166 head = &pHddTdlsCtx->peer_list[i];
Chilam NG571c65a2013-01-19 12:27:36 +0530167
Hoonki Lee387663d2013-02-05 18:08:43 -0800168 list_for_each (pos, head) {
169 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
Chilam NG571c65a2013-01-19 12:27:36 +0530170
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -0800171 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800172 "%d " MAC_ADDRESS_STR " %d %d, %d %d %d %d", i,
173 MAC_ADDR_ARRAY(curr_peer->peerMac),
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800174 curr_peer->discovery_processed,
175 discover_req_sent,
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -0800176 curr_peer->tdls_support,
177 curr_peer->link_status,
178 curr_peer->discovery_attempt,
179 pHddTdlsCtx->threshold_config.discovery_tries_n);
Hoonki Lee387663d2013-02-05 18:08:43 -0800180
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800181 if (discover_req_sent < TDLS_MAX_DISCOVER_REQS_PER_TIMER) {
182 if (!curr_peer->discovery_processed) {
Chilam NG571c65a2013-01-19 12:27:36 +0530183
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800184 curr_peer->discovery_processed = 1;
185 discover_req_sent++;
186 pHddTdlsCtx->discovery_peer_cnt--;
187
188 if ((eTDLS_CAP_UNKNOWN == curr_peer->tdls_support) &&
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800189 (eTDLS_LINK_IDLE == curr_peer->link_status) &&
Gopichand Nakkalab88f6772013-02-27 18:12:56 -0800190 (curr_peer->tx_pkt >=
191 pHddTdlsCtx->threshold_config.tx_packet_n)) {
Gopichand Nakkala273d5a02013-02-19 15:15:09 -0800192
193 if (curr_peer->discovery_attempt <
194 pHddTdlsCtx->threshold_config.discovery_tries_n) {
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800195 sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter),
196 pHddTdlsCtx->pAdapter->sessionId,
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800197 curr_peer->peerMac,
198 WLAN_TDLS_DISCOVERY_REQUEST,
199 1, 0, NULL, 0, 0);
Gopichand Nakkala273d5a02013-02-19 15:15:09 -0800200 curr_peer->discovery_attempt++;
201 }
202 else
203 {
204 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
205 "%s: Maximum Discovery retries reached", __func__);
206 curr_peer->tdls_support = eTDLS_CAP_NOT_SUPPORTED;
207 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800208
209 }
210 }
Chilam NG571c65a2013-01-19 12:27:36 +0530211 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800212 else
213 goto exit_loop;
Hoonki Lee387663d2013-02-05 18:08:43 -0800214 }
Hoonki Leef63df0d2013-01-16 19:29:14 -0800215 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800216exit_loop:
Hoonki Leef63df0d2013-01-16 19:29:14 -0800217
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800218 if (0 != pHddTdlsCtx->discovery_peer_cnt) {
219 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
220 "discovery_peer_cnt is %d , Starting SUB_DISCOVERY_TIMER",
221 pHddTdlsCtx->discovery_peer_cnt);
222 discover_expiry = TDLS_SUB_DISCOVERY_PERIOD;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800223 doMutexLock = eANI_BOOLEAN_FALSE;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800224 goto done;
225 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800226 discover_expiry = pHddTdlsCtx->threshold_config.discovery_period_t;
227
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800228 wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx);
Chilam NG571c65a2013-01-19 12:27:36 +0530229
Gopichand Nakkala638ebc72013-03-21 18:04:02 -0700230 mutex_unlock(&tdls_lock);
231
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800232 /* Commenting out the following function as it was introducing
233 * a race condition when pHddTdlsCtx is deleted. Also , this
234 * function is consuming more time in the timer callback.
235 * RSSI based trigger needs to revisit this part of the code.
236 */
237
238 /*
239 * wlan_hdd_get_rssi(pAdapter, &pHddTdlsCtx->ap_rssi);
240 */
Chilam NG571c65a2013-01-19 12:27:36 +0530241
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800242done:
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800243 wlan_hdd_tdls_start_peer_discover_timer(pHddTdlsCtx, doMutexLock, discover_expiry);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800244
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800245 if ( !doMutexLock )
246 mutex_unlock(&tdls_lock);
247 return;
Hoonki Leef63df0d2013-01-16 19:29:14 -0800248}
Hoonki Leed37cbb32013-04-20 00:31:14 -0700249#endif
Chilam NG571c65a2013-01-19 12:27:36 +0530250
Hoonki Lee387663d2013-02-05 18:08:43 -0800251static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData )
Chilam NG571c65a2013-01-19 12:27:36 +0530252{
253 int i;
Hoonki Lee387663d2013-02-05 18:08:43 -0800254 struct list_head *head;
255 struct list_head *pos;
Chilam NG571c65a2013-01-19 12:27:36 +0530256 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800257 tdlsCtx_t *pHddTdlsCtx;
Hoonki Leebfee0342013-01-21 16:43:45 -0800258
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800259 if (mutex_lock_interruptible(&tdls_lock))
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800260 {
261 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
262 "%s: unable to lock list", __func__);
263 return;
264 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800265 pHddTdlsCtx = (tdlsCtx_t *)userData;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800266 if (NULL == pHddTdlsCtx)
267 {
268 mutex_unlock(&tdls_lock);
269 return;
270 }
271
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800272 if (NULL == pHddTdlsCtx->pAdapter)
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800273 {
274 mutex_unlock(&tdls_lock);
275 return;
276 }
277
Chilam NG571c65a2013-01-19 12:27:36 +0530278 for (i = 0; i < 256; i++) {
Hoonki Lee387663d2013-02-05 18:08:43 -0800279 head = &pHddTdlsCtx->peer_list[i];
Chilam NG571c65a2013-01-19 12:27:36 +0530280
Hoonki Lee387663d2013-02-05 18:08:43 -0800281 list_for_each (pos, head) {
282 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
Chilam NG571c65a2013-01-19 12:27:36 +0530283
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800284 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Hoonki Lee66b75f32013-04-16 18:30:07 -0700285 "%s: " MAC_ADDRESS_STR " link_status %d"
286 " tdls_support %d", __func__, MAC_ADDR_ARRAY(curr_peer->peerMac),
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700287 curr_peer->link_status, curr_peer->tdls_support);
Hoonki Lee387663d2013-02-05 18:08:43 -0800288
Chilam NG571c65a2013-01-19 12:27:36 +0530289 if (eTDLS_CAP_SUPPORTED == curr_peer->tdls_support) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800290 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Hoonki Lee66b75f32013-04-16 18:30:07 -0700291 "tx %d, rx %d (thr.pkt %d/idle %d), rssi %d (thr.trig %d/hys %d/tear %d)",
292 curr_peer->tx_pkt, curr_peer->rx_pkt,
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800293 pHddTdlsCtx->threshold_config.tx_packet_n,
Hoonki Lee66b75f32013-04-16 18:30:07 -0700294 pHddTdlsCtx->threshold_config.idle_packet_n,
295 curr_peer->rssi,
296 pHddTdlsCtx->threshold_config.rssi_trigger_threshold,
297 pHddTdlsCtx->threshold_config.rssi_hysteresis,
298 pHddTdlsCtx->threshold_config.rssi_teardown_threshold);
Chilam Ng01120412013-02-19 18:32:21 -0800299
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800300 if ((eTDLS_LINK_IDLE == curr_peer->link_status) ||
301 (eTDLS_LINK_DISCOVERING == curr_peer->link_status)){
Chilam NG571c65a2013-01-19 12:27:36 +0530302 if (curr_peer->tx_pkt >=
303 pHddTdlsCtx->threshold_config.tx_packet_n) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800304
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800305 if (HDD_MAX_NUM_TDLS_STA > wlan_hdd_tdlsConnectedPeers(pHddTdlsCtx->pAdapter))
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800306 {
307
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700308 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "Tput trigger TDLS pre-setup");
Chilam NG571c65a2013-01-19 12:27:36 +0530309#ifdef CONFIG_TDLS_IMPLICIT
Hoonki Leed37cbb32013-04-20 00:31:14 -0700310 wlan_hdd_tdls_pre_setup_init_work(pHddTdlsCtx, curr_peer);
Chilam NG571c65a2013-01-19 12:27:36 +0530311#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800312 }
313 else
314 {
315 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800316 "%s: Maximum peer connected already! %d",
317 __func__, wlan_hdd_tdlsConnectedPeers(pHddTdlsCtx->pAdapter) );
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800318 }
Hoonki Leecdd8e962013-01-20 00:45:46 -0800319 goto next_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530320 }
Hoonki Leefb8df672013-04-10 18:20:34 -0700321 }
322 else if (eTDLS_LINK_CONNECTED == curr_peer->link_status) {
Chilam Ng01120412013-02-19 18:32:21 -0800323 if ((tANI_S32)curr_peer->rssi <
324 (tANI_S32)pHddTdlsCtx->threshold_config.rssi_teardown_threshold) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800325
Chilam Ng01120412013-02-19 18:32:21 -0800326 VOS_TRACE( VOS_MODULE_ID_HDD,
327 VOS_TRACE_LEVEL_WARN,
328 "Tear down - low RSSI: " MAC_ADDRESS_STR "!",
329 MAC_ADDR_ARRAY(curr_peer->peerMac));
330#ifdef CONFIG_TDLS_IMPLICIT
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -0700331 wlan_hdd_tdls_indicate_teardown(pHddTdlsCtx->pAdapter,
332 curr_peer,
333 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
Chilam Ng01120412013-02-19 18:32:21 -0800334#endif
Hoonki Leecdd8e962013-01-20 00:45:46 -0800335 goto next_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530336 }
Chilam Ng01120412013-02-19 18:32:21 -0800337
338 if ((curr_peer->tx_pkt <
339 pHddTdlsCtx->threshold_config.idle_packet_n) &&
340 (curr_peer->rx_pkt <
341 pHddTdlsCtx->threshold_config.idle_packet_n)) {
342 if (VOS_TIMER_STATE_RUNNING !=
343 vos_timer_getCurrentState(&curr_peer->peerIdleTimer)) {
344 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
345 "Tx/Rx Idle timer start: " MAC_ADDRESS_STR "!",
346 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkala3046fc92013-03-23 13:56:43 -0700347 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
348 &curr_peer->peerIdleTimer,
349 pHddTdlsCtx->threshold_config.idle_timeout_t);
Chilam Ng01120412013-02-19 18:32:21 -0800350 }
351 } else {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800352 if (VOS_TIMER_STATE_RUNNING ==
353 vos_timer_getCurrentState(&curr_peer->peerIdleTimer)) {
Chilam Ng01120412013-02-19 18:32:21 -0800354 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
355 "Tx/Rx Idle timer stop: " MAC_ADDRESS_STR "!",
356 MAC_ADDR_ARRAY(curr_peer->peerMac));
357 vos_timer_stop( &curr_peer->peerIdleTimer);
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800358 }
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800359 }
Chilam Ng01120412013-02-19 18:32:21 -0800360
Hoonki Leecdd8e962013-01-20 00:45:46 -0800361// if (curr_peer->rssi <
362// (pHddTdlsCtx->threshold_config.rssi_hysteresis +
363// pHddTdlsCtx->ap_rssi)) {
364//
365//#ifdef CONFIG_TDLS_IMPLICIT
366// cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
367// curr_peer->peerMac,
368// NL80211_TDLS_TEARDOWN, FALSE,
369// GFP_KERNEL);
370//#endif
371// }
Chilam NG571c65a2013-01-19 12:27:36 +0530372 }
Chilam Ng01120412013-02-19 18:32:21 -0800373 } else if (eTDLS_CAP_UNKNOWN == curr_peer->tdls_support) {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -0700374 if (!TDLS_IS_CONNECTED(curr_peer)) {
Chilam Ng01120412013-02-19 18:32:21 -0800375 if (curr_peer->tx_pkt >=
376 pHddTdlsCtx->threshold_config.tx_packet_n) {
Chilam Ng01120412013-02-19 18:32:21 -0800377
Gopichand Nakkala062bcbd2013-03-29 18:14:47 -0700378 if (curr_peer->discovery_attempt++ <
Chilam Ng01120412013-02-19 18:32:21 -0800379 pHddTdlsCtx->threshold_config.discovery_tries_n) {
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700380 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "TDLS UNKNOWN discover ");
Hoonki Leed37cbb32013-04-20 00:31:14 -0700381#ifdef CONFIG_TDLS_IMPLICIT
382 wlan_hdd_tdls_pre_setup_init_work(pHddTdlsCtx, curr_peer);
383#endif
Chilam Ng01120412013-02-19 18:32:21 -0800384 }
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800385 else
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800386 {
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800387 curr_peer->tdls_support = eTDLS_CAP_NOT_SUPPORTED;
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800388 curr_peer->link_status = eTDLS_LINK_IDLE;
389 }
Chilam Ng01120412013-02-19 18:32:21 -0800390 }
391 }
Chilam NG571c65a2013-01-19 12:27:36 +0530392 }
393
Hoonki Leecdd8e962013-01-20 00:45:46 -0800394next_peer:
Chilam NG571c65a2013-01-19 12:27:36 +0530395 curr_peer->tx_pkt = 0;
Chilam Ng1279e232013-01-25 15:06:52 -0800396 curr_peer->rx_pkt = 0;
Hoonki Lee387663d2013-02-05 18:08:43 -0800397 }
Chilam NG571c65a2013-01-19 12:27:36 +0530398 }
399
Gopichand Nakkala3046fc92013-03-23 13:56:43 -0700400 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
401 &pHddTdlsCtx->peerUpdateTimer,
402 pHddTdlsCtx->threshold_config.tx_period_t);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800403 mutex_unlock(&tdls_lock);
Chilam NG571c65a2013-01-19 12:27:36 +0530404}
405
Chilam Ng1279e232013-01-25 15:06:52 -0800406static v_VOID_t wlan_hdd_tdls_idle_cb( v_PVOID_t userData )
407{
Lee Hoonkic1262f22013-01-24 21:59:00 -0800408#ifdef CONFIG_TDLS_IMPLICIT
Chilam Ng1279e232013-01-25 15:06:52 -0800409 hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData;
410
Rajesh Chauhan1ace6002013-04-18 18:08:21 -0700411 if (NULL == curr_peer)
412 {
413 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
414 "%s: Invalid tdls idle timer expired", __func__);
415 return;
416 }
417
418 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
419 "%s: Tx/Rx Idle " MAC_ADDRESS_STR " tx_pkt: %d, rx_pkt: %d, idle_packet_n: %d\n",
420 __func__, MAC_ADDR_ARRAY(curr_peer->peerMac),
421 curr_peer->tx_pkt,
422 curr_peer->rx_pkt,
423 curr_peer->pHddTdlsCtx->threshold_config.idle_packet_n);
424
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800425 if (mutex_lock_interruptible(&tdls_lock))
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800426 {
427 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
428 "%s: unable to lock list", __func__);
429 return;
430 }
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800431
Rajesh Chauhan1ace6002013-04-18 18:08:21 -0700432 /* Check tx/rx statistics on this tdls link for recent activities and
433 * then decide whether to tear down the link or keep it.
434 */
435 if ((curr_peer->tx_pkt >= curr_peer->pHddTdlsCtx->threshold_config.idle_packet_n) || (curr_peer->rx_pkt >= curr_peer->pHddTdlsCtx->threshold_config.idle_packet_n))
436 {
437 /* this tdls link got back to normal, so keep it */
438 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
439 "%s: tdls link to " MAC_ADDRESS_STR " back to normal, will stay",
440 __func__, MAC_ADDR_ARRAY(curr_peer->peerMac));
441 }
442 else
443 {
444 /* this tdls link needs to get torn down */
445 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
446 "%s: trigger tdls link to " MAC_ADDRESS_STR " down",
447 __func__, MAC_ADDR_ARRAY(curr_peer->peerMac));
448
449 wlan_hdd_tdls_indicate_teardown(curr_peer->pHddTdlsCtx->pAdapter,
450 curr_peer,
451 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
452 }
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800453 mutex_unlock(&tdls_lock);
Chilam Ng1279e232013-01-25 15:06:52 -0800454#endif
455}
456
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700457static v_VOID_t wlan_hdd_tdls_discovery_timeout_peer_cb(v_PVOID_t userData)
458{
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700459 int i;
460 struct list_head *head;
461 hddTdlsPeer_t *tmp;
462 struct list_head *pos, *q;
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700463 tdlsCtx_t *pHddTdlsCtx;
464
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700465 if (mutex_lock_interruptible(&tdls_lock))
466 {
467 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
468 "%s: unable to lock list", __func__);
469 return ;
470 }
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700471 pHddTdlsCtx = (tdlsCtx_t *)userData;
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700472
473 if ( NULL == pHddTdlsCtx )
474 {
475 mutex_unlock(&tdls_lock);
476 return ;
477 }
478
479 for (i = 0; i < 256; i++) {
480 head = &pHddTdlsCtx->peer_list[i];
481 list_for_each_safe (pos, q, head) {
482 tmp = list_entry(pos, hddTdlsPeer_t, node);
483 if (eTDLS_LINK_DISCOVERING == tmp->link_status)
484 {
485 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
486 "%s: " MAC_ADDRESS_STR " to idle state", __func__,
487 MAC_ADDR_ARRAY(tmp->peerMac));
488 tmp->link_status = eTDLS_LINK_IDLE;
489 }
490 }
491 }
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700492
493 pHddTdlsCtx->discovery_sent_cnt = 0;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700494 wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700495
496 mutex_unlock(&tdls_lock);
497
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700498 wlan_hdd_tdls_check_bmps(pHddTdlsCtx->pAdapter);
499
500 return;
501}
502
Hoonki Lee14621352013-04-16 17:51:19 -0700503static v_VOID_t wlan_hdd_tdls_initiator_wait_cb( v_PVOID_t userData )
504{
505 hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData;
506 tdlsCtx_t *pHddTdlsCtx;
507
508 if ( NULL == curr_peer )
509 return;
510
511 pHddTdlsCtx = curr_peer->pHddTdlsCtx;
512
513 if ( NULL == pHddTdlsCtx )
514 return;
515
516 WLANTL_ResumeDataTx( (WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter))->pvosContext,
517 (v_U8_t *)&curr_peer->staId);
518}
519
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800520static void wlan_hdd_tdls_free_list(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800521{
522 int i;
523 struct list_head *head;
524 hddTdlsPeer_t *tmp;
525 struct list_head *pos, *q;
526
527 if (NULL == pHddTdlsCtx) return;
528
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800529
530 for (i = 0; i < 256; i++) {
531 head = &pHddTdlsCtx->peer_list[i];
532 list_for_each_safe (pos, q, head) {
533 tmp = list_entry(pos, hddTdlsPeer_t, node);
534 list_del(pos);
535 vos_mem_free(tmp);
536 }
537 }
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800538}
539
Hoonki Lee27511902013-03-14 18:19:06 -0700540int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter)
Chilam Ng01120412013-02-19 18:32:21 -0800541{
Chilam Ng01120412013-02-19 18:32:21 -0800542 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Hoonki Lee27511902013-03-14 18:19:06 -0700543 tdlsCtx_t *pHddTdlsCtx;
Chilam Ng01120412013-02-19 18:32:21 -0800544 int i;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800545 v_U8_t staIdx;
Chilam Ng01120412013-02-19 18:32:21 -0800546
Hoonki Lee27511902013-03-14 18:19:06 -0700547 mutex_init(&tdls_lock);
Chilam Ng01120412013-02-19 18:32:21 -0800548
Hoonki Lee27511902013-03-14 18:19:06 -0700549 if ((FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport) ||
550 (FALSE == sme_IsFeatureSupportedByFW(TDLS)))
551 {
552 pHddCtx->tdls_mode = eTDLS_SUPPORT_NOT_ENABLED;
553 pAdapter->sessionCtx.station.pHddTdlsCtx = NULL;
554 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS not enabled (%d) or FW doesn't support (%d)!",
555 __func__, pHddCtx->cfg_ini->fEnableTDLSSupport,
556 sme_IsFeatureSupportedByFW(TDLS));
557 return 0;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800558 }
559
Hoonki Lee27511902013-03-14 18:19:06 -0700560 pHddTdlsCtx = vos_mem_malloc(sizeof(tdlsCtx_t));
561
562 if (NULL == pHddTdlsCtx) {
563 hddLog(VOS_TRACE_LEVEL_ERROR, "%s malloc failed!", __func__);
564 pAdapter->sessionCtx.station.pHddTdlsCtx = NULL;
565 return -1;
566 }
567
568 pAdapter->sessionCtx.station.pHddTdlsCtx = pHddTdlsCtx;
569
570 /* initialize TDLS global context */
571 pHddCtx->connected_peer_count = 0;
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700572 sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
Hoonki Lee27511902013-03-14 18:19:06 -0700573
Hoonki Lee93e67ff2013-03-19 15:49:25 -0700574 pHddCtx->tdls_scan_ctxt.magic = 0;
Hoonki Leefb8df672013-04-10 18:20:34 -0700575 pHddCtx->tdls_scan_ctxt.attempt = 0;
576 pHddCtx->tdls_scan_ctxt.reject = 0;
Hoonki Lee93e67ff2013-03-19 15:49:25 -0700577 pHddCtx->tdls_scan_ctxt.scan_request = NULL;
578
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800579 for (staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
580 {
581 pHddCtx->tdlsConnInfo[staIdx].staId = 0;
582 pHddCtx->tdlsConnInfo[staIdx].sessionId = 255;
583 vos_mem_zero(&pHddCtx->tdlsConnInfo[staIdx].peerMac,
584 sizeof(v_MACADDR_t)) ;
Chilam Ng01120412013-02-19 18:32:21 -0800585 }
586
Hoonki Lee27511902013-03-14 18:19:06 -0700587 /* initialize TDLS pAdater context */
588 vos_mem_zero(pHddTdlsCtx, sizeof(tdlsCtx_t));
589
590 pHddTdlsCtx->pAdapter = pAdapter;
591
592 for (i = 0; i < 256; i++)
593 {
594 INIT_LIST_HEAD(&pHddTdlsCtx->peer_list[i]);
595 }
596
Hoonki Leed37cbb32013-04-20 00:31:14 -0700597 pHddTdlsCtx->curr_candidate = NULL;
598 pHddTdlsCtx->magic = 0;
599
600#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER
Chilam Ng01120412013-02-19 18:32:21 -0800601 vos_timer_init(&pHddTdlsCtx->peerDiscoverTimer,
602 VOS_TIMER_TYPE_SW,
603 wlan_hdd_tdls_discover_peer_cb,
604 pHddTdlsCtx);
Hoonki Leed37cbb32013-04-20 00:31:14 -0700605#endif
Chilam Ng01120412013-02-19 18:32:21 -0800606
607 vos_timer_init(&pHddTdlsCtx->peerUpdateTimer,
608 VOS_TIMER_TYPE_SW,
609 wlan_hdd_tdls_update_peer_cb,
610 pHddTdlsCtx);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700611 vos_timer_init(&pHddTdlsCtx->peerDiscoveryTimeoutTimer,
612 VOS_TIMER_TYPE_SW,
613 wlan_hdd_tdls_discovery_timeout_peer_cb,
614 pHddTdlsCtx);
Chilam Ng01120412013-02-19 18:32:21 -0800615
Hoonki Lee27511902013-03-14 18:19:06 -0700616 /* remember configuration even if it is not used right now. it could be used later */
617 pHddTdlsCtx->threshold_config.tx_period_t = pHddCtx->cfg_ini->fTDLSTxStatsPeriod;
618 pHddTdlsCtx->threshold_config.tx_packet_n = pHddCtx->cfg_ini->fTDLSTxPacketThreshold;
619 pHddTdlsCtx->threshold_config.discovery_period_t = pHddCtx->cfg_ini->fTDLSDiscoveryPeriod;
620 pHddTdlsCtx->threshold_config.discovery_tries_n = pHddCtx->cfg_ini->fTDLSMaxDiscoveryAttempt;
621 pHddTdlsCtx->threshold_config.idle_timeout_t = pHddCtx->cfg_ini->fTDLSIdleTimeout;
622 pHddTdlsCtx->threshold_config.idle_packet_n = pHddCtx->cfg_ini->fTDLSIdlePacketThreshold;
623 pHddTdlsCtx->threshold_config.rssi_hysteresis = pHddCtx->cfg_ini->fTDLSRSSIHysteresis;
624 pHddTdlsCtx->threshold_config.rssi_trigger_threshold = pHddCtx->cfg_ini->fTDLSRSSITriggerThreshold;
625 pHddTdlsCtx->threshold_config.rssi_teardown_threshold = pHddCtx->cfg_ini->fTDLSRSSITeardownThreshold;
Chilam NG571c65a2013-01-19 12:27:36 +0530626
Chilam Ng01120412013-02-19 18:32:21 -0800627 if (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger)
Hoonki Lee387663d2013-02-05 18:08:43 -0800628 {
Chilam Ng01120412013-02-19 18:32:21 -0800629 pHddCtx->tdls_mode = eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY;
Hoonki Leebf870f32013-01-19 15:53:30 +0530630 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS Implicit trigger not enabled!", __func__);
Hoonki Leebf870f32013-01-19 15:53:30 +0530631 }
Hoonki Lee27511902013-03-14 18:19:06 -0700632 else
633 {
634 pHddCtx->tdls_mode = eTDLS_SUPPORT_ENABLED;
Hoonki Lee27511902013-03-14 18:19:06 -0700635 }
636
637 return 0;
Chilam NG571c65a2013-01-19 12:27:36 +0530638}
639
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800640void wlan_hdd_tdls_exit(hdd_adapter_t *pAdapter)
Chilam NG571c65a2013-01-19 12:27:36 +0530641{
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800642 tdlsCtx_t *pHddTdlsCtx;
Hoonki Lee93e67ff2013-03-19 15:49:25 -0700643 hdd_context_t *pHddCtx;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800644
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800645 if (mutex_lock_interruptible(&tdls_lock))
646 {
647 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
648 "%s: unable to lock list", __func__);
649 return;
650 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800651
Hoonki Lee93e67ff2013-03-19 15:49:25 -0700652 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
653 if (NULL == pHddCtx)
654 {
655 mutex_unlock(&tdls_lock);
656 return;
657 }
658
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800659 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800660 if (NULL == pHddTdlsCtx)
661 {
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800662 mutex_unlock(&tdls_lock);
Hoonki Leebfee0342013-01-21 16:43:45 -0800663 hddLog(VOS_TRACE_LEVEL_WARN, "%s TDLS not enabled, exiting!", __func__);
664 return;
665 }
666
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800667 /* must stop timer here before freeing peer list, because peerIdleTimer is
668 part of peer list structure. */
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800669 wlan_hdd_tdls_timers_destroy(pHddTdlsCtx);
670 wlan_hdd_tdls_free_list(pHddTdlsCtx);
Chilam Nga75d8b62013-01-29 01:35:59 -0800671
Hoonki Lee93e67ff2013-03-19 15:49:25 -0700672 wlan_hdd_tdls_free_scan_request(&pHddCtx->tdls_scan_ctxt);
673
Chilam Nga75d8b62013-01-29 01:35:59 -0800674 vos_mem_free(pHddTdlsCtx);
675 pHddTdlsCtx = NULL;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800676 mutex_unlock(&tdls_lock);
Chilam NG571c65a2013-01-19 12:27:36 +0530677}
678
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800679/* stop all the tdls timers running */
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800680static void wlan_hdd_tdls_timers_stop(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800681{
682 int i;
683 struct list_head *head;
684 struct list_head *pos;
685 hddTdlsPeer_t *curr_peer;
686
Hoonki Leed37cbb32013-04-20 00:31:14 -0700687#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800688 vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer);
Hoonki Leed37cbb32013-04-20 00:31:14 -0700689#endif
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800690 vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700691 vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer);
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800692
693 for (i = 0; i < 256; i++)
694 {
695 head = &pHddTdlsCtx->peer_list[i];
696
697 list_for_each (pos, head) {
698 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
699
700 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800701 "%s: " MAC_ADDRESS_STR " -> stop idle timer",
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800702 __func__,
Chilam Ng01120412013-02-19 18:32:21 -0800703 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800704 vos_timer_stop ( &curr_peer->peerIdleTimer );
Hoonki Lee14621352013-04-16 17:51:19 -0700705 vos_timer_stop( &curr_peer->initiatorWaitTimeoutTimer );
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800706 }
707 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800708}
709
710/* destroy all the tdls timers running */
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800711static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800712{
713 int i;
714 struct list_head *head;
715 struct list_head *pos;
716 hddTdlsPeer_t *curr_peer;
717
Hoonki Leed37cbb32013-04-20 00:31:14 -0700718#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800719 vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer);
720 vos_timer_destroy(&pHddTdlsCtx->peerDiscoverTimer);
Hoonki Leed37cbb32013-04-20 00:31:14 -0700721#endif
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800722 vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer);
723 vos_timer_destroy(&pHddTdlsCtx->peerUpdateTimer);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700724 vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer);
725 vos_timer_destroy(&pHddTdlsCtx->peerDiscoveryTimeoutTimer);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800726
727 for (i = 0; i < 256; i++)
728 {
729 head = &pHddTdlsCtx->peer_list[i];
730
731 list_for_each (pos, head) {
732 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
733
734 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800735 "%s: " MAC_ADDRESS_STR " -> destroy idle timer",
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800736 __func__,
Chilam Ng01120412013-02-19 18:32:21 -0800737 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800738 vos_timer_stop ( &curr_peer->peerIdleTimer );
739 vos_timer_destroy ( &curr_peer->peerIdleTimer );
Hoonki Lee14621352013-04-16 17:51:19 -0700740 vos_timer_stop(&curr_peer->initiatorWaitTimeoutTimer);
741 vos_timer_destroy(&curr_peer->initiatorWaitTimeoutTimer);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800742 }
743 }
744}
745
Hoonki Lee387663d2013-02-05 18:08:43 -0800746/* if mac address exist, return pointer
747 if mac address doesn't exist, create a list and add, return pointer
748 return NULL if fails to get new mac address
749*/
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800750hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, u8 *mac)
Chilam NG571c65a2013-01-19 12:27:36 +0530751{
Hoonki Lee387663d2013-02-05 18:08:43 -0800752 struct list_head *head;
753 hddTdlsPeer_t *peer;
754 u8 key;
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -0700755 tdlsCtx_t *pHddTdlsCtx;
Hoonki Leebfee0342013-01-21 16:43:45 -0800756
Hoonki Lee387663d2013-02-05 18:08:43 -0800757 /* if already there, just update */
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800758 peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -0800759 if (peer != NULL)
760 {
761 return peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530762 }
763
Hoonki Lee387663d2013-02-05 18:08:43 -0800764 /* not found, allocate and add the list */
765 peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
766 if (NULL == peer) {
767 hddLog(VOS_TRACE_LEVEL_ERROR, "%s peer malloc failed!", __func__);
768 return NULL;
769 }
Chilam NG571c65a2013-01-19 12:27:36 +0530770
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800771 if (mutex_lock_interruptible(&tdls_lock))
Hoonki Lee387663d2013-02-05 18:08:43 -0800772 {
773 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -0700774 "%s: unable to lock list", __func__);
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -0700775 vos_mem_free(peer);
Hoonki Lee387663d2013-02-05 18:08:43 -0800776 return NULL;
777 }
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -0700778 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
779
780 if (NULL == pHddTdlsCtx)
781 {
782 vos_mem_free(peer);
783 mutex_unlock(&tdls_lock);
784 return NULL;
785 }
786
787 key = wlan_hdd_tdls_hash_key(mac);
788 head = &pHddTdlsCtx->peer_list[key];
Chilam NG571c65a2013-01-19 12:27:36 +0530789
Hoonki Lee387663d2013-02-05 18:08:43 -0800790 vos_mem_zero(peer, sizeof(hddTdlsPeer_t));
791 vos_mem_copy(peer->peerMac, mac, sizeof(peer->peerMac));
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800792 peer->pHddTdlsCtx = pHddTdlsCtx;
Hoonki Lee387663d2013-02-05 18:08:43 -0800793
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800794 vos_timer_init(&peer->peerIdleTimer,
795 VOS_TIMER_TYPE_SW,
796 wlan_hdd_tdls_idle_cb,
797 peer);
798
Hoonki Lee14621352013-04-16 17:51:19 -0700799 vos_timer_init(&peer->initiatorWaitTimeoutTimer,
800 VOS_TIMER_TYPE_SW,
801 wlan_hdd_tdls_initiator_wait_cb,
802 peer);
803
Hoonki Lee387663d2013-02-05 18:08:43 -0800804 list_add_tail(&peer->node, head);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800805 mutex_unlock(&tdls_lock);
Hoonki Lee387663d2013-02-05 18:08:43 -0800806
807 return peer;
808}
809
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700810int wlan_hdd_tdls_set_cap(hdd_adapter_t *pAdapter,
Hoonki Lee27511902013-03-14 18:19:06 -0700811 u8* mac,
812 tTDLSCapType cap)
813{
814 hddTdlsPeer_t *curr_peer;
815
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700816 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee27511902013-03-14 18:19:06 -0700817 if (curr_peer == NULL)
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700818 return -1;
Hoonki Lee27511902013-03-14 18:19:06 -0700819
820 curr_peer->tdls_support = cap;
821
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700822 return 0;
Hoonki Lee27511902013-03-14 18:19:06 -0700823}
824
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800825void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer, tTDLSLinkStatus status)
Hoonki Lee387663d2013-02-05 18:08:43 -0800826{
827 if (curr_peer == NULL)
828 return;
829
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800830 hddLog(VOS_TRACE_LEVEL_WARN, "tdls set peer " MAC_ADDRESS_STR " link status to %u",
Chilam Ng01120412013-02-19 18:32:21 -0800831 MAC_ADDR_ARRAY(curr_peer->peerMac), status);
Chilam NG571c65a2013-01-19 12:27:36 +0530832
833 curr_peer->link_status = status;
834
Chilam NG571c65a2013-01-19 12:27:36 +0530835}
836
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800837void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter,
838 u8* mac,
839 tTDLSLinkStatus linkStatus)
840{
841 hddTdlsPeer_t *curr_peer;
842
843 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
844 if (curr_peer == NULL)
845 return;
846
847 curr_peer->link_status= linkStatus;
848
849 return;
850}
851
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800852int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter, u8 *mac)
Chilam NG571c65a2013-01-19 12:27:36 +0530853{
854 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700855 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Chilam NG571c65a2013-01-19 12:27:36 +0530856
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800857 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700858
859 if (NULL == curr_peer)
Hoonki Lee387663d2013-02-05 18:08:43 -0800860 return -1;
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700861
862 if (pHddTdlsCtx->discovery_sent_cnt)
863 pHddTdlsCtx->discovery_sent_cnt--;
864
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700865 wlan_hdd_tdls_check_power_save_prohibited(pAdapter);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700866 if (0 == pHddTdlsCtx->discovery_sent_cnt)
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700867 {
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700868 vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700869 }
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700870
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800871 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700872 "Discovery(%lu) Response from " MAC_ADDRESS_STR " link_status %d",
873 pHddTdlsCtx->discovery_sent_cnt, MAC_ADDR_ARRAY(curr_peer->peerMac),
874 curr_peer->link_status);
875
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800876 if (eTDLS_LINK_DISCOVERING == curr_peer->link_status)
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800877 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -0700878 /* Since we are here, it means Throughput threshold is alredy met. Make sure RSSI
879 threshold is also met before setting up TDLS link*/
880 if ((tANI_S32) curr_peer->rssi > (tANI_S32) pHddTdlsCtx->threshold_config.rssi_trigger_threshold)
881 {
882 curr_peer->link_status = eTDLS_LINK_DISCOVERED;
883 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
884 "Rssi Threshold met: "MAC_ADDRESS_STR" rssi = %d threshold= %d" ,
885 MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->rssi,
886 pHddTdlsCtx->threshold_config.rssi_trigger_threshold);
887 cfg80211_tdls_oper_request(pAdapter->dev, curr_peer->peerMac, NL80211_TDLS_SETUP, FALSE, GFP_KERNEL);
888 }
889 else
890 {
891 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
892 "Rssi Threshold not met: "MAC_ADDRESS_STR" rssi = %d threshold = %d ",
893 MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->rssi,
894 pHddTdlsCtx->threshold_config.rssi_trigger_threshold);
895 curr_peer->link_status = eTDLS_LINK_IDLE;
896 }
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800897 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700898 else
899 {
900 wlan_hdd_tdls_check_bmps(pAdapter);
901 }
Chilam NG571c65a2013-01-19 12:27:36 +0530902
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800903 curr_peer->tdls_support = eTDLS_CAP_SUPPORTED;
Hoonki Lee387663d2013-02-05 18:08:43 -0800904 return 0;
Chilam NG571c65a2013-01-19 12:27:36 +0530905}
906
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +0530907int wlan_hdd_tdls_set_peer_caps(hdd_adapter_t *pAdapter,
908 u8 *mac,
909 tANI_U8 uapsdQueues,
910 tANI_U8 maxSp,
911 tANI_BOOLEAN isBufSta)
912{
913 hddTdlsPeer_t *curr_peer;
914
915 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
916 if (curr_peer == NULL)
917 return -1;
918
919 curr_peer->uapsdQueues = uapsdQueues;
920 curr_peer->maxSp = maxSp;
921 curr_peer->isBufSta = isBufSta;
922 return 0;
923}
924
925int wlan_hdd_tdls_get_link_establish_params(hdd_adapter_t *pAdapter, u8 *mac,
926 tCsrTdlsLinkEstablishParams* tdlsLinkEstablishParams)
927{
928 hddTdlsPeer_t *curr_peer;
929
930 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
931 if (curr_peer == NULL)
932 return -1;
933
934 tdlsLinkEstablishParams->isResponder = curr_peer->is_responder;
935 tdlsLinkEstablishParams->uapsdQueues = curr_peer->uapsdQueues;
936 tdlsLinkEstablishParams->maxSp = curr_peer->maxSp;
937 tdlsLinkEstablishParams->isBufSta = curr_peer->isBufSta;
938 return 0;
939}
940
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800941int wlan_hdd_tdls_set_rssi(hdd_adapter_t *pAdapter, u8 *mac, tANI_S8 rxRssi)
Chilam NG571c65a2013-01-19 12:27:36 +0530942{
943 hddTdlsPeer_t *curr_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530944
Shailender Karmuchi13c0d082013-03-26 14:41:39 -0700945 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -0800946 if (curr_peer == NULL)
947 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530948
949 curr_peer->rssi = rxRssi;
950
Hoonki Lee387663d2013-02-05 18:08:43 -0800951 return 0;
Chilam NG571c65a2013-01-19 12:27:36 +0530952}
953
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800954int wlan_hdd_tdls_set_responder(hdd_adapter_t *pAdapter, u8 *mac, tANI_U8 responder)
Hoonki Leea34dd892013-02-05 22:56:02 -0800955{
956 hddTdlsPeer_t *curr_peer;
957
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800958 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800959 if (curr_peer == NULL)
Hoonki Leea34dd892013-02-05 22:56:02 -0800960 return -1;
961
962 curr_peer->is_responder = responder;
963
964 return 0;
965}
966
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800967int wlan_hdd_tdls_get_responder(hdd_adapter_t *pAdapter, u8 *mac)
Hoonki Leea34dd892013-02-05 22:56:02 -0800968{
969 hddTdlsPeer_t *curr_peer;
970
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800971 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800972 if (curr_peer == NULL)
Hoonki Leea34dd892013-02-05 22:56:02 -0800973 return -1;
974
975 return (curr_peer->is_responder);
976}
977
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800978int wlan_hdd_tdls_set_signature(hdd_adapter_t *pAdapter, u8 *mac, tANI_U8 uSignature)
Hoonki Lee11f7dda2013-02-14 16:55:44 -0800979{
980 hddTdlsPeer_t *curr_peer;
981
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800982 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee11f7dda2013-02-14 16:55:44 -0800983 if (curr_peer == NULL)
984 return -1;
985
986 curr_peer->signature = uSignature;
987
988 return 0;
989}
990
Hoonki Leea34dd892013-02-05 22:56:02 -0800991
Hoonki Lee387663d2013-02-05 18:08:43 -0800992void wlan_hdd_tdls_extract_da(struct sk_buff *skb, u8 *mac)
Chilam NG571c65a2013-01-19 12:27:36 +0530993{
Chilam NG571c65a2013-01-19 12:27:36 +0530994 memcpy(mac, skb->data, 6);
Chilam NG571c65a2013-01-19 12:27:36 +0530995}
996
Hoonki Lee387663d2013-02-05 18:08:43 -0800997void wlan_hdd_tdls_extract_sa(struct sk_buff *skb, u8 *mac)
Chilam Ng1279e232013-01-25 15:06:52 -0800998{
Chilam Ng1279e232013-01-25 15:06:52 -0800999 memcpy(mac, skb->data+6, 6);
Chilam Ng1279e232013-01-25 15:06:52 -08001000}
1001
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001002int wlan_hdd_tdls_increment_pkt_count(hdd_adapter_t *pAdapter, u8 *mac, u8 tx)
Chilam NG571c65a2013-01-19 12:27:36 +05301003{
Hoonki Lee387663d2013-02-05 18:08:43 -08001004 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001005 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam NG571c65a2013-01-19 12:27:36 +05301006
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001007 if (eTDLS_SUPPORT_ENABLED != pHddCtx->tdls_mode)
1008 return -1;
Hoonki Leebfee0342013-01-21 16:43:45 -08001009
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001010 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -08001011 if (curr_peer == NULL)
Chilam NG571c65a2013-01-19 12:27:36 +05301012 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +05301013
Chilam Ng1279e232013-01-25 15:06:52 -08001014 if (tx)
1015 curr_peer->tx_pkt++;
1016 else
1017 curr_peer->rx_pkt++;
Chilam NG571c65a2013-01-19 12:27:36 +05301018
Chilam NG571c65a2013-01-19 12:27:36 +05301019 return 0;
1020}
1021
Hoonki Lee27511902013-03-14 18:19:06 -07001022static int wlan_hdd_tdls_check_config(tdls_config_params_t *config)
1023{
1024 if (config->tdls > 2)
1025 {
1026 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 1st argument %d. <0...2>", __func__, config->tdls);
1027 return -1;
1028 }
1029 if (config->tx_period_t < CFG_TDLS_TX_STATS_PERIOD_MIN ||
1030 config->tx_period_t > CFG_TDLS_TX_STATS_PERIOD_MAX)
1031 {
1032 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 2nd argument %d. <%d...%d>", __func__, config->tx_period_t,
1033 CFG_TDLS_TX_STATS_PERIOD_MIN, CFG_TDLS_TX_STATS_PERIOD_MAX);
1034 return -1;
1035 }
1036 if (config->tx_packet_n < CFG_TDLS_TX_PACKET_THRESHOLD_MIN ||
1037 config->tx_packet_n > CFG_TDLS_TX_PACKET_THRESHOLD_MAX)
1038 {
1039 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 3rd argument %d. <%d...%d>", __func__, config->tx_packet_n,
1040 CFG_TDLS_TX_PACKET_THRESHOLD_MIN, CFG_TDLS_TX_PACKET_THRESHOLD_MAX);
1041 return -1;
1042 }
1043 if (config->discovery_period_t < CFG_TDLS_DISCOVERY_PERIOD_MIN ||
1044 config->discovery_period_t > CFG_TDLS_DISCOVERY_PERIOD_MAX)
1045 {
1046 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 4th argument %d. <%d...%d>", __func__, config->discovery_period_t,
1047 CFG_TDLS_DISCOVERY_PERIOD_MIN, CFG_TDLS_DISCOVERY_PERIOD_MAX);
1048 return -1;
1049 }
1050 if (config->discovery_tries_n < CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MIN ||
1051 config->discovery_tries_n > CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MAX)
1052 {
1053 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 5th argument %d. <%d...%d>", __func__, config->discovery_tries_n,
1054 CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MIN, CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MAX);
1055 return -1;
1056 }
1057 if (config->idle_timeout_t < CFG_TDLS_IDLE_TIMEOUT_MIN ||
1058 config->idle_timeout_t > CFG_TDLS_IDLE_TIMEOUT_MAX)
1059 {
1060 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 6th argument %d. <%d...%d>", __func__, config->idle_timeout_t,
1061 CFG_TDLS_IDLE_TIMEOUT_MIN, CFG_TDLS_IDLE_TIMEOUT_MAX);
1062 return -1;
1063 }
1064 if (config->idle_packet_n < CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN ||
1065 config->idle_packet_n > CFG_TDLS_IDLE_PACKET_THRESHOLD_MAX)
1066 {
1067 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 7th argument %d. <%d...%d>", __func__, config->idle_packet_n,
1068 CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN, CFG_TDLS_IDLE_PACKET_THRESHOLD_MAX);
1069 return -1;
1070 }
1071 if (config->rssi_hysteresis < CFG_TDLS_RSSI_HYSTERESIS_MIN ||
1072 config->rssi_hysteresis > CFG_TDLS_RSSI_HYSTERESIS_MAX)
1073 {
1074 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 8th argument %d. <%d...%d>", __func__, config->rssi_hysteresis,
1075 CFG_TDLS_RSSI_HYSTERESIS_MIN, CFG_TDLS_RSSI_HYSTERESIS_MAX);
1076 return -1;
1077 }
1078 if (config->rssi_trigger_threshold < CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MIN ||
1079 config->rssi_trigger_threshold > CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MAX)
1080 {
1081 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 9th argument %d. <%d...%d>", __func__, config->rssi_trigger_threshold,
1082 CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MIN, CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MAX);
1083 return -1;
1084 }
1085 if (config->rssi_teardown_threshold < CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN ||
1086 config->rssi_teardown_threshold > CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX)
1087 {
1088 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 10th argument %d. <%d...%d>", __func__, config->rssi_teardown_threshold,
1089 CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN, CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX);
1090 return -1;
1091 }
1092 return 0;
1093}
1094
Chilam Ng01120412013-02-19 18:32:21 -08001095int wlan_hdd_tdls_set_params(struct net_device *dev, tdls_config_params_t *config)
Chilam NG571c65a2013-01-19 12:27:36 +05301096{
Chilam Ng01120412013-02-19 18:32:21 -08001097 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1098 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001099 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Hoonki Lee27511902013-03-14 18:19:06 -07001100 eTDLSSupportMode req_tdls_mode;
Hoonki Leebfee0342013-01-21 16:43:45 -08001101
Hoonki Lee27511902013-03-14 18:19:06 -07001102 if (NULL == pHddTdlsCtx)
1103 {
1104 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS not enabled!", __func__);
1105 return -1;
Chilam Ng01120412013-02-19 18:32:21 -08001106 }
Chilam NG571c65a2013-01-19 12:27:36 +05301107
Hoonki Lee27511902013-03-14 18:19:06 -07001108 if (wlan_hdd_tdls_check_config(config) != 0)
1109 {
1110 return -1;
1111 }
1112
1113 /* config->tdls is mapped to 0->1, 1->2, 2->3 */
1114 req_tdls_mode = config->tdls + 1;
1115 if (pHddCtx->tdls_mode == req_tdls_mode)
1116 {
1117 hddLog(VOS_TRACE_LEVEL_ERROR, "%s already in mode %d", __func__, config->tdls);
1118 return -1;
1119 }
1120
1121 /* copy the configuration only when given tdls mode is implicit trigger enable */
1122 if (eTDLS_SUPPORT_ENABLED == req_tdls_mode)
1123 {
Chilam Ng01120412013-02-19 18:32:21 -08001124 memcpy(&pHddTdlsCtx->threshold_config, config, sizeof(tdls_config_params_t));
1125 }
Chilam NG571c65a2013-01-19 12:27:36 +05301126
Chilam Ng01120412013-02-19 18:32:21 -08001127 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1128 "iw set tdls params: %d %d %d %d %d %d %d %d %d %d",
1129 config->tdls,
1130 config->tx_period_t,
1131 config->tx_packet_n,
1132 config->discovery_period_t,
1133 config->discovery_tries_n,
1134 config->idle_timeout_t,
1135 config->idle_packet_n,
1136 config->rssi_hysteresis,
1137 config->rssi_trigger_threshold,
1138 config->rssi_teardown_threshold);
Chilam NG571c65a2013-01-19 12:27:36 +05301139
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07001140 wlan_hdd_tdls_set_mode(pHddCtx, req_tdls_mode, TRUE);
Chilam Ng01120412013-02-19 18:32:21 -08001141
Chilam NG571c65a2013-01-19 12:27:36 +05301142 return 0;
1143}
1144
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001145int wlan_hdd_tdls_set_sta_id(hdd_adapter_t *pAdapter, u8 *mac, u8 staId)
Kiran V1ccee932012-12-12 14:49:46 -08001146{
Hoonki Lee387663d2013-02-05 18:08:43 -08001147 hddTdlsPeer_t *curr_peer;
Kiran V1ccee932012-12-12 14:49:46 -08001148
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001149 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -08001150 if (curr_peer == NULL)
Chilam NG571c65a2013-01-19 12:27:36 +05301151 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +05301152
Hoonki Lee387663d2013-02-05 18:08:43 -08001153 curr_peer->staId = staId;
Chilam NG571c65a2013-01-19 12:27:36 +05301154
1155 return 0;
Kiran V1ccee932012-12-12 14:49:46 -08001156}
1157
Hoonki Lee387663d2013-02-05 18:08:43 -08001158/* if peerMac is found, then it returns pointer to hddTdlsPeer_t
1159 otherwise, it returns NULL
1160*/
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001161hddTdlsPeer_t *wlan_hdd_tdls_find_peer(hdd_adapter_t *pAdapter, u8 *mac)
Kiran V1ccee932012-12-12 14:49:46 -08001162{
Hoonki Lee387663d2013-02-05 18:08:43 -08001163 u8 key;
1164 struct list_head *pos;
1165 struct list_head *head;
1166 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001167 tdlsCtx_t *pHddTdlsCtx;
Hoonki Lee387663d2013-02-05 18:08:43 -08001168
Hoonki Lee387663d2013-02-05 18:08:43 -08001169
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001170 if (mutex_lock_interruptible(&tdls_lock))
Hoonki Lee387663d2013-02-05 18:08:43 -08001171 {
1172 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1173 "%s: unable to lock list", __func__);
1174 return NULL;
1175 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001176 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001177 if (NULL == pHddTdlsCtx)
1178 {
1179 mutex_unlock(&tdls_lock);
1180 return NULL;
1181 }
1182
1183 key = wlan_hdd_tdls_hash_key(mac);
1184
1185 head = &pHddTdlsCtx->peer_list[key];
Hoonki Lee387663d2013-02-05 18:08:43 -08001186
1187 list_for_each(pos, head) {
1188 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
1189 if (!memcmp(mac, curr_peer->peerMac, 6)) {
1190 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1191 "findTdlsPeer: found staId %d", curr_peer->staId);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001192 mutex_unlock(&tdls_lock);
Hoonki Lee387663d2013-02-05 18:08:43 -08001193 return curr_peer;
1194 }
1195 }
1196
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001197 mutex_unlock(&tdls_lock);
Hoonki Lee387663d2013-02-05 18:08:43 -08001198 return NULL;
1199}
1200
Hoonki Leea6d49be2013-04-05 09:43:25 -07001201hddTdlsPeer_t *wlan_hdd_tdls_find_all_peer(hdd_context_t *pHddCtx, u8 *mac)
1202{
1203 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1204 hdd_adapter_t *pAdapter = NULL;
1205 tdlsCtx_t *pHddTdlsCtx = NULL;
1206 hddTdlsPeer_t *curr_peer= NULL;
1207 VOS_STATUS status = 0;
1208
1209 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1210 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1211 {
1212 pAdapter = pAdapterNode->pAdapter;
1213
1214 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
1215 if (NULL != pHddTdlsCtx)
1216 {
1217 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
1218 if (curr_peer)
1219 return curr_peer;
1220 }
1221 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1222 pAdapterNode = pNext;
1223 }
1224 return curr_peer;
1225}
1226
1227
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001228int wlan_hdd_tdls_reset_peer(hdd_adapter_t *pAdapter, u8 *mac)
Hoonki Lee387663d2013-02-05 18:08:43 -08001229{
Chilam Ng01120412013-02-19 18:32:21 -08001230 hdd_context_t *pHddCtx;
Chilam NG571c65a2013-01-19 12:27:36 +05301231 hddTdlsPeer_t *curr_peer;
Kiran V1ccee932012-12-12 14:49:46 -08001232
Chilam Ng01120412013-02-19 18:32:21 -08001233 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1234
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001235 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -08001236 if (curr_peer == NULL)
1237 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +05301238
Gopichand Nakkala901e8922013-03-04 23:45:58 -08001239 curr_peer->link_status = eTDLS_LINK_IDLE;
Hoonki Leecdd8e962013-01-20 00:45:46 -08001240 curr_peer->staId = 0;
Hoonki Lee387663d2013-02-05 18:08:43 -08001241
Chilam Ng01120412013-02-19 18:32:21 -08001242 if(eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) {
Chilam Nga75d8b62013-01-29 01:35:59 -08001243 vos_timer_stop( &curr_peer->peerIdleTimer );
Chilam Nga75d8b62013-01-29 01:35:59 -08001244 }
Hoonki Lee387663d2013-02-05 18:08:43 -08001245 return 0;
Hoonki Leecdd8e962013-01-20 00:45:46 -08001246}
1247
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001248/* Caller has to take the lock before calling this function */
Hoonki Lee27511902013-03-14 18:19:06 -07001249static void wlan_tdd_tdls_reset_tx_rx(tdlsCtx_t *pHddTdlsCtx)
1250{
1251 int i;
1252 struct list_head *head;
1253 hddTdlsPeer_t *tmp;
1254 struct list_head *pos, *q;
1255
Hoonki Lee27511902013-03-14 18:19:06 -07001256 for (i = 0; i < 256; i++) {
1257 head = &pHddTdlsCtx->peer_list[i];
1258 list_for_each_safe (pos, q, head) {
1259 tmp = list_entry(pos, hddTdlsPeer_t, node);
1260 tmp->tx_pkt = 0;
1261 tmp->rx_pkt = 0;
1262 }
1263 }
Hoonki Lee27511902013-03-14 18:19:06 -07001264
1265 return ;
1266}
1267
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001268/* Caller has to take the lock before calling this function */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001269static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001270{
1271 int i;
1272 struct list_head *head;
1273 hddTdlsPeer_t *tmp;
1274 struct list_head *pos, *q;
1275
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001276 pHddTdlsCtx->discovery_peer_cnt = 0;
1277
1278 for (i = 0; i < 256; i++) {
1279 head = &pHddTdlsCtx->peer_list[i];
1280 list_for_each_safe (pos, q, head) {
1281 tmp = list_entry(pos, hddTdlsPeer_t, node);
1282 tmp->discovery_processed = 0;
1283 }
1284 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001285
1286 return 0;
1287}
1288
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001289static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001290{
1291 int i;
1292 struct list_head *head;
1293 struct list_head *pos, *q;
1294 int discovery_peer_cnt=0;
1295 hddTdlsPeer_t *tmp;
1296
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001297 /*
1298 * This function expects the callers to acquire the Mutex.
1299 */
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001300
1301 for (i = 0; i < 256; i++) {
1302 head = &pHddTdlsCtx->peer_list[i];
1303 list_for_each_safe (pos, q, head) {
1304 tmp = list_entry(pos, hddTdlsPeer_t, node);
1305 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -08001306 "%s, %d, " MAC_ADDRESS_STR, __func__, i,
1307 MAC_ADDR_ARRAY(tmp->peerMac));
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001308 discovery_peer_cnt++;
1309 }
1310 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001311 return discovery_peer_cnt;
1312}
1313
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001314tANI_U16 wlan_hdd_tdlsConnectedPeers(hdd_adapter_t *pAdapter)
Lee Hoonkic1262f22013-01-24 21:59:00 -08001315{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001316 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1317
1318 if (NULL == pHddCtx)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001319 return 0;
Lee Hoonkic1262f22013-01-24 21:59:00 -08001320
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001321 return pHddCtx->connected_peer_count;
Lee Hoonkic1262f22013-01-24 21:59:00 -08001322}
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001323
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001324int wlan_hdd_tdls_get_all_peers(hdd_adapter_t *pAdapter, char *buf, int buflen)
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001325{
1326 int i;
1327 int len, init_len;
Hoonki Lee387663d2013-02-05 18:08:43 -08001328 struct list_head *head;
1329 struct list_head *pos;
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001330 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001331 tdlsCtx_t *pHddTdlsCtx;
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001332
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001333
1334 init_len = buflen;
1335 len = snprintf(buf, buflen, "\n%-18s%-3s%-4s%-3s%-5s\n", "MAC", "Id", "cap", "up", "RSSI");
1336 buf += len;
1337 buflen -= len;
1338 /* 1234567890123456789012345678901234567 */
1339 len = snprintf(buf, buflen, "---------------------------------\n");
1340 buf += len;
1341 buflen -= len;
1342
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001343 if (mutex_lock_interruptible(&tdls_lock))
Gopichand Nakkala91b09262013-02-10 14:27:02 -08001344 {
1345 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1346 "%s: unable to lock list", __func__);
1347 return init_len-buflen;
1348 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001349 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001350 if (NULL == pHddTdlsCtx) {
1351 mutex_unlock(&tdls_lock);
1352 len = snprintf(buf, buflen, "TDLS not enabled\n");
1353 return len;
1354 }
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001355 for (i = 0; i < 256; i++) {
Hoonki Lee387663d2013-02-05 18:08:43 -08001356 head = &pHddTdlsCtx->peer_list[i];
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001357
Hoonki Lee387663d2013-02-05 18:08:43 -08001358 list_for_each(pos, head) {
1359 curr_peer= list_entry (pos, hddTdlsPeer_t, node);
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001360
Hoonki Lee387663d2013-02-05 18:08:43 -08001361 if (buflen < 32+1)
1362 break;
1363 len = snprintf(buf, buflen,
Chilam Ng01120412013-02-19 18:32:21 -08001364 MAC_ADDRESS_STR"%3d%4s%3s%5d\n",
1365 MAC_ADDR_ARRAY(curr_peer->peerMac),
Hoonki Lee387663d2013-02-05 18:08:43 -08001366 curr_peer->staId,
1367 (curr_peer->tdls_support == eTDLS_CAP_SUPPORTED) ? "Y":"N",
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07001368 TDLS_IS_CONNECTED(curr_peer) ? "Y":"N",
Hoonki Lee387663d2013-02-05 18:08:43 -08001369 curr_peer->rssi);
1370 buf += len;
1371 buflen -= len;
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001372 }
1373 }
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001374 mutex_unlock(&tdls_lock);
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001375 return init_len-buflen;
1376}
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001377
1378void wlan_hdd_tdls_connection_callback(hdd_adapter_t *pAdapter)
1379{
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001380 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001381 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001382
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001383 if (mutex_lock_interruptible(&tdls_lock))
1384 {
1385 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1386 "%s: unable to lock list", __func__);
1387 return;
1388 }
1389
1390 if (NULL == pHddCtx || NULL == pHddTdlsCtx)
1391 {
1392 mutex_unlock(&tdls_lock);
1393 return;
1394 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001395
1396 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1397 "%s, update %d discover %d", __func__,
1398 pHddTdlsCtx->threshold_config.tx_period_t,
1399 pHddTdlsCtx->threshold_config.discovery_period_t);
1400
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05301401#ifdef FEATURE_WLAN_TDLS_OXYGEN_DISAPPEAR_AP
1402 pHddTdlsCtx->defer_link_lost_indication = FALSE;
1403#endif
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001404 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode)
1405 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001406 wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001407 pHddTdlsCtx->discovery_sent_cnt = 0;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001408 wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001409
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001410#ifdef FEATURE_WLAN_TDLS_INTERNAL
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001411 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
1412 &pHddTdlsCtx->peerDiscoverTimer,
1413 pHddTdlsCtx->threshold_config.discovery_period_t);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001414#endif
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001415 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
1416 &pHddTdlsCtx->peerUpdateTimer,
1417 pHddTdlsCtx->threshold_config.tx_period_t);
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001418 }
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001419 mutex_unlock(&tdls_lock);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001420
1421}
1422
1423void wlan_hdd_tdls_disconnection_callback(hdd_adapter_t *pAdapter)
1424{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001425 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001426
1427 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s", __func__);
1428
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001429 if (mutex_lock_interruptible(&tdls_lock))
1430 {
1431 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1432 "%s: unable to lock list", __func__);
1433 return;
1434 }
1435 if (NULL == pHddTdlsCtx)
1436 {
1437 mutex_unlock(&tdls_lock);
1438 return;
1439 }
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05301440#ifdef FEATURE_WLAN_TDLS_OXYGEN_DISAPPEAR_AP
1441 pHddTdlsCtx->defer_link_lost_indication = FALSE;
1442#endif
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001443 pHddTdlsCtx->discovery_sent_cnt = 0;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001444 wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001445
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001446 wlan_hdd_tdls_timers_stop(pHddTdlsCtx);
1447 wlan_hdd_tdls_free_list(pHddTdlsCtx);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001448
1449 mutex_unlock(&tdls_lock);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001450}
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001451
1452void wlan_hdd_tdls_mgmt_completion_callback(hdd_adapter_t *pAdapter, tANI_U32 statusCode)
1453{
1454 pAdapter->mgmtTxCompletionStatus = statusCode;
1455 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s: Mgmt TX Completion %d",
1456 __func__, statusCode);
1457 complete(&pAdapter->tdls_mgmt_comp);
1458}
1459
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001460void wlan_hdd_tdls_increment_peer_count(hdd_adapter_t *pAdapter)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001461{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001462 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001463
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001464 if (NULL == pHddCtx) return;
1465
1466 pHddCtx->connected_peer_count++;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001467 wlan_hdd_tdls_check_power_save_prohibited(pAdapter);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001468
1469 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: %d",
1470 __func__, pHddCtx->connected_peer_count);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001471}
1472
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001473void wlan_hdd_tdls_decrement_peer_count(hdd_adapter_t *pAdapter)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001474{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001475 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001476
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001477 if (NULL == pHddCtx) return;
1478
1479 if (pHddCtx->connected_peer_count)
1480 pHddCtx->connected_peer_count--;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001481 wlan_hdd_tdls_check_power_save_prohibited(pAdapter);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001482
1483 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: %d",
1484 __func__, pHddCtx->connected_peer_count);
1485
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001486}
1487
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001488void wlan_hdd_tdls_check_bmps(hdd_adapter_t *pAdapter)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001489{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001490 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001491 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Hoonki Lee14621352013-04-16 17:51:19 -07001492 hddTdlsPeer_t *curr_peer;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001493
Gopichand Nakkala16c02842013-03-18 12:31:35 -07001494 if ((NULL == pHddCtx) || (NULL == pHddTdlsCtx)) return;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001495
Hoonki Lee14621352013-04-16 17:51:19 -07001496 curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, TRUE);
1497 if (NULL != curr_peer)
1498 {
1499 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1500 "%s: tdls in progress. Dont check for BMPS " MAC_ADDRESS_STR,
1501 __func__, MAC_ADDR_ARRAY (curr_peer->peerMac));
1502 return;
1503 }
1504
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001505 if ((TDLS_CTX_MAGIC != pHddCtx->tdls_scan_ctxt.magic) &&
1506 (0 == pHddCtx->connected_peer_count) &&
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001507 (0 == pHddTdlsCtx->discovery_sent_cnt))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001508 {
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001509 if (FALSE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
1510 {
1511 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001512 "%s: No TDLS peer connected/discovery sent. Enable BMPS",
1513 __func__);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001514 hdd_enable_bmps_imps(pHddCtx);
1515 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001516 }
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001517 else
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001518 {
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001519 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
1520 {
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001521 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1522 "%s: TDLS peer connected. Disable BMPS", __func__);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001523 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
1524 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001525 }
1526 return;
1527}
1528
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001529u8 wlan_hdd_tdls_is_peer_progress(hdd_adapter_t *pAdapter, u8 *mac)
1530{
1531 hddTdlsPeer_t *curr_peer;
1532
1533 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
1534 if (curr_peer == NULL)
1535 return 0;
1536
1537 return (eTDLS_LINK_CONNECTING == curr_peer->link_status);
1538}
1539
Hoonki Leefb8df672013-04-10 18:20:34 -07001540/* return pointer to hddTdlsPeer_t if TDLS is ongoing. Otherwise return NULL.
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001541 * mac - if NULL check for all the peer list, otherwise, skip this mac when skip_self is TRUE
1542 * skip_self - if TRUE, skip this mac. otherwise, check all the peer list. if
1543 mac is NULL, this argument is ignored, and check for all the peer list.
1544 */
Hoonki Leefb8df672013-04-10 18:20:34 -07001545static hddTdlsPeer_t *wlan_hdd_tdls_find_progress_peer(hdd_adapter_t *pAdapter, u8 *mac, u8 skip_self, tANI_BOOLEAN mutexLock)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001546{
1547 int i;
1548 struct list_head *head;
1549 hddTdlsPeer_t *curr_peer;
1550 struct list_head *pos;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001551 tdlsCtx_t *pHddTdlsCtx;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001552
Hoonki Leefb8df672013-04-10 18:20:34 -07001553 if (mutexLock)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001554 {
Hoonki Leefb8df672013-04-10 18:20:34 -07001555 if (mutex_lock_interruptible(&tdls_lock))
1556 {
1557 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001558 "%s: unable to lock list", __func__);
Hoonki Leefb8df672013-04-10 18:20:34 -07001559 return NULL;
1560 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001561 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001562 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001563 if (NULL == pHddTdlsCtx)
1564 {
Hoonki Leefb8df672013-04-10 18:20:34 -07001565 if (mutexLock)
1566 mutex_unlock(&tdls_lock);
1567 return NULL;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001568 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001569
1570 for (i = 0; i < 256; i++) {
1571 head = &pHddTdlsCtx->peer_list[i];
1572 list_for_each(pos, head) {
1573 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
1574 if (skip_self && mac && !memcmp(mac, curr_peer->peerMac, 6)) {
1575 continue;
1576 }
1577 else
1578 {
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08001579 if (eTDLS_LINK_CONNECTING == curr_peer->link_status)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001580 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07001581 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001582 "%s:" MAC_ADDRESS_STR " eTDLS_LINK_CONNECTING",
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07001583 __func__, MAC_ADDR_ARRAY(curr_peer->peerMac));
Hoonki Leefb8df672013-04-10 18:20:34 -07001584 if (mutexLock)
1585 mutex_unlock(&tdls_lock);
1586 return curr_peer;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001587 }
1588 }
1589 }
1590 }
1591
Hoonki Leefb8df672013-04-10 18:20:34 -07001592 if (mutexLock)
1593 mutex_unlock(&tdls_lock);
1594 return NULL;
1595}
1596
1597hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx, u8 *mac, u8 skip_self, tANI_BOOLEAN mutexLock)
1598{
1599 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1600 hdd_adapter_t *pAdapter = NULL;
1601 tdlsCtx_t *pHddTdlsCtx = NULL;
1602 hddTdlsPeer_t *curr_peer= NULL;
1603 VOS_STATUS status = 0;
1604
1605 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1606 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1607 {
1608 pAdapter = pAdapterNode->pAdapter;
1609
1610 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
1611 if (NULL != pHddTdlsCtx)
1612 {
1613 curr_peer = wlan_hdd_tdls_find_progress_peer(pAdapter, mac, skip_self, mutexLock);
1614 if (curr_peer)
1615 return curr_peer;
1616 }
1617 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1618 pAdapterNode = pNext;
1619 }
1620 return NULL;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001621}
Hoonki Lee27511902013-03-14 18:19:06 -07001622
1623static void wlan_hdd_tdls_implicit_disable(tdlsCtx_t *pHddTdlsCtx)
1624{
Hoonki Lee27511902013-03-14 18:19:06 -07001625 wlan_hdd_tdls_timers_stop(pHddTdlsCtx);
Hoonki Lee27511902013-03-14 18:19:06 -07001626}
1627
1628static void wlan_hdd_tdls_implicit_enable(tdlsCtx_t *pHddTdlsCtx)
1629{
1630 wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001631 pHddTdlsCtx->discovery_sent_cnt = 0;
Hoonki Lee27511902013-03-14 18:19:06 -07001632 wlan_tdd_tdls_reset_tx_rx(pHddTdlsCtx);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001633 wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001634
Hoonki Lee27511902013-03-14 18:19:06 -07001635
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001636#ifdef FEATURE_WLAN_TDLS_INTERNAL
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001637 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
1638 &pHddTdlsCtx->peerDiscoverTimer,
1639 pHddTdlsCtx->threshold_config.discovery_period_t);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001640#endif
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001641 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
1642 &pHddTdlsCtx->peerUpdateTimer,
1643 pHddTdlsCtx->threshold_config.tx_period_t);
Hoonki Lee27511902013-03-14 18:19:06 -07001644}
1645
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07001646void wlan_hdd_tdls_set_mode(hdd_context_t *pHddCtx,
1647 eTDLSSupportMode tdls_mode,
1648 v_BOOL_t bUpdateLast)
Hoonki Lee27511902013-03-14 18:19:06 -07001649{
1650 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1651 VOS_STATUS status;
1652 hdd_adapter_t *pAdapter;
1653 tdlsCtx_t *pHddTdlsCtx;
1654
1655 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s mode %d", __func__, (int)tdls_mode);
1656
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001657 if (mutex_lock_interruptible(&tdls_lock))
1658 {
1659 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1660 "%s: unable to lock list", __func__);
1661 return;
1662 }
1663
1664 if (NULL == pHddCtx)
1665 {
1666 mutex_unlock(&tdls_lock);
1667 return;
1668 }
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001669
1670 if (pHddCtx->tdls_mode == tdls_mode)
1671 {
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001672 hddLog(TDLS_LOG_LEVEL, "%s already in mode %d", __func__, (int)tdls_mode);
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001673 mutex_unlock(&tdls_lock);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001674 return;
1675 }
1676
Hoonki Lee27511902013-03-14 18:19:06 -07001677 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1678
1679 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1680 {
1681 pAdapter = pAdapterNode->pAdapter;
Hoonki Leea6d49be2013-04-05 09:43:25 -07001682 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
1683 if (NULL != pHddTdlsCtx)
Hoonki Lee27511902013-03-14 18:19:06 -07001684 {
Hoonki Leea6d49be2013-04-05 09:43:25 -07001685 if(eTDLS_SUPPORT_ENABLED == tdls_mode)
1686 wlan_hdd_tdls_implicit_enable(pHddTdlsCtx);
1687 else if((eTDLS_SUPPORT_DISABLED == tdls_mode) ||
1688 (eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode))
1689 wlan_hdd_tdls_implicit_disable(pHddTdlsCtx);
Hoonki Lee27511902013-03-14 18:19:06 -07001690 }
1691 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1692 pAdapterNode = pNext;
1693 }
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07001694 if(bUpdateLast)
1695 {
1696 pHddCtx->tdls_mode_last = tdls_mode;
1697 }
1698 else
1699 {
1700 pHddCtx->tdls_mode_last = pHddCtx->tdls_mode;
1701 }
Hoonki Lee27511902013-03-14 18:19:06 -07001702 pHddCtx->tdls_mode = tdls_mode;
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07001703
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001704 mutex_unlock(&tdls_lock);
Hoonki Lee27511902013-03-14 18:19:06 -07001705}
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001706
Hoonki Leed37cbb32013-04-20 00:31:14 -07001707static void wlan_hdd_tdls_pre_setup(struct work_struct *work)
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001708{
Hoonki Leed37cbb32013-04-20 00:31:14 -07001709 tdlsCtx_t *pHddTdlsCtx =
1710 container_of(work, tdlsCtx_t, implicit_setup);
1711 hdd_context_t *pHddCtx;
1712 hddTdlsPeer_t *curr_peer;
Hoonki Leefb8df672013-04-10 18:20:34 -07001713 hddTdlsPeer_t *temp_peer;
Hoonki Leed37cbb32013-04-20 00:31:14 -07001714 int status;
1715
1716 if (NULL == pHddTdlsCtx)
1717 return;
1718
1719 if (unlikely(TDLS_CTX_MAGIC != pHddTdlsCtx->magic))
1720 return;
1721
1722 pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter);
Hoonki Leefb8df672013-04-10 18:20:34 -07001723
1724 if (NULL == pHddCtx)
1725 return;
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001726
Hoonki Leed37cbb32013-04-20 00:31:14 -07001727 curr_peer = pHddTdlsCtx->curr_candidate;
1728
1729 if (NULL == curr_peer)
1730 return;
1731
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001732 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter)))
1733 {
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001734 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s: Disable BMPS", __func__);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001735 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
1736 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001737
Hoonki Leefb8df672013-04-10 18:20:34 -07001738 temp_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, FALSE);
1739 if (NULL != temp_peer)
1740 {
1741 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: " MAC_ADDRESS_STR " ongoing. pre_setup ignored\n",
1742 __func__, MAC_ADDR_ARRAY(temp_peer->peerMac));
Hoonki Leed37cbb32013-04-20 00:31:14 -07001743 goto done;
Hoonki Leefb8df672013-04-10 18:20:34 -07001744 }
1745
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001746 if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support)
1747 curr_peer->link_status = eTDLS_LINK_DISCOVERING;
1748
Hoonki Leed37cbb32013-04-20 00:31:14 -07001749 status = wlan_hdd_cfg80211_send_tdls_discover_req(pHddTdlsCtx->pAdapter->wdev.wiphy,
1750 pHddTdlsCtx->pAdapter->dev,
1751 curr_peer->peerMac);
1752
1753 if (0 != status)
1754 {
1755 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: " MAC_ADDRESS_STR " discovery could not sent\n",
1756 __func__, MAC_ADDR_ARRAY(curr_peer->peerMac));
1757 if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support)
1758 curr_peer->link_status = eTDLS_LINK_IDLE;
1759 goto done;
1760 }
1761
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001762 pHddTdlsCtx->discovery_sent_cnt++;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001763 wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001764 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: discovery count %lu timeout %lu msec",
1765 __func__, pHddTdlsCtx->discovery_sent_cnt,
1766 pHddTdlsCtx->threshold_config.tx_period_t - TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE);
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001767
1768 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
1769 &pHddTdlsCtx->peerDiscoveryTimeoutTimer,
1770 pHddTdlsCtx->threshold_config.tx_period_t - TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001771
Hoonki Leed37cbb32013-04-20 00:31:14 -07001772done:
1773 pHddTdlsCtx->curr_candidate = NULL;
1774 pHddTdlsCtx->magic = 0;
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001775 return;
1776}
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001777
1778tANI_U32 wlan_hdd_tdls_discovery_sent_cnt(hdd_context_t *pHddCtx)
1779{
1780 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1781 hdd_adapter_t *pAdapter = NULL;
1782 tdlsCtx_t *pHddTdlsCtx = NULL;
1783 VOS_STATUS status = 0;
1784 tANI_U32 count = 0;
1785
1786 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1787 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1788 {
1789 pAdapter = pAdapterNode->pAdapter;
1790
Hoonki Leea6d49be2013-04-05 09:43:25 -07001791 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
1792 if (NULL != pHddTdlsCtx)
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001793 {
Hoonki Leea6d49be2013-04-05 09:43:25 -07001794 count = count + pHddTdlsCtx->discovery_sent_cnt;
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001795 }
1796 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1797 pAdapterNode = pNext;
1798 }
1799 return count;
1800}
1801
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001802void wlan_hdd_tdls_check_power_save_prohibited(hdd_adapter_t *pAdapter)
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001803{
1804 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
1805 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1806
1807 if ((NULL == pHddTdlsCtx) || (NULL == pHddCtx))
1808 return;
1809
1810 if ((0 == pHddCtx->connected_peer_count) &&
1811 (0 == wlan_hdd_tdls_discovery_sent_cnt(pHddCtx)))
1812 {
1813 sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter), 0);
1814 return;
1815 }
1816 sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter), 1);
1817 return;
1818}
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001819
1820void wlan_hdd_tdls_free_scan_request (tdls_scan_context_t *tdls_scan_ctx)
1821{
1822 if (NULL == tdls_scan_ctx)
1823 return;
1824
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001825 tdls_scan_ctx->attempt = 0;
Hoonki Leefb8df672013-04-10 18:20:34 -07001826 tdls_scan_ctx->reject = 0;
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001827 tdls_scan_ctx->magic = 0;
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001828 tdls_scan_ctx->scan_request = NULL;
1829 return;
1830}
1831
1832int wlan_hdd_tdls_copy_scan_context(hdd_context_t *pHddCtx,
1833 struct wiphy *wiphy,
1834#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
1835 struct net_device *dev,
1836#endif
1837 struct cfg80211_scan_request *request)
1838{
1839 tdls_scan_context_t *scan_ctx;
1840
1841 if (NULL == pHddCtx )
1842 return -1;
1843
1844 scan_ctx = &pHddCtx->tdls_scan_ctxt;
1845
1846 scan_ctx->wiphy = wiphy;
1847#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
1848 scan_ctx->dev = dev;
1849#endif
1850
1851 scan_ctx->scan_request = request;
1852 return 0;
1853}
1854
1855static void wlan_hdd_tdls_schedule_scan(struct work_struct *work)
1856{
1857 tdls_scan_context_t *scan_ctx =
1858 container_of(work, tdls_scan_context_t, tdls_scan_work.work);
1859
1860 if (NULL == scan_ctx)
1861 return;
1862
1863 if (unlikely(TDLS_CTX_MAGIC != scan_ctx->magic))
1864 return;
1865
1866 scan_ctx->attempt++;
1867
1868 wlan_hdd_cfg80211_scan(scan_ctx->wiphy,
1869#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
1870 scan_ctx->dev,
1871#endif
1872 scan_ctx->scan_request);
1873}
1874
1875static void wlan_hdd_tdls_scan_init_work(hdd_context_t *pHddCtx,
1876 struct wiphy *wiphy,
1877#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
1878 struct net_device *dev,
1879#endif
1880 struct cfg80211_scan_request *request,
1881 unsigned long delay)
1882{
1883 if (TDLS_CTX_MAGIC != pHddCtx->tdls_scan_ctxt.magic)
1884 {
1885#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
1886 wlan_hdd_tdls_copy_scan_context(pHddCtx, wiphy, dev, request);
1887#else
1888 wlan_hdd_tdls_copy_scan_context(pHddCtx, wiphy, request);
1889#endif
1890 pHddCtx->tdls_scan_ctxt.attempt = 0;
1891 pHddCtx->tdls_scan_ctxt.magic = TDLS_CTX_MAGIC;
1892 }
1893 INIT_DELAYED_WORK(&pHddCtx->tdls_scan_ctxt.tdls_scan_work, wlan_hdd_tdls_schedule_scan);
1894
1895 schedule_delayed_work(&pHddCtx->tdls_scan_ctxt.tdls_scan_work, delay);
1896}
1897
1898/* return negative = caller should stop and return error code immediately
1899 return 0 = caller should stop and return success immediately
1900 return 1 = caller can continue to scan
1901 */
1902int wlan_hdd_tdls_scan_callback (hdd_adapter_t *pAdapter,
1903 struct wiphy *wiphy,
1904#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
1905 struct net_device *dev,
1906#endif
1907 struct cfg80211_scan_request *request)
1908{
1909#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1910 struct net_device *dev = request->wdev->netdev;
1911#endif
1912 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1913 u16 connectedTdlsPeers;
Hoonki Leefb8df672013-04-10 18:20:34 -07001914 hddTdlsPeer_t *curr_peer;
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001915 unsigned long delay;
1916
1917 if (NULL == pHddCtx)
1918 return 0;
1919
1920 /* if tdls is not enabled, then continue scan */
1921 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
1922 return 1;
1923
Hoonki Leefb8df672013-04-10 18:20:34 -07001924 curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, TRUE);
1925 if (NULL != curr_peer)
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001926 {
Hoonki Leefb8df672013-04-10 18:20:34 -07001927 if (pHddCtx->tdls_scan_ctxt.reject++ >= TDLS_MAX_SCAN_REJECT)
1928 {
1929 pHddCtx->tdls_scan_ctxt.reject = 0;
1930 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1931 "%s: " MAC_ADDRESS_STR ". scan rejected %d. force it to idle",
1932 __func__, MAC_ADDR_ARRAY (curr_peer->peerMac), pHddCtx->tdls_scan_ctxt.reject);
1933
1934 wlan_hdd_tdls_set_peer_link_status (curr_peer, eTDLS_LINK_IDLE);
1935 return 1;
1936 }
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001937 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Hoonki Leefb8df672013-04-10 18:20:34 -07001938 "%s: tdls in progress. scan rejected %d",
1939 __func__, pHddCtx->tdls_scan_ctxt.reject);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001940 return -EBUSY;
1941 }
1942
1943 /* tdls teardown is ongoing */
1944 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
1945 {
1946 connectedTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
1947 if (connectedTdlsPeers && (pHddCtx->tdls_scan_ctxt.attempt < TDLS_MAX_SCAN_SCHEDULE))
1948 {
1949 delay = (unsigned long)(TDLS_DELAY_SCAN_PER_CONNECTION*connectedTdlsPeers);
1950 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1951 "%s: tdls disabled, but still connected_peers %d attempt %d. schedule scan %lu msec",
1952 __func__, connectedTdlsPeers, pHddCtx->tdls_scan_ctxt.attempt, delay);
1953
1954 wlan_hdd_tdls_scan_init_work (pHddCtx, wiphy,
1955#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
1956 dev,
1957#endif
1958 request,
1959 msecs_to_jiffies(delay));
1960 /* scan should not continue */
1961 return 0;
1962 }
1963 /* no connected peer or max retry reached, scan continue */
1964 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1965 "%s: tdls disabled. connected_peers %d attempt %d. scan allowed",
1966 __func__, connectedTdlsPeers, pHddCtx->tdls_scan_ctxt.attempt);
1967 return 1;
1968 }
1969 /* while tdls is up, first time scan */
1970 else if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode ||
1971 eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode)
1972 {
1973 /* disable implicit trigger logic & tdls operatoin */
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07001974 wlan_hdd_tdls_set_mode(pHddCtx, eTDLS_SUPPORT_DISABLED, FALSE);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001975 /* indicate the teardown all connected to peer */
1976 connectedTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
1977 if (connectedTdlsPeers)
1978 {
1979 tANI_U8 staIdx;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07001980 hddTdlsPeer_t *curr_peer;
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001981
1982 for (staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
1983 {
1984 if (pHddCtx->tdlsConnInfo[staIdx].staId)
1985 {
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001986 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001987 ("%s: indicate TDLS teadown (staId %d)"), __func__, pHddCtx->tdlsConnInfo[staIdx].staId) ;
1988
1989#ifdef CONFIG_TDLS_IMPLICIT
Hoonki Leea6d49be2013-04-05 09:43:25 -07001990 curr_peer = wlan_hdd_tdls_find_all_peer(pHddCtx, pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes);
1991 if(curr_peer)
1992 wlan_hdd_tdls_indicate_teardown(curr_peer->pHddTdlsCtx->pAdapter, curr_peer, eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001993#endif
1994 }
1995 }
1996 /* schedule scan */
1997 delay = (unsigned long)(TDLS_DELAY_SCAN_PER_CONNECTION*connectedTdlsPeers);
1998
1999 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2000 "%s: tdls enabled (mode %d), connected_peers %d. schedule scan %lu msec",
2001 __func__, pHddCtx->tdls_mode, wlan_hdd_tdlsConnectedPeers(pAdapter),
2002 delay);
2003
2004 wlan_hdd_tdls_scan_init_work (pHddCtx, wiphy,
2005#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
2006 dev,
2007#endif
2008 request,
2009 msecs_to_jiffies(delay));
2010 /* scan should not continue */
2011 return 0;
2012 }
2013 /* no connected peer, scan continue */
2014 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2015 "%s: tdls_mode %d, and no tdls connection. scan allowed",
2016 __func__, pHddCtx->tdls_mode);
2017 }
2018 return 1;
2019}
2020
2021void wlan_hdd_tdls_scan_done_callback(hdd_adapter_t *pAdapter)
2022{
2023 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002024
2025 if (NULL == pHddCtx)
2026 return;
2027
2028 /* free allocated memory at scan time */
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07002029 wlan_hdd_tdls_free_scan_request (&pHddCtx->tdls_scan_ctxt);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002030
2031 /* if tdls was enabled before scan, re-enable tdls mode */
2032 if(eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode_last ||
2033 eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode_last)
2034 {
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07002035 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002036 ("%s: revert tdls mode %d"), __func__, pHddCtx->tdls_mode_last);
2037
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07002038 wlan_hdd_tdls_set_mode(pHddCtx, pHddCtx->tdls_mode_last, FALSE);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002039 }
2040 wlan_hdd_tdls_check_bmps(pAdapter);
2041}
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07002042
2043void wlan_hdd_tdls_timer_restart(hdd_adapter_t *pAdapter,
2044 vos_timer_t *timer,
2045 v_U32_t expirationTime)
2046{
2047 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2048
2049 if (NULL == pHddStaCtx)
2050 return;
2051
2052 /* Check whether driver load unload is in progress */
2053 if(vos_is_load_unload_in_progress( VOS_MODULE_ID_VOSS, NULL))
2054 {
2055 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2056 "%s: Driver load/unload is in progress.", __func__);
2057 return;
2058 }
2059
2060 if (hdd_connIsConnected(pHddStaCtx))
2061 {
2062 vos_timer_stop(timer);
2063 vos_timer_start(timer, expirationTime);
2064 }
2065}
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002066void wlan_hdd_tdls_indicate_teardown(hdd_adapter_t *pAdapter,
2067 hddTdlsPeer_t *curr_peer,
2068 tANI_U16 reason)
2069{
2070 if (NULL == pAdapter || NULL == curr_peer)
2071 return;
2072
2073 if (eTDLS_LINK_CONNECTED != curr_peer->link_status)
2074 return;
2075
2076 wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_TEARING);
2077 cfg80211_tdls_oper_request(pAdapter->dev,
2078 curr_peer->peerMac,
2079 NL80211_TDLS_TEARDOWN,
2080 reason,
2081 GFP_KERNEL);
2082}