blob: 1ba803b6259cf9a4f7a5f345ff7f0ed5f652755e [file] [log] [blame]
Kiran V1ccee932012-12-12 14:49:46 -08001/*
Gopichand Nakkala0c1331e2013-01-07 22:49:07 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
Kiran V1ccee932012-12-12 14:49:46 -080021
22/**========================================================================
23
24 \file wlan_hdd_tdls.c
25
Chilam NG571c65a2013-01-19 12:27:36 +053026 \brief WLAN Host Device Driver implementation for TDLS
Kiran V1ccee932012-12-12 14:49:46 -080027
Kiran V1ccee932012-12-12 14:49:46 -080028 ========================================================================*/
29
30#include <wlan_hdd_includes.h>
31#include <wlan_hdd_hostapd.h>
32#include <net/cfg80211.h>
33#include <linux/netdevice.h>
34#include <linux/skbuff.h>
Chilam NG571c65a2013-01-19 12:27:36 +053035#include <linux/list.h>
Kiran V1ccee932012-12-12 14:49:46 -080036#include <linux/etherdevice.h>
37#include <net/ieee80211_radiotap.h>
38#include "wlan_hdd_tdls.h"
Chilam NG571c65a2013-01-19 12:27:36 +053039#include "wlan_hdd_cfg80211.h"
Kiran V1ccee932012-12-12 14:49:46 -080040
Chilam NG571c65a2013-01-19 12:27:36 +053041
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080042static struct mutex tdls_lock;
Gopichand Nakkala4327a152013-03-04 23:22:42 -080043static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(tdlsCtx_t *pHddTdlsCtx);
44static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t *pHddTdlsCtx);
45static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx);
Chilam NG571c65a2013-01-19 12:27:36 +053046
Hoonki Lee5a4b2172013-01-29 01:45:53 -080047#ifndef WLAN_FEATURE_TDLS_DEBUG
48#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
49#else
50#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_WARN
51#endif
52
Hoonki Lee387663d2013-02-05 18:08:43 -080053static u8 wlan_hdd_tdls_hash_key (u8 *mac)
Hoonki Leef63df0d2013-01-16 19:29:14 -080054{
55 int i;
Hoonki Lee387663d2013-02-05 18:08:43 -080056 u8 key = 0;
57
58 for (i = 0; i < 6; i++)
59 key ^= mac[i];
60
61 return key;
62}
63
Gopichand Nakkala4327a152013-03-04 23:22:42 -080064static v_VOID_t wlan_hdd_tdls_start_peer_discover_timer(tdlsCtx_t *pHddTdlsCtx,
65 tANI_BOOLEAN mutexLock,
66 v_U32_t discoveryExpiry)
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080067{
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080068 hdd_station_ctx_t *pHddStaCtx;
69
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080070 if ( mutexLock )
71 {
72 if (mutex_lock_interruptible(&tdls_lock))
73 {
74 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
75 "%s: unable to lock list: %d", __func__, __LINE__);
76 return;
77 }
78 }
79 if (NULL == pHddTdlsCtx)
80 {
81 if ( mutexLock )
82 mutex_unlock(&tdls_lock);
83 return;
84 }
85
Gopichand Nakkala4327a152013-03-04 23:22:42 -080086 if (NULL == pHddTdlsCtx->pAdapter)
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -080087 {
88 if ( mutexLock )
89 mutex_unlock(&tdls_lock);
90 return;
91 }
92
Gopichand Nakkala4327a152013-03-04 23:22:42 -080093 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pHddTdlsCtx->pAdapter);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -070094#ifdef FEATURE_WLAN_TDLS_INTERNAL
Gopichand Nakkala3046fc92013-03-23 13:56:43 -070095 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
96 &pHddTdlsCtx->peerDiscoverTimer,
97 discoveryExpiry);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -070098#endif
Gopichand Nakkala3046fc92013-03-23 13:56:43 -070099 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "beacon rssi: %d",
100 pHddTdlsCtx->ap_rssi);
101
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800102 if ( mutexLock )
103 mutex_unlock(&tdls_lock);
104
105 return;
106}
107
Hoonki Lee387663d2013-02-05 18:08:43 -0800108static v_VOID_t wlan_hdd_tdls_discover_peer_cb( v_PVOID_t userData )
109{
110 int i;
111 struct list_head *head;
112 struct list_head *pos;
Chilam NG571c65a2013-01-19 12:27:36 +0530113 hddTdlsPeer_t *curr_peer;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800114 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800115 tdlsCtx_t *pHddTdlsCtx = (tdlsCtx_t *)userData;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800116 int discover_req_sent = 0;
117 v_U32_t discover_expiry = TDLS_SUB_DISCOVERY_PERIOD;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800118 tANI_BOOLEAN doMutexLock = eANI_BOOLEAN_TRUE;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800119
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800120 if (mutex_lock_interruptible(&tdls_lock))
121 {
122 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
123 "%s: unable to lock list : %d", __func__, __LINE__);
124 return;
125 }
Hoonki Leebfee0342013-01-21 16:43:45 -0800126
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800127 if (NULL == pHddTdlsCtx)
128 {
129 mutex_unlock(&tdls_lock);
130 return;
131 }
Hoonki Leebfee0342013-01-21 16:43:45 -0800132
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800133 if (NULL == pHddTdlsCtx->pAdapter)
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800134 {
135 mutex_unlock(&tdls_lock);
136 return;
137 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800138
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800139 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pHddTdlsCtx->pAdapter);
Hoonki Leef63df0d2013-01-16 19:29:14 -0800140
Hoonki Lee387663d2013-02-05 18:08:43 -0800141 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: ", __func__);
142
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800143 if (0 == pHddTdlsCtx->discovery_peer_cnt)
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800144 pHddTdlsCtx->discovery_peer_cnt = wlan_hdd_get_tdls_discovery_peer_cnt(pHddTdlsCtx);
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800145
Chilam NG571c65a2013-01-19 12:27:36 +0530146 for (i = 0; i < 256; i++) {
Hoonki Lee387663d2013-02-05 18:08:43 -0800147 head = &pHddTdlsCtx->peer_list[i];
Chilam NG571c65a2013-01-19 12:27:36 +0530148
Hoonki Lee387663d2013-02-05 18:08:43 -0800149 list_for_each (pos, head) {
150 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
Chilam NG571c65a2013-01-19 12:27:36 +0530151
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -0800152 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800153 "%d " MAC_ADDRESS_STR " %d %d, %d %d %d %d", i,
154 MAC_ADDR_ARRAY(curr_peer->peerMac),
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800155 curr_peer->discovery_processed,
156 discover_req_sent,
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -0800157 curr_peer->tdls_support,
158 curr_peer->link_status,
159 curr_peer->discovery_attempt,
160 pHddTdlsCtx->threshold_config.discovery_tries_n);
Hoonki Lee387663d2013-02-05 18:08:43 -0800161
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800162 if (discover_req_sent < TDLS_MAX_DISCOVER_REQS_PER_TIMER) {
163 if (!curr_peer->discovery_processed) {
Chilam NG571c65a2013-01-19 12:27:36 +0530164
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800165 curr_peer->discovery_processed = 1;
166 discover_req_sent++;
167 pHddTdlsCtx->discovery_peer_cnt--;
168
169 if ((eTDLS_CAP_UNKNOWN == curr_peer->tdls_support) &&
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800170 (eTDLS_LINK_IDLE == curr_peer->link_status) &&
Gopichand Nakkalab88f6772013-02-27 18:12:56 -0800171 (curr_peer->tx_pkt >=
172 pHddTdlsCtx->threshold_config.tx_packet_n)) {
Gopichand Nakkala273d5a02013-02-19 15:15:09 -0800173
174 if (curr_peer->discovery_attempt <
175 pHddTdlsCtx->threshold_config.discovery_tries_n) {
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800176 sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter),
177 pHddTdlsCtx->pAdapter->sessionId,
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800178 curr_peer->peerMac,
179 WLAN_TDLS_DISCOVERY_REQUEST,
180 1, 0, NULL, 0, 0);
Gopichand Nakkala273d5a02013-02-19 15:15:09 -0800181 curr_peer->discovery_attempt++;
182 }
183 else
184 {
185 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
186 "%s: Maximum Discovery retries reached", __func__);
187 curr_peer->tdls_support = eTDLS_CAP_NOT_SUPPORTED;
188 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800189
190 }
191 }
Chilam NG571c65a2013-01-19 12:27:36 +0530192 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800193 else
194 goto exit_loop;
Hoonki Lee387663d2013-02-05 18:08:43 -0800195 }
Hoonki Leef63df0d2013-01-16 19:29:14 -0800196 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800197exit_loop:
Hoonki Leef63df0d2013-01-16 19:29:14 -0800198
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800199 if (0 != pHddTdlsCtx->discovery_peer_cnt) {
200 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
201 "discovery_peer_cnt is %d , Starting SUB_DISCOVERY_TIMER",
202 pHddTdlsCtx->discovery_peer_cnt);
203 discover_expiry = TDLS_SUB_DISCOVERY_PERIOD;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800204 doMutexLock = eANI_BOOLEAN_FALSE;
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800205 goto done;
206 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800207 discover_expiry = pHddTdlsCtx->threshold_config.discovery_period_t;
208
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800209 wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx);
Chilam NG571c65a2013-01-19 12:27:36 +0530210
Gopichand Nakkala638ebc72013-03-21 18:04:02 -0700211 mutex_unlock(&tdls_lock);
212
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800213 /* Commenting out the following function as it was introducing
214 * a race condition when pHddTdlsCtx is deleted. Also , this
215 * function is consuming more time in the timer callback.
216 * RSSI based trigger needs to revisit this part of the code.
217 */
218
219 /*
220 * wlan_hdd_get_rssi(pAdapter, &pHddTdlsCtx->ap_rssi);
221 */
Chilam NG571c65a2013-01-19 12:27:36 +0530222
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800223done:
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800224 wlan_hdd_tdls_start_peer_discover_timer(pHddTdlsCtx, doMutexLock, discover_expiry);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800225
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800226 if ( !doMutexLock )
227 mutex_unlock(&tdls_lock);
228 return;
Hoonki Leef63df0d2013-01-16 19:29:14 -0800229}
Chilam NG571c65a2013-01-19 12:27:36 +0530230
Hoonki Lee387663d2013-02-05 18:08:43 -0800231static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData )
Chilam NG571c65a2013-01-19 12:27:36 +0530232{
233 int i;
Hoonki Lee387663d2013-02-05 18:08:43 -0800234 struct list_head *head;
235 struct list_head *pos;
Chilam NG571c65a2013-01-19 12:27:36 +0530236 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800237 tdlsCtx_t *pHddTdlsCtx;
Hoonki Leebfee0342013-01-21 16:43:45 -0800238
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800239 if (mutex_lock_interruptible(&tdls_lock))
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800240 {
241 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
242 "%s: unable to lock list", __func__);
243 return;
244 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800245 pHddTdlsCtx = (tdlsCtx_t *)userData;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800246 if (NULL == pHddTdlsCtx)
247 {
248 mutex_unlock(&tdls_lock);
249 return;
250 }
251
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800252 if (NULL == pHddTdlsCtx->pAdapter)
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800253 {
254 mutex_unlock(&tdls_lock);
255 return;
256 }
257
Chilam NG571c65a2013-01-19 12:27:36 +0530258 for (i = 0; i < 256; i++) {
Hoonki Lee387663d2013-02-05 18:08:43 -0800259 head = &pHddTdlsCtx->peer_list[i];
Chilam NG571c65a2013-01-19 12:27:36 +0530260
Hoonki Lee387663d2013-02-05 18:08:43 -0800261 list_for_each (pos, head) {
262 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
Chilam NG571c65a2013-01-19 12:27:36 +0530263
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800264 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700265 "hdd update cb " MAC_ADDRESS_STR " link_status %d"
266 " tdls_support %d", MAC_ADDR_ARRAY(curr_peer->peerMac),
267 curr_peer->link_status, curr_peer->tdls_support);
Hoonki Lee387663d2013-02-05 18:08:43 -0800268
Chilam NG571c65a2013-01-19 12:27:36 +0530269 if (eTDLS_CAP_SUPPORTED == curr_peer->tdls_support) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800270 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800271 "%s: (tx %d, rx %d, config %d) " MAC_ADDRESS_STR " (%d) ",
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800272 __func__, curr_peer->tx_pkt, curr_peer->rx_pkt,
273 pHddTdlsCtx->threshold_config.tx_packet_n,
Chilam Ng01120412013-02-19 18:32:21 -0800274 MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->link_status);
275
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800276 if ((eTDLS_LINK_IDLE == curr_peer->link_status) ||
277 (eTDLS_LINK_DISCOVERING == curr_peer->link_status)){
Chilam NG571c65a2013-01-19 12:27:36 +0530278 if (curr_peer->tx_pkt >=
279 pHddTdlsCtx->threshold_config.tx_packet_n) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800280
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800281 if (HDD_MAX_NUM_TDLS_STA > wlan_hdd_tdlsConnectedPeers(pHddTdlsCtx->pAdapter))
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800282 {
283
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700284 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "Tput trigger TDLS pre-setup");
Chilam NG571c65a2013-01-19 12:27:36 +0530285#ifdef CONFIG_TDLS_IMPLICIT
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700286 wlan_hdd_tdls_pre_setup(pHddTdlsCtx, curr_peer);
Chilam NG571c65a2013-01-19 12:27:36 +0530287#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800288 }
289 else
290 {
291 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800292 "%s: Maximum peer connected already! %d",
293 __func__, wlan_hdd_tdlsConnectedPeers(pHddTdlsCtx->pAdapter) );
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800294 }
Hoonki Leecdd8e962013-01-20 00:45:46 -0800295 goto next_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530296 }
Hoonki Leefb8df672013-04-10 18:20:34 -0700297 }
298 else if (eTDLS_LINK_CONNECTED == curr_peer->link_status) {
Chilam Ng01120412013-02-19 18:32:21 -0800299 if ((tANI_S32)curr_peer->rssi <
300 (tANI_S32)pHddTdlsCtx->threshold_config.rssi_teardown_threshold) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800301
Chilam Ng01120412013-02-19 18:32:21 -0800302 VOS_TRACE( VOS_MODULE_ID_HDD,
303 VOS_TRACE_LEVEL_WARN,
304 "Tear down - low RSSI: " MAC_ADDRESS_STR "!",
305 MAC_ADDR_ARRAY(curr_peer->peerMac));
306#ifdef CONFIG_TDLS_IMPLICIT
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -0700307 wlan_hdd_tdls_indicate_teardown(pHddTdlsCtx->pAdapter,
308 curr_peer,
309 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
Chilam Ng01120412013-02-19 18:32:21 -0800310#endif
Hoonki Leecdd8e962013-01-20 00:45:46 -0800311 goto next_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530312 }
Chilam Ng01120412013-02-19 18:32:21 -0800313
314 if ((curr_peer->tx_pkt <
315 pHddTdlsCtx->threshold_config.idle_packet_n) &&
316 (curr_peer->rx_pkt <
317 pHddTdlsCtx->threshold_config.idle_packet_n)) {
318 if (VOS_TIMER_STATE_RUNNING !=
319 vos_timer_getCurrentState(&curr_peer->peerIdleTimer)) {
320 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
321 "Tx/Rx Idle timer start: " MAC_ADDRESS_STR "!",
322 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkala3046fc92013-03-23 13:56:43 -0700323 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
324 &curr_peer->peerIdleTimer,
325 pHddTdlsCtx->threshold_config.idle_timeout_t);
Chilam Ng01120412013-02-19 18:32:21 -0800326 }
327 } else {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800328 if (VOS_TIMER_STATE_RUNNING ==
329 vos_timer_getCurrentState(&curr_peer->peerIdleTimer)) {
Chilam Ng01120412013-02-19 18:32:21 -0800330 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
331 "Tx/Rx Idle timer stop: " MAC_ADDRESS_STR "!",
332 MAC_ADDR_ARRAY(curr_peer->peerMac));
333 vos_timer_stop( &curr_peer->peerIdleTimer);
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800334 }
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800335 }
Chilam Ng01120412013-02-19 18:32:21 -0800336
Hoonki Leecdd8e962013-01-20 00:45:46 -0800337// if (curr_peer->rssi <
338// (pHddTdlsCtx->threshold_config.rssi_hysteresis +
339// pHddTdlsCtx->ap_rssi)) {
340//
341//#ifdef CONFIG_TDLS_IMPLICIT
342// cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
343// curr_peer->peerMac,
344// NL80211_TDLS_TEARDOWN, FALSE,
345// GFP_KERNEL);
346//#endif
347// }
Chilam NG571c65a2013-01-19 12:27:36 +0530348 }
Chilam Ng01120412013-02-19 18:32:21 -0800349 } else if (eTDLS_CAP_UNKNOWN == curr_peer->tdls_support) {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -0700350 if (!TDLS_IS_CONNECTED(curr_peer)) {
Chilam Ng01120412013-02-19 18:32:21 -0800351 if (curr_peer->tx_pkt >=
352 pHddTdlsCtx->threshold_config.tx_packet_n) {
Chilam Ng01120412013-02-19 18:32:21 -0800353
Gopichand Nakkala062bcbd2013-03-29 18:14:47 -0700354 if (curr_peer->discovery_attempt++ <
Chilam Ng01120412013-02-19 18:32:21 -0800355 pHddTdlsCtx->threshold_config.discovery_tries_n) {
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700356 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "TDLS UNKNOWN discover ");
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700357 wlan_hdd_tdls_pre_setup(pHddTdlsCtx, curr_peer);
Chilam Ng01120412013-02-19 18:32:21 -0800358 }
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800359 else
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800360 {
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800361 curr_peer->tdls_support = eTDLS_CAP_NOT_SUPPORTED;
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800362 curr_peer->link_status = eTDLS_LINK_IDLE;
363 }
Chilam Ng01120412013-02-19 18:32:21 -0800364 }
365 }
Chilam NG571c65a2013-01-19 12:27:36 +0530366 }
367
Hoonki Leecdd8e962013-01-20 00:45:46 -0800368next_peer:
Chilam NG571c65a2013-01-19 12:27:36 +0530369 curr_peer->tx_pkt = 0;
Chilam Ng1279e232013-01-25 15:06:52 -0800370 curr_peer->rx_pkt = 0;
Hoonki Lee387663d2013-02-05 18:08:43 -0800371 }
Chilam NG571c65a2013-01-19 12:27:36 +0530372 }
373
Gopichand Nakkala3046fc92013-03-23 13:56:43 -0700374 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
375 &pHddTdlsCtx->peerUpdateTimer,
376 pHddTdlsCtx->threshold_config.tx_period_t);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800377 mutex_unlock(&tdls_lock);
Chilam NG571c65a2013-01-19 12:27:36 +0530378}
379
Chilam Ng1279e232013-01-25 15:06:52 -0800380static v_VOID_t wlan_hdd_tdls_idle_cb( v_PVOID_t userData )
381{
Lee Hoonkic1262f22013-01-24 21:59:00 -0800382#ifdef CONFIG_TDLS_IMPLICIT
Chilam Ng1279e232013-01-25 15:06:52 -0800383 hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData;
384
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800385 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800386 "%s: Tx/Rx Idle " MAC_ADDRESS_STR " trigger teardown",
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800387 __func__,
Chilam Ng01120412013-02-19 18:32:21 -0800388 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800389 if (mutex_lock_interruptible(&tdls_lock))
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800390 {
391 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
392 "%s: unable to lock list", __func__);
393 return;
394 }
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800395
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -0700396 wlan_hdd_tdls_indicate_teardown(curr_peer->pHddTdlsCtx->pAdapter,
397 curr_peer,
398 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800399 mutex_unlock(&tdls_lock);
Chilam Ng1279e232013-01-25 15:06:52 -0800400#endif
401}
402
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700403static v_VOID_t wlan_hdd_tdls_discovery_timeout_peer_cb(v_PVOID_t userData)
404{
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700405 int i;
406 struct list_head *head;
407 hddTdlsPeer_t *tmp;
408 struct list_head *pos, *q;
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700409 tdlsCtx_t *pHddTdlsCtx;
410
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700411 if (mutex_lock_interruptible(&tdls_lock))
412 {
413 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
414 "%s: unable to lock list", __func__);
415 return ;
416 }
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700417 pHddTdlsCtx = (tdlsCtx_t *)userData;
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700418
419 if ( NULL == pHddTdlsCtx )
420 {
421 mutex_unlock(&tdls_lock);
422 return ;
423 }
424
425 for (i = 0; i < 256; i++) {
426 head = &pHddTdlsCtx->peer_list[i];
427 list_for_each_safe (pos, q, head) {
428 tmp = list_entry(pos, hddTdlsPeer_t, node);
429 if (eTDLS_LINK_DISCOVERING == tmp->link_status)
430 {
431 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
432 "%s: " MAC_ADDRESS_STR " to idle state", __func__,
433 MAC_ADDR_ARRAY(tmp->peerMac));
434 tmp->link_status = eTDLS_LINK_IDLE;
435 }
436 }
437 }
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700438
439 pHddTdlsCtx->discovery_sent_cnt = 0;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700440 wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700441
442 mutex_unlock(&tdls_lock);
443
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700444 wlan_hdd_tdls_check_bmps(pHddTdlsCtx->pAdapter);
445
446 return;
447}
448
Hoonki Lee14621352013-04-16 17:51:19 -0700449static v_VOID_t wlan_hdd_tdls_initiator_wait_cb( v_PVOID_t userData )
450{
451 hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData;
452 tdlsCtx_t *pHddTdlsCtx;
453
454 if ( NULL == curr_peer )
455 return;
456
457 pHddTdlsCtx = curr_peer->pHddTdlsCtx;
458
459 if ( NULL == pHddTdlsCtx )
460 return;
461
462 WLANTL_ResumeDataTx( (WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter))->pvosContext,
463 (v_U8_t *)&curr_peer->staId);
464}
465
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800466static void wlan_hdd_tdls_free_list(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800467{
468 int i;
469 struct list_head *head;
470 hddTdlsPeer_t *tmp;
471 struct list_head *pos, *q;
472
473 if (NULL == pHddTdlsCtx) return;
474
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800475
476 for (i = 0; i < 256; i++) {
477 head = &pHddTdlsCtx->peer_list[i];
478 list_for_each_safe (pos, q, head) {
479 tmp = list_entry(pos, hddTdlsPeer_t, node);
480 list_del(pos);
481 vos_mem_free(tmp);
482 }
483 }
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800484}
485
Hoonki Lee27511902013-03-14 18:19:06 -0700486int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter)
Chilam Ng01120412013-02-19 18:32:21 -0800487{
Chilam Ng01120412013-02-19 18:32:21 -0800488 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Hoonki Lee27511902013-03-14 18:19:06 -0700489 tdlsCtx_t *pHddTdlsCtx;
Chilam Ng01120412013-02-19 18:32:21 -0800490 int i;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800491 v_U8_t staIdx;
Chilam Ng01120412013-02-19 18:32:21 -0800492
Hoonki Lee27511902013-03-14 18:19:06 -0700493 mutex_init(&tdls_lock);
Chilam Ng01120412013-02-19 18:32:21 -0800494
Hoonki Lee27511902013-03-14 18:19:06 -0700495 if ((FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport) ||
496 (FALSE == sme_IsFeatureSupportedByFW(TDLS)))
497 {
498 pHddCtx->tdls_mode = eTDLS_SUPPORT_NOT_ENABLED;
499 pAdapter->sessionCtx.station.pHddTdlsCtx = NULL;
500 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS not enabled (%d) or FW doesn't support (%d)!",
501 __func__, pHddCtx->cfg_ini->fEnableTDLSSupport,
502 sme_IsFeatureSupportedByFW(TDLS));
503 return 0;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800504 }
505
Hoonki Lee27511902013-03-14 18:19:06 -0700506 pHddTdlsCtx = vos_mem_malloc(sizeof(tdlsCtx_t));
507
508 if (NULL == pHddTdlsCtx) {
509 hddLog(VOS_TRACE_LEVEL_ERROR, "%s malloc failed!", __func__);
510 pAdapter->sessionCtx.station.pHddTdlsCtx = NULL;
511 return -1;
512 }
513
514 pAdapter->sessionCtx.station.pHddTdlsCtx = pHddTdlsCtx;
515
516 /* initialize TDLS global context */
517 pHddCtx->connected_peer_count = 0;
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700518 sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
Hoonki Lee27511902013-03-14 18:19:06 -0700519
Hoonki Lee93e67ff2013-03-19 15:49:25 -0700520 pHddCtx->tdls_scan_ctxt.magic = 0;
Hoonki Leefb8df672013-04-10 18:20:34 -0700521 pHddCtx->tdls_scan_ctxt.attempt = 0;
522 pHddCtx->tdls_scan_ctxt.reject = 0;
Hoonki Lee93e67ff2013-03-19 15:49:25 -0700523 pHddCtx->tdls_scan_ctxt.scan_request = NULL;
524
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800525 for (staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
526 {
527 pHddCtx->tdlsConnInfo[staIdx].staId = 0;
528 pHddCtx->tdlsConnInfo[staIdx].sessionId = 255;
529 vos_mem_zero(&pHddCtx->tdlsConnInfo[staIdx].peerMac,
530 sizeof(v_MACADDR_t)) ;
Chilam Ng01120412013-02-19 18:32:21 -0800531 }
532
Hoonki Lee27511902013-03-14 18:19:06 -0700533 /* initialize TDLS pAdater context */
534 vos_mem_zero(pHddTdlsCtx, sizeof(tdlsCtx_t));
535
536 pHddTdlsCtx->pAdapter = pAdapter;
537
538 for (i = 0; i < 256; i++)
539 {
540 INIT_LIST_HEAD(&pHddTdlsCtx->peer_list[i]);
541 }
542
Chilam Ng01120412013-02-19 18:32:21 -0800543 vos_timer_init(&pHddTdlsCtx->peerDiscoverTimer,
544 VOS_TIMER_TYPE_SW,
545 wlan_hdd_tdls_discover_peer_cb,
546 pHddTdlsCtx);
547
548 vos_timer_init(&pHddTdlsCtx->peerUpdateTimer,
549 VOS_TIMER_TYPE_SW,
550 wlan_hdd_tdls_update_peer_cb,
551 pHddTdlsCtx);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700552 vos_timer_init(&pHddTdlsCtx->peerDiscoveryTimeoutTimer,
553 VOS_TIMER_TYPE_SW,
554 wlan_hdd_tdls_discovery_timeout_peer_cb,
555 pHddTdlsCtx);
Chilam Ng01120412013-02-19 18:32:21 -0800556
Hoonki Lee27511902013-03-14 18:19:06 -0700557 /* remember configuration even if it is not used right now. it could be used later */
558 pHddTdlsCtx->threshold_config.tx_period_t = pHddCtx->cfg_ini->fTDLSTxStatsPeriod;
559 pHddTdlsCtx->threshold_config.tx_packet_n = pHddCtx->cfg_ini->fTDLSTxPacketThreshold;
560 pHddTdlsCtx->threshold_config.discovery_period_t = pHddCtx->cfg_ini->fTDLSDiscoveryPeriod;
561 pHddTdlsCtx->threshold_config.discovery_tries_n = pHddCtx->cfg_ini->fTDLSMaxDiscoveryAttempt;
562 pHddTdlsCtx->threshold_config.idle_timeout_t = pHddCtx->cfg_ini->fTDLSIdleTimeout;
563 pHddTdlsCtx->threshold_config.idle_packet_n = pHddCtx->cfg_ini->fTDLSIdlePacketThreshold;
564 pHddTdlsCtx->threshold_config.rssi_hysteresis = pHddCtx->cfg_ini->fTDLSRSSIHysteresis;
565 pHddTdlsCtx->threshold_config.rssi_trigger_threshold = pHddCtx->cfg_ini->fTDLSRSSITriggerThreshold;
566 pHddTdlsCtx->threshold_config.rssi_teardown_threshold = pHddCtx->cfg_ini->fTDLSRSSITeardownThreshold;
Chilam NG571c65a2013-01-19 12:27:36 +0530567
Chilam Ng01120412013-02-19 18:32:21 -0800568 if (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger)
Hoonki Lee387663d2013-02-05 18:08:43 -0800569 {
Chilam Ng01120412013-02-19 18:32:21 -0800570 pHddCtx->tdls_mode = eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY;
Hoonki Leebf870f32013-01-19 15:53:30 +0530571 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS Implicit trigger not enabled!", __func__);
Hoonki Leebf870f32013-01-19 15:53:30 +0530572 }
Hoonki Lee27511902013-03-14 18:19:06 -0700573 else
574 {
575 pHddCtx->tdls_mode = eTDLS_SUPPORT_ENABLED;
Hoonki Lee27511902013-03-14 18:19:06 -0700576 }
577
578 return 0;
Chilam NG571c65a2013-01-19 12:27:36 +0530579}
580
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800581void wlan_hdd_tdls_exit(hdd_adapter_t *pAdapter)
Chilam NG571c65a2013-01-19 12:27:36 +0530582{
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800583 tdlsCtx_t *pHddTdlsCtx;
Hoonki Lee93e67ff2013-03-19 15:49:25 -0700584 hdd_context_t *pHddCtx;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800585
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800586 if (mutex_lock_interruptible(&tdls_lock))
587 {
588 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
589 "%s: unable to lock list", __func__);
590 return;
591 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800592
Hoonki Lee93e67ff2013-03-19 15:49:25 -0700593 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
594 if (NULL == pHddCtx)
595 {
596 mutex_unlock(&tdls_lock);
597 return;
598 }
599
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800600 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800601 if (NULL == pHddTdlsCtx)
602 {
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800603 mutex_unlock(&tdls_lock);
Hoonki Leebfee0342013-01-21 16:43:45 -0800604 hddLog(VOS_TRACE_LEVEL_WARN, "%s TDLS not enabled, exiting!", __func__);
605 return;
606 }
607
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800608 /* must stop timer here before freeing peer list, because peerIdleTimer is
609 part of peer list structure. */
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800610 wlan_hdd_tdls_timers_destroy(pHddTdlsCtx);
611 wlan_hdd_tdls_free_list(pHddTdlsCtx);
Chilam Nga75d8b62013-01-29 01:35:59 -0800612
Hoonki Lee93e67ff2013-03-19 15:49:25 -0700613 wlan_hdd_tdls_free_scan_request(&pHddCtx->tdls_scan_ctxt);
614
Chilam Nga75d8b62013-01-29 01:35:59 -0800615 vos_mem_free(pHddTdlsCtx);
616 pHddTdlsCtx = NULL;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800617 mutex_unlock(&tdls_lock);
Chilam NG571c65a2013-01-19 12:27:36 +0530618}
619
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800620/* stop all the tdls timers running */
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800621static void wlan_hdd_tdls_timers_stop(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800622{
623 int i;
624 struct list_head *head;
625 struct list_head *pos;
626 hddTdlsPeer_t *curr_peer;
627
628 vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer);
629 vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700630 vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer);
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800631
632 for (i = 0; i < 256; i++)
633 {
634 head = &pHddTdlsCtx->peer_list[i];
635
636 list_for_each (pos, head) {
637 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
638
639 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800640 "%s: " MAC_ADDRESS_STR " -> stop idle timer",
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800641 __func__,
Chilam Ng01120412013-02-19 18:32:21 -0800642 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800643 vos_timer_stop ( &curr_peer->peerIdleTimer );
Hoonki Lee14621352013-04-16 17:51:19 -0700644 vos_timer_stop( &curr_peer->initiatorWaitTimeoutTimer );
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800645 }
646 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800647}
648
649/* destroy all the tdls timers running */
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800650static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800651{
652 int i;
653 struct list_head *head;
654 struct list_head *pos;
655 hddTdlsPeer_t *curr_peer;
656
657 vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer);
658 vos_timer_destroy(&pHddTdlsCtx->peerDiscoverTimer);
659 vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer);
660 vos_timer_destroy(&pHddTdlsCtx->peerUpdateTimer);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700661 vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer);
662 vos_timer_destroy(&pHddTdlsCtx->peerDiscoveryTimeoutTimer);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800663
664 for (i = 0; i < 256; i++)
665 {
666 head = &pHddTdlsCtx->peer_list[i];
667
668 list_for_each (pos, head) {
669 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
670
671 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800672 "%s: " MAC_ADDRESS_STR " -> destroy idle timer",
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800673 __func__,
Chilam Ng01120412013-02-19 18:32:21 -0800674 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800675 vos_timer_stop ( &curr_peer->peerIdleTimer );
676 vos_timer_destroy ( &curr_peer->peerIdleTimer );
Hoonki Lee14621352013-04-16 17:51:19 -0700677 vos_timer_stop(&curr_peer->initiatorWaitTimeoutTimer);
678 vos_timer_destroy(&curr_peer->initiatorWaitTimeoutTimer);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800679 }
680 }
681}
682
Hoonki Lee387663d2013-02-05 18:08:43 -0800683/* if mac address exist, return pointer
684 if mac address doesn't exist, create a list and add, return pointer
685 return NULL if fails to get new mac address
686*/
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800687hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, u8 *mac)
Chilam NG571c65a2013-01-19 12:27:36 +0530688{
Hoonki Lee387663d2013-02-05 18:08:43 -0800689 struct list_head *head;
690 hddTdlsPeer_t *peer;
691 u8 key;
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -0700692 tdlsCtx_t *pHddTdlsCtx;
Hoonki Leebfee0342013-01-21 16:43:45 -0800693
Hoonki Lee387663d2013-02-05 18:08:43 -0800694 /* if already there, just update */
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800695 peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -0800696 if (peer != NULL)
697 {
698 return peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530699 }
700
Hoonki Lee387663d2013-02-05 18:08:43 -0800701 /* not found, allocate and add the list */
702 peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
703 if (NULL == peer) {
704 hddLog(VOS_TRACE_LEVEL_ERROR, "%s peer malloc failed!", __func__);
705 return NULL;
706 }
Chilam NG571c65a2013-01-19 12:27:36 +0530707
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800708 if (mutex_lock_interruptible(&tdls_lock))
Hoonki Lee387663d2013-02-05 18:08:43 -0800709 {
710 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -0700711 "%s: unable to lock list", __func__);
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -0700712 vos_mem_free(peer);
Hoonki Lee387663d2013-02-05 18:08:43 -0800713 return NULL;
714 }
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -0700715 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
716
717 if (NULL == pHddTdlsCtx)
718 {
719 vos_mem_free(peer);
720 mutex_unlock(&tdls_lock);
721 return NULL;
722 }
723
724 key = wlan_hdd_tdls_hash_key(mac);
725 head = &pHddTdlsCtx->peer_list[key];
Chilam NG571c65a2013-01-19 12:27:36 +0530726
Hoonki Lee387663d2013-02-05 18:08:43 -0800727 vos_mem_zero(peer, sizeof(hddTdlsPeer_t));
728 vos_mem_copy(peer->peerMac, mac, sizeof(peer->peerMac));
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800729 peer->pHddTdlsCtx = pHddTdlsCtx;
Hoonki Lee387663d2013-02-05 18:08:43 -0800730
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800731 vos_timer_init(&peer->peerIdleTimer,
732 VOS_TIMER_TYPE_SW,
733 wlan_hdd_tdls_idle_cb,
734 peer);
735
Hoonki Lee14621352013-04-16 17:51:19 -0700736 vos_timer_init(&peer->initiatorWaitTimeoutTimer,
737 VOS_TIMER_TYPE_SW,
738 wlan_hdd_tdls_initiator_wait_cb,
739 peer);
740
Hoonki Lee387663d2013-02-05 18:08:43 -0800741 list_add_tail(&peer->node, head);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -0800742 mutex_unlock(&tdls_lock);
Hoonki Lee387663d2013-02-05 18:08:43 -0800743
744 return peer;
745}
746
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700747int wlan_hdd_tdls_set_cap(hdd_adapter_t *pAdapter,
Hoonki Lee27511902013-03-14 18:19:06 -0700748 u8* mac,
749 tTDLSCapType cap)
750{
751 hddTdlsPeer_t *curr_peer;
752
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700753 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee27511902013-03-14 18:19:06 -0700754 if (curr_peer == NULL)
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700755 return -1;
Hoonki Lee27511902013-03-14 18:19:06 -0700756
757 curr_peer->tdls_support = cap;
758
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700759 return 0;
Hoonki Lee27511902013-03-14 18:19:06 -0700760}
761
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800762void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer, tTDLSLinkStatus status)
Hoonki Lee387663d2013-02-05 18:08:43 -0800763{
764 if (curr_peer == NULL)
765 return;
766
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800767 hddLog(VOS_TRACE_LEVEL_WARN, "tdls set peer " MAC_ADDRESS_STR " link status to %u",
Chilam Ng01120412013-02-19 18:32:21 -0800768 MAC_ADDR_ARRAY(curr_peer->peerMac), status);
Chilam NG571c65a2013-01-19 12:27:36 +0530769
770 curr_peer->link_status = status;
771
Chilam NG571c65a2013-01-19 12:27:36 +0530772}
773
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800774void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter,
775 u8* mac,
776 tTDLSLinkStatus linkStatus)
777{
778 hddTdlsPeer_t *curr_peer;
779
780 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
781 if (curr_peer == NULL)
782 return;
783
784 curr_peer->link_status= linkStatus;
785
786 return;
787}
788
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800789int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter, u8 *mac)
Chilam NG571c65a2013-01-19 12:27:36 +0530790{
791 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700792 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Chilam NG571c65a2013-01-19 12:27:36 +0530793
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800794 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700795
796 if (NULL == curr_peer)
Hoonki Lee387663d2013-02-05 18:08:43 -0800797 return -1;
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700798
799 if (pHddTdlsCtx->discovery_sent_cnt)
800 pHddTdlsCtx->discovery_sent_cnt--;
801
Gopichand Nakkala34d1b062013-03-19 15:28:33 -0700802 wlan_hdd_tdls_check_power_save_prohibited(pAdapter);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700803 if (0 == pHddTdlsCtx->discovery_sent_cnt)
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700804 {
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700805 vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700806 }
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700807
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800808 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala75e7b282013-03-15 18:37:13 -0700809 "Discovery(%lu) Response from " MAC_ADDRESS_STR " link_status %d",
810 pHddTdlsCtx->discovery_sent_cnt, MAC_ADDR_ARRAY(curr_peer->peerMac),
811 curr_peer->link_status);
812
Gopichand Nakkala8b00c632013-03-08 19:47:52 -0800813 if (eTDLS_LINK_DISCOVERING == curr_peer->link_status)
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800814 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -0700815 /* Since we are here, it means Throughput threshold is alredy met. Make sure RSSI
816 threshold is also met before setting up TDLS link*/
817 if ((tANI_S32) curr_peer->rssi > (tANI_S32) pHddTdlsCtx->threshold_config.rssi_trigger_threshold)
818 {
819 curr_peer->link_status = eTDLS_LINK_DISCOVERED;
820 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
821 "Rssi Threshold met: "MAC_ADDRESS_STR" rssi = %d threshold= %d" ,
822 MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->rssi,
823 pHddTdlsCtx->threshold_config.rssi_trigger_threshold);
824 cfg80211_tdls_oper_request(pAdapter->dev, curr_peer->peerMac, NL80211_TDLS_SETUP, FALSE, GFP_KERNEL);
825 }
826 else
827 {
828 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
829 "Rssi Threshold not met: "MAC_ADDRESS_STR" rssi = %d threshold = %d ",
830 MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->rssi,
831 pHddTdlsCtx->threshold_config.rssi_trigger_threshold);
832 curr_peer->link_status = eTDLS_LINK_IDLE;
833 }
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800834 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -0700835 else
836 {
837 wlan_hdd_tdls_check_bmps(pAdapter);
838 }
Chilam NG571c65a2013-01-19 12:27:36 +0530839
Gopichand Nakkala901e8922013-03-04 23:45:58 -0800840 curr_peer->tdls_support = eTDLS_CAP_SUPPORTED;
Hoonki Lee387663d2013-02-05 18:08:43 -0800841 return 0;
Chilam NG571c65a2013-01-19 12:27:36 +0530842}
843
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800844int wlan_hdd_tdls_set_rssi(hdd_adapter_t *pAdapter, u8 *mac, tANI_S8 rxRssi)
Chilam NG571c65a2013-01-19 12:27:36 +0530845{
846 hddTdlsPeer_t *curr_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530847
Shailender Karmuchi13c0d082013-03-26 14:41:39 -0700848 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -0800849 if (curr_peer == NULL)
850 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530851
852 curr_peer->rssi = rxRssi;
853
Hoonki Lee387663d2013-02-05 18:08:43 -0800854 return 0;
Chilam NG571c65a2013-01-19 12:27:36 +0530855}
856
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800857int wlan_hdd_tdls_set_responder(hdd_adapter_t *pAdapter, u8 *mac, tANI_U8 responder)
Hoonki Leea34dd892013-02-05 22:56:02 -0800858{
859 hddTdlsPeer_t *curr_peer;
860
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800861 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800862 if (curr_peer == NULL)
Hoonki Leea34dd892013-02-05 22:56:02 -0800863 return -1;
864
865 curr_peer->is_responder = responder;
866
867 return 0;
868}
869
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800870int wlan_hdd_tdls_get_responder(hdd_adapter_t *pAdapter, u8 *mac)
Hoonki Leea34dd892013-02-05 22:56:02 -0800871{
872 hddTdlsPeer_t *curr_peer;
873
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800874 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800875 if (curr_peer == NULL)
Hoonki Leea34dd892013-02-05 22:56:02 -0800876 return -1;
877
878 return (curr_peer->is_responder);
879}
880
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800881int wlan_hdd_tdls_set_signature(hdd_adapter_t *pAdapter, u8 *mac, tANI_U8 uSignature)
Hoonki Lee11f7dda2013-02-14 16:55:44 -0800882{
883 hddTdlsPeer_t *curr_peer;
884
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800885 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee11f7dda2013-02-14 16:55:44 -0800886 if (curr_peer == NULL)
887 return -1;
888
889 curr_peer->signature = uSignature;
890
891 return 0;
892}
893
Hoonki Leea34dd892013-02-05 22:56:02 -0800894
Hoonki Lee387663d2013-02-05 18:08:43 -0800895void wlan_hdd_tdls_extract_da(struct sk_buff *skb, u8 *mac)
Chilam NG571c65a2013-01-19 12:27:36 +0530896{
Chilam NG571c65a2013-01-19 12:27:36 +0530897 memcpy(mac, skb->data, 6);
Chilam NG571c65a2013-01-19 12:27:36 +0530898}
899
Hoonki Lee387663d2013-02-05 18:08:43 -0800900void wlan_hdd_tdls_extract_sa(struct sk_buff *skb, u8 *mac)
Chilam Ng1279e232013-01-25 15:06:52 -0800901{
Chilam Ng1279e232013-01-25 15:06:52 -0800902 memcpy(mac, skb->data+6, 6);
Chilam Ng1279e232013-01-25 15:06:52 -0800903}
904
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800905int wlan_hdd_tdls_increment_pkt_count(hdd_adapter_t *pAdapter, u8 *mac, u8 tx)
Chilam NG571c65a2013-01-19 12:27:36 +0530906{
Hoonki Lee387663d2013-02-05 18:08:43 -0800907 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800908 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam NG571c65a2013-01-19 12:27:36 +0530909
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800910 if (eTDLS_SUPPORT_ENABLED != pHddCtx->tdls_mode)
911 return -1;
Hoonki Leebfee0342013-01-21 16:43:45 -0800912
Gopichand Nakkala4327a152013-03-04 23:22:42 -0800913 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -0800914 if (curr_peer == NULL)
Chilam NG571c65a2013-01-19 12:27:36 +0530915 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530916
Chilam Ng1279e232013-01-25 15:06:52 -0800917 if (tx)
918 curr_peer->tx_pkt++;
919 else
920 curr_peer->rx_pkt++;
Chilam NG571c65a2013-01-19 12:27:36 +0530921
Chilam NG571c65a2013-01-19 12:27:36 +0530922 return 0;
923}
924
Hoonki Lee27511902013-03-14 18:19:06 -0700925static int wlan_hdd_tdls_check_config(tdls_config_params_t *config)
926{
927 if (config->tdls > 2)
928 {
929 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 1st argument %d. <0...2>", __func__, config->tdls);
930 return -1;
931 }
932 if (config->tx_period_t < CFG_TDLS_TX_STATS_PERIOD_MIN ||
933 config->tx_period_t > CFG_TDLS_TX_STATS_PERIOD_MAX)
934 {
935 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 2nd argument %d. <%d...%d>", __func__, config->tx_period_t,
936 CFG_TDLS_TX_STATS_PERIOD_MIN, CFG_TDLS_TX_STATS_PERIOD_MAX);
937 return -1;
938 }
939 if (config->tx_packet_n < CFG_TDLS_TX_PACKET_THRESHOLD_MIN ||
940 config->tx_packet_n > CFG_TDLS_TX_PACKET_THRESHOLD_MAX)
941 {
942 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 3rd argument %d. <%d...%d>", __func__, config->tx_packet_n,
943 CFG_TDLS_TX_PACKET_THRESHOLD_MIN, CFG_TDLS_TX_PACKET_THRESHOLD_MAX);
944 return -1;
945 }
946 if (config->discovery_period_t < CFG_TDLS_DISCOVERY_PERIOD_MIN ||
947 config->discovery_period_t > CFG_TDLS_DISCOVERY_PERIOD_MAX)
948 {
949 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 4th argument %d. <%d...%d>", __func__, config->discovery_period_t,
950 CFG_TDLS_DISCOVERY_PERIOD_MIN, CFG_TDLS_DISCOVERY_PERIOD_MAX);
951 return -1;
952 }
953 if (config->discovery_tries_n < CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MIN ||
954 config->discovery_tries_n > CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MAX)
955 {
956 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 5th argument %d. <%d...%d>", __func__, config->discovery_tries_n,
957 CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MIN, CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MAX);
958 return -1;
959 }
960 if (config->idle_timeout_t < CFG_TDLS_IDLE_TIMEOUT_MIN ||
961 config->idle_timeout_t > CFG_TDLS_IDLE_TIMEOUT_MAX)
962 {
963 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 6th argument %d. <%d...%d>", __func__, config->idle_timeout_t,
964 CFG_TDLS_IDLE_TIMEOUT_MIN, CFG_TDLS_IDLE_TIMEOUT_MAX);
965 return -1;
966 }
967 if (config->idle_packet_n < CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN ||
968 config->idle_packet_n > CFG_TDLS_IDLE_PACKET_THRESHOLD_MAX)
969 {
970 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 7th argument %d. <%d...%d>", __func__, config->idle_packet_n,
971 CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN, CFG_TDLS_IDLE_PACKET_THRESHOLD_MAX);
972 return -1;
973 }
974 if (config->rssi_hysteresis < CFG_TDLS_RSSI_HYSTERESIS_MIN ||
975 config->rssi_hysteresis > CFG_TDLS_RSSI_HYSTERESIS_MAX)
976 {
977 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 8th argument %d. <%d...%d>", __func__, config->rssi_hysteresis,
978 CFG_TDLS_RSSI_HYSTERESIS_MIN, CFG_TDLS_RSSI_HYSTERESIS_MAX);
979 return -1;
980 }
981 if (config->rssi_trigger_threshold < CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MIN ||
982 config->rssi_trigger_threshold > CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MAX)
983 {
984 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 9th argument %d. <%d...%d>", __func__, config->rssi_trigger_threshold,
985 CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MIN, CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MAX);
986 return -1;
987 }
988 if (config->rssi_teardown_threshold < CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN ||
989 config->rssi_teardown_threshold > CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX)
990 {
991 hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 10th argument %d. <%d...%d>", __func__, config->rssi_teardown_threshold,
992 CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN, CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX);
993 return -1;
994 }
995 return 0;
996}
997
Chilam Ng01120412013-02-19 18:32:21 -0800998int wlan_hdd_tdls_set_params(struct net_device *dev, tdls_config_params_t *config)
Chilam NG571c65a2013-01-19 12:27:36 +0530999{
Chilam Ng01120412013-02-19 18:32:21 -08001000 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1001 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001002 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Hoonki Lee27511902013-03-14 18:19:06 -07001003 eTDLSSupportMode req_tdls_mode;
Hoonki Leebfee0342013-01-21 16:43:45 -08001004
Hoonki Lee27511902013-03-14 18:19:06 -07001005 if (NULL == pHddTdlsCtx)
1006 {
1007 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS not enabled!", __func__);
1008 return -1;
Chilam Ng01120412013-02-19 18:32:21 -08001009 }
Chilam NG571c65a2013-01-19 12:27:36 +05301010
Hoonki Lee27511902013-03-14 18:19:06 -07001011 if (wlan_hdd_tdls_check_config(config) != 0)
1012 {
1013 return -1;
1014 }
1015
1016 /* config->tdls is mapped to 0->1, 1->2, 2->3 */
1017 req_tdls_mode = config->tdls + 1;
1018 if (pHddCtx->tdls_mode == req_tdls_mode)
1019 {
1020 hddLog(VOS_TRACE_LEVEL_ERROR, "%s already in mode %d", __func__, config->tdls);
1021 return -1;
1022 }
1023
1024 /* copy the configuration only when given tdls mode is implicit trigger enable */
1025 if (eTDLS_SUPPORT_ENABLED == req_tdls_mode)
1026 {
Chilam Ng01120412013-02-19 18:32:21 -08001027 memcpy(&pHddTdlsCtx->threshold_config, config, sizeof(tdls_config_params_t));
1028 }
Chilam NG571c65a2013-01-19 12:27:36 +05301029
Chilam Ng01120412013-02-19 18:32:21 -08001030 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1031 "iw set tdls params: %d %d %d %d %d %d %d %d %d %d",
1032 config->tdls,
1033 config->tx_period_t,
1034 config->tx_packet_n,
1035 config->discovery_period_t,
1036 config->discovery_tries_n,
1037 config->idle_timeout_t,
1038 config->idle_packet_n,
1039 config->rssi_hysteresis,
1040 config->rssi_trigger_threshold,
1041 config->rssi_teardown_threshold);
Chilam NG571c65a2013-01-19 12:27:36 +05301042
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07001043 wlan_hdd_tdls_set_mode(pHddCtx, req_tdls_mode, TRUE);
Chilam Ng01120412013-02-19 18:32:21 -08001044
Chilam NG571c65a2013-01-19 12:27:36 +05301045 return 0;
1046}
1047
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001048int wlan_hdd_tdls_set_sta_id(hdd_adapter_t *pAdapter, u8 *mac, u8 staId)
Kiran V1ccee932012-12-12 14:49:46 -08001049{
Hoonki Lee387663d2013-02-05 18:08:43 -08001050 hddTdlsPeer_t *curr_peer;
Kiran V1ccee932012-12-12 14:49:46 -08001051
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001052 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -08001053 if (curr_peer == NULL)
Chilam NG571c65a2013-01-19 12:27:36 +05301054 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +05301055
Hoonki Lee387663d2013-02-05 18:08:43 -08001056 curr_peer->staId = staId;
Chilam NG571c65a2013-01-19 12:27:36 +05301057
1058 return 0;
Kiran V1ccee932012-12-12 14:49:46 -08001059}
1060
Hoonki Lee387663d2013-02-05 18:08:43 -08001061/* if peerMac is found, then it returns pointer to hddTdlsPeer_t
1062 otherwise, it returns NULL
1063*/
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001064hddTdlsPeer_t *wlan_hdd_tdls_find_peer(hdd_adapter_t *pAdapter, u8 *mac)
Kiran V1ccee932012-12-12 14:49:46 -08001065{
Hoonki Lee387663d2013-02-05 18:08:43 -08001066 u8 key;
1067 struct list_head *pos;
1068 struct list_head *head;
1069 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001070 tdlsCtx_t *pHddTdlsCtx;
Hoonki Lee387663d2013-02-05 18:08:43 -08001071
Hoonki Lee387663d2013-02-05 18:08:43 -08001072
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001073 if (mutex_lock_interruptible(&tdls_lock))
Hoonki Lee387663d2013-02-05 18:08:43 -08001074 {
1075 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1076 "%s: unable to lock list", __func__);
1077 return NULL;
1078 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001079 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001080 if (NULL == pHddTdlsCtx)
1081 {
1082 mutex_unlock(&tdls_lock);
1083 return NULL;
1084 }
1085
1086 key = wlan_hdd_tdls_hash_key(mac);
1087
1088 head = &pHddTdlsCtx->peer_list[key];
Hoonki Lee387663d2013-02-05 18:08:43 -08001089
1090 list_for_each(pos, head) {
1091 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
1092 if (!memcmp(mac, curr_peer->peerMac, 6)) {
1093 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1094 "findTdlsPeer: found staId %d", curr_peer->staId);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001095 mutex_unlock(&tdls_lock);
Hoonki Lee387663d2013-02-05 18:08:43 -08001096 return curr_peer;
1097 }
1098 }
1099
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001100 mutex_unlock(&tdls_lock);
Hoonki Lee387663d2013-02-05 18:08:43 -08001101 return NULL;
1102}
1103
Hoonki Leea6d49be2013-04-05 09:43:25 -07001104hddTdlsPeer_t *wlan_hdd_tdls_find_all_peer(hdd_context_t *pHddCtx, u8 *mac)
1105{
1106 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1107 hdd_adapter_t *pAdapter = NULL;
1108 tdlsCtx_t *pHddTdlsCtx = NULL;
1109 hddTdlsPeer_t *curr_peer= NULL;
1110 VOS_STATUS status = 0;
1111
1112 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1113 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1114 {
1115 pAdapter = pAdapterNode->pAdapter;
1116
1117 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
1118 if (NULL != pHddTdlsCtx)
1119 {
1120 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
1121 if (curr_peer)
1122 return curr_peer;
1123 }
1124 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1125 pAdapterNode = pNext;
1126 }
1127 return curr_peer;
1128}
1129
1130
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001131int wlan_hdd_tdls_reset_peer(hdd_adapter_t *pAdapter, u8 *mac)
Hoonki Lee387663d2013-02-05 18:08:43 -08001132{
Chilam Ng01120412013-02-19 18:32:21 -08001133 hdd_context_t *pHddCtx;
Chilam NG571c65a2013-01-19 12:27:36 +05301134 hddTdlsPeer_t *curr_peer;
Kiran V1ccee932012-12-12 14:49:46 -08001135
Chilam Ng01120412013-02-19 18:32:21 -08001136 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1137
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001138 curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee387663d2013-02-05 18:08:43 -08001139 if (curr_peer == NULL)
1140 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +05301141
Gopichand Nakkala901e8922013-03-04 23:45:58 -08001142 curr_peer->link_status = eTDLS_LINK_IDLE;
Hoonki Leecdd8e962013-01-20 00:45:46 -08001143 curr_peer->staId = 0;
Hoonki Lee387663d2013-02-05 18:08:43 -08001144
Chilam Ng01120412013-02-19 18:32:21 -08001145 if(eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) {
Chilam Nga75d8b62013-01-29 01:35:59 -08001146 vos_timer_stop( &curr_peer->peerIdleTimer );
Chilam Nga75d8b62013-01-29 01:35:59 -08001147 }
Hoonki Lee387663d2013-02-05 18:08:43 -08001148 return 0;
Hoonki Leecdd8e962013-01-20 00:45:46 -08001149}
1150
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001151/* Caller has to take the lock before calling this function */
Hoonki Lee27511902013-03-14 18:19:06 -07001152static void wlan_tdd_tdls_reset_tx_rx(tdlsCtx_t *pHddTdlsCtx)
1153{
1154 int i;
1155 struct list_head *head;
1156 hddTdlsPeer_t *tmp;
1157 struct list_head *pos, *q;
1158
Hoonki Lee27511902013-03-14 18:19:06 -07001159 for (i = 0; i < 256; i++) {
1160 head = &pHddTdlsCtx->peer_list[i];
1161 list_for_each_safe (pos, q, head) {
1162 tmp = list_entry(pos, hddTdlsPeer_t, node);
1163 tmp->tx_pkt = 0;
1164 tmp->rx_pkt = 0;
1165 }
1166 }
Hoonki Lee27511902013-03-14 18:19:06 -07001167
1168 return ;
1169}
1170
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001171/* Caller has to take the lock before calling this function */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001172static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001173{
1174 int i;
1175 struct list_head *head;
1176 hddTdlsPeer_t *tmp;
1177 struct list_head *pos, *q;
1178
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001179 pHddTdlsCtx->discovery_peer_cnt = 0;
1180
1181 for (i = 0; i < 256; i++) {
1182 head = &pHddTdlsCtx->peer_list[i];
1183 list_for_each_safe (pos, q, head) {
1184 tmp = list_entry(pos, hddTdlsPeer_t, node);
1185 tmp->discovery_processed = 0;
1186 }
1187 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001188
1189 return 0;
1190}
1191
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001192static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(tdlsCtx_t *pHddTdlsCtx)
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001193{
1194 int i;
1195 struct list_head *head;
1196 struct list_head *pos, *q;
1197 int discovery_peer_cnt=0;
1198 hddTdlsPeer_t *tmp;
1199
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001200 /*
1201 * This function expects the callers to acquire the Mutex.
1202 */
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001203
1204 for (i = 0; i < 256; i++) {
1205 head = &pHddTdlsCtx->peer_list[i];
1206 list_for_each_safe (pos, q, head) {
1207 tmp = list_entry(pos, hddTdlsPeer_t, node);
1208 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -08001209 "%s, %d, " MAC_ADDRESS_STR, __func__, i,
1210 MAC_ADDR_ARRAY(tmp->peerMac));
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001211 discovery_peer_cnt++;
1212 }
1213 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001214 return discovery_peer_cnt;
1215}
1216
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001217tANI_U16 wlan_hdd_tdlsConnectedPeers(hdd_adapter_t *pAdapter)
Lee Hoonkic1262f22013-01-24 21:59:00 -08001218{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001219 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1220
1221 if (NULL == pHddCtx)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001222 return 0;
Lee Hoonkic1262f22013-01-24 21:59:00 -08001223
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001224 return pHddCtx->connected_peer_count;
Lee Hoonkic1262f22013-01-24 21:59:00 -08001225}
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001226
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001227int wlan_hdd_tdls_get_all_peers(hdd_adapter_t *pAdapter, char *buf, int buflen)
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001228{
1229 int i;
1230 int len, init_len;
Hoonki Lee387663d2013-02-05 18:08:43 -08001231 struct list_head *head;
1232 struct list_head *pos;
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001233 hddTdlsPeer_t *curr_peer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001234 tdlsCtx_t *pHddTdlsCtx;
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001235
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001236
1237 init_len = buflen;
1238 len = snprintf(buf, buflen, "\n%-18s%-3s%-4s%-3s%-5s\n", "MAC", "Id", "cap", "up", "RSSI");
1239 buf += len;
1240 buflen -= len;
1241 /* 1234567890123456789012345678901234567 */
1242 len = snprintf(buf, buflen, "---------------------------------\n");
1243 buf += len;
1244 buflen -= len;
1245
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001246 if (mutex_lock_interruptible(&tdls_lock))
Gopichand Nakkala91b09262013-02-10 14:27:02 -08001247 {
1248 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1249 "%s: unable to lock list", __func__);
1250 return init_len-buflen;
1251 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001252 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001253 if (NULL == pHddTdlsCtx) {
1254 mutex_unlock(&tdls_lock);
1255 len = snprintf(buf, buflen, "TDLS not enabled\n");
1256 return len;
1257 }
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001258 for (i = 0; i < 256; i++) {
Hoonki Lee387663d2013-02-05 18:08:43 -08001259 head = &pHddTdlsCtx->peer_list[i];
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001260
Hoonki Lee387663d2013-02-05 18:08:43 -08001261 list_for_each(pos, head) {
1262 curr_peer= list_entry (pos, hddTdlsPeer_t, node);
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001263
Hoonki Lee387663d2013-02-05 18:08:43 -08001264 if (buflen < 32+1)
1265 break;
1266 len = snprintf(buf, buflen,
Chilam Ng01120412013-02-19 18:32:21 -08001267 MAC_ADDRESS_STR"%3d%4s%3s%5d\n",
1268 MAC_ADDR_ARRAY(curr_peer->peerMac),
Hoonki Lee387663d2013-02-05 18:08:43 -08001269 curr_peer->staId,
1270 (curr_peer->tdls_support == eTDLS_CAP_SUPPORTED) ? "Y":"N",
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07001271 TDLS_IS_CONNECTED(curr_peer) ? "Y":"N",
Hoonki Lee387663d2013-02-05 18:08:43 -08001272 curr_peer->rssi);
1273 buf += len;
1274 buflen -= len;
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001275 }
1276 }
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001277 mutex_unlock(&tdls_lock);
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001278 return init_len-buflen;
1279}
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001280
1281void wlan_hdd_tdls_connection_callback(hdd_adapter_t *pAdapter)
1282{
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001283 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001284 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001285
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001286 if (mutex_lock_interruptible(&tdls_lock))
1287 {
1288 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1289 "%s: unable to lock list", __func__);
1290 return;
1291 }
1292
1293 if (NULL == pHddCtx || NULL == pHddTdlsCtx)
1294 {
1295 mutex_unlock(&tdls_lock);
1296 return;
1297 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001298
1299 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1300 "%s, update %d discover %d", __func__,
1301 pHddTdlsCtx->threshold_config.tx_period_t,
1302 pHddTdlsCtx->threshold_config.discovery_period_t);
1303
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001304 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode)
1305 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001306 wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001307 pHddTdlsCtx->discovery_sent_cnt = 0;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001308 wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001309
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001310#ifdef FEATURE_WLAN_TDLS_INTERNAL
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001311 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
1312 &pHddTdlsCtx->peerDiscoverTimer,
1313 pHddTdlsCtx->threshold_config.discovery_period_t);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001314#endif
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001315 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
1316 &pHddTdlsCtx->peerUpdateTimer,
1317 pHddTdlsCtx->threshold_config.tx_period_t);
Gopichand Nakkala9d76a9b2013-02-28 15:38:37 -08001318 }
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001319 mutex_unlock(&tdls_lock);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001320
1321}
1322
1323void wlan_hdd_tdls_disconnection_callback(hdd_adapter_t *pAdapter)
1324{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001325 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001326
1327 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s", __func__);
1328
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001329 if (mutex_lock_interruptible(&tdls_lock))
1330 {
1331 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1332 "%s: unable to lock list", __func__);
1333 return;
1334 }
1335 if (NULL == pHddTdlsCtx)
1336 {
1337 mutex_unlock(&tdls_lock);
1338 return;
1339 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001340 pHddTdlsCtx->discovery_sent_cnt = 0;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001341 wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001342
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001343 wlan_hdd_tdls_timers_stop(pHddTdlsCtx);
1344 wlan_hdd_tdls_free_list(pHddTdlsCtx);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001345
1346 mutex_unlock(&tdls_lock);
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001347}
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001348
1349void wlan_hdd_tdls_mgmt_completion_callback(hdd_adapter_t *pAdapter, tANI_U32 statusCode)
1350{
1351 pAdapter->mgmtTxCompletionStatus = statusCode;
1352 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s: Mgmt TX Completion %d",
1353 __func__, statusCode);
1354 complete(&pAdapter->tdls_mgmt_comp);
1355}
1356
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001357void wlan_hdd_tdls_increment_peer_count(hdd_adapter_t *pAdapter)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001358{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001359 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001360
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001361 if (NULL == pHddCtx) return;
1362
1363 pHddCtx->connected_peer_count++;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001364 wlan_hdd_tdls_check_power_save_prohibited(pAdapter);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001365
1366 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: %d",
1367 __func__, pHddCtx->connected_peer_count);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001368}
1369
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001370void wlan_hdd_tdls_decrement_peer_count(hdd_adapter_t *pAdapter)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001371{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001372 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001373
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001374 if (NULL == pHddCtx) return;
1375
1376 if (pHddCtx->connected_peer_count)
1377 pHddCtx->connected_peer_count--;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001378 wlan_hdd_tdls_check_power_save_prohibited(pAdapter);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001379
1380 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: %d",
1381 __func__, pHddCtx->connected_peer_count);
1382
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001383}
1384
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001385void wlan_hdd_tdls_check_bmps(hdd_adapter_t *pAdapter)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001386{
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001387 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001388 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Hoonki Lee14621352013-04-16 17:51:19 -07001389 hddTdlsPeer_t *curr_peer;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001390
Gopichand Nakkala16c02842013-03-18 12:31:35 -07001391 if ((NULL == pHddCtx) || (NULL == pHddTdlsCtx)) return;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001392
Hoonki Lee14621352013-04-16 17:51:19 -07001393 curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, TRUE);
1394 if (NULL != curr_peer)
1395 {
1396 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1397 "%s: tdls in progress. Dont check for BMPS " MAC_ADDRESS_STR,
1398 __func__, MAC_ADDR_ARRAY (curr_peer->peerMac));
1399 return;
1400 }
1401
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001402 if ((TDLS_CTX_MAGIC != pHddCtx->tdls_scan_ctxt.magic) &&
1403 (0 == pHddCtx->connected_peer_count) &&
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001404 (0 == pHddTdlsCtx->discovery_sent_cnt))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001405 {
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001406 if (FALSE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
1407 {
1408 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001409 "%s: No TDLS peer connected/discovery sent. Enable BMPS",
1410 __func__);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001411 hdd_enable_bmps_imps(pHddCtx);
1412 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001413 }
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001414 else
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001415 {
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001416 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
1417 {
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001418 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1419 "%s: TDLS peer connected. Disable BMPS", __func__);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001420 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
1421 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001422 }
1423 return;
1424}
1425
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001426u8 wlan_hdd_tdls_is_peer_progress(hdd_adapter_t *pAdapter, u8 *mac)
1427{
1428 hddTdlsPeer_t *curr_peer;
1429
1430 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
1431 if (curr_peer == NULL)
1432 return 0;
1433
1434 return (eTDLS_LINK_CONNECTING == curr_peer->link_status);
1435}
1436
Hoonki Leefb8df672013-04-10 18:20:34 -07001437/* return pointer to hddTdlsPeer_t if TDLS is ongoing. Otherwise return NULL.
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001438 * mac - if NULL check for all the peer list, otherwise, skip this mac when skip_self is TRUE
1439 * skip_self - if TRUE, skip this mac. otherwise, check all the peer list. if
1440 mac is NULL, this argument is ignored, and check for all the peer list.
1441 */
Hoonki Leefb8df672013-04-10 18:20:34 -07001442static hddTdlsPeer_t *wlan_hdd_tdls_find_progress_peer(hdd_adapter_t *pAdapter, u8 *mac, u8 skip_self, tANI_BOOLEAN mutexLock)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001443{
1444 int i;
1445 struct list_head *head;
1446 hddTdlsPeer_t *curr_peer;
1447 struct list_head *pos;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001448 tdlsCtx_t *pHddTdlsCtx;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001449
Hoonki Leefb8df672013-04-10 18:20:34 -07001450 if (mutexLock)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001451 {
Hoonki Leefb8df672013-04-10 18:20:34 -07001452 if (mutex_lock_interruptible(&tdls_lock))
1453 {
1454 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001455 "%s: unable to lock list", __func__);
Hoonki Leefb8df672013-04-10 18:20:34 -07001456 return NULL;
1457 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001458 }
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001459 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001460 if (NULL == pHddTdlsCtx)
1461 {
Hoonki Leefb8df672013-04-10 18:20:34 -07001462 if (mutexLock)
1463 mutex_unlock(&tdls_lock);
1464 return NULL;
Gopichand Nakkalaeb69b602013-02-27 11:40:31 -08001465 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001466
1467 for (i = 0; i < 256; i++) {
1468 head = &pHddTdlsCtx->peer_list[i];
1469 list_for_each(pos, head) {
1470 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
1471 if (skip_self && mac && !memcmp(mac, curr_peer->peerMac, 6)) {
1472 continue;
1473 }
1474 else
1475 {
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08001476 if (eTDLS_LINK_CONNECTING == curr_peer->link_status)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001477 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07001478 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001479 "%s:" MAC_ADDRESS_STR " eTDLS_LINK_CONNECTING",
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07001480 __func__, MAC_ADDR_ARRAY(curr_peer->peerMac));
Hoonki Leefb8df672013-04-10 18:20:34 -07001481 if (mutexLock)
1482 mutex_unlock(&tdls_lock);
1483 return curr_peer;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001484 }
1485 }
1486 }
1487 }
1488
Hoonki Leefb8df672013-04-10 18:20:34 -07001489 if (mutexLock)
1490 mutex_unlock(&tdls_lock);
1491 return NULL;
1492}
1493
1494hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx, u8 *mac, u8 skip_self, tANI_BOOLEAN mutexLock)
1495{
1496 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1497 hdd_adapter_t *pAdapter = NULL;
1498 tdlsCtx_t *pHddTdlsCtx = NULL;
1499 hddTdlsPeer_t *curr_peer= NULL;
1500 VOS_STATUS status = 0;
1501
1502 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1503 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1504 {
1505 pAdapter = pAdapterNode->pAdapter;
1506
1507 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
1508 if (NULL != pHddTdlsCtx)
1509 {
1510 curr_peer = wlan_hdd_tdls_find_progress_peer(pAdapter, mac, skip_self, mutexLock);
1511 if (curr_peer)
1512 return curr_peer;
1513 }
1514 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1515 pAdapterNode = pNext;
1516 }
1517 return NULL;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001518}
Hoonki Lee27511902013-03-14 18:19:06 -07001519
1520static void wlan_hdd_tdls_implicit_disable(tdlsCtx_t *pHddTdlsCtx)
1521{
Hoonki Lee27511902013-03-14 18:19:06 -07001522 wlan_hdd_tdls_timers_stop(pHddTdlsCtx);
Hoonki Lee27511902013-03-14 18:19:06 -07001523}
1524
1525static void wlan_hdd_tdls_implicit_enable(tdlsCtx_t *pHddTdlsCtx)
1526{
1527 wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001528 pHddTdlsCtx->discovery_sent_cnt = 0;
Hoonki Lee27511902013-03-14 18:19:06 -07001529 wlan_tdd_tdls_reset_tx_rx(pHddTdlsCtx);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001530 wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001531
Hoonki Lee27511902013-03-14 18:19:06 -07001532
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001533#ifdef FEATURE_WLAN_TDLS_INTERNAL
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001534 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
1535 &pHddTdlsCtx->peerDiscoverTimer,
1536 pHddTdlsCtx->threshold_config.discovery_period_t);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001537#endif
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001538 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
1539 &pHddTdlsCtx->peerUpdateTimer,
1540 pHddTdlsCtx->threshold_config.tx_period_t);
Hoonki Lee27511902013-03-14 18:19:06 -07001541}
1542
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07001543void wlan_hdd_tdls_set_mode(hdd_context_t *pHddCtx,
1544 eTDLSSupportMode tdls_mode,
1545 v_BOOL_t bUpdateLast)
Hoonki Lee27511902013-03-14 18:19:06 -07001546{
1547 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1548 VOS_STATUS status;
1549 hdd_adapter_t *pAdapter;
1550 tdlsCtx_t *pHddTdlsCtx;
1551
1552 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s mode %d", __func__, (int)tdls_mode);
1553
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001554 if (mutex_lock_interruptible(&tdls_lock))
1555 {
1556 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1557 "%s: unable to lock list", __func__);
1558 return;
1559 }
1560
1561 if (NULL == pHddCtx)
1562 {
1563 mutex_unlock(&tdls_lock);
1564 return;
1565 }
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001566
1567 if (pHddCtx->tdls_mode == tdls_mode)
1568 {
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001569 hddLog(TDLS_LOG_LEVEL, "%s already in mode %d", __func__, (int)tdls_mode);
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001570 mutex_unlock(&tdls_lock);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001571 return;
1572 }
1573
Hoonki Lee27511902013-03-14 18:19:06 -07001574 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1575
1576 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1577 {
1578 pAdapter = pAdapterNode->pAdapter;
Hoonki Leea6d49be2013-04-05 09:43:25 -07001579 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
1580 if (NULL != pHddTdlsCtx)
Hoonki Lee27511902013-03-14 18:19:06 -07001581 {
Hoonki Leea6d49be2013-04-05 09:43:25 -07001582 if(eTDLS_SUPPORT_ENABLED == tdls_mode)
1583 wlan_hdd_tdls_implicit_enable(pHddTdlsCtx);
1584 else if((eTDLS_SUPPORT_DISABLED == tdls_mode) ||
1585 (eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode))
1586 wlan_hdd_tdls_implicit_disable(pHddTdlsCtx);
Hoonki Lee27511902013-03-14 18:19:06 -07001587 }
1588 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1589 pAdapterNode = pNext;
1590 }
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07001591 if(bUpdateLast)
1592 {
1593 pHddCtx->tdls_mode_last = tdls_mode;
1594 }
1595 else
1596 {
1597 pHddCtx->tdls_mode_last = pHddCtx->tdls_mode;
1598 }
Hoonki Lee27511902013-03-14 18:19:06 -07001599 pHddCtx->tdls_mode = tdls_mode;
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07001600
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07001601 mutex_unlock(&tdls_lock);
Hoonki Lee27511902013-03-14 18:19:06 -07001602}
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001603
Hoonki Leefb8df672013-04-10 18:20:34 -07001604static void wlan_hdd_tdls_pre_setup(tdlsCtx_t *pHddTdlsCtx,
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001605 hddTdlsPeer_t *curr_peer)
1606{
1607 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter);
Hoonki Leefb8df672013-04-10 18:20:34 -07001608 hddTdlsPeer_t *temp_peer;
1609
1610 if (NULL == pHddCtx)
1611 return;
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001612
1613 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter)))
1614 {
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001615 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s: Disable BMPS", __func__);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001616 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
1617 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001618
Hoonki Leefb8df672013-04-10 18:20:34 -07001619 temp_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, FALSE);
1620 if (NULL != temp_peer)
1621 {
1622 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: " MAC_ADDRESS_STR " ongoing. pre_setup ignored\n",
1623 __func__, MAC_ADDR_ARRAY(temp_peer->peerMac));
1624 return;
1625 }
1626
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001627 if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support)
1628 curr_peer->link_status = eTDLS_LINK_DISCOVERING;
1629
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001630 sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter),
1631 pHddTdlsCtx->pAdapter->sessionId,
1632 curr_peer->peerMac,
1633 WLAN_TDLS_DISCOVERY_REQUEST,
1634 1, 0, NULL, 0, 0);
1635 pHddTdlsCtx->discovery_sent_cnt++;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001636 wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001637 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: discovery count %lu timeout %lu msec",
1638 __func__, pHddTdlsCtx->discovery_sent_cnt,
1639 pHddTdlsCtx->threshold_config.tx_period_t - TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE);
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001640
1641 wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
1642 &pHddTdlsCtx->peerDiscoveryTimeoutTimer,
1643 pHddTdlsCtx->threshold_config.tx_period_t - TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE);
Gopichand Nakkala75e7b282013-03-15 18:37:13 -07001644
1645 return;
1646}
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001647
1648tANI_U32 wlan_hdd_tdls_discovery_sent_cnt(hdd_context_t *pHddCtx)
1649{
1650 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1651 hdd_adapter_t *pAdapter = NULL;
1652 tdlsCtx_t *pHddTdlsCtx = NULL;
1653 VOS_STATUS status = 0;
1654 tANI_U32 count = 0;
1655
1656 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1657 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1658 {
1659 pAdapter = pAdapterNode->pAdapter;
1660
Hoonki Leea6d49be2013-04-05 09:43:25 -07001661 pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
1662 if (NULL != pHddTdlsCtx)
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001663 {
Hoonki Leea6d49be2013-04-05 09:43:25 -07001664 count = count + pHddTdlsCtx->discovery_sent_cnt;
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001665 }
1666 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1667 pAdapterNode = pNext;
1668 }
1669 return count;
1670}
1671
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07001672void wlan_hdd_tdls_check_power_save_prohibited(hdd_adapter_t *pAdapter)
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07001673{
1674 tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
1675 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1676
1677 if ((NULL == pHddTdlsCtx) || (NULL == pHddCtx))
1678 return;
1679
1680 if ((0 == pHddCtx->connected_peer_count) &&
1681 (0 == wlan_hdd_tdls_discovery_sent_cnt(pHddCtx)))
1682 {
1683 sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter), 0);
1684 return;
1685 }
1686 sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter), 1);
1687 return;
1688}
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001689
1690void wlan_hdd_tdls_free_scan_request (tdls_scan_context_t *tdls_scan_ctx)
1691{
1692 if (NULL == tdls_scan_ctx)
1693 return;
1694
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001695 tdls_scan_ctx->attempt = 0;
Hoonki Leefb8df672013-04-10 18:20:34 -07001696 tdls_scan_ctx->reject = 0;
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001697 tdls_scan_ctx->magic = 0;
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001698 tdls_scan_ctx->scan_request = NULL;
1699 return;
1700}
1701
1702int wlan_hdd_tdls_copy_scan_context(hdd_context_t *pHddCtx,
1703 struct wiphy *wiphy,
1704#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
1705 struct net_device *dev,
1706#endif
1707 struct cfg80211_scan_request *request)
1708{
1709 tdls_scan_context_t *scan_ctx;
1710
1711 if (NULL == pHddCtx )
1712 return -1;
1713
1714 scan_ctx = &pHddCtx->tdls_scan_ctxt;
1715
1716 scan_ctx->wiphy = wiphy;
1717#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
1718 scan_ctx->dev = dev;
1719#endif
1720
1721 scan_ctx->scan_request = request;
1722 return 0;
1723}
1724
1725static void wlan_hdd_tdls_schedule_scan(struct work_struct *work)
1726{
1727 tdls_scan_context_t *scan_ctx =
1728 container_of(work, tdls_scan_context_t, tdls_scan_work.work);
1729
1730 if (NULL == scan_ctx)
1731 return;
1732
1733 if (unlikely(TDLS_CTX_MAGIC != scan_ctx->magic))
1734 return;
1735
1736 scan_ctx->attempt++;
1737
1738 wlan_hdd_cfg80211_scan(scan_ctx->wiphy,
1739#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
1740 scan_ctx->dev,
1741#endif
1742 scan_ctx->scan_request);
1743}
1744
1745static void wlan_hdd_tdls_scan_init_work(hdd_context_t *pHddCtx,
1746 struct wiphy *wiphy,
1747#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
1748 struct net_device *dev,
1749#endif
1750 struct cfg80211_scan_request *request,
1751 unsigned long delay)
1752{
1753 if (TDLS_CTX_MAGIC != pHddCtx->tdls_scan_ctxt.magic)
1754 {
1755#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
1756 wlan_hdd_tdls_copy_scan_context(pHddCtx, wiphy, dev, request);
1757#else
1758 wlan_hdd_tdls_copy_scan_context(pHddCtx, wiphy, request);
1759#endif
1760 pHddCtx->tdls_scan_ctxt.attempt = 0;
1761 pHddCtx->tdls_scan_ctxt.magic = TDLS_CTX_MAGIC;
1762 }
1763 INIT_DELAYED_WORK(&pHddCtx->tdls_scan_ctxt.tdls_scan_work, wlan_hdd_tdls_schedule_scan);
1764
1765 schedule_delayed_work(&pHddCtx->tdls_scan_ctxt.tdls_scan_work, delay);
1766}
1767
1768/* return negative = caller should stop and return error code immediately
1769 return 0 = caller should stop and return success immediately
1770 return 1 = caller can continue to scan
1771 */
1772int wlan_hdd_tdls_scan_callback (hdd_adapter_t *pAdapter,
1773 struct wiphy *wiphy,
1774#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
1775 struct net_device *dev,
1776#endif
1777 struct cfg80211_scan_request *request)
1778{
1779#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1780 struct net_device *dev = request->wdev->netdev;
1781#endif
1782 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1783 u16 connectedTdlsPeers;
Hoonki Leefb8df672013-04-10 18:20:34 -07001784 hddTdlsPeer_t *curr_peer;
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001785 unsigned long delay;
1786
1787 if (NULL == pHddCtx)
1788 return 0;
1789
1790 /* if tdls is not enabled, then continue scan */
1791 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
1792 return 1;
1793
Hoonki Leefb8df672013-04-10 18:20:34 -07001794 curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, TRUE);
1795 if (NULL != curr_peer)
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001796 {
Hoonki Leefb8df672013-04-10 18:20:34 -07001797 if (pHddCtx->tdls_scan_ctxt.reject++ >= TDLS_MAX_SCAN_REJECT)
1798 {
1799 pHddCtx->tdls_scan_ctxt.reject = 0;
1800 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1801 "%s: " MAC_ADDRESS_STR ". scan rejected %d. force it to idle",
1802 __func__, MAC_ADDR_ARRAY (curr_peer->peerMac), pHddCtx->tdls_scan_ctxt.reject);
1803
1804 wlan_hdd_tdls_set_peer_link_status (curr_peer, eTDLS_LINK_IDLE);
1805 return 1;
1806 }
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001807 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Hoonki Leefb8df672013-04-10 18:20:34 -07001808 "%s: tdls in progress. scan rejected %d",
1809 __func__, pHddCtx->tdls_scan_ctxt.reject);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001810 return -EBUSY;
1811 }
1812
1813 /* tdls teardown is ongoing */
1814 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
1815 {
1816 connectedTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
1817 if (connectedTdlsPeers && (pHddCtx->tdls_scan_ctxt.attempt < TDLS_MAX_SCAN_SCHEDULE))
1818 {
1819 delay = (unsigned long)(TDLS_DELAY_SCAN_PER_CONNECTION*connectedTdlsPeers);
1820 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1821 "%s: tdls disabled, but still connected_peers %d attempt %d. schedule scan %lu msec",
1822 __func__, connectedTdlsPeers, pHddCtx->tdls_scan_ctxt.attempt, delay);
1823
1824 wlan_hdd_tdls_scan_init_work (pHddCtx, wiphy,
1825#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
1826 dev,
1827#endif
1828 request,
1829 msecs_to_jiffies(delay));
1830 /* scan should not continue */
1831 return 0;
1832 }
1833 /* no connected peer or max retry reached, scan continue */
1834 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1835 "%s: tdls disabled. connected_peers %d attempt %d. scan allowed",
1836 __func__, connectedTdlsPeers, pHddCtx->tdls_scan_ctxt.attempt);
1837 return 1;
1838 }
1839 /* while tdls is up, first time scan */
1840 else if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode ||
1841 eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode)
1842 {
1843 /* disable implicit trigger logic & tdls operatoin */
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07001844 wlan_hdd_tdls_set_mode(pHddCtx, eTDLS_SUPPORT_DISABLED, FALSE);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001845 /* indicate the teardown all connected to peer */
1846 connectedTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
1847 if (connectedTdlsPeers)
1848 {
1849 tANI_U8 staIdx;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07001850 hddTdlsPeer_t *curr_peer;
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001851
1852 for (staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
1853 {
1854 if (pHddCtx->tdlsConnInfo[staIdx].staId)
1855 {
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001856 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001857 ("%s: indicate TDLS teadown (staId %d)"), __func__, pHddCtx->tdlsConnInfo[staIdx].staId) ;
1858
1859#ifdef CONFIG_TDLS_IMPLICIT
Hoonki Leea6d49be2013-04-05 09:43:25 -07001860 curr_peer = wlan_hdd_tdls_find_all_peer(pHddCtx, pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes);
1861 if(curr_peer)
1862 wlan_hdd_tdls_indicate_teardown(curr_peer->pHddTdlsCtx->pAdapter, curr_peer, eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001863#endif
1864 }
1865 }
1866 /* schedule scan */
1867 delay = (unsigned long)(TDLS_DELAY_SCAN_PER_CONNECTION*connectedTdlsPeers);
1868
1869 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1870 "%s: tdls enabled (mode %d), connected_peers %d. schedule scan %lu msec",
1871 __func__, pHddCtx->tdls_mode, wlan_hdd_tdlsConnectedPeers(pAdapter),
1872 delay);
1873
1874 wlan_hdd_tdls_scan_init_work (pHddCtx, wiphy,
1875#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
1876 dev,
1877#endif
1878 request,
1879 msecs_to_jiffies(delay));
1880 /* scan should not continue */
1881 return 0;
1882 }
1883 /* no connected peer, scan continue */
1884 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1885 "%s: tdls_mode %d, and no tdls connection. scan allowed",
1886 __func__, pHddCtx->tdls_mode);
1887 }
1888 return 1;
1889}
1890
1891void wlan_hdd_tdls_scan_done_callback(hdd_adapter_t *pAdapter)
1892{
1893 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001894
1895 if (NULL == pHddCtx)
1896 return;
1897
1898 /* free allocated memory at scan time */
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001899 wlan_hdd_tdls_free_scan_request (&pHddCtx->tdls_scan_ctxt);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001900
1901 /* if tdls was enabled before scan, re-enable tdls mode */
1902 if(eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode_last ||
1903 eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode_last)
1904 {
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001905 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001906 ("%s: revert tdls mode %d"), __func__, pHddCtx->tdls_mode_last);
1907
Gopichand Nakkaladcbcf4e2013-03-23 14:32:39 -07001908 wlan_hdd_tdls_set_mode(pHddCtx, pHddCtx->tdls_mode_last, FALSE);
Hoonki Lee93e67ff2013-03-19 15:49:25 -07001909 }
1910 wlan_hdd_tdls_check_bmps(pAdapter);
1911}
Gopichand Nakkala3046fc92013-03-23 13:56:43 -07001912
1913void wlan_hdd_tdls_timer_restart(hdd_adapter_t *pAdapter,
1914 vos_timer_t *timer,
1915 v_U32_t expirationTime)
1916{
1917 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1918
1919 if (NULL == pHddStaCtx)
1920 return;
1921
1922 /* Check whether driver load unload is in progress */
1923 if(vos_is_load_unload_in_progress( VOS_MODULE_ID_VOSS, NULL))
1924 {
1925 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1926 "%s: Driver load/unload is in progress.", __func__);
1927 return;
1928 }
1929
1930 if (hdd_connIsConnected(pHddStaCtx))
1931 {
1932 vos_timer_stop(timer);
1933 vos_timer_start(timer, expirationTime);
1934 }
1935}
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07001936void wlan_hdd_tdls_indicate_teardown(hdd_adapter_t *pAdapter,
1937 hddTdlsPeer_t *curr_peer,
1938 tANI_U16 reason)
1939{
1940 if (NULL == pAdapter || NULL == curr_peer)
1941 return;
1942
1943 if (eTDLS_LINK_CONNECTED != curr_peer->link_status)
1944 return;
1945
1946 wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_TEARING);
1947 cfg80211_tdls_oper_request(pAdapter->dev,
1948 curr_peer->peerMac,
1949 NL80211_TDLS_TEARDOWN,
1950 reason,
1951 GFP_KERNEL);
1952}