blob: bc108c04e8f1776432aa566346a70712866ed6da [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 Nakkala4327a152013-03-04 23:22:42 -080042static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(tdlsCtx_t *pHddTdlsCtx);
43static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t *pHddTdlsCtx);
44static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx);
Madan Mohan Koyyalamudi693275b2013-07-22 19:14:09 +053045static void wlan_hdd_tdls_peer_timers_destroy(tdlsCtx_t *pHddTdlsCtx);
Sunil Dutt41de4e22013-11-14 18:09:02 +053046int wpa_tdls_is_allowed_force_peer(tdlsCtx_t *pHddTdlsCtx, u8 *mac);
Hoonki Leed37cbb32013-04-20 00:31:14 -070047#ifdef CONFIG_TDLS_IMPLICIT
48static void wlan_hdd_tdls_pre_setup(struct work_struct *work);
49#endif
Chilam NG571c65a2013-01-19 12:27:36 +053050
Hoonki Lee5a4b2172013-01-29 01:45:53 -080051#ifndef WLAN_FEATURE_TDLS_DEBUG
52#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
53#else
54#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_WARN
55#endif
56
Hoonki Lee387663d2013-02-05 18:08:43 -080057static u8 wlan_hdd_tdls_hash_key (u8 *mac)
Hoonki Leef63df0d2013-01-16 19:29:14 -080058{
59 int i;
Hoonki Lee387663d2013-02-05 18:08:43 -080060 u8 key = 0;
61
62 for (i = 0; i < 6; i++)
63 key ^= mac[i];
64
65 return key;
66}
67
Hoonki Leed37cbb32013-04-20 00:31:14 -070068#ifdef CONFIG_TDLS_IMPLICIT
69static void wlan_hdd_tdls_pre_setup_init_work(tdlsCtx_t * pHddTdlsCtx,
70 hddTdlsPeer_t *curr_candidate)
71{
72 if (TDLS_CTX_MAGIC != pHddTdlsCtx->magic)
73 {
74 pHddTdlsCtx->curr_candidate = curr_candidate;
75 pHddTdlsCtx->magic = TDLS_CTX_MAGIC;
76
Hoonki Leed37cbb32013-04-20 00:31:14 -070077 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;
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +053087 hdd_context_t *pHddCtx;
88
89 if ((NULL == pHddTdlsCtx))
90 return;
91
92 if ((NULL == pHddTdlsCtx->pAdapter) )
93 return;
94
95 pHddCtx = WLAN_HDD_GET_CTX( pHddTdlsCtx->pAdapter );
96
97 if (NULL == pHddCtx)
98 return;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080099
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800100 if ( mutexLock )
101 {
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530102 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800103 {
104 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
105 "%s: unable to lock list: %d", __func__, __LINE__);
106 return;
107 }
108 }
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800109
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800110 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pHddTdlsCtx->pAdapter);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700111#ifdef FEATURE_WLAN_TDLS_INTERNAL
Gopichand Nakkala3046fc92013-03-23 13:56:43 -0700112 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
113 &pHddTdlsCtx->peerDiscoverTimer,
114 discoveryExpiry);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700115#endif
Gopichand Nakkala3046fc92013-03-23 13:56:43 -0700116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "beacon rssi: %d",
117 pHddTdlsCtx->ap_rssi);
118
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800119 if ( mutexLock )
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530120 mutex_unlock(&pHddCtx->tdls_lock);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800121
122 return;
123}
124
Hoonki Leed37cbb32013-04-20 00:31:14 -0700125#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER
Hoonki Lee387663d2013-02-05 18:08:43 -0800126static v_VOID_t wlan_hdd_tdls_discover_peer_cb( v_PVOID_t userData )
127{
128 int i;
129 struct list_head *head;
130 struct list_head *pos;
Chilam NG571c65a2013-01-19 12:27:36 +0530131 hddTdlsPeer_t *curr_peer;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800132 hdd_station_ctx_t *pHddStaCtx;
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530133 hdd_context_t *pHddCtx;
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
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530139 if ((NULL == pHddTdlsCtx))
140 return;
141
142 if (NULL == pHddTdlsCtx->pAdapter)
143 return;
144
145 pHddCtx = WLAN_HDD_GET_CTX( pHddTdlsCtx->pAdapter );
146
147 if (NULL == pHddCtx)
148 return;
149
150
151 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800152 {
153 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
154 "%s: unable to lock list : %d", __func__, __LINE__);
155 return;
156 }
Hoonki Leebfee0342013-01-21 16:43:45 -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
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530230 mutex_unlock(&pHddCtx->tdls_lock);
Gopichand Nakkala638ebc72013-03-21 18:04:02 -0700231
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 )
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530246 mutex_unlock(&pHddCtx->tdls_lock);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800247 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;
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530257 tdlsCtx_t *pHddTdlsCtx = (tdlsCtx_t *)userData;
258 hdd_context_t *pHddCtx;
Hoonki Leebfee0342013-01-21 16:43:45 -0800259
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530260 if ((NULL == pHddTdlsCtx))
261 return;
262
263 if (NULL == pHddTdlsCtx->pAdapter)
264 return;
265
266 pHddCtx = WLAN_HDD_GET_CTX( pHddTdlsCtx->pAdapter );
267
268 if (NULL == pHddCtx)
269 return;
270
271 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800272 {
273 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
274 "%s: unable to lock list", __func__);
275 return;
276 }
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800277
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);
Sunil Dutt41de4e22013-11-14 18:09:02 +0530288 if (pHddCtx->cfg_ini->fTDLSExternalControl &&
289 (0 == wpa_tdls_is_allowed_force_peer (pHddTdlsCtx, curr_peer->peerMac))) {
290 continue;
291 }
Hoonki Lee387663d2013-02-05 18:08:43 -0800292
Chilam NG571c65a2013-01-19 12:27:36 +0530293 if (eTDLS_CAP_SUPPORTED == curr_peer->tdls_support) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800294 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Hoonki Lee66b75f32013-04-16 18:30:07 -0700295 "tx %d, rx %d (thr.pkt %d/idle %d), rssi %d (thr.trig %d/hys %d/tear %d)",
296 curr_peer->tx_pkt, curr_peer->rx_pkt,
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800297 pHddTdlsCtx->threshold_config.tx_packet_n,
Hoonki Lee66b75f32013-04-16 18:30:07 -0700298 pHddTdlsCtx->threshold_config.idle_packet_n,
299 curr_peer->rssi,
300 pHddTdlsCtx->threshold_config.rssi_trigger_threshold,
301 pHddTdlsCtx->threshold_config.rssi_hysteresis,
302 pHddTdlsCtx->threshold_config.rssi_teardown_threshold);
Chilam Ng01120412013-02-19 18:32:21 -0800303
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800304 if ((eTDLS_LINK_IDLE == curr_peer->link_status) ||
305 (eTDLS_LINK_DISCOVERING == curr_peer->link_status)){
Chilam NG571c65a2013-01-19 12:27:36 +0530306 if (curr_peer->tx_pkt >=
307 pHddTdlsCtx->threshold_config.tx_packet_n) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800308
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800309 if (HDD_MAX_NUM_TDLS_STA > wlan_hdd_tdlsConnectedPeers(pHddTdlsCtx->pAdapter))
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800310 {
311
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700312 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "Tput trigger TDLS pre-setup");
Chilam NG571c65a2013-01-19 12:27:36 +0530313#ifdef CONFIG_TDLS_IMPLICIT
Hoonki Leed37cbb32013-04-20 00:31:14 -0700314 wlan_hdd_tdls_pre_setup_init_work(pHddTdlsCtx, curr_peer);
Chilam NG571c65a2013-01-19 12:27:36 +0530315#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800316 }
317 else
318 {
319 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800320 "%s: Maximum peer connected already! %d",
321 __func__, wlan_hdd_tdlsConnectedPeers(pHddTdlsCtx->pAdapter) );
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800322 }
Hoonki Leecdd8e962013-01-20 00:45:46 -0800323 goto next_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530324 }
Hoonki Leefb8df672013-04-10 18:20:34 -0700325 }
326 else if (eTDLS_LINK_CONNECTED == curr_peer->link_status) {
Chilam Ng01120412013-02-19 18:32:21 -0800327 if ((tANI_S32)curr_peer->rssi <
328 (tANI_S32)pHddTdlsCtx->threshold_config.rssi_teardown_threshold) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800329
Chilam Ng01120412013-02-19 18:32:21 -0800330 VOS_TRACE( VOS_MODULE_ID_HDD,
331 VOS_TRACE_LEVEL_WARN,
332 "Tear down - low RSSI: " MAC_ADDRESS_STR "!",
333 MAC_ADDR_ARRAY(curr_peer->peerMac));
334#ifdef CONFIG_TDLS_IMPLICIT
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -0700335 wlan_hdd_tdls_indicate_teardown(pHddTdlsCtx->pAdapter,
336 curr_peer,
337 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
Chilam Ng01120412013-02-19 18:32:21 -0800338#endif
Hoonki Leecdd8e962013-01-20 00:45:46 -0800339 goto next_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530340 }
Chilam Ng01120412013-02-19 18:32:21 -0800341
Naresh Jayaramdb4514b2013-11-25 18:08:10 +0530342 /* Only teardown based on non zero idle packet threshold, to address a use
343 * case where this threshold does not get consider for TEAR DOWN.
344 */
345
346 if (( 0 != pHddTdlsCtx->threshold_config.idle_packet_n ) &&
347 ((curr_peer->tx_pkt <
Chilam Ng01120412013-02-19 18:32:21 -0800348 pHddTdlsCtx->threshold_config.idle_packet_n) &&
349 (curr_peer->rx_pkt <
Naresh Jayaramdb4514b2013-11-25 18:08:10 +0530350 pHddTdlsCtx->threshold_config.idle_packet_n))) {
Chilam Ng01120412013-02-19 18:32:21 -0800351 if (VOS_TIMER_STATE_RUNNING !=
352 vos_timer_getCurrentState(&curr_peer->peerIdleTimer)) {
353 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
354 "Tx/Rx Idle timer start: " MAC_ADDRESS_STR "!",
355 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkala3046fc92013-03-23 13:56:43 -0700356 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
357 &curr_peer->peerIdleTimer,
358 pHddTdlsCtx->threshold_config.idle_timeout_t);
Chilam Ng01120412013-02-19 18:32:21 -0800359 }
360 } else {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800361 if (VOS_TIMER_STATE_RUNNING ==
362 vos_timer_getCurrentState(&curr_peer->peerIdleTimer)) {
Chilam Ng01120412013-02-19 18:32:21 -0800363 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
364 "Tx/Rx Idle timer stop: " MAC_ADDRESS_STR "!",
365 MAC_ADDR_ARRAY(curr_peer->peerMac));
366 vos_timer_stop( &curr_peer->peerIdleTimer);
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800367 }
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800368 }
Chilam Ng01120412013-02-19 18:32:21 -0800369
Hoonki Leecdd8e962013-01-20 00:45:46 -0800370// if (curr_peer->rssi <
371// (pHddTdlsCtx->threshold_config.rssi_hysteresis +
372// pHddTdlsCtx->ap_rssi)) {
373//
374//#ifdef CONFIG_TDLS_IMPLICIT
375// cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
376// curr_peer->peerMac,
377// NL80211_TDLS_TEARDOWN, FALSE,
378// GFP_KERNEL);
379//#endif
380// }
Chilam NG571c65a2013-01-19 12:27:36 +0530381 }
Chilam Ng01120412013-02-19 18:32:21 -0800382 } else if (eTDLS_CAP_UNKNOWN == curr_peer->tdls_support) {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -0700383 if (!TDLS_IS_CONNECTED(curr_peer)) {
Chilam Ng01120412013-02-19 18:32:21 -0800384 if (curr_peer->tx_pkt >=
385 pHddTdlsCtx->threshold_config.tx_packet_n) {
Chilam Ng01120412013-02-19 18:32:21 -0800386
Gopichand Nakkala062bcbd2013-03-29 18:14:47 -0700387 if (curr_peer->discovery_attempt++ <
Chilam Ng01120412013-02-19 18:32:21 -0800388 pHddTdlsCtx->threshold_config.discovery_tries_n) {
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700389 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "TDLS UNKNOWN discover ");
Hoonki Leed37cbb32013-04-20 00:31:14 -0700390#ifdef CONFIG_TDLS_IMPLICIT
391 wlan_hdd_tdls_pre_setup_init_work(pHddTdlsCtx, curr_peer);
392#endif
Chilam Ng01120412013-02-19 18:32:21 -0800393 }
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800394 else
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800395 {
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800396 curr_peer->tdls_support = eTDLS_CAP_NOT_SUPPORTED;
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800397 curr_peer->link_status = eTDLS_LINK_IDLE;
398 }
Chilam Ng01120412013-02-19 18:32:21 -0800399 }
400 }
Chilam NG571c65a2013-01-19 12:27:36 +0530401 }
402
Hoonki Leecdd8e962013-01-20 00:45:46 -0800403next_peer:
Chilam NG571c65a2013-01-19 12:27:36 +0530404 curr_peer->tx_pkt = 0;
Chilam Ng1279e232013-01-25 15:06:52 -0800405 curr_peer->rx_pkt = 0;
Hoonki Lee387663d2013-02-05 18:08:43 -0800406 }
Chilam NG571c65a2013-01-19 12:27:36 +0530407 }
408
Gopichand Nakkala3046fc92013-03-23 13:56:43 -0700409 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
410 &pHddTdlsCtx->peerUpdateTimer,
411 pHddTdlsCtx->threshold_config.tx_period_t);
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530412 mutex_unlock(&pHddCtx->tdls_lock);
Chilam NG571c65a2013-01-19 12:27:36 +0530413}
414
Chilam Ng1279e232013-01-25 15:06:52 -0800415static v_VOID_t wlan_hdd_tdls_idle_cb( v_PVOID_t userData )
416{
Lee Hoonkic1262f22013-01-24 21:59:00 -0800417#ifdef CONFIG_TDLS_IMPLICIT
Chilam Ng1279e232013-01-25 15:06:52 -0800418 hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData;
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530419 tdlsCtx_t *pHddTdlsCtx;
420 hdd_context_t *pHddCtx;
Chilam Ng1279e232013-01-25 15:06:52 -0800421
Rajesh Chauhan1ace6002013-04-18 18:08:21 -0700422 if (NULL == curr_peer)
423 {
424 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
425 "%s: Invalid tdls idle timer expired", __func__);
426 return;
427 }
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530428 pHddTdlsCtx = curr_peer->pHddTdlsCtx;
429
430 if ((NULL == pHddTdlsCtx) || (NULL == pHddTdlsCtx->pAdapter) )
431 return;
432
433 pHddCtx = WLAN_HDD_GET_CTX( pHddTdlsCtx->pAdapter );
434
435 if (NULL == pHddCtx)
436 return;
437
Rajesh Chauhan1ace6002013-04-18 18:08:21 -0700438
439 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800440 "%s: Tx/Rx Idle " MAC_ADDRESS_STR " tx_pkt: %d, rx_pkt: %d, idle_packet_n: %d",
Rajesh Chauhan1ace6002013-04-18 18:08:21 -0700441 __func__, MAC_ADDR_ARRAY(curr_peer->peerMac),
442 curr_peer->tx_pkt,
443 curr_peer->rx_pkt,
444 curr_peer->pHddTdlsCtx->threshold_config.idle_packet_n);
445
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530446 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800447 {
448 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
449 "%s: unable to lock list", __func__);
450 return;
451 }
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800452
Rajesh Chauhan1ace6002013-04-18 18:08:21 -0700453 /* Check tx/rx statistics on this tdls link for recent activities and
454 * then decide whether to tear down the link or keep it.
455 */
456 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))
457 {
458 /* this tdls link got back to normal, so keep it */
459 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
460 "%s: tdls link to " MAC_ADDRESS_STR " back to normal, will stay",
461 __func__, MAC_ADDR_ARRAY(curr_peer->peerMac));
462 }
463 else
464 {
465 /* this tdls link needs to get torn down */
466 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
467 "%s: trigger tdls link to " MAC_ADDRESS_STR " down",
468 __func__, MAC_ADDR_ARRAY(curr_peer->peerMac));
469
470 wlan_hdd_tdls_indicate_teardown(curr_peer->pHddTdlsCtx->pAdapter,
471 curr_peer,
472 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
473 }
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530474 mutex_unlock(&pHddCtx->tdls_lock);
Chilam Ng1279e232013-01-25 15:06:52 -0800475#endif
476}
477
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700478static v_VOID_t wlan_hdd_tdls_discovery_timeout_peer_cb(v_PVOID_t userData)
479{
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700480 int i;
481 struct list_head *head;
482 hddTdlsPeer_t *tmp;
483 struct list_head *pos, *q;
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700484 tdlsCtx_t *pHddTdlsCtx;
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530485 hdd_context_t *pHddCtx;
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700486
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530487 pHddTdlsCtx = (tdlsCtx_t *)userData;
488
489 if ((NULL == pHddTdlsCtx) || (NULL == pHddTdlsCtx->pAdapter) )
490 return;
491
492 pHddCtx = WLAN_HDD_GET_CTX( pHddTdlsCtx->pAdapter );
493
494 if (NULL == pHddCtx)
495 return;
496
497 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700498 {
499 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
500 "%s: unable to lock list", __func__);
501 return ;
502 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700503
504 for (i = 0; i < 256; i++) {
505 head = &pHddTdlsCtx->peer_list[i];
506 list_for_each_safe (pos, q, head) {
507 tmp = list_entry(pos, hddTdlsPeer_t, node);
508 if (eTDLS_LINK_DISCOVERING == tmp->link_status)
509 {
510 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
511 "%s: " MAC_ADDRESS_STR " to idle state", __func__,
512 MAC_ADDR_ARRAY(tmp->peerMac));
513 tmp->link_status = eTDLS_LINK_IDLE;
514 }
515 }
516 }
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700517
518 pHddTdlsCtx->discovery_sent_cnt = 0;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700519 wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700520
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530521 mutex_unlock(&pHddCtx->tdls_lock);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700522
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700523 wlan_hdd_tdls_check_bmps(pHddTdlsCtx->pAdapter);
524
525 return;
526}
527
Hoonki Lee14621352013-04-16 17:51:19 -0700528static v_VOID_t wlan_hdd_tdls_initiator_wait_cb( v_PVOID_t userData )
529{
530 hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData;
531 tdlsCtx_t *pHddTdlsCtx;
532
533 if ( NULL == curr_peer )
534 return;
535
536 pHddTdlsCtx = curr_peer->pHddTdlsCtx;
537
538 if ( NULL == pHddTdlsCtx )
539 return;
540
541 WLANTL_ResumeDataTx( (WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter))->pvosContext,
542 (v_U8_t *)&curr_peer->staId);
543}
544
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800545static void wlan_hdd_tdls_free_list(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800546{
547 int i;
548 struct list_head *head;
549 hddTdlsPeer_t *tmp;
550 struct list_head *pos, *q;
551
552 if (NULL == pHddTdlsCtx) return;
553
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800554
555 for (i = 0; i < 256; i++) {
556 head = &pHddTdlsCtx->peer_list[i];
557 list_for_each_safe (pos, q, head) {
558 tmp = list_entry(pos, hddTdlsPeer_t, node);
559 list_del(pos);
560 vos_mem_free(tmp);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -0800561 tmp = NULL;
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800562 }
563 }
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800564}
565
Sameer Thalappilbee426e2013-10-30 10:30:30 -0700566static void wlan_hdd_tdls_schedule_scan(struct work_struct *work)
567{
568 tdls_scan_context_t *scan_ctx =
569 container_of(work, tdls_scan_context_t, tdls_scan_work.work);
570
571 if (NULL == scan_ctx)
572 return;
573
574 if (unlikely(TDLS_CTX_MAGIC != scan_ctx->magic))
575 return;
576
577 scan_ctx->attempt++;
578
579 wlan_hdd_cfg80211_scan(scan_ctx->wiphy,
580#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
581 scan_ctx->dev,
582#endif
583 scan_ctx->scan_request);
584}
585
586
Hoonki Lee27511902013-03-14 18:19:06 -0700587int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter)
Chilam Ng01120412013-02-19 18:32:21 -0800588{
Chilam Ng01120412013-02-19 18:32:21 -0800589 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Hoonki Lee27511902013-03-14 18:19:06 -0700590 tdlsCtx_t *pHddTdlsCtx;
Chilam Ng01120412013-02-19 18:32:21 -0800591 int i;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800592 v_U8_t staIdx;
Chilam Ng01120412013-02-19 18:32:21 -0800593
Sunil Dutt66485cb2013-12-19 19:05:03 +0530594 if (NULL == pHddCtx)
595 return -1;
596
597 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
598 {
599 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
600 "%s: unable to lock list", __func__);
601 return -1;
602 }
603
Hoonki Lee27511902013-03-14 18:19:06 -0700604 if ((FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport) ||
605 (FALSE == sme_IsFeatureSupportedByFW(TDLS)))
606 {
607 pHddCtx->tdls_mode = eTDLS_SUPPORT_NOT_ENABLED;
608 pAdapter->sessionCtx.station.pHddTdlsCtx = NULL;
609 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS not enabled (%d) or FW doesn't support (%d)!",
610 __func__, pHddCtx->cfg_ini->fEnableTDLSSupport,
611 sme_IsFeatureSupportedByFW(TDLS));
Sunil Dutt66485cb2013-12-19 19:05:03 +0530612 mutex_unlock(&pHddCtx->tdls_lock);
Hoonki Lee27511902013-03-14 18:19:06 -0700613 return 0;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800614 }
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +0530615 /* TDLS is supported only in STA / P2P Client modes,
616 * hence the check for TDLS support in a specific Device mode.
617 * Do not return a failure rather do not continue further
618 * with the initialization as tdls_init would be called
619 * during the open adapter for a p2p interface at which point
620 * the device mode would be a P2P_DEVICE. The point here is to
621 * continue initialization for STA / P2P Client modes.
622 * TDLS exit also check for the device mode for clean up hence
623 * there is no issue even if success is returned.
624 */
625 if (0 == WLAN_HDD_IS_TDLS_SUPPORTED_ADAPTER(pAdapter))
626 {
Sunil Dutt66485cb2013-12-19 19:05:03 +0530627 mutex_unlock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +0530628 return 0;
629 }
630 /* Check for the valid pHddTdlsCtx. If valid do not further
631 * allocate the memory, rather continue with the initialization.
632 * If tdls_initialization would get reinvoked without tdls_exit
633 * getting invoked (SSR) there is no point to further proceed
634 * with the memory allocations.
635 */
636 if (NULL == pAdapter->sessionCtx.station.pHddTdlsCtx)
637 {
638 pHddTdlsCtx = vos_mem_malloc(sizeof(tdlsCtx_t));
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800639
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +0530640 if (NULL == pHddTdlsCtx) {
641 hddLog(VOS_TRACE_LEVEL_ERROR, "%s malloc failed!", __func__);
642 pAdapter->sessionCtx.station.pHddTdlsCtx = NULL;
Sunil Dutt66485cb2013-12-19 19:05:03 +0530643 mutex_unlock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +0530644 return -1;
645 }
646 /* initialize TDLS pAdater context */
647 vos_mem_zero(pHddTdlsCtx, sizeof(tdlsCtx_t));
648#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER
649 vos_timer_init(&pHddTdlsCtx->peerDiscoverTimer,
650 VOS_TIMER_TYPE_SW,
651 wlan_hdd_tdls_discover_peer_cb,
652 pHddTdlsCtx);
653#endif
Hoonki Lee27511902013-03-14 18:19:06 -0700654
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +0530655 vos_timer_init(&pHddTdlsCtx->peerUpdateTimer,
656 VOS_TIMER_TYPE_SW,
657 wlan_hdd_tdls_update_peer_cb,
658 pHddTdlsCtx);
659 vos_timer_init(&pHddTdlsCtx->peerDiscoveryTimeoutTimer,
660 VOS_TIMER_TYPE_SW,
661 wlan_hdd_tdls_discovery_timeout_peer_cb,
662 pHddTdlsCtx);
663
664 pAdapter->sessionCtx.station.pHddTdlsCtx = pHddTdlsCtx;
Hoonki Lee27511902013-03-14 18:19:06 -0700665 }
666
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +0530667 pHddTdlsCtx = pAdapter->sessionCtx.station.pHddTdlsCtx;
Hoonki Lee27511902013-03-14 18:19:06 -0700668
669 /* initialize TDLS global context */
670 pHddCtx->connected_peer_count = 0;
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700671 sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
Hoonki Lee27511902013-03-14 18:19:06 -0700672
Hoonki Lee93e67ff2013-03-19 15:49:25 -0700673 pHddCtx->tdls_scan_ctxt.magic = 0;
Hoonki Leefb8df672013-04-10 18:20:34 -0700674 pHddCtx->tdls_scan_ctxt.attempt = 0;
675 pHddCtx->tdls_scan_ctxt.reject = 0;
Hoonki Lee93e67ff2013-03-19 15:49:25 -0700676 pHddCtx->tdls_scan_ctxt.scan_request = NULL;
677
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800678 for (staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
679 {
680 pHddCtx->tdlsConnInfo[staIdx].staId = 0;
681 pHddCtx->tdlsConnInfo[staIdx].sessionId = 255;
682 vos_mem_zero(&pHddCtx->tdlsConnInfo[staIdx].peerMac,
683 sizeof(v_MACADDR_t)) ;
Chilam Ng01120412013-02-19 18:32:21 -0800684 }
685
Hoonki Lee27511902013-03-14 18:19:06 -0700686 pHddTdlsCtx->pAdapter = pAdapter;
687
688 for (i = 0; i < 256; i++)
689 {
690 INIT_LIST_HEAD(&pHddTdlsCtx->peer_list[i]);
691 }
692
Hoonki Leed37cbb32013-04-20 00:31:14 -0700693 pHddTdlsCtx->curr_candidate = NULL;
694 pHddTdlsCtx->magic = 0;
695
Hoonki Lee27511902013-03-14 18:19:06 -0700696 /* remember configuration even if it is not used right now. it could be used later */
697 pHddTdlsCtx->threshold_config.tx_period_t = pHddCtx->cfg_ini->fTDLSTxStatsPeriod;
698 pHddTdlsCtx->threshold_config.tx_packet_n = pHddCtx->cfg_ini->fTDLSTxPacketThreshold;
699 pHddTdlsCtx->threshold_config.discovery_period_t = pHddCtx->cfg_ini->fTDLSDiscoveryPeriod;
700 pHddTdlsCtx->threshold_config.discovery_tries_n = pHddCtx->cfg_ini->fTDLSMaxDiscoveryAttempt;
701 pHddTdlsCtx->threshold_config.idle_timeout_t = pHddCtx->cfg_ini->fTDLSIdleTimeout;
702 pHddTdlsCtx->threshold_config.idle_packet_n = pHddCtx->cfg_ini->fTDLSIdlePacketThreshold;
703 pHddTdlsCtx->threshold_config.rssi_hysteresis = pHddCtx->cfg_ini->fTDLSRSSIHysteresis;
704 pHddTdlsCtx->threshold_config.rssi_trigger_threshold = pHddCtx->cfg_ini->fTDLSRSSITriggerThreshold;
705 pHddTdlsCtx->threshold_config.rssi_teardown_threshold = pHddCtx->cfg_ini->fTDLSRSSITeardownThreshold;
Chilam NG571c65a2013-01-19 12:27:36 +0530706
Chilam Ng01120412013-02-19 18:32:21 -0800707 if (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger)
Hoonki Lee387663d2013-02-05 18:08:43 -0800708 {
Chilam Ng01120412013-02-19 18:32:21 -0800709 pHddCtx->tdls_mode = eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY;
Hoonki Leebf870f32013-01-19 15:53:30 +0530710 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS Implicit trigger not enabled!", __func__);
Hoonki Leebf870f32013-01-19 15:53:30 +0530711 }
Hoonki Lee27511902013-03-14 18:19:06 -0700712 else
713 {
714 pHddCtx->tdls_mode = eTDLS_SUPPORT_ENABLED;
Hoonki Lee27511902013-03-14 18:19:06 -0700715 }
Sameer Thalappilbee426e2013-10-30 10:30:30 -0700716 INIT_WORK(&pHddTdlsCtx->implicit_setup, wlan_hdd_tdls_pre_setup);
717 INIT_DELAYED_WORK(&pHddCtx->tdls_scan_ctxt.tdls_scan_work, wlan_hdd_tdls_schedule_scan);
Sunil Dutt66485cb2013-12-19 19:05:03 +0530718 mutex_unlock(&pHddCtx->tdls_lock);
Hoonki Lee27511902013-03-14 18:19:06 -0700719
720 return 0;
Chilam NG571c65a2013-01-19 12:27:36 +0530721}
722
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800723void wlan_hdd_tdls_exit(hdd_adapter_t *pAdapter)
Chilam NG571c65a2013-01-19 12:27:36 +0530724{
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800725 tdlsCtx_t *pHddTdlsCtx;
Hoonki Lee93e67ff2013-03-19 15:49:25 -0700726 hdd_context_t *pHddCtx;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800727
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +0530728 /*
729 * NOTE: The Callers of this function should ensure to acquire the
730 * tdls_lock to avoid any concurrent access to the Adapter.
731 */
732
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530733 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
734 if (NULL == pHddCtx)
735 {
736 return;
737 }
738
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800739 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800740 if (NULL == pHddTdlsCtx)
741 {
Hoonki Leebfee0342013-01-21 16:43:45 -0800742 hddLog(VOS_TRACE_LEVEL_WARN, "%s TDLS not enabled, exiting!", __func__);
743 return;
744 }
Sameer Thalappilbee426e2013-10-30 10:30:30 -0700745#ifdef WLAN_OPEN_SOURCE
746 cancel_work_sync(&pHddTdlsCtx->implicit_setup);
747 cancel_delayed_work_sync(&pHddCtx->tdls_scan_ctxt.tdls_scan_work);
748#endif
Hoonki Leebfee0342013-01-21 16:43:45 -0800749
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800750 /* must stop timer here before freeing peer list, because peerIdleTimer is
751 part of peer list structure. */
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800752 wlan_hdd_tdls_timers_destroy(pHddTdlsCtx);
753 wlan_hdd_tdls_free_list(pHddTdlsCtx);
Chilam Nga75d8b62013-01-29 01:35:59 -0800754
Hoonki Lee93e67ff2013-03-19 15:49:25 -0700755 wlan_hdd_tdls_free_scan_request(&pHddCtx->tdls_scan_ctxt);
756
Chilam Nga75d8b62013-01-29 01:35:59 -0800757 vos_mem_free(pHddTdlsCtx);
758 pHddTdlsCtx = NULL;
Chilam NG571c65a2013-01-19 12:27:36 +0530759}
760
Madan Mohan Koyyalamudi693275b2013-07-22 19:14:09 +0530761/* stop all monitoring timers per Adapter */
762static void wlan_hdd_tdls_monitor_timers_stop(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800763{
Hoonki Leed37cbb32013-04-20 00:31:14 -0700764#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800765 vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer);
Hoonki Leed37cbb32013-04-20 00:31:14 -0700766#endif
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800767 vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700768 vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer);
Madan Mohan Koyyalamudi693275b2013-07-22 19:14:09 +0530769}
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800770
Madan Mohan Koyyalamudi693275b2013-07-22 19:14:09 +0530771/* stop all per peer timers */
772static void wlan_hdd_tdls_peer_timers_stop(tdlsCtx_t *pHddTdlsCtx)
773{
774 int i;
775 struct list_head *head;
776 struct list_head *pos;
777 hddTdlsPeer_t *curr_peer;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800778 for (i = 0; i < 256; i++)
779 {
780 head = &pHddTdlsCtx->peer_list[i];
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800781 list_for_each (pos, head) {
782 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800783 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800784 "%s: " MAC_ADDRESS_STR " -> stop idle timer",
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800785 __func__,
Chilam Ng01120412013-02-19 18:32:21 -0800786 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800787 vos_timer_stop ( &curr_peer->peerIdleTimer );
Hoonki Lee14621352013-04-16 17:51:19 -0700788 vos_timer_stop( &curr_peer->initiatorWaitTimeoutTimer );
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800789 }
790 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800791}
792
Madan Mohan Koyyalamudi693275b2013-07-22 19:14:09 +0530793/* stop all the tdls timers running */
794static void wlan_hdd_tdls_timers_stop(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800795{
Madan Mohan Koyyalamudi693275b2013-07-22 19:14:09 +0530796 wlan_hdd_tdls_monitor_timers_stop(pHddTdlsCtx);
797 wlan_hdd_tdls_peer_timers_stop(pHddTdlsCtx);
798}
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800799
Madan Mohan Koyyalamudi693275b2013-07-22 19:14:09 +0530800static void wlan_hdd_tdls_monitor_timers_destroy(tdlsCtx_t *pHddTdlsCtx)
801{
Hoonki Leed37cbb32013-04-20 00:31:14 -0700802#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800803 vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer);
804 vos_timer_destroy(&pHddTdlsCtx->peerDiscoverTimer);
Hoonki Leed37cbb32013-04-20 00:31:14 -0700805#endif
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800806 vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer);
807 vos_timer_destroy(&pHddTdlsCtx->peerUpdateTimer);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700808 vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer);
809 vos_timer_destroy(&pHddTdlsCtx->peerDiscoveryTimeoutTimer);
Madan Mohan Koyyalamudi693275b2013-07-22 19:14:09 +0530810}
811/*Free all the timers related to the TDLS peer */
812static void wlan_hdd_tdls_peer_timers_destroy(tdlsCtx_t *pHddTdlsCtx)
813{
814 int i;
815 struct list_head *head;
816 struct list_head *pos;
817 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800818 for (i = 0; i < 256; i++)
819 {
820 head = &pHddTdlsCtx->peer_list[i];
821
822 list_for_each (pos, head) {
823 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
824
825 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800826 "%s: " MAC_ADDRESS_STR " -> destroy idle timer",
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800827 __func__,
Chilam Ng01120412013-02-19 18:32:21 -0800828 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800829 vos_timer_stop ( &curr_peer->peerIdleTimer );
830 vos_timer_destroy ( &curr_peer->peerIdleTimer );
Hoonki Lee14621352013-04-16 17:51:19 -0700831 vos_timer_stop(&curr_peer->initiatorWaitTimeoutTimer);
832 vos_timer_destroy(&curr_peer->initiatorWaitTimeoutTimer);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800833 }
834 }
Madan Mohan Koyyalamudi693275b2013-07-22 19:14:09 +0530835
836}
837
838/* destroy all the tdls timers running */
839static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx)
840{
841 wlan_hdd_tdls_monitor_timers_destroy(pHddTdlsCtx);
842 wlan_hdd_tdls_peer_timers_destroy(pHddTdlsCtx);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800843}
844
Hoonki Lee387663d2013-02-05 18:08:43 -0800845/* if mac address exist, return pointer
846 if mac address doesn't exist, create a list and add, return pointer
847 return NULL if fails to get new mac address
848*/
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800849hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, u8 *mac)
Chilam NG571c65a2013-01-19 12:27:36 +0530850{
Hoonki Lee387663d2013-02-05 18:08:43 -0800851 struct list_head *head;
852 hddTdlsPeer_t *peer;
853 u8 key;
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -0700854 tdlsCtx_t *pHddTdlsCtx;
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530855 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
856
857 if ((NULL == pHddCtx)) return NULL;
Hoonki Leebfee0342013-01-21 16:43:45 -0800858
Hoonki Lee387663d2013-02-05 18:08:43 -0800859 /* if already there, just update */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +0530860 peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Hoonki Lee387663d2013-02-05 18:08:43 -0800861 if (peer != NULL)
862 {
863 return peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530864 }
865
Hoonki Lee387663d2013-02-05 18:08:43 -0800866 /* not found, allocate and add the list */
867 peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
868 if (NULL == peer) {
869 hddLog(VOS_TRACE_LEVEL_ERROR, "%s peer malloc failed!", __func__);
870 return NULL;
871 }
Chilam NG571c65a2013-01-19 12:27:36 +0530872
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530873 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
Hoonki Lee387663d2013-02-05 18:08:43 -0800874 {
875 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -0700876 "%s: unable to lock list", __func__);
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -0700877 vos_mem_free(peer);
Hoonki Lee387663d2013-02-05 18:08:43 -0800878 return NULL;
879 }
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -0700880 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
881
882 if (NULL == pHddTdlsCtx)
883 {
884 vos_mem_free(peer);
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530885 mutex_unlock(&pHddCtx->tdls_lock);
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -0700886 return NULL;
887 }
888
889 key = wlan_hdd_tdls_hash_key(mac);
890 head = &pHddTdlsCtx->peer_list[key];
Chilam NG571c65a2013-01-19 12:27:36 +0530891
Hoonki Lee387663d2013-02-05 18:08:43 -0800892 vos_mem_zero(peer, sizeof(hddTdlsPeer_t));
893 vos_mem_copy(peer->peerMac, mac, sizeof(peer->peerMac));
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800894 peer->pHddTdlsCtx = pHddTdlsCtx;
Hoonki Lee387663d2013-02-05 18:08:43 -0800895
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800896 vos_timer_init(&peer->peerIdleTimer,
897 VOS_TIMER_TYPE_SW,
898 wlan_hdd_tdls_idle_cb,
899 peer);
900
Hoonki Lee14621352013-04-16 17:51:19 -0700901 vos_timer_init(&peer->initiatorWaitTimeoutTimer,
902 VOS_TIMER_TYPE_SW,
903 wlan_hdd_tdls_initiator_wait_cb,
904 peer);
905
Hoonki Lee387663d2013-02-05 18:08:43 -0800906 list_add_tail(&peer->node, head);
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +0530907 mutex_unlock(&pHddCtx->tdls_lock);
Hoonki Lee387663d2013-02-05 18:08:43 -0800908
909 return peer;
910}
911
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700912int wlan_hdd_tdls_set_cap(hdd_adapter_t *pAdapter,
Hoonki Lee27511902013-03-14 18:19:06 -0700913 u8* mac,
914 tTDLSCapType cap)
915{
916 hddTdlsPeer_t *curr_peer;
917
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700918 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee27511902013-03-14 18:19:06 -0700919 if (curr_peer == NULL)
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700920 return -1;
Hoonki Lee27511902013-03-14 18:19:06 -0700921
922 curr_peer->tdls_support = cap;
923
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700924 return 0;
Hoonki Lee27511902013-03-14 18:19:06 -0700925}
926
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800927void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer, tTDLSLinkStatus status)
Hoonki Lee387663d2013-02-05 18:08:43 -0800928{
929 if (curr_peer == NULL)
930 return;
931
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800932 hddLog(VOS_TRACE_LEVEL_WARN, "tdls set peer " MAC_ADDRESS_STR " link status to %u",
Chilam Ng01120412013-02-19 18:32:21 -0800933 MAC_ADDR_ARRAY(curr_peer->peerMac), status);
Chilam NG571c65a2013-01-19 12:27:36 +0530934
935 curr_peer->link_status = status;
936
Chilam NG571c65a2013-01-19 12:27:36 +0530937}
938
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800939void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter,
940 u8* mac,
941 tTDLSLinkStatus linkStatus)
942{
943 hddTdlsPeer_t *curr_peer;
944
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +0530945 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800946 if (curr_peer == NULL)
947 return;
948
949 curr_peer->link_status= linkStatus;
950
951 return;
952}
953
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800954int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter, u8 *mac)
Chilam NG571c65a2013-01-19 12:27:36 +0530955{
956 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700957 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +0530958 hdd_context_t *pHddCtx;
959
960 if ( NULL == pHddTdlsCtx )
961 return -1;
962
963 pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter);
964
965 if (NULL == pHddCtx)
966 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530967
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800968 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700969
970 if (NULL == curr_peer)
Hoonki Lee387663d2013-02-05 18:08:43 -0800971 return -1;
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700972
973 if (pHddTdlsCtx->discovery_sent_cnt)
974 pHddTdlsCtx->discovery_sent_cnt--;
975
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +0530976 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
977 {
978 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
979 "%s: unable to lock list", __func__);
980 return -1;
981 }
982
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700983 wlan_hdd_tdls_check_power_save_prohibited(pAdapter);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +0530984
985 mutex_unlock(&pHddCtx->tdls_lock);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700986 if (0 == pHddTdlsCtx->discovery_sent_cnt)
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700987 {
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700988 vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700989 }
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700990
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800991 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -0700992 "Discovery(%u) Response from " MAC_ADDRESS_STR " link_status %d",
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700993 pHddTdlsCtx->discovery_sent_cnt, MAC_ADDR_ARRAY(curr_peer->peerMac),
994 curr_peer->link_status);
995
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800996 if (eTDLS_LINK_DISCOVERING == curr_peer->link_status)
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800997 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -0700998 /* Since we are here, it means Throughput threshold is alredy met. Make sure RSSI
999 threshold is also met before setting up TDLS link*/
1000 if ((tANI_S32) curr_peer->rssi > (tANI_S32) pHddTdlsCtx->threshold_config.rssi_trigger_threshold)
1001 {
1002 curr_peer->link_status = eTDLS_LINK_DISCOVERED;
1003 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1004 "Rssi Threshold met: "MAC_ADDRESS_STR" rssi = %d threshold= %d" ,
1005 MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->rssi,
1006 pHddTdlsCtx->threshold_config.rssi_trigger_threshold);
1007 cfg80211_tdls_oper_request(pAdapter->dev, curr_peer->peerMac, NL80211_TDLS_SETUP, FALSE, GFP_KERNEL);
1008 }
1009 else
1010 {
1011 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1012 "Rssi Threshold not met: "MAC_ADDRESS_STR" rssi = %d threshold = %d ",
1013 MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->rssi,
1014 pHddTdlsCtx->threshold_config.rssi_trigger_threshold);
1015 curr_peer->link_status = eTDLS_LINK_IDLE;
1016 }
Gopichand Nakkala901e8922013-03-04 23:45:58 -08001017 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001018 else
1019 {
1020 wlan_hdd_tdls_check_bmps(pAdapter);
1021 }
Chilam NG571c65a2013-01-19 12:27:36 +05301022
Gopichand Nakkala901e8922013-03-04 23:45:58 -08001023 curr_peer->tdls_support = eTDLS_CAP_SUPPORTED;
Hoonki Lee387663d2013-02-05 18:08:43 -08001024 return 0;
Chilam NG571c65a2013-01-19 12:27:36 +05301025}
1026
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05301027int wlan_hdd_tdls_set_peer_caps(hdd_adapter_t *pAdapter,
1028 u8 *mac,
1029 tANI_U8 uapsdQueues,
1030 tANI_U8 maxSp,
1031 tANI_BOOLEAN isBufSta)
1032{
1033 hddTdlsPeer_t *curr_peer;
1034
1035 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
1036 if (curr_peer == NULL)
1037 return -1;
1038
1039 curr_peer->uapsdQueues = uapsdQueues;
1040 curr_peer->maxSp = maxSp;
1041 curr_peer->isBufSta = isBufSta;
1042 return 0;
1043}
1044
1045int wlan_hdd_tdls_get_link_establish_params(hdd_adapter_t *pAdapter, u8 *mac,
1046 tCsrTdlsLinkEstablishParams* tdlsLinkEstablishParams)
1047{
1048 hddTdlsPeer_t *curr_peer;
1049
1050 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
1051 if (curr_peer == NULL)
1052 return -1;
1053
1054 tdlsLinkEstablishParams->isResponder = curr_peer->is_responder;
1055 tdlsLinkEstablishParams->uapsdQueues = curr_peer->uapsdQueues;
1056 tdlsLinkEstablishParams->maxSp = curr_peer->maxSp;
1057 tdlsLinkEstablishParams->isBufSta = curr_peer->isBufSta;
1058 return 0;
1059}
1060
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001061int wlan_hdd_tdls_set_rssi(hdd_adapter_t *pAdapter, u8 *mac, tANI_S8 rxRssi)
Chilam NG571c65a2013-01-19 12:27:36 +05301062{
1063 hddTdlsPeer_t *curr_peer;
Chilam NG571c65a2013-01-19 12:27:36 +05301064
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301065 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Hoonki Lee387663d2013-02-05 18:08:43 -08001066 if (curr_peer == NULL)
1067 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +05301068
1069 curr_peer->rssi = rxRssi;
1070
Hoonki Lee387663d2013-02-05 18:08:43 -08001071 return 0;
Chilam NG571c65a2013-01-19 12:27:36 +05301072}
1073
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001074int wlan_hdd_tdls_set_responder(hdd_adapter_t *pAdapter, u8 *mac, tANI_U8 responder)
Hoonki Leea34dd892013-02-05 22:56:02 -08001075{
1076 hddTdlsPeer_t *curr_peer;
1077
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001078 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Gopichand Nakkala91b09262013-02-10 14:27:02 -08001079 if (curr_peer == NULL)
Hoonki Leea34dd892013-02-05 22:56:02 -08001080 return -1;
1081
1082 curr_peer->is_responder = responder;
1083
1084 return 0;
1085}
1086
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001087int wlan_hdd_tdls_get_responder(hdd_adapter_t *pAdapter, u8 *mac)
Hoonki Leea34dd892013-02-05 22:56:02 -08001088{
1089 hddTdlsPeer_t *curr_peer;
1090
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301091 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkala91b09262013-02-10 14:27:02 -08001092 if (curr_peer == NULL)
Hoonki Leea34dd892013-02-05 22:56:02 -08001093 return -1;
1094
1095 return (curr_peer->is_responder);
1096}
1097
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001098int wlan_hdd_tdls_set_signature(hdd_adapter_t *pAdapter, u8 *mac, tANI_U8 uSignature)
Hoonki Lee11f7dda2013-02-14 16:55:44 -08001099{
1100 hddTdlsPeer_t *curr_peer;
1101
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001102 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08001103 if (curr_peer == NULL)
1104 return -1;
1105
1106 curr_peer->signature = uSignature;
1107
1108 return 0;
1109}
1110
Hoonki Leea34dd892013-02-05 22:56:02 -08001111
Hoonki Lee387663d2013-02-05 18:08:43 -08001112void wlan_hdd_tdls_extract_da(struct sk_buff *skb, u8 *mac)
Chilam NG571c65a2013-01-19 12:27:36 +05301113{
Chilam NG571c65a2013-01-19 12:27:36 +05301114 memcpy(mac, skb->data, 6);
Chilam NG571c65a2013-01-19 12:27:36 +05301115}
1116
Hoonki Lee387663d2013-02-05 18:08:43 -08001117void wlan_hdd_tdls_extract_sa(struct sk_buff *skb, u8 *mac)
Chilam Ng1279e232013-01-25 15:06:52 -08001118{
Chilam Ng1279e232013-01-25 15:06:52 -08001119 memcpy(mac, skb->data+6, 6);
Chilam Ng1279e232013-01-25 15:06:52 -08001120}
1121
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001122int wlan_hdd_tdls_increment_pkt_count(hdd_adapter_t *pAdapter, u8 *mac, u8 tx)
Chilam NG571c65a2013-01-19 12:27:36 +05301123{
Hoonki Lee387663d2013-02-05 18:08:43 -08001124 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001125 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam NG571c65a2013-01-19 12:27:36 +05301126
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001127 if (eTDLS_SUPPORT_ENABLED != pHddCtx->tdls_mode)
1128 return -1;
Hoonki Leebfee0342013-01-21 16:43:45 -08001129
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001130 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -08001131 if (curr_peer == NULL)
Chilam NG571c65a2013-01-19 12:27:36 +05301132 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +05301133
Chilam Ng1279e232013-01-25 15:06:52 -08001134 if (tx)
1135 curr_peer->tx_pkt++;
1136 else
1137 curr_peer->rx_pkt++;
Chilam NG571c65a2013-01-19 12:27:36 +05301138
Chilam NG571c65a2013-01-19 12:27:36 +05301139 return 0;
1140}
1141
Hoonki Lee27511902013-03-14 18:19:06 -07001142static int wlan_hdd_tdls_check_config(tdls_config_params_t *config)
1143{
1144 if (config->tdls > 2)
1145 {
1146 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 1st argument %d. <0...2>", __func__, config->tdls);
1147 return -1;
1148 }
1149 if (config->tx_period_t < CFG_TDLS_TX_STATS_PERIOD_MIN ||
1150 config->tx_period_t > CFG_TDLS_TX_STATS_PERIOD_MAX)
1151 {
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001152 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 2nd argument %d. <%d...%ld>", __func__, config->tx_period_t,
Hoonki Lee27511902013-03-14 18:19:06 -07001153 CFG_TDLS_TX_STATS_PERIOD_MIN, CFG_TDLS_TX_STATS_PERIOD_MAX);
1154 return -1;
1155 }
1156 if (config->tx_packet_n < CFG_TDLS_TX_PACKET_THRESHOLD_MIN ||
1157 config->tx_packet_n > CFG_TDLS_TX_PACKET_THRESHOLD_MAX)
1158 {
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001159 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 3rd argument %d. <%d...%ld>", __func__, config->tx_packet_n,
Hoonki Lee27511902013-03-14 18:19:06 -07001160 CFG_TDLS_TX_PACKET_THRESHOLD_MIN, CFG_TDLS_TX_PACKET_THRESHOLD_MAX);
1161 return -1;
1162 }
1163 if (config->discovery_period_t < CFG_TDLS_DISCOVERY_PERIOD_MIN ||
1164 config->discovery_period_t > CFG_TDLS_DISCOVERY_PERIOD_MAX)
1165 {
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001166 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 4th argument %d. <%d...%ld>", __func__, config->discovery_period_t,
Hoonki Lee27511902013-03-14 18:19:06 -07001167 CFG_TDLS_DISCOVERY_PERIOD_MIN, CFG_TDLS_DISCOVERY_PERIOD_MAX);
1168 return -1;
1169 }
1170 if (config->discovery_tries_n < CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MIN ||
1171 config->discovery_tries_n > CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MAX)
1172 {
1173 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 5th argument %d. <%d...%d>", __func__, config->discovery_tries_n,
1174 CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MIN, CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MAX);
1175 return -1;
1176 }
1177 if (config->idle_timeout_t < CFG_TDLS_IDLE_TIMEOUT_MIN ||
1178 config->idle_timeout_t > CFG_TDLS_IDLE_TIMEOUT_MAX)
1179 {
1180 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 6th argument %d. <%d...%d>", __func__, config->idle_timeout_t,
1181 CFG_TDLS_IDLE_TIMEOUT_MIN, CFG_TDLS_IDLE_TIMEOUT_MAX);
1182 return -1;
1183 }
1184 if (config->idle_packet_n < CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN ||
1185 config->idle_packet_n > CFG_TDLS_IDLE_PACKET_THRESHOLD_MAX)
1186 {
1187 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 7th argument %d. <%d...%d>", __func__, config->idle_packet_n,
1188 CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN, CFG_TDLS_IDLE_PACKET_THRESHOLD_MAX);
1189 return -1;
1190 }
1191 if (config->rssi_hysteresis < CFG_TDLS_RSSI_HYSTERESIS_MIN ||
1192 config->rssi_hysteresis > CFG_TDLS_RSSI_HYSTERESIS_MAX)
1193 {
1194 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 8th argument %d. <%d...%d>", __func__, config->rssi_hysteresis,
1195 CFG_TDLS_RSSI_HYSTERESIS_MIN, CFG_TDLS_RSSI_HYSTERESIS_MAX);
1196 return -1;
1197 }
1198 if (config->rssi_trigger_threshold < CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MIN ||
1199 config->rssi_trigger_threshold > CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MAX)
1200 {
1201 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 9th argument %d. <%d...%d>", __func__, config->rssi_trigger_threshold,
1202 CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MIN, CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MAX);
1203 return -1;
1204 }
1205 if (config->rssi_teardown_threshold < CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN ||
1206 config->rssi_teardown_threshold > CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX)
1207 {
1208 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 10th argument %d. <%d...%d>", __func__, config->rssi_teardown_threshold,
1209 CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN, CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX);
1210 return -1;
1211 }
1212 return 0;
1213}
1214
Chilam Ng01120412013-02-19 18:32:21 -08001215int wlan_hdd_tdls_set_params(struct net_device *dev, tdls_config_params_t *config)
Chilam NG571c65a2013-01-19 12:27:36 +05301216{
Chilam Ng01120412013-02-19 18:32:21 -08001217 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1218 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001219 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Hoonki Lee27511902013-03-14 18:19:06 -07001220 eTDLSSupportMode req_tdls_mode;
Hoonki Leebfee0342013-01-21 16:43:45 -08001221
Hoonki Lee27511902013-03-14 18:19:06 -07001222 if (NULL == pHddTdlsCtx)
1223 {
1224 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS not enabled!", __func__);
1225 return -1;
Chilam Ng01120412013-02-19 18:32:21 -08001226 }
Chilam NG571c65a2013-01-19 12:27:36 +05301227
Hoonki Lee27511902013-03-14 18:19:06 -07001228 if (wlan_hdd_tdls_check_config(config) != 0)
1229 {
1230 return -1;
1231 }
1232
1233 /* config->tdls is mapped to 0->1, 1->2, 2->3 */
1234 req_tdls_mode = config->tdls + 1;
1235 if (pHddCtx->tdls_mode == req_tdls_mode)
1236 {
1237 hddLog(VOS_TRACE_LEVEL_ERROR, "%s already in mode %d", __func__, config->tdls);
1238 return -1;
1239 }
1240
1241 /* copy the configuration only when given tdls mode is implicit trigger enable */
1242 if (eTDLS_SUPPORT_ENABLED == req_tdls_mode)
1243 {
Chilam Ng01120412013-02-19 18:32:21 -08001244 memcpy(&pHddTdlsCtx->threshold_config, config, sizeof(tdls_config_params_t));
1245 }
Chilam NG571c65a2013-01-19 12:27:36 +05301246
Chilam Ng01120412013-02-19 18:32:21 -08001247 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1248 "iw set tdls params: %d %d %d %d %d %d %d %d %d %d",
1249 config->tdls,
1250 config->tx_period_t,
1251 config->tx_packet_n,
1252 config->discovery_period_t,
1253 config->discovery_tries_n,
1254 config->idle_timeout_t,
1255 config->idle_packet_n,
1256 config->rssi_hysteresis,
1257 config->rssi_trigger_threshold,
1258 config->rssi_teardown_threshold);
Chilam NG571c65a2013-01-19 12:27:36 +05301259
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07001260 wlan_hdd_tdls_set_mode(pHddCtx, req_tdls_mode, TRUE);
Chilam Ng01120412013-02-19 18:32:21 -08001261
Chilam NG571c65a2013-01-19 12:27:36 +05301262 return 0;
1263}
1264
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001265int wlan_hdd_tdls_set_sta_id(hdd_adapter_t *pAdapter, u8 *mac, u8 staId)
Kiran V1ccee932012-12-12 14:49:46 -08001266{
Hoonki Lee387663d2013-02-05 18:08:43 -08001267 hddTdlsPeer_t *curr_peer;
Kiran V1ccee932012-12-12 14:49:46 -08001268
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001269 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -08001270 if (curr_peer == NULL)
Chilam NG571c65a2013-01-19 12:27:36 +05301271 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +05301272
Hoonki Lee387663d2013-02-05 18:08:43 -08001273 curr_peer->staId = staId;
Chilam NG571c65a2013-01-19 12:27:36 +05301274
1275 return 0;
Kiran V1ccee932012-12-12 14:49:46 -08001276}
1277
Sunil Dutt41de4e22013-11-14 18:09:02 +05301278int wpa_tdls_is_allowed_force_peer(tdlsCtx_t *pHddTdlsCtx, u8 *mac)
1279{
1280 int i;
1281 for (i=0; i<pHddTdlsCtx->forcePeerCnt; i++)
1282 {
1283 if (!memcmp(mac, pHddTdlsCtx->forcePeer[i].macAddr, 6))
1284 {
1285 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1286 "%s: " MAC_ADDRESS_STR "is a forced peer",
1287 __func__,MAC_ADDR_ARRAY(mac));
1288 return 1;
1289 }
1290 }
1291 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1292 "%s: " MAC_ADDRESS_STR "is not a forced peer",
1293 __func__,MAC_ADDR_ARRAY(mac));
1294 return 0;
1295}
1296
1297int wlan_hdd_tdls_remove_force_peer(hdd_adapter_t *pAdapter, u8 *mac)
1298{
1299 int i;
1300 tdlsCtx_t *pHddTdlsCtx;
1301 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1302
1303 if ((NULL == pHddCtx)) return -1;
1304
1305 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
1306 {
1307 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1308 "%s: unable to lock list", __func__);
1309 return -1;
1310 }
1311
1312 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
1313 if (NULL == pHddTdlsCtx)
1314 {
1315 mutex_unlock(&pHddCtx->tdls_lock);
1316 return -1;
1317 }
1318
1319 for (i=0; i<HDD_MAX_NUM_TDLS_STA; i++)
1320 {
1321 if (!memcmp(mac, pHddTdlsCtx->forcePeer[i].macAddr, 6))
1322 {
1323 /*
1324 * Entry Already Exists,Clear the entry and return.
1325 */
1326 memset(pHddTdlsCtx->forcePeer[i].macAddr, 0, 6);
1327 pHddTdlsCtx->forcePeerCnt--;
1328 mutex_unlock(&pHddCtx->tdls_lock);
1329 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1330 "%s: Removed the requested foce peer", __func__);
1331 return 0;
1332 }
1333 }
1334
1335 /* Should not have come here if the existing entry has to be removed */
1336 mutex_unlock(&pHddCtx->tdls_lock);
1337 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1338 "%s: Failed to remove the requested force peer: No Entry Found ", __func__);
1339 return -1;
1340}
1341
1342int wlan_hdd_tdls_add_force_peer(hdd_adapter_t *pAdapter, u8 *mac)
1343{
1344 int i ;
1345 tdlsCtx_t *pHddTdlsCtx;
1346 tANI_U8 zeroMac[6] = {0};
1347 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1348
1349 if ((NULL == pHddCtx)) return -1;
1350
1351 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
1352 {
1353 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1354 "%s: unable to lock list", __func__);
1355 return -1;
1356 }
1357
1358 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
1359 if (NULL == pHddTdlsCtx)
1360 {
1361 mutex_unlock(&pHddCtx->tdls_lock);
1362 return -1;
1363 }
1364
1365 if (pHddTdlsCtx->forcePeerCnt >= HDD_MAX_NUM_TDLS_STA )
1366 {
1367 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1368 "%s: Fail to add the requested foce peer : Quota Full"
1369 " forcePeerCnt is %d ", __func__,pHddTdlsCtx->forcePeerCnt);
1370 /* Quota Full, hence return failure from here*/
1371 goto error;
1372 }
1373
1374 for (i=0; i<HDD_MAX_NUM_TDLS_STA; i++)
1375 {
1376 if (!memcmp(mac, pHddTdlsCtx->forcePeer[i].macAddr, 6))
1377 {
1378 /*
1379 * Entry Already Exists,No need to create a new one.
1380 * Hence return from here.
1381 */
1382 mutex_unlock(&pHddCtx->tdls_lock);
1383 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1384 "%s: Add the requested foce peer success : Entry present"
1385 " forcePeerCnt is %d ", __func__,
1386 pHddTdlsCtx->forcePeerCnt);
1387 return 0;
1388 }
1389 }
1390 for (i=0; i<HDD_MAX_NUM_TDLS_STA; i++)
1391 {
1392 if ( !memcmp(pHddTdlsCtx->forcePeer[i].macAddr, zeroMac, 6) )
1393 {
1394 memcpy(pHddTdlsCtx->forcePeer[i].macAddr, mac, 6);
1395 pHddTdlsCtx->forcePeerCnt++;
1396 mutex_unlock(&pHddCtx->tdls_lock);
1397 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1398 "%s: Add the requested foce peer success at index i"
1399 " forcePeerCnt is %d ", __func__, i,
1400 pHddTdlsCtx->forcePeerCnt);
1401 return 0;
1402 }
1403 }
1404error:
1405 mutex_unlock(&pHddCtx->tdls_lock);
1406 return -1;
1407}
1408
Hoonki Lee387663d2013-02-05 18:08:43 -08001409/* if peerMac is found, then it returns pointer to hddTdlsPeer_t
1410 otherwise, it returns NULL
1411*/
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301412hddTdlsPeer_t *wlan_hdd_tdls_find_peer(hdd_adapter_t *pAdapter, u8 *mac,
1413 tANI_BOOLEAN mutexLock)
Kiran V1ccee932012-12-12 14:49:46 -08001414{
Hoonki Lee387663d2013-02-05 18:08:43 -08001415 u8 key;
1416 struct list_head *pos;
1417 struct list_head *head;
1418 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001419 tdlsCtx_t *pHddTdlsCtx;
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301420 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Hoonki Lee387663d2013-02-05 18:08:43 -08001421
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301422 if ((NULL == pHddCtx)) return NULL;
Hoonki Lee387663d2013-02-05 18:08:43 -08001423
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301424 if ( mutexLock )
Hoonki Lee387663d2013-02-05 18:08:43 -08001425 {
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301426 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
1427 {
1428 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1429 "%s: unable to lock list", __func__);
1430 return NULL;
1431 }
Hoonki Lee387663d2013-02-05 18:08:43 -08001432 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001433 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001434 if (NULL == pHddTdlsCtx)
1435 {
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301436 if ( mutexLock )
1437 mutex_unlock(&pHddCtx->tdls_lock);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001438 return NULL;
1439 }
1440
1441 key = wlan_hdd_tdls_hash_key(mac);
1442
1443 head = &pHddTdlsCtx->peer_list[key];
Hoonki Lee387663d2013-02-05 18:08:43 -08001444
1445 list_for_each(pos, head) {
1446 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
1447 if (!memcmp(mac, curr_peer->peerMac, 6)) {
1448 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1449 "findTdlsPeer: found staId %d", curr_peer->staId);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301450 if ( mutexLock )
1451 mutex_unlock(&pHddCtx->tdls_lock);
Hoonki Lee387663d2013-02-05 18:08:43 -08001452 return curr_peer;
1453 }
1454 }
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301455 if ( mutexLock )
1456 mutex_unlock(&pHddCtx->tdls_lock);
Hoonki Lee387663d2013-02-05 18:08:43 -08001457 return NULL;
1458}
1459
Hoonki Leea6d49be2013-04-05 09:43:25 -07001460hddTdlsPeer_t *wlan_hdd_tdls_find_all_peer(hdd_context_t *pHddCtx, u8 *mac)
1461{
1462 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1463 hdd_adapter_t *pAdapter = NULL;
1464 tdlsCtx_t *pHddTdlsCtx = NULL;
1465 hddTdlsPeer_t *curr_peer= NULL;
1466 VOS_STATUS status = 0;
1467
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301468 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
1469 {
1470 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1471 "%s: unable to lock list", __func__);
1472 return NULL;
1473 }
Hoonki Leea6d49be2013-04-05 09:43:25 -07001474 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1475 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1476 {
1477 pAdapter = pAdapterNode->pAdapter;
1478
1479 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
1480 if (NULL != pHddTdlsCtx)
1481 {
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301482 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, FALSE);
Hoonki Leea6d49be2013-04-05 09:43:25 -07001483 if (curr_peer)
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301484 {
1485 mutex_unlock(&pHddCtx->tdls_lock);
Hoonki Leea6d49be2013-04-05 09:43:25 -07001486 return curr_peer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301487 }
Hoonki Leea6d49be2013-04-05 09:43:25 -07001488 }
1489 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1490 pAdapterNode = pNext;
1491 }
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301492 mutex_unlock(&pHddCtx->tdls_lock);
Hoonki Leea6d49be2013-04-05 09:43:25 -07001493 return curr_peer;
1494}
1495
1496
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001497int wlan_hdd_tdls_reset_peer(hdd_adapter_t *pAdapter, u8 *mac)
Hoonki Lee387663d2013-02-05 18:08:43 -08001498{
Chilam Ng01120412013-02-19 18:32:21 -08001499 hdd_context_t *pHddCtx;
Chilam NG571c65a2013-01-19 12:27:36 +05301500 hddTdlsPeer_t *curr_peer;
Kiran V1ccee932012-12-12 14:49:46 -08001501
Chilam Ng01120412013-02-19 18:32:21 -08001502 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1503
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001504 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -08001505 if (curr_peer == NULL)
1506 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +05301507
Gopichand Nakkala901e8922013-03-04 23:45:58 -08001508 curr_peer->link_status = eTDLS_LINK_IDLE;
Hoonki Leecdd8e962013-01-20 00:45:46 -08001509 curr_peer->staId = 0;
Hoonki Lee387663d2013-02-05 18:08:43 -08001510
Chilam Ng01120412013-02-19 18:32:21 -08001511 if(eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) {
Chilam Nga75d8b62013-01-29 01:35:59 -08001512 vos_timer_stop( &curr_peer->peerIdleTimer );
Chilam Nga75d8b62013-01-29 01:35:59 -08001513 }
Hoonki Lee387663d2013-02-05 18:08:43 -08001514 return 0;
Hoonki Leecdd8e962013-01-20 00:45:46 -08001515}
1516
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001517/* Caller has to take the lock before calling this function */
Hoonki Lee27511902013-03-14 18:19:06 -07001518static void wlan_tdd_tdls_reset_tx_rx(tdlsCtx_t *pHddTdlsCtx)
1519{
1520 int i;
1521 struct list_head *head;
1522 hddTdlsPeer_t *tmp;
1523 struct list_head *pos, *q;
1524
Hoonki Lee27511902013-03-14 18:19:06 -07001525 for (i = 0; i < 256; i++) {
1526 head = &pHddTdlsCtx->peer_list[i];
1527 list_for_each_safe (pos, q, head) {
1528 tmp = list_entry(pos, hddTdlsPeer_t, node);
1529 tmp->tx_pkt = 0;
1530 tmp->rx_pkt = 0;
1531 }
1532 }
Hoonki Lee27511902013-03-14 18:19:06 -07001533
1534 return ;
1535}
1536
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001537/* Caller has to take the lock before calling this function */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001538static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001539{
1540 int i;
1541 struct list_head *head;
1542 hddTdlsPeer_t *tmp;
1543 struct list_head *pos, *q;
1544
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001545 pHddTdlsCtx->discovery_peer_cnt = 0;
1546
1547 for (i = 0; i < 256; i++) {
1548 head = &pHddTdlsCtx->peer_list[i];
1549 list_for_each_safe (pos, q, head) {
1550 tmp = list_entry(pos, hddTdlsPeer_t, node);
1551 tmp->discovery_processed = 0;
1552 }
1553 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001554
1555 return 0;
1556}
1557
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001558static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001559{
1560 int i;
1561 struct list_head *head;
1562 struct list_head *pos, *q;
1563 int discovery_peer_cnt=0;
1564 hddTdlsPeer_t *tmp;
1565
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001566 /*
1567 * This function expects the callers to acquire the Mutex.
1568 */
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001569
1570 for (i = 0; i < 256; i++) {
1571 head = &pHddTdlsCtx->peer_list[i];
1572 list_for_each_safe (pos, q, head) {
1573 tmp = list_entry(pos, hddTdlsPeer_t, node);
1574 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -08001575 "%s, %d, " MAC_ADDRESS_STR, __func__, i,
1576 MAC_ADDR_ARRAY(tmp->peerMac));
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001577 discovery_peer_cnt++;
1578 }
1579 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001580 return discovery_peer_cnt;
1581}
1582
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001583tANI_U16 wlan_hdd_tdlsConnectedPeers(hdd_adapter_t *pAdapter)
Lee Hoonkic1262f22013-01-24 21:59:00 -08001584{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001585 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1586
1587 if (NULL == pHddCtx)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001588 return 0;
Lee Hoonkic1262f22013-01-24 21:59:00 -08001589
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001590 return pHddCtx->connected_peer_count;
Lee Hoonkic1262f22013-01-24 21:59:00 -08001591}
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001592
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001593int wlan_hdd_tdls_get_all_peers(hdd_adapter_t *pAdapter, char *buf, int buflen)
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001594{
1595 int i;
1596 int len, init_len;
Hoonki Lee387663d2013-02-05 18:08:43 -08001597 struct list_head *head;
1598 struct list_head *pos;
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001599 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001600 tdlsCtx_t *pHddTdlsCtx;
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301601 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1602
1603 if ((NULL == pHddCtx)) {
1604 len = snprintf(buf, buflen, "NULL HddCtx\n");
1605 return len;
1606 }
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001607
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001608
1609 init_len = buflen;
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001610 len = scnprintf(buf, buflen, "\n%-18s%-3s%-4s%-3s%-5s\n",
1611 "MAC", "Id", "cap", "up", "RSSI");
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001612 buf += len;
1613 buflen -= len;
1614 /* 1234567890123456789012345678901234567 */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001615 len = scnprintf(buf, buflen, "---------------------------------\n");
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001616 buf += len;
1617 buflen -= len;
1618
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301619 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
Gopichand Nakkala91b09262013-02-10 14:27:02 -08001620 {
1621 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1622 "%s: unable to lock list", __func__);
1623 return init_len-buflen;
1624 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001625 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001626 if (NULL == pHddTdlsCtx) {
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301627 mutex_unlock(&pHddCtx->tdls_lock);
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001628 len = scnprintf(buf, buflen, "TDLS not enabled\n");
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001629 return len;
1630 }
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001631 for (i = 0; i < 256; i++) {
Hoonki Lee387663d2013-02-05 18:08:43 -08001632 head = &pHddTdlsCtx->peer_list[i];
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001633
Hoonki Lee387663d2013-02-05 18:08:43 -08001634 list_for_each(pos, head) {
1635 curr_peer= list_entry (pos, hddTdlsPeer_t, node);
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001636
Hoonki Lee387663d2013-02-05 18:08:43 -08001637 if (buflen < 32+1)
1638 break;
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001639 len = scnprintf(buf, buflen,
Chilam Ng01120412013-02-19 18:32:21 -08001640 MAC_ADDRESS_STR"%3d%4s%3s%5d\n",
1641 MAC_ADDR_ARRAY(curr_peer->peerMac),
Hoonki Lee387663d2013-02-05 18:08:43 -08001642 curr_peer->staId,
1643 (curr_peer->tdls_support == eTDLS_CAP_SUPPORTED) ? "Y":"N",
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07001644 TDLS_IS_CONNECTED(curr_peer) ? "Y":"N",
Hoonki Lee387663d2013-02-05 18:08:43 -08001645 curr_peer->rssi);
1646 buf += len;
1647 buflen -= len;
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001648 }
1649 }
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301650 mutex_unlock(&pHddCtx->tdls_lock);
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001651 return init_len-buflen;
1652}
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001653
1654void wlan_hdd_tdls_connection_callback(hdd_adapter_t *pAdapter)
1655{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001656 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301657 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001658
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301659 if ((NULL == pHddCtx) || (NULL == pHddTdlsCtx)) return;
1660
1661 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001662 {
1663 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1664 "%s: unable to lock list", __func__);
1665 return;
1666 }
1667
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001668 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1669 "%s, update %d discover %d", __func__,
1670 pHddTdlsCtx->threshold_config.tx_period_t,
1671 pHddTdlsCtx->threshold_config.discovery_period_t);
1672
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001673 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode)
1674 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001675 wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001676 pHddTdlsCtx->discovery_sent_cnt = 0;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001677 wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001678
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001679#ifdef FEATURE_WLAN_TDLS_INTERNAL
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001680 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
1681 &pHddTdlsCtx->peerDiscoverTimer,
1682 pHddTdlsCtx->threshold_config.discovery_period_t);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001683#endif
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001684 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
1685 &pHddTdlsCtx->peerUpdateTimer,
1686 pHddTdlsCtx->threshold_config.tx_period_t);
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001687 }
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301688 mutex_unlock(&pHddCtx->tdls_lock);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001689
1690}
1691
1692void wlan_hdd_tdls_disconnection_callback(hdd_adapter_t *pAdapter)
1693{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001694 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301695 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1696
1697 if ((NULL == pHddCtx) || (NULL == pHddTdlsCtx)) return;
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001698
1699 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s", __func__);
1700
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301701 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001702 {
1703 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1704 "%s: unable to lock list", __func__);
1705 return;
1706 }
1707 if (NULL == pHddTdlsCtx)
1708 {
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301709 mutex_unlock(&pHddCtx->tdls_lock);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001710 return;
1711 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001712 pHddTdlsCtx->discovery_sent_cnt = 0;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001713 wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001714
Madan Mohan Koyyalamudi693275b2013-07-22 19:14:09 +05301715 wlan_hdd_tdls_monitor_timers_stop(pHddTdlsCtx);
1716 wlan_hdd_tdls_peer_timers_destroy(pHddTdlsCtx);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001717 wlan_hdd_tdls_free_list(pHddTdlsCtx);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001718
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301719 mutex_unlock(&pHddCtx->tdls_lock);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001720}
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001721
1722void wlan_hdd_tdls_mgmt_completion_callback(hdd_adapter_t *pAdapter, tANI_U32 statusCode)
1723{
1724 pAdapter->mgmtTxCompletionStatus = statusCode;
1725 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s: Mgmt TX Completion %d",
1726 __func__, statusCode);
1727 complete(&pAdapter->tdls_mgmt_comp);
1728}
1729
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001730void wlan_hdd_tdls_increment_peer_count(hdd_adapter_t *pAdapter)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001731{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001732 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001733
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001734 if (NULL == pHddCtx) return;
1735
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301736 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
1737 {
1738 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1739 "%s: unable to lock list", __func__);
1740 return;
1741 }
1742
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001743 pHddCtx->connected_peer_count++;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001744 wlan_hdd_tdls_check_power_save_prohibited(pAdapter);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001745
1746 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: %d",
1747 __func__, pHddCtx->connected_peer_count);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301748
1749 mutex_unlock(&pHddCtx->tdls_lock);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001750}
1751
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001752void wlan_hdd_tdls_decrement_peer_count(hdd_adapter_t *pAdapter)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001753{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001754 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001755
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001756 if (NULL == pHddCtx) return;
1757
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301758 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
1759 {
1760 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1761 "%s: unable to lock list", __func__);
1762 return;
1763 }
1764
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001765 if (pHddCtx->connected_peer_count)
1766 pHddCtx->connected_peer_count--;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001767 wlan_hdd_tdls_check_power_save_prohibited(pAdapter);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001768
1769 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: %d",
1770 __func__, pHddCtx->connected_peer_count);
1771
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301772 mutex_unlock(&pHddCtx->tdls_lock);
1773
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001774}
1775
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001776void wlan_hdd_tdls_check_bmps(hdd_adapter_t *pAdapter)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001777{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001778 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001779 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Hoonki Lee14621352013-04-16 17:51:19 -07001780 hddTdlsPeer_t *curr_peer;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001781
Gopichand Nakkala16c02842013-03-18 12:31:35 -07001782 if ((NULL == pHddCtx) || (NULL == pHddTdlsCtx)) return;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001783
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301784 curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0);
Hoonki Lee14621352013-04-16 17:51:19 -07001785 if (NULL != curr_peer)
1786 {
1787 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1788 "%s: tdls in progress. Dont check for BMPS " MAC_ADDRESS_STR,
1789 __func__, MAC_ADDR_ARRAY (curr_peer->peerMac));
1790 return;
1791 }
1792
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001793 if ((TDLS_CTX_MAGIC != pHddCtx->tdls_scan_ctxt.magic) &&
1794 (0 == pHddCtx->connected_peer_count) &&
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001795 (0 == pHddTdlsCtx->discovery_sent_cnt))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001796 {
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001797 if (FALSE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
1798 {
1799 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001800 "%s: No TDLS peer connected/discovery sent. Enable BMPS",
1801 __func__);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001802 hdd_enable_bmps_imps(pHddCtx);
1803 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001804 }
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001805 else
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001806 {
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001807 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
1808 {
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001809 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1810 "%s: TDLS peer connected. Disable BMPS", __func__);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001811 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
1812 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001813 }
1814 return;
1815}
1816
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001817u8 wlan_hdd_tdls_is_peer_progress(hdd_adapter_t *pAdapter, u8 *mac)
1818{
1819 hddTdlsPeer_t *curr_peer;
1820
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301821 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001822 if (curr_peer == NULL)
1823 return 0;
1824
1825 return (eTDLS_LINK_CONNECTING == curr_peer->link_status);
1826}
1827
Hoonki Leefb8df672013-04-10 18:20:34 -07001828/* return pointer to hddTdlsPeer_t if TDLS is ongoing. Otherwise return NULL.
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001829 * mac - if NULL check for all the peer list, otherwise, skip this mac when skip_self is TRUE
1830 * skip_self - if TRUE, skip this mac. otherwise, check all the peer list. if
1831 mac is NULL, this argument is ignored, and check for all the peer list.
1832 */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301833static hddTdlsPeer_t *wlan_hdd_tdls_find_progress_peer(hdd_adapter_t *pAdapter, u8 *mac, u8 skip_self)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001834{
1835 int i;
1836 struct list_head *head;
1837 hddTdlsPeer_t *curr_peer;
1838 struct list_head *pos;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301839 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);;
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301840
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301841 if (NULL == pHddTdlsCtx)
1842 return NULL;
1843
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001844 for (i = 0; i < 256; i++) {
1845 head = &pHddTdlsCtx->peer_list[i];
1846 list_for_each(pos, head) {
1847 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
1848 if (skip_self && mac && !memcmp(mac, curr_peer->peerMac, 6)) {
1849 continue;
1850 }
1851 else
1852 {
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08001853 if (eTDLS_LINK_CONNECTING == curr_peer->link_status)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001854 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07001855 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001856 "%s:" MAC_ADDRESS_STR " eTDLS_LINK_CONNECTING",
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07001857 __func__, MAC_ADDR_ARRAY(curr_peer->peerMac));
Hoonki Leefb8df672013-04-10 18:20:34 -07001858 return curr_peer;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001859 }
1860 }
1861 }
1862 }
Hoonki Leefb8df672013-04-10 18:20:34 -07001863 return NULL;
1864}
1865
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301866hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx, u8 *mac, u8 skip_self)
Hoonki Leefb8df672013-04-10 18:20:34 -07001867{
1868 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1869 hdd_adapter_t *pAdapter = NULL;
1870 tdlsCtx_t *pHddTdlsCtx = NULL;
1871 hddTdlsPeer_t *curr_peer= NULL;
1872 VOS_STATUS status = 0;
1873
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301874 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
1875 {
1876 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1877 "%s: unable to lock list", __func__);
1878 return NULL;
1879 }
1880
Hoonki Leefb8df672013-04-10 18:20:34 -07001881 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1882 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1883 {
1884 pAdapter = pAdapterNode->pAdapter;
1885
1886 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
1887 if (NULL != pHddTdlsCtx)
1888 {
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301889 curr_peer = wlan_hdd_tdls_find_progress_peer(pAdapter, mac, skip_self);
Hoonki Leefb8df672013-04-10 18:20:34 -07001890 if (curr_peer)
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301891 {
1892 mutex_unlock(&pHddCtx->tdls_lock);
Hoonki Leefb8df672013-04-10 18:20:34 -07001893 return curr_peer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301894 }
Hoonki Leefb8df672013-04-10 18:20:34 -07001895 }
1896 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1897 pAdapterNode = pNext;
1898 }
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301899 mutex_unlock(&pHddCtx->tdls_lock);
Hoonki Leefb8df672013-04-10 18:20:34 -07001900 return NULL;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001901}
Hoonki Lee27511902013-03-14 18:19:06 -07001902
1903static void wlan_hdd_tdls_implicit_disable(tdlsCtx_t *pHddTdlsCtx)
1904{
Hoonki Lee27511902013-03-14 18:19:06 -07001905 wlan_hdd_tdls_timers_stop(pHddTdlsCtx);
Hoonki Lee27511902013-03-14 18:19:06 -07001906}
1907
1908static void wlan_hdd_tdls_implicit_enable(tdlsCtx_t *pHddTdlsCtx)
1909{
1910 wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001911 pHddTdlsCtx->discovery_sent_cnt = 0;
Hoonki Lee27511902013-03-14 18:19:06 -07001912 wlan_tdd_tdls_reset_tx_rx(pHddTdlsCtx);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001913 wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001914
Hoonki Lee27511902013-03-14 18:19:06 -07001915
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001916#ifdef FEATURE_WLAN_TDLS_INTERNAL
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001917 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
1918 &pHddTdlsCtx->peerDiscoverTimer,
1919 pHddTdlsCtx->threshold_config.discovery_period_t);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001920#endif
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001921 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
1922 &pHddTdlsCtx->peerUpdateTimer,
1923 pHddTdlsCtx->threshold_config.tx_period_t);
Hoonki Lee27511902013-03-14 18:19:06 -07001924}
1925
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07001926void wlan_hdd_tdls_set_mode(hdd_context_t *pHddCtx,
1927 eTDLSSupportMode tdls_mode,
1928 v_BOOL_t bUpdateLast)
Hoonki Lee27511902013-03-14 18:19:06 -07001929{
1930 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1931 VOS_STATUS status;
1932 hdd_adapter_t *pAdapter;
1933 tdlsCtx_t *pHddTdlsCtx;
1934
1935 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s mode %d", __func__, (int)tdls_mode);
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301936 if (NULL == pHddCtx)
1937 return;
Hoonki Lee27511902013-03-14 18:19:06 -07001938
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301939 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001940 {
1941 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1942 "%s: unable to lock list", __func__);
1943 return;
1944 }
1945
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001946
1947 if (pHddCtx->tdls_mode == tdls_mode)
1948 {
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001949 hddLog(TDLS_LOG_LEVEL, "%s already in mode %d", __func__, (int)tdls_mode);
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301950 mutex_unlock(&pHddCtx->tdls_lock);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001951 return;
1952 }
1953
Hoonki Lee27511902013-03-14 18:19:06 -07001954 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1955
1956 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1957 {
1958 pAdapter = pAdapterNode->pAdapter;
Hoonki Leea6d49be2013-04-05 09:43:25 -07001959 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
1960 if (NULL != pHddTdlsCtx)
Hoonki Lee27511902013-03-14 18:19:06 -07001961 {
Hoonki Leea6d49be2013-04-05 09:43:25 -07001962 if(eTDLS_SUPPORT_ENABLED == tdls_mode)
1963 wlan_hdd_tdls_implicit_enable(pHddTdlsCtx);
1964 else if((eTDLS_SUPPORT_DISABLED == tdls_mode) ||
1965 (eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode))
1966 wlan_hdd_tdls_implicit_disable(pHddTdlsCtx);
Hoonki Lee27511902013-03-14 18:19:06 -07001967 }
1968 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1969 pAdapterNode = pNext;
1970 }
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07001971 if(bUpdateLast)
1972 {
1973 pHddCtx->tdls_mode_last = tdls_mode;
1974 }
1975 else
1976 {
1977 pHddCtx->tdls_mode_last = pHddCtx->tdls_mode;
1978 }
Hoonki Lee27511902013-03-14 18:19:06 -07001979 pHddCtx->tdls_mode = tdls_mode;
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07001980
Madan Mohan Koyyalamudi263cec12013-10-07 10:57:50 +05301981 mutex_unlock(&pHddCtx->tdls_lock);
Hoonki Lee27511902013-03-14 18:19:06 -07001982}
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001983
Hoonki Leed37cbb32013-04-20 00:31:14 -07001984static void wlan_hdd_tdls_pre_setup(struct work_struct *work)
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001985{
Hoonki Leed37cbb32013-04-20 00:31:14 -07001986 tdlsCtx_t *pHddTdlsCtx =
1987 container_of(work, tdlsCtx_t, implicit_setup);
1988 hdd_context_t *pHddCtx;
1989 hddTdlsPeer_t *curr_peer;
Hoonki Leefb8df672013-04-10 18:20:34 -07001990 hddTdlsPeer_t *temp_peer;
Hoonki Leed37cbb32013-04-20 00:31:14 -07001991 int status;
1992
1993 if (NULL == pHddTdlsCtx)
1994 return;
1995
1996 if (unlikely(TDLS_CTX_MAGIC != pHddTdlsCtx->magic))
1997 return;
1998
1999 pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter);
Hoonki Leefb8df672013-04-10 18:20:34 -07002000
2001 if (NULL == pHddCtx)
2002 return;
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07002003
Hoonki Leed37cbb32013-04-20 00:31:14 -07002004 curr_peer = pHddTdlsCtx->curr_candidate;
2005
2006 if (NULL == curr_peer)
2007 return;
2008
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07002009 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter)))
2010 {
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07002011 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s: Disable BMPS", __func__);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07002012 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
2013 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07002014
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302015 temp_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0);
Hoonki Leefb8df672013-04-10 18:20:34 -07002016 if (NULL != temp_peer)
2017 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08002018 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: " MAC_ADDRESS_STR " ongoing. pre_setup ignored",
Hoonki Leefb8df672013-04-10 18:20:34 -07002019 __func__, MAC_ADDR_ARRAY(temp_peer->peerMac));
Hoonki Leed37cbb32013-04-20 00:31:14 -07002020 goto done;
Hoonki Leefb8df672013-04-10 18:20:34 -07002021 }
2022
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07002023 if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support)
2024 curr_peer->link_status = eTDLS_LINK_DISCOVERING;
2025
Hoonki Leed37cbb32013-04-20 00:31:14 -07002026 status = wlan_hdd_cfg80211_send_tdls_discover_req(pHddTdlsCtx->pAdapter->wdev.wiphy,
2027 pHddTdlsCtx->pAdapter->dev,
2028 curr_peer->peerMac);
2029
2030 if (0 != status)
2031 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08002032 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: " MAC_ADDRESS_STR " discovery could not sent",
Hoonki Leed37cbb32013-04-20 00:31:14 -07002033 __func__, MAC_ADDR_ARRAY(curr_peer->peerMac));
2034 if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support)
2035 curr_peer->link_status = eTDLS_LINK_IDLE;
2036 goto done;
2037 }
2038
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07002039 pHddTdlsCtx->discovery_sent_cnt++;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302040
2041 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
2042 {
2043 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2044 "%s: unable to lock list", __func__);
2045 return;
2046 }
2047
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002048 wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302049
2050 mutex_unlock(&pHddCtx->tdls_lock);
Jeff Johnson0299d0a2013-10-30 12:37:43 -07002051 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: discovery count %u timeout %u msec",
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07002052 __func__, pHddTdlsCtx->discovery_sent_cnt,
2053 pHddTdlsCtx->threshold_config.tx_period_t - TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE);
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07002054
2055 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
2056 &pHddTdlsCtx->peerDiscoveryTimeoutTimer,
2057 pHddTdlsCtx->threshold_config.tx_period_t - TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07002058
Hoonki Leed37cbb32013-04-20 00:31:14 -07002059done:
2060 pHddTdlsCtx->curr_candidate = NULL;
2061 pHddTdlsCtx->magic = 0;
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07002062 return;
2063}
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07002064
2065tANI_U32 wlan_hdd_tdls_discovery_sent_cnt(hdd_context_t *pHddCtx)
2066{
2067 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2068 hdd_adapter_t *pAdapter = NULL;
2069 tdlsCtx_t *pHddTdlsCtx = NULL;
2070 VOS_STATUS status = 0;
2071 tANI_U32 count = 0;
2072
2073 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2074 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2075 {
2076 pAdapter = pAdapterNode->pAdapter;
2077
Hoonki Leea6d49be2013-04-05 09:43:25 -07002078 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
2079 if (NULL != pHddTdlsCtx)
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07002080 {
Hoonki Leea6d49be2013-04-05 09:43:25 -07002081 count = count + pHddTdlsCtx->discovery_sent_cnt;
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07002082 }
2083 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2084 pAdapterNode = pNext;
2085 }
2086 return count;
2087}
2088
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002089void wlan_hdd_tdls_check_power_save_prohibited(hdd_adapter_t *pAdapter)
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07002090{
2091 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
2092 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2093
2094 if ((NULL == pHddTdlsCtx) || (NULL == pHddCtx))
2095 return;
2096
2097 if ((0 == pHddCtx->connected_peer_count) &&
2098 (0 == wlan_hdd_tdls_discovery_sent_cnt(pHddCtx)))
2099 {
2100 sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter), 0);
2101 return;
2102 }
2103 sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter), 1);
2104 return;
2105}
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002106
2107void wlan_hdd_tdls_free_scan_request (tdls_scan_context_t *tdls_scan_ctx)
2108{
2109 if (NULL == tdls_scan_ctx)
2110 return;
2111
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07002112 tdls_scan_ctx->attempt = 0;
Hoonki Leefb8df672013-04-10 18:20:34 -07002113 tdls_scan_ctx->reject = 0;
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07002114 tdls_scan_ctx->magic = 0;
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002115 tdls_scan_ctx->scan_request = NULL;
2116 return;
2117}
2118
2119int wlan_hdd_tdls_copy_scan_context(hdd_context_t *pHddCtx,
2120 struct wiphy *wiphy,
2121#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
2122 struct net_device *dev,
2123#endif
2124 struct cfg80211_scan_request *request)
2125{
2126 tdls_scan_context_t *scan_ctx;
2127
2128 if (NULL == pHddCtx )
2129 return -1;
2130
2131 scan_ctx = &pHddCtx->tdls_scan_ctxt;
2132
2133 scan_ctx->wiphy = wiphy;
2134#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
2135 scan_ctx->dev = dev;
2136#endif
2137
2138 scan_ctx->scan_request = request;
2139 return 0;
2140}
2141
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002142static void wlan_hdd_tdls_scan_init_work(hdd_context_t *pHddCtx,
2143 struct wiphy *wiphy,
2144#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
2145 struct net_device *dev,
2146#endif
2147 struct cfg80211_scan_request *request,
2148 unsigned long delay)
2149{
2150 if (TDLS_CTX_MAGIC != pHddCtx->tdls_scan_ctxt.magic)
2151 {
2152#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
2153 wlan_hdd_tdls_copy_scan_context(pHddCtx, wiphy, dev, request);
2154#else
2155 wlan_hdd_tdls_copy_scan_context(pHddCtx, wiphy, request);
2156#endif
2157 pHddCtx->tdls_scan_ctxt.attempt = 0;
2158 pHddCtx->tdls_scan_ctxt.magic = TDLS_CTX_MAGIC;
2159 }
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002160 schedule_delayed_work(&pHddCtx->tdls_scan_ctxt.tdls_scan_work, delay);
2161}
2162
2163/* return negative = caller should stop and return error code immediately
2164 return 0 = caller should stop and return success immediately
2165 return 1 = caller can continue to scan
2166 */
2167int wlan_hdd_tdls_scan_callback (hdd_adapter_t *pAdapter,
2168 struct wiphy *wiphy,
2169#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
2170 struct net_device *dev,
2171#endif
2172 struct cfg80211_scan_request *request)
2173{
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002174 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2175 u16 connectedTdlsPeers;
Hoonki Leefb8df672013-04-10 18:20:34 -07002176 hddTdlsPeer_t *curr_peer;
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002177 unsigned long delay;
2178
2179 if (NULL == pHddCtx)
2180 return 0;
2181
2182 /* if tdls is not enabled, then continue scan */
2183 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
2184 return 1;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302185 curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0);
Hoonki Leefb8df672013-04-10 18:20:34 -07002186 if (NULL != curr_peer)
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002187 {
Hoonki Leefb8df672013-04-10 18:20:34 -07002188 if (pHddCtx->tdls_scan_ctxt.reject++ >= TDLS_MAX_SCAN_REJECT)
2189 {
2190 pHddCtx->tdls_scan_ctxt.reject = 0;
2191 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2192 "%s: " MAC_ADDRESS_STR ". scan rejected %d. force it to idle",
2193 __func__, MAC_ADDR_ARRAY (curr_peer->peerMac), pHddCtx->tdls_scan_ctxt.reject);
2194
2195 wlan_hdd_tdls_set_peer_link_status (curr_peer, eTDLS_LINK_IDLE);
2196 return 1;
2197 }
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002198 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Hoonki Leefb8df672013-04-10 18:20:34 -07002199 "%s: tdls in progress. scan rejected %d",
2200 __func__, pHddCtx->tdls_scan_ctxt.reject);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002201 return -EBUSY;
2202 }
2203
2204 /* tdls teardown is ongoing */
2205 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
2206 {
2207 connectedTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
2208 if (connectedTdlsPeers && (pHddCtx->tdls_scan_ctxt.attempt < TDLS_MAX_SCAN_SCHEDULE))
2209 {
2210 delay = (unsigned long)(TDLS_DELAY_SCAN_PER_CONNECTION*connectedTdlsPeers);
2211 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2212 "%s: tdls disabled, but still connected_peers %d attempt %d. schedule scan %lu msec",
2213 __func__, connectedTdlsPeers, pHddCtx->tdls_scan_ctxt.attempt, delay);
2214
2215 wlan_hdd_tdls_scan_init_work (pHddCtx, wiphy,
2216#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
2217 dev,
2218#endif
2219 request,
2220 msecs_to_jiffies(delay));
2221 /* scan should not continue */
2222 return 0;
2223 }
2224 /* no connected peer or max retry reached, scan continue */
2225 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2226 "%s: tdls disabled. connected_peers %d attempt %d. scan allowed",
2227 __func__, connectedTdlsPeers, pHddCtx->tdls_scan_ctxt.attempt);
2228 return 1;
2229 }
2230 /* while tdls is up, first time scan */
2231 else if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode ||
2232 eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode)
2233 {
2234 /* disable implicit trigger logic & tdls operatoin */
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07002235 wlan_hdd_tdls_set_mode(pHddCtx, eTDLS_SUPPORT_DISABLED, FALSE);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002236 /* indicate the teardown all connected to peer */
2237 connectedTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
2238 if (connectedTdlsPeers)
2239 {
2240 tANI_U8 staIdx;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002241 hddTdlsPeer_t *curr_peer;
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002242
2243 for (staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
2244 {
2245 if (pHddCtx->tdlsConnInfo[staIdx].staId)
2246 {
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07002247 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002248 ("%s: indicate TDLS teadown (staId %d)"), __func__, pHddCtx->tdlsConnInfo[staIdx].staId) ;
2249
2250#ifdef CONFIG_TDLS_IMPLICIT
Hoonki Leea6d49be2013-04-05 09:43:25 -07002251 curr_peer = wlan_hdd_tdls_find_all_peer(pHddCtx, pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes);
2252 if(curr_peer)
2253 wlan_hdd_tdls_indicate_teardown(curr_peer->pHddTdlsCtx->pAdapter, curr_peer, eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002254#endif
2255 }
2256 }
2257 /* schedule scan */
2258 delay = (unsigned long)(TDLS_DELAY_SCAN_PER_CONNECTION*connectedTdlsPeers);
2259
2260 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2261 "%s: tdls enabled (mode %d), connected_peers %d. schedule scan %lu msec",
2262 __func__, pHddCtx->tdls_mode, wlan_hdd_tdlsConnectedPeers(pAdapter),
2263 delay);
2264
2265 wlan_hdd_tdls_scan_init_work (pHddCtx, wiphy,
2266#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
2267 dev,
2268#endif
2269 request,
2270 msecs_to_jiffies(delay));
2271 /* scan should not continue */
2272 return 0;
2273 }
2274 /* no connected peer, scan continue */
2275 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2276 "%s: tdls_mode %d, and no tdls connection. scan allowed",
2277 __func__, pHddCtx->tdls_mode);
2278 }
2279 return 1;
2280}
2281
2282void wlan_hdd_tdls_scan_done_callback(hdd_adapter_t *pAdapter)
2283{
2284 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002285
2286 if (NULL == pHddCtx)
2287 return;
2288
Sunil Dutt41de4e22013-11-14 18:09:02 +05302289
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002290 /* free allocated memory at scan time */
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07002291 wlan_hdd_tdls_free_scan_request (&pHddCtx->tdls_scan_ctxt);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002292
2293 /* if tdls was enabled before scan, re-enable tdls mode */
2294 if(eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode_last ||
2295 eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode_last)
2296 {
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07002297 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002298 ("%s: revert tdls mode %d"), __func__, pHddCtx->tdls_mode_last);
2299
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07002300 wlan_hdd_tdls_set_mode(pHddCtx, pHddCtx->tdls_mode_last, FALSE);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07002301 }
2302 wlan_hdd_tdls_check_bmps(pAdapter);
2303}
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07002304
2305void wlan_hdd_tdls_timer_restart(hdd_adapter_t *pAdapter,
2306 vos_timer_t *timer,
2307 v_U32_t expirationTime)
2308{
2309 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2310
2311 if (NULL == pHddStaCtx)
2312 return;
2313
2314 /* Check whether driver load unload is in progress */
2315 if(vos_is_load_unload_in_progress( VOS_MODULE_ID_VOSS, NULL))
2316 {
2317 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2318 "%s: Driver load/unload is in progress.", __func__);
2319 return;
2320 }
2321
2322 if (hdd_connIsConnected(pHddStaCtx))
2323 {
2324 vos_timer_stop(timer);
2325 vos_timer_start(timer, expirationTime);
2326 }
2327}
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002328void wlan_hdd_tdls_indicate_teardown(hdd_adapter_t *pAdapter,
2329 hddTdlsPeer_t *curr_peer,
2330 tANI_U16 reason)
2331{
2332 if (NULL == pAdapter || NULL == curr_peer)
2333 return;
2334
2335 if (eTDLS_LINK_CONNECTED != curr_peer->link_status)
2336 return;
2337
2338 wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_TEARING);
2339 cfg80211_tdls_oper_request(pAdapter->dev,
2340 curr_peer->peerMac,
2341 NL80211_TDLS_TEARDOWN,
2342 reason,
2343 GFP_KERNEL);
2344}