blob: 6670bf5317cfd27abc35e6515aa6e1f0bcfa281d [file] [log] [blame]
Ravi Joshia063dd92016-05-25 16:43:13 -07001/*
Dustin Brown4ea21db2018-01-05 14:13:17 -08002 * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
Ravi Joshia063dd92016-05-25 16:43:13 -07003 *
Ravi Joshia063dd92016-05-25 16:43:13 -07004 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/**
20 * DOC: wlan_hdd_nan_datapath.c
21 *
22 * WLAN Host Device Driver nan datapath API implementation
23 */
Deepak Dhamdhere13983f22016-05-31 19:06:09 -070024#include <wlan_hdd_includes.h>
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070025#include <linux/if.h>
26#include <linux/netdevice.h>
27#include <linux/skbuff.h>
28#include <linux/etherdevice.h>
29#include "wlan_hdd_includes.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070030#include "wlan_hdd_p2p.h"
31#include "wma_api.h"
Deepak Dhamdhere0f076bd2016-06-02 11:29:21 -070032#include "wlan_hdd_assoc.h"
33#include "sme_nan_datapath.h"
Rajeev Kumar699debf2017-01-06 14:17:00 -080034#include "wlan_hdd_object_manager.h"
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080035#include <qca_vendor.h>
Naveen Rawat63de5422017-03-22 11:03:56 -070036#include "os_if_nan.h"
Naveen Rawatcb5c5402017-03-22 10:12:19 -070037#include "wlan_nan_api.h"
38#include "nan_public_structs.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070039
Deepak Dhamdhere3385d752016-05-25 20:36:47 -070040/**
41 * hdd_ndp_print_ini_config()- Print nan datapath specific INI configuration
42 * @hdd_ctx: handle to hdd context
43 *
44 * Return: None
45 */
Jeff Johnson88dc4f92017-08-28 11:51:34 -070046void hdd_ndp_print_ini_config(struct hdd_context *hdd_ctx)
Deepak Dhamdhere3385d752016-05-25 20:36:47 -070047{
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -070048 hdd_debug("Name = [%s] Value = [%u]", CFG_ENABLE_NAN_DATAPATH_NAME,
Deepak Dhamdhere3385d752016-05-25 20:36:47 -070049 hdd_ctx->config->enable_nan_datapath);
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -070050 hdd_debug("Name = [%s] Value = [%u]", CFG_ENABLE_NAN_NDI_CHANNEL_NAME,
Deepak Dhamdhere3385d752016-05-25 20:36:47 -070051 hdd_ctx->config->nan_datapath_ndi_channel);
52}
Deepak Dhamdhere13230d32016-05-26 00:46:53 -070053
54/**
55 * hdd_nan_datapath_target_config() - Configure NAN datapath features
56 * @hdd_ctx: Pointer to HDD context
57 * @cfg: Pointer to target device capability information
58 *
Deepak Dhamdhere13983f22016-05-31 19:06:09 -070059 * NAN datapath functionality is enabled if it is enabled in
60 * .ini file and also supported on target device.
Deepak Dhamdhere13230d32016-05-26 00:46:53 -070061 *
62 * Return: None
63 */
Jeff Johnson88dc4f92017-08-28 11:51:34 -070064void hdd_nan_datapath_target_config(struct hdd_context *hdd_ctx,
Deepak Dhamdhere13230d32016-05-26 00:46:53 -070065 struct wma_tgt_cfg *cfg)
66{
Deepak Dhamdhere7e6016f2016-06-01 09:37:37 -070067 hdd_ctx->nan_datapath_enabled =
68 hdd_ctx->config->enable_nan_datapath &&
69 cfg->nan_datapath_enabled;
Naveen Rawatcb5c5402017-03-22 10:12:19 -070070 hdd_info("enable_nan_datapath: final: %d, host: %d, fw: %d",
71 hdd_ctx->nan_datapath_enabled,
72 hdd_ctx->config->enable_nan_datapath,
73 cfg->nan_datapath_enabled);
Deepak Dhamdhere13230d32016-05-26 00:46:53 -070074}
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070075
76/**
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -070077 * hdd_close_ndi() - close NAN Data interface
78 * @adapter: adapter context
79 *
80 * Close the adapter if start BSS fails
81 *
82 * Returns: 0 on success, negative error code otherwise
83 */
Jeff Johnson8cb9df12017-08-29 14:28:45 -070084static int hdd_close_ndi(struct hdd_adapter *adapter)
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -070085{
Dustin Brown0d2eeae2017-03-24 15:21:32 -070086 int errno;
Jeff Johnson88dc4f92017-08-28 11:51:34 -070087 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -070088
Dustin Brown491d54b2018-03-14 12:39:11 -070089 hdd_enter();
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -070090
91 /* check if the adapter is in NAN Data mode */
92 if (QDF_NDI_MODE != adapter->device_mode) {
Naveen Rawatba4f6612016-07-05 12:03:16 -070093 hdd_err("Interface is not in NDI mode");
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -070094 return -EINVAL;
95 }
Deepak Dhamdhere5872c8c2016-06-02 15:51:47 -070096 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053097 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
Deepak Dhamdhere5872c8c2016-06-02 15:51:47 -070098 WLAN_CONTROL_PATH);
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -070099
100#ifdef WLAN_OPEN_SOURCE
Jeff Johnsonb527ebe2017-10-28 13:14:03 -0700101 cancel_work_sync(&adapter->ipv4_notifier_work);
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700102#endif
103 hdd_deregister_tx_flow_control(adapter);
104
105#ifdef WLAN_NS_OFFLOAD
106#ifdef WLAN_OPEN_SOURCE
Jeff Johnsonb527ebe2017-10-28 13:14:03 -0700107 cancel_work_sync(&adapter->ipv6_notifier_work);
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700108#endif
109#endif
Dustin Brown0d2eeae2017-03-24 15:21:32 -0700110 errno = hdd_vdev_destroy(adapter);
111 if (errno)
112 hdd_err("failed to destroy vdev: %d", errno);
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700113
114 /* We are good to close the adapter */
115 hdd_close_adapter(hdd_ctx, adapter, true);
116
Dustin Browne74003f2018-03-14 12:51:58 -0700117 hdd_exit();
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700118 return 0;
119}
120
121/**
Deepak Dhamdhere0f076bd2016-06-02 11:29:21 -0700122 * hdd_is_ndp_allowed() - Indicates if NDP is allowed
123 * @hdd_ctx: hdd context
124 *
125 * NDP is not allowed with any other role active except STA.
126 *
127 * Return: true if allowed, false otherwise
128 */
Jeff Johnson88dc4f92017-08-28 11:51:34 -0700129static bool hdd_is_ndp_allowed(struct hdd_context *hdd_ctx)
Deepak Dhamdhere0f076bd2016-06-02 11:29:21 -0700130{
Jeff Johnson8cb9df12017-08-29 14:28:45 -0700131 struct hdd_adapter *adapter;
Jeff Johnson40dae4e2017-08-29 14:00:25 -0700132 struct hdd_station_ctx *sta_ctx;
Deepak Dhamdhere0f076bd2016-06-02 11:29:21 -0700133
Dustin Brown920397d2017-12-13 16:27:50 -0800134 hdd_for_each_adapter(hdd_ctx, adapter) {
Deepak Dhamdhere0f076bd2016-06-02 11:29:21 -0700135 switch (adapter->device_mode) {
136 case QDF_P2P_GO_MODE:
137 case QDF_SAP_MODE:
138 if (test_bit(SOFTAP_BSS_STARTED,
139 &adapter->event_flags))
140 return false;
141 break;
142 case QDF_P2P_CLIENT_MODE:
143 case QDF_IBSS_MODE:
144 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
145 if (hdd_conn_is_connected(sta_ctx) ||
146 hdd_is_connecting(sta_ctx))
147 return false;
148 break;
149 default:
150 break;
151 }
Deepak Dhamdhere0f076bd2016-06-02 11:29:21 -0700152 }
153
154 return true;
155}
156
157/**
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700158 * hdd_ndi_start_bss() - Start BSS on NAN data interface
159 * @adapter: adapter context
160 * @operating_channel: channel on which the BSS to be started
161 *
162 * Return: 0 on success, error value on failure
163 */
Jeff Johnson8cb9df12017-08-29 14:28:45 -0700164static int hdd_ndi_start_bss(struct hdd_adapter *adapter,
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700165 uint8_t operating_channel)
166{
Jeff Johnson32833f12018-06-13 20:26:34 -0700167 QDF_STATUS status;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700168 uint32_t roam_id;
Jeff Johnson641839e2018-03-18 14:50:39 -0700169 struct csr_roam_profile *roam_profile;
Jeff Johnson32833f12018-06-13 20:26:34 -0700170 mac_handle_t mac_handle;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700171
Dustin Brown491d54b2018-03-14 12:39:11 -0700172 hdd_enter();
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700173
Jeff Johnson641839e2018-03-18 14:50:39 -0700174 roam_profile = hdd_roam_profile(adapter);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700175
176 if (HDD_WMM_USER_MODE_NO_QOS ==
177 (WLAN_HDD_GET_CTX(adapter))->config->WmmMode) {
178 /* QoS not enabled in cfg file*/
179 roam_profile->uapsd_mask = 0;
180 } else {
181 /* QoS enabled, update uapsd mask from cfg file*/
182 roam_profile->uapsd_mask =
183 (WLAN_HDD_GET_CTX(adapter))->config->UapsdMask;
184 }
185
186 roam_profile->csrPersona = adapter->device_mode;
187
Naveen Rawat709c0cb2018-03-14 17:04:15 -0700188 if (!operating_channel)
189 operating_channel = NAN_SOCIAL_CHANNEL_2_4GHZ;
190
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700191 roam_profile->ChannelInfo.numOfChannels = 1;
Naveen Rawat709c0cb2018-03-14 17:04:15 -0700192 roam_profile->ChannelInfo.ChannelList = &operating_channel;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700193
194 roam_profile->SSIDs.numOfSSIDs = 1;
195 roam_profile->SSIDs.SSIDList->SSID.length = 0;
196
197 roam_profile->phyMode = eCSR_DOT11_MODE_11ac;
198 roam_profile->BSSType = eCSR_BSS_TYPE_NDI;
199 roam_profile->BSSIDs.numOfBSSIDs = 1;
200 qdf_mem_copy((void *)(roam_profile->BSSIDs.bssid),
Jeff Johnson1e851a12017-10-28 14:36:12 -0700201 &adapter->mac_addr.bytes[0],
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700202 QDF_MAC_ADDR_SIZE);
203
204 roam_profile->AuthType.numEntries = 1;
205 roam_profile->AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM;
206 roam_profile->EncryptionType.numEntries = 1;
207 roam_profile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
208
Jeff Johnson32833f12018-06-13 20:26:34 -0700209 mac_handle = hdd_adapter_get_mac_handle(adapter);
210 status = sme_roam_connect(mac_handle, adapter->session_id,
211 roam_profile, &roam_id);
212 if (QDF_IS_STATUS_ERROR(status)) {
Naveen Rawatba4f6612016-07-05 12:03:16 -0700213 hdd_err("NDI sme_RoamConnect session %d failed with status %d -> NotConnected",
Jeff Johnson32833f12018-06-13 20:26:34 -0700214 adapter->session_id, status);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700215 /* change back to NotConnected */
216 hdd_conn_set_connection_state(adapter,
Jeff Johnson32833f12018-06-13 20:26:34 -0700217 eConnectionState_NotConnected);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700218 } else {
Naveen Rawatba4f6612016-07-05 12:03:16 -0700219 hdd_info("sme_RoamConnect issued successfully for NDI");
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700220 }
221
222 roam_profile->ChannelInfo.ChannelList = NULL;
223 roam_profile->ChannelInfo.numOfChannels = 0;
224
Dustin Browne74003f2018-03-14 12:51:58 -0700225 hdd_exit();
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700226
Jeff Johnson32833f12018-06-13 20:26:34 -0700227 return 0;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700228}
229
Naveen Rawat5a6f8402017-07-03 16:00:11 -0700230/**
231 * hdd_get_random_nan_mac_addr() - generate random non pre-existent mac address
232 * @hdd_ctx: hdd context pointer
233 * @mac_addr: mac address buffer to populate
234 *
235 * Return: status of operation
236 */
Jeff Johnson88dc4f92017-08-28 11:51:34 -0700237static int hdd_get_random_nan_mac_addr(struct hdd_context *hdd_ctx,
Naveen Rawat5a6f8402017-07-03 16:00:11 -0700238 struct qdf_mac_addr *mac_addr)
239{
Jeff Johnson8cb9df12017-08-29 14:28:45 -0700240 struct hdd_adapter *adapter;
Naveen Rawatea1ece82018-02-09 14:22:52 -0800241 uint8_t pos, bit_pos, byte_pos, mask;
Naveen Rawat5a6f8402017-07-03 16:00:11 -0700242 uint8_t i, attempts, max_attempt = 16;
Naveen Rawat5a6f8402017-07-03 16:00:11 -0700243
244 for (attempts = 0; attempts < max_attempt; attempts++) {
Naveen Rawatea1ece82018-02-09 14:22:52 -0800245 /* if NDI is present next addr is required to be 1 bit apart */
246 adapter = hdd_get_adapter(hdd_ctx, QDF_NDI_MODE);
247 if (adapter) {
248 hdd_debug("NDI already exists, deriving next mac");
249 qdf_mem_copy(mac_addr, &adapter->mac_addr,
250 sizeof(*mac_addr));
251 cds_rand_get_bytes(0, &pos, sizeof(pos));
252 /* skipping byte 0, 5 leaves 8*4=32 positions */
253 pos = pos % 32;
254 bit_pos = pos % 8;
255 byte_pos = pos / 8;
256 mask = 1 << bit_pos;
257 /* flip the required bit */
258 mac_addr->bytes[byte_pos + 1] ^= mask;
259 } else {
260 cds_rand_get_bytes(0, (uint8_t *)mac_addr,
261 sizeof(*mac_addr));
262 /*
263 * Reset multicast bit (bit-0) and set
264 * locally-administered bit
265 */
266 mac_addr->bytes[0] = 0x2;
Ravi Joshi04a1c992017-06-11 19:47:54 -0700267
Naveen Rawatea1ece82018-02-09 14:22:52 -0800268 /*
269 * to avoid potential conflict with FW's generated NMI
270 * mac addr, host sets LSB if 6th byte to 0
271 */
272 mac_addr->bytes[5] &= 0xFE;
273 }
Naveen Rawat5a6f8402017-07-03 16:00:11 -0700274 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
275 if (!qdf_mem_cmp(hdd_ctx->config->intfMacAddr[i].bytes,
276 mac_addr, sizeof(*mac_addr)))
277 continue;
278 }
279
280 adapter = hdd_get_adapter_by_macaddr(hdd_ctx, mac_addr->bytes);
281 if (!adapter)
282 return 0;
283 }
284
285 hdd_err("unable to get non-pre-existing mac address in %d attempts",
286 max_attempt);
287
288 return -EINVAL;
289}
290
Jeff Johnson8cb9df12017-08-29 14:28:45 -0700291void hdd_ndp_event_handler(struct hdd_adapter *adapter,
Jeff Johnson172237b2017-11-07 15:32:59 -0800292 struct csr_roam_info *roam_info,
293 uint32_t roam_id, eRoamCmdStatus roam_status,
294 eCsrRoamResult roam_result)
Naveen Rawat97500352017-03-22 10:07:58 -0700295{
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700296 bool success;
297 struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(adapter->hdd_vdev);
298
299 if (roam_status == eCSR_ROAM_NDP_STATUS_UPDATE) {
300 switch (roam_result) {
301 case eCSR_ROAM_RESULT_NDI_CREATE_RSP:
302 success = (roam_info->ndp.ndi_create_params.status ==
303 NAN_DATAPATH_RSP_STATUS_SUCCESS);
304 hdd_debug("posting ndi create status: %d to umac",
305 success);
Jeff Johnson1b780e42017-10-31 14:11:45 -0700306 os_if_nan_post_ndi_create_rsp(psoc, adapter->session_id,
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700307 success);
308 return;
309 case eCSR_ROAM_RESULT_NDI_DELETE_RSP:
310 success = (roam_info->ndp.ndi_create_params.status ==
311 NAN_DATAPATH_RSP_STATUS_SUCCESS);
312 hdd_debug("posting ndi delete status: %d to umac",
313 success);
Jeff Johnson1b780e42017-10-31 14:11:45 -0700314 os_if_nan_post_ndi_delete_rsp(psoc, adapter->session_id,
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700315 success);
316 return;
317 default:
318 hdd_err("in correct roam_result: %d", roam_result);
319 return;
320 }
321 } else {
322 hdd_err("in correct roam_status: %d", roam_status);
323 return;
324 }
Naveen Rawat97500352017-03-22 10:07:58 -0700325}
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700326
327/**
328 * __wlan_hdd_cfg80211_process_ndp_cmds() - handle NDP request
329 * @wiphy: pointer to wireless wiphy structure.
330 * @wdev: pointer to wireless_dev structure.
331 * @data: Pointer to the data to be passed via vendor interface
332 * @data_len:Length of the data to be passed
333 *
334 * This function is invoked to handle vendor command
335 *
336 * Return: 0 on success, negative errno on failure
337 */
Naveen Rawat63de5422017-03-22 11:03:56 -0700338static int __wlan_hdd_cfg80211_process_ndp_cmd(struct wiphy *wiphy,
339 struct wireless_dev *wdev, const void *data, int data_len)
340{
341 int ret_val;
Jeff Johnson88dc4f92017-08-28 11:51:34 -0700342 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Naveen Rawat63de5422017-03-22 11:03:56 -0700343
Dustin Brown491d54b2018-03-14 12:39:11 -0700344 hdd_enter();
Naveen Rawat63de5422017-03-22 11:03:56 -0700345
346 ret_val = wlan_hdd_validate_context(hdd_ctx);
347 if (ret_val)
348 return ret_val;
349
350 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
351 hdd_err("Command not allowed in FTM mode");
352 return -EPERM;
353 }
354
355 if (!WLAN_HDD_IS_NDP_ENABLED(hdd_ctx)) {
356 hdd_err("NAN datapath is not enabled");
357 return -EPERM;
358 }
359 /* NAN data path coexists only with STA interface */
360 if (false == hdd_is_ndp_allowed(hdd_ctx)) {
361 hdd_err("Unsupported concurrency for NAN datapath");
362 return -EPERM;
363 }
364
365 /* NAN data path coexists only with STA interface */
366 if (false == hdd_is_ndp_allowed(hdd_ctx)) {
367 hdd_err("Unsupported concurrency for NAN datapath");
368 return -EPERM;
369 }
370
371 return os_if_nan_process_ndp_cmd(hdd_ctx->hdd_psoc,
372 data, data_len);
373}
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700374
375/**
376 * wlan_hdd_cfg80211_process_ndp_cmd() - handle NDP request
377 * @wiphy: pointer to wireless wiphy structure.
378 * @wdev: pointer to wireless_dev structure.
379 * @data: Pointer to the data to be passed via vendor interface
380 * @data_len:Length of the data to be passed
381 *
382 * This function is called to send a NAN request to
383 * firmware. This is an SSR-protected wrapper function.
384 *
385 * Return: 0 on success, negative errno on failure
386 */
387int wlan_hdd_cfg80211_process_ndp_cmd(struct wiphy *wiphy,
388 struct wireless_dev *wdev, const void *data, int data_len)
389{
390 int ret;
391
392 cds_ssr_protect(__func__);
393 ret = __wlan_hdd_cfg80211_process_ndp_cmd(wiphy, wdev, data, data_len);
394 cds_ssr_unprotect(__func__);
395
396 return ret;
397}
398
Jeff Johnson85b5c112017-08-11 15:15:23 -0700399static int update_ndi_state(struct hdd_adapter *adapter, uint32_t state)
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700400{
401 return os_if_nan_set_ndi_state(adapter->hdd_vdev, state);
402}
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700403
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700404/**
405 * hdd_init_nan_data_mode() - initialize nan data mode
406 * @adapter: adapter context
407 *
408 * Returns: 0 on success negative error code on error
409 */
Jeff Johnson85b5c112017-08-11 15:15:23 -0700410int hdd_init_nan_data_mode(struct hdd_adapter *adapter)
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700411{
412 struct net_device *wlan_dev = adapter->dev;
Jeff Johnson88dc4f92017-08-28 11:51:34 -0700413 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700414 QDF_STATUS status;
Jeff Johnson32833f12018-06-13 20:26:34 -0700415 int32_t ret_val;
416 mac_handle_t mac_handle;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700417
Krunal Sonib51eec72017-11-20 21:53:01 -0800418 ret_val = hdd_vdev_create(adapter, hdd_sme_roam_callback, adapter);
Dustin Brownd28772b2017-03-17 14:16:07 -0700419 if (ret_val) {
420 hdd_err("failed to create vdev: %d", ret_val);
421 return ret_val;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700422 }
423
Jeff Johnson32833f12018-06-13 20:26:34 -0700424 mac_handle = hdd_ctx->mac_handle;
425
Ravi Joshi8eb65f92017-07-20 16:30:19 -0700426 /* Configure self HT/VHT capabilities */
Jeff Johnson32833f12018-06-13 20:26:34 -0700427 sme_set_curr_device_mode(mac_handle, adapter->device_mode);
428 sme_set_pdev_ht_vht_ies(mac_handle, hdd_ctx->config->enable2x2);
429 sme_set_vdev_ies_per_band(mac_handle, adapter->session_id);
Ravi Joshi8eb65f92017-07-20 16:30:19 -0700430
Jeff Johnson7f2c5912018-03-23 11:42:28 -0700431 hdd_roam_profile_init(adapter);
432 hdd_register_wext(wlan_dev);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700433
434 status = hdd_init_tx_rx(adapter);
435 if (QDF_STATUS_SUCCESS != status) {
Naveen Rawatba4f6612016-07-05 12:03:16 -0700436 hdd_err("hdd_init_tx_rx() init failed, status %d", status);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700437 ret_val = -EAGAIN;
438 goto error_init_txrx;
439 }
440
441 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
442
443 status = hdd_wmm_adapter_init(adapter);
444 if (QDF_STATUS_SUCCESS != status) {
Naveen Rawatba4f6612016-07-05 12:03:16 -0700445 hdd_err("hdd_wmm_adapter_init() failed, status %d", status);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700446 ret_val = -EAGAIN;
447 goto error_wmm_init;
448 }
449
450 set_bit(WMM_INIT_DONE, &adapter->event_flags);
451
Jeff Johnson1b780e42017-10-31 14:11:45 -0700452 ret_val = wma_cli_set_command((int)adapter->session_id,
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700453 (int)WMI_PDEV_PARAM_BURST_ENABLE,
Dundi Raviteja3aa01be2018-05-21 18:58:59 +0530454 (int)HDD_ENABLE_SIFS_BURST_DEFAULT,
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700455 PDEV_CMD);
Arunk Khandavalli15664e42017-06-29 15:56:14 +0530456 if (0 != ret_val)
Naveen Rawatba4f6612016-07-05 12:03:16 -0700457 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d", ret_val);
Arunk Khandavalli15664e42017-06-29 15:56:14 +0530458
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700459
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700460 update_ndi_state(adapter, NAN_DATA_NDI_CREATING_STATE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700461 return ret_val;
462
463error_wmm_init:
464 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
465 hdd_deinit_tx_rx(adapter);
466
467error_init_txrx:
468 hdd_unregister_wext(wlan_dev);
469
Dustin Brownd28772b2017-03-17 14:16:07 -0700470 QDF_BUG(!hdd_vdev_destroy(adapter));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700471
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700472 return ret_val;
473}
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700474
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700475struct wlan_objmgr_vdev *hdd_ndi_open(char *iface_name)
476{
Jeff Johnson8cb9df12017-08-29 14:28:45 -0700477 struct hdd_adapter *adapter;
Ravi Joshi9771d432017-06-26 13:58:12 -0700478 struct qdf_mac_addr random_ndi_mac;
Jeff Johnson88dc4f92017-08-28 11:51:34 -0700479 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Ravi Joshi9771d432017-06-26 13:58:12 -0700480 uint8_t *ndi_mac_addr;
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700481
Dustin Brown491d54b2018-03-14 12:39:11 -0700482 hdd_enter();
Naveen Rawat5a6f8402017-07-03 16:00:11 -0700483
Naveen Rawatf9391622017-12-20 17:06:01 -0800484 if (!hdd_ctx) {
485 hdd_err("hdd_ctx null");
486 return NULL;
487 }
488
Ravi Joshi9771d432017-06-26 13:58:12 -0700489 if (hdd_ctx->config->is_ndi_mac_randomized) {
490 if (hdd_get_random_nan_mac_addr(hdd_ctx, &random_ndi_mac)) {
491 hdd_err("get random mac address failed");
492 return NULL;
493 }
494 ndi_mac_addr = &random_ndi_mac.bytes[0];
495 } else {
496 ndi_mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
497 if (!ndi_mac_addr) {
498 hdd_err("get intf address failed");
499 return NULL;
500 }
Naveen Rawat5a6f8402017-07-03 16:00:11 -0700501 }
502
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700503 adapter = hdd_open_adapter(hdd_ctx, QDF_NDI_MODE, iface_name,
Ravi Joshi9771d432017-06-26 13:58:12 -0700504 ndi_mac_addr, NET_NAME_UNKNOWN, true);
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700505 if (!adapter) {
506 hdd_err("hdd_open_adapter failed");
507 return NULL;
508 }
509
Dustin Browne74003f2018-03-14 12:51:58 -0700510 hdd_exit();
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700511 return adapter->hdd_vdev;
512}
513
514int hdd_ndi_start(uint8_t vdev_id)
515{
Naveen Rawatf9391622017-12-20 17:06:01 -0800516 uint8_t op_channel;
517 struct hdd_adapter *adapter;
Jeff Johnson88dc4f92017-08-28 11:51:34 -0700518 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700519
Dustin Brown491d54b2018-03-14 12:39:11 -0700520 hdd_enter();
Naveen Rawatf9391622017-12-20 17:06:01 -0800521
522 if (!hdd_ctx) {
523 hdd_err("hdd_ctx is null");
524 return -EINVAL;
525 }
526
527 op_channel = hdd_ctx->config->nan_datapath_ndi_channel;
528 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
529 if (!adapter) {
530 hdd_err("adapter is null");
531 return -EINVAL;
532 }
533
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700534 /*
535 * The NAN data interface has been created at this point.
536 * Unlike traditional device modes, where the higher application
537 * layer initiates connect / join / start, the NAN data
538 * interface does not have any such formal requests. The NDI
539 * create request is responsible for starting the BSS as well.
540 */
jitiphil31cf1ba2018-05-11 15:54:38 +0530541 if (op_channel != NAN_SOCIAL_CHANNEL_2_4GHZ &&
542 op_channel != NAN_SOCIAL_CHANNEL_5GHZ_LOWER_BAND &&
543 op_channel != NAN_SOCIAL_CHANNEL_5GHZ_UPPER_BAND) {
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700544 /* start NDI on the default 2.4 GHz social channel */
545 op_channel = NAN_SOCIAL_CHANNEL_2_4GHZ;
546 }
547 if (hdd_ndi_start_bss(adapter, op_channel)) {
548 hdd_err("NDI start bss failed");
549 /* Start BSS failed, delete the interface */
550 hdd_close_ndi(adapter);
Dustin Browne74003f2018-03-14 12:51:58 -0700551 hdd_exit();
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700552 return -EINVAL;
553 }
554
Dustin Browne74003f2018-03-14 12:51:58 -0700555 hdd_exit();
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700556 return 0;
557}
558
559int hdd_ndi_delete(uint8_t vdev_id, char *iface_name, uint16_t transaction_id)
560{
561 int ret;
Jeff Johnson8cb9df12017-08-29 14:28:45 -0700562 struct hdd_adapter *adapter;
Jeff Johnson40dae4e2017-08-29 14:00:25 -0700563 struct hdd_station_ctx *sta_ctx;
Jeff Johnson88dc4f92017-08-28 11:51:34 -0700564 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700565
Naveen Rawatf9391622017-12-20 17:06:01 -0800566 if (!hdd_ctx) {
567 hdd_err("hdd_ctx is null");
568 return -EINVAL;
569 }
570
Naveen Rawatc4b045c2017-06-30 16:11:42 -0700571 /* check if adapter by vdev_id is valid NDI */
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700572 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
573 if (!adapter || !WLAN_HDD_IS_NDI(adapter)) {
574 hdd_err("NAN data interface %s is not available", iface_name);
575 return -EINVAL;
576 }
577
578 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
579 if (!sta_ctx) {
580 hdd_err("sta_ctx is NULL");
581 return -EINVAL;
582 }
583
584 /* Since, the interface is being deleted, remove the broadcast id. */
585 hdd_ctx->sta_to_adapter[sta_ctx->broadcast_staid] = 0;
586 sta_ctx->broadcast_staid = HDD_WLAN_INVALID_STA_ID;
587
588 os_if_nan_set_ndp_delete_transaction_id(adapter->hdd_vdev,
589 transaction_id);
590 os_if_nan_set_ndi_state(adapter->hdd_vdev, NAN_DATA_NDI_DELETING_STATE);
591
592 /* Delete the interface */
593 ret = __wlan_hdd_del_virtual_intf(hdd_ctx->wiphy, &adapter->wdev);
594 if (ret)
595 hdd_err("NDI delete request failed");
596 else
597 hdd_err("NDI delete request successfully issued");
598
599 return ret;
600}
601
602void hdd_ndi_drv_ndi_create_rsp_handler(uint8_t vdev_id,
603 struct nan_datapath_inf_create_rsp *ndi_rsp)
604{
Naveen Rawatf9391622017-12-20 17:06:01 -0800605 struct hdd_context *hdd_ctx;
606 struct hdd_adapter *adapter;
607 struct hdd_station_ctx *sta_ctx;
Jeff Johnson172237b2017-11-07 15:32:59 -0800608 struct csr_roam_info roam_info = {0};
Jeff Johnson4ba73cb2017-10-06 11:12:33 -0700609 struct bss_description tmp_bss_descp = {0};
Dustin Brownce5b3d32018-01-17 15:07:38 -0800610 struct qdf_mac_addr bc_mac_addr = QDF_MAC_ADDR_BCAST_INIT;
Naveen Rawatf9391622017-12-20 17:06:01 -0800611
612 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
613 if (!hdd_ctx) {
614 hdd_err("hdd_ctx is null");
615 return;
616 }
617
618 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
619 if (!adapter) {
620 hdd_err("adapter is null");
621 return;
622 }
623
624 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
625 if (!sta_ctx) {
626 hdd_err("sta_ctx is null");
627 return;
628 }
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700629
630 if (ndi_rsp->status == QDF_STATUS_SUCCESS) {
631 hdd_alert("NDI interface successfully created");
632 os_if_nan_set_ndp_create_transaction_id(adapter->hdd_vdev, 0);
633 os_if_nan_set_ndi_state(adapter->hdd_vdev,
634 NAN_DATA_NDI_CREATED_STATE);
635 wlan_hdd_netif_queue_control(adapter,
636 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
637 WLAN_CONTROL_PATH);
638 } else {
639 hdd_alert("NDI interface creation failed with reason %d",
640 ndi_rsp->reason /* create_reason */);
641 }
642
643 sta_ctx->broadcast_staid = ndi_rsp->sta_id;
644 hdd_save_peer(sta_ctx, sta_ctx->broadcast_staid, &bc_mac_addr);
645 hdd_roam_register_sta(adapter, &roam_info,
646 sta_ctx->broadcast_staid,
647 &bc_mac_addr, &tmp_bss_descp);
Naveen Rawatb7be1ed2017-11-16 16:52:08 -0800648 if (hdd_objmgr_add_peer_object(adapter->hdd_vdev,
649 QDF_NDI_MODE, bc_mac_addr.bytes, false))
650 hdd_err("Peer object "MAC_ADDRESS_STR" add fails!",
651 MAC_ADDR_ARRAY(bc_mac_addr.bytes));
652
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700653 hdd_ctx->sta_to_adapter[sta_ctx->broadcast_staid] = adapter;
654}
655
656void hdd_ndi_close(uint8_t vdev_id)
657{
Naveen Rawatf9391622017-12-20 17:06:01 -0800658 struct hdd_context *hdd_ctx;
659 struct hdd_adapter *adapter;
660
661 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
662 if (!hdd_ctx) {
663 hdd_err("hdd_ctx is null");
664 return;
665 }
666
667 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
668 if (!adapter) {
669 hdd_err("adapter is null");
670 return;
671 }
Jeff Johnson4f7f7c62017-10-05 08:53:41 -0700672
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700673 hdd_close_ndi(adapter);
674}
675
676void hdd_ndi_drv_ndi_delete_rsp_handler(uint8_t vdev_id)
677{
Naveen Rawatf9391622017-12-20 17:06:01 -0800678 struct hdd_context *hdd_ctx;
679 struct hdd_adapter *adapter;
680 struct hdd_station_ctx *sta_ctx;
681
682 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
683 if (!hdd_ctx) {
684 hdd_err("hdd_ctx is null");
685 return;
686 }
687
688 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
689 if (!adapter) {
690 hdd_err("adapter is null");
691 return;
692 }
693
694 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
695 if (!sta_ctx) {
696 hdd_err("sta_ctx is null");
697 return;
698 }
Naveen Rawatb7be1ed2017-11-16 16:52:08 -0800699
700 hdd_ctx->sta_to_adapter[sta_ctx->broadcast_staid] = NULL;
701 hdd_roam_deregister_sta(adapter, sta_ctx->broadcast_staid);
702 hdd_delete_peer(sta_ctx, sta_ctx->broadcast_staid);
703 sta_ctx->broadcast_staid = HDD_WLAN_INVALID_STA_ID;
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700704
705 wlan_hdd_netif_queue_control(adapter,
706 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
707 WLAN_CONTROL_PATH);
708
709 complete(&adapter->disconnect_comp_var);
710}
711
Jeff Johnson8cb9df12017-08-29 14:28:45 -0700712void hdd_ndp_session_end_handler(struct hdd_adapter *adapter)
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700713{
714 os_if_nan_ndi_session_end(adapter->hdd_vdev);
715}
716
Naveen Rawat37f62c82017-03-26 22:24:43 -0700717int hdd_ndp_get_peer_idx(uint8_t vdev_id, struct qdf_mac_addr *addr)
718{
Jeff Johnson88dc4f92017-08-28 11:51:34 -0700719 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Jeff Johnson8cb9df12017-08-29 14:28:45 -0700720 struct hdd_adapter *adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
Jeff Johnson40dae4e2017-08-29 14:00:25 -0700721 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson4f7f7c62017-10-05 08:53:41 -0700722
Naveen Rawat37f62c82017-03-26 22:24:43 -0700723 return hdd_get_peer_idx(sta_ctx, addr);
724}
725
726/**
727 * hdd_ndp_new_peer_handler() - NDP new peer indication handler
728 * @adapter: pointer to adapter context
729 * @ind_params: indication parameters
730 *
731 * Return: none
732 */
733int hdd_ndp_new_peer_handler(uint8_t vdev_id, uint16_t sta_id,
734 struct qdf_mac_addr *peer_mac_addr, bool fist_peer)
735{
Naveen Rawatf9391622017-12-20 17:06:01 -0800736 struct hdd_context *hdd_ctx;
737 struct hdd_adapter *adapter;
738 struct hdd_station_ctx *sta_ctx;
Jeff Johnson4ba73cb2017-10-06 11:12:33 -0700739 struct bss_description tmp_bss_descp = {0};
Jeff Johnson172237b2017-11-07 15:32:59 -0800740 struct csr_roam_info roam_info = {0};
Naveen Rawat37f62c82017-03-26 22:24:43 -0700741
Dustin Brown491d54b2018-03-14 12:39:11 -0700742 hdd_enter();
Naveen Rawatf9391622017-12-20 17:06:01 -0800743
744 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
745 if (!hdd_ctx) {
746 hdd_err("hdd_ctx is null");
747 return -EINVAL;
748 }
749
750 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
751 if (!adapter) {
752 hdd_err("adapter is null");
753 return -EINVAL;
754 }
755
756 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
757 if (!sta_ctx) {
758 hdd_err("sta_ctx is null");
759 return -EINVAL;
760 }
761
Naveen Rawat37f62c82017-03-26 22:24:43 -0700762 /* save peer in ndp ctx */
763 if (false == hdd_save_peer(sta_ctx, sta_id, peer_mac_addr)) {
764 hdd_err("Ndp peer table full. cannot save new peer");
765 return -EPERM;
766 }
767
768 /* this function is called for each new peer */
769 hdd_roam_register_sta(adapter, &roam_info, sta_id,
770 peer_mac_addr, &tmp_bss_descp);
Naveen Rawatb7be1ed2017-11-16 16:52:08 -0800771 if (hdd_objmgr_add_peer_object(adapter->hdd_vdev,
772 QDF_NDI_MODE, peer_mac_addr->bytes, false))
773 hdd_err("Peer object "MAC_ADDRESS_STR" add fails!",
774 MAC_ADDR_ARRAY(peer_mac_addr->bytes));
Naveen Rawat37f62c82017-03-26 22:24:43 -0700775 hdd_ctx->sta_to_adapter[sta_id] = adapter;
776 /* perform following steps for first new peer ind */
777 if (fist_peer) {
778 hdd_info("Set ctx connection state to connected");
779 sta_ctx->conn_info.connState = eConnectionState_NdiConnected;
780 hdd_wmm_connect(adapter, &roam_info, eCSR_BSS_TYPE_NDI);
781 wlan_hdd_netif_queue_control(adapter,
782 WLAN_WAKE_ALL_NETIF_QUEUE, WLAN_CONTROL_PATH);
783 }
Dustin Browne74003f2018-03-14 12:51:58 -0700784 hdd_exit();
Naveen Rawat37f62c82017-03-26 22:24:43 -0700785 return 0;
786}
787
Naveen Rawatb3143ea2017-03-26 22:25:46 -0700788
789/**
790 * hdd_ndp_peer_departed_handler() - Handle NDP peer departed indication
791 * @adapter: pointer to adapter context
792 * @ind_params: indication parameters
793 *
794 * Return: none
795 */
796void hdd_ndp_peer_departed_handler(uint8_t vdev_id, uint16_t sta_id,
797 struct qdf_mac_addr *peer_mac_addr, bool last_peer)
798{
Naveen Rawatf9391622017-12-20 17:06:01 -0800799 struct hdd_context *hdd_ctx;
800 struct hdd_adapter *adapter;
801 struct hdd_station_ctx *sta_ctx;
Naveen Rawatb3143ea2017-03-26 22:25:46 -0700802
Dustin Brown491d54b2018-03-14 12:39:11 -0700803 hdd_enter();
Naveen Rawatf9391622017-12-20 17:06:01 -0800804
805 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
806 if (!hdd_ctx) {
807 hdd_err("hdd_ctx is null");
808 return;
809 }
810
811 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
812 if (!adapter) {
813 hdd_err("adapter is null");
814 return;
815 }
816
817 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
818 if (!sta_ctx) {
819 hdd_err("sta_ctx is null");
820 return;
821 }
822
Naveen Rawatb3143ea2017-03-26 22:25:46 -0700823 hdd_roam_deregister_sta(adapter, sta_id);
824 hdd_delete_peer(sta_ctx, sta_id);
825 hdd_ctx->sta_to_adapter[sta_id] = NULL;
826
827 if (last_peer) {
828 hdd_info("No more ndp peers.");
829 sta_ctx->conn_info.connState = eConnectionState_NdiDisconnected;
830 hdd_conn_set_connection_state(adapter,
831 eConnectionState_NdiDisconnected);
832 hdd_info("Stop netif tx queues.");
833 wlan_hdd_netif_queue_control(adapter, WLAN_STOP_ALL_NETIF_QUEUE,
834 WLAN_CONTROL_PATH);
835 }
Dustin Browne74003f2018-03-14 12:51:58 -0700836 hdd_exit();
Naveen Rawatb3143ea2017-03-26 22:25:46 -0700837}