blob: 71fbce17c05cd2c8fd0886c35df3685747d822ba [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 Dhamdhere5cdce842016-05-31 10:39:12 -070026#include <linux/if.h>
27#include <linux/netdevice.h>
28#include <linux/skbuff.h>
29#include <linux/etherdevice.h>
30#include "wlan_hdd_includes.h"
Ravi Joshia063dd92016-05-25 16:43:13 -070031#include "wlan_hdd_nan_datapath.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 Dhamdhere5cdce842016-05-31 10:39:12 -070081 * NAN datapath functinality is enabled if it is enabled in
82 * .ini file and also supported in firmware.
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) {
113 hddLog(LOGE, FL("No valid roam profile"));
114 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) {
156 hddLog(LOGE,
157 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]) {
196 hddLog(LOGE, FL("Interface name string is unavailable"));
197 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]) {
202 hddLog(LOGE, FL("transaction id is unavailable"));
203 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) {
211 hddLog(LOGE, FL("Cannot support more than one NDI"));
212 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) {
219 hddLog(LOGE, FL("hdd_open_adapter failed"));
220 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;
229
230 /*
231 * The NAN data interface has been created at this point.
232 * Unlike traditional device modes, where the higher application
233 * layer initiates connect / join / start, the NAN data interface
234 * does not have any such formal requests. The NDI create request
235 * is responsible for starting the BSS as well.
236 */
237 if (op_channel != NAN_SOCIAL_CHANNEL_2_4GHZ ||
238 op_channel != NAN_SOCIAL_CHANNEL_5GHZ_LOWER_BAND ||
239 op_channel != NAN_SOCIAL_CHANNEL_5GHZ_UPPER_BAND) {
240 /* start NDI on the default 2.4 GHz social channel */
241 op_channel = NAN_SOCIAL_CHANNEL_2_4GHZ;
242 }
243 ret = hdd_ndi_start_bss(adapter, op_channel);
244 if (0 > ret)
245 hddLog(LOGE, FL("NDI start bss failed"));
246
247 EXIT();
248 return ret;
249}
250
251/**
252 * hdd_ndi_delete_req_handler() - NDI delete request handler
253 * @hdd_ctx: hdd context
254 * @tb: parsed NL attribute list
255 *
256 * Return: 0 on success or error code on failure
257 */
258static int hdd_ndi_delete_req_handler(hdd_context_t *hdd_ctx,
259 struct nlattr **tb)
260{
261 return 0;
262}
263
264
265/**
266 * hdd_ndp_initiator_req_handler() - NDP initiator request handler
267 * @hdd_ctx: hdd context
268 * @tb: parsed NL attribute list
269 *
270 * Return: 0 on success or error code on failure
271 */
272static int hdd_ndp_initiator_req_handler(hdd_context_t *hdd_ctx,
273 struct nlattr **tb)
274{
275 return 0;
276}
277
278/**
279 * hdd_ndp_responder_req_handler() - NDP responder request handler
280 * @hdd_ctx: hdd context
281 * @tb: parsed NL attribute list
282 *
283 * Return: 0 on success or error code on failure
284 */
285static int hdd_ndp_responder_req_handler(hdd_context_t *hdd_ctx,
286 struct nlattr **tb)
287{
288 return 0;
289}
290
291/**
292 * hdd_ndp_end_req_handler() - NDP end request handler
293 * @hdd_ctx: hdd context
294 * @tb: parsed NL attribute list
295 *
296 * Return: 0 on success or error code on failure
297 */
298static int hdd_ndp_end_req_handler(hdd_context_t *hdd_ctx,
299 struct nlattr **tb)
300{
301 return 0;
302}
303
304/**
305 * hdd_ndp_schedule_req_handler() - NDP schedule request handler
306 * @hdd_ctx: hdd context
307 * @tb: parsed NL attribute list
308 *
309 * Return: 0 on success or error code on failure
310 */
311static int hdd_ndp_schedule_req_handler(hdd_context_t *hdd_ctx,
312 struct nlattr **tb)
313{
314 return 0;
315}
316
317
318/**
319 * hdd_ndp_iface_create_rsp_handler() - NDP iface create response handler
320 * @adapter: pointer to adapter context
321 * @rsp_params: response parameters
322 *
323 * The function is expected to send a response back to the user space
324 * even if the creation of BSS has failed
325 *
326 * Following vendor event is sent to cfg80211:
327 * QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD =
328 * QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE (4 bytes)
329 * QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID (2 bytes)
330 * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE (4 bytes)
331 * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE
332 *
333 * Return: none
334 */
335static void hdd_ndp_iface_create_rsp_handler(hdd_adapter_t *adapter,
336 void *rsp_params)
337{
338 struct sk_buff *vendor_event;
339 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
340 struct ndi_create_rsp *ndi_rsp = (struct ndi_create_rsp *)rsp_params;
341 uint32_t data_len = (3 * sizeof(uint32_t)) + sizeof(uint16_t) +
342 NLMSG_HDRLEN + (4 * NLA_HDRLEN);
343 struct nan_datapath_ctx *ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
344
345 ENTER();
346
347 if (wlan_hdd_validate_context(hdd_ctx))
348 return;
349
350 if (!ndi_rsp) {
351 hddLog(LOGE, FL("Invalid ndi create response"));
352 return;
353 }
354
355 /* notify response to the upper layer */
356 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
357 NULL,
358 data_len,
359 QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX,
360 cds_get_gfp_flags());
361
362 if (!vendor_event) {
363 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
364 return;
365 }
366
367 /* Sub vendor command */
368 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
369 QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE)) {
370 hddLog(LOGE, FL("QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD put fail"));
371 goto nla_put_failure;
372 }
373
374 /* Transaction id */
375 if (nla_put_u16(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
376 ndp_ctx->ndp_create_transaction_id)) {
377 hddLog(LOGE, FL("VENDOR_ATTR_NDP_TRANSACTION_ID put fail"));
378 goto nla_put_failure;
379 }
380
381 /* Status code */
382 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE,
383 ndi_rsp->status)) {
384 hddLog(LOGE, FL("VENDOR_ATTR_NDP_DRV_RETURN_TYPE put fail"));
385 goto nla_put_failure;
386 }
387
388 /* Status return value */
389 if (nla_put_u32(vendor_event,
390 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, 0xA5)) {
391 hddLog(LOGE, FL("VENDOR_ATTR_NDP_DRV_RETURN_VALUE put fail"));
392 goto nla_put_failure;
393 }
394
395 hddLog(LOG2, FL("sub command: %d, value: %d"),
396 QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX,
397 QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE);
398 hddLog(LOG2, FL("create transaction id: %d, value: %d"),
399 QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
400 ndp_ctx->ndp_create_transaction_id);
401 hddLog(LOG2, FL("status code: %d, value: %d"),
402 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE, ndi_rsp->status);
403 hddLog(LOG2, FL("Return value: %d, value: %d"),
404 QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, 0xA5);
405
406 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
407
408 ndp_ctx->ndp_create_transaction_id = 0;
409
410 if (ndi_rsp->status == QDF_STATUS_SUCCESS) {
411 hddLog(LOGE, FL("NDI interface successfully created"));
412 } else {
413 hddLog(LOGE,
414 FL("NDI interface creation failed with reason %d"),
415 ndi_rsp->reason);
416 }
417 EXIT();
418 return;
419
420nla_put_failure:
421 kfree_skb(vendor_event);
422 return;
423}
424
425/**
426 * hdd_ndp_iface_delete_rsp_handler() - NDP iface delete response handler
427 * @adapter: pointer to adapter context
428 * @rsp_params: response parameters
429 *
430 * Return: none
431 */
432static void hdd_ndp_iface_delete_rsp_handler(hdd_adapter_t *adapter,
433 void *rsp_params)
434{
435 return;
436}
437
438/**
439 * hdd_ndp_initiator_rsp_handler() - NDP initiator response handler
440 * @adapter: pointer to adapter context
441 * @rsp_params: response parameters
442 *
443 * Return: none
444 */
445static void hdd_ndp_initiator_rsp_handler(hdd_adapter_t *adapter,
446 void *rsp_params)
447{
448 return;
449}
450
451/**
452 * hdd_ndp_new_peer_ind_handler() - NDP new peer indication handler
453 * @adapter: pointer to adapter context
454 * @ind_params: indication parameters
455 *
456 * Return: none
457 */
458static void hdd_ndp_new_peer_ind_handler(hdd_adapter_t *adapter,
459 void *ind_params)
460{
461 return;
462}
463
464/**
465 * hdd_ndp_peer_departed_ind_handler() - NDP peer departed indication handler
466 * @adapter: pointer to adapter context
467 * @ind_params: indication parameters
468 *
469 * Return: none
470 */
471static void hdd_ndp_peer_departed_ind_handler(
472 hdd_adapter_t *adapter, void *ind_params)
473{
474 return;
475}
476
477/**
478 * hdd_ndp_confirm_ind_handler() - NDP confirm indication handler
479 * @adapter: pointer to adapter context
480 * @ind_params: indication parameters
481 *
482 * Return: none
483 */
484static void hdd_ndp_confirm_ind_handler(hdd_adapter_t *adapter,
485 void *ind_params)
486{
487 return;
488}
489
490/**
491 * hdd_ndp_indication_handler() - NDP indication handler
492 * @adapter: pointer to adapter context
493 * @ind_params: indication parameters
494 *
495 * Return: none
496 */
497static void hdd_ndp_indication_handler(hdd_adapter_t *adapter,
498 void *ind_params)
499{
500 return;
501}
502
503/**
504 * hdd_ndp_responder_rsp_handler() - NDP responder response handler
505 * @adapter: pointer to adapter context
506 * @rsp_params: response parameters
507 *
508 * Return: none
509 */
510static void hdd_ndp_responder_rsp_handler(hdd_adapter_t *adapter,
511 void *rsp_params)
512{
513 return;
514}
515
516/**
517 * hdd_ndp_end_rsp_handler() - NDP end response handler
518 * @adapter: pointer to adapter context
519 * @rsp_params: response parameters
520 *
521 * Return: none
522 */
523static void hdd_ndp_end_rsp_handler(hdd_adapter_t *adapter,
524 void *rsp_params)
525{
526 return;
527}
528
529/**
530 * hdd_ndp_end_ind_handler() - NDP end indication handler
531 * @adapter: pointer to adapter context
532 * @ind_params: indication parameters
533 *
534 * Return: none
535 */
536static void hdd_ndp_end_ind_handler(hdd_adapter_t *adapter,
537 void *ind_params)
538{
539 return;
540}
541
542/**
543 * hdd_ndp_schedule_update_rsp_handler() - NDP schedule update response handler
544 * @adapter: pointer to adapter context
545 * @rsp_params: response parameters
546 *
547 * Return: none
548 */
549static void hdd_ndp_schedule_update_rsp_handler(
550 hdd_adapter_t *adapter, void *rsp_params)
551{
552 return;
553}
554
555/**
556 * hdd_ndp_event_handler() - ndp response and indication handler
557 * @adapter: adapter context
558 * @roam_info: pointer to roam_info structure
559 * @roam_id: roam id as indicated by SME
560 * @roam_status: roam status
561 * @roam_result: roam result
562 *
563 * Return: none
564 */
565void hdd_ndp_event_handler(hdd_adapter_t *adapter,
566 tCsrRoamInfo *roam_info, uint32_t roam_id, eRoamCmdStatus roam_status,
567 eCsrRoamResult roam_result)
568{
569 if (roam_status == eCSR_ROAM_NDP_STATUS_UPDATE) {
570 switch (roam_result) {
571 case eCSR_ROAM_RESULT_NDP_CREATE_RSP:
572 hdd_ndp_iface_create_rsp_handler(adapter,
573 &roam_info->ndp.ndi_create_params);
574 break;
575 case eCSR_ROAM_RESULT_NDP_DELETE_RSP:
576 hdd_ndp_iface_delete_rsp_handler(adapter,
577 &roam_info->ndp.ndi_delete_params);
578 break;
579 case eCSR_ROAM_RESULT_NDP_INITIATOR_RSP:
580 hdd_ndp_initiator_rsp_handler(adapter,
581 &roam_info->ndp.ndp_init_rsp_params);
582 break;
583 case eCSR_ROAM_RESULT_NDP_NEW_PEER_IND:
584 hdd_ndp_new_peer_ind_handler(adapter,
585 &roam_info->ndp.ndp_peer_ind_params);
586 break;
587 case eCSR_ROAM_RESULT_NDP_CONFIRM_IND:
588 hdd_ndp_confirm_ind_handler(adapter,
589 &roam_info->ndp.ndp_confirm_params);
590 break;
591 case eCSR_ROAM_RESULT_NDP_INDICATION:
592 hdd_ndp_indication_handler(adapter,
593 &roam_info->ndp.ndp_indication_params);
594 break;
595 case eCSR_ROAM_RESULT_NDP_SCHED_UPDATE_RSP:
596 hdd_ndp_schedule_update_rsp_handler(adapter,
597 &roam_info->ndp.ndp_sched_upd_rsp_params);
598 break;
599 case eCSR_ROAM_RESULT_NDP_RESPONDER_RSP:
600 hdd_ndp_responder_rsp_handler(adapter,
601 &roam_info->ndp.ndp_responder_rsp_params);
602 break;
603 case eCSR_ROAM_RESULT_NDP_END_RSP:
604 hdd_ndp_end_rsp_handler(adapter,
605 &roam_info->ndp.ndp_end_rsp_params);
606 break;
607 case eCSR_ROAM_RESULT_NDP_PEER_DEPARTED_IND:
608 hdd_ndp_peer_departed_ind_handler(adapter,
609 &roam_info->ndp.ndp_peer_ind_params);
610 break;
611 case eCSR_ROAM_RESULT_NDP_END_IND:
612 hdd_ndp_end_ind_handler(adapter,
613 &roam_info->ndp.ndp_end_ind_params);
614 break;
615 default:
616 hddLog(LOGE,
617 FL("Unknown NDP response event from SME %d"),
618 roam_result);
619 break;
620 }
621 }
622}
623
624/**
625 * __wlan_hdd_cfg80211_process_ndp_cmds() - handle NDP request
626 * @wiphy: pointer to wireless wiphy structure.
627 * @wdev: pointer to wireless_dev structure.
628 * @data: Pointer to the data to be passed via vendor interface
629 * @data_len:Length of the data to be passed
630 *
631 * This function is invoked to handle vendor command
632 *
633 * Return: 0 on success, negative errno on failure
634 */
635static int __wlan_hdd_cfg80211_process_ndp_cmd(struct wiphy *wiphy,
636 struct wireless_dev *wdev, const void *data, int data_len)
637{
638 uint32_t ndp_cmd_type;
639 uint16_t transaction_id;
640 int ret_val;
641 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
642 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX + 1];
643 char *iface_name;
644
645 ENTER();
646
647 ret_val = wlan_hdd_validate_context(hdd_ctx);
648 if (ret_val)
649 return ret_val;
650
651 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
652 hddLog(LOGE, FL("Command not allowed in FTM mode"));
653 return -EPERM;
654 }
655 if (!hdd_ctx->config->enable_nan_datapath) {
656 hddLog(LOGE, FL("NAN datapath is not suported"));
657 return -EPERM;
658 }
659 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX,
660 data, data_len,
661 qca_wlan_vendor_ndp_policy)) {
662 hddLog(LOGE, FL("Invalid NDP vendor command attributes"));
663 return -EINVAL;
664 }
665
666 /* Parse and fetch NDP Command Type*/
667 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD]) {
668 hddLog(LOGE, FL("NAN datapath cmd type failed"));
669 return -EINVAL;
670 }
671 ndp_cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD]);
672
673 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]) {
674 hddLog(LOGE, FL("attr transaction id failed"));
675 return -EINVAL;
676 }
677 transaction_id = nla_get_u16(
678 tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]);
679
680 if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) {
681 hddLog(LOGE, FL("Interface name string is unavailable"));
682 return -EINVAL;
683 }
684 iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]);
685
686 hddLog(LOG2, FL("Transaction Id: %d NDP Cmd: %d iface_name: %s"),
687 transaction_id, ndp_cmd_type, iface_name);
688
689 switch (ndp_cmd_type) {
690 case QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE:
691 ret_val = hdd_ndi_create_req_handler(hdd_ctx, tb);
692 break;
693 case QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE:
694 ret_val = hdd_ndi_delete_req_handler(hdd_ctx, tb);
695 break;
696 case QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_REQUEST:
697 ret_val = hdd_ndp_initiator_req_handler(hdd_ctx, tb);
698 break;
699 case QCA_WLAN_VENDOR_ATTR_NDP_RESPONDER_REQUEST:
700 ret_val = hdd_ndp_responder_req_handler(hdd_ctx, tb);
701 break;
702 case QCA_WLAN_VENDOR_ATTR_NDP_END_REQUEST:
703 ret_val = hdd_ndp_end_req_handler(hdd_ctx, tb);
704 break;
705 case QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_REQUEST:
706 ret_val = hdd_ndp_schedule_req_handler(hdd_ctx, tb);
707 break;
708 default:
709 hddLog(LOGE, FL("Unrecognized NDP vendor cmd %d"),
710 ndp_cmd_type);
711 ret_val = -EINVAL;
712 break;
713 }
714
715 return ret_val;
716}
717
718/**
719 * wlan_hdd_cfg80211_process_ndp_cmd() - handle NDP request
720 * @wiphy: pointer to wireless wiphy structure.
721 * @wdev: pointer to wireless_dev structure.
722 * @data: Pointer to the data to be passed via vendor interface
723 * @data_len:Length of the data to be passed
724 *
725 * This function is called to send a NAN request to
726 * firmware. This is an SSR-protected wrapper function.
727 *
728 * Return: 0 on success, negative errno on failure
729 */
730int wlan_hdd_cfg80211_process_ndp_cmd(struct wiphy *wiphy,
731 struct wireless_dev *wdev, const void *data, int data_len)
732{
733 int ret;
734
735 cds_ssr_protect(__func__);
736 ret = __wlan_hdd_cfg80211_process_ndp_cmd(wiphy, wdev, data, data_len);
737 cds_ssr_unprotect(__func__);
738
739 return ret;
740}
741
742/**
743 * hdd_init_nan_data_mode() - initialize nan data mode
744 * @adapter: adapter context
745 *
746 * Returns: 0 on success negative error code on error
747 */
748int hdd_init_nan_data_mode(struct hdd_adapter_s *adapter)
749{
750 struct net_device *wlan_dev = adapter->dev;
751 struct nan_datapath_ctx *ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
752 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
753 QDF_STATUS status;
754 uint32_t type, sub_type;
755 int32_t ret_val = 0;
756 unsigned long rc;
757 uint32_t timeout = WLAN_WAIT_TIME_SESSIONOPENCLOSE;
758
759 INIT_COMPLETION(adapter->session_open_comp_var);
760 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
761 status = cds_get_vdev_types(adapter->device_mode, &type, &sub_type);
762 if (QDF_STATUS_SUCCESS != status) {
763 hddLog(LOGE, "failed to get vdev type");
764 goto error_sme_open;
765 }
766
767 /* open sme session for future use */
768 status = sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback,
769 adapter, (uint8_t *)&adapter->macAddressCurrent,
770 &adapter->sessionId, type, sub_type);
771 if (QDF_STATUS_SUCCESS == status) {
772 hddLog(LOGE, "sme_open_session() failed with status code %d",
773 status);
774 ret_val = -EAGAIN;
775 goto error_sme_open;
776 }
777
778 /* Block on a completion variable. Can't wait forever though */
779 rc = wait_for_completion_timeout(
780 &adapter->session_open_comp_var,
781 msecs_to_jiffies(timeout));
782 if (!rc) {
783 hddLog(LOGE,
784 FL("Failed to open session, timeout code: %ld"), rc);
785 ret_val = -ETIMEDOUT;
786 goto error_sme_open;
787 }
788
789 /* Register wireless extensions */
790 ret_val = hdd_register_wext(wlan_dev);
791 if (0 > ret_val) {
792 hddLog(LOGE, FL("Wext registration failed with status code %d"),
793 ret_val);
794 ret_val = -EAGAIN;
795 goto error_register_wext;
796 }
797
798 status = hdd_init_tx_rx(adapter);
799 if (QDF_STATUS_SUCCESS != status) {
800 hddLog(LOGE, FL("hdd_init_tx_rx() init failed, status %d"),
801 status);
802 ret_val = -EAGAIN;
803 goto error_init_txrx;
804 }
805
806 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
807
808 status = hdd_wmm_adapter_init(adapter);
809 if (QDF_STATUS_SUCCESS != status) {
810 hddLog(LOGE, FL("hdd_wmm_adapter_init() failed, status %d"),
811 status);
812 ret_val = -EAGAIN;
813 goto error_wmm_init;
814 }
815
816 set_bit(WMM_INIT_DONE, &adapter->event_flags);
817
818 ret_val = wma_cli_set_command((int)adapter->sessionId,
819 (int)WMI_PDEV_PARAM_BURST_ENABLE,
820 (int)hdd_ctx->config->enableSifsBurst,
821 PDEV_CMD);
822 if (0 != ret_val) {
823 hddLog(LOGE, FL("WMI_PDEV_PARAM_BURST_ENABLE set failed %d"),
824 ret_val);
825 }
826
827 ndp_ctx->state = NAN_DATA_NDI_CREATING_STATE;
828 return ret_val;
829
830error_wmm_init:
831 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
832 hdd_deinit_tx_rx(adapter);
833
834error_init_txrx:
835 hdd_unregister_wext(wlan_dev);
836
837error_register_wext:
838 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
839 INIT_COMPLETION(adapter->session_close_comp_var);
840 if (QDF_STATUS_SUCCESS ==
841 sme_close_session(hdd_ctx->hHal,
842 adapter->sessionId,
843 hdd_sme_close_session_callback,
844 adapter)) {
845 rc = wait_for_completion_timeout(
846 &adapter->session_close_comp_var,
847 msecs_to_jiffies(timeout));
848 if (rc <= 0) {
849 hddLog(LOGE,
850 FL("Session close failed status %ld"),
851 rc);
852 ret_val = -ETIMEDOUT;
853 }
854 }
855 }
856
857error_sme_open:
858 return ret_val;
859}