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