blob: 9cb61a541c69c4c5b4385f3099d18f412ef7cb34 [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 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for
7 * any purpose with or without fee is hereby granted, provided that the
8 * above copyright notice and this permission notice appear in all
9 * copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
12 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
15 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
16 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
17 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
18 * PERFORMANCE OF THIS SOFTWARE.
19 */
20
21/**
22 * DOC: wlan_hdd_nan_datapath.c
23 *
24 * WLAN Host Device Driver nan datapath API implementation
25 */
Deepak Dhamdhere13983f22016-05-31 19:06:09 -070026#include <wlan_hdd_includes.h>
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070027#include <linux/if.h>
28#include <linux/netdevice.h>
29#include <linux/skbuff.h>
30#include <linux/etherdevice.h>
31#include "wlan_hdd_includes.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070032#include "wlan_hdd_p2p.h"
33#include "wma_api.h"
Deepak Dhamdhere0f076bd2016-06-02 11:29:21 -070034#include "wlan_hdd_assoc.h"
35#include "sme_nan_datapath.h"
Rajeev Kumar699debf2017-01-06 14:17:00 -080036#include "wlan_hdd_object_manager.h"
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080037#include <qca_vendor.h>
Naveen Rawat63de5422017-03-22 11:03:56 -070038#include "os_if_nan.h"
Naveen Rawatcb5c5402017-03-22 10:12:19 -070039#include "wlan_nan_api.h"
40#include "nan_public_structs.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070041
Deepak Dhamdhere3385d752016-05-25 20:36:47 -070042/**
43 * hdd_ndp_print_ini_config()- Print nan datapath specific INI configuration
44 * @hdd_ctx: handle to hdd context
45 *
46 * Return: None
47 */
Jeff Johnson88dc4f92017-08-28 11:51:34 -070048void hdd_ndp_print_ini_config(struct hdd_context *hdd_ctx)
Deepak Dhamdhere3385d752016-05-25 20:36:47 -070049{
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -070050 hdd_debug("Name = [%s] Value = [%u]", CFG_ENABLE_NAN_DATAPATH_NAME,
Deepak Dhamdhere3385d752016-05-25 20:36:47 -070051 hdd_ctx->config->enable_nan_datapath);
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -070052 hdd_debug("Name = [%s] Value = [%u]", CFG_ENABLE_NAN_NDI_CHANNEL_NAME,
Deepak Dhamdhere3385d752016-05-25 20:36:47 -070053 hdd_ctx->config->nan_datapath_ndi_channel);
54}
Deepak Dhamdhere13230d32016-05-26 00:46:53 -070055
56/**
57 * hdd_nan_datapath_target_config() - Configure NAN datapath features
58 * @hdd_ctx: Pointer to HDD context
59 * @cfg: Pointer to target device capability information
60 *
Deepak Dhamdhere13983f22016-05-31 19:06:09 -070061 * NAN datapath functionality is enabled if it is enabled in
62 * .ini file and also supported on target device.
Deepak Dhamdhere13230d32016-05-26 00:46:53 -070063 *
64 * Return: None
65 */
Jeff Johnson88dc4f92017-08-28 11:51:34 -070066void hdd_nan_datapath_target_config(struct hdd_context *hdd_ctx,
Deepak Dhamdhere13230d32016-05-26 00:46:53 -070067 struct wma_tgt_cfg *cfg)
68{
Deepak Dhamdhere7e6016f2016-06-01 09:37:37 -070069 hdd_ctx->nan_datapath_enabled =
70 hdd_ctx->config->enable_nan_datapath &&
71 cfg->nan_datapath_enabled;
Naveen Rawatcb5c5402017-03-22 10:12:19 -070072 hdd_info("enable_nan_datapath: final: %d, host: %d, fw: %d",
73 hdd_ctx->nan_datapath_enabled,
74 hdd_ctx->config->enable_nan_datapath,
75 cfg->nan_datapath_enabled);
Deepak Dhamdhere13230d32016-05-26 00:46:53 -070076}
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070077
78/**
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -070079 * hdd_close_ndi() - close NAN Data interface
80 * @adapter: adapter context
81 *
82 * Close the adapter if start BSS fails
83 *
84 * Returns: 0 on success, negative error code otherwise
85 */
Jeff Johnson8cb9df12017-08-29 14:28:45 -070086static int hdd_close_ndi(struct hdd_adapter *adapter)
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -070087{
Dustin Brown0d2eeae2017-03-24 15:21:32 -070088 int errno;
Jeff Johnson88dc4f92017-08-28 11:51:34 -070089 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -070090
91 ENTER();
92
93 /* check if the adapter is in NAN Data mode */
94 if (QDF_NDI_MODE != adapter->device_mode) {
Naveen Rawatba4f6612016-07-05 12:03:16 -070095 hdd_err("Interface is not in NDI mode");
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -070096 return -EINVAL;
97 }
Deepak Dhamdhere5872c8c2016-06-02 15:51:47 -070098 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053099 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
Deepak Dhamdhere5872c8c2016-06-02 15:51:47 -0700100 WLAN_CONTROL_PATH);
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700101
102#ifdef WLAN_OPEN_SOURCE
Jeff Johnsonb527ebe2017-10-28 13:14:03 -0700103 cancel_work_sync(&adapter->ipv4_notifier_work);
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700104#endif
105 hdd_deregister_tx_flow_control(adapter);
106
107#ifdef WLAN_NS_OFFLOAD
108#ifdef WLAN_OPEN_SOURCE
Jeff Johnsonb527ebe2017-10-28 13:14:03 -0700109 cancel_work_sync(&adapter->ipv6_notifier_work);
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700110#endif
111#endif
Dustin Brown0d2eeae2017-03-24 15:21:32 -0700112 errno = hdd_vdev_destroy(adapter);
113 if (errno)
114 hdd_err("failed to destroy vdev: %d", errno);
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700115
116 /* We are good to close the adapter */
117 hdd_close_adapter(hdd_ctx, adapter, true);
118
119 EXIT();
120 return 0;
121}
122
123/**
Deepak Dhamdhere0f076bd2016-06-02 11:29:21 -0700124 * hdd_is_ndp_allowed() - Indicates if NDP is allowed
125 * @hdd_ctx: hdd context
126 *
127 * NDP is not allowed with any other role active except STA.
128 *
129 * Return: true if allowed, false otherwise
130 */
Jeff Johnson88dc4f92017-08-28 11:51:34 -0700131static bool hdd_is_ndp_allowed(struct hdd_context *hdd_ctx)
Deepak Dhamdhere0f076bd2016-06-02 11:29:21 -0700132{
Jeff Johnson8cb9df12017-08-29 14:28:45 -0700133 struct hdd_adapter *adapter;
Jeff Johnson40dae4e2017-08-29 14:00:25 -0700134 struct hdd_station_ctx *sta_ctx;
Deepak Dhamdhere0f076bd2016-06-02 11:29:21 -0700135
Dustin Brown920397d2017-12-13 16:27:50 -0800136 hdd_for_each_adapter(hdd_ctx, adapter) {
Deepak Dhamdhere0f076bd2016-06-02 11:29:21 -0700137 switch (adapter->device_mode) {
138 case QDF_P2P_GO_MODE:
139 case QDF_SAP_MODE:
140 if (test_bit(SOFTAP_BSS_STARTED,
141 &adapter->event_flags))
142 return false;
143 break;
144 case QDF_P2P_CLIENT_MODE:
145 case QDF_IBSS_MODE:
146 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
147 if (hdd_conn_is_connected(sta_ctx) ||
148 hdd_is_connecting(sta_ctx))
149 return false;
150 break;
151 default:
152 break;
153 }
Deepak Dhamdhere0f076bd2016-06-02 11:29:21 -0700154 }
155
156 return true;
157}
158
159/**
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700160 * hdd_ndi_start_bss() - Start BSS on NAN data interface
161 * @adapter: adapter context
162 * @operating_channel: channel on which the BSS to be started
163 *
164 * Return: 0 on success, error value on failure
165 */
Jeff Johnson8cb9df12017-08-29 14:28:45 -0700166static int hdd_ndi_start_bss(struct hdd_adapter *adapter,
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700167 uint8_t operating_channel)
168{
169 int ret;
170 uint32_t roam_id;
Jeff Johnson2a722002017-09-30 20:02:35 -0700171 struct hdd_wext_state *wext_state =
Deepak Dhamdhere8360d4c2016-06-01 13:24:31 -0700172 WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700173 tCsrRoamProfile *roam_profile = &wext_state->roamProfile;
174
175 ENTER();
176
177 if (!roam_profile) {
Naveen Rawatba4f6612016-07-05 12:03:16 -0700178 hdd_err("No valid roam profile");
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700179 return -EINVAL;
180 }
181
182 if (HDD_WMM_USER_MODE_NO_QOS ==
183 (WLAN_HDD_GET_CTX(adapter))->config->WmmMode) {
184 /* QoS not enabled in cfg file*/
185 roam_profile->uapsd_mask = 0;
186 } else {
187 /* QoS enabled, update uapsd mask from cfg file*/
188 roam_profile->uapsd_mask =
189 (WLAN_HDD_GET_CTX(adapter))->config->UapsdMask;
190 }
191
192 roam_profile->csrPersona = adapter->device_mode;
193
194 roam_profile->ChannelInfo.numOfChannels = 1;
195 if (operating_channel) {
196 roam_profile->ChannelInfo.ChannelList = &operating_channel;
197 } else {
198 roam_profile->ChannelInfo.ChannelList[0] =
199 NAN_SOCIAL_CHANNEL_2_4GHZ;
200 }
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700201
202 roam_profile->SSIDs.numOfSSIDs = 1;
203 roam_profile->SSIDs.SSIDList->SSID.length = 0;
204
205 roam_profile->phyMode = eCSR_DOT11_MODE_11ac;
206 roam_profile->BSSType = eCSR_BSS_TYPE_NDI;
207 roam_profile->BSSIDs.numOfBSSIDs = 1;
208 qdf_mem_copy((void *)(roam_profile->BSSIDs.bssid),
Jeff Johnson1e851a12017-10-28 14:36:12 -0700209 &adapter->mac_addr.bytes[0],
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700210 QDF_MAC_ADDR_SIZE);
211
212 roam_profile->AuthType.numEntries = 1;
213 roam_profile->AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM;
214 roam_profile->EncryptionType.numEntries = 1;
215 roam_profile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
216
217 ret = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -0700218 adapter->session_id, roam_profile, &roam_id);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700219 if (QDF_STATUS_SUCCESS != ret) {
Naveen Rawatba4f6612016-07-05 12:03:16 -0700220 hdd_err("NDI sme_RoamConnect session %d failed with status %d -> NotConnected",
Jeff Johnson1b780e42017-10-31 14:11:45 -0700221 adapter->session_id, ret);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700222 /* change back to NotConnected */
223 hdd_conn_set_connection_state(adapter,
224 eConnectionState_NotConnected);
225 } else {
Naveen Rawatba4f6612016-07-05 12:03:16 -0700226 hdd_info("sme_RoamConnect issued successfully for NDI");
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700227 }
228
229 roam_profile->ChannelInfo.ChannelList = NULL;
230 roam_profile->ChannelInfo.numOfChannels = 0;
231
232 EXIT();
233
234 return ret;
235}
236
Naveen Rawat5a6f8402017-07-03 16:00:11 -0700237/**
238 * hdd_get_random_nan_mac_addr() - generate random non pre-existent mac address
239 * @hdd_ctx: hdd context pointer
240 * @mac_addr: mac address buffer to populate
241 *
242 * Return: status of operation
243 */
Jeff Johnson88dc4f92017-08-28 11:51:34 -0700244static int hdd_get_random_nan_mac_addr(struct hdd_context *hdd_ctx,
Naveen Rawat5a6f8402017-07-03 16:00:11 -0700245 struct qdf_mac_addr *mac_addr)
246{
Jeff Johnson8cb9df12017-08-29 14:28:45 -0700247 struct hdd_adapter *adapter;
Naveen Rawat5a6f8402017-07-03 16:00:11 -0700248 uint8_t i, attempts, max_attempt = 16;
Naveen Rawat5a6f8402017-07-03 16:00:11 -0700249
250 for (attempts = 0; attempts < max_attempt; attempts++) {
251 cds_rand_get_bytes(0, (uint8_t *)mac_addr, sizeof(*mac_addr));
Ravi Joshi04a1c992017-06-11 19:47:54 -0700252
253 /*
254 * Reset multicast bit (bit-0) and set locally-administered bit
255 */
256 mac_addr->bytes[0] = 0x2;
257
Naveen Rawat5a6f8402017-07-03 16:00:11 -0700258 /*
259 * to avoid potential conflict with FW's generated NMI mac addr,
260 * host sets LSB if 6th byte to 0
261 */
262 mac_addr->bytes[5] &= 0xFE;
263
Naveen Rawat5a6f8402017-07-03 16:00:11 -0700264 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
265 if (!qdf_mem_cmp(hdd_ctx->config->intfMacAddr[i].bytes,
266 mac_addr, sizeof(*mac_addr)))
267 continue;
268 }
269
270 adapter = hdd_get_adapter_by_macaddr(hdd_ctx, mac_addr->bytes);
271 if (!adapter)
272 return 0;
273 }
274
275 hdd_err("unable to get non-pre-existing mac address in %d attempts",
276 max_attempt);
277
278 return -EINVAL;
279}
280
Jeff Johnson8cb9df12017-08-29 14:28:45 -0700281void hdd_ndp_event_handler(struct hdd_adapter *adapter,
Jeff Johnson172237b2017-11-07 15:32:59 -0800282 struct csr_roam_info *roam_info,
283 uint32_t roam_id, eRoamCmdStatus roam_status,
284 eCsrRoamResult roam_result)
Naveen Rawat97500352017-03-22 10:07:58 -0700285{
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700286 bool success;
287 struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(adapter->hdd_vdev);
288
289 if (roam_status == eCSR_ROAM_NDP_STATUS_UPDATE) {
290 switch (roam_result) {
291 case eCSR_ROAM_RESULT_NDI_CREATE_RSP:
292 success = (roam_info->ndp.ndi_create_params.status ==
293 NAN_DATAPATH_RSP_STATUS_SUCCESS);
294 hdd_debug("posting ndi create status: %d to umac",
295 success);
Jeff Johnson1b780e42017-10-31 14:11:45 -0700296 os_if_nan_post_ndi_create_rsp(psoc, adapter->session_id,
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700297 success);
298 return;
299 case eCSR_ROAM_RESULT_NDI_DELETE_RSP:
300 success = (roam_info->ndp.ndi_create_params.status ==
301 NAN_DATAPATH_RSP_STATUS_SUCCESS);
302 hdd_debug("posting ndi delete status: %d to umac",
303 success);
Jeff Johnson1b780e42017-10-31 14:11:45 -0700304 os_if_nan_post_ndi_delete_rsp(psoc, adapter->session_id,
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700305 success);
306 return;
307 default:
308 hdd_err("in correct roam_result: %d", roam_result);
309 return;
310 }
311 } else {
312 hdd_err("in correct roam_status: %d", roam_status);
313 return;
314 }
Naveen Rawat97500352017-03-22 10:07:58 -0700315}
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700316
317/**
318 * __wlan_hdd_cfg80211_process_ndp_cmds() - handle NDP request
319 * @wiphy: pointer to wireless wiphy structure.
320 * @wdev: pointer to wireless_dev structure.
321 * @data: Pointer to the data to be passed via vendor interface
322 * @data_len:Length of the data to be passed
323 *
324 * This function is invoked to handle vendor command
325 *
326 * Return: 0 on success, negative errno on failure
327 */
Naveen Rawat63de5422017-03-22 11:03:56 -0700328static int __wlan_hdd_cfg80211_process_ndp_cmd(struct wiphy *wiphy,
329 struct wireless_dev *wdev, const void *data, int data_len)
330{
331 int ret_val;
Jeff Johnson88dc4f92017-08-28 11:51:34 -0700332 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Naveen Rawat63de5422017-03-22 11:03:56 -0700333
334 ENTER();
335
336 ret_val = wlan_hdd_validate_context(hdd_ctx);
337 if (ret_val)
338 return ret_val;
339
340 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
341 hdd_err("Command not allowed in FTM mode");
342 return -EPERM;
343 }
344
345 if (!WLAN_HDD_IS_NDP_ENABLED(hdd_ctx)) {
346 hdd_err("NAN datapath is not enabled");
347 return -EPERM;
348 }
349 /* NAN data path coexists only with STA interface */
350 if (false == hdd_is_ndp_allowed(hdd_ctx)) {
351 hdd_err("Unsupported concurrency for NAN datapath");
352 return -EPERM;
353 }
354
355 /* NAN data path coexists only with STA interface */
356 if (false == hdd_is_ndp_allowed(hdd_ctx)) {
357 hdd_err("Unsupported concurrency for NAN datapath");
358 return -EPERM;
359 }
360
361 return os_if_nan_process_ndp_cmd(hdd_ctx->hdd_psoc,
362 data, data_len);
363}
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700364
365/**
366 * wlan_hdd_cfg80211_process_ndp_cmd() - handle NDP request
367 * @wiphy: pointer to wireless wiphy structure.
368 * @wdev: pointer to wireless_dev structure.
369 * @data: Pointer to the data to be passed via vendor interface
370 * @data_len:Length of the data to be passed
371 *
372 * This function is called to send a NAN request to
373 * firmware. This is an SSR-protected wrapper function.
374 *
375 * Return: 0 on success, negative errno on failure
376 */
377int wlan_hdd_cfg80211_process_ndp_cmd(struct wiphy *wiphy,
378 struct wireless_dev *wdev, const void *data, int data_len)
379{
380 int ret;
381
382 cds_ssr_protect(__func__);
383 ret = __wlan_hdd_cfg80211_process_ndp_cmd(wiphy, wdev, data, data_len);
384 cds_ssr_unprotect(__func__);
385
386 return ret;
387}
388
Jeff Johnson85b5c112017-08-11 15:15:23 -0700389static int update_ndi_state(struct hdd_adapter *adapter, uint32_t state)
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700390{
391 return os_if_nan_set_ndi_state(adapter->hdd_vdev, state);
392}
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700393
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700394/**
395 * hdd_init_nan_data_mode() - initialize nan data mode
396 * @adapter: adapter context
397 *
398 * Returns: 0 on success negative error code on error
399 */
Jeff Johnson85b5c112017-08-11 15:15:23 -0700400int hdd_init_nan_data_mode(struct hdd_adapter *adapter)
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700401{
402 struct net_device *wlan_dev = adapter->dev;
Jeff Johnson88dc4f92017-08-28 11:51:34 -0700403 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700404 QDF_STATUS status;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700405 int32_t ret_val = 0;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700406
Krunal Sonib51eec72017-11-20 21:53:01 -0800407 ret_val = hdd_vdev_create(adapter, hdd_sme_roam_callback, adapter);
Dustin Brownd28772b2017-03-17 14:16:07 -0700408 if (ret_val) {
409 hdd_err("failed to create vdev: %d", ret_val);
410 return ret_val;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700411 }
412
Ravi Joshi8eb65f92017-07-20 16:30:19 -0700413 /* Configure self HT/VHT capabilities */
414 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
415 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Jeff Johnson1b780e42017-10-31 14:11:45 -0700416 sme_set_vdev_ies_per_band(hdd_ctx->hHal, adapter->session_id);
Ravi Joshi8eb65f92017-07-20 16:30:19 -0700417
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700418 /* Register wireless extensions */
419 ret_val = hdd_register_wext(wlan_dev);
420 if (0 > ret_val) {
Naveen Rawatba4f6612016-07-05 12:03:16 -0700421 hdd_err("Wext registration failed with status code %d",
422 ret_val);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700423 ret_val = -EAGAIN;
424 goto error_register_wext;
425 }
426
427 status = hdd_init_tx_rx(adapter);
428 if (QDF_STATUS_SUCCESS != status) {
Naveen Rawatba4f6612016-07-05 12:03:16 -0700429 hdd_err("hdd_init_tx_rx() init failed, status %d", status);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700430 ret_val = -EAGAIN;
431 goto error_init_txrx;
432 }
433
434 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
435
436 status = hdd_wmm_adapter_init(adapter);
437 if (QDF_STATUS_SUCCESS != status) {
Naveen Rawatba4f6612016-07-05 12:03:16 -0700438 hdd_err("hdd_wmm_adapter_init() failed, status %d", status);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700439 ret_val = -EAGAIN;
440 goto error_wmm_init;
441 }
442
443 set_bit(WMM_INIT_DONE, &adapter->event_flags);
444
Jeff Johnson1b780e42017-10-31 14:11:45 -0700445 ret_val = wma_cli_set_command((int)adapter->session_id,
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700446 (int)WMI_PDEV_PARAM_BURST_ENABLE,
447 (int)hdd_ctx->config->enableSifsBurst,
448 PDEV_CMD);
Arunk Khandavalli15664e42017-06-29 15:56:14 +0530449 if (0 != ret_val)
Naveen Rawatba4f6612016-07-05 12:03:16 -0700450 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d", ret_val);
Arunk Khandavalli15664e42017-06-29 15:56:14 +0530451
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700452
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700453 update_ndi_state(adapter, NAN_DATA_NDI_CREATING_STATE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700454 return ret_val;
455
456error_wmm_init:
457 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
458 hdd_deinit_tx_rx(adapter);
459
460error_init_txrx:
461 hdd_unregister_wext(wlan_dev);
462
463error_register_wext:
Dustin Brownd28772b2017-03-17 14:16:07 -0700464 QDF_BUG(!hdd_vdev_destroy(adapter));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700465
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700466 return ret_val;
467}
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700468
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700469struct wlan_objmgr_vdev *hdd_ndi_open(char *iface_name)
470{
Jeff Johnson8cb9df12017-08-29 14:28:45 -0700471 struct hdd_adapter *adapter;
Ravi Joshi9771d432017-06-26 13:58:12 -0700472 struct qdf_mac_addr random_ndi_mac;
Jeff Johnson88dc4f92017-08-28 11:51:34 -0700473 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Ravi Joshi9771d432017-06-26 13:58:12 -0700474 uint8_t *ndi_mac_addr;
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700475
476 ENTER();
Naveen Rawat5a6f8402017-07-03 16:00:11 -0700477
Naveen Rawatf9391622017-12-20 17:06:01 -0800478 if (!hdd_ctx) {
479 hdd_err("hdd_ctx null");
480 return NULL;
481 }
482
Ravi Joshi9771d432017-06-26 13:58:12 -0700483 if (hdd_ctx->config->is_ndi_mac_randomized) {
484 if (hdd_get_random_nan_mac_addr(hdd_ctx, &random_ndi_mac)) {
485 hdd_err("get random mac address failed");
486 return NULL;
487 }
488 ndi_mac_addr = &random_ndi_mac.bytes[0];
489 } else {
490 ndi_mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
491 if (!ndi_mac_addr) {
492 hdd_err("get intf address failed");
493 return NULL;
494 }
Naveen Rawat5a6f8402017-07-03 16:00:11 -0700495 }
496
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700497 adapter = hdd_open_adapter(hdd_ctx, QDF_NDI_MODE, iface_name,
Ravi Joshi9771d432017-06-26 13:58:12 -0700498 ndi_mac_addr, NET_NAME_UNKNOWN, true);
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700499 if (!adapter) {
500 hdd_err("hdd_open_adapter failed");
501 return NULL;
502 }
503
504 EXIT();
505 return adapter->hdd_vdev;
506}
507
508int hdd_ndi_start(uint8_t vdev_id)
509{
Naveen Rawatf9391622017-12-20 17:06:01 -0800510 uint8_t op_channel;
511 struct hdd_adapter *adapter;
Jeff Johnson88dc4f92017-08-28 11:51:34 -0700512 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700513
514 ENTER();
Naveen Rawatf9391622017-12-20 17:06:01 -0800515
516 if (!hdd_ctx) {
517 hdd_err("hdd_ctx is null");
518 return -EINVAL;
519 }
520
521 op_channel = hdd_ctx->config->nan_datapath_ndi_channel;
522 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
523 if (!adapter) {
524 hdd_err("adapter is null");
525 return -EINVAL;
526 }
527
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700528 /*
529 * The NAN data interface has been created at this point.
530 * Unlike traditional device modes, where the higher application
531 * layer initiates connect / join / start, the NAN data
532 * interface does not have any such formal requests. The NDI
533 * create request is responsible for starting the BSS as well.
534 */
535 if (op_channel != NAN_SOCIAL_CHANNEL_2_4GHZ ||
536 op_channel != NAN_SOCIAL_CHANNEL_5GHZ_LOWER_BAND ||
537 op_channel != NAN_SOCIAL_CHANNEL_5GHZ_UPPER_BAND) {
538 /* start NDI on the default 2.4 GHz social channel */
539 op_channel = NAN_SOCIAL_CHANNEL_2_4GHZ;
540 }
541 if (hdd_ndi_start_bss(adapter, op_channel)) {
542 hdd_err("NDI start bss failed");
543 /* Start BSS failed, delete the interface */
544 hdd_close_ndi(adapter);
545 EXIT();
546 return -EINVAL;
547 }
548
Naveen Rawatf9391622017-12-20 17:06:01 -0800549 EXIT();
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700550 return 0;
551}
552
553int hdd_ndi_delete(uint8_t vdev_id, char *iface_name, uint16_t transaction_id)
554{
555 int ret;
Jeff Johnson8cb9df12017-08-29 14:28:45 -0700556 struct hdd_adapter *adapter;
Jeff Johnson40dae4e2017-08-29 14:00:25 -0700557 struct hdd_station_ctx *sta_ctx;
Jeff Johnson88dc4f92017-08-28 11:51:34 -0700558 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700559
Naveen Rawatf9391622017-12-20 17:06:01 -0800560 if (!hdd_ctx) {
561 hdd_err("hdd_ctx is null");
562 return -EINVAL;
563 }
564
Naveen Rawatc4b045c2017-06-30 16:11:42 -0700565 /* check if adapter by vdev_id is valid NDI */
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700566 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
567 if (!adapter || !WLAN_HDD_IS_NDI(adapter)) {
568 hdd_err("NAN data interface %s is not available", iface_name);
569 return -EINVAL;
570 }
571
572 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
573 if (!sta_ctx) {
574 hdd_err("sta_ctx is NULL");
575 return -EINVAL;
576 }
577
578 /* Since, the interface is being deleted, remove the broadcast id. */
579 hdd_ctx->sta_to_adapter[sta_ctx->broadcast_staid] = 0;
580 sta_ctx->broadcast_staid = HDD_WLAN_INVALID_STA_ID;
581
582 os_if_nan_set_ndp_delete_transaction_id(adapter->hdd_vdev,
583 transaction_id);
584 os_if_nan_set_ndi_state(adapter->hdd_vdev, NAN_DATA_NDI_DELETING_STATE);
585
586 /* Delete the interface */
587 ret = __wlan_hdd_del_virtual_intf(hdd_ctx->wiphy, &adapter->wdev);
588 if (ret)
589 hdd_err("NDI delete request failed");
590 else
591 hdd_err("NDI delete request successfully issued");
592
593 return ret;
594}
595
596void hdd_ndi_drv_ndi_create_rsp_handler(uint8_t vdev_id,
597 struct nan_datapath_inf_create_rsp *ndi_rsp)
598{
Naveen Rawatf9391622017-12-20 17:06:01 -0800599 struct hdd_context *hdd_ctx;
600 struct hdd_adapter *adapter;
601 struct hdd_station_ctx *sta_ctx;
Jeff Johnson172237b2017-11-07 15:32:59 -0800602 struct csr_roam_info roam_info = {0};
Jeff Johnson4ba73cb2017-10-06 11:12:33 -0700603 struct bss_description tmp_bss_descp = {0};
Dustin Brownce5b3d32018-01-17 15:07:38 -0800604 struct qdf_mac_addr bc_mac_addr = QDF_MAC_ADDR_BCAST_INIT;
Naveen Rawatf9391622017-12-20 17:06:01 -0800605
606 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
607 if (!hdd_ctx) {
608 hdd_err("hdd_ctx is null");
609 return;
610 }
611
612 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
613 if (!adapter) {
614 hdd_err("adapter is null");
615 return;
616 }
617
618 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
619 if (!sta_ctx) {
620 hdd_err("sta_ctx is null");
621 return;
622 }
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700623
624 if (ndi_rsp->status == QDF_STATUS_SUCCESS) {
625 hdd_alert("NDI interface successfully created");
626 os_if_nan_set_ndp_create_transaction_id(adapter->hdd_vdev, 0);
627 os_if_nan_set_ndi_state(adapter->hdd_vdev,
628 NAN_DATA_NDI_CREATED_STATE);
629 wlan_hdd_netif_queue_control(adapter,
630 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
631 WLAN_CONTROL_PATH);
632 } else {
633 hdd_alert("NDI interface creation failed with reason %d",
634 ndi_rsp->reason /* create_reason */);
635 }
636
637 sta_ctx->broadcast_staid = ndi_rsp->sta_id;
638 hdd_save_peer(sta_ctx, sta_ctx->broadcast_staid, &bc_mac_addr);
639 hdd_roam_register_sta(adapter, &roam_info,
640 sta_ctx->broadcast_staid,
641 &bc_mac_addr, &tmp_bss_descp);
Naveen Rawatb7be1ed2017-11-16 16:52:08 -0800642 if (hdd_objmgr_add_peer_object(adapter->hdd_vdev,
643 QDF_NDI_MODE, bc_mac_addr.bytes, false))
644 hdd_err("Peer object "MAC_ADDRESS_STR" add fails!",
645 MAC_ADDR_ARRAY(bc_mac_addr.bytes));
646
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700647 hdd_ctx->sta_to_adapter[sta_ctx->broadcast_staid] = adapter;
648}
649
650void hdd_ndi_close(uint8_t vdev_id)
651{
Naveen Rawatf9391622017-12-20 17:06:01 -0800652 struct hdd_context *hdd_ctx;
653 struct hdd_adapter *adapter;
654
655 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
656 if (!hdd_ctx) {
657 hdd_err("hdd_ctx is null");
658 return;
659 }
660
661 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
662 if (!adapter) {
663 hdd_err("adapter is null");
664 return;
665 }
Jeff Johnson4f7f7c62017-10-05 08:53:41 -0700666
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700667 hdd_close_ndi(adapter);
668}
669
670void hdd_ndi_drv_ndi_delete_rsp_handler(uint8_t vdev_id)
671{
Naveen Rawatf9391622017-12-20 17:06:01 -0800672 struct hdd_context *hdd_ctx;
673 struct hdd_adapter *adapter;
674 struct hdd_station_ctx *sta_ctx;
675
676 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
677 if (!hdd_ctx) {
678 hdd_err("hdd_ctx is null");
679 return;
680 }
681
682 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
683 if (!adapter) {
684 hdd_err("adapter is null");
685 return;
686 }
687
688 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
689 if (!sta_ctx) {
690 hdd_err("sta_ctx is null");
691 return;
692 }
Naveen Rawatb7be1ed2017-11-16 16:52:08 -0800693
694 hdd_ctx->sta_to_adapter[sta_ctx->broadcast_staid] = NULL;
695 hdd_roam_deregister_sta(adapter, sta_ctx->broadcast_staid);
696 hdd_delete_peer(sta_ctx, sta_ctx->broadcast_staid);
697 sta_ctx->broadcast_staid = HDD_WLAN_INVALID_STA_ID;
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700698
699 wlan_hdd_netif_queue_control(adapter,
700 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
701 WLAN_CONTROL_PATH);
702
703 complete(&adapter->disconnect_comp_var);
704}
705
Jeff Johnson8cb9df12017-08-29 14:28:45 -0700706void hdd_ndp_session_end_handler(struct hdd_adapter *adapter)
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700707{
708 os_if_nan_ndi_session_end(adapter->hdd_vdev);
709}
710
Naveen Rawat37f62c82017-03-26 22:24:43 -0700711int hdd_ndp_get_peer_idx(uint8_t vdev_id, struct qdf_mac_addr *addr)
712{
Jeff Johnson88dc4f92017-08-28 11:51:34 -0700713 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Jeff Johnson8cb9df12017-08-29 14:28:45 -0700714 struct hdd_adapter *adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
Jeff Johnson40dae4e2017-08-29 14:00:25 -0700715 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson4f7f7c62017-10-05 08:53:41 -0700716
Naveen Rawat37f62c82017-03-26 22:24:43 -0700717 return hdd_get_peer_idx(sta_ctx, addr);
718}
719
720/**
721 * hdd_ndp_new_peer_handler() - NDP new peer indication handler
722 * @adapter: pointer to adapter context
723 * @ind_params: indication parameters
724 *
725 * Return: none
726 */
727int hdd_ndp_new_peer_handler(uint8_t vdev_id, uint16_t sta_id,
728 struct qdf_mac_addr *peer_mac_addr, bool fist_peer)
729{
Naveen Rawatf9391622017-12-20 17:06:01 -0800730 struct hdd_context *hdd_ctx;
731 struct hdd_adapter *adapter;
732 struct hdd_station_ctx *sta_ctx;
Jeff Johnson4ba73cb2017-10-06 11:12:33 -0700733 struct bss_description tmp_bss_descp = {0};
Jeff Johnson172237b2017-11-07 15:32:59 -0800734 struct csr_roam_info roam_info = {0};
Naveen Rawat37f62c82017-03-26 22:24:43 -0700735
736 ENTER();
Naveen Rawatf9391622017-12-20 17:06:01 -0800737
738 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
739 if (!hdd_ctx) {
740 hdd_err("hdd_ctx is null");
741 return -EINVAL;
742 }
743
744 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
745 if (!adapter) {
746 hdd_err("adapter is null");
747 return -EINVAL;
748 }
749
750 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
751 if (!sta_ctx) {
752 hdd_err("sta_ctx is null");
753 return -EINVAL;
754 }
755
Naveen Rawat37f62c82017-03-26 22:24:43 -0700756 /* save peer in ndp ctx */
757 if (false == hdd_save_peer(sta_ctx, sta_id, peer_mac_addr)) {
758 hdd_err("Ndp peer table full. cannot save new peer");
759 return -EPERM;
760 }
761
762 /* this function is called for each new peer */
763 hdd_roam_register_sta(adapter, &roam_info, sta_id,
764 peer_mac_addr, &tmp_bss_descp);
Naveen Rawatb7be1ed2017-11-16 16:52:08 -0800765 if (hdd_objmgr_add_peer_object(adapter->hdd_vdev,
766 QDF_NDI_MODE, peer_mac_addr->bytes, false))
767 hdd_err("Peer object "MAC_ADDRESS_STR" add fails!",
768 MAC_ADDR_ARRAY(peer_mac_addr->bytes));
Naveen Rawat37f62c82017-03-26 22:24:43 -0700769 hdd_ctx->sta_to_adapter[sta_id] = adapter;
770 /* perform following steps for first new peer ind */
771 if (fist_peer) {
772 hdd_info("Set ctx connection state to connected");
773 sta_ctx->conn_info.connState = eConnectionState_NdiConnected;
774 hdd_wmm_connect(adapter, &roam_info, eCSR_BSS_TYPE_NDI);
775 wlan_hdd_netif_queue_control(adapter,
776 WLAN_WAKE_ALL_NETIF_QUEUE, WLAN_CONTROL_PATH);
777 }
778 EXIT();
779 return 0;
780}
781
Naveen Rawatb3143ea2017-03-26 22:25:46 -0700782
783/**
784 * hdd_ndp_peer_departed_handler() - Handle NDP peer departed indication
785 * @adapter: pointer to adapter context
786 * @ind_params: indication parameters
787 *
788 * Return: none
789 */
790void hdd_ndp_peer_departed_handler(uint8_t vdev_id, uint16_t sta_id,
791 struct qdf_mac_addr *peer_mac_addr, bool last_peer)
792{
Naveen Rawatf9391622017-12-20 17:06:01 -0800793 struct hdd_context *hdd_ctx;
794 struct hdd_adapter *adapter;
795 struct hdd_station_ctx *sta_ctx;
Naveen Rawatb3143ea2017-03-26 22:25:46 -0700796
797 ENTER();
Naveen Rawatf9391622017-12-20 17:06:01 -0800798
799 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
800 if (!hdd_ctx) {
801 hdd_err("hdd_ctx is null");
802 return;
803 }
804
805 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
806 if (!adapter) {
807 hdd_err("adapter is null");
808 return;
809 }
810
811 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
812 if (!sta_ctx) {
813 hdd_err("sta_ctx is null");
814 return;
815 }
816
Naveen Rawatb3143ea2017-03-26 22:25:46 -0700817 hdd_roam_deregister_sta(adapter, sta_id);
818 hdd_delete_peer(sta_ctx, sta_id);
819 hdd_ctx->sta_to_adapter[sta_id] = NULL;
820
821 if (last_peer) {
822 hdd_info("No more ndp peers.");
823 sta_ctx->conn_info.connState = eConnectionState_NdiDisconnected;
824 hdd_conn_set_connection_state(adapter,
825 eConnectionState_NdiDisconnected);
826 hdd_info("Stop netif tx queues.");
827 wlan_hdd_netif_queue_control(adapter, WLAN_STOP_ALL_NETIF_QUEUE,
828 WLAN_CONTROL_PATH);
829 }
830 EXIT();
831}