blob: f222593a7a07cbea7eec435f7aa0fee2ea10fcbc [file] [log] [blame]
Kiran V1ccee932012-12-12 14:49:46 -08001/*
Gopichand Nakkala0c1331e2013-01-07 22:49:07 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
Kiran V1ccee932012-12-12 14:49:46 -080021
22/**========================================================================
23
24 \file wlan_hdd_tdls.c
25
Chilam NG571c65a2013-01-19 12:27:36 +053026 \brief WLAN Host Device Driver implementation for TDLS
Kiran V1ccee932012-12-12 14:49:46 -080027
Kiran V1ccee932012-12-12 14:49:46 -080028 ========================================================================*/
29
30#include <wlan_hdd_includes.h>
31#include <wlan_hdd_hostapd.h>
32#include <net/cfg80211.h>
33#include <linux/netdevice.h>
34#include <linux/skbuff.h>
Chilam NG571c65a2013-01-19 12:27:36 +053035#include <linux/list.h>
Kiran V1ccee932012-12-12 14:49:46 -080036#include <linux/etherdevice.h>
37#include <net/ieee80211_radiotap.h>
38#include "wlan_hdd_tdls.h"
Chilam NG571c65a2013-01-19 12:27:36 +053039#include "wlan_hdd_cfg80211.h"
Kiran V1ccee932012-12-12 14:49:46 -080040
Chilam NG571c65a2013-01-19 12:27:36 +053041
Chilam Nga75d8b62013-01-29 01:35:59 -080042static tdlsCtx_t *pHddTdlsCtx;
Gopichand Nakkalac3694582013-02-13 20:51:22 -080043static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(void);
44static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(void);
Chilam NG571c65a2013-01-19 12:27:36 +053045
Hoonki Lee5a4b2172013-01-29 01:45:53 -080046#ifndef WLAN_FEATURE_TDLS_DEBUG
47#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
48#else
49#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_WARN
50#endif
51
Hoonki Lee387663d2013-02-05 18:08:43 -080052static u8 wlan_hdd_tdls_hash_key (u8 *mac)
Hoonki Leef63df0d2013-01-16 19:29:14 -080053{
54 int i;
Hoonki Lee387663d2013-02-05 18:08:43 -080055 u8 key = 0;
56
57 for (i = 0; i < 6; i++)
58 key ^= mac[i];
59
60 return key;
61}
62
63static v_VOID_t wlan_hdd_tdls_discover_peer_cb( v_PVOID_t userData )
64{
65 int i;
66 struct list_head *head;
67 struct list_head *pos;
Chilam NG571c65a2013-01-19 12:27:36 +053068 hddTdlsPeer_t *curr_peer;
Hoonki Leebfee0342013-01-21 16:43:45 -080069 hdd_adapter_t *pAdapter;
70 hdd_context_t *pHddCtx;
Gopichand Nakkalac3694582013-02-13 20:51:22 -080071 hdd_station_ctx_t *pHddStaCtx;
72 int discover_req_sent = 0;
73 v_U32_t discover_expiry = TDLS_SUB_DISCOVERY_PERIOD;
74
Hoonki Leebfee0342013-01-21 16:43:45 -080075
76 if (NULL == pHddTdlsCtx) return;
77
78 pAdapter = WLAN_HDD_GET_PRIV_PTR(pHddTdlsCtx->dev);
Gopichand Nakkalac3694582013-02-13 20:51:22 -080079
80 if (NULL == pAdapter) return;
81
82 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Hoonki Leebfee0342013-01-21 16:43:45 -080083 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Hoonki Leef63df0d2013-01-16 19:29:14 -080084
Hoonki Lee387663d2013-02-05 18:08:43 -080085 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: ", __func__);
86
Gopichand Nakkalac3694582013-02-13 20:51:22 -080087 if (0 == pHddTdlsCtx->discovery_peer_cnt)
88 pHddTdlsCtx->discovery_peer_cnt = wlan_hdd_get_tdls_discovery_peer_cnt();
89
90 if (-1 == pHddTdlsCtx->discovery_peer_cnt) {
91 discover_expiry = pHddTdlsCtx->threshold_config.discovery_period_t;
92
93 goto done;
94 }
95
Gopichand Nakkala91b09262013-02-10 14:27:02 -080096 if (mutex_lock_interruptible(&pHddTdlsCtx->lock))
97 {
98 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac3694582013-02-13 20:51:22 -080099 "%s: unable to lock list : %d", __func__, __LINE__);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800100 return;
101 }
102
Chilam NG571c65a2013-01-19 12:27:36 +0530103 for (i = 0; i < 256; i++) {
Hoonki Lee387663d2013-02-05 18:08:43 -0800104 head = &pHddTdlsCtx->peer_list[i];
Chilam NG571c65a2013-01-19 12:27:36 +0530105
Hoonki Lee387663d2013-02-05 18:08:43 -0800106 list_for_each (pos, head) {
107 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
Chilam NG571c65a2013-01-19 12:27:36 +0530108
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -0800109 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800110 "%d " MAC_ADDRESS_STR " %d %d, %d %d %d %d", i,
111 MAC_ADDR_ARRAY(curr_peer->peerMac),
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800112 curr_peer->discovery_processed,
113 discover_req_sent,
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -0800114 curr_peer->tdls_support,
115 curr_peer->link_status,
116 curr_peer->discovery_attempt,
117 pHddTdlsCtx->threshold_config.discovery_tries_n);
Hoonki Lee387663d2013-02-05 18:08:43 -0800118
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800119 if (discover_req_sent < TDLS_MAX_DISCOVER_REQS_PER_TIMER) {
120 if (!curr_peer->discovery_processed) {
Chilam NG571c65a2013-01-19 12:27:36 +0530121
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800122 curr_peer->discovery_processed = 1;
123 discover_req_sent++;
124 pHddTdlsCtx->discovery_peer_cnt--;
125
126 if ((eTDLS_CAP_UNKNOWN == curr_peer->tdls_support) &&
Gopichand Nakkala273d5a02013-02-19 15:15:09 -0800127 (eTDLS_LINK_NOT_CONNECTED == curr_peer->link_status)) {
128
129 if (curr_peer->discovery_attempt <
130 pHddTdlsCtx->threshold_config.discovery_tries_n) {
131
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800132 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala273d5a02013-02-19 15:15:09 -0800133 "sme_SendTdlsMgmtFrame(%d)", pAdapter->sessionId);
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800134
135 sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter),
136 pAdapter->sessionId,
137 curr_peer->peerMac,
138 WLAN_TDLS_DISCOVERY_REQUEST,
139 1, 0, NULL, 0, 0);
Gopichand Nakkala273d5a02013-02-19 15:15:09 -0800140 curr_peer->discovery_attempt++;
141 }
142 else
143 {
144 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
145 "%s: Maximum Discovery retries reached", __func__);
146 curr_peer->tdls_support = eTDLS_CAP_NOT_SUPPORTED;
147 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800148
149 }
150 }
Chilam NG571c65a2013-01-19 12:27:36 +0530151 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800152 else
153 goto exit_loop;
Hoonki Lee387663d2013-02-05 18:08:43 -0800154 }
Hoonki Leef63df0d2013-01-16 19:29:14 -0800155 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800156exit_loop:
157 mutex_unlock(&pHddTdlsCtx->lock);
Hoonki Leef63df0d2013-01-16 19:29:14 -0800158
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800159 if (0 != pHddTdlsCtx->discovery_peer_cnt) {
160 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
161 "discovery_peer_cnt is %d , Starting SUB_DISCOVERY_TIMER",
162 pHddTdlsCtx->discovery_peer_cnt);
163 discover_expiry = TDLS_SUB_DISCOVERY_PERIOD;
164 goto done;
165 }
166
167 discover_expiry = pHddTdlsCtx->threshold_config.discovery_period_t;
168
169 wlan_hdd_tdls_peer_reset_discovery_processed();
Chilam NG571c65a2013-01-19 12:27:36 +0530170
171 wlan_hdd_get_rssi(pAdapter, &pHddTdlsCtx->ap_rssi);
172
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800173done:
174 if (mutex_lock_interruptible(&pHddTdlsCtx->lock))
175 {
176 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
177 "%s: unable to lock list: %d", __func__, __LINE__);
178 return;
179 }
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800180
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800181 if (hdd_connIsConnected( pHddStaCtx ))
182 {
183 vos_timer_start(&pHddTdlsCtx->peerDiscoverTimer, discover_expiry);
184 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "beacon rssi: %d",
185 pHddTdlsCtx->ap_rssi);
186 }
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800187 mutex_unlock(&pHddTdlsCtx->lock);
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800188
Hoonki Leef63df0d2013-01-16 19:29:14 -0800189}
Chilam NG571c65a2013-01-19 12:27:36 +0530190
Hoonki Lee387663d2013-02-05 18:08:43 -0800191static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData )
Chilam NG571c65a2013-01-19 12:27:36 +0530192{
193 int i;
Hoonki Lee387663d2013-02-05 18:08:43 -0800194 struct list_head *head;
195 struct list_head *pos;
Chilam NG571c65a2013-01-19 12:27:36 +0530196 hddTdlsPeer_t *curr_peer;
197
Hoonki Leebfee0342013-01-21 16:43:45 -0800198 if (NULL == pHddTdlsCtx) return;
199
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800200 if (mutex_lock_interruptible(&pHddTdlsCtx->lock))
201 {
202 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
203 "%s: unable to lock list", __func__);
204 return;
205 }
206
Chilam NG571c65a2013-01-19 12:27:36 +0530207 for (i = 0; i < 256; i++) {
Hoonki Lee387663d2013-02-05 18:08:43 -0800208 head = &pHddTdlsCtx->peer_list[i];
Chilam NG571c65a2013-01-19 12:27:36 +0530209
Hoonki Lee387663d2013-02-05 18:08:43 -0800210 list_for_each (pos, head) {
211 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
Chilam NG571c65a2013-01-19 12:27:36 +0530212
Hoonki Lee387663d2013-02-05 18:08:43 -0800213 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Chilam Ng01120412013-02-19 18:32:21 -0800214 "hdd update cb - %d: " MAC_ADDRESS_STR " -> %d\n", i,
215 MAC_ADDR_ARRAY(curr_peer->peerMac),
Hoonki Lee387663d2013-02-05 18:08:43 -0800216 curr_peer->tx_pkt);
217
Chilam NG571c65a2013-01-19 12:27:36 +0530218 if (eTDLS_CAP_SUPPORTED == curr_peer->tdls_support) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800219 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800220 "%s: (tx %d, rx %d, config %d) " MAC_ADDRESS_STR " (%d) ",
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800221 __func__, curr_peer->tx_pkt, curr_peer->rx_pkt,
222 pHddTdlsCtx->threshold_config.tx_packet_n,
Chilam Ng01120412013-02-19 18:32:21 -0800223 MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->link_status);
224
Chilam NG571c65a2013-01-19 12:27:36 +0530225 if (eTDLS_LINK_CONNECTED != curr_peer->link_status) {
226 if (curr_peer->tx_pkt >=
227 pHddTdlsCtx->threshold_config.tx_packet_n) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800228
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800229 if (HDD_MAX_NUM_TDLS_STA > wlan_hdd_tdlsConnectedPeers())
230 {
231
232 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "-> Tput trigger TDLS SETUP");
Chilam NG571c65a2013-01-19 12:27:36 +0530233#ifdef CONFIG_TDLS_IMPLICIT
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800234 cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
235 curr_peer->peerMac,
236 NL80211_TDLS_SETUP, FALSE,
237 GFP_KERNEL);
Chilam NG571c65a2013-01-19 12:27:36 +0530238#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800239 }
240 else
241 {
242 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
243 "%s: TDLS max peer already connected.", __func__);
244 }
Hoonki Leecdd8e962013-01-20 00:45:46 -0800245 goto next_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530246 }
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800247#ifdef WLAN_FEATURE_TDLS_DEBUG
248 else {
249 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "-> ignored.");
250 }
251#endif
Chilam Ng01120412013-02-19 18:32:21 -0800252 if (((tANI_S32)curr_peer->rssi >
Hoonki Leecdd8e962013-01-20 00:45:46 -0800253 (tANI_S32)(pHddTdlsCtx->threshold_config.rssi_hysteresis +
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800254 pHddTdlsCtx->ap_rssi))&&(HDD_MAX_NUM_TDLS_STA > wlan_hdd_tdlsConnectedPeers())) {
Chilam NG571c65a2013-01-19 12:27:36 +0530255
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800256 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
257 "%s: RSSI (peer %d > ap %d + hysteresis %d) triggering to %02x:%02x:%02x:%02x:%02x:%02x ",
258 __func__, (tANI_S32)curr_peer->rssi,
259 pHddTdlsCtx->ap_rssi,
260 (tANI_S32)(pHddTdlsCtx->threshold_config.rssi_hysteresis),
261 curr_peer->peerMac[0], curr_peer->peerMac[1], curr_peer->peerMac[2],
262 curr_peer->peerMac[3], curr_peer->peerMac[4], curr_peer->peerMac[5]);
Chilam NG571c65a2013-01-19 12:27:36 +0530263
264#ifdef CONFIG_TDLS_IMPLICIT
265 cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
266 curr_peer->peerMac,
267 NL80211_TDLS_SETUP, FALSE,
268 GFP_KERNEL);
269#endif
270 }
271 } else {
Chilam Ng01120412013-02-19 18:32:21 -0800272 if ((tANI_S32)curr_peer->rssi <
273 (tANI_S32)pHddTdlsCtx->threshold_config.rssi_teardown_threshold) {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800274
Chilam Ng01120412013-02-19 18:32:21 -0800275 VOS_TRACE( VOS_MODULE_ID_HDD,
276 VOS_TRACE_LEVEL_WARN,
277 "Tear down - low RSSI: " MAC_ADDRESS_STR "!",
278 MAC_ADDR_ARRAY(curr_peer->peerMac));
279#ifdef CONFIG_TDLS_IMPLICIT
280 cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
281 curr_peer->peerMac,
282 NL80211_TDLS_TEARDOWN, FALSE,
283 GFP_KERNEL);
284#endif
Hoonki Leecdd8e962013-01-20 00:45:46 -0800285 goto next_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530286 }
Chilam Ng01120412013-02-19 18:32:21 -0800287
288 if ((curr_peer->tx_pkt <
289 pHddTdlsCtx->threshold_config.idle_packet_n) &&
290 (curr_peer->rx_pkt <
291 pHddTdlsCtx->threshold_config.idle_packet_n)) {
292 if (VOS_TIMER_STATE_RUNNING !=
293 vos_timer_getCurrentState(&curr_peer->peerIdleTimer)) {
294 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
295 "Tx/Rx Idle timer start: " MAC_ADDRESS_STR "!",
296 MAC_ADDR_ARRAY(curr_peer->peerMac));
297 vos_timer_start( &curr_peer->peerIdleTimer,
298 pHddTdlsCtx->threshold_config.idle_timeout_t );
299 }
300 } else {
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800301 if (VOS_TIMER_STATE_RUNNING ==
302 vos_timer_getCurrentState(&curr_peer->peerIdleTimer)) {
Chilam Ng01120412013-02-19 18:32:21 -0800303 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
304 "Tx/Rx Idle timer stop: " MAC_ADDRESS_STR "!",
305 MAC_ADDR_ARRAY(curr_peer->peerMac));
306 vos_timer_stop( &curr_peer->peerIdleTimer);
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800307 }
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800308 }
Chilam Ng01120412013-02-19 18:32:21 -0800309
Hoonki Leecdd8e962013-01-20 00:45:46 -0800310// if (curr_peer->rssi <
311// (pHddTdlsCtx->threshold_config.rssi_hysteresis +
312// pHddTdlsCtx->ap_rssi)) {
313//
314//#ifdef CONFIG_TDLS_IMPLICIT
315// cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
316// curr_peer->peerMac,
317// NL80211_TDLS_TEARDOWN, FALSE,
318// GFP_KERNEL);
319//#endif
320// }
Chilam NG571c65a2013-01-19 12:27:36 +0530321 }
Chilam Ng01120412013-02-19 18:32:21 -0800322 } else if (eTDLS_CAP_UNKNOWN == curr_peer->tdls_support) {
323 if (eTDLS_LINK_CONNECTED != curr_peer->link_status) {
324 if (curr_peer->tx_pkt >=
325 pHddTdlsCtx->threshold_config.tx_packet_n) {
326 hdd_adapter_t *pAdapter;
327 hdd_context_t *pHddCtx;
328
329 pAdapter = WLAN_HDD_GET_PRIV_PTR(pHddTdlsCtx->dev);
330 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
331
332 if (++curr_peer->discovery_attempt <
333 pHddTdlsCtx->threshold_config.discovery_tries_n) {
334 curr_peer->tdls_support = eTDLS_CAP_NOT_SUPPORTED;
335 wlan_hdd_cfg80211_send_tdls_discover_req(pHddCtx->wiphy,
336 pHddTdlsCtx->dev, curr_peer->peerMac);
337 }
338
339 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
340 "Tput triggering TDLS discovery: " MAC_ADDRESS_STR "!",
341 MAC_ADDR_ARRAY(curr_peer->peerMac));
342 }
343 }
Chilam NG571c65a2013-01-19 12:27:36 +0530344 }
345
Hoonki Leecdd8e962013-01-20 00:45:46 -0800346next_peer:
Chilam NG571c65a2013-01-19 12:27:36 +0530347 curr_peer->tx_pkt = 0;
Chilam Ng1279e232013-01-25 15:06:52 -0800348 curr_peer->rx_pkt = 0;
Hoonki Lee387663d2013-02-05 18:08:43 -0800349 }
Chilam NG571c65a2013-01-19 12:27:36 +0530350 }
351
352 vos_timer_start( &pHddTdlsCtx->peerUpdateTimer,
353 pHddTdlsCtx->threshold_config.tx_period_t );
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800354 mutex_unlock(&pHddTdlsCtx->lock);
Chilam NG571c65a2013-01-19 12:27:36 +0530355}
356
Chilam Ng1279e232013-01-25 15:06:52 -0800357static v_VOID_t wlan_hdd_tdls_idle_cb( v_PVOID_t userData )
358{
Lee Hoonkic1262f22013-01-24 21:59:00 -0800359#ifdef CONFIG_TDLS_IMPLICIT
Chilam Ng1279e232013-01-25 15:06:52 -0800360 hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData;
361
Chilam Ng1279e232013-01-25 15:06:52 -0800362
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800363 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800364 "%s: Tx/Rx Idle " MAC_ADDRESS_STR " trigger teardown",
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800365 __func__,
Chilam Ng01120412013-02-19 18:32:21 -0800366 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800367 if (mutex_lock_interruptible(&pHddTdlsCtx->lock))
368 {
369 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
370 "%s: unable to lock list", __func__);
371 return;
372 }
Hoonki Lee5a4b2172013-01-29 01:45:53 -0800373
Chilam Ng1279e232013-01-25 15:06:52 -0800374 cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
375 curr_peer->peerMac,
Hoonki Leea34dd892013-02-05 22:56:02 -0800376 NL80211_TDLS_TEARDOWN,
377 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON,
Chilam Ng1279e232013-01-25 15:06:52 -0800378 GFP_KERNEL);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800379 mutex_unlock(&pHddTdlsCtx->lock);
Chilam Ng1279e232013-01-25 15:06:52 -0800380#endif
381}
382
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800383static void wlan_hdd_tdls_free_list(void)
384{
385 int i;
386 struct list_head *head;
387 hddTdlsPeer_t *tmp;
388 struct list_head *pos, *q;
389
390 if (NULL == pHddTdlsCtx) return;
391
392 if (mutex_lock_interruptible(&pHddTdlsCtx->lock))
393 {
394 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
395 "%s: unable to lock list", __func__);
396 return;
397 }
398
399 for (i = 0; i < 256; i++) {
400 head = &pHddTdlsCtx->peer_list[i];
401 list_for_each_safe (pos, q, head) {
402 tmp = list_entry(pos, hddTdlsPeer_t, node);
403 list_del(pos);
404 vos_mem_free(tmp);
405 }
406 }
407 mutex_unlock(&pHddTdlsCtx->lock);
408
409}
410
Chilam Ng01120412013-02-19 18:32:21 -0800411static int wlan_hdd_tdls_core_init(struct net_device *dev, tdls_config_params_t *config)
412{
413 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
414 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
415 int i;
416
417 if (NULL == pHddTdlsCtx) {
418 pHddTdlsCtx = vos_mem_malloc(sizeof(tdlsCtx_t));
419
420 if (NULL == pHddTdlsCtx) {
421 hddLog(VOS_TRACE_LEVEL_ERROR, "%s malloc failed!", __func__);
422 return -1;
423 }
424
425 vos_mem_zero(pHddTdlsCtx, sizeof(tdlsCtx_t));
426
427 if (NULL == config) {
428 if (eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY != pHddCtx->tdls_mode) {
429 pHddTdlsCtx->threshold_config.tx_period_t =
430 pHddCtx->cfg_ini->fTDLSTxStatsPeriod;
431 pHddTdlsCtx->threshold_config.tx_packet_n =
432 pHddCtx->cfg_ini->fTDLSTxPacketThreshold;
433 pHddTdlsCtx->threshold_config.discovery_period_t =
434 pHddCtx->cfg_ini->fTDLSDiscoveryPeriod;
435 pHddTdlsCtx->threshold_config.discovery_tries_n =
436 pHddCtx->cfg_ini->fTDLSMaxDiscoveryAttempt;
437 pHddTdlsCtx->threshold_config.idle_timeout_t =
438 pHddCtx->cfg_ini->fTDLSIdleTimeout;
439 pHddTdlsCtx->threshold_config.idle_packet_n =
440 pHddCtx->cfg_ini->fTDLSIdlePacketThreshold;
441 pHddTdlsCtx->threshold_config.rssi_hysteresis =
442 pHddCtx->cfg_ini->fTDLSRSSIHysteresis;
443 pHddTdlsCtx->threshold_config.rssi_trigger_threshold =
444 pHddCtx->cfg_ini->fTDLSRSSITriggerThreshold;
445 pHddTdlsCtx->threshold_config.rssi_teardown_threshold =
446 pHddCtx->cfg_ini->fTDLSRSSITeardownThreshold;
447 }
448 } else {
449 memcpy(&pHddTdlsCtx->threshold_config, config,
450 sizeof(tdls_config_params_t));
451 }
452
453 mutex_init(&pHddTdlsCtx->lock);
454
455 for (i = 0; i < 256; i++)
456 {
457 INIT_LIST_HEAD(&pHddTdlsCtx->peer_list[i]);
458 }
459
460 pHddTdlsCtx->dev = dev;
461 }
462
463 vos_timer_init(&pHddTdlsCtx->peerDiscoverTimer,
464 VOS_TIMER_TYPE_SW,
465 wlan_hdd_tdls_discover_peer_cb,
466 pHddTdlsCtx);
467
468 vos_timer_init(&pHddTdlsCtx->peerUpdateTimer,
469 VOS_TIMER_TYPE_SW,
470 wlan_hdd_tdls_update_peer_cb,
471 pHddTdlsCtx);
472
473 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) {
474 vos_timer_start( &pHddTdlsCtx->peerDiscoverTimer,
475 pHddTdlsCtx->threshold_config.discovery_period_t );
476
477 vos_timer_start( &pHddTdlsCtx->peerUpdateTimer,
478 pHddTdlsCtx->threshold_config.tx_period_t );
479 }
480
481 return 0;
482}
483
Chilam NG571c65a2013-01-19 12:27:36 +0530484int wlan_hdd_tdls_init(struct net_device *dev)
485{
Hoonki Leebf870f32013-01-19 15:53:30 +0530486 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
487 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Chilam NG571c65a2013-01-19 12:27:36 +0530488
Hoonki Lee387663d2013-02-05 18:08:43 -0800489 if (FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport)
Hoonki Leebf870f32013-01-19 15:53:30 +0530490 {
Chilam Ng01120412013-02-19 18:32:21 -0800491 pHddCtx->tdls_mode = eTDLS_SUPPORT_DISABLED;
Hoonki Leebf870f32013-01-19 15:53:30 +0530492 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS not enabled!", __func__);
Hoonki Lee387663d2013-02-05 18:08:43 -0800493 return 0;
Hoonki Leebf870f32013-01-19 15:53:30 +0530494 }
495
Chilam Ng01120412013-02-19 18:32:21 -0800496 pHddCtx->tdls_mode = eTDLS_SUPPORT_ENABLED;
Chilam NG571c65a2013-01-19 12:27:36 +0530497
Chilam Ng01120412013-02-19 18:32:21 -0800498 if (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger)
Hoonki Lee387663d2013-02-05 18:08:43 -0800499 {
Chilam Ng01120412013-02-19 18:32:21 -0800500 pHddCtx->tdls_mode = eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY;
Hoonki Leebf870f32013-01-19 15:53:30 +0530501 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS Implicit trigger not enabled!", __func__);
Hoonki Leebf870f32013-01-19 15:53:30 +0530502 }
Chilam NG571c65a2013-01-19 12:27:36 +0530503
Chilam Ng01120412013-02-19 18:32:21 -0800504 return wlan_hdd_tdls_core_init(dev, NULL);
Chilam NG571c65a2013-01-19 12:27:36 +0530505}
506
507void wlan_hdd_tdls_exit()
508{
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800509 if (NULL == pHddTdlsCtx)
510 {
Hoonki Leebfee0342013-01-21 16:43:45 -0800511 hddLog(VOS_TRACE_LEVEL_WARN, "%s TDLS not enabled, exiting!", __func__);
512 return;
513 }
514
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800515 /* must stop timer here before freeing peer list, because peerIdleTimer is
516 part of peer list structure. */
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800517 wlan_hdd_tdls_timers_destroy();
Hoonki Lee387663d2013-02-05 18:08:43 -0800518 wlan_hdd_tdls_free_list();
Chilam Nga75d8b62013-01-29 01:35:59 -0800519
520 vos_mem_free(pHddTdlsCtx);
521 pHddTdlsCtx = NULL;
Chilam NG571c65a2013-01-19 12:27:36 +0530522}
523
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800524/* stop all the tdls timers running */
525void wlan_hdd_tdls_timers_stop(void)
526{
527 int i;
528 struct list_head *head;
529 struct list_head *pos;
530 hddTdlsPeer_t *curr_peer;
531
532 vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer);
533 vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer);
534
535 if (mutex_lock_interruptible(&pHddTdlsCtx->lock))
536 {
537 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
538 "%s: unable to lock list", __func__);
539 return;
540 }
541
542 for (i = 0; i < 256; i++)
543 {
544 head = &pHddTdlsCtx->peer_list[i];
545
546 list_for_each (pos, head) {
547 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
548
549 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800550 "%s: " MAC_ADDRESS_STR " -> stop idle timer",
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800551 __func__,
Chilam Ng01120412013-02-19 18:32:21 -0800552 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800553 vos_timer_stop ( &curr_peer->peerIdleTimer );
554 }
555 }
556 mutex_unlock(&pHddTdlsCtx->lock);
557}
558
559/* destroy all the tdls timers running */
560void wlan_hdd_tdls_timers_destroy(void)
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800561{
562 int i;
563 struct list_head *head;
564 struct list_head *pos;
565 hddTdlsPeer_t *curr_peer;
566
567 vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer);
568 vos_timer_destroy(&pHddTdlsCtx->peerDiscoverTimer);
569 vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer);
570 vos_timer_destroy(&pHddTdlsCtx->peerUpdateTimer);
571
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800572 if (mutex_lock_interruptible(&pHddTdlsCtx->lock))
573 {
574 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
575 "%s: unable to lock list", __func__);
576 return;
577 }
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800578 for (i = 0; i < 256; i++)
579 {
580 head = &pHddTdlsCtx->peer_list[i];
581
582 list_for_each (pos, head) {
583 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
584
585 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800586 "%s: " MAC_ADDRESS_STR " -> destroy idle timer",
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800587 __func__,
Chilam Ng01120412013-02-19 18:32:21 -0800588 MAC_ADDR_ARRAY(curr_peer->peerMac));
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800589 vos_timer_stop ( &curr_peer->peerIdleTimer );
590 vos_timer_destroy ( &curr_peer->peerIdleTimer );
591 }
592 }
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800593 mutex_unlock(&pHddTdlsCtx->lock);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800594}
595
Hoonki Lee387663d2013-02-05 18:08:43 -0800596/* if mac address exist, return pointer
597 if mac address doesn't exist, create a list and add, return pointer
598 return NULL if fails to get new mac address
599*/
600hddTdlsPeer_t *wlan_hdd_tdls_get_peer(u8 *mac)
Chilam NG571c65a2013-01-19 12:27:36 +0530601{
Hoonki Lee387663d2013-02-05 18:08:43 -0800602 struct list_head *head;
603 hddTdlsPeer_t *peer;
Chilam Ng01120412013-02-19 18:32:21 -0800604 hdd_adapter_t *pAdapter;
605 hdd_context_t *pHddCtx;
Hoonki Lee387663d2013-02-05 18:08:43 -0800606 u8 key;
Chilam NG571c65a2013-01-19 12:27:36 +0530607
Hoonki Lee387663d2013-02-05 18:08:43 -0800608 if (NULL == pHddTdlsCtx)
609 return NULL;
Hoonki Leebfee0342013-01-21 16:43:45 -0800610
Hoonki Lee387663d2013-02-05 18:08:43 -0800611 /* if already there, just update */
612 peer = wlan_hdd_tdls_find_peer(mac);
613 if (peer != NULL)
614 {
615 return peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530616 }
617
Hoonki Lee387663d2013-02-05 18:08:43 -0800618 /* not found, allocate and add the list */
619 peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
620 if (NULL == peer) {
621 hddLog(VOS_TRACE_LEVEL_ERROR, "%s peer malloc failed!", __func__);
622 return NULL;
623 }
Chilam NG571c65a2013-01-19 12:27:36 +0530624
Hoonki Lee387663d2013-02-05 18:08:43 -0800625 key = wlan_hdd_tdls_hash_key(mac);
626 head = &pHddTdlsCtx->peer_list[key];
Chilam NG571c65a2013-01-19 12:27:36 +0530627
Hoonki Lee387663d2013-02-05 18:08:43 -0800628 if (mutex_lock_interruptible(&pHddTdlsCtx->lock))
629 {
630 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
631 "%s: unable to lock list", __func__);
632 return NULL;
633 }
Chilam NG571c65a2013-01-19 12:27:36 +0530634
Hoonki Lee387663d2013-02-05 18:08:43 -0800635 vos_mem_zero(peer, sizeof(hddTdlsPeer_t));
636 vos_mem_copy(peer->peerMac, mac, sizeof(peer->peerMac));
637
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800638 vos_timer_init(&peer->peerIdleTimer,
639 VOS_TIMER_TYPE_SW,
640 wlan_hdd_tdls_idle_cb,
641 peer);
642
Chilam Ng01120412013-02-19 18:32:21 -0800643 pAdapter = WLAN_HDD_GET_PRIV_PTR(pHddTdlsCtx->dev);
644 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
645
646 if (++peer->discovery_attempt <
647 pHddTdlsCtx->threshold_config.discovery_tries_n) {
648 wlan_hdd_cfg80211_send_tdls_discover_req(pHddCtx->wiphy,
649 pHddTdlsCtx->dev, peer->peerMac);
650 }
651
Hoonki Lee387663d2013-02-05 18:08:43 -0800652 list_add_tail(&peer->node, head);
653 mutex_unlock(&pHddTdlsCtx->lock);
654
655 return peer;
656}
657
658void wlan_hdd_tdls_set_link_status(hddTdlsPeer_t *curr_peer, int status)
659{
660 if (curr_peer == NULL)
661 return;
662
Chilam Ng01120412013-02-19 18:32:21 -0800663 hddLog(VOS_TRACE_LEVEL_WARN, "tdls set peer " MAC_ADDRESS_STR " link status to %d",
664 MAC_ADDR_ARRAY(curr_peer->peerMac), status);
Chilam NG571c65a2013-01-19 12:27:36 +0530665
666 curr_peer->link_status = status;
667
Chilam NG571c65a2013-01-19 12:27:36 +0530668}
669
670int wlan_hdd_tdls_set_cap(u8 *mac, int cap)
671{
672 hddTdlsPeer_t *curr_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530673
Hoonki Leebfee0342013-01-21 16:43:45 -0800674 if (NULL == pHddTdlsCtx) return -1;
675
Hoonki Lee387663d2013-02-05 18:08:43 -0800676 curr_peer = wlan_hdd_tdls_get_peer(mac);
677 if (curr_peer == NULL)
678 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530679
680 curr_peer->tdls_support = cap;
681
Hoonki Lee387663d2013-02-05 18:08:43 -0800682 return 0;
Chilam NG571c65a2013-01-19 12:27:36 +0530683}
684
685int wlan_hdd_tdls_set_rssi(u8 *mac, tANI_S8 rxRssi)
686{
687 hddTdlsPeer_t *curr_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530688
Hoonki Leebfee0342013-01-21 16:43:45 -0800689 if (NULL == pHddTdlsCtx) return -1;
690
Hoonki Lee387663d2013-02-05 18:08:43 -0800691 curr_peer = wlan_hdd_tdls_get_peer(mac);
692 if (curr_peer == NULL)
693 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530694
695 curr_peer->rssi = rxRssi;
696
Hoonki Lee387663d2013-02-05 18:08:43 -0800697 return 0;
Chilam NG571c65a2013-01-19 12:27:36 +0530698}
699
Hoonki Leea34dd892013-02-05 22:56:02 -0800700int wlan_hdd_tdls_set_responder(u8 *mac, tANI_U8 responder)
701{
702 hddTdlsPeer_t *curr_peer;
703
704 if (NULL == pHddTdlsCtx) return -1;
705
706 curr_peer = wlan_hdd_tdls_get_peer(mac);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800707 if (curr_peer == NULL)
Hoonki Leea34dd892013-02-05 22:56:02 -0800708 return -1;
709
710 curr_peer->is_responder = responder;
711
712 return 0;
713}
714
715int wlan_hdd_tdls_get_responder(u8 *mac)
716{
717 hddTdlsPeer_t *curr_peer;
718
719 if (NULL == pHddTdlsCtx) return -1;
720
721 curr_peer = wlan_hdd_tdls_find_peer(mac);
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800722 if (curr_peer == NULL)
Hoonki Leea34dd892013-02-05 22:56:02 -0800723 return -1;
724
725 return (curr_peer->is_responder);
726}
727
Hoonki Lee11f7dda2013-02-14 16:55:44 -0800728int wlan_hdd_tdls_set_signature(u8 *mac, tANI_U8 uSignature)
729{
730 hddTdlsPeer_t *curr_peer;
731
732 if (NULL == pHddTdlsCtx) return -1;
733
734 curr_peer = wlan_hdd_tdls_get_peer(mac);
735 if (curr_peer == NULL)
736 return -1;
737
738 curr_peer->signature = uSignature;
739
740 return 0;
741}
742
Hoonki Leea34dd892013-02-05 22:56:02 -0800743
Hoonki Lee387663d2013-02-05 18:08:43 -0800744void wlan_hdd_tdls_extract_da(struct sk_buff *skb, u8 *mac)
Chilam NG571c65a2013-01-19 12:27:36 +0530745{
Chilam NG571c65a2013-01-19 12:27:36 +0530746 memcpy(mac, skb->data, 6);
Chilam NG571c65a2013-01-19 12:27:36 +0530747}
748
Hoonki Lee387663d2013-02-05 18:08:43 -0800749void wlan_hdd_tdls_extract_sa(struct sk_buff *skb, u8 *mac)
Chilam Ng1279e232013-01-25 15:06:52 -0800750{
Chilam Ng1279e232013-01-25 15:06:52 -0800751 memcpy(mac, skb->data+6, 6);
Chilam Ng1279e232013-01-25 15:06:52 -0800752}
753
Hoonki Lee387663d2013-02-05 18:08:43 -0800754int wlan_hdd_tdls_increment_pkt_count(u8 *mac, u8 tx)
Chilam NG571c65a2013-01-19 12:27:36 +0530755{
Hoonki Lee387663d2013-02-05 18:08:43 -0800756 hddTdlsPeer_t *curr_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530757
Hoonki Leebfee0342013-01-21 16:43:45 -0800758 if (NULL == pHddTdlsCtx) return -1;
759
Hoonki Lee387663d2013-02-05 18:08:43 -0800760 curr_peer = wlan_hdd_tdls_get_peer(mac);
761 if (curr_peer == NULL)
Chilam NG571c65a2013-01-19 12:27:36 +0530762 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530763
Chilam Ng1279e232013-01-25 15:06:52 -0800764 if (tx)
765 curr_peer->tx_pkt++;
766 else
767 curr_peer->rx_pkt++;
Chilam NG571c65a2013-01-19 12:27:36 +0530768
Chilam NG571c65a2013-01-19 12:27:36 +0530769 return 0;
770}
771
Chilam Ng01120412013-02-19 18:32:21 -0800772int wlan_hdd_tdls_set_params(struct net_device *dev, tdls_config_params_t *config)
Chilam NG571c65a2013-01-19 12:27:36 +0530773{
Chilam Ng01120412013-02-19 18:32:21 -0800774 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
775 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Hoonki Leebfee0342013-01-21 16:43:45 -0800776
Chilam Ng01120412013-02-19 18:32:21 -0800777 if ((eTDLS_SUPPORT_DISABLED == config->tdls) &&
778 ((NULL == pHddTdlsCtx) ||
779 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))) return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530780
Chilam Ng01120412013-02-19 18:32:21 -0800781 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) {
782 vos_timer_stop( &pHddTdlsCtx->peerDiscoverTimer);
783 vos_timer_stop( &pHddTdlsCtx->peerUpdateTimer);
784 }
Chilam NG571c65a2013-01-19 12:27:36 +0530785
Chilam Ng01120412013-02-19 18:32:21 -0800786 if (eTDLS_SUPPORT_DISABLED != pHddCtx->tdls_mode) {
787 memcpy(&pHddTdlsCtx->threshold_config, config, sizeof(tdls_config_params_t));
788 }
Chilam NG571c65a2013-01-19 12:27:36 +0530789
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800790 wlan_hdd_tdls_peer_reset_discovery_processed();
791
Chilam Ng01120412013-02-19 18:32:21 -0800792 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
793 "iw set tdls params: %d %d %d %d %d %d %d %d %d %d",
794 config->tdls,
795 config->tx_period_t,
796 config->tx_packet_n,
797 config->discovery_period_t,
798 config->discovery_tries_n,
799 config->idle_timeout_t,
800 config->idle_packet_n,
801 config->rssi_hysteresis,
802 config->rssi_trigger_threshold,
803 config->rssi_teardown_threshold);
Chilam NG571c65a2013-01-19 12:27:36 +0530804
Chilam Ng01120412013-02-19 18:32:21 -0800805 pHddCtx->tdls_mode = config->tdls;
806
807 if (eTDLS_SUPPORT_DISABLED == config->tdls) {
808 wlan_hdd_tdls_exit();
809 } else {
810 wlan_hdd_tdls_core_init(dev, config);
811 }
812
Chilam NG571c65a2013-01-19 12:27:36 +0530813 return 0;
814}
815
Hoonki Lee387663d2013-02-05 18:08:43 -0800816int wlan_hdd_tdls_set_sta_id(u8 *mac, u8 staId)
Kiran V1ccee932012-12-12 14:49:46 -0800817{
Hoonki Lee387663d2013-02-05 18:08:43 -0800818 hddTdlsPeer_t *curr_peer;
Kiran V1ccee932012-12-12 14:49:46 -0800819
Hoonki Leebfee0342013-01-21 16:43:45 -0800820 if (NULL == pHddTdlsCtx) return -1;
821
Hoonki Lee387663d2013-02-05 18:08:43 -0800822 curr_peer = wlan_hdd_tdls_get_peer(mac);
823 if (curr_peer == NULL)
Chilam NG571c65a2013-01-19 12:27:36 +0530824 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530825
Hoonki Lee387663d2013-02-05 18:08:43 -0800826 curr_peer->staId = staId;
Chilam NG571c65a2013-01-19 12:27:36 +0530827
828 return 0;
Kiran V1ccee932012-12-12 14:49:46 -0800829}
830
Hoonki Lee387663d2013-02-05 18:08:43 -0800831/* if peerMac is found, then it returns pointer to hddTdlsPeer_t
832 otherwise, it returns NULL
833*/
834hddTdlsPeer_t *wlan_hdd_tdls_find_peer(u8 *mac)
Kiran V1ccee932012-12-12 14:49:46 -0800835{
Hoonki Lee387663d2013-02-05 18:08:43 -0800836 u8 key;
837 struct list_head *pos;
838 struct list_head *head;
839 hddTdlsPeer_t *curr_peer;
840
841 if (NULL == pHddTdlsCtx)
842 return NULL;
843
844 key = wlan_hdd_tdls_hash_key(mac);
845
846 head = &pHddTdlsCtx->peer_list[key];
847
848 if (mutex_lock_interruptible(&pHddTdlsCtx->lock))
849 {
850 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
851 "%s: unable to lock list", __func__);
852 return NULL;
853 }
854
855 list_for_each(pos, head) {
856 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
857 if (!memcmp(mac, curr_peer->peerMac, 6)) {
858 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
859 "findTdlsPeer: found staId %d", curr_peer->staId);
860 mutex_unlock(&pHddTdlsCtx->lock);
861 return curr_peer;
862 }
863 }
864
865 mutex_unlock(&pHddTdlsCtx->lock);
866 return NULL;
867}
868
869int wlan_hdd_tdls_reset_peer(u8 *mac)
870{
Chilam Ng01120412013-02-19 18:32:21 -0800871 hdd_adapter_t *pAdapter;
872 hdd_context_t *pHddCtx;
Chilam NG571c65a2013-01-19 12:27:36 +0530873 hddTdlsPeer_t *curr_peer;
Kiran V1ccee932012-12-12 14:49:46 -0800874
Hoonki Leebfee0342013-01-21 16:43:45 -0800875 if (NULL == pHddTdlsCtx) return -1;
876
Chilam Ng01120412013-02-19 18:32:21 -0800877 pAdapter = WLAN_HDD_GET_PRIV_PTR(pHddTdlsCtx->dev);
878 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
879
Hoonki Lee387663d2013-02-05 18:08:43 -0800880 curr_peer = wlan_hdd_tdls_get_peer(mac);
881 if (curr_peer == NULL)
882 return -1;
Chilam NG571c65a2013-01-19 12:27:36 +0530883
Hoonki Leecdd8e962013-01-20 00:45:46 -0800884 curr_peer->link_status = eTDLS_LINK_NOT_CONNECTED;
885 curr_peer->staId = 0;
886 curr_peer->rssi = -120;
Hoonki Lee387663d2013-02-05 18:08:43 -0800887
Chilam Ng01120412013-02-19 18:32:21 -0800888 if(eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) {
Chilam Nga75d8b62013-01-29 01:35:59 -0800889 vos_timer_stop( &curr_peer->peerIdleTimer );
Chilam Nga75d8b62013-01-29 01:35:59 -0800890 }
Hoonki Lee387663d2013-02-05 18:08:43 -0800891 return 0;
Hoonki Leecdd8e962013-01-20 00:45:46 -0800892}
893
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800894static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(void)
895{
896 int i;
897 struct list_head *head;
898 hddTdlsPeer_t *tmp;
899 struct list_head *pos, *q;
900
901 if (NULL == pHddTdlsCtx) return -1;
902
903 if (mutex_lock_interruptible(&pHddTdlsCtx->lock))
904 {
905 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
906 "%s: unable to lock list", __func__);
907 return -1;
908 }
909
910 pHddTdlsCtx->discovery_peer_cnt = 0;
911
912 for (i = 0; i < 256; i++) {
913 head = &pHddTdlsCtx->peer_list[i];
914 list_for_each_safe (pos, q, head) {
915 tmp = list_entry(pos, hddTdlsPeer_t, node);
916 tmp->discovery_processed = 0;
917 }
918 }
919 mutex_unlock(&pHddTdlsCtx->lock);
920
921 return 0;
922}
923
924static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(void)
925{
926 int i;
927 struct list_head *head;
928 struct list_head *pos, *q;
929 int discovery_peer_cnt=0;
930 hddTdlsPeer_t *tmp;
931
932 if (NULL == pHddTdlsCtx) return -1;
933
934 if (mutex_lock_interruptible(&pHddTdlsCtx->lock))
935 {
936 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
937 "%s: unable to lock list", __func__);
938 return -1;
939 }
940
941 for (i = 0; i < 256; i++) {
942 head = &pHddTdlsCtx->peer_list[i];
943 list_for_each_safe (pos, q, head) {
944 tmp = list_entry(pos, hddTdlsPeer_t, node);
945 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Chilam Ng01120412013-02-19 18:32:21 -0800946 "%s, %d, " MAC_ADDRESS_STR, __func__, i,
947 MAC_ADDR_ARRAY(tmp->peerMac));
Gopichand Nakkalac3694582013-02-13 20:51:22 -0800948 discovery_peer_cnt++;
949 }
950 }
951 mutex_unlock(&pHddTdlsCtx->lock);
952
953 return discovery_peer_cnt;
954}
955
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800956tANI_U16 wlan_hdd_tdlsConnectedPeers(void)
Lee Hoonkic1262f22013-01-24 21:59:00 -0800957{
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800958 if (NULL == pHddTdlsCtx)
959 return 0;
Lee Hoonkic1262f22013-01-24 21:59:00 -0800960
Gopichand Nakkalab977a972013-02-18 19:15:09 -0800961 return pHddTdlsCtx->connected_peer_count;
Lee Hoonkic1262f22013-01-24 21:59:00 -0800962}
Chilam Ng16a2a1c2013-01-29 01:27:29 -0800963
964int wlan_hdd_tdls_get_all_peers(char *buf, int buflen)
965{
966 int i;
967 int len, init_len;
Hoonki Lee387663d2013-02-05 18:08:43 -0800968 struct list_head *head;
969 struct list_head *pos;
Chilam Ng16a2a1c2013-01-29 01:27:29 -0800970 hddTdlsPeer_t *curr_peer;
971
972 if (NULL == pHddTdlsCtx) {
973 len = snprintf(buf, buflen, "TDLS not enabled\n");
974 return len;
975 }
976
977 init_len = buflen;
978 len = snprintf(buf, buflen, "\n%-18s%-3s%-4s%-3s%-5s\n", "MAC", "Id", "cap", "up", "RSSI");
979 buf += len;
980 buflen -= len;
981 /* 1234567890123456789012345678901234567 */
982 len = snprintf(buf, buflen, "---------------------------------\n");
983 buf += len;
984 buflen -= len;
985
Gopichand Nakkala91b09262013-02-10 14:27:02 -0800986 if (mutex_lock_interruptible(&pHddTdlsCtx->lock))
987 {
988 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
989 "%s: unable to lock list", __func__);
990 return init_len-buflen;
991 }
Chilam Ng16a2a1c2013-01-29 01:27:29 -0800992 for (i = 0; i < 256; i++) {
Hoonki Lee387663d2013-02-05 18:08:43 -0800993 head = &pHddTdlsCtx->peer_list[i];
Chilam Ng16a2a1c2013-01-29 01:27:29 -0800994
Hoonki Lee387663d2013-02-05 18:08:43 -0800995 list_for_each(pos, head) {
996 curr_peer= list_entry (pos, hddTdlsPeer_t, node);
Chilam Ng16a2a1c2013-01-29 01:27:29 -0800997
Hoonki Lee387663d2013-02-05 18:08:43 -0800998 if (buflen < 32+1)
999 break;
1000 len = snprintf(buf, buflen,
Chilam Ng01120412013-02-19 18:32:21 -08001001 MAC_ADDRESS_STR"%3d%4s%3s%5d\n",
1002 MAC_ADDR_ARRAY(curr_peer->peerMac),
Hoonki Lee387663d2013-02-05 18:08:43 -08001003 curr_peer->staId,
1004 (curr_peer->tdls_support == eTDLS_CAP_SUPPORTED) ? "Y":"N",
1005 (curr_peer->link_status == eTDLS_LINK_CONNECTED) ? "Y":"N",
1006 curr_peer->rssi);
1007 buf += len;
1008 buflen -= len;
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001009 }
1010 }
Gopichand Nakkala91b09262013-02-10 14:27:02 -08001011 mutex_unlock(&pHddTdlsCtx->lock);
Chilam Ng16a2a1c2013-01-29 01:27:29 -08001012 return init_len-buflen;
1013}
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001014
1015void wlan_hdd_tdls_connection_callback(hdd_adapter_t *pAdapter)
1016{
1017 if (NULL == pHddTdlsCtx) return;
1018
1019 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
1020 "%s, update %d discover %d", __func__,
1021 pHddTdlsCtx->threshold_config.tx_period_t,
1022 pHddTdlsCtx->threshold_config.discovery_period_t);
1023
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001024 pHddTdlsCtx->connected_peer_count = 0;
1025
Gopichand Nakkalac3694582013-02-13 20:51:22 -08001026 wlan_hdd_tdls_peer_reset_discovery_processed();
1027
1028 vos_timer_start(&pHddTdlsCtx->peerDiscoverTimer,
1029 pHddTdlsCtx->threshold_config.discovery_period_t);
1030
1031
1032 vos_timer_start(&pHddTdlsCtx->peerUpdateTimer,
1033 pHddTdlsCtx->threshold_config.tx_period_t);
1034
1035}
1036
1037void wlan_hdd_tdls_disconnection_callback(hdd_adapter_t *pAdapter)
1038{
1039 if (NULL == pHddTdlsCtx) return;
1040
1041 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s", __func__);
1042
1043 wlan_hdd_tdls_timers_stop();
1044 wlan_hdd_tdls_free_list();
1045}
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001046
1047void wlan_hdd_tdls_mgmt_completion_callback(hdd_adapter_t *pAdapter, tANI_U32 statusCode)
1048{
1049 pAdapter->mgmtTxCompletionStatus = statusCode;
1050 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s: Mgmt TX Completion %d",
1051 __func__, statusCode);
1052 complete(&pAdapter->tdls_mgmt_comp);
1053}
1054
1055void wlan_hdd_tdls_increment_peer_count(void)
1056{
1057 if (NULL == pHddTdlsCtx) return;
1058
1059 pHddTdlsCtx->connected_peer_count++;
1060}
1061
1062void wlan_hdd_tdls_decrement_peer_count(void)
1063{
1064 if (NULL == pHddTdlsCtx) return;
1065
1066 if (pHddTdlsCtx->connected_peer_count)
1067 pHddTdlsCtx->connected_peer_count--;
1068}
1069
1070void wlan_hdd_tdls_check_bmps(hdd_context_t *pHddCtx)
1071{
1072 if (NULL == pHddTdlsCtx) return;
1073
1074 if (0 == pHddTdlsCtx->connected_peer_count)
1075 {
1076 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"No TDLS peer connected so Enable BMPS");
1077 hdd_enable_bmps_imps(pHddCtx);
1078 }
1079 else if (1 == pHddTdlsCtx->connected_peer_count)
1080 {
1081 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"TDLS peer connected so Disable BMPS");
1082 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
1083 }
1084 return;
1085}
1086
1087/* return TRUE if TDLS is ongoing
1088 * mac - if NULL check for all the peer list, otherwise, skip this mac when skip_self is TRUE
1089 * skip_self - if TRUE, skip this mac. otherwise, check all the peer list. if
1090 mac is NULL, this argument is ignored, and check for all the peer list.
1091 */
1092u8 wlan_hdd_tdls_is_progress(u8 *mac, u8 skip_self)
1093{
1094 int i;
1095 struct list_head *head;
1096 hddTdlsPeer_t *curr_peer;
1097 struct list_head *pos;
1098
1099 if (NULL == pHddTdlsCtx) return FALSE;
1100
1101 if (mutex_lock_interruptible(&pHddTdlsCtx->lock))
1102 {
1103 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1104 "%s: unable to lock list", __func__);
1105 return FALSE;
1106 }
1107
1108 for (i = 0; i < 256; i++) {
1109 head = &pHddTdlsCtx->peer_list[i];
1110 list_for_each(pos, head) {
1111 curr_peer = list_entry (pos, hddTdlsPeer_t, node);
1112 if (skip_self && mac && !memcmp(mac, curr_peer->peerMac, 6)) {
1113 continue;
1114 }
1115 else
1116 {
1117 if (curr_peer->isTDLSInProgress)
1118 {
1119 mutex_unlock(&pHddTdlsCtx->lock);
1120 return TRUE;
1121 }
1122 }
1123 }
1124 }
1125
1126 mutex_unlock(&pHddTdlsCtx->lock);
1127 return FALSE;
1128}
1129
1130void wlan_hdd_tdls_set_connection_progress(u8* mac, u8 isProgress)
1131{
1132 hddTdlsPeer_t *curr_peer;
1133
1134 if (NULL == pHddTdlsCtx) return;
1135
1136 curr_peer = wlan_hdd_tdls_find_peer(mac);
1137 if (curr_peer == NULL)
1138 return;
1139
1140 curr_peer->isTDLSInProgress = isProgress;
1141
1142 return;
1143}