blob: 8e4e08c15a57b49c0cbe93f6193908b6ad9a9e8d [file] [log] [blame]
Ravi Joshia063dd92016-05-25 16:43:13 -07001/*
2 * Copyright (c) 2016 The Linux Foundation. All rights reserved.
3 *
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"
34
35/* NLA policy */
36static const struct nla_policy
37qca_wlan_vendor_ndp_policy[QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX + 1] = {
38 [QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD] = { .type = NLA_U32 },
39 [QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID] = { .type = NLA_U16 },
40 [QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR] = { .type = NLA_STRING,
41 .len = IFNAMSIZ },
42 [QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID] = { .type = NLA_U32 },
43 [QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_SPEC_CHANNEL] = { .type = NLA_U32 },
44 [QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR] = {
45 .type = NLA_BINARY,
46 .len = QDF_MAC_ADDR_SIZE },
47 [QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_SECURITY] = { .type = NLA_U16 },
48 [QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS] = { .type = NLA_BINARY,
49 .len = NDP_QOS_INFO_LEN },
50 [QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO_LEN] = { .type = NLA_U16 },
51 [QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO] = { .type = NLA_BINARY,
52 .len = NDP_APP_INFO_LEN },
53 [QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID] = { .type = NLA_U32 },
54 [QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_RESPONSE_CODE] = { .type = NLA_U16 },
55 [QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_STATUS_CODE] = { .type = NLA_U16 },
56 [QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR] = { .type = NLA_BINARY,
57 .len = QDF_MAC_ADDR_SIZE },
58};
Deepak Dhamdhere3385d752016-05-25 20:36:47 -070059
60/**
61 * hdd_ndp_print_ini_config()- Print nan datapath specific INI configuration
62 * @hdd_ctx: handle to hdd context
63 *
64 * Return: None
65 */
66void hdd_ndp_print_ini_config(hdd_context_t *hdd_ctx)
67{
68 hddLog(LOG2, "Name = [%s] Value = [%u]",
69 CFG_ENABLE_NAN_DATAPATH_NAME,
70 hdd_ctx->config->enable_nan_datapath);
71 hddLog(LOG2, "Name = [%s] Value = [%u]",
72 CFG_ENABLE_NAN_NDI_CHANNEL_NAME,
73 hdd_ctx->config->nan_datapath_ndi_channel);
74}
Deepak Dhamdhere13230d32016-05-26 00:46:53 -070075
76/**
77 * hdd_nan_datapath_target_config() - Configure NAN datapath features
78 * @hdd_ctx: Pointer to HDD context
79 * @cfg: Pointer to target device capability information
80 *
Deepak Dhamdhere13983f22016-05-31 19:06:09 -070081 * NAN datapath functionality is enabled if it is enabled in
82 * .ini file and also supported on target device.
Deepak Dhamdhere13230d32016-05-26 00:46:53 -070083 *
84 * Return: None
85 */
Deepak Dhamdhere13230d32016-05-26 00:46:53 -070086void hdd_nan_datapath_target_config(hdd_context_t *hdd_ctx,
87 struct wma_tgt_cfg *cfg)
88{
Deepak Dhamdhere7e6016f2016-06-01 09:37:37 -070089 hdd_ctx->nan_datapath_enabled =
90 hdd_ctx->config->enable_nan_datapath &&
91 cfg->nan_datapath_enabled;
92 hdd_info(FL("enable_nan_datapath: %d"), hdd_ctx->nan_datapath_enabled);
Deepak Dhamdhere13230d32016-05-26 00:46:53 -070093}
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070094
95/**
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -070096 * hdd_close_ndi() - close NAN Data interface
97 * @adapter: adapter context
98 *
99 * Close the adapter if start BSS fails
100 *
101 * Returns: 0 on success, negative error code otherwise
102 */
103static int hdd_close_ndi(hdd_adapter_t *adapter)
104{
105 int rc;
106 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
107 uint32_t timeout = WLAN_WAIT_TIME_SESSIONOPENCLOSE;
108
109 ENTER();
110
111 /* check if the adapter is in NAN Data mode */
112 if (QDF_NDI_MODE != adapter->device_mode) {
113 hdd_err(FL("Interface is not in NDI mode"));
114 return -EINVAL;
115 }
116 netif_tx_disable(adapter->dev);
117 netif_carrier_off(adapter->dev);
118
119#ifdef WLAN_OPEN_SOURCE
120 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
121#endif
122 hdd_deregister_tx_flow_control(adapter);
123
124#ifdef WLAN_NS_OFFLOAD
125#ifdef WLAN_OPEN_SOURCE
126 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
127#endif
128#endif
129 /* check if the session is open */
130 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
131 INIT_COMPLETION(adapter->session_close_comp_var);
132 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
133 adapter->sessionId,
134 hdd_sme_close_session_callback, adapter)) {
135 /* Block on a timed completion variable */
136 rc = wait_for_completion_timeout(
137 &adapter->session_close_comp_var,
138 msecs_to_jiffies(timeout));
139 if (!rc)
140 hdd_err(FL("session close timeout"));
141 }
142 }
143
144 /* We are good to close the adapter */
145 hdd_close_adapter(hdd_ctx, adapter, true);
146
147 EXIT();
148 return 0;
149}
150
151/**
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700152 * hdd_ndi_start_bss() - Start BSS on NAN data interface
153 * @adapter: adapter context
154 * @operating_channel: channel on which the BSS to be started
155 *
156 * Return: 0 on success, error value on failure
157 */
158static int hdd_ndi_start_bss(hdd_adapter_t *adapter,
159 uint8_t operating_channel)
160{
161 int ret;
162 uint32_t roam_id;
163 hdd_wext_state_t *wext_state =
Deepak Dhamdhere8360d4c2016-06-01 13:24:31 -0700164 WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700165 tCsrRoamProfile *roam_profile = &wext_state->roamProfile;
166
167 ENTER();
168
169 if (!roam_profile) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700170 hdd_err(FL("No valid roam profile"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700171 return -EINVAL;
172 }
173
174 if (HDD_WMM_USER_MODE_NO_QOS ==
175 (WLAN_HDD_GET_CTX(adapter))->config->WmmMode) {
176 /* QoS not enabled in cfg file*/
177 roam_profile->uapsd_mask = 0;
178 } else {
179 /* QoS enabled, update uapsd mask from cfg file*/
180 roam_profile->uapsd_mask =
181 (WLAN_HDD_GET_CTX(adapter))->config->UapsdMask;
182 }
183
184 roam_profile->csrPersona = adapter->device_mode;
185
186 roam_profile->ChannelInfo.numOfChannels = 1;
187 if (operating_channel) {
188 roam_profile->ChannelInfo.ChannelList = &operating_channel;
189 } else {
190 roam_profile->ChannelInfo.ChannelList[0] =
191 NAN_SOCIAL_CHANNEL_2_4GHZ;
192 }
193 hdd_select_cbmode(adapter, operating_channel);
194
195 roam_profile->SSIDs.numOfSSIDs = 1;
196 roam_profile->SSIDs.SSIDList->SSID.length = 0;
197
198 roam_profile->phyMode = eCSR_DOT11_MODE_11ac;
199 roam_profile->BSSType = eCSR_BSS_TYPE_NDI;
200 roam_profile->BSSIDs.numOfBSSIDs = 1;
201 qdf_mem_copy((void *)(roam_profile->BSSIDs.bssid),
202 &adapter->macAddressCurrent.bytes[0],
203 QDF_MAC_ADDR_SIZE);
204
205 roam_profile->AuthType.numEntries = 1;
206 roam_profile->AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM;
207 roam_profile->EncryptionType.numEntries = 1;
208 roam_profile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
209
210 ret = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(adapter),
211 adapter->sessionId, roam_profile, &roam_id);
212 if (QDF_STATUS_SUCCESS != ret) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700213 hdd_err(
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700214 FL("NDI sme_RoamConnect session %d failed with status %d -> NotConnected"),
215 adapter->sessionId, ret);
216 /* change back to NotConnected */
217 hdd_conn_set_connection_state(adapter,
218 eConnectionState_NotConnected);
219 } else {
220 hddLog(LOG2, FL("sme_RoamConnect issued successfully for NDI"));
221 }
222
223 roam_profile->ChannelInfo.ChannelList = NULL;
224 roam_profile->ChannelInfo.numOfChannels = 0;
225
226 EXIT();
227
228 return ret;
229}
230
231
232/**
233 * hdd_ndi_create_req_handler() - NDI create request handler
234 * @hdd_ctx: hdd context
235 * @tb: parsed NL attribute list
236 *
237 * Return: 0 on success or error code on failure
238 */
239static int hdd_ndi_create_req_handler(hdd_context_t *hdd_ctx,
240 struct nlattr **tb)
241{
242 hdd_adapter_t *adapter;
243 char *iface_name;
244 uint16_t transaction_id;
245 int ret;
246 struct nan_datapath_ctx *ndp_ctx;
247 uint8_t op_channel =
248 hdd_ctx->config->nan_datapath_ndi_channel;
249
250 ENTER();
251
252 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700253 hdd_err(FL("Interface name string is unavailable"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700254 return -EINVAL;
255 }
256 iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]);
257
258 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700259 hdd_err(FL("transaction id is unavailable"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700260 return -EINVAL;
261 }
262 transaction_id =
263 nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]);
264
265 /* Check for an existing interface of NDI type */
266 adapter = hdd_get_adapter(hdd_ctx, QDF_NDI_MODE);
267 if (adapter) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700268 hdd_err(FL("Cannot support more than one NDI"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700269 return -EEXIST;
270 }
271
272 adapter = hdd_open_adapter(hdd_ctx, QDF_NDI_MODE, iface_name,
273 wlan_hdd_get_intf_addr(hdd_ctx), NET_NAME_UNKNOWN,
274 true);
275 if (!adapter) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700276 hdd_err(FL("hdd_open_adapter failed"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700277 return -ENOMEM;
278 }
279
280 /*
281 * Create transaction id is required to be saved since the firmware
282 * does not honor the transaction id for create request
283 */
284 ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
285 ndp_ctx->ndp_create_transaction_id = transaction_id;
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700286 ndp_ctx->state = NAN_DATA_NDI_CREATING_STATE;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700287
288 /*
289 * The NAN data interface has been created at this point.
290 * Unlike traditional device modes, where the higher application
291 * layer initiates connect / join / start, the NAN data interface
292 * does not have any such formal requests. The NDI create request
293 * is responsible for starting the BSS as well.
294 */
295 if (op_channel != NAN_SOCIAL_CHANNEL_2_4GHZ ||
296 op_channel != NAN_SOCIAL_CHANNEL_5GHZ_LOWER_BAND ||
297 op_channel != NAN_SOCIAL_CHANNEL_5GHZ_UPPER_BAND) {
298 /* start NDI on the default 2.4 GHz social channel */
299 op_channel = NAN_SOCIAL_CHANNEL_2_4GHZ;
300 }
301 ret = hdd_ndi_start_bss(adapter, op_channel);
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700302 if (0 > ret) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700303 hdd_err(FL("NDI start bss failed"));
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700304 /* Start BSS failed, delete the interface */
305 hdd_close_ndi(adapter);
306 }
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700307
308 EXIT();
309 return ret;
310}
311
312/**
313 * hdd_ndi_delete_req_handler() - NDI delete request handler
314 * @hdd_ctx: hdd context
315 * @tb: parsed NL attribute list
316 *
317 * Return: 0 on success or error code on failure
318 */
319static int hdd_ndi_delete_req_handler(hdd_context_t *hdd_ctx,
320 struct nlattr **tb)
321{
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700322 hdd_adapter_t *adapter;
323 char *iface_name;
324 uint16_t transaction_id;
325 struct nan_datapath_ctx *ndp_ctx;
326 int ret;
327
328 ENTER();
329
330 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) {
331 hdd_err(FL("Interface name string is unavailable"));
332 return -EINVAL;
333 }
334
335 iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]);
336
337 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]) {
338 hdd_err(FL("Transaction id is unavailable"));
339 return -EINVAL;
340 }
341
342 transaction_id =
343 nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]);
344
345 /* Check if there is already an existing inteface with the same name */
346 adapter = hdd_get_adapter(hdd_ctx, QDF_NDI_MODE);
347 if (!adapter) {
348 hdd_err(FL("NAN data interface %s is not available"),
349 iface_name);
350 return -EINVAL;
351 }
352
353 /* check if adapter is in NDI mode */
354 if (QDF_NDI_MODE != adapter->device_mode) {
355 hdd_err(FL("Interface %s is not in NDI mode"),
356 iface_name);
357 return -EINVAL;
358 }
359
360 ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
361 if (!ndp_ctx) {
362 hdd_err(FL("ndp_ctx is NULL"));
363 return -EINVAL;
364 }
365
366 /* check if there are active NDP sessions on the adapter */
367 if (ndp_ctx->active_ndp_sessions > 0) {
368 hdd_err(FL("NDP sessions active %d, cannot delete NDI"),
369 ndp_ctx->active_ndp_sessions);
370 return -EINVAL;
371 }
372
373 ndp_ctx->ndp_delete_transaction_id = transaction_id;
374 ndp_ctx->state = NAN_DATA_NDI_DELETING_STATE;
375
376 /* Delete the interface */
377 ret = __wlan_hdd_del_virtual_intf(hdd_ctx->wiphy, &adapter->wdev);
378 if (ret < 0)
379 hdd_err(FL("NDI delete request failed"));
380 else
381 hdd_err(FL("NDI delete request successfully issued"));
382
383 return ret;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700384}
385
386
387/**
388 * hdd_ndp_initiator_req_handler() - NDP initiator request handler
389 * @hdd_ctx: hdd context
390 * @tb: parsed NL attribute list
391 *
392 * Return: 0 on success or error code on failure
393 */
394static int hdd_ndp_initiator_req_handler(hdd_context_t *hdd_ctx,
395 struct nlattr **tb)
396{
397 return 0;
398}
399
400/**
401 * hdd_ndp_responder_req_handler() - NDP responder request handler
402 * @hdd_ctx: hdd context
403 * @tb: parsed NL attribute list
404 *
405 * Return: 0 on success or error code on failure
406 */
407static int hdd_ndp_responder_req_handler(hdd_context_t *hdd_ctx,
408 struct nlattr **tb)
409{
410 return 0;
411}
412
413/**
414 * hdd_ndp_end_req_handler() - NDP end request handler
415 * @hdd_ctx: hdd context
416 * @tb: parsed NL attribute list
417 *
418 * Return: 0 on success or error code on failure
419 */
420static int hdd_ndp_end_req_handler(hdd_context_t *hdd_ctx,
421 struct nlattr **tb)
422{
423 return 0;
424}
425
426/**
427 * hdd_ndp_schedule_req_handler() - NDP schedule request handler
428 * @hdd_ctx: hdd context
429 * @tb: parsed NL attribute list
430 *
431 * Return: 0 on success or error code on failure
432 */
433static int hdd_ndp_schedule_req_handler(hdd_context_t *hdd_ctx,
434 struct nlattr **tb)
435{
436 return 0;
437}
438
439
440/**
441 * hdd_ndp_iface_create_rsp_handler() - NDP iface create response handler
442 * @adapter: pointer to adapter context
443 * @rsp_params: response parameters
444 *
445 * The function is expected to send a response back to the user space
446 * even if the creation of BSS has failed
447 *
448 * Following vendor event is sent to cfg80211:
449 * QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD =
450 * QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE (4 bytes)
451 * QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID (2 bytes)
452 * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE (4 bytes)
453 * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE
454 *
455 * Return: none
456 */
457static void hdd_ndp_iface_create_rsp_handler(hdd_adapter_t *adapter,
458 void *rsp_params)
459{
460 struct sk_buff *vendor_event;
461 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
462 struct ndi_create_rsp *ndi_rsp = (struct ndi_create_rsp *)rsp_params;
463 uint32_t data_len = (3 * sizeof(uint32_t)) + sizeof(uint16_t) +
464 NLMSG_HDRLEN + (4 * NLA_HDRLEN);
465 struct nan_datapath_ctx *ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700466 bool create_fail = false;
467 uint8_t create_transaction_id = 0;
468 uint8_t create_status = 0;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700469
470 ENTER();
471
472 if (wlan_hdd_validate_context(hdd_ctx))
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700473 /* No way the driver can send response back to user space */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700474 return;
475
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700476 if (ndi_rsp) {
477 create_status = ndi_rsp->status;
478 } else {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700479 hdd_err(FL("Invalid ndi create response"));
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700480 create_fail = true;
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700481 }
482
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700483 if (ndp_ctx) {
484 create_transaction_id = ndp_ctx->ndp_create_transaction_id;
485 } else {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700486 hdd_err(FL("ndp_ctx is NULL"));
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700487 create_fail = true;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700488 }
489
490 /* notify response to the upper layer */
491 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
492 NULL,
493 data_len,
494 QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX,
495 cds_get_gfp_flags());
496
497 if (!vendor_event) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700498 hdd_err(FL("cfg80211_vendor_event_alloc failed"));
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700499 create_fail = true;
500 goto close_ndi;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700501 }
502
503 /* Sub vendor command */
504 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
505 QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE)) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700506 hdd_err(FL("QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD put fail"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700507 goto nla_put_failure;
508 }
509
510 /* Transaction id */
511 if (nla_put_u16(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700512 create_transaction_id)) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700513 hdd_err(FL("VENDOR_ATTR_NDP_TRANSACTION_ID put fail"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700514 goto nla_put_failure;
515 }
516
517 /* Status code */
518 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE,
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700519 create_status)) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700520 hdd_err(FL("VENDOR_ATTR_NDP_DRV_RETURN_TYPE put fail"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700521 goto nla_put_failure;
522 }
523
524 /* Status return value */
525 if (nla_put_u32(vendor_event,
526 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, 0xA5)) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700527 hdd_err(FL("VENDOR_ATTR_NDP_DRV_RETURN_VALUE put fail"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700528 goto nla_put_failure;
529 }
530
531 hddLog(LOG2, FL("sub command: %d, value: %d"),
532 QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX,
533 QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE);
534 hddLog(LOG2, FL("create transaction id: %d, value: %d"),
535 QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700536 create_transaction_id);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700537 hddLog(LOG2, FL("status code: %d, value: %d"),
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700538 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE, create_status);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700539 hddLog(LOG2, FL("Return value: %d, value: %d"),
540 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, 0xA5);
541
542 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
543
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700544 if (!create_fail && ndi_rsp->status == QDF_STATUS_SUCCESS) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700545 hdd_err(FL("NDI interface successfully created"));
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700546 ndp_ctx->ndp_create_transaction_id = 0;
547 ndp_ctx->state = NAN_DATA_NDI_CREATED_STATE;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700548 } else {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700549 hdd_err(FL("NDI interface creation failed with reason %d"),
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700550 ndi_rsp->reason);
551 }
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700552
553 /* Something went wrong while starting the BSS */
554 if (create_fail)
555 goto close_ndi;
556
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700557 EXIT();
558 return;
559
560nla_put_failure:
561 kfree_skb(vendor_event);
Deepak Dhamdhere616d9c52016-06-01 12:39:51 -0700562close_ndi:
563 hdd_close_ndi(adapter);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700564 return;
565}
566
567/**
568 * hdd_ndp_iface_delete_rsp_handler() - NDP iface delete response handler
569 * @adapter: pointer to adapter context
570 * @rsp_params: response parameters
571 *
572 * Return: none
573 */
574static void hdd_ndp_iface_delete_rsp_handler(hdd_adapter_t *adapter,
575 void *rsp_params)
576{
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700577 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
578 struct ndi_delete_rsp *ndi_rsp = rsp_params;
579
580 if (wlan_hdd_validate_context(hdd_ctx))
581 return;
582
583 if (!ndi_rsp) {
584 hdd_err(FL("Invalid ndi delete response"));
585 return;
586 }
587
588 if (ndi_rsp->status == QDF_STATUS_SUCCESS)
589 hdd_err(FL("NDI BSS successfully stopped"));
590 else
591 hdd_err(FL("NDI BSS stop failed with reason %d"),
592 ndi_rsp->reason);
593
594 complete(&adapter->disconnect_comp_var);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700595 return;
596}
597
598/**
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700599 * hdd_ndp_session_end_handler() - NDI session termination handler
600 * @adapter: pointer to adapter context
601 *
602 * Following vendor event is sent to cfg80211:
603 * QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD =
604 * QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE (4 bytes)
605 * QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID (2 bytes)
606 * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE (4 bytes)
607 * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE (4 bytes)
608 *
609 * Return: none
610 */
611void hdd_ndp_session_end_handler(hdd_adapter_t *adapter)
612{
613 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
614 struct sk_buff *vendor_event;
615 struct nan_datapath_ctx *ndp_ctx;
616 uint32_t data_len = sizeof(uint32_t) * (3 + sizeof(uint16_t)) +
617 (NLA_HDRLEN * 4) + NLMSG_HDRLEN;
618
619 ENTER();
620
621 if (wlan_hdd_validate_context(hdd_ctx))
622 return;
623
624 /* Handle only if adapter is in NDI mode */
625 if (QDF_NDI_MODE != adapter->device_mode) {
626 hdd_err(FL("Adapter is not in NDI mode"));
627 return;
628 }
629
630 ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
631 if (!ndp_ctx) {
632 hdd_err(FL("ndp context is NULL"));
633 return;
634 }
635
636 /*
637 * The virtual adapters are stopped and closed even during
638 * driver unload or stop, the service layer is not required
639 * to be informed in that case (response is not expected)
640 */
641 if (NAN_DATA_NDI_DELETING_STATE != ndp_ctx->state) {
642 hdd_err(FL("NDI interface %s deleted"),
643 adapter->dev->name);
644 return;
645 }
646
647 /* notify response to the upper layer */
648 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
649 NULL,
650 data_len,
651 QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX,
652 GFP_KERNEL);
653
654 if (!vendor_event) {
655 hdd_err(FL("cfg80211_vendor_event_alloc failed"));
656 return;
657 }
658
659 /* Sub vendor command goes first */
660 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
661 QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE)) {
662 hdd_err(FL("VENDOR_ATTR_NDP_SUBCMD put fail"));
663 goto failure;
664 }
665
666 /* Transaction id */
667 if (nla_put_u16(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
668 ndp_ctx->ndp_delete_transaction_id)) {
669 hdd_err(FL("VENDOR_ATTR_NDP_TRANSACTION_ID put fail"));
670 goto failure;
671 }
672
673 /* Status code */
674 if (nla_put_u32(vendor_event,
675 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE, 0x0)) {
676 hdd_err(FL("VENDOR_ATTR_NDP_DRV_RETURN_TYPE put fail"));
677 goto failure;
678 }
679
680 /* Status return value */
681 if (nla_put_u32(vendor_event,
682 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, 0x0)) {
683 hdd_err(FL("VENDOR_ATTR_NDP_DRV_RETURN_VALUE put fail"));
684 goto failure;
685 }
686
687 hddLog(LOG2, FL("sub command: %d, value: %d"),
688 QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
689 QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE);
690 hddLog(LOG2, FL("delete transaction id: %d, value: %d"),
691 QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
692 ndp_ctx->ndp_delete_transaction_id);
693 hddLog(LOG2, FL("status code: %d, value: %d"),
694 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE,
695 true);
696 hddLog(LOG2, FL("Return value: %d, value: %d"),
697 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, 0x5A);
698
699 ndp_ctx->ndp_delete_transaction_id = 0;
700 ndp_ctx->state = NAN_DATA_NDI_DELETED_STATE;
701
702 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
703
704 EXIT();
705 return;
706
707failure:
708 kfree_skb(vendor_event);
709}
710
711
712/**
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700713 * hdd_ndp_initiator_rsp_handler() - NDP initiator response handler
714 * @adapter: pointer to adapter context
715 * @rsp_params: response parameters
716 *
717 * Return: none
718 */
719static void hdd_ndp_initiator_rsp_handler(hdd_adapter_t *adapter,
720 void *rsp_params)
721{
722 return;
723}
724
725/**
726 * hdd_ndp_new_peer_ind_handler() - NDP new peer indication handler
727 * @adapter: pointer to adapter context
728 * @ind_params: indication parameters
729 *
730 * Return: none
731 */
732static void hdd_ndp_new_peer_ind_handler(hdd_adapter_t *adapter,
733 void *ind_params)
734{
735 return;
736}
737
738/**
739 * hdd_ndp_peer_departed_ind_handler() - NDP peer departed indication handler
740 * @adapter: pointer to adapter context
741 * @ind_params: indication parameters
742 *
743 * Return: none
744 */
745static void hdd_ndp_peer_departed_ind_handler(
746 hdd_adapter_t *adapter, void *ind_params)
747{
748 return;
749}
750
751/**
752 * hdd_ndp_confirm_ind_handler() - NDP confirm indication handler
753 * @adapter: pointer to adapter context
754 * @ind_params: indication parameters
755 *
756 * Return: none
757 */
758static void hdd_ndp_confirm_ind_handler(hdd_adapter_t *adapter,
759 void *ind_params)
760{
761 return;
762}
763
764/**
765 * hdd_ndp_indication_handler() - NDP indication handler
766 * @adapter: pointer to adapter context
767 * @ind_params: indication parameters
768 *
769 * Return: none
770 */
771static void hdd_ndp_indication_handler(hdd_adapter_t *adapter,
772 void *ind_params)
773{
774 return;
775}
776
777/**
778 * hdd_ndp_responder_rsp_handler() - NDP responder response handler
779 * @adapter: pointer to adapter context
780 * @rsp_params: response parameters
781 *
782 * Return: none
783 */
784static void hdd_ndp_responder_rsp_handler(hdd_adapter_t *adapter,
785 void *rsp_params)
786{
787 return;
788}
789
790/**
791 * hdd_ndp_end_rsp_handler() - NDP end response handler
792 * @adapter: pointer to adapter context
793 * @rsp_params: response parameters
794 *
795 * Return: none
796 */
797static void hdd_ndp_end_rsp_handler(hdd_adapter_t *adapter,
798 void *rsp_params)
799{
800 return;
801}
802
803/**
804 * hdd_ndp_end_ind_handler() - NDP end indication handler
805 * @adapter: pointer to adapter context
806 * @ind_params: indication parameters
807 *
808 * Return: none
809 */
810static void hdd_ndp_end_ind_handler(hdd_adapter_t *adapter,
811 void *ind_params)
812{
813 return;
814}
815
816/**
817 * hdd_ndp_schedule_update_rsp_handler() - NDP schedule update response handler
818 * @adapter: pointer to adapter context
819 * @rsp_params: response parameters
820 *
821 * Return: none
822 */
823static void hdd_ndp_schedule_update_rsp_handler(
824 hdd_adapter_t *adapter, void *rsp_params)
825{
826 return;
827}
828
829/**
830 * hdd_ndp_event_handler() - ndp response and indication handler
831 * @adapter: adapter context
832 * @roam_info: pointer to roam_info structure
833 * @roam_id: roam id as indicated by SME
834 * @roam_status: roam status
835 * @roam_result: roam result
836 *
837 * Return: none
838 */
839void hdd_ndp_event_handler(hdd_adapter_t *adapter,
840 tCsrRoamInfo *roam_info, uint32_t roam_id, eRoamCmdStatus roam_status,
841 eCsrRoamResult roam_result)
842{
843 if (roam_status == eCSR_ROAM_NDP_STATUS_UPDATE) {
844 switch (roam_result) {
845 case eCSR_ROAM_RESULT_NDP_CREATE_RSP:
846 hdd_ndp_iface_create_rsp_handler(adapter,
847 &roam_info->ndp.ndi_create_params);
848 break;
849 case eCSR_ROAM_RESULT_NDP_DELETE_RSP:
850 hdd_ndp_iface_delete_rsp_handler(adapter,
851 &roam_info->ndp.ndi_delete_params);
852 break;
853 case eCSR_ROAM_RESULT_NDP_INITIATOR_RSP:
854 hdd_ndp_initiator_rsp_handler(adapter,
855 &roam_info->ndp.ndp_init_rsp_params);
856 break;
857 case eCSR_ROAM_RESULT_NDP_NEW_PEER_IND:
858 hdd_ndp_new_peer_ind_handler(adapter,
859 &roam_info->ndp.ndp_peer_ind_params);
860 break;
861 case eCSR_ROAM_RESULT_NDP_CONFIRM_IND:
862 hdd_ndp_confirm_ind_handler(adapter,
863 &roam_info->ndp.ndp_confirm_params);
864 break;
865 case eCSR_ROAM_RESULT_NDP_INDICATION:
866 hdd_ndp_indication_handler(adapter,
867 &roam_info->ndp.ndp_indication_params);
868 break;
869 case eCSR_ROAM_RESULT_NDP_SCHED_UPDATE_RSP:
870 hdd_ndp_schedule_update_rsp_handler(adapter,
871 &roam_info->ndp.ndp_sched_upd_rsp_params);
872 break;
873 case eCSR_ROAM_RESULT_NDP_RESPONDER_RSP:
874 hdd_ndp_responder_rsp_handler(adapter,
875 &roam_info->ndp.ndp_responder_rsp_params);
876 break;
877 case eCSR_ROAM_RESULT_NDP_END_RSP:
878 hdd_ndp_end_rsp_handler(adapter,
879 &roam_info->ndp.ndp_end_rsp_params);
880 break;
881 case eCSR_ROAM_RESULT_NDP_PEER_DEPARTED_IND:
882 hdd_ndp_peer_departed_ind_handler(adapter,
883 &roam_info->ndp.ndp_peer_ind_params);
884 break;
885 case eCSR_ROAM_RESULT_NDP_END_IND:
886 hdd_ndp_end_ind_handler(adapter,
887 &roam_info->ndp.ndp_end_ind_params);
888 break;
889 default:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700890 hdd_err(FL("Unknown NDP response event from SME %d"),
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700891 roam_result);
892 break;
893 }
894 }
895}
896
897/**
898 * __wlan_hdd_cfg80211_process_ndp_cmds() - handle NDP request
899 * @wiphy: pointer to wireless wiphy structure.
900 * @wdev: pointer to wireless_dev structure.
901 * @data: Pointer to the data to be passed via vendor interface
902 * @data_len:Length of the data to be passed
903 *
904 * This function is invoked to handle vendor command
905 *
906 * Return: 0 on success, negative errno on failure
907 */
908static int __wlan_hdd_cfg80211_process_ndp_cmd(struct wiphy *wiphy,
909 struct wireless_dev *wdev, const void *data, int data_len)
910{
911 uint32_t ndp_cmd_type;
912 uint16_t transaction_id;
913 int ret_val;
914 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
915 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX + 1];
916 char *iface_name;
917
918 ENTER();
919
920 ret_val = wlan_hdd_validate_context(hdd_ctx);
921 if (ret_val)
922 return ret_val;
923
924 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700925 hdd_err(FL("Command not allowed in FTM mode"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700926 return -EPERM;
927 }
Deepak Dhamdhere7e6016f2016-06-01 09:37:37 -0700928 if (!WLAN_HDD_IS_NDP_ENABLED(hdd_ctx)) {
929 hdd_err(FL("NAN datapath is not enabled"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700930 return -EPERM;
931 }
932 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX,
933 data, data_len,
934 qca_wlan_vendor_ndp_policy)) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700935 hdd_err(FL("Invalid NDP vendor command attributes"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700936 return -EINVAL;
937 }
938
939 /* Parse and fetch NDP Command Type*/
940 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD]) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700941 hdd_err(FL("NAN datapath cmd type failed"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700942 return -EINVAL;
943 }
944 ndp_cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD]);
945
946 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700947 hdd_err(FL("attr transaction id failed"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700948 return -EINVAL;
949 }
950 transaction_id = nla_get_u16(
951 tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]);
952
953 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700954 hdd_err(FL("Interface name string is unavailable"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700955 return -EINVAL;
956 }
957 iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]);
958
959 hddLog(LOG2, FL("Transaction Id: %d NDP Cmd: %d iface_name: %s"),
960 transaction_id, ndp_cmd_type, iface_name);
961
962 switch (ndp_cmd_type) {
963 case QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE:
964 ret_val = hdd_ndi_create_req_handler(hdd_ctx, tb);
965 break;
966 case QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE:
967 ret_val = hdd_ndi_delete_req_handler(hdd_ctx, tb);
968 break;
969 case QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_REQUEST:
970 ret_val = hdd_ndp_initiator_req_handler(hdd_ctx, tb);
971 break;
972 case QCA_WLAN_VENDOR_ATTR_NDP_RESPONDER_REQUEST:
973 ret_val = hdd_ndp_responder_req_handler(hdd_ctx, tb);
974 break;
975 case QCA_WLAN_VENDOR_ATTR_NDP_END_REQUEST:
976 ret_val = hdd_ndp_end_req_handler(hdd_ctx, tb);
977 break;
978 case QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_REQUEST:
979 ret_val = hdd_ndp_schedule_req_handler(hdd_ctx, tb);
980 break;
981 default:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700982 hdd_err(FL("Unrecognized NDP vendor cmd %d"),
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700983 ndp_cmd_type);
984 ret_val = -EINVAL;
985 break;
986 }
987
988 return ret_val;
989}
990
991/**
992 * wlan_hdd_cfg80211_process_ndp_cmd() - handle NDP request
993 * @wiphy: pointer to wireless wiphy structure.
994 * @wdev: pointer to wireless_dev structure.
995 * @data: Pointer to the data to be passed via vendor interface
996 * @data_len:Length of the data to be passed
997 *
998 * This function is called to send a NAN request to
999 * firmware. This is an SSR-protected wrapper function.
1000 *
1001 * Return: 0 on success, negative errno on failure
1002 */
1003int wlan_hdd_cfg80211_process_ndp_cmd(struct wiphy *wiphy,
1004 struct wireless_dev *wdev, const void *data, int data_len)
1005{
1006 int ret;
1007
1008 cds_ssr_protect(__func__);
1009 ret = __wlan_hdd_cfg80211_process_ndp_cmd(wiphy, wdev, data, data_len);
1010 cds_ssr_unprotect(__func__);
1011
1012 return ret;
1013}
1014
1015/**
1016 * hdd_init_nan_data_mode() - initialize nan data mode
1017 * @adapter: adapter context
1018 *
1019 * Returns: 0 on success negative error code on error
1020 */
1021int hdd_init_nan_data_mode(struct hdd_adapter_s *adapter)
1022{
1023 struct net_device *wlan_dev = adapter->dev;
1024 struct nan_datapath_ctx *ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
1025 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1026 QDF_STATUS status;
1027 uint32_t type, sub_type;
1028 int32_t ret_val = 0;
1029 unsigned long rc;
1030 uint32_t timeout = WLAN_WAIT_TIME_SESSIONOPENCLOSE;
1031
1032 INIT_COMPLETION(adapter->session_open_comp_var);
1033 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
1034 status = cds_get_vdev_types(adapter->device_mode, &type, &sub_type);
1035 if (QDF_STATUS_SUCCESS != status) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07001036 hdd_err("failed to get vdev type");
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001037 goto error_sme_open;
1038 }
1039
1040 /* open sme session for future use */
1041 status = sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback,
1042 adapter, (uint8_t *)&adapter->macAddressCurrent,
1043 &adapter->sessionId, type, sub_type);
1044 if (QDF_STATUS_SUCCESS == status) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07001045 hdd_err("sme_open_session() failed with status code %d",
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001046 status);
1047 ret_val = -EAGAIN;
1048 goto error_sme_open;
1049 }
1050
1051 /* Block on a completion variable. Can't wait forever though */
1052 rc = wait_for_completion_timeout(
1053 &adapter->session_open_comp_var,
1054 msecs_to_jiffies(timeout));
1055 if (!rc) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07001056 hdd_err(
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001057 FL("Failed to open session, timeout code: %ld"), rc);
1058 ret_val = -ETIMEDOUT;
1059 goto error_sme_open;
1060 }
1061
1062 /* Register wireless extensions */
1063 ret_val = hdd_register_wext(wlan_dev);
1064 if (0 > ret_val) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07001065 hdd_err(FL("Wext registration failed with status code %d"),
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001066 ret_val);
1067 ret_val = -EAGAIN;
1068 goto error_register_wext;
1069 }
1070
1071 status = hdd_init_tx_rx(adapter);
1072 if (QDF_STATUS_SUCCESS != status) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07001073 hdd_err(FL("hdd_init_tx_rx() init failed, status %d"),
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001074 status);
1075 ret_val = -EAGAIN;
1076 goto error_init_txrx;
1077 }
1078
1079 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
1080
1081 status = hdd_wmm_adapter_init(adapter);
1082 if (QDF_STATUS_SUCCESS != status) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07001083 hdd_err(FL("hdd_wmm_adapter_init() failed, status %d"),
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001084 status);
1085 ret_val = -EAGAIN;
1086 goto error_wmm_init;
1087 }
1088
1089 set_bit(WMM_INIT_DONE, &adapter->event_flags);
1090
1091 ret_val = wma_cli_set_command((int)adapter->sessionId,
1092 (int)WMI_PDEV_PARAM_BURST_ENABLE,
1093 (int)hdd_ctx->config->enableSifsBurst,
1094 PDEV_CMD);
1095 if (0 != ret_val) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07001096 hdd_err(FL("WMI_PDEV_PARAM_BURST_ENABLE set failed %d"),
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001097 ret_val);
1098 }
1099
1100 ndp_ctx->state = NAN_DATA_NDI_CREATING_STATE;
1101 return ret_val;
1102
1103error_wmm_init:
1104 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
1105 hdd_deinit_tx_rx(adapter);
1106
1107error_init_txrx:
1108 hdd_unregister_wext(wlan_dev);
1109
1110error_register_wext:
1111 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
1112 INIT_COMPLETION(adapter->session_close_comp_var);
1113 if (QDF_STATUS_SUCCESS ==
1114 sme_close_session(hdd_ctx->hHal,
1115 adapter->sessionId,
1116 hdd_sme_close_session_callback,
1117 adapter)) {
1118 rc = wait_for_completion_timeout(
1119 &adapter->session_close_comp_var,
1120 msecs_to_jiffies(timeout));
1121 if (rc <= 0) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07001122 hdd_err(FL("Session close failed status %ld"),
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001123 rc);
1124 ret_val = -ETIMEDOUT;
1125 }
1126 }
1127 }
1128
1129error_sme_open:
1130 return ret_val;
1131}