blob: 6c53f7b6db10f74b2fb78a0f084c2512e711be52 [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/**
96 * hdd_ndi_start_bss() - Start BSS on NAN data interface
97 * @adapter: adapter context
98 * @operating_channel: channel on which the BSS to be started
99 *
100 * Return: 0 on success, error value on failure
101 */
102static int hdd_ndi_start_bss(hdd_adapter_t *adapter,
103 uint8_t operating_channel)
104{
105 int ret;
106 uint32_t roam_id;
107 hdd_wext_state_t *wext_state =
108 WLAN_HDD_GET_NDP_WEXT_STATE_PTR(adapter);
109 tCsrRoamProfile *roam_profile = &wext_state->roamProfile;
110
111 ENTER();
112
113 if (!roam_profile) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700114 hdd_err(FL("No valid roam profile"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700115 return -EINVAL;
116 }
117
118 if (HDD_WMM_USER_MODE_NO_QOS ==
119 (WLAN_HDD_GET_CTX(adapter))->config->WmmMode) {
120 /* QoS not enabled in cfg file*/
121 roam_profile->uapsd_mask = 0;
122 } else {
123 /* QoS enabled, update uapsd mask from cfg file*/
124 roam_profile->uapsd_mask =
125 (WLAN_HDD_GET_CTX(adapter))->config->UapsdMask;
126 }
127
128 roam_profile->csrPersona = adapter->device_mode;
129
130 roam_profile->ChannelInfo.numOfChannels = 1;
131 if (operating_channel) {
132 roam_profile->ChannelInfo.ChannelList = &operating_channel;
133 } else {
134 roam_profile->ChannelInfo.ChannelList[0] =
135 NAN_SOCIAL_CHANNEL_2_4GHZ;
136 }
137 hdd_select_cbmode(adapter, operating_channel);
138
139 roam_profile->SSIDs.numOfSSIDs = 1;
140 roam_profile->SSIDs.SSIDList->SSID.length = 0;
141
142 roam_profile->phyMode = eCSR_DOT11_MODE_11ac;
143 roam_profile->BSSType = eCSR_BSS_TYPE_NDI;
144 roam_profile->BSSIDs.numOfBSSIDs = 1;
145 qdf_mem_copy((void *)(roam_profile->BSSIDs.bssid),
146 &adapter->macAddressCurrent.bytes[0],
147 QDF_MAC_ADDR_SIZE);
148
149 roam_profile->AuthType.numEntries = 1;
150 roam_profile->AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM;
151 roam_profile->EncryptionType.numEntries = 1;
152 roam_profile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
153
154 ret = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(adapter),
155 adapter->sessionId, roam_profile, &roam_id);
156 if (QDF_STATUS_SUCCESS != ret) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700157 hdd_err(
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700158 FL("NDI sme_RoamConnect session %d failed with status %d -> NotConnected"),
159 adapter->sessionId, ret);
160 /* change back to NotConnected */
161 hdd_conn_set_connection_state(adapter,
162 eConnectionState_NotConnected);
163 } else {
164 hddLog(LOG2, FL("sme_RoamConnect issued successfully for NDI"));
165 }
166
167 roam_profile->ChannelInfo.ChannelList = NULL;
168 roam_profile->ChannelInfo.numOfChannels = 0;
169
170 EXIT();
171
172 return ret;
173}
174
175
176/**
177 * hdd_ndi_create_req_handler() - NDI create request handler
178 * @hdd_ctx: hdd context
179 * @tb: parsed NL attribute list
180 *
181 * Return: 0 on success or error code on failure
182 */
183static int hdd_ndi_create_req_handler(hdd_context_t *hdd_ctx,
184 struct nlattr **tb)
185{
186 hdd_adapter_t *adapter;
187 char *iface_name;
188 uint16_t transaction_id;
189 int ret;
190 struct nan_datapath_ctx *ndp_ctx;
191 uint8_t op_channel =
192 hdd_ctx->config->nan_datapath_ndi_channel;
193
194 ENTER();
195
196 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700197 hdd_err(FL("Interface name string is unavailable"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700198 return -EINVAL;
199 }
200 iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]);
201
202 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700203 hdd_err(FL("transaction id is unavailable"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700204 return -EINVAL;
205 }
206 transaction_id =
207 nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]);
208
209 /* Check for an existing interface of NDI type */
210 adapter = hdd_get_adapter(hdd_ctx, QDF_NDI_MODE);
211 if (adapter) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700212 hdd_err(FL("Cannot support more than one NDI"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700213 return -EEXIST;
214 }
215
216 adapter = hdd_open_adapter(hdd_ctx, QDF_NDI_MODE, iface_name,
217 wlan_hdd_get_intf_addr(hdd_ctx), NET_NAME_UNKNOWN,
218 true);
219 if (!adapter) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700220 hdd_err(FL("hdd_open_adapter failed"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700221 return -ENOMEM;
222 }
223
224 /*
225 * Create transaction id is required to be saved since the firmware
226 * does not honor the transaction id for create request
227 */
228 ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
229 ndp_ctx->ndp_create_transaction_id = transaction_id;
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700230 ndp_ctx->state = NAN_DATA_NDI_CREATING_STATE;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700231
232 /*
233 * The NAN data interface has been created at this point.
234 * Unlike traditional device modes, where the higher application
235 * layer initiates connect / join / start, the NAN data interface
236 * does not have any such formal requests. The NDI create request
237 * is responsible for starting the BSS as well.
238 */
239 if (op_channel != NAN_SOCIAL_CHANNEL_2_4GHZ ||
240 op_channel != NAN_SOCIAL_CHANNEL_5GHZ_LOWER_BAND ||
241 op_channel != NAN_SOCIAL_CHANNEL_5GHZ_UPPER_BAND) {
242 /* start NDI on the default 2.4 GHz social channel */
243 op_channel = NAN_SOCIAL_CHANNEL_2_4GHZ;
244 }
245 ret = hdd_ndi_start_bss(adapter, op_channel);
246 if (0 > ret)
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700247 hdd_err(FL("NDI start bss failed"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700248
249 EXIT();
250 return ret;
251}
252
253/**
254 * hdd_ndi_delete_req_handler() - NDI delete request handler
255 * @hdd_ctx: hdd context
256 * @tb: parsed NL attribute list
257 *
258 * Return: 0 on success or error code on failure
259 */
260static int hdd_ndi_delete_req_handler(hdd_context_t *hdd_ctx,
261 struct nlattr **tb)
262{
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700263 hdd_adapter_t *adapter;
264 char *iface_name;
265 uint16_t transaction_id;
266 struct nan_datapath_ctx *ndp_ctx;
267 int ret;
268
269 ENTER();
270
271 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) {
272 hdd_err(FL("Interface name string is unavailable"));
273 return -EINVAL;
274 }
275
276 iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]);
277
278 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]) {
279 hdd_err(FL("Transaction id is unavailable"));
280 return -EINVAL;
281 }
282
283 transaction_id =
284 nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]);
285
286 /* Check if there is already an existing inteface with the same name */
287 adapter = hdd_get_adapter(hdd_ctx, QDF_NDI_MODE);
288 if (!adapter) {
289 hdd_err(FL("NAN data interface %s is not available"),
290 iface_name);
291 return -EINVAL;
292 }
293
294 /* check if adapter is in NDI mode */
295 if (QDF_NDI_MODE != adapter->device_mode) {
296 hdd_err(FL("Interface %s is not in NDI mode"),
297 iface_name);
298 return -EINVAL;
299 }
300
301 ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
302 if (!ndp_ctx) {
303 hdd_err(FL("ndp_ctx is NULL"));
304 return -EINVAL;
305 }
306
307 /* check if there are active NDP sessions on the adapter */
308 if (ndp_ctx->active_ndp_sessions > 0) {
309 hdd_err(FL("NDP sessions active %d, cannot delete NDI"),
310 ndp_ctx->active_ndp_sessions);
311 return -EINVAL;
312 }
313
314 ndp_ctx->ndp_delete_transaction_id = transaction_id;
315 ndp_ctx->state = NAN_DATA_NDI_DELETING_STATE;
316
317 /* Delete the interface */
318 ret = __wlan_hdd_del_virtual_intf(hdd_ctx->wiphy, &adapter->wdev);
319 if (ret < 0)
320 hdd_err(FL("NDI delete request failed"));
321 else
322 hdd_err(FL("NDI delete request successfully issued"));
323
324 return ret;
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700325}
326
327
328/**
329 * hdd_ndp_initiator_req_handler() - NDP initiator request handler
330 * @hdd_ctx: hdd context
331 * @tb: parsed NL attribute list
332 *
333 * Return: 0 on success or error code on failure
334 */
335static int hdd_ndp_initiator_req_handler(hdd_context_t *hdd_ctx,
336 struct nlattr **tb)
337{
338 return 0;
339}
340
341/**
342 * hdd_ndp_responder_req_handler() - NDP responder request handler
343 * @hdd_ctx: hdd context
344 * @tb: parsed NL attribute list
345 *
346 * Return: 0 on success or error code on failure
347 */
348static int hdd_ndp_responder_req_handler(hdd_context_t *hdd_ctx,
349 struct nlattr **tb)
350{
351 return 0;
352}
353
354/**
355 * hdd_ndp_end_req_handler() - NDP end request handler
356 * @hdd_ctx: hdd context
357 * @tb: parsed NL attribute list
358 *
359 * Return: 0 on success or error code on failure
360 */
361static int hdd_ndp_end_req_handler(hdd_context_t *hdd_ctx,
362 struct nlattr **tb)
363{
364 return 0;
365}
366
367/**
368 * hdd_ndp_schedule_req_handler() - NDP schedule request handler
369 * @hdd_ctx: hdd context
370 * @tb: parsed NL attribute list
371 *
372 * Return: 0 on success or error code on failure
373 */
374static int hdd_ndp_schedule_req_handler(hdd_context_t *hdd_ctx,
375 struct nlattr **tb)
376{
377 return 0;
378}
379
380
381/**
382 * hdd_ndp_iface_create_rsp_handler() - NDP iface create response handler
383 * @adapter: pointer to adapter context
384 * @rsp_params: response parameters
385 *
386 * The function is expected to send a response back to the user space
387 * even if the creation of BSS has failed
388 *
389 * Following vendor event is sent to cfg80211:
390 * QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD =
391 * QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE (4 bytes)
392 * QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID (2 bytes)
393 * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE (4 bytes)
394 * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE
395 *
396 * Return: none
397 */
398static void hdd_ndp_iface_create_rsp_handler(hdd_adapter_t *adapter,
399 void *rsp_params)
400{
401 struct sk_buff *vendor_event;
402 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
403 struct ndi_create_rsp *ndi_rsp = (struct ndi_create_rsp *)rsp_params;
404 uint32_t data_len = (3 * sizeof(uint32_t)) + sizeof(uint16_t) +
405 NLMSG_HDRLEN + (4 * NLA_HDRLEN);
406 struct nan_datapath_ctx *ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
407
408 ENTER();
409
410 if (wlan_hdd_validate_context(hdd_ctx))
411 return;
412
413 if (!ndi_rsp) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700414 hdd_err(FL("Invalid ndi create response"));
415 return;
416 }
417
418 if (!ndp_ctx) {
419 hdd_err(FL("ndp_ctx is NULL"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700420 return;
421 }
422
423 /* notify response to the upper layer */
424 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
425 NULL,
426 data_len,
427 QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX,
428 cds_get_gfp_flags());
429
430 if (!vendor_event) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700431 hdd_err(FL("cfg80211_vendor_event_alloc failed"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700432 return;
433 }
434
435 /* Sub vendor command */
436 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
437 QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE)) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700438 hdd_err(FL("QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD put fail"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700439 goto nla_put_failure;
440 }
441
442 /* Transaction id */
443 if (nla_put_u16(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
444 ndp_ctx->ndp_create_transaction_id)) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700445 hdd_err(FL("VENDOR_ATTR_NDP_TRANSACTION_ID put fail"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700446 goto nla_put_failure;
447 }
448
449 /* Status code */
450 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE,
451 ndi_rsp->status)) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700452 hdd_err(FL("VENDOR_ATTR_NDP_DRV_RETURN_TYPE put fail"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700453 goto nla_put_failure;
454 }
455
456 /* Status return value */
457 if (nla_put_u32(vendor_event,
458 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, 0xA5)) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700459 hdd_err(FL("VENDOR_ATTR_NDP_DRV_RETURN_VALUE put fail"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700460 goto nla_put_failure;
461 }
462
463 hddLog(LOG2, FL("sub command: %d, value: %d"),
464 QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX,
465 QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE);
466 hddLog(LOG2, FL("create transaction id: %d, value: %d"),
467 QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
468 ndp_ctx->ndp_create_transaction_id);
469 hddLog(LOG2, FL("status code: %d, value: %d"),
470 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE, ndi_rsp->status);
471 hddLog(LOG2, FL("Return value: %d, value: %d"),
472 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, 0xA5);
473
474 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
475
476 ndp_ctx->ndp_create_transaction_id = 0;
477
478 if (ndi_rsp->status == QDF_STATUS_SUCCESS) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700479 hdd_err(FL("NDI interface successfully created"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700480 } else {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700481 hdd_err(FL("NDI interface creation failed with reason %d"),
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700482 ndi_rsp->reason);
483 }
484 EXIT();
485 return;
486
487nla_put_failure:
488 kfree_skb(vendor_event);
489 return;
490}
491
492/**
493 * hdd_ndp_iface_delete_rsp_handler() - NDP iface delete response handler
494 * @adapter: pointer to adapter context
495 * @rsp_params: response parameters
496 *
497 * Return: none
498 */
499static void hdd_ndp_iface_delete_rsp_handler(hdd_adapter_t *adapter,
500 void *rsp_params)
501{
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700502 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
503 struct ndi_delete_rsp *ndi_rsp = rsp_params;
504
505 if (wlan_hdd_validate_context(hdd_ctx))
506 return;
507
508 if (!ndi_rsp) {
509 hdd_err(FL("Invalid ndi delete response"));
510 return;
511 }
512
513 if (ndi_rsp->status == QDF_STATUS_SUCCESS)
514 hdd_err(FL("NDI BSS successfully stopped"));
515 else
516 hdd_err(FL("NDI BSS stop failed with reason %d"),
517 ndi_rsp->reason);
518
519 complete(&adapter->disconnect_comp_var);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700520 return;
521}
522
523/**
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700524 * hdd_ndp_session_end_handler() - NDI session termination handler
525 * @adapter: pointer to adapter context
526 *
527 * Following vendor event is sent to cfg80211:
528 * QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD =
529 * QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE (4 bytes)
530 * QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID (2 bytes)
531 * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE (4 bytes)
532 * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE (4 bytes)
533 *
534 * Return: none
535 */
536void hdd_ndp_session_end_handler(hdd_adapter_t *adapter)
537{
538 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
539 struct sk_buff *vendor_event;
540 struct nan_datapath_ctx *ndp_ctx;
541 uint32_t data_len = sizeof(uint32_t) * (3 + sizeof(uint16_t)) +
542 (NLA_HDRLEN * 4) + NLMSG_HDRLEN;
543
544 ENTER();
545
546 if (wlan_hdd_validate_context(hdd_ctx))
547 return;
548
549 /* Handle only if adapter is in NDI mode */
550 if (QDF_NDI_MODE != adapter->device_mode) {
551 hdd_err(FL("Adapter is not in NDI mode"));
552 return;
553 }
554
555 ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
556 if (!ndp_ctx) {
557 hdd_err(FL("ndp context is NULL"));
558 return;
559 }
560
561 /*
562 * The virtual adapters are stopped and closed even during
563 * driver unload or stop, the service layer is not required
564 * to be informed in that case (response is not expected)
565 */
566 if (NAN_DATA_NDI_DELETING_STATE != ndp_ctx->state) {
567 hdd_err(FL("NDI interface %s deleted"),
568 adapter->dev->name);
569 return;
570 }
571
572 /* notify response to the upper layer */
573 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
574 NULL,
575 data_len,
576 QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX,
577 GFP_KERNEL);
578
579 if (!vendor_event) {
580 hdd_err(FL("cfg80211_vendor_event_alloc failed"));
581 return;
582 }
583
584 /* Sub vendor command goes first */
585 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
586 QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE)) {
587 hdd_err(FL("VENDOR_ATTR_NDP_SUBCMD put fail"));
588 goto failure;
589 }
590
591 /* Transaction id */
592 if (nla_put_u16(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
593 ndp_ctx->ndp_delete_transaction_id)) {
594 hdd_err(FL("VENDOR_ATTR_NDP_TRANSACTION_ID put fail"));
595 goto failure;
596 }
597
598 /* Status code */
599 if (nla_put_u32(vendor_event,
600 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE, 0x0)) {
601 hdd_err(FL("VENDOR_ATTR_NDP_DRV_RETURN_TYPE put fail"));
602 goto failure;
603 }
604
605 /* Status return value */
606 if (nla_put_u32(vendor_event,
607 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, 0x0)) {
608 hdd_err(FL("VENDOR_ATTR_NDP_DRV_RETURN_VALUE put fail"));
609 goto failure;
610 }
611
612 hddLog(LOG2, FL("sub command: %d, value: %d"),
613 QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
614 QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE);
615 hddLog(LOG2, FL("delete transaction id: %d, value: %d"),
616 QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
617 ndp_ctx->ndp_delete_transaction_id);
618 hddLog(LOG2, FL("status code: %d, value: %d"),
619 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE,
620 true);
621 hddLog(LOG2, FL("Return value: %d, value: %d"),
622 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, 0x5A);
623
624 ndp_ctx->ndp_delete_transaction_id = 0;
625 ndp_ctx->state = NAN_DATA_NDI_DELETED_STATE;
626
627 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
628
629 EXIT();
630 return;
631
632failure:
633 kfree_skb(vendor_event);
634}
635
636
637/**
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700638 * hdd_ndp_initiator_rsp_handler() - NDP initiator response handler
639 * @adapter: pointer to adapter context
640 * @rsp_params: response parameters
641 *
642 * Return: none
643 */
644static void hdd_ndp_initiator_rsp_handler(hdd_adapter_t *adapter,
645 void *rsp_params)
646{
647 return;
648}
649
650/**
651 * hdd_ndp_new_peer_ind_handler() - NDP new peer indication handler
652 * @adapter: pointer to adapter context
653 * @ind_params: indication parameters
654 *
655 * Return: none
656 */
657static void hdd_ndp_new_peer_ind_handler(hdd_adapter_t *adapter,
658 void *ind_params)
659{
660 return;
661}
662
663/**
664 * hdd_ndp_peer_departed_ind_handler() - NDP peer departed indication handler
665 * @adapter: pointer to adapter context
666 * @ind_params: indication parameters
667 *
668 * Return: none
669 */
670static void hdd_ndp_peer_departed_ind_handler(
671 hdd_adapter_t *adapter, void *ind_params)
672{
673 return;
674}
675
676/**
677 * hdd_ndp_confirm_ind_handler() - NDP confirm indication handler
678 * @adapter: pointer to adapter context
679 * @ind_params: indication parameters
680 *
681 * Return: none
682 */
683static void hdd_ndp_confirm_ind_handler(hdd_adapter_t *adapter,
684 void *ind_params)
685{
686 return;
687}
688
689/**
690 * hdd_ndp_indication_handler() - NDP indication handler
691 * @adapter: pointer to adapter context
692 * @ind_params: indication parameters
693 *
694 * Return: none
695 */
696static void hdd_ndp_indication_handler(hdd_adapter_t *adapter,
697 void *ind_params)
698{
699 return;
700}
701
702/**
703 * hdd_ndp_responder_rsp_handler() - NDP responder response handler
704 * @adapter: pointer to adapter context
705 * @rsp_params: response parameters
706 *
707 * Return: none
708 */
709static void hdd_ndp_responder_rsp_handler(hdd_adapter_t *adapter,
710 void *rsp_params)
711{
712 return;
713}
714
715/**
716 * hdd_ndp_end_rsp_handler() - NDP end response handler
717 * @adapter: pointer to adapter context
718 * @rsp_params: response parameters
719 *
720 * Return: none
721 */
722static void hdd_ndp_end_rsp_handler(hdd_adapter_t *adapter,
723 void *rsp_params)
724{
725 return;
726}
727
728/**
729 * hdd_ndp_end_ind_handler() - NDP end indication handler
730 * @adapter: pointer to adapter context
731 * @ind_params: indication parameters
732 *
733 * Return: none
734 */
735static void hdd_ndp_end_ind_handler(hdd_adapter_t *adapter,
736 void *ind_params)
737{
738 return;
739}
740
741/**
742 * hdd_ndp_schedule_update_rsp_handler() - NDP schedule update response handler
743 * @adapter: pointer to adapter context
744 * @rsp_params: response parameters
745 *
746 * Return: none
747 */
748static void hdd_ndp_schedule_update_rsp_handler(
749 hdd_adapter_t *adapter, void *rsp_params)
750{
751 return;
752}
753
754/**
755 * hdd_ndp_event_handler() - ndp response and indication handler
756 * @adapter: adapter context
757 * @roam_info: pointer to roam_info structure
758 * @roam_id: roam id as indicated by SME
759 * @roam_status: roam status
760 * @roam_result: roam result
761 *
762 * Return: none
763 */
764void hdd_ndp_event_handler(hdd_adapter_t *adapter,
765 tCsrRoamInfo *roam_info, uint32_t roam_id, eRoamCmdStatus roam_status,
766 eCsrRoamResult roam_result)
767{
768 if (roam_status == eCSR_ROAM_NDP_STATUS_UPDATE) {
769 switch (roam_result) {
770 case eCSR_ROAM_RESULT_NDP_CREATE_RSP:
771 hdd_ndp_iface_create_rsp_handler(adapter,
772 &roam_info->ndp.ndi_create_params);
773 break;
774 case eCSR_ROAM_RESULT_NDP_DELETE_RSP:
775 hdd_ndp_iface_delete_rsp_handler(adapter,
776 &roam_info->ndp.ndi_delete_params);
777 break;
778 case eCSR_ROAM_RESULT_NDP_INITIATOR_RSP:
779 hdd_ndp_initiator_rsp_handler(adapter,
780 &roam_info->ndp.ndp_init_rsp_params);
781 break;
782 case eCSR_ROAM_RESULT_NDP_NEW_PEER_IND:
783 hdd_ndp_new_peer_ind_handler(adapter,
784 &roam_info->ndp.ndp_peer_ind_params);
785 break;
786 case eCSR_ROAM_RESULT_NDP_CONFIRM_IND:
787 hdd_ndp_confirm_ind_handler(adapter,
788 &roam_info->ndp.ndp_confirm_params);
789 break;
790 case eCSR_ROAM_RESULT_NDP_INDICATION:
791 hdd_ndp_indication_handler(adapter,
792 &roam_info->ndp.ndp_indication_params);
793 break;
794 case eCSR_ROAM_RESULT_NDP_SCHED_UPDATE_RSP:
795 hdd_ndp_schedule_update_rsp_handler(adapter,
796 &roam_info->ndp.ndp_sched_upd_rsp_params);
797 break;
798 case eCSR_ROAM_RESULT_NDP_RESPONDER_RSP:
799 hdd_ndp_responder_rsp_handler(adapter,
800 &roam_info->ndp.ndp_responder_rsp_params);
801 break;
802 case eCSR_ROAM_RESULT_NDP_END_RSP:
803 hdd_ndp_end_rsp_handler(adapter,
804 &roam_info->ndp.ndp_end_rsp_params);
805 break;
806 case eCSR_ROAM_RESULT_NDP_PEER_DEPARTED_IND:
807 hdd_ndp_peer_departed_ind_handler(adapter,
808 &roam_info->ndp.ndp_peer_ind_params);
809 break;
810 case eCSR_ROAM_RESULT_NDP_END_IND:
811 hdd_ndp_end_ind_handler(adapter,
812 &roam_info->ndp.ndp_end_ind_params);
813 break;
814 default:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700815 hdd_err(FL("Unknown NDP response event from SME %d"),
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700816 roam_result);
817 break;
818 }
819 }
820}
821
822/**
823 * __wlan_hdd_cfg80211_process_ndp_cmds() - handle NDP request
824 * @wiphy: pointer to wireless wiphy structure.
825 * @wdev: pointer to wireless_dev structure.
826 * @data: Pointer to the data to be passed via vendor interface
827 * @data_len:Length of the data to be passed
828 *
829 * This function is invoked to handle vendor command
830 *
831 * Return: 0 on success, negative errno on failure
832 */
833static int __wlan_hdd_cfg80211_process_ndp_cmd(struct wiphy *wiphy,
834 struct wireless_dev *wdev, const void *data, int data_len)
835{
836 uint32_t ndp_cmd_type;
837 uint16_t transaction_id;
838 int ret_val;
839 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
840 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX + 1];
841 char *iface_name;
842
843 ENTER();
844
845 ret_val = wlan_hdd_validate_context(hdd_ctx);
846 if (ret_val)
847 return ret_val;
848
849 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700850 hdd_err(FL("Command not allowed in FTM mode"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700851 return -EPERM;
852 }
Deepak Dhamdhere7e6016f2016-06-01 09:37:37 -0700853 if (!WLAN_HDD_IS_NDP_ENABLED(hdd_ctx)) {
854 hdd_err(FL("NAN datapath is not enabled"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700855 return -EPERM;
856 }
857 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX,
858 data, data_len,
859 qca_wlan_vendor_ndp_policy)) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700860 hdd_err(FL("Invalid NDP vendor command attributes"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700861 return -EINVAL;
862 }
863
864 /* Parse and fetch NDP Command Type*/
865 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD]) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700866 hdd_err(FL("NAN datapath cmd type failed"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700867 return -EINVAL;
868 }
869 ndp_cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD]);
870
871 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700872 hdd_err(FL("attr transaction id failed"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700873 return -EINVAL;
874 }
875 transaction_id = nla_get_u16(
876 tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]);
877
878 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700879 hdd_err(FL("Interface name string is unavailable"));
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700880 return -EINVAL;
881 }
882 iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]);
883
884 hddLog(LOG2, FL("Transaction Id: %d NDP Cmd: %d iface_name: %s"),
885 transaction_id, ndp_cmd_type, iface_name);
886
887 switch (ndp_cmd_type) {
888 case QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE:
889 ret_val = hdd_ndi_create_req_handler(hdd_ctx, tb);
890 break;
891 case QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE:
892 ret_val = hdd_ndi_delete_req_handler(hdd_ctx, tb);
893 break;
894 case QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_REQUEST:
895 ret_val = hdd_ndp_initiator_req_handler(hdd_ctx, tb);
896 break;
897 case QCA_WLAN_VENDOR_ATTR_NDP_RESPONDER_REQUEST:
898 ret_val = hdd_ndp_responder_req_handler(hdd_ctx, tb);
899 break;
900 case QCA_WLAN_VENDOR_ATTR_NDP_END_REQUEST:
901 ret_val = hdd_ndp_end_req_handler(hdd_ctx, tb);
902 break;
903 case QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_REQUEST:
904 ret_val = hdd_ndp_schedule_req_handler(hdd_ctx, tb);
905 break;
906 default:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700907 hdd_err(FL("Unrecognized NDP vendor cmd %d"),
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700908 ndp_cmd_type);
909 ret_val = -EINVAL;
910 break;
911 }
912
913 return ret_val;
914}
915
916/**
917 * wlan_hdd_cfg80211_process_ndp_cmd() - handle NDP request
918 * @wiphy: pointer to wireless wiphy structure.
919 * @wdev: pointer to wireless_dev structure.
920 * @data: Pointer to the data to be passed via vendor interface
921 * @data_len:Length of the data to be passed
922 *
923 * This function is called to send a NAN request to
924 * firmware. This is an SSR-protected wrapper function.
925 *
926 * Return: 0 on success, negative errno on failure
927 */
928int wlan_hdd_cfg80211_process_ndp_cmd(struct wiphy *wiphy,
929 struct wireless_dev *wdev, const void *data, int data_len)
930{
931 int ret;
932
933 cds_ssr_protect(__func__);
934 ret = __wlan_hdd_cfg80211_process_ndp_cmd(wiphy, wdev, data, data_len);
935 cds_ssr_unprotect(__func__);
936
937 return ret;
938}
939
940/**
941 * hdd_init_nan_data_mode() - initialize nan data mode
942 * @adapter: adapter context
943 *
944 * Returns: 0 on success negative error code on error
945 */
946int hdd_init_nan_data_mode(struct hdd_adapter_s *adapter)
947{
948 struct net_device *wlan_dev = adapter->dev;
949 struct nan_datapath_ctx *ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
950 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
951 QDF_STATUS status;
952 uint32_t type, sub_type;
953 int32_t ret_val = 0;
954 unsigned long rc;
955 uint32_t timeout = WLAN_WAIT_TIME_SESSIONOPENCLOSE;
956
957 INIT_COMPLETION(adapter->session_open_comp_var);
958 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
959 status = cds_get_vdev_types(adapter->device_mode, &type, &sub_type);
960 if (QDF_STATUS_SUCCESS != status) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700961 hdd_err("failed to get vdev type");
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700962 goto error_sme_open;
963 }
964
965 /* open sme session for future use */
966 status = sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback,
967 adapter, (uint8_t *)&adapter->macAddressCurrent,
968 &adapter->sessionId, type, sub_type);
969 if (QDF_STATUS_SUCCESS == status) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700970 hdd_err("sme_open_session() failed with status code %d",
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700971 status);
972 ret_val = -EAGAIN;
973 goto error_sme_open;
974 }
975
976 /* Block on a completion variable. Can't wait forever though */
977 rc = wait_for_completion_timeout(
978 &adapter->session_open_comp_var,
979 msecs_to_jiffies(timeout));
980 if (!rc) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700981 hdd_err(
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700982 FL("Failed to open session, timeout code: %ld"), rc);
983 ret_val = -ETIMEDOUT;
984 goto error_sme_open;
985 }
986
987 /* Register wireless extensions */
988 ret_val = hdd_register_wext(wlan_dev);
989 if (0 > ret_val) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700990 hdd_err(FL("Wext registration failed with status code %d"),
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700991 ret_val);
992 ret_val = -EAGAIN;
993 goto error_register_wext;
994 }
995
996 status = hdd_init_tx_rx(adapter);
997 if (QDF_STATUS_SUCCESS != status) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -0700998 hdd_err(FL("hdd_init_tx_rx() init failed, status %d"),
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700999 status);
1000 ret_val = -EAGAIN;
1001 goto error_init_txrx;
1002 }
1003
1004 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
1005
1006 status = hdd_wmm_adapter_init(adapter);
1007 if (QDF_STATUS_SUCCESS != status) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07001008 hdd_err(FL("hdd_wmm_adapter_init() failed, status %d"),
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001009 status);
1010 ret_val = -EAGAIN;
1011 goto error_wmm_init;
1012 }
1013
1014 set_bit(WMM_INIT_DONE, &adapter->event_flags);
1015
1016 ret_val = wma_cli_set_command((int)adapter->sessionId,
1017 (int)WMI_PDEV_PARAM_BURST_ENABLE,
1018 (int)hdd_ctx->config->enableSifsBurst,
1019 PDEV_CMD);
1020 if (0 != ret_val) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07001021 hdd_err(FL("WMI_PDEV_PARAM_BURST_ENABLE set failed %d"),
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001022 ret_val);
1023 }
1024
1025 ndp_ctx->state = NAN_DATA_NDI_CREATING_STATE;
1026 return ret_val;
1027
1028error_wmm_init:
1029 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
1030 hdd_deinit_tx_rx(adapter);
1031
1032error_init_txrx:
1033 hdd_unregister_wext(wlan_dev);
1034
1035error_register_wext:
1036 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
1037 INIT_COMPLETION(adapter->session_close_comp_var);
1038 if (QDF_STATUS_SUCCESS ==
1039 sme_close_session(hdd_ctx->hHal,
1040 adapter->sessionId,
1041 hdd_sme_close_session_callback,
1042 adapter)) {
1043 rc = wait_for_completion_timeout(
1044 &adapter->session_close_comp_var,
1045 msecs_to_jiffies(timeout));
1046 if (rc <= 0) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07001047 hdd_err(FL("Session close failed status %ld"),
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001048 rc);
1049 ret_val = -ETIMEDOUT;
1050 }
1051 }
1052 }
1053
1054error_sme_open:
1055 return ret_val;
1056}