blob: d9d60d5c06951003f771f500de967e3ca6aae640 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Dustin Brown4ea21db2018-01-05 14:13:17 -08002 * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
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 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_tdls.c
30 *
31 * WLAN Host Device Driver implementation for TDLS
32 */
33
34#include <wlan_hdd_includes.h>
Archana Ramachandran2ad7de22016-04-22 16:53:25 -070035#include <ani_global.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080036#include <wlan_hdd_hostapd.h>
37#include <wlan_hdd_trace.h>
38#include <net/cfg80211.h>
39#include <linux/netdevice.h>
40#include <linux/skbuff.h>
41#include <linux/list.h>
42#include <linux/etherdevice.h>
43#include <net/ieee80211_radiotap.h>
44#include "wlan_hdd_tdls.h"
45#include "wlan_hdd_cfg80211.h"
Nitesh Shah99dd9552017-03-20 19:27:47 +053046#include "wlan_hdd_assoc.h"
47#include "sme_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080048#include "cds_sched.h"
49#include "wma_types.h"
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080050#include "wlan_policy_mgr_api.h"
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080051#include <qca_vendor.h>
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080052#include "wlan_hdd_ipa.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053
Kabilan Kannand053aaf2016-10-26 02:06:14 -070054/**
55 * enum qca_wlan_vendor_tdls_trigger_mode_hdd_map: Maps the user space TDLS
56 * trigger mode in the host driver.
57 * @WLAN_HDD_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT: TDLS Connection and
58 * disconnection handled by user space.
59 * @WLAN_HDD_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT: TDLS connection and
60 * disconnection controlled by host driver based on data traffic.
61 * @WLAN_HDD_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL: TDLS connection and
62 * disconnection jointly controlled by user space and host driver.
63 */
64enum qca_wlan_vendor_tdls_trigger_mode_hdd_map {
65 WLAN_HDD_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT =
66 QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT,
67 WLAN_HDD_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT =
68 QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT,
69 WLAN_HDD_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL =
70 ((QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT |
71 QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT) << 1),
72};
73
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080074/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080075 * wlan_hdd_tdls_get_all_peers() - dump all TDLS peer info into output string
Jeff Johnson6bff8942017-10-02 13:22:18 -070076 * @adapter: HDD adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080077 * @buf: output string buffer to hold the peer info
78 * @buflen: the size of output string buffer
79 *
80 * Return: The size (in bytes) of the valid peer info in the output buffer
81 */
Jeff Johnson6bff8942017-10-02 13:22:18 -070082int wlan_hdd_tdls_get_all_peers(struct hdd_adapter *adapter,
Jeff Johnson327b9d42017-08-29 14:20:07 -070083 char *buf, int buflen)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080084{
Kabilan Kannan3eeefea2017-11-14 17:27:03 -080085 int len;
86 struct hdd_context *hdd_ctx;
87
88 ENTER();
89
90 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
91 if (0 != (wlan_hdd_validate_context(hdd_ctx))) {
92 len = scnprintf(buf, buflen,
93 "\nHDD context is not valid\n");
94 return len;
95 }
96
97 if ((QDF_STA_MODE != adapter->device_mode) &&
98 (QDF_P2P_CLIENT_MODE != adapter->device_mode)) {
99 len = scnprintf(buf, buflen,
100 "\nNo TDLS support for this adapter\n");
101 return len;
102 }
103
104 return wlan_cfg80211_tdls_get_all_peers(adapter->hdd_vdev,
105 buf, buflen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800106}
107
108#ifdef FEATURE_WLAN_TDLS
109static const struct nla_policy
110 wlan_hdd_tdls_config_enable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX +
111 1] = {
Jeff Johnson19a5a7e2017-06-15 14:51:26 -0700112 [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR] = {
113 .type = NLA_UNSPEC,
114 .len = QDF_MAC_ADDR_SIZE},
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530115 [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL] = {.type = NLA_U32},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800116 [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS] = {.type =
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530117 NLA_U32},
118 [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS] = {.type = NLA_U32},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800119 [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS] = {.type =
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530120 NLA_U32},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800121};
122static const struct nla_policy
123 wlan_hdd_tdls_config_disable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX +
124 1] = {
Jeff Johnson19a5a7e2017-06-15 14:51:26 -0700125 [QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR] = {
126 .type = NLA_UNSPEC,
127 .len = QDF_MAC_ADDR_SIZE},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800128};
129static const struct nla_policy
130 wlan_hdd_tdls_config_state_change_policy[QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAX
131 + 1] = {
Jeff Johnson19a5a7e2017-06-15 14:51:26 -0700132 [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR] = {
133 .type = NLA_UNSPEC,
134 .len = QDF_MAC_ADDR_SIZE},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800135 [QCA_WLAN_VENDOR_ATTR_TDLS_NEW_STATE] = {.type = NLA_U32},
136 [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_REASON] = {.type = NLA_S32},
137 [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_CHANNEL] = {.type = NLA_U32},
138 [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_GLOBAL_OPERATING_CLASS] = {.type =
139 NLA_U32},
140};
141static const struct nla_policy
142 wlan_hdd_tdls_config_get_status_policy
143[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX + 1] = {
Jeff Johnson19a5a7e2017-06-15 14:51:26 -0700144 [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR] = {
145 .type = NLA_UNSPEC,
146 .len = QDF_MAC_ADDR_SIZE},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147 [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE] = {.type = NLA_U32},
148 [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON] = {.type = NLA_S32},
149 [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_CHANNEL] = {.type = NLA_U32},
150 [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_GLOBAL_OPERATING_CLASS] = {
151 .type = NLA_U32},
152};
153
Kabilan Kannand053aaf2016-10-26 02:06:14 -0700154static const struct nla_policy
155 wlan_hdd_tdls_mode_configuration_policy
156 [QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX + 1] = {
157 [QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TRIGGER_MODE] = {
158 .type = NLA_U32},
159 [QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_STATS_PERIOD] = {
160 .type = NLA_U32},
161 [QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_THRESHOLD] = {
162 .type = NLA_U32},
163 [QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_DISCOVERY_PERIOD] = {
164 .type = NLA_U32},
165 [QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX_DISCOVERY_ATTEMPT] = {
166 .type = NLA_U32},
167 [QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_TIMEOUT] = {
168 .type = NLA_U32},
169 [QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_PACKET_THRESHOLD] = {
170 .type = NLA_U32},
171 [QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_SETUP_RSSI_THRESHOLD] = {
172 .type = NLA_S32},
173 [QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TEARDOWN_RSSI_THRESHOLD] = {
174 .type = NLA_S32},
175};
176
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800177/**
178 * __wlan_hdd_cfg80211_exttdls_get_status() - handle get status cfg80211 command
179 * @wiphy: wiphy
180 * @wdev: wireless dev
181 * @data: netlink buffer with the mac address of the peer to get the status for
182 * @data_len: length of data in bytes
183 */
184static int
185__wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy,
186 struct wireless_dev *wdev,
187 const void *data,
188 int data_len)
189{
Frank Liu5c63dc82017-09-07 14:49:05 +0800190 /* TODO */
191 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800192}
193
194/**
Kabilan Kannand053aaf2016-10-26 02:06:14 -0700195 * __wlan_hdd_cfg80211_configure_tdls_mode() - configure the tdls mode
196 * @wiphy: wiphy
197 * @wdev: wireless dev
198 * @data: netlink buffer
199 * @data_len: length of data in bytes
200 *
201 * Return 0 for success and error code for failure
202 */
203static int
204__wlan_hdd_cfg80211_configure_tdls_mode(struct wiphy *wiphy,
205 struct wireless_dev *wdev,
206 const void *data,
207 int data_len)
208{
209 struct net_device *dev = wdev->netdev;
Jeff Johnsonaf772ed2017-08-28 11:40:36 -0700210 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnson327b9d42017-08-29 14:20:07 -0700211 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Kabilan Kannand053aaf2016-10-26 02:06:14 -0700212 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX + 1];
213 int ret;
Kabilan Kannand053aaf2016-10-26 02:06:14 -0700214 uint32_t trigger_mode;
Kabilan Kannand053aaf2016-10-26 02:06:14 -0700215
216 ENTER_DEV(dev);
217
218 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
219 hdd_err("Command not allowed in FTM mode");
220 return -EPERM;
221 }
222
223 ret = wlan_hdd_validate_context(hdd_ctx);
224 if (0 != ret)
225 return -EINVAL;
226
227 if (NULL == adapter)
228 return -EINVAL;
229
Dustin Brown4ea21db2018-01-05 14:13:17 -0800230 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX,
231 data, data_len,
232 wlan_hdd_tdls_mode_configuration_policy)) {
Kabilan Kannand053aaf2016-10-26 02:06:14 -0700233 hdd_err("Invalid attribute");
234 return -EINVAL;
235 }
236
237 if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TRIGGER_MODE]) {
238 hdd_err("attr tdls trigger mode failed");
239 return -EINVAL;
240 }
241 trigger_mode = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TRIGGER_MODE]);
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700242 hdd_debug("TDLS trigger mode %d", trigger_mode);
Kabilan Kannand053aaf2016-10-26 02:06:14 -0700243
Kabilan Kannan1c1c4022017-04-06 22:49:26 -0700244 if (hdd_ctx->tdls_umac_comp_active) {
245 ret = wlan_cfg80211_tdls_configure_mode(adapter->hdd_vdev,
246 trigger_mode);
247 return ret;
248 }
249
Frank Liu5c63dc82017-09-07 14:49:05 +0800250 return -EINVAL;
Kabilan Kannand053aaf2016-10-26 02:06:14 -0700251}
252
253/**
254 * wlan_hdd_cfg80211_configure_tdls_mode() - configure tdls mode
255 * @wiphy: pointer to wireless wiphy structure.
256 * @wdev: pointer to wireless_dev structure.
257 * @data: Pointer to the data to be passed via vendor interface
258 * @data_len:Length of the data to be passed
259 *
260 * Return: Return the Success or Failure code.
261 */
262int wlan_hdd_cfg80211_configure_tdls_mode(struct wiphy *wiphy,
263 struct wireless_dev *wdev,
264 const void *data,
265 int data_len)
266{
267 int ret;
268
269 cds_ssr_protect(__func__);
270 ret = __wlan_hdd_cfg80211_configure_tdls_mode(wiphy, wdev, data,
271 data_len);
272 cds_ssr_unprotect(__func__);
273
274 return ret;
275}
276
277/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800278 * wlan_hdd_cfg80211_exttdls_get_status() - get ext tdls status
279 * @wiphy: pointer to wireless wiphy structure.
280 * @wdev: pointer to wireless_dev structure.
281 * @data: Pointer to the data to be passed via vendor interface
282 * @data_len:Length of the data to be passed
283 *
284 * Return: Return the Success or Failure code.
285 */
286int wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy,
287 struct wireless_dev *wdev,
288 const void *data,
289 int data_len)
290{
291 int ret = 0;
292
293 cds_ssr_protect(__func__);
294 ret = __wlan_hdd_cfg80211_exttdls_get_status(wiphy, wdev, data,
295 data_len);
296 cds_ssr_unprotect(__func__);
297
298 return ret;
299}
300
301/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800302 * __wlan_hdd_cfg80211_exttdls_enable() - enable an externally controllable
303 * TDLS peer and set parameters
304 * wiphy: wiphy
305 * @wdev: wireless dev pointer
306 * @data: netlink buffer with peer MAC address and configuration parameters
307 * @data_len: size of data in bytes
308 *
309 * This function sets channel, operation class, maximum latency and minimal
310 * bandwidth parameters on a TDLS peer that's externally controllable.
311 *
312 * Return: 0 for success; negative errno otherwise
313 */
314static int
315__wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy,
316 struct wireless_dev *wdev,
317 const void *data,
318 int data_len)
319{
Frank Liu5c63dc82017-09-07 14:49:05 +0800320 /* TODO */
321 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800322}
323
324/**
325 * wlan_hdd_cfg80211_exttdls_enable() - enable ext tdls
326 * @wiphy: pointer to wireless wiphy structure.
327 * @wdev: pointer to wireless_dev structure.
328 * @data: Pointer to the data to be passed via vendor interface
329 * @data_len:Length of the data to be passed
330 *
331 * Return: Return the Success or Failure code.
332 */
333int wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy,
334 struct wireless_dev *wdev,
335 const void *data,
336 int data_len)
337{
338 int ret = 0;
339
340 cds_ssr_protect(__func__);
341 ret = __wlan_hdd_cfg80211_exttdls_enable(wiphy, wdev, data, data_len);
342 cds_ssr_unprotect(__func__);
343
344 return ret;
345}
346
347/**
348 * __wlan_hdd_cfg80211_exttdls_disable() - disable an externally controllable
349 * TDLS peer
350 * wiphy: wiphy
351 * @wdev: wireless dev pointer
352 * @data: netlink buffer with peer MAC address
353 * @data_len: size of data in bytes
354 *
355 * This function disables an externally controllable TDLS peer
356 *
357 * Return: 0 for success; negative errno otherwise
358 */
359static int __wlan_hdd_cfg80211_exttdls_disable(struct wiphy *wiphy,
360 struct wireless_dev *wdev,
361 const void *data,
362 int data_len)
363{
Frank Liu5c63dc82017-09-07 14:49:05 +0800364 /* TODO */
365 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800366}
367
368/**
369 * wlan_hdd_cfg80211_exttdls_disable() - disable ext tdls
370 * @wiphy: pointer to wireless wiphy structure.
371 * @wdev: pointer to wireless_dev structure.
372 * @data: Pointer to the data to be passed via vendor interface
373 * @data_len:Length of the data to be passed
374 *
375 * Return: Return the Success or Failure code.
376 */
377int wlan_hdd_cfg80211_exttdls_disable(struct wiphy *wiphy,
378 struct wireless_dev *wdev,
379 const void *data,
380 int data_len)
381{
382 int ret = 0;
383
384 cds_ssr_protect(__func__);
385 ret = __wlan_hdd_cfg80211_exttdls_disable(wiphy, wdev, data, data_len);
386 cds_ssr_unprotect(__func__);
387
388 return ret;
389}
390
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391#if TDLS_MGMT_VERSION2
392/**
393 * __wlan_hdd_cfg80211_tdls_mgmt() - handle management actions on a given peer
394 * @wiphy: wiphy
395 * @dev: net device
396 * @peer: MAC address of the TDLS peer
397 * @action_code: action code
398 * @dialog_token: dialog token
399 * @status_code: status code
400 * @peer_capability: peer capability
401 * @buf: additional IE to include
402 * @len: length of buf in bytes
403 *
404 * Return: 0 if success; negative errno otherwise
405 */
406static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
407 struct net_device *dev, u8 *peer,
408 u8 action_code, u8 dialog_token,
409 u16 status_code, u32 peer_capability,
410 const u8 *buf, size_t len)
411#else
412/**
413 * __wlan_hdd_cfg80211_tdls_mgmt() - handle management actions on a given peer
414 * @wiphy: wiphy
415 * @dev: net device
416 * @peer: MAC address of the TDLS peer
417 * @action_code: action code
418 * @dialog_token: dialog token
419 * @status_code: status code
420 * @buf: additional IE to include
421 * @len: length of buf in bytes
422 *
423 * Return: 0 if success; negative errno otherwise
424 */
425#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
426static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
427 struct net_device *dev, const uint8_t *peer,
428 uint8_t action_code, uint8_t dialog_token,
429 uint16_t status_code, uint32_t peer_capability,
430 bool initiator, const uint8_t *buf,
431 size_t len)
432#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
433static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
434 struct net_device *dev, const uint8_t *peer,
435 uint8_t action_code, uint8_t dialog_token,
436 uint16_t status_code, uint32_t peer_capability,
437 const uint8_t *buf, size_t len)
438#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
439static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
440 struct net_device *dev, uint8_t *peer,
441 uint8_t action_code, uint8_t dialog_token,
442 uint16_t status_code, uint32_t peer_capability,
443 const uint8_t *buf, size_t len)
444#else
445static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
446 struct net_device *dev, uint8_t *peer,
447 uint8_t action_code, uint8_t dialog_token,
448 uint16_t status_code, const uint8_t *buf,
449 size_t len)
450#endif
451#endif
452{
Jeff Johnson6bff8942017-10-02 13:22:18 -0700453 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson6fab9b72017-09-03 08:56:01 -0700454 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800455#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0))
456#if !(TDLS_MGMT_VERSION2)
457 u32 peer_capability;
Srinivas Girigowda6331eaf2017-03-25 17:21:35 -0700458
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800459 peer_capability = 0;
460#endif
461#endif
462
Anurag Chouhan6d760662016-02-20 16:05:43 +0530463 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kabilan Kannan38ff9f32016-08-25 14:51:14 -0700464 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800465 return -EINVAL;
466 }
467
Jeff Johnson1b780e42017-10-31 14:11:45 -0700468 if (wlan_hdd_validate_session_id(adapter->session_id)) {
469 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +0530470 return -EINVAL;
471 }
472
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530473 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800474 TRACE_CODE_HDD_CFG80211_TDLS_MGMT,
Jeff Johnson1b780e42017-10-31 14:11:45 -0700475 adapter->session_id, action_code));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800476
Jeff Johnson6fab9b72017-09-03 08:56:01 -0700477 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800478 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800479
Kabilan Kannan15772302018-01-09 21:01:01 -0800480 if (false == hdd_ctx->config->fEnableTDLSSupport) {
481 hdd_debug("TDLS Disabled in INI OR not enabled in FW. "
482 "Cannot process TDLS commands");
483 return -ENOTSUPP;
484 }
485
Jeff Johnson6fab9b72017-09-03 08:56:01 -0700486 if (hdd_ctx->tdls_umac_comp_active)
487 return wlan_cfg80211_tdls_mgmt(hdd_ctx->hdd_pdev, dev,
Kabilan Kannan1c1c4022017-04-06 22:49:26 -0700488 peer,
489 action_code, dialog_token,
490 status_code, peer_capability,
491 buf, len);
Kabilan Kannanf56f9d52017-04-05 03:31:34 -0700492
Frank Liud1a28462017-09-06 22:55:48 +0800493 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800494}
495
496/**
497 * wlan_hdd_cfg80211_tdls_mgmt() - cfg80211 tdls mgmt handler function
498 * @wiphy: Pointer to wiphy structure.
499 * @dev: Pointer to net_device structure.
500 * @peer: peer address
501 * @action_code: action code
502 * @dialog_token: dialog token
503 * @status_code: status code
504 * @peer_capability: peer capability
505 * @buf: buffer
506 * @len: Length of @buf
507 *
508 * This is the cfg80211 tdls mgmt handler function which invokes
509 * the internal function @__wlan_hdd_cfg80211_tdls_mgmt with
510 * SSR protection.
511 *
512 * Return: 0 for success, error number on failure.
513 */
514#if TDLS_MGMT_VERSION2
515int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
516 struct net_device *dev,
517 u8 *peer, u8 action_code,
518 u8 dialog_token,
519 u16 status_code, u32 peer_capability,
520 const u8 *buf, size_t len)
521#else /* TDLS_MGMT_VERSION2 */
522#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
523int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
524 struct net_device *dev,
525 const u8 *peer, u8 action_code,
526 u8 dialog_token, u16 status_code,
527 u32 peer_capability, bool initiator,
528 const u8 *buf, size_t len)
529#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
530int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
531 struct net_device *dev,
532 const u8 *peer, u8 action_code,
533 u8 dialog_token, u16 status_code,
534 u32 peer_capability, const u8 *buf,
535 size_t len)
536#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
537int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
538 struct net_device *dev,
539 u8 *peer, u8 action_code,
540 u8 dialog_token,
541 u16 status_code, u32 peer_capability,
542 const u8 *buf, size_t len)
543#else
544int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
545 struct net_device *dev,
546 u8 *peer, u8 action_code,
547 u8 dialog_token,
548 u16 status_code, const u8 *buf,
549 size_t len)
550#endif
551#endif
552{
553 int ret;
554
555 cds_ssr_protect(__func__);
556#if TDLS_MGMT_VERSION2
557 ret = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code,
558 dialog_token, status_code,
559 peer_capability, buf, len);
560#else /* TDLS_MGMT_VERSION2 */
561#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
562 ret = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code,
563 dialog_token, status_code,
564 peer_capability, initiator,
565 buf, len);
566#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
567 ret = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code,
568 dialog_token, status_code,
569 peer_capability, buf, len);
570#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
571 ret = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code,
572 dialog_token, status_code,
573 peer_capability, buf, len);
574#else
575 ret = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code,
576 dialog_token, status_code, buf, len);
577#endif
578#endif
579
580 cds_ssr_unprotect(__func__);
581
582 return ret;
583}
584
585/**
586 * wlan_hdd_tdls_extctrl_config_peer() - configure an externally controllable
587 * TDLS peer
Jeff Johnson6bff8942017-10-02 13:22:18 -0700588 * @adapter: HDD adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800589 * @peer: MAC address of the TDLS peer
590 * @callback: Callback to set on the peer
591 * @chan: Channel
592 * @max_latency: Maximum latency
593 * @op_class: Operation class
594 * @min_bandwidth: Minimal bandwidth
595 *
596 * Return: 0 on success; negative otherwise
597 */
Jeff Johnson6bff8942017-10-02 13:22:18 -0700598int wlan_hdd_tdls_extctrl_config_peer(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800599 const uint8_t *peer,
600 cfg80211_exttdls_callback callback,
601 u32 chan,
602 u32 max_latency,
603 u32 op_class, u32 min_bandwidth)
604{
Frank Liu5c63dc82017-09-07 14:49:05 +0800605 /* TODO */
606 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800607}
608
609/**
610 * wlan_hdd_tdls_extctrl_deconfig_peer() - de-configure an externally
611 * controllable TDLS peer
Jeff Johnson6bff8942017-10-02 13:22:18 -0700612 * @adapter: HDD adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800613 * @peer: MAC address of the tdls peer
614 *
615 * Return: 0 if success; negative errno otherwisw
616 */
Jeff Johnson6bff8942017-10-02 13:22:18 -0700617int wlan_hdd_tdls_extctrl_deconfig_peer(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800618 const uint8_t *peer)
619{
Frank Liu5c63dc82017-09-07 14:49:05 +0800620 /* TODO */
621 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800622}
623
Frank Liud4b2fa02017-03-29 11:46:48 +0800624/**
625 * __wlan_hdd_cfg80211_tdls_oper() - helper function to handle cfg80211 operation
626 * on an TDLS peer
627 * @wiphy: wiphy
628 * @dev: net device
629 * @peer: MAC address of the TDLS peer
630 * @oper: cfg80211 TDLS operation
631 *
632 * Return: 0 on success; negative errno otherwise
633 */
634static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy,
635 struct net_device *dev,
636 const uint8_t *peer,
637 enum nl80211_tdls_operation oper)
638{
Jeff Johnson6bff8942017-10-02 13:22:18 -0700639 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson6fab9b72017-09-03 08:56:01 -0700640 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Frank Liud4b2fa02017-03-29 11:46:48 +0800641 int status;
642
643 ENTER();
644
645 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
646 hdd_err("Command not allowed in FTM mode");
647 return -EINVAL;
648 }
649
Jeff Johnson1b780e42017-10-31 14:11:45 -0700650 if (wlan_hdd_validate_session_id(adapter->session_id)) {
651 hdd_err("invalid session id: %d", adapter->session_id);
Frank Liud4b2fa02017-03-29 11:46:48 +0800652 return -EINVAL;
653 }
654
Kabilan Kannan15772302018-01-09 21:01:01 -0800655 if (false == hdd_ctx->config->fEnableTDLSSupport) {
656 hdd_debug("TDLS Disabled in INI OR not enabled in FW. "
657 "Cannot process TDLS commands");
658 return -ENOTSUPP;
659 }
660
Frank Liud4b2fa02017-03-29 11:46:48 +0800661 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
662 TRACE_CODE_HDD_CFG80211_TDLS_OPER,
Jeff Johnson1b780e42017-10-31 14:11:45 -0700663 adapter->session_id, oper));
Frank Liud4b2fa02017-03-29 11:46:48 +0800664 if (NULL == peer) {
665 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
666 "%s: Invalid arguments", __func__);
667 return -EINVAL;
668 }
669
Jeff Johnson6fab9b72017-09-03 08:56:01 -0700670 status = wlan_hdd_validate_context(hdd_ctx);
Frank Liud4b2fa02017-03-29 11:46:48 +0800671
672 if (0 != status)
673 return status;
674
Frank Liud1a28462017-09-06 22:55:48 +0800675 if (hdd_ctx->tdls_umac_comp_active) {
676 status = wlan_cfg80211_tdls_oper(hdd_ctx->hdd_pdev,
677 dev, peer, oper);
678 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800679 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800680 }
Frank Liud4b2fa02017-03-29 11:46:48 +0800681
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530682 EXIT();
Frank Liud1a28462017-09-06 22:55:48 +0800683 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800684}
685
686/**
687 * wlan_hdd_cfg80211_tdls_oper() - handle cfg80211 operation on an TDLS peer
688 * @wiphy: wiphy
689 * @dev: net device
690 * @peer: MAC address of the TDLS peer
691 * @oper: cfg80211 TDLS operation
692 *
693 * Return: 0 on success; negative errno otherwise
694 */
695#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
696int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy,
697 struct net_device *dev,
698 const uint8_t *peer,
699 enum nl80211_tdls_operation oper)
700#else
701int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy,
702 struct net_device *dev,
703 uint8_t *peer,
704 enum nl80211_tdls_operation oper)
705#endif
706{
707 int ret;
708
709 cds_ssr_protect(__func__);
710 ret = __wlan_hdd_cfg80211_tdls_oper(wiphy, dev, peer, oper);
711 cds_ssr_unprotect(__func__);
712
713 return ret;
714}
715
716/**
717 * wlan_hdd_cfg80211_send_tdls_discover_req() - send out TDLS discovery for
718 * a TDLS peer
719 * @wiphy: wiphy
720 * @dev: net device
721 * @peer: MAC address of the peer
722 *
723 * Return: 0 if success; negative errno otherwise
724 */
725int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
726 struct net_device *dev, u8 *peer)
727{
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700728 hdd_debug("tdls send discover req: " MAC_ADDRESS_STR,
Kabilan Kannan38ff9f32016-08-25 14:51:14 -0700729 MAC_ADDR_ARRAY(peer));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800730#if TDLS_MGMT_VERSION2
731 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
732 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, 0,
733 NULL, 0);
734#else
735#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
736 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
737 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0,
738 0, 0, NULL, 0);
739#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
740 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
741 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0,
742 0, NULL, 0);
743#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
744 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
745 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0,
746 0, NULL, 0);
747#else
748 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
749 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0,
750 NULL, 0);
751#endif
752#endif
753}
754
755#endif /* End of FEATURE_WLAN_TDLS */
756
757/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800758 * hdd_set_tdls_offchannel() - set tdls off-channel number
759 * @adapter: Pointer to the HDD adapter
760 * @offchanmode: tdls off-channel number
761 *
762 * This function sets tdls off-channel number
763 *
764 * Return: 0 on success; negative errno otherwise
765 */
Jeff Johnsonaf772ed2017-08-28 11:40:36 -0700766int hdd_set_tdls_offchannel(struct hdd_context *hdd_ctx, int offchannel)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767{
Frank Liu5c63dc82017-09-07 14:49:05 +0800768 /* TODO */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800769 return 0;
770}
771
772/**
773 * hdd_set_tdls_secoffchanneloffset() - set secondary tdls off-channel offset
774 * @adapter: Pointer to the HDD adapter
775 * @offchanmode: tdls off-channel offset
776 *
777 * This function sets 2nd tdls off-channel offset
778 *
779 * Return: 0 on success; negative errno otherwise
780 */
Jeff Johnsonae9adc82017-10-03 11:22:31 -0700781int hdd_set_tdls_secoffchanneloffset(struct hdd_context *hdd_ctx,
782 int offchanoffset)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800783{
Frank Liu5c63dc82017-09-07 14:49:05 +0800784 /* TODO */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785 return 0;
786}
787
788/**
789 * hdd_set_tdls_offchannelmode() - set tdls off-channel mode
790 * @adapter: Pointer to the HDD adapter
791 * @offchanmode: tdls off-channel mode
792 *
793 * This function sets tdls off-channel mode
794 *
795 * Return: 0 on success; negative errno otherwise
796 */
Jeff Johnson327b9d42017-08-29 14:20:07 -0700797int hdd_set_tdls_offchannelmode(struct hdd_adapter *adapter, int offchanmode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800798{
Frank Liu5c63dc82017-09-07 14:49:05 +0800799 /* TODO */
800 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800801}
802
803/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804 * hdd_set_tdls_scan_type - set scan during active tdls session
805 * @hdd_ctx: ptr to hdd context.
806 * @val: scan type value: 0 or 1.
807 *
808 * Set scan type during tdls session. If set to 1, that means driver
809 * shall maintain tdls link and allow scan regardless if tdls peer is
810 * buffer sta capable or not and/or if device is sleep sta capable or
811 * not. If tdls peer is not buffer sta capable then during scan there
812 * will be loss of Rx packets and Tx would stop when device moves away
813 * from tdls channel. If set to 0, then driver shall teardown tdls link
814 * before initiating scan if peer is not buffer sta capable and device
815 * is not sleep sta capable. By default, scan type is set to 0.
816 *
817 * Return: success (0) or failure (errno value)
818 */
Jeff Johnsonaf772ed2017-08-28 11:40:36 -0700819int hdd_set_tdls_scan_type(struct hdd_context *hdd_ctx, int val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800820{
821 if ((val != 0) && (val != 1)) {
Kabilan Kannan38ff9f32016-08-25 14:51:14 -0700822 hdd_err("Incorrect value of tdls scan type: %d", val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800823 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800824 }
Jeff Johnson68755312017-02-10 11:46:55 -0800825
826 hdd_ctx->config->enable_tdls_scan = val;
Jeff Johnson68755312017-02-10 11:46:55 -0800827 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800828}
Archana Ramachandrand5d2e922016-04-20 16:57:35 -0700829
830/**
Archana Ramachandrand5d2e922016-04-20 16:57:35 -0700831 * wlan_hdd_tdls_antenna_switch() - Dynamic TDLS antenna switch 1x1 <-> 2x2
832 * antenna mode in standalone station
833 * @hdd_ctx: Pointer to hdd contex
834 * @adapter: Pointer to hdd adapter
835 *
836 * Return: 0 if success else non zero
837 */
Jeff Johnsonaf772ed2017-08-28 11:40:36 -0700838int wlan_hdd_tdls_antenna_switch(struct hdd_context *hdd_ctx,
Jeff Johnson327b9d42017-08-29 14:20:07 -0700839 struct hdd_adapter *adapter,
840 uint32_t mode)
Archana Ramachandrand5d2e922016-04-20 16:57:35 -0700841{
Frank Liuc0c25fd2017-07-24 19:14:57 +0800842 if (hdd_ctx->tdls_umac_comp_active)
843 return wlan_tdls_antenna_switch(adapter->hdd_vdev, mode);
844
Archana Ramachandrand5d2e922016-04-20 16:57:35 -0700845 return 0;
846}
Nitesh Shah61c10d92016-10-19 19:29:15 +0530847
Frank Liud4b2fa02017-03-29 11:46:48 +0800848QDF_STATUS hdd_tdls_register_tdls_peer(void *userdata, uint32_t vdev_id,
849 const uint8_t *mac, uint16_t sta_id,
850 uint8_t ucastsig, uint8_t qos)
851{
Jeff Johnson327b9d42017-08-29 14:20:07 -0700852 struct hdd_adapter *adapter;
Jeff Johnsonaf772ed2017-08-28 11:40:36 -0700853 struct hdd_context *hddctx;
Frank Liud4b2fa02017-03-29 11:46:48 +0800854
855 hddctx = userdata;
856 if (!hddctx) {
857 hdd_err("Invalid hddctx");
858 return QDF_STATUS_E_INVAL;
859 }
860 adapter = hdd_get_adapter_by_vdev(hddctx, vdev_id);
861 if (!adapter) {
862 hdd_err("Invalid adapter");
863 return QDF_STATUS_E_FAILURE;
864 }
865
866 return hdd_roam_register_tdlssta(adapter, mac, sta_id, ucastsig, qos);
867}
868
869QDF_STATUS hdd_tdls_deregister_tdl_peer(void *userdata,
870 uint32_t vdev_id, uint8_t sta_id)
871{
Jeff Johnson327b9d42017-08-29 14:20:07 -0700872 struct hdd_adapter *adapter;
Jeff Johnsonaf772ed2017-08-28 11:40:36 -0700873 struct hdd_context *hddctx;
Frank Liud4b2fa02017-03-29 11:46:48 +0800874
875 hddctx = userdata;
876 if (!hddctx) {
877 hdd_err("Invalid hddctx");
878 return QDF_STATUS_E_INVAL;
879 }
880 adapter = hdd_get_adapter_by_vdev(hddctx, vdev_id);
881 if (!adapter) {
882 hdd_err("Invalid adapter");
883 return QDF_STATUS_E_FAILURE;
884 }
885
886 return hdd_roam_deregister_tdlssta(adapter, sta_id);
887}