blob: 8b270fd8beb510016072183712bb2fc57358a7b5 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002 * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wma_scan_roam.c
30 * This file contains functions related to scan and
31 * roaming functionality.
32 */
33
34/* Header files */
35
36#include "wma.h"
37#include "wma_api.h"
38#include "cds_api.h"
39#include "wmi_unified_api.h"
40#include "wlan_qct_sys.h"
41#include "wni_api.h"
42#include "ani_global.h"
43#include "wmi_unified.h"
44#include "wni_cfg.h"
45#include "cfg_api.h"
46#include "ol_txrx_ctrl_api.h"
47#include "wlan_tgt_def_config.h"
48
Nirav Shahcbc6d722016-03-01 16:24:53 +053049#include "qdf_nbuf.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053050#include "qdf_types.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080051#include "ol_txrx_api.h"
Anurag Chouhan600c3a02016-03-01 10:33:54 +053052#include "qdf_mem.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "ol_txrx_types.h"
54#include "ol_txrx_peer_find.h"
55
56#include "wma_types.h"
57#include "lim_api.h"
58#include "lim_session_utils.h"
59
60#include "cds_utils.h"
61
62#if !defined(REMOVE_PKT_LOG)
63#include "pktlog_ac.h"
64#endif /* REMOVE_PKT_LOG */
65
66#include "dbglog_host.h"
67/* FIXME: Inclusion of .c looks odd but this is how it is in internal codebase */
68#include "csr_api.h"
69#include "ol_fw.h"
70
71#include "dfs.h"
72#include "wma_internal.h"
73
74#define WMA_MCC_MIRACAST_REST_TIME 400
75#define WMA_SCAN_ID_MASK 0x0fff
76
77#ifdef FEATURE_WLAN_EXTSCAN
78/**
79 * enum extscan_report_events_type - extscan report events type
80 * @EXTSCAN_REPORT_EVENTS_BUFFER_FULL: report only when scan history is % full
81 * @EXTSCAN_REPORT_EVENTS_EACH_SCAN: report a scan completion event after scan
82 * @EXTSCAN_REPORT_EVENTS_FULL_RESULTS: forward scan results
83 * (beacons/probe responses + IEs)
84 * in real time to HAL, in addition to completion events.
85 * Note: To keep backward compatibility,
86 * fire completion events regardless of REPORT_EVENTS_EACH_SCAN.
87 * @EXTSCAN_REPORT_EVENTS_NO_BATCH: controls batching,
88 * 0 => batching, 1 => no batching
89 */
90enum extscan_report_events_type {
91 EXTSCAN_REPORT_EVENTS_BUFFER_FULL = 0x00,
92 EXTSCAN_REPORT_EVENTS_EACH_SCAN = 0x01,
93 EXTSCAN_REPORT_EVENTS_FULL_RESULTS = 0x02,
94 EXTSCAN_REPORT_EVENTS_NO_BATCH = 0x04,
95};
96
97#define WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION (5 * 1000) /* in msec */
98#endif
99
100/**
101 * wma_set_p2p_scan_info() - set p2p scan info in wma handle
102 * @wma_handle: wma handle
103 * @scan_id: scan id
104 * @vdev_id: vdev id
105 * @p2p_scan_type: p2p scan type
106 *
107 * Return: none
108 */
109static inline void wma_set_p2p_scan_info(tp_wma_handle wma_handle,
110 uint32_t scan_id,
111 uint32_t vdev_id,
112 tSirP2pScanType p2p_scan_type)
113{
114 wma_handle->interfaces[vdev_id].p2p_scan_info.scan_id = scan_id;
115 wma_handle->interfaces[vdev_id].p2p_scan_info.p2p_scan_type =
116 p2p_scan_type;
117}
118
119/**
120 * wma_reset_p2p_scan_info() - reset scan info from wma handle
121 * @wma_handle: wma handle
122 * @vdev_id: vdev id
123 *
124 * Return: none
125 */
126static inline void wma_reset_p2p_scan_info(tp_wma_handle wma_handle,
127 uint8_t vdev_id)
128{
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530129 qdf_mem_zero((void *)&(wma_handle->interfaces[vdev_id].p2p_scan_info),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800130 sizeof(struct p2p_scan_param));
131}
132
133/**
134 * wma_is_mcc_24G() - check that if device is in 2.4GHz MCC
135 * @handle: wma handle
136 *
137 * Return: true/false
138 */
139static bool wma_is_mcc_24G(WMA_HANDLE handle)
140{
141 tp_wma_handle wma_handle = (tp_wma_handle) handle;
142 int32_t prev_chan = 0;
143 int32_t i;
144
145 if (NULL == wma_handle) {
146 WMA_LOGE("%s: wma_handle is NULL", __func__);
147 return false;
148 }
149 for (i = 0; i < wma_handle->max_bssid; i++) {
150 if (wma_handle->interfaces[i].handle &&
151 wma_handle->interfaces[i].vdev_up) {
152 if ((prev_chan != 0 &&
153 prev_chan != wma_handle->interfaces[i].mhz) &&
154 (wma_handle->interfaces[i].mhz <=
155 CDS_CHAN_14_FREQ))
156 return true;
157 else
158 prev_chan = wma_handle->interfaces[i].mhz;
159 }
160 }
161 return false;
162}
163
164/**
165 * wma_get_buf_start_scan_cmd() - Fill start scan command
166 * @wma_handle: wma handle
167 * @scan_req: scan request
168 * @buf: wmi buffer to be filled in
169 * @buf_len: buf length
170 *
171 * Fill individual elements of wmi_start_scan_req and TLV for
172 * channel list, bssid, ssid etc.
173 *
174 * Return: CDF status
175 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530176QDF_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800177 tSirScanOffloadReq *scan_req,
178 wmi_buf_t *buf, int *buf_len)
179{
180 wmi_start_scan_cmd_fixed_param *cmd;
181 wmi_chan_list *chan_list = NULL;
182 wmi_mac_addr *bssid;
183 wmi_ssid *ssid = NULL;
184 uint32_t *tmp_ptr, ie_len_with_pad;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530185 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800186 uint8_t *buf_ptr;
187 uint32_t dwell_time;
188 uint8_t SSID_num;
189 int i;
190 int len = sizeof(*cmd);
Anurag Chouhan6d760662016-02-20 16:05:43 +0530191 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800192
193 if (!pMac) {
194 WMA_LOGP("%s: pMac is NULL!", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530195 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800196 }
197
198 len += WMI_TLV_HDR_SIZE; /* Length TLV placeholder for array of uint32_t */
199 /* calculate the length of buffer required */
200 if (scan_req->channelList.numChannels)
201 len += scan_req->channelList.numChannels * sizeof(uint32_t);
202
203 len += WMI_TLV_HDR_SIZE; /* Length TLV placeholder for array of wmi_ssid structures */
204 if (scan_req->numSsid)
205 len += scan_req->numSsid * sizeof(wmi_ssid);
206
207 len += WMI_TLV_HDR_SIZE; /* Length TLV placeholder for array of wmi_mac_addr structures */
208 len += sizeof(wmi_mac_addr);
209
210 len += WMI_TLV_HDR_SIZE; /* Length TLV placeholder for array of bytes */
211 if (scan_req->uIEFieldLen)
212 len += roundup(scan_req->uIEFieldLen, sizeof(uint32_t));
213
214 /* Allocate the memory */
215 *buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
216 if (!*buf) {
217 WMA_LOGP("%s: failed to allocate memory for start scan cmd",
218 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530219 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800220 }
221
222 buf_ptr = (uint8_t *) wmi_buf_data(*buf);
223 cmd = (wmi_start_scan_cmd_fixed_param *) buf_ptr;
224 WMITLV_SET_HDR(&cmd->tlv_header,
225 WMITLV_TAG_STRUC_wmi_start_scan_cmd_fixed_param,
226 WMITLV_GET_STRUCT_TLVLEN
227 (wmi_start_scan_cmd_fixed_param));
228
229 cmd->vdev_id = scan_req->sessionId;
230 /*
231 * host cycles through the lower 12 bits for scan id generation
232 * and prefix 0xA000 to scan id
233 */
234 if (scan_req->scan_id < WMA_HOST_SCAN_REQID_PREFIX) {
235 WMA_LOGE("Received scan_id 0x%x is wrong",
236 cmd->scan_id);
237 scan_req->scan_id = scan_req->scan_id & WMA_SCAN_ID_MASK;
238 /* Appending the 0xA000 to scan Id*/
239 cmd->scan_id = scan_req->scan_id | WMA_HOST_SCAN_REQID_PREFIX;
240 } else {
241 cmd->scan_id = scan_req->scan_id;
242 }
243 cmd->scan_priority = WMI_SCAN_PRIORITY_LOW;
Deepak Dhamdhered97bfb32015-10-11 15:16:18 -0700244 cmd->scan_req_id = scan_req->scan_requestor_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800245
246 /* Set the scan events which the driver is intereseted to receive */
247 /* TODO: handle all the other flags also */
248 cmd->notify_scan_events = WMI_SCAN_EVENT_STARTED |
249 WMI_SCAN_EVENT_START_FAILED |
250 WMI_SCAN_EVENT_FOREIGN_CHANNEL |
251 WMI_SCAN_EVENT_COMPLETED |
252 WMI_SCAN_EVENT_DEQUEUED |
253 WMI_SCAN_EVENT_PREEMPTED | WMI_SCAN_EVENT_RESTARTED;
254
255 cmd->dwell_time_active = scan_req->maxChannelTime;
256
257 if (scan_req->scanType == eSIR_ACTIVE_SCAN) {
258 /* In Active scan case, the firmware has to do passive scan on DFS channels
259 * So the passive scan duration should be updated properly so that the duration
260 * will be sufficient enough to receive the beacon from AP */
261
262 if (wlan_cfg_get_int(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME,
263 &dwell_time) != eSIR_SUCCESS) {
264 WMA_LOGE("Failed to get passive max channel value"
265 "using default value");
266 dwell_time = WMA_DWELL_TIME_PASSIVE_DEFAULT;
267 }
268 cmd->dwell_time_passive = dwell_time;
269 } else
270 cmd->dwell_time_passive = scan_req->maxChannelTime;
271
272 WMA_LOGI("Scan Type %x, Active dwell time %u, Passive dwell time %u",
273 scan_req->scanType, cmd->dwell_time_active,
274 cmd->dwell_time_passive);
275
276 /* Ensure correct number of probes are sent on active channel */
277 cmd->repeat_probe_time =
278 cmd->dwell_time_active / WMA_SCAN_NPROBES_DEFAULT;
279
280 /* CSR sends only one value restTime for staying on home channel
281 * to continue data traffic. Rome fw has facility to monitor the traffic
282 * and move to next channel. Stay on the channel for at least half
283 * of the requested time and then leave if there is no traffic.
284 */
285 cmd->min_rest_time = scan_req->restTime / 2;
286 cmd->max_rest_time = scan_req->restTime;
287
288 /* Check for traffic at idle_time interval after min_rest_time.
289 * Default value is 25 ms to allow full use of max_rest_time
290 * when voice packets are running at 20 ms interval.
291 */
292 cmd->idle_time = WMA_SCAN_IDLE_TIME_DEFAULT;
293
294 /* Large timeout value for full scan cycle, 30 seconds */
295 cmd->max_scan_time = WMA_HW_DEF_SCAN_MAX_DURATION;
296
Sreelakshmi Konamki75deb332015-09-14 10:58:03 +0530297 /* add DS param IE in probe req frame */
298 cmd->scan_ctrl_flags |= WMI_SCAN_ADD_DS_IE_IN_PROBE_REQ;
299
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800300 /* do not add OFDM rates in 11B mode */
301 if (scan_req->dot11mode != WNI_CFG_DOT11_MODE_11B)
302 cmd->scan_ctrl_flags |= WMI_SCAN_ADD_OFDM_RATES;
303 else
304 WMA_LOGD("OFDM_RATES not included in 11B mode");
305
306 /* Do not combine multiple channels in a single burst. Come back
307 * to home channel for data traffic after every foreign channel.
308 * By default, prefer throughput performance over scan cycle time.
309 */
310 cmd->burst_duration = 0;
311
312 if (!scan_req->p2pScanType) {
313 WMA_LOGD("Normal Scan request");
314 cmd->scan_ctrl_flags |= WMI_SCAN_ADD_CCK_RATES;
315 if (!scan_req->numSsid)
316 cmd->scan_ctrl_flags |= WMI_SCAN_ADD_BCAST_PROBE_REQ;
317 if (scan_req->scanType == eSIR_PASSIVE_SCAN)
318 cmd->scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE;
319 cmd->scan_ctrl_flags |= WMI_SCAN_FILTER_PROBE_REQ;
320
321 /*
322 * Decide burst_duration and dwell_time_active based on
323 * what type of devices are active.
324 */
325 do {
326 if (wma_is_sap_active(wma_handle) &&
327 wma_is_p2p_go_active(wma_handle) &&
328 wma_is_sta_active(wma_handle)) {
329 if (scan_req->maxChannelTime <=
330 WMA_3PORT_CONC_SCAN_MAX_BURST_DURATION)
331 cmd->burst_duration =
332 scan_req->maxChannelTime;
333 else
334 cmd->burst_duration =
335 WMA_3PORT_CONC_SCAN_MAX_BURST_DURATION;
336 break;
337 }
338 if (wma_is_sap_active(wma_handle)) {
339 /* Background scan while SoftAP is sending beacons.
340 * Max duration of CTS2self is 32 ms, which limits
341 * the dwell time.
342 */
343 cmd->dwell_time_active =
Anurag Chouhan6d760662016-02-20 16:05:43 +0530344 QDF_MIN(scan_req->maxChannelTime,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800345 (WMA_CTS_DURATION_MS_MAX -
346 WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME));
347 cmd->dwell_time_passive =
348 cmd->dwell_time_active;
349 cmd->burst_duration = 0;
350 break;
351 }
352 if (wma_handle->miracast_value &&
353 wma_is_mcc_24G(wma_handle)) {
354 cmd->max_rest_time =
355 pMac->f_sta_miracast_mcc_rest_time_val;
356 }
357 if (wma_is_p2p_go_active(wma_handle)) {
358 /* Background scan while GO is sending beacons.
359 * Every off-channel transition has overhead of 2 beacon
360 * intervals for NOA. Maximize number of channels in
361 * every transition by using burst scan.
362 */
363 if (wma_handle->miracast_value) {
364 /* When miracast is running, burst duration
365 * needs to be minimum to avoid any stutter
366 * or glitch in miracast during station scan
367 */
368 if (scan_req->maxChannelTime <=
369 WMA_GO_MIN_ACTIVE_SCAN_BURST_DURATION)
370 cmd->burst_duration =
371 scan_req->maxChannelTime;
372 else
373 cmd->burst_duration =
374 WMA_GO_MIN_ACTIVE_SCAN_BURST_DURATION;
375 } else {
376 /* If miracast is not running, accomodate max
377 * stations to make the scans faster
378 */
379 cmd->burst_duration =
380 WMA_BURST_SCAN_MAX_NUM_OFFCHANNELS *
381 scan_req->maxChannelTime;
382 if (cmd->burst_duration >
383 WMA_GO_MAX_ACTIVE_SCAN_BURST_DURATION) {
384 uint8_t channels =
385 WMA_P2P_SCAN_MAX_BURST_DURATION
386 / scan_req->maxChannelTime;
387 if (channels)
388 cmd->burst_duration =
389 channels *
390 scan_req->maxChannelTime;
391 else
392 cmd->burst_duration =
393 WMA_GO_MAX_ACTIVE_SCAN_BURST_DURATION;
394 }
395 }
396 break;
397 }
398 if (wma_is_sta_active(wma_handle) ||
399 wma_is_p2p_cli_active(wma_handle)) {
400 /* Typical background scan. Disable burst scan for now. */
401 cmd->burst_duration = 0;
402 break;
403 }
404 } while (0);
405
406 } else {
407 WMA_LOGD("P2P Scan");
408 switch (scan_req->p2pScanType) {
409 case P2P_SCAN_TYPE_LISTEN:
410 WMA_LOGD("P2P_SCAN_TYPE_LISTEN");
411 cmd->scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE;
412 cmd->notify_scan_events |=
413 WMI_SCAN_EVENT_FOREIGN_CHANNEL;
414 cmd->repeat_probe_time = 0;
415 break;
416 case P2P_SCAN_TYPE_SEARCH:
417 WMA_LOGD("P2P_SCAN_TYPE_SEARCH");
418 cmd->scan_ctrl_flags |= WMI_SCAN_FILTER_PROBE_REQ;
419 /* Default P2P burst duration of 120 ms will cover
420 * 3 channels with default max dwell time 40 ms.
421 * Cap limit will be set by
422 * WMA_P2P_SCAN_MAX_BURST_DURATION. Burst duration
423 * should be such that no channel is scanned less
424 * than the dwell time in normal scenarios.
425 */
426 if (scan_req->channelList.numChannels ==
427 P2P_SOCIAL_CHANNELS
428 && (!(wma_handle->miracast_value)))
429 cmd->repeat_probe_time =
430 scan_req->maxChannelTime / 5;
431 else
432 cmd->repeat_probe_time =
433 scan_req->maxChannelTime / 3;
434
435 cmd->burst_duration =
436 WMA_BURST_SCAN_MAX_NUM_OFFCHANNELS *
437 scan_req->maxChannelTime;
438 if (cmd->burst_duration >
439 WMA_P2P_SCAN_MAX_BURST_DURATION) {
440 uint8_t channels =
441 WMA_P2P_SCAN_MAX_BURST_DURATION /
442 scan_req->maxChannelTime;
443 if (channels)
444 cmd->burst_duration =
445 channels * scan_req->maxChannelTime;
446 else
447 cmd->burst_duration =
448 WMA_P2P_SCAN_MAX_BURST_DURATION;
449 }
450 break;
451 default:
452 WMA_LOGE("Invalid scan type");
453 goto error;
454 }
455 }
456
457 cmd->n_probes = (cmd->repeat_probe_time > 0) ?
458 cmd->dwell_time_active / cmd->repeat_probe_time : 0;
459
460 buf_ptr += sizeof(*cmd);
461 tmp_ptr = (uint32_t *) (buf_ptr + WMI_TLV_HDR_SIZE);
462
463 if (scan_req->channelList.numChannels) {
464 chan_list = (wmi_chan_list *) tmp_ptr;
465 cmd->num_chan = scan_req->channelList.numChannels;
466 for (i = 0; i < scan_req->channelList.numChannels; ++i) {
467 tmp_ptr[i] =
468 cds_chan_to_freq(scan_req->channelList.
469 channelNumber[i]);
470 }
471 }
472 WMITLV_SET_HDR(buf_ptr,
473 WMITLV_TAG_ARRAY_UINT32,
474 (cmd->num_chan * sizeof(uint32_t)));
475 buf_ptr += WMI_TLV_HDR_SIZE + (cmd->num_chan * sizeof(uint32_t));
476 if (scan_req->numSsid > SIR_SCAN_MAX_NUM_SSID) {
477 WMA_LOGE("Invalid value for numSsid");
478 goto error;
479 }
480 cmd->num_ssids = scan_req->numSsid;
481 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
482 (cmd->num_ssids * sizeof(wmi_ssid)));
483 if (scan_req->numSsid) {
484 ssid = (wmi_ssid *) (buf_ptr + WMI_TLV_HDR_SIZE);
485 for (i = 0; i < scan_req->numSsid; ++i) {
486 ssid->ssid_len = scan_req->ssId[i].length;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530487 qdf_mem_copy(ssid->ssid, scan_req->ssId[i].ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800488 scan_req->ssId[i].length);
489 ssid++;
490 }
491 }
492 buf_ptr += WMI_TLV_HDR_SIZE + (cmd->num_ssids * sizeof(wmi_ssid));
493
494 cmd->num_bssid = 1;
495
496 if (!scan_req->p2pScanType) {
497 if (wma_is_sap_active(wma_handle)) {
498 SSID_num = cmd->num_ssids * cmd->num_bssid;
499 cmd->repeat_probe_time = probe_time_dwell_time_map[
Anurag Chouhan6d760662016-02-20 16:05:43 +0530500 QDF_MIN(SSID_num,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800501 WMA_DWELL_TIME_PROBE_TIME_MAP_SIZE
502 - 1)].probe_time;
503 }
504 }
505
506 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
507 (cmd->num_bssid * sizeof(wmi_mac_addr)));
508 bssid = (wmi_mac_addr *) (buf_ptr + WMI_TLV_HDR_SIZE);
Srinivas Girigowdaa5bf5432015-09-24 11:20:22 -0700509 WMI_CHAR_ARRAY_TO_MAC_ADDR(scan_req->bssId.bytes, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800510 buf_ptr += WMI_TLV_HDR_SIZE + (cmd->num_bssid * sizeof(wmi_mac_addr));
511
512 cmd->ie_len = scan_req->uIEFieldLen;
513 ie_len_with_pad = roundup(scan_req->uIEFieldLen, sizeof(uint32_t));
514 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_with_pad);
515 if (scan_req->uIEFieldLen) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530516 qdf_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800517 (uint8_t *) scan_req +
518 (scan_req->uIEFieldOffset), scan_req->uIEFieldLen);
519 }
520 buf_ptr += WMI_TLV_HDR_SIZE + ie_len_with_pad;
521
522 *buf_len = len;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530523 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800524error:
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530525 qdf_mem_free(*buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800526 *buf = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530527 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528}
529
530/**
531 * wma_get_buf_stop_scan_cmd() - Fill stop scan command
532 * @wma_handle: wma handle
533 * @buf: wmi buffer to be filled in
534 * @buf_len: buf length
535 * @abort_scan_req: abort scan request
536 *
537 * Fill wmi_stop_scan_cmd buffer.
538 *
539 * Return: CDF status
540 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530541QDF_STATUS wma_get_buf_stop_scan_cmd(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800542 wmi_buf_t *buf,
543 int *buf_len,
544 tAbortScanParams *abort_scan_req)
545{
546 wmi_stop_scan_cmd_fixed_param *cmd;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530547 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800548 int len = sizeof(*cmd);
549
550 /* Allocate the memory */
551 *buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
552 if (!*buf) {
553 WMA_LOGP("%s: failed to allocate memory for stop scan cmd",
554 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530555 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556 goto error;
557 }
558
559 cmd = (wmi_stop_scan_cmd_fixed_param *) wmi_buf_data(*buf);
560 WMITLV_SET_HDR(&cmd->tlv_header,
561 WMITLV_TAG_STRUC_wmi_stop_scan_cmd_fixed_param,
562 WMITLV_GET_STRUCT_TLVLEN(wmi_stop_scan_cmd_fixed_param));
563 cmd->vdev_id = abort_scan_req->SessionId;
Deepak Dhamdhered97bfb32015-10-11 15:16:18 -0700564 cmd->requestor = abort_scan_req->scan_requestor_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800565 cmd->scan_id = abort_scan_req->scan_id;
566 /* stop the scan with the corresponding scan_id */
567 cmd->req_type = WMI_SCAN_STOP_ONE;
568
569 *buf_len = len;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530570 qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800571error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530572 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800573
574}
575
576
577/**
578 * wma_start_scan() - start scan command
579 * @wma_handle: wma handle
580 * @scan_req: scan request params
581 * @msg_type: message time
582 *
583 * Send start scan command to fw.
584 *
585 * Return: CDF status
586 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530587QDF_STATUS wma_start_scan(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588 tSirScanOffloadReq *scan_req, uint16_t msg_type)
589{
590 uint32_t vdev_id, scan_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530591 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592 wmi_buf_t buf = NULL;
593 wmi_start_scan_cmd_fixed_param *cmd;
594 int status = 0;
595 int len;
596 tSirScanOffloadEvent *scan_event;
597
598 if (scan_req->sessionId > wma_handle->max_bssid) {
599 WMA_LOGE("%s: Invalid vdev_id %d, msg_type : 0x%x", __func__,
600 scan_req->sessionId, msg_type);
601 goto error;
602 }
603
604 /* Sanity check to find whether vdev id active or not */
605 if (msg_type != WMA_START_SCAN_OFFLOAD_REQ &&
606 !wma_handle->interfaces[scan_req->sessionId].handle) {
607 WMA_LOGA("vdev id [%d] is not active", scan_req->sessionId);
608 goto error;
609 }
610
611 /* Fill individual elements of wmi_start_scan_req and
612 * TLV for channel list, bssid, ssid etc ... */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530613 qdf_status = wma_get_buf_start_scan_cmd(wma_handle, scan_req,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800614 &buf, &len);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530615 if (qdf_status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616 WMA_LOGE("Failed to get buffer for start scan cmd");
617 goto error;
618 }
619
620 if (NULL == buf) {
621 WMA_LOGE("Failed to get buffer for saving current scan info");
622 goto error;
623 }
624
625 /* Save current scan info */
626 cmd = (wmi_start_scan_cmd_fixed_param *) wmi_buf_data(buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800627 if (scan_req->p2pScanType == P2P_SCAN_TYPE_LISTEN)
628 wma_set_p2p_scan_info(wma_handle, cmd->scan_id,
629 cmd->vdev_id, P2P_SCAN_TYPE_LISTEN);
630 WMA_LOGE("scan_id 0x%x, vdev_id %d, p2pScanType %d, msg_type 0x%x",
631 cmd->scan_id, cmd->vdev_id, scan_req->p2pScanType, msg_type);
632 /*
633 * Cache vdev_id and scan_id because cmd is freed after calling
634 * wmi_unified_cmd_send cmd. WMI internally frees cmd buffer after
635 * getting TX complete from CE
636 */
637 vdev_id = cmd->vdev_id;
638 scan_id = cmd->scan_id;
639 WMA_LOGI("ActiveDwell %d, PassiveDwell %d, ScanFlags 0x%x NumChan %d",
640 cmd->dwell_time_active, cmd->dwell_time_passive,
641 cmd->scan_ctrl_flags, cmd->num_chan);
642
643 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
644 len, WMI_START_SCAN_CMDID);
645 /* Call the wmi api to request the scan */
646 if (status != EOK) {
647 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530648 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800649 goto error;
650 }
651
652 WMA_LOGI("WMA --> WMI_START_SCAN_CMDID");
653
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530654 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800655error:
656 /* Send completion event for only for start scan request */
657 if (msg_type == WMA_START_SCAN_OFFLOAD_REQ) {
658 scan_event =
659 (tSirScanOffloadEvent *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530660 qdf_mem_malloc(sizeof(tSirScanOffloadEvent));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800661 if (!scan_event) {
662 WMA_LOGP("%s: Failed to allocate memory for scan rsp",
663 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530664 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800665 }
666 memset(scan_event, 0x00, sizeof(*scan_event));
667 scan_event->event = WMI_SCAN_EVENT_COMPLETED;
668 scan_event->reasonCode = eSIR_SME_SCAN_FAILED;
669 scan_event->sessionId = scan_req->sessionId;
670 scan_event->p2pScanType = scan_req->p2pScanType;
671 scan_event->scanId = scan_req->scan_id;
Deepak Dhamdhered97bfb32015-10-11 15:16:18 -0700672 scan_event->requestor = scan_req->scan_requestor_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800673 wma_send_msg(wma_handle, WMA_RX_SCAN_EVENT, (void *)scan_event,
674 0);
675 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530676 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677}
678
679/**
680 * wma_stop_scan() - stop scan command
681 * @wma_handle: wma handle
682 * @abort_scan_req: abort scan params
683 *
684 * Send stop scan command to fw.
685 *
686 * Return: CDF status
687 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530688QDF_STATUS wma_stop_scan(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800689 tAbortScanParams *abort_scan_req)
690{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530691 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800692 wmi_buf_t buf;
693 int status = 0;
694 int len;
695
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530696 qdf_status = wma_get_buf_stop_scan_cmd(wma_handle, &buf, &len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800697 abort_scan_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530698 if (qdf_status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 WMA_LOGE("Failed to get buffer for stop scan cmd");
700 goto error1;
701 }
702
703 if (NULL == buf) {
704 WMA_LOGE("Failed to get buffer for stop scan cmd");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530705 qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800706 goto error1;
707 }
708
709 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
710 len, WMI_STOP_SCAN_CMDID);
711 /* Call the wmi api to request the scan */
712 if (status != EOK) {
713 WMA_LOGE("wmi_unified_cmd_send WMI_STOP_SCAN_CMDID returned Error %d",
714 status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530715 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800716 goto error;
717 }
Deepak Dhamdhered97bfb32015-10-11 15:16:18 -0700718 WMA_LOGE("scan_id 0x%x, scan_requestor_id 0x%x, vdev_id %d",
719 abort_scan_req->scan_id,
720 abort_scan_req->scan_requestor_id,
721 abort_scan_req->SessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 WMA_LOGI("WMA --> WMI_STOP_SCAN_CMDID");
723
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530724 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800725error:
726 if (buf)
Nirav Shahcbc6d722016-03-01 16:24:53 +0530727 qdf_nbuf_free(buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800728error1:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530729 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800730}
731
732/**
733 * wma_update_channel_list() - update channel list
734 * @handle: wma handle
735 * @chan_list: channel list
736 *
737 * Function is used to update the support channel list in fw.
738 *
739 * Return: CDF status
740 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530741QDF_STATUS wma_update_channel_list(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800742 tSirUpdateChanList *chan_list)
743{
744 tp_wma_handle wma_handle = (tp_wma_handle) handle;
745 wmi_buf_t buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530746 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800747 wmi_scan_chan_list_cmd_fixed_param *cmd;
748 int status, i;
749 uint8_t *buf_ptr;
750 wmi_channel *chan_info;
751 uint16_t len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
752
753 len += sizeof(wmi_channel) * chan_list->numChan;
754 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
755 if (!buf) {
756 WMA_LOGE("Failed to allocate memory");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530757 qdf_status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800758 goto end;
759 }
760
761 buf_ptr = (uint8_t *) wmi_buf_data(buf);
762 cmd = (wmi_scan_chan_list_cmd_fixed_param *) buf_ptr;
763 WMITLV_SET_HDR(&cmd->tlv_header,
764 WMITLV_TAG_STRUC_wmi_scan_chan_list_cmd_fixed_param,
765 WMITLV_GET_STRUCT_TLVLEN
766 (wmi_scan_chan_list_cmd_fixed_param));
767
768 WMA_LOGD("no of channels = %d, len = %d", chan_list->numChan, len);
769
770 cmd->num_scan_chans = chan_list->numChan;
771 WMITLV_SET_HDR((buf_ptr + sizeof(wmi_scan_chan_list_cmd_fixed_param)),
772 WMITLV_TAG_ARRAY_STRUC,
773 sizeof(wmi_channel) * chan_list->numChan);
774 chan_info = (wmi_channel *) (buf_ptr + sizeof(*cmd) + WMI_TLV_HDR_SIZE);
775
776 for (i = 0; i < chan_list->numChan; ++i) {
777 WMITLV_SET_HDR(&chan_info->tlv_header,
778 WMITLV_TAG_STRUC_wmi_channel,
779 WMITLV_GET_STRUCT_TLVLEN(wmi_channel));
780 chan_info->mhz =
781 cds_chan_to_freq(chan_list->chanParam[i].chanId);
782 chan_info->band_center_freq1 = chan_info->mhz;
783 chan_info->band_center_freq2 = 0;
784
785 WMA_LOGD("chan[%d] = %u", i, chan_info->mhz);
786 if (chan_list->chanParam[i].dfsSet) {
787 WMI_SET_CHANNEL_FLAG(chan_info, WMI_CHAN_FLAG_PASSIVE);
788 WMA_LOGI("chan[%d] DFS[%d]\n",
789 chan_list->chanParam[i].chanId,
790 chan_list->chanParam[i].dfsSet);
791 }
792
793 if (chan_info->mhz < WMA_2_4_GHZ_MAX_FREQ)
794 WMI_SET_CHANNEL_MODE(chan_info, MODE_11G);
795 else
796 WMI_SET_CHANNEL_MODE(chan_info, MODE_11A);
797
798 if (chan_list->chanParam[i].half_rate)
799 WMI_SET_CHANNEL_FLAG(chan_info,
800 WMI_CHAN_FLAG_HALF_RATE);
801 else if (chan_list->chanParam[i].quarter_rate)
802 WMI_SET_CHANNEL_FLAG(chan_info,
803 WMI_CHAN_FLAG_QUARTER_RATE);
804
805 WMI_SET_CHANNEL_MAX_TX_POWER(chan_info,
806 chan_list->chanParam[i].pwr);
807
808 WMI_SET_CHANNEL_REG_POWER(chan_info,
809 chan_list->chanParam[i].pwr);
810 WMA_LOGD("Channel TX power[%d] = %u: %d", i, chan_info->mhz,
811 chan_list->chanParam[i].pwr);
812 /*TODO: Set WMI_SET_CHANNEL_MIN_POWER */
813 /*TODO: Set WMI_SET_CHANNEL_ANTENNA_MAX */
814 /*TODO: WMI_SET_CHANNEL_REG_CLASSID */
815 chan_info++;
816 }
817
818 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
819 WMI_SCAN_CHAN_LIST_CMDID);
820
821 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530822 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800823 WMA_LOGE("Failed to send WMI_SCAN_CHAN_LIST_CMDID");
824 wmi_buf_free(buf);
825 }
826end:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530827 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800828}
829
830
831/**
832 * wma_roam_scan_offload_mode() - send roam scan mode request to fw
833 * @wma_handle: wma handle
834 * @scan_cmd_fp: start scan command ptr
835 * @roam_req: roam request param
836 * @mode: mode
837 * @vdev_id: vdev id
838 *
839 * send WMI_ROAM_SCAN_MODE TLV to firmware. It has a piggyback
840 * of WMI_ROAM_SCAN_MODE.
841 *
842 * Return: CDF status
843 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530844QDF_STATUS wma_roam_scan_offload_mode(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800845 wmi_start_scan_cmd_fixed_param *
846 scan_cmd_fp,
847 tSirRoamOffloadScanReq *roam_req,
848 uint32_t mode, uint32_t vdev_id)
849{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530850 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800851 wmi_buf_t buf = NULL;
852 int status = 0;
853 int len;
854 uint8_t *buf_ptr;
855 wmi_roam_scan_mode_fixed_param *roam_scan_mode_fp;
856#ifdef WLAN_FEATURE_ROAM_OFFLOAD
857 int auth_mode = WMI_AUTH_NONE;
858 wmi_roam_offload_tlv_param *roam_offload_params;
859 wmi_roam_11i_offload_tlv_param *roam_offload_11i;
860 wmi_roam_11r_offload_tlv_param *roam_offload_11r;
861 wmi_roam_ese_offload_tlv_param *roam_offload_ese;
862 if (roam_req)
863 auth_mode = e_csr_auth_type_to_rsn_authmode
864 (roam_req->ConnectedNetwork.authentication,
865 roam_req->ConnectedNetwork.encryption);
866 WMA_LOGD("%s : auth mode = %d", __func__, auth_mode);
867#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
868 /* Need to create a buf with roam_scan command at
869 * front and piggyback with scan command */
870 len = sizeof(wmi_roam_scan_mode_fixed_param) +
871#ifdef WLAN_FEATURE_ROAM_OFFLOAD
872 (2 * WMI_TLV_HDR_SIZE) +
873#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
874 sizeof(wmi_start_scan_cmd_fixed_param);
875#ifdef WLAN_FEATURE_ROAM_OFFLOAD
876 if (roam_req && roam_req->RoamOffloadEnabled) {
877 len += sizeof(wmi_roam_offload_tlv_param);
878 len += WMI_TLV_HDR_SIZE;
879 if ((auth_mode != WMI_AUTH_NONE) &&
880 ((auth_mode != WMI_AUTH_OPEN) ||
881 (auth_mode == WMI_AUTH_OPEN &&
882 roam_req->MDID.mdiePresent) || roam_req->IsESEAssoc)) {
883 len += WMI_TLV_HDR_SIZE;
884 if (roam_req->IsESEAssoc)
885 len += sizeof(wmi_roam_ese_offload_tlv_param);
886 else if (auth_mode == WMI_AUTH_FT_RSNA ||
887 auth_mode == WMI_AUTH_FT_RSNA_PSK ||
888 (auth_mode == WMI_AUTH_OPEN &&
889 roam_req->MDID.mdiePresent))
890 len += sizeof(wmi_roam_11r_offload_tlv_param);
891 else
892 len += sizeof(wmi_roam_11i_offload_tlv_param);
893 } else {
894 len += WMI_TLV_HDR_SIZE;
895 }
896 } else {
897 if (roam_req)
898 WMA_LOGD("%s : roam offload = %d",
899 __func__, roam_req->RoamOffloadEnabled);
900 else
901 WMA_LOGD("%s : roam_req is NULL", __func__);
902 len += (2 * WMI_TLV_HDR_SIZE);
903 }
904 if (roam_req && roam_req->RoamOffloadEnabled) {
905 mode = mode | WMI_ROAM_SCAN_MODE_ROAMOFFLOAD;
906 }
907#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
908 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
909 if (!buf) {
910 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530911 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800912 }
913
914 buf_ptr = (uint8_t *) wmi_buf_data(buf);
915 roam_scan_mode_fp = (wmi_roam_scan_mode_fixed_param *) buf_ptr;
916 WMITLV_SET_HDR(&roam_scan_mode_fp->tlv_header,
917 WMITLV_TAG_STRUC_wmi_roam_scan_mode_fixed_param,
918 WMITLV_GET_STRUCT_TLVLEN
919 (wmi_roam_scan_mode_fixed_param));
920
921 roam_scan_mode_fp->roam_scan_mode = mode;
922 roam_scan_mode_fp->vdev_id = vdev_id;
923 /* Fill in scan parameters suitable for roaming scan */
924 buf_ptr += sizeof(wmi_roam_scan_mode_fixed_param);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530925 qdf_mem_copy(buf_ptr, scan_cmd_fp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800926 sizeof(wmi_start_scan_cmd_fixed_param));
927 /* Ensure there is no additional IEs */
928 scan_cmd_fp->ie_len = 0;
929 WMITLV_SET_HDR(buf_ptr,
930 WMITLV_TAG_STRUC_wmi_start_scan_cmd_fixed_param,
931 WMITLV_GET_STRUCT_TLVLEN
932 (wmi_start_scan_cmd_fixed_param));
933#ifdef WLAN_FEATURE_ROAM_OFFLOAD
934 buf_ptr += sizeof(wmi_start_scan_cmd_fixed_param);
935 if (roam_req && roam_req->RoamOffloadEnabled) {
936 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
937 sizeof(wmi_roam_offload_tlv_param));
938 buf_ptr += WMI_TLV_HDR_SIZE;
939 roam_offload_params = (wmi_roam_offload_tlv_param *) buf_ptr;
940 WMITLV_SET_HDR(buf_ptr,
941 WMITLV_TAG_STRUC_wmi_roam_offload_tlv_param,
942 WMITLV_GET_STRUCT_TLVLEN
943 (wmi_roam_offload_tlv_param));
944 roam_offload_params->prefer_5g = roam_req->Prefer5GHz;
945 roam_offload_params->rssi_cat_gap = roam_req->RoamRssiCatGap;
946 roam_offload_params->select_5g_margin =
947 roam_req->Select5GHzMargin;
948 roam_offload_params->reassoc_failure_timeout =
949 roam_req->ReassocFailureTimeout;
950 /* Fill the capabilities */
951 wma_roam_scan_fill_self_caps(wma_handle, roam_offload_params,
952 roam_req);
953 buf_ptr += sizeof(wmi_roam_offload_tlv_param);
954 /* The TLV's are in the order of 11i, 11R, ESE. Hence,
955 * they are filled in the same order.Depending on the
956 * authentication type, the other mode TLV's are nullified
957 * and only headers are filled.*/
958 if ((auth_mode != WMI_AUTH_NONE) &&
959 ((auth_mode != WMI_AUTH_OPEN) ||
960 (auth_mode == WMI_AUTH_OPEN
961 && roam_req->MDID.mdiePresent) || roam_req->IsESEAssoc)) {
962 if (roam_req->IsESEAssoc) {
963 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
964 WMITLV_GET_STRUCT_TLVLEN(0));
965 buf_ptr += WMI_TLV_HDR_SIZE;
966 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
967 WMITLV_GET_STRUCT_TLVLEN(0));
968 buf_ptr += WMI_TLV_HDR_SIZE;
969 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
970 sizeof(wmi_roam_ese_offload_tlv_param));
971 buf_ptr += WMI_TLV_HDR_SIZE;
972 roam_offload_ese =
973 (wmi_roam_ese_offload_tlv_param *) buf_ptr;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530974 qdf_mem_copy(roam_offload_ese->krk,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800975 roam_req->KRK,
976 sizeof(roam_req->KRK));
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530977 qdf_mem_copy(roam_offload_ese->btk,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800978 roam_req->BTK,
979 sizeof(roam_req->BTK));
980 WMITLV_SET_HDR(&roam_offload_ese->tlv_header,
981 WMITLV_TAG_STRUC_wmi_roam_ese_offload_tlv_param,
982 WMITLV_GET_STRUCT_TLVLEN
983 (wmi_roam_ese_offload_tlv_param));
984 buf_ptr +=
985 sizeof(wmi_roam_ese_offload_tlv_param);
986 } else if (auth_mode == WMI_AUTH_FT_RSNA
987 || auth_mode == WMI_AUTH_FT_RSNA_PSK
988 || (auth_mode == WMI_AUTH_OPEN
989 && roam_req->MDID.mdiePresent)) {
990 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
991 0);
992 buf_ptr += WMI_TLV_HDR_SIZE;
993 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
994 sizeof(wmi_roam_11r_offload_tlv_param));
995 buf_ptr += WMI_TLV_HDR_SIZE;
996 roam_offload_11r =
997 (wmi_roam_11r_offload_tlv_param *) buf_ptr;
998 roam_offload_11r->r0kh_id_len =
999 roam_req->R0KH_ID_Length;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301000 qdf_mem_copy(roam_offload_11r->r0kh_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001001 roam_req->R0KH_ID,
1002 roam_offload_11r->r0kh_id_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301003 qdf_mem_copy(roam_offload_11r->psk_msk,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001004 roam_req->PSK_PMK,
1005 sizeof(roam_req->PSK_PMK));
1006 roam_offload_11r->psk_msk_len =
1007 roam_req->pmk_len;
1008 roam_offload_11r->mdie_present =
1009 roam_req->MDID.mdiePresent;
1010 roam_offload_11r->mdid =
1011 roam_req->MDID.mobilityDomain;
1012 if (auth_mode == WMI_AUTH_OPEN) {
1013 /* If FT-Open ensure pmk length
1014 and r0khid len are zero */
1015 roam_offload_11r->r0kh_id_len = 0;
1016 roam_offload_11r->psk_msk_len = 0;
1017 }
1018 WMITLV_SET_HDR(&roam_offload_11r->tlv_header,
1019 WMITLV_TAG_STRUC_wmi_roam_11r_offload_tlv_param,
1020 WMITLV_GET_STRUCT_TLVLEN
1021 (wmi_roam_11r_offload_tlv_param));
1022 buf_ptr +=
1023 sizeof(wmi_roam_11r_offload_tlv_param);
1024 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1025 WMITLV_GET_STRUCT_TLVLEN(0));
1026 buf_ptr += WMI_TLV_HDR_SIZE;
1027 } else {
1028 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1029 sizeof(wmi_roam_11i_offload_tlv_param));
1030 buf_ptr += WMI_TLV_HDR_SIZE;
1031 roam_offload_11i =
1032 (wmi_roam_11i_offload_tlv_param *) buf_ptr;
1033 if (roam_req->RoamKeyMgmtOffloadEnabled) {
1034 WMI_SET_ROAM_OFFLOAD_OKC_ENABLED
1035 (roam_offload_11i->flags);
1036 WMA_LOGE("LFR3:OKC Enabled");
1037 } else {
1038 WMI_SET_ROAM_OFFLOAD_OKC_DISABLED
1039 (roam_offload_11i->flags);
1040 WMA_LOGE("LFR3:OKC Disabled");
1041 }
1042
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301043 qdf_mem_copy(roam_offload_11i->pmk,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001044 roam_req->PSK_PMK,
1045 sizeof(roam_req->PSK_PMK));
1046 roam_offload_11i->pmk_len = roam_req->pmk_len;
1047 WMITLV_SET_HDR(&roam_offload_11i->tlv_header,
1048 WMITLV_TAG_STRUC_wmi_roam_11i_offload_tlv_param,
1049 WMITLV_GET_STRUCT_TLVLEN
1050 (wmi_roam_11i_offload_tlv_param));
1051 buf_ptr +=
1052 sizeof(wmi_roam_11i_offload_tlv_param);
1053 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1054 0);
1055 buf_ptr += WMI_TLV_HDR_SIZE;
1056 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1057 0);
1058 buf_ptr += WMI_TLV_HDR_SIZE;
1059 }
1060 } else {
1061 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1062 WMITLV_GET_STRUCT_TLVLEN(0));
1063 buf_ptr += WMI_TLV_HDR_SIZE;
1064 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1065 WMITLV_GET_STRUCT_TLVLEN(0));
1066 buf_ptr += WMI_TLV_HDR_SIZE;
1067 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1068 WMITLV_GET_STRUCT_TLVLEN(0));
1069 }
1070 } else {
1071 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1072 WMITLV_GET_STRUCT_TLVLEN(0));
1073 buf_ptr += WMI_TLV_HDR_SIZE;
1074 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1075 WMITLV_GET_STRUCT_TLVLEN(0));
1076 buf_ptr += WMI_TLV_HDR_SIZE;
1077 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1078 WMITLV_GET_STRUCT_TLVLEN(0));
1079 buf_ptr += WMI_TLV_HDR_SIZE;
1080 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1081 WMITLV_GET_STRUCT_TLVLEN(0));
1082 }
1083#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
1084 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
1085 len, WMI_ROAM_SCAN_MODE);
1086 if (status != EOK) {
1087 WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_SCAN_MODE returned Error %d",
1088 status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301089 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001090 goto error;
1091 }
1092
1093 WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_MODE", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301094 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001095error:
1096 wmi_buf_free(buf);
1097
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301098 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001099}
1100
1101/**
1102 * wma_roam_scan_offload_rssi_threshold() - set scan offload rssi threashold
1103 * @wma_handle: wma handle
1104 * @roam_req: Roaming request buffer
1105 *
1106 * Send WMI_ROAM_SCAN_RSSI_THRESHOLD TLV to firmware
1107 *
1108 * Return: CDF status
1109 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301110QDF_STATUS wma_roam_scan_offload_rssi_thresh(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001111 tSirRoamOffloadScanReq *roam_req)
1112{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301113 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001114 wmi_buf_t buf = NULL;
1115 int status = 0;
1116 int len, rssi_thresh, rssi_thresh_diff;
1117 uint8_t *buf_ptr;
1118 wmi_roam_scan_rssi_threshold_fixed_param *rssi_threshold_fp;
1119 wmi_roam_scan_extended_threshold_param *ext_thresholds = NULL;
Varun Reddy Yeturu05186292015-09-28 17:12:33 -07001120 wmi_roam_earlystop_rssi_thres_param *early_stop_thresholds = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001121 struct roam_ext_params *roam_params;
1122 int32_t good_rssi_threshold;
1123 uint32_t hirssi_scan_max_count;
1124 uint32_t hirssi_scan_delta;
1125 int32_t hirssi_upper_bound;
1126
1127 /* Send rssi threshold */
1128 roam_params = &roam_req->roam_params;
1129 rssi_thresh = roam_req->LookupThreshold - WMA_NOISE_FLOOR_DBM_DEFAULT;
1130 rssi_thresh_diff = roam_req->OpportunisticScanThresholdDiff;
1131 hirssi_scan_max_count = roam_req->hi_rssi_scan_max_count;
1132 hirssi_scan_delta = roam_req->hi_rssi_scan_rssi_delta;
1133 hirssi_upper_bound = roam_req->hi_rssi_scan_rssi_ub -
1134 WMA_NOISE_FLOOR_DBM_DEFAULT;
1135 len = sizeof(wmi_roam_scan_rssi_threshold_fixed_param);
1136 len += WMI_TLV_HDR_SIZE; /* TLV for ext_thresholds*/
1137 len += sizeof(wmi_roam_scan_extended_threshold_param);
Varun Reddy Yeturu05186292015-09-28 17:12:33 -07001138 len += WMI_TLV_HDR_SIZE;
1139 len += sizeof(wmi_roam_earlystop_rssi_thres_param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001140 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
1141 if (!buf) {
1142 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301143 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001144 }
1145
1146 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1147 rssi_threshold_fp =
1148 (wmi_roam_scan_rssi_threshold_fixed_param *) buf_ptr;
1149 WMITLV_SET_HDR(&rssi_threshold_fp->tlv_header,
1150 WMITLV_TAG_STRUC_wmi_roam_scan_rssi_threshold_fixed_param,
1151 WMITLV_GET_STRUCT_TLVLEN
1152 (wmi_roam_scan_rssi_threshold_fixed_param));
1153 /* fill in threshold values */
1154 rssi_threshold_fp->vdev_id = roam_req->sessionId;
1155 rssi_threshold_fp->roam_scan_rssi_thresh = rssi_thresh & 0x000000ff;
1156 rssi_threshold_fp->roam_rssi_thresh_diff =
1157 rssi_thresh_diff & 0x000000ff;
1158 rssi_threshold_fp->hirssi_scan_max_count = hirssi_scan_max_count;
1159 rssi_threshold_fp->hirssi_scan_delta = hirssi_scan_delta;
1160 rssi_threshold_fp->hirssi_upper_bound = hirssi_upper_bound & 0x00000ff;
1161
1162 buf_ptr += sizeof(wmi_roam_scan_rssi_threshold_fixed_param);
1163 WMITLV_SET_HDR(buf_ptr,
1164 WMITLV_TAG_ARRAY_STRUC,
1165 sizeof(wmi_roam_scan_extended_threshold_param));
1166 buf_ptr += WMI_TLV_HDR_SIZE;
1167 ext_thresholds = (wmi_roam_scan_extended_threshold_param *) buf_ptr;
1168 /*
1169 * The current Noise floor in firmware is -96dBm. Penalty/Boost
1170 * threshold is applied on a weaker signal to make it even more weaker.
1171 * So, there is a chance that the user may configure a very low
1172 * Penalty/Boost threshold beyond the noise floor. If that is the case,
1173 * then suppress the penalty/boost threshold to the noise floor.
1174 */
1175 if (roam_params->raise_rssi_thresh_5g < WMA_NOISE_FLOOR_DBM_DEFAULT)
1176 ext_thresholds->penalty_threshold_5g = 0;
1177 else
1178 ext_thresholds->boost_threshold_5g =
1179 (roam_params->raise_rssi_thresh_5g -
1180 WMA_NOISE_FLOOR_DBM_DEFAULT) & 0x000000ff;
1181 if (roam_params->drop_rssi_thresh_5g < WMA_NOISE_FLOOR_DBM_DEFAULT)
1182 ext_thresholds->penalty_threshold_5g = 0;
1183 else
1184 ext_thresholds->penalty_threshold_5g =
1185 (roam_params->drop_rssi_thresh_5g -
1186 WMA_NOISE_FLOOR_DBM_DEFAULT) & 0x000000ff;
1187 ext_thresholds->boost_algorithm_5g =
1188 WMI_ROAM_5G_BOOST_PENALIZE_ALGO_LINEAR;
1189 ext_thresholds->boost_factor_5g = roam_params->raise_factor_5g;
1190 ext_thresholds->penalty_algorithm_5g =
1191 WMI_ROAM_5G_BOOST_PENALIZE_ALGO_LINEAR;
1192 ext_thresholds->penalty_factor_5g = roam_params->drop_factor_5g;
1193 ext_thresholds->max_boost_5g = roam_params->max_raise_rssi_5g;
1194 ext_thresholds->max_penalty_5g = roam_params->max_drop_rssi_5g;
1195
1196 if (roam_params->good_rssi_roam)
1197 good_rssi_threshold = WMA_NOISE_FLOOR_DBM_DEFAULT;
1198 else
1199 good_rssi_threshold = 0;
1200 ext_thresholds->good_rssi_threshold =
1201 (good_rssi_threshold - WMA_NOISE_FLOOR_DBM_DEFAULT) & 0x000000ff;
1202
1203 WMA_LOGD("WMA --> good_rssi_threshold=%d",
1204 ext_thresholds->good_rssi_threshold);
1205
1206 WMITLV_SET_HDR(&ext_thresholds->tlv_header,
1207 WMITLV_TAG_STRUC_wmi_roam_scan_extended_threshold_param,
1208 WMITLV_GET_STRUCT_TLVLEN
1209 (wmi_roam_scan_extended_threshold_param));
Varun Reddy Yeturu05186292015-09-28 17:12:33 -07001210 buf_ptr += sizeof(wmi_roam_scan_extended_threshold_param);
1211 WMITLV_SET_HDR(buf_ptr,
1212 WMITLV_TAG_ARRAY_STRUC,
1213 sizeof(wmi_roam_earlystop_rssi_thres_param));
1214 buf_ptr += WMI_TLV_HDR_SIZE;
1215 early_stop_thresholds = (wmi_roam_earlystop_rssi_thres_param *) buf_ptr;
1216 early_stop_thresholds->roam_earlystop_thres_min =
1217 roam_req->early_stop_scan_min_threshold -
1218 WMA_NOISE_FLOOR_DBM_DEFAULT;
1219 early_stop_thresholds->roam_earlystop_thres_max =
1220 roam_req->early_stop_scan_max_threshold -
1221 WMA_NOISE_FLOOR_DBM_DEFAULT;
1222 WMITLV_SET_HDR(&early_stop_thresholds->tlv_header,
1223 WMITLV_TAG_STRUC_wmi_roam_earlystop_rssi_thres_param,
1224 WMITLV_GET_STRUCT_TLVLEN
1225 (wmi_roam_earlystop_rssi_thres_param));
1226 WMA_LOGD("early_stop_thresholds en=%d, min=%d, max=%d",
1227 roam_req->early_stop_scan_enable,
1228 early_stop_thresholds->roam_earlystop_thres_min,
1229 early_stop_thresholds->roam_earlystop_thres_max);
1230
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001231 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
1232 len, WMI_ROAM_SCAN_RSSI_THRESHOLD);
1233 if (status != EOK) {
1234 WMA_LOGE("cmd WMI_ROAM_SCAN_RSSI_THRESHOLD returned Error %d",
1235 status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301236 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001237 goto error;
1238 }
1239
1240 WMA_LOGI(FL("roam_scan_rssi_thresh=%d, roam_rssi_thresh_diff=%d"),
1241 rssi_thresh, rssi_thresh_diff);
1242 WMA_LOGI(
1243 FL("hirssi_scan max_count=%d, delta=%d, hirssi_upper_bound=%d"),
1244 hirssi_scan_max_count, hirssi_scan_delta, hirssi_upper_bound);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301245 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001246error:
1247 wmi_buf_free(buf);
1248
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301249 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001250}
1251
1252/**
1253 * wma_roam_scan_offload_scan_period() - set roam offload scan period
1254 * @wma_handle: wma handle
1255 * @scan_period: scan period
1256 * @scan_age: scan age
1257 * @vdev_id: vdev id
1258 *
1259 * Send WMI_ROAM_SCAN_PERIOD parameters to fw.
1260 *
1261 * Return: CDF status
1262 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301263QDF_STATUS wma_roam_scan_offload_scan_period(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264 uint32_t scan_period,
1265 uint32_t scan_age,
1266 uint32_t vdev_id)
1267{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301268 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001269 wmi_buf_t buf = NULL;
1270 int status = 0;
1271 int len;
1272 uint8_t *buf_ptr;
1273 wmi_roam_scan_period_fixed_param *scan_period_fp;
1274
1275 /* Send scan period values */
1276 len = sizeof(wmi_roam_scan_period_fixed_param);
1277 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
1278 if (!buf) {
1279 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301280 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001281 }
1282
1283 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1284 scan_period_fp = (wmi_roam_scan_period_fixed_param *) buf_ptr;
1285 WMITLV_SET_HDR(&scan_period_fp->tlv_header,
1286 WMITLV_TAG_STRUC_wmi_roam_scan_period_fixed_param,
1287 WMITLV_GET_STRUCT_TLVLEN
1288 (wmi_roam_scan_period_fixed_param));
1289 /* fill in scan period values */
1290 scan_period_fp->vdev_id = vdev_id;
1291 scan_period_fp->roam_scan_period = scan_period; /* 20 seconds */
1292 scan_period_fp->roam_scan_age = scan_age;
1293
1294 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
1295 len, WMI_ROAM_SCAN_PERIOD);
1296 if (status != EOK) {
1297 WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_SCAN_PERIOD returned Error %d",
1298 status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301299 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001300 goto error;
1301 }
1302
1303 WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_PERIOD roam_scan_period=%d, roam_scan_age=%d",
1304 __func__, scan_period, scan_age);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301305 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001306error:
1307 wmi_buf_free(buf);
1308
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301309 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001310}
1311
1312/**
1313 * wma_roam_scan_offload_rssi_change() - set roam offload RSSI change threshold
1314 * @wma_handle: wma handle
1315 * @rssi_change_thresh: RSSI Change threshold
1316 * @bcn_rssi_weight: beacon RSSI weight
1317 * @vdev_id: vdev id
1318 *
1319 * Send WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD parameters to fw.
1320 *
1321 * Return: CDF status
1322 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301323QDF_STATUS wma_roam_scan_offload_rssi_change(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001324 uint32_t vdev_id,
1325 int32_t rssi_change_thresh,
1326 uint32_t bcn_rssi_weight,
1327 uint32_t hirssi_delay_btw_scans)
1328{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301329 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001330 wmi_buf_t buf = NULL;
1331 int status = 0;
1332 int len;
1333 uint8_t *buf_ptr;
1334 wmi_roam_scan_rssi_change_threshold_fixed_param *rssi_change_fp;
1335
1336 /* Send rssi change parameters */
1337 len = sizeof(wmi_roam_scan_rssi_change_threshold_fixed_param);
1338 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
1339 if (!buf) {
1340 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301341 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001342 }
1343
1344 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1345 rssi_change_fp =
1346 (wmi_roam_scan_rssi_change_threshold_fixed_param *) buf_ptr;
1347 WMITLV_SET_HDR(&rssi_change_fp->tlv_header,
1348 WMITLV_TAG_STRUC_wmi_roam_scan_rssi_change_threshold_fixed_param,
1349 WMITLV_GET_STRUCT_TLVLEN
1350 (wmi_roam_scan_rssi_change_threshold_fixed_param));
1351 /* fill in rssi change threshold (hysteresis) values */
1352 rssi_change_fp->vdev_id = vdev_id;
1353 rssi_change_fp->roam_scan_rssi_change_thresh = rssi_change_thresh;
1354 rssi_change_fp->bcn_rssi_weight = bcn_rssi_weight;
1355 rssi_change_fp->hirssi_delay_btw_scans = hirssi_delay_btw_scans;
1356
1357 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
1358 len, WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD);
1359 if (status != EOK) {
1360 WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD returned Error %d",
1361 status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301362 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001363 goto error;
1364 }
1365
1366 WMA_LOGI(FL("roam_scan_rssi_change_thresh=%d, bcn_rssi_weight=%d"),
1367 rssi_change_thresh, bcn_rssi_weight);
1368 WMA_LOGI(FL("hirssi_delay_btw_scans=%d"), hirssi_delay_btw_scans);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301369 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370error:
1371 wmi_buf_free(buf);
1372
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301373 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374}
1375
1376/**
1377 * wma_roam_scan_offload_chan_list() - set roam offload channel list
1378 * @wma_handle: wma handle
1379 * @chan_count: channel count
1380 * @chan_list: channel list
1381 * @list_type: list type
1382 * @vdev_id: vdev id
1383 *
1384 * Set roam offload channel list.
1385 *
1386 * Return: CDF status
1387 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301388QDF_STATUS wma_roam_scan_offload_chan_list(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001389 uint8_t chan_count,
1390 uint8_t *chan_list,
1391 uint8_t list_type, uint32_t vdev_id)
1392{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301393 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001394 wmi_buf_t buf = NULL;
1395 int status = 0;
1396 int len, list_tlv_len;
1397 int i;
1398 uint8_t *buf_ptr;
1399 wmi_roam_chan_list_fixed_param *chan_list_fp;
1400 A_UINT32 *roam_chan_list_array;
1401
1402 if (chan_count == 0) {
1403 WMA_LOGD("%s : invalid number of channels %d", __func__,
1404 chan_count);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301405 return QDF_STATUS_E_EMPTY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001406 }
1407 /* Channel list is a table of 2 TLV's */
1408 list_tlv_len = WMI_TLV_HDR_SIZE + chan_count * sizeof(A_UINT32);
1409 len = sizeof(wmi_roam_chan_list_fixed_param) + list_tlv_len;
1410 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
1411 if (!buf) {
1412 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301413 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001414 }
1415
1416 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1417 chan_list_fp = (wmi_roam_chan_list_fixed_param *) buf_ptr;
1418 WMITLV_SET_HDR(&chan_list_fp->tlv_header,
1419 WMITLV_TAG_STRUC_wmi_roam_chan_list_fixed_param,
1420 WMITLV_GET_STRUCT_TLVLEN
1421 (wmi_roam_chan_list_fixed_param));
1422 chan_list_fp->vdev_id = vdev_id;
1423 chan_list_fp->num_chan = chan_count;
1424 if (chan_count > 0 && list_type == CHANNEL_LIST_STATIC) {
1425 /* external app is controlling channel list */
1426 chan_list_fp->chan_list_type =
1427 WMI_ROAM_SCAN_CHAN_LIST_TYPE_STATIC;
1428 } else {
1429 /* umac supplied occupied channel list in LFR */
1430 chan_list_fp->chan_list_type =
1431 WMI_ROAM_SCAN_CHAN_LIST_TYPE_DYNAMIC;
1432 }
1433
1434 buf_ptr += sizeof(wmi_roam_chan_list_fixed_param);
1435 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
1436 (chan_list_fp->num_chan * sizeof(uint32_t)));
1437 roam_chan_list_array = (A_UINT32 *) (buf_ptr + WMI_TLV_HDR_SIZE);
1438 WMA_LOGI("%s: %d channels = ", __func__, chan_list_fp->num_chan);
1439 for (i = 0; ((i < chan_list_fp->num_chan) &&
1440 (i < SIR_ROAM_MAX_CHANNELS)); i++) {
1441 roam_chan_list_array[i] = cds_chan_to_freq(chan_list[i]);
1442 WMA_LOGI("%d,", roam_chan_list_array[i]);
1443 }
1444
1445 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
1446 len, WMI_ROAM_CHAN_LIST);
1447 if (status != EOK) {
1448 WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_CHAN_LIST returned Error %d",
1449 status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301450 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001451 goto error;
1452 }
1453
1454 WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_CHAN_LIST", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301455 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001456error:
1457 wmi_buf_free(buf);
1458
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301459 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001460}
1461
1462/**
1463 * e_csr_auth_type_to_rsn_authmode() - map csr auth type to rsn authmode
1464 * @authtype: CSR authtype
1465 * @encr: CSR Encryption
1466 *
1467 * Map CSR's authentication type into RSN auth mode used by firmware
1468 *
1469 * Return: WMI RSN auth mode
1470 */
1471A_UINT32 e_csr_auth_type_to_rsn_authmode(eCsrAuthType authtype,
1472 eCsrEncryptionType encr)
1473{
1474 switch (authtype) {
1475 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
1476 return WMI_AUTH_OPEN;
1477 case eCSR_AUTH_TYPE_WPA:
1478 return WMI_AUTH_WPA;
1479 case eCSR_AUTH_TYPE_WPA_PSK:
1480 return WMI_AUTH_WPA_PSK;
1481 case eCSR_AUTH_TYPE_RSN:
1482 return WMI_AUTH_RSNA;
1483 case eCSR_AUTH_TYPE_RSN_PSK:
1484 return WMI_AUTH_RSNA_PSK;
1485#if defined WLAN_FEATURE_VOWIFI_11R
1486 case eCSR_AUTH_TYPE_FT_RSN:
1487 return WMI_AUTH_FT_RSNA;
1488 case eCSR_AUTH_TYPE_FT_RSN_PSK:
1489 return WMI_AUTH_FT_RSNA_PSK;
1490#endif /* WLAN_FEATURE_VOWIFI_11R */
1491#ifdef FEATURE_WLAN_WAPI
1492 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
1493 return WMI_AUTH_WAPI;
1494 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
1495 return WMI_AUTH_WAPI_PSK;
1496#endif /* FEATURE_WLAN_WAPI */
1497#ifdef FEATURE_WLAN_ESE
1498 case eCSR_AUTH_TYPE_CCKM_WPA:
1499 case eCSR_AUTH_TYPE_CCKM_RSN:
1500 return WMI_AUTH_CCKM;
1501#endif /* FEATURE_WLAN_ESE */
1502#ifdef WLAN_FEATURE_11W
1503 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
1504 return WMI_AUTH_RSNA_PSK_SHA256;
1505 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
1506 return WMI_AUTH_RSNA_8021X_SHA256;
1507#endif /* WLAN_FEATURE_11W */
1508 case eCSR_AUTH_TYPE_NONE:
1509 case eCSR_AUTH_TYPE_AUTOSWITCH:
1510 /* In case of WEP and other keys, NONE means OPEN auth */
1511 if (encr == eCSR_ENCRYPT_TYPE_WEP40_STATICKEY ||
1512 encr == eCSR_ENCRYPT_TYPE_WEP104_STATICKEY ||
1513 encr == eCSR_ENCRYPT_TYPE_WEP40 ||
1514 encr == eCSR_ENCRYPT_TYPE_WEP104 ||
1515 encr == eCSR_ENCRYPT_TYPE_TKIP ||
1516 encr == eCSR_ENCRYPT_TYPE_AES) {
1517 return WMI_AUTH_OPEN;
1518 }
1519 return WMI_AUTH_NONE;
1520 default:
1521 return WMI_AUTH_NONE;
1522 }
1523}
1524
1525/**
1526 * e_csr_encryption_type_to_rsn_cipherset() - map csr enc type to ESN cipher
1527 * @encr: CSR Encryption
1528 *
1529 * Map CSR's encryption type into RSN cipher types used by firmware
1530 *
1531 * Return: WMI RSN cipher
1532 */
1533A_UINT32 e_csr_encryption_type_to_rsn_cipherset(eCsrEncryptionType encr)
1534{
1535
1536 switch (encr) {
1537 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
1538 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
1539 case eCSR_ENCRYPT_TYPE_WEP40:
1540 case eCSR_ENCRYPT_TYPE_WEP104:
1541 return WMI_CIPHER_WEP;
1542 case eCSR_ENCRYPT_TYPE_TKIP:
1543 return WMI_CIPHER_TKIP;
1544 case eCSR_ENCRYPT_TYPE_AES:
1545 return WMI_CIPHER_AES_CCM;
1546#ifdef FEATURE_WLAN_WAPI
1547 case eCSR_ENCRYPT_TYPE_WPI:
1548 return WMI_CIPHER_WAPI;
1549#endif /* FEATURE_WLAN_WAPI */
1550 case eCSR_ENCRYPT_TYPE_ANY:
1551 return WMI_CIPHER_ANY;
1552 case eCSR_ENCRYPT_TYPE_NONE:
1553 default:
1554 return WMI_CIPHER_NONE;
1555 }
1556}
1557
1558/**
1559 * wma_roam_scan_fill_ap_profile() - fill ap_profile
1560 * @wma_handle: wma handle
1561 * @pMac: Mac ptr
1562 * @roam_req: roam offload scan request
1563 * @ap_profile_p: ap profile
1564 *
1565 * Fill ap_profile structure from configured parameters
1566 *
1567 * Return: none
1568 */
1569void wma_roam_scan_fill_ap_profile(tp_wma_handle wma_handle,
1570 tpAniSirGlobal pMac,
1571 tSirRoamOffloadScanReq *roam_req,
1572 wmi_ap_profile *ap_profile_p)
1573{
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301574 qdf_mem_zero(ap_profile_p, sizeof(wmi_ap_profile));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001575 if (roam_req == NULL) {
1576 ap_profile_p->ssid.ssid_len = 0;
1577 ap_profile_p->ssid.ssid[0] = 0;
1578 ap_profile_p->rsn_authmode = WMI_AUTH_NONE;
1579 ap_profile_p->rsn_ucastcipherset = WMI_CIPHER_NONE;
1580 ap_profile_p->rsn_mcastcipherset = WMI_CIPHER_NONE;
1581 ap_profile_p->rsn_mcastmgmtcipherset = WMI_CIPHER_NONE;
1582 ap_profile_p->rssi_threshold = WMA_ROAM_RSSI_DIFF_DEFAULT;
1583 } else {
1584 ap_profile_p->ssid.ssid_len =
1585 roam_req->ConnectedNetwork.ssId.length;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301586 qdf_mem_copy(ap_profile_p->ssid.ssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001587 roam_req->ConnectedNetwork.ssId.ssId,
1588 ap_profile_p->ssid.ssid_len);
1589 ap_profile_p->rsn_authmode =
1590 e_csr_auth_type_to_rsn_authmode(roam_req->ConnectedNetwork.authentication,
1591 roam_req->ConnectedNetwork.encryption);
1592 ap_profile_p->rsn_ucastcipherset =
1593 e_csr_encryption_type_to_rsn_cipherset(roam_req->ConnectedNetwork.encryption);
1594 ap_profile_p->rsn_mcastcipherset =
1595 e_csr_encryption_type_to_rsn_cipherset(roam_req->ConnectedNetwork.mcencryption);
1596 ap_profile_p->rsn_mcastmgmtcipherset =
1597 ap_profile_p->rsn_mcastcipherset;
1598 ap_profile_p->rssi_threshold = roam_req->RoamRssiDiff;
1599#ifdef WLAN_FEATURE_11W
1600 if (roam_req->ConnectedNetwork.mfp_enabled)
1601 ap_profile_p->flags |= WMI_AP_PROFILE_FLAG_PMF;
1602#endif
1603 }
1604}
1605
1606/**
1607 * wma_roam_scan_scan_params() - fill roam scan params
1608 * @wma_handle: wma handle
1609 * @pMac: Mac ptr
1610 * @scan_params: scan parameters
1611 * @roam_req: NULL if this routine is called before connect
1612 * It will be non-NULL if called after assoc.
1613 *
1614 * Fill scan_params structure from configured parameters
1615 *
1616 * Return: none
1617 */
1618void wma_roam_scan_fill_scan_params(tp_wma_handle wma_handle,
1619 tpAniSirGlobal pMac,
1620 tSirRoamOffloadScanReq *roam_req,
1621 wmi_start_scan_cmd_fixed_param *
1622 scan_params)
1623{
1624 uint8_t channels_per_burst = 0;
1625 uint32_t val = 0;
1626
1627 if (NULL == pMac) {
1628 WMA_LOGE("%s: pMac is NULL", __func__);
1629 return;
1630 }
1631
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301632 qdf_mem_zero(scan_params, sizeof(wmi_start_scan_cmd_fixed_param));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001633 scan_params->scan_ctrl_flags = WMI_SCAN_ADD_CCK_RATES |
Sreelakshmi Konamki75deb332015-09-14 10:58:03 +05301634 WMI_SCAN_ADD_OFDM_RATES |
1635 WMI_SCAN_ADD_DS_IE_IN_PROBE_REQ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001636 if (roam_req != NULL) {
1637 /* Parameters updated after association is complete */
1638 WMA_LOGI("%s: Input parameters: NeighborScanChannelMinTime"
1639 " = %d, NeighborScanChannelMaxTime = %d",
1640 __func__,
1641 roam_req->NeighborScanChannelMinTime,
1642 roam_req->NeighborScanChannelMaxTime);
1643 WMA_LOGI("%s: Input parameters: NeighborScanTimerPeriod ="
1644 " %d, HomeAwayTime = %d, nProbes = %d",
1645 __func__,
1646 roam_req->NeighborScanTimerPeriod,
1647 roam_req->HomeAwayTime, roam_req->nProbes);
1648
1649 /*
1650 * roam_req->NeighborScanChannelMaxTime = SCAN_CHANNEL_TIME
1651 * roam_req->HomeAwayTime = SCAN_HOME_AWAY_TIME
1652 * roam_req->NeighborScanTimerPeriod = SCAN_HOME_TIME
1653 *
1654 * scan_params->dwell_time_active = time station stays on channel
1655 * and sends probes;
1656 * scan_params->dwell_time_passive = time station stays on channel
1657 * and listens probes;
1658 * scan_params->burst_duration = time station goes off channel
1659 * to scan;
1660 */
1661
1662 if (wlan_cfg_get_int
1663 (pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME,
1664 &val) != eSIR_SUCCESS) {
1665 /*
1666 * Could not get max channel value from CFG. Log error.
1667 */
1668 WMA_LOGE
1669 ("could not retrieve passive max channel value");
1670
1671 /* use a default value of 110ms */
1672 val = WMA_ROAM_DWELL_TIME_PASSIVE_DEFAULT;
1673 }
1674
1675 scan_params->dwell_time_passive = val;
1676 /*
1677 * Here is the formula,
1678 * T(HomeAway) = N * T(dwell) + (N+1) * T(cs)
1679 * where N is number of channels scanned in single burst
1680 */
1681 scan_params->dwell_time_active =
1682 roam_req->NeighborScanChannelMaxTime;
1683 if (roam_req->HomeAwayTime <
1684 2 * WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME) {
1685 /* clearly we can't follow home away time.
1686 * Make it a split scan.
1687 */
1688 scan_params->burst_duration = 0;
1689 } else {
1690 channels_per_burst =
1691 (roam_req->HomeAwayTime -
1692 WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME)
1693 / (scan_params->dwell_time_active +
1694 WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME);
1695
1696 if (channels_per_burst < 1) {
1697 /* dwell time and home away time conflicts */
1698 /* we will override dwell time */
1699 scan_params->dwell_time_active =
1700 roam_req->HomeAwayTime -
1701 2 * WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME;
1702 scan_params->burst_duration =
1703 scan_params->dwell_time_active;
1704 } else {
1705 scan_params->burst_duration =
1706 channels_per_burst *
1707 scan_params->dwell_time_active;
1708 }
1709 }
1710 if (roam_req->allowDFSChannelRoam ==
1711 SIR_ROAMING_DFS_CHANNEL_ENABLED_NORMAL
1712 && roam_req->HomeAwayTime > 0
1713 && roam_req->ChannelCacheType != CHANNEL_LIST_STATIC) {
1714 /* Roaming on DFS channels is supported and it is not
1715 * app channel list. It is ok to override homeAwayTime
1716 * to accomodate DFS dwell time in burst
1717 * duration.
1718 */
1719 scan_params->burst_duration =
Anurag Chouhan6d760662016-02-20 16:05:43 +05301720 QDF_MAX(scan_params->burst_duration,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001721 scan_params->dwell_time_passive);
1722 }
1723 scan_params->min_rest_time = roam_req->NeighborScanTimerPeriod;
1724 scan_params->max_rest_time = roam_req->NeighborScanTimerPeriod;
1725 scan_params->repeat_probe_time = (roam_req->nProbes > 0) ?
Anurag Chouhan6d760662016-02-20 16:05:43 +05301726 QDF_MAX(scan_params->dwell_time_active / roam_req->nProbes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001727 1) : 0;
1728 scan_params->probe_spacing_time = 0;
1729 scan_params->probe_delay = 0;
1730 /* 30 seconds for full scan cycle */
1731 scan_params->max_scan_time = WMA_HW_DEF_SCAN_MAX_DURATION;
1732 scan_params->idle_time = scan_params->min_rest_time;
1733 scan_params->n_probes = roam_req->nProbes;
1734 if (roam_req->allowDFSChannelRoam ==
1735 SIR_ROAMING_DFS_CHANNEL_DISABLED) {
1736 scan_params->scan_ctrl_flags |= WMI_SCAN_BYPASS_DFS_CHN;
1737 } else {
1738 /* Roaming scan on DFS channel is allowed.
1739 * No need to change any flags for default
1740 * allowDFSChannelRoam = 1.
1741 * Special case where static channel list is given by\
1742 * application that contains DFS channels.
1743 * Assume that the application has knowledge of matching
1744 * APs being active and that probe request transmission
1745 * is permitted on those channel.
1746 * Force active scans on those channels.
1747 */
1748
1749 if (roam_req->allowDFSChannelRoam ==
1750 SIR_ROAMING_DFS_CHANNEL_ENABLED_ACTIVE &&
1751 roam_req->ChannelCacheType == CHANNEL_LIST_STATIC &&
1752 roam_req->ConnectedNetwork.ChannelCount > 0) {
1753 scan_params->scan_ctrl_flags |=
1754 WMI_SCAN_FLAG_FORCE_ACTIVE_ON_DFS;
1755 }
1756 }
1757 } else {
1758 /* roam_req = NULL during initial or pre-assoc invocation */
1759 scan_params->dwell_time_active =
1760 WMA_ROAM_DWELL_TIME_ACTIVE_DEFAULT;
1761 scan_params->dwell_time_passive =
1762 WMA_ROAM_DWELL_TIME_PASSIVE_DEFAULT;
1763 scan_params->min_rest_time = WMA_ROAM_MIN_REST_TIME_DEFAULT;
1764 scan_params->max_rest_time = WMA_ROAM_MAX_REST_TIME_DEFAULT;
1765 scan_params->repeat_probe_time = 0;
1766 scan_params->probe_spacing_time = 0;
1767 scan_params->probe_delay = 0;
1768 scan_params->max_scan_time = WMA_HW_DEF_SCAN_MAX_DURATION;
1769 scan_params->idle_time = scan_params->min_rest_time;
1770 scan_params->burst_duration = 0;
1771 scan_params->n_probes = 0;
1772 }
1773
1774 WMA_LOGI("%s: Rome roam scan parameters:"
1775 " dwell_time_active = %d, dwell_time_passive = %d",
1776 __func__,
1777 scan_params->dwell_time_active,
1778 scan_params->dwell_time_passive);
1779 WMA_LOGI("%s: min_rest_time = %d, max_rest_time = %d,"
1780 " repeat_probe_time = %d n_probes = %d",
1781 __func__,
1782 scan_params->min_rest_time,
1783 scan_params->max_rest_time,
1784 scan_params->repeat_probe_time, scan_params->n_probes);
1785 WMA_LOGI("%s: max_scan_time = %d, idle_time = %d,"
1786 " burst_duration = %d, scan_ctrl_flags = 0x%x",
1787 __func__,
1788 scan_params->max_scan_time,
1789 scan_params->idle_time,
1790 scan_params->burst_duration, scan_params->scan_ctrl_flags);
1791}
1792
1793/**
1794 * wma_roam_scan_offload_ap_profile() - set roam ap profile in fw
1795 * @wma_handle: wma handle
1796 * @ap_profile_p: ap profile
1797 * @vdev_id: vdev id
1798 *
1799 * Send WMI_ROAM_AP_PROFILE to firmware
1800 *
1801 * Return: CDF status
1802 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301803QDF_STATUS wma_roam_scan_offload_ap_profile(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001804 wmi_ap_profile *ap_profile_p,
1805 uint32_t vdev_id)
1806{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301807 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001808 wmi_buf_t buf = NULL;
1809 int status = 0;
1810 int len;
1811 uint8_t *buf_ptr;
1812 wmi_roam_ap_profile_fixed_param *roam_ap_profile_fp;
1813
1814 len = sizeof(wmi_roam_ap_profile_fixed_param) + sizeof(wmi_ap_profile);
1815
1816 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
1817 if (!buf) {
1818 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301819 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001820 }
1821
1822 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1823 roam_ap_profile_fp = (wmi_roam_ap_profile_fixed_param *) buf_ptr;
1824 WMITLV_SET_HDR(&roam_ap_profile_fp->tlv_header,
1825 WMITLV_TAG_STRUC_wmi_roam_ap_profile_fixed_param,
1826 WMITLV_GET_STRUCT_TLVLEN
1827 (wmi_roam_ap_profile_fixed_param));
1828 /* fill in threshold values */
1829 roam_ap_profile_fp->vdev_id = vdev_id;
1830 roam_ap_profile_fp->id = 0;
1831 buf_ptr += sizeof(wmi_roam_ap_profile_fixed_param);
1832
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301833 qdf_mem_copy(buf_ptr, ap_profile_p, sizeof(wmi_ap_profile));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001834 WMITLV_SET_HDR(buf_ptr,
1835 WMITLV_TAG_STRUC_wmi_ap_profile,
1836 WMITLV_GET_STRUCT_TLVLEN(wmi_ap_profile));
1837 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
1838 len, WMI_ROAM_AP_PROFILE);
1839 if (status != EOK) {
1840 WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_AP_PROFILE returned Error %d",
1841 status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301842 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843 goto error;
1844 }
1845
1846 WMA_LOGI("WMA --> WMI_ROAM_AP_PROFILE and other parameters");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301847 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001848error:
1849 wmi_buf_free(buf);
1850
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301851 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001852}
1853
1854/**
1855 * wma_roam_scan_filter() - Filter to be applied while roaming
1856 * @wma_handle: Global WMA Handle
1857 * @roam_req: Request which contains the filters
1858 *
1859 * There are filters such as whitelist, blacklist and preferred
1860 * list that need to be applied to the scan results to form the
1861 * probable candidates for roaming.
1862 *
1863 * Return: Return success upon succesfully passing the
1864 * parameters to the firmware, otherwise failure.
1865 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301866QDF_STATUS wma_roam_scan_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001867 tSirRoamOffloadScanReq *roam_req)
1868{
1869 wmi_buf_t buf = NULL;
1870 int status = 0, i;
1871 uint32_t len, num_bssid_black_list = 0, num_ssid_white_list = 0,
1872 num_bssid_preferred_list = 0;
1873 uint32_t op_bitmap = 0;
1874 uint8_t *buf_ptr;
1875 wmi_roam_filter_fixed_param *roam_filter;
1876 uint8_t *bssid_src_ptr = NULL;
1877 wmi_mac_addr *bssid_dst_ptr = NULL;
1878 wmi_ssid *ssid_ptr = NULL;
1879 uint32_t *bssid_preferred_factor_ptr = NULL;
1880 struct roam_ext_params *roam_params;
1881
1882 roam_params = &roam_req->roam_params;
1883 len = sizeof(wmi_roam_filter_fixed_param);
1884 len += WMI_TLV_HDR_SIZE;
1885 if (roam_req->Command != ROAM_SCAN_OFFLOAD_STOP) {
1886 switch (roam_req->reason) {
1887 case REASON_ROAM_SET_BLACKLIST_BSSID:
1888 op_bitmap |= 0x1;
1889 num_bssid_black_list =
1890 roam_params->num_bssid_avoid_list;
1891 len += num_bssid_black_list * sizeof(wmi_mac_addr);
1892 len += WMI_TLV_HDR_SIZE;
1893 break;
1894 case REASON_ROAM_SET_SSID_ALLOWED:
1895 op_bitmap |= 0x2;
1896 num_ssid_white_list =
1897 roam_params->num_ssid_allowed_list;
1898 len += num_ssid_white_list * sizeof(wmi_ssid);
1899 len += WMI_TLV_HDR_SIZE;
1900 break;
1901 case REASON_ROAM_SET_FAVORED_BSSID:
1902 op_bitmap |= 0x4;
1903 num_bssid_preferred_list =
1904 roam_params->num_bssid_favored;
1905 len += num_bssid_preferred_list * sizeof(wmi_mac_addr);
1906 len += WMI_TLV_HDR_SIZE;
1907 len += num_bssid_preferred_list * sizeof(A_UINT32);
1908 break;
1909 default:
1910 WMA_LOGD("%s : Roam Filter need not be sent", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301911 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001912 break;
1913 }
1914 } else {
1915 /* In case of STOP command, reset all the variables
1916 * except for blacklist BSSID which should be retained
1917 * across connections.*/
1918 op_bitmap = 0x2 | 0x4;
1919 num_ssid_white_list = roam_params->num_ssid_allowed_list;
1920 len += num_ssid_white_list * sizeof(wmi_ssid);
1921 num_bssid_preferred_list = roam_params->num_bssid_favored;
1922 len += num_bssid_preferred_list * sizeof(wmi_mac_addr);
1923 len += num_bssid_preferred_list * sizeof(A_UINT32);
1924 len += (2 * WMI_TLV_HDR_SIZE);
1925 }
1926 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
1927 if (!buf) {
1928 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301929 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001930 }
1931
1932 buf_ptr = (u_int8_t *) wmi_buf_data(buf);
1933 roam_filter = (wmi_roam_filter_fixed_param *) buf_ptr;
1934 WMITLV_SET_HDR(&roam_filter->tlv_header,
1935 WMITLV_TAG_STRUC_wmi_roam_filter_fixed_param,
1936 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_filter_fixed_param));
1937 /* fill in fixed values */
1938 roam_filter->vdev_id = roam_req->sessionId;
1939 roam_filter->flags = 0;
1940 roam_filter->op_bitmap = op_bitmap;
1941 roam_filter->num_bssid_black_list = num_bssid_black_list;
1942 roam_filter->num_ssid_white_list = num_ssid_white_list;
1943 roam_filter->num_bssid_preferred_list = num_bssid_preferred_list;
1944 buf_ptr += sizeof(wmi_roam_filter_fixed_param);
1945
1946 WMITLV_SET_HDR((buf_ptr),
1947 WMITLV_TAG_ARRAY_FIXED_STRUC,
1948 (num_bssid_black_list * sizeof(wmi_mac_addr)));
1949 bssid_src_ptr = (uint8_t *)&roam_params->bssid_avoid_list;
1950 bssid_dst_ptr = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE);
1951 for (i = 0; i < num_bssid_black_list; i++) {
1952 WMI_CHAR_ARRAY_TO_MAC_ADDR(bssid_src_ptr, bssid_dst_ptr);
1953 bssid_src_ptr += ATH_MAC_LEN;
1954 bssid_dst_ptr++;
1955 }
1956 buf_ptr += WMI_TLV_HDR_SIZE +
1957 (num_bssid_black_list * sizeof(wmi_mac_addr));
1958 WMITLV_SET_HDR((buf_ptr),
1959 WMITLV_TAG_ARRAY_FIXED_STRUC,
1960 (num_ssid_white_list * sizeof(wmi_ssid)));
1961 ssid_ptr = (wmi_ssid *)(buf_ptr + WMI_TLV_HDR_SIZE);
1962 for (i = 0; i < num_ssid_white_list; i++) {
1963 memcpy(&ssid_ptr->ssid, &roam_params->ssid_allowed_list[i].ssId,
1964 roam_params->ssid_allowed_list[i].length);
1965 ssid_ptr->ssid_len = roam_params->ssid_allowed_list[i].length;
1966 WMA_LOGD("%s: SSID length=%d", __func__, ssid_ptr->ssid_len);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301967 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968 (uint8_t *)ssid_ptr->ssid,
1969 ssid_ptr->ssid_len);
1970 ssid_ptr++;
1971 }
1972 buf_ptr += WMI_TLV_HDR_SIZE + (num_ssid_white_list * sizeof(wmi_ssid));
1973 WMITLV_SET_HDR((buf_ptr),
1974 WMITLV_TAG_ARRAY_FIXED_STRUC,
1975 (num_bssid_preferred_list * sizeof(wmi_mac_addr)));
1976 bssid_src_ptr = (uint8_t *)&roam_params->bssid_favored;
1977 bssid_dst_ptr = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE);
1978 for (i = 0; i < num_bssid_preferred_list; i++) {
1979 WMI_CHAR_ARRAY_TO_MAC_ADDR(bssid_src_ptr,
1980 (wmi_mac_addr *)bssid_dst_ptr);
1981 bssid_src_ptr += ATH_MAC_LEN;
1982 bssid_dst_ptr++;
1983 }
1984 buf_ptr += WMI_TLV_HDR_SIZE +
1985 (num_bssid_preferred_list * sizeof(wmi_mac_addr));
1986 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
1987 (num_bssid_preferred_list * sizeof(uint32_t)));
1988 bssid_preferred_factor_ptr = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE);
1989 for (i = 0; i < num_bssid_preferred_list; i++) {
1990 *bssid_preferred_factor_ptr =
1991 roam_params->bssid_favored_factor[i];
1992 bssid_preferred_factor_ptr++;
1993 }
1994 buf_ptr += WMI_TLV_HDR_SIZE +
1995 (num_bssid_preferred_list * sizeof(uint32_t));
1996 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
1997 len, WMI_ROAM_FILTER_CMDID);
1998 if (status != EOK) {
1999 WMA_LOGE("cmd WMI_ROAM_FILTER_CMDID returned Error %d",
2000 status);
2001 goto error;
2002 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302003 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002004error:
2005 wmi_buf_free(buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302006 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002007}
2008
2009/**
2010 * wma_roam_scan_bmiss_cnt() - set bmiss count to fw
2011 * @wma_handle: wma handle
2012 * @first_bcnt: first bmiss count
2013 * @final_bcnt: final bmiss count
2014 * @vdev_id: vdev id
2015 *
2016 * set first & final biss count to fw.
2017 *
2018 * Return: CDF status
2019 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302020QDF_STATUS wma_roam_scan_bmiss_cnt(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002021 A_INT32 first_bcnt,
2022 A_UINT32 final_bcnt, uint32_t vdev_id)
2023{
2024 int status = 0;
2025
2026 WMA_LOGI("%s: first_bcnt=%d, final_bcnt=%d", __func__, first_bcnt,
2027 final_bcnt);
2028
2029 status = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle,
2030 vdev_id,
2031 WMI_VDEV_PARAM_BMISS_FIRST_BCNT,
2032 first_bcnt);
2033 if (status != EOK) {
2034 WMA_LOGE("wmi_unified_vdev_set_param_send WMI_VDEV_PARAM_BMISS_FIRST_BCNT returned Error %d",
2035 status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302036 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002037 }
2038
2039 status = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle,
2040 vdev_id,
2041 WMI_VDEV_PARAM_BMISS_FINAL_BCNT,
2042 final_bcnt);
2043 if (status != EOK) {
2044 WMA_LOGE("wmi_unified_vdev_set_param_send WMI_VDEV_PARAM_BMISS_FINAL_BCNT returned Error %d",
2045 status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302046 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002047 }
2048
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302049 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002050}
2051
2052/**
2053 * wma_roam_scan_offload_command() - set roam offload command
2054 * @wma_handle: wma handle
2055 * @command: command
2056 * @vdev_id: vdev id
2057 *
2058 * This function set roam offload command to fw.
2059 *
2060 * Return: CDF status
2061 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302062QDF_STATUS wma_roam_scan_offload_command(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002063 uint32_t command, uint32_t vdev_id)
2064{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302065 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002066 wmi_roam_scan_cmd_fixed_param *cmd_fp;
2067 wmi_buf_t buf = NULL;
2068 int status = 0;
2069 int len;
2070 uint8_t *buf_ptr;
2071
2072 len = sizeof(wmi_roam_scan_cmd_fixed_param);
2073 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
2074 if (!buf) {
2075 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302076 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002077 }
2078
2079 buf_ptr = (uint8_t *) wmi_buf_data(buf);
2080
2081 cmd_fp = (wmi_roam_scan_cmd_fixed_param *) buf_ptr;
2082 WMITLV_SET_HDR(&cmd_fp->tlv_header,
2083 WMITLV_TAG_STRUC_wmi_roam_scan_cmd_fixed_param,
2084 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_scan_cmd_fixed_param));
2085 cmd_fp->vdev_id = vdev_id;
2086 cmd_fp->command_arg = command;
2087
2088 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
2089 len, WMI_ROAM_SCAN_CMD);
2090 if (status != EOK) {
2091 WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_SCAN_CMD returned Error %d",
2092 status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302093 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002094 goto error;
2095 }
2096
2097 WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_CMD", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302098 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002099
2100error:
2101 wmi_buf_free(buf);
2102
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302103 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002104}
2105
2106/**
2107 * wma_process_roam_scan_req() - process roam request
2108 * @wma_handle: wma handle
2109 * @roam_req: roam request parameters
2110 *
2111 * Main routine to handle ROAM commands coming from CSR module.
2112 *
2113 * Return: CDF status
2114 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302115QDF_STATUS wma_process_roam_scan_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002116 tSirRoamOffloadScanReq *roam_req)
2117{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302118 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002119 wmi_start_scan_cmd_fixed_param scan_params;
2120 wmi_ap_profile ap_profile;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302121 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002122 uint32_t mode = 0;
2123 struct wma_txrx_node *intr = NULL;
2124
2125 WMA_LOGI("%s: command 0x%x, reason %d", __func__, roam_req->Command,
2126 roam_req->reason);
2127
2128 if (NULL == pMac) {
2129 WMA_LOGE("%s: pMac is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302130 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002131 }
2132
2133 if (!wma_handle->roam_offload_enabled) {
2134 /* roam scan offload is not enabled in firmware.
2135 * Cannot initialize it in the middle of connection.
2136 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302137 qdf_mem_free(roam_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302138 return QDF_STATUS_E_PERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002139 }
2140 switch (roam_req->Command) {
2141 case ROAM_SCAN_OFFLOAD_START:
2142 intr = &wma_handle->interfaces[roam_req->sessionId];
2143 intr->delay_before_vdev_stop = roam_req->delay_before_vdev_stop;
2144 /*
2145 * Scan/Roam threshold parameters are translated from fields of
2146 * tSirRoamOffloadScanReq to WMITLV values sent to Rome firmware.
2147 * some of these parameters are configurable in qcom_cfg.ini file.
2148 */
2149
2150 /* First parameter is positive rssi value to trigger rssi based scan.
2151 * Opportunistic scan is started at 30 dB higher that trigger rssi.
2152 */
2153 wma_handle->suitable_ap_hb_failure = false;
2154
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302155 qdf_status = wma_roam_scan_offload_rssi_thresh(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002156 roam_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302157 if (qdf_status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002158 break;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302159 qdf_status = wma_roam_scan_bmiss_cnt(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002160 roam_req->RoamBmissFirstBcnt,
2161 roam_req->RoamBmissFinalBcnt,
2162 roam_req->sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302163 if (qdf_status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002164 break;
2165
2166 /* Opportunistic scan runs on a timer, value set by
2167 * EmptyRefreshScanPeriod. Age out the entries after 3 such
2168 * cycles.
2169 */
2170 if (roam_req->EmptyRefreshScanPeriod > 0) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302171 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002172 wma_roam_scan_offload_scan_period(wma_handle,
2173 roam_req->EmptyRefreshScanPeriod,
2174 roam_req->EmptyRefreshScanPeriod * 3,
2175 roam_req->sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302176 if (qdf_status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002177 break;
2178
2179 mode = WMI_ROAM_SCAN_MODE_PERIODIC;
2180 /* Don't use rssi triggered roam scans if external app
2181 * is in control of channel list.
2182 */
2183 if (roam_req->ChannelCacheType != CHANNEL_LIST_STATIC)
2184 mode |= WMI_ROAM_SCAN_MODE_RSSI_CHANGE;
2185
2186 } else {
2187 mode = WMI_ROAM_SCAN_MODE_RSSI_CHANGE;
2188 }
2189
2190 /* Start new rssi triggered scan only if it changes by RoamRssiDiff value.
2191 * Beacon weight of 14 means average rssi is taken over 14 previous samples +
2192 * 2 times the current beacon's rssi.
2193 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302194 qdf_status = wma_roam_scan_offload_rssi_change(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002195 roam_req->sessionId,
2196 roam_req->RoamRescanRssiDiff,
2197 roam_req->RoamBeaconRssiWeight,
2198 roam_req->hi_rssi_scan_delay);
2199
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302200 if (qdf_status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002201 break;
2202
2203 wma_roam_scan_fill_ap_profile(wma_handle, pMac, roam_req,
2204 &ap_profile);
2205
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302206 qdf_status = wma_roam_scan_offload_ap_profile(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002207 &ap_profile,
2208 roam_req->sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302209 if (qdf_status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002210 break;
2211
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302212 qdf_status = wma_roam_scan_offload_chan_list(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002213 roam_req->ConnectedNetwork.ChannelCount,
2214 &roam_req->ConnectedNetwork.ChannelCache[0],
2215 roam_req->ChannelCacheType,
2216 roam_req->sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302217 if ((qdf_status != QDF_STATUS_SUCCESS) &&
2218 (qdf_status != QDF_STATUS_E_EMPTY))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002219 break;
2220
2221
2222 wma_roam_scan_fill_scan_params(wma_handle, pMac, roam_req,
2223 &scan_params);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302224 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002225 wma_roam_scan_offload_mode(wma_handle, &scan_params,
2226 roam_req, mode,
2227 roam_req->sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302228 if (qdf_status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002229 break;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302230 qdf_status = wma_roam_scan_filter(wma_handle, roam_req);
2231 if (qdf_status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002232 WMA_LOGE("Sending start for roam scan filter failed");
2233 break;
2234 }
2235 break;
2236
2237 case ROAM_SCAN_OFFLOAD_STOP:
2238 wma_handle->suitable_ap_hb_failure = false;
2239 if (wma_handle->roam_offload_enabled) {
2240
2241 wma_roam_scan_fill_scan_params(wma_handle, pMac,
2242 NULL, &scan_params);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302243 qdf_status = wma_roam_scan_offload_mode(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002244 &scan_params,
2245 NULL,
2246 WMI_ROAM_SCAN_MODE_NONE,
2247 roam_req->sessionId);
2248 }
2249 /*
2250 * If the STOP command is due to a disconnect, then
2251 * send the filter command to clear all the filter
2252 * entries. If it is roaming scenario, then do not
2253 * send the cleared entries.
2254 */
2255 if (!roam_req->middle_of_roaming) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302256 qdf_status = wma_roam_scan_filter(wma_handle, roam_req);
2257 if (qdf_status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002258 WMA_LOGE("clear for roam scan filter failed");
2259 break;
2260 }
2261 }
2262
2263 if (roam_req->reason ==
2264 REASON_OS_REQUESTED_ROAMING_NOW) {
2265 cds_msg_t cds_msg;
2266 tSirRoamOffloadScanRsp *scan_offload_rsp;
2267 scan_offload_rsp =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302268 qdf_mem_malloc(sizeof(*scan_offload_rsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002269 if (!scan_offload_rsp) {
2270 WMA_LOGE("%s: Alloc failed for scan_offload_rsp",
2271 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302272 qdf_mem_free(roam_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302273 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002274 }
2275 cds_msg.type = eWNI_SME_ROAM_SCAN_OFFLOAD_RSP;
2276 scan_offload_rsp->sessionId = roam_req->sessionId;
2277 scan_offload_rsp->reason = roam_req->reason;
2278 cds_msg.bodyptr = scan_offload_rsp;
2279 /*
2280 * Since REASSOC request is processed in
2281 * Roam_Scan_Offload_Rsp post a dummy rsp msg back to
2282 * SME with proper reason code.
2283 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302284 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002285 cds_mq_post_message(CDS_MQ_ID_SME,
2286 (cds_msg_t *) &cds_msg)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302287 qdf_mem_free(scan_offload_rsp);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302288 QDF_TRACE(QDF_MODULE_ID_WMA,
2289 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002290 "%s: Failed to post Scan Offload Rsp to UMAC",
2291 __func__);
2292 }
2293 }
2294 break;
2295
2296 case ROAM_SCAN_OFFLOAD_ABORT_SCAN:
2297 /* If roam scan is running, stop that cycle.
2298 * It will continue automatically on next trigger.
2299 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302300 qdf_status = wma_roam_scan_offload_command(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002301 WMI_ROAM_SCAN_STOP_CMD,
2302 roam_req->sessionId);
2303 break;
2304
2305 case ROAM_SCAN_OFFLOAD_RESTART:
2306 /* Rome offload engine does not stop after any scan.
2307 * If this command is sent because all preauth attempts failed
2308 * and WMI_ROAM_REASON_SUITABLE_AP event was received earlier,
2309 * now it is time to call it heartbeat failure.
2310 */
2311 if ((roam_req->reason == REASON_PREAUTH_FAILED_FOR_ALL)
2312 && wma_handle->suitable_ap_hb_failure) {
2313 WMA_LOGE("%s: Sending heartbeat failure after preauth failures",
2314 __func__);
2315 wma_beacon_miss_handler(wma_handle,
2316 roam_req->sessionId);
2317 wma_handle->suitable_ap_hb_failure = false;
2318 }
2319 break;
2320
2321 case ROAM_SCAN_OFFLOAD_UPDATE_CFG:
2322 wma_handle->suitable_ap_hb_failure = false;
2323 wma_roam_scan_fill_scan_params(wma_handle, pMac, roam_req,
2324 &scan_params);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302325 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002326 wma_roam_scan_offload_mode(wma_handle, &scan_params,
2327 roam_req,
2328 WMI_ROAM_SCAN_MODE_NONE,
2329 roam_req->sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302330 if (qdf_status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002331 break;
2332
2333 if (roam_req->RoamScanOffloadEnabled == false)
2334 break;
2335
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302336 qdf_status = wma_roam_scan_bmiss_cnt(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002337 roam_req->RoamBmissFirstBcnt,
2338 roam_req->RoamBmissFinalBcnt,
2339 roam_req->sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302340 if (qdf_status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002341 break;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302342 qdf_status = wma_roam_scan_filter(wma_handle, roam_req);
2343 if (qdf_status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002344 WMA_LOGE("Sending update for roam scan filter failed");
2345 break;
2346 }
2347
2348
2349 /*
2350 * Runtime (after association) changes to rssi thresholds and
2351 * other parameters.
2352 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302353 qdf_status = wma_roam_scan_offload_chan_list(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002354 roam_req->ConnectedNetwork.ChannelCount,
2355 &roam_req->ConnectedNetwork.ChannelCache[0],
2356 roam_req->ChannelCacheType,
2357 roam_req->sessionId);
2358 /*
2359 * Even though the channel list is empty, we can
2360 * still go ahead and start Roaming.
2361 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302362 if ((qdf_status != QDF_STATUS_SUCCESS) &&
2363 (qdf_status != QDF_STATUS_E_EMPTY))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002364 break;
2365
2366
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302367 qdf_status = wma_roam_scan_offload_rssi_thresh(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002368 roam_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302369 if (qdf_status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002370 break;
2371
2372 if (roam_req->EmptyRefreshScanPeriod > 0) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302373 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002374 wma_roam_scan_offload_scan_period(wma_handle,
2375 roam_req->EmptyRefreshScanPeriod,
2376 roam_req->EmptyRefreshScanPeriod * 3,
2377 roam_req->sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302378 if (qdf_status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002379 break;
2380
2381 mode = WMI_ROAM_SCAN_MODE_PERIODIC;
2382 /* Don't use rssi triggered roam scans if external app
2383 * is in control of channel list.
2384 */
2385 if (roam_req->ChannelCacheType != CHANNEL_LIST_STATIC)
2386 mode |= WMI_ROAM_SCAN_MODE_RSSI_CHANGE;
2387
2388 } else {
2389 mode = WMI_ROAM_SCAN_MODE_RSSI_CHANGE;
2390 }
2391
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302392 qdf_status = wma_roam_scan_offload_rssi_change(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002393 roam_req->sessionId,
2394 roam_req->RoamRescanRssiDiff,
2395 roam_req->RoamBeaconRssiWeight,
2396 roam_req->hi_rssi_scan_delay);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302397 if (qdf_status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002398 break;
2399
2400 wma_roam_scan_fill_ap_profile(wma_handle, pMac, roam_req,
2401 &ap_profile);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302402 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002403 wma_roam_scan_offload_ap_profile(wma_handle, &ap_profile,
2404 roam_req->sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302405 if (qdf_status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002406 break;
2407
2408 wma_roam_scan_fill_scan_params(wma_handle, pMac, roam_req,
2409 &scan_params);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302410 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002411 wma_roam_scan_offload_mode(wma_handle, &scan_params,
2412 roam_req, mode,
2413 roam_req->sessionId);
2414
2415 break;
2416
2417 default:
2418 break;
2419 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302420 qdf_mem_free(roam_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302421 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002422}
2423
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002424#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2425
2426/**
2427 * wma_process_roam_invoke() - send roam invoke command to fw.
2428 * @handle: wma handle
2429 * @roaminvoke: roam invoke command
2430 *
2431 * Send roam invoke command to fw for fastreassoc.
2432 *
2433 * Return: none
2434 */
2435void wma_process_roam_invoke(WMA_HANDLE handle,
2436 struct wma_roam_invoke_cmd *roaminvoke)
2437{
2438 tp_wma_handle wma_handle = (tp_wma_handle) handle;
2439 wmi_roam_invoke_cmd_fixed_param *cmd;
2440 wmi_buf_t wmi_buf;
2441 u_int8_t *buf_ptr;
2442 u_int16_t len, args_tlv_len;
2443 A_UINT32 *channel_list;
2444 wmi_mac_addr *bssid_list;
2445
2446 if (!wma_handle || !wma_handle->wmi_handle) {
2447 WMA_LOGE("%s: WMA is closed, can not send roam invoke",
2448 __func__);
2449 return;
2450 }
2451 /* Host sends only one channel and one bssid */
2452 args_tlv_len = 2 * WMI_TLV_HDR_SIZE + sizeof(A_UINT32) +
2453 sizeof(wmi_mac_addr);
2454 len = sizeof(wmi_roam_invoke_cmd_fixed_param) + args_tlv_len;
2455 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
2456 if (!wmi_buf) {
2457 WMA_LOGE("%s: wmai_buf_alloc failed", __func__);
2458 return;
2459 }
2460
2461 cmd = (wmi_roam_invoke_cmd_fixed_param *)wmi_buf_data(wmi_buf);
2462 buf_ptr = (u_int8_t *) cmd;
2463 WMITLV_SET_HDR(&cmd->tlv_header,
2464 WMITLV_TAG_STRUC_wmi_roam_invoke_cmd_fixed_param,
2465 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_invoke_cmd_fixed_param));
2466 cmd->vdev_id = roaminvoke->vdev_id;
2467 cmd->flags = 0;
2468 cmd->roam_scan_mode = 0;
2469 cmd->roam_ap_sel_mode = 0;
2470 cmd->roam_delay = 0;
2471 cmd->num_chan = 1;
2472 cmd->num_bssid = 1;
2473 buf_ptr += sizeof(wmi_roam_invoke_cmd_fixed_param);
2474 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
2475 (sizeof(u_int32_t)));
2476 channel_list = (A_UINT32 *)(buf_ptr + WMI_TLV_HDR_SIZE);
2477 *channel_list = (A_UINT32)cds_chan_to_freq(roaminvoke->channel);
2478 buf_ptr += sizeof(A_UINT32) + WMI_TLV_HDR_SIZE;
2479 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
2480 (sizeof(wmi_mac_addr)));
2481 bssid_list = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE);
2482 WMI_CHAR_ARRAY_TO_MAC_ADDR(roaminvoke->bssid, bssid_list);
2483 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
2484 WMI_ROAM_INVOKE_CMDID)) {
2485 WMA_LOGP("%s: failed to send roam invoke command", __func__);
2486 wmi_buf_free(wmi_buf);
2487 return;
2488 }
2489 return;
2490}
2491
2492/**
2493 * wma_process_roam_synch_fail() -roam synch failure handle
2494 * @handle: wma handle
2495 * @synch_fail: roam synch fail parameters
2496 *
2497 * Return: none
2498 */
2499void wma_process_roam_synch_fail(WMA_HANDLE handle,
2500 struct roam_offload_synch_fail *synch_fail)
2501{
2502 tp_wma_handle wma_handle = (tp_wma_handle) handle;
2503 if (!wma_handle || !wma_handle->wmi_handle) {
2504 WMA_LOGE("%s: WMA is closed, can not clean-up roam synch",
2505 __func__);
2506 return;
2507 }
2508 /* Hand Off Failure could happen as an exception, when a roam synch
2509 * indication is posted to Host, but a roam synch complete is not
2510 * posted to the firmware.So, clear the roam synch in progress
2511 * flag before disconnecting the session through this event.*/
2512 wma_handle->interfaces[synch_fail->session_id].roam_synch_in_progress =
2513 false;
2514}
2515
2516/**
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002517 * wma_fill_roam_synch_buffer() - Fill the the roam sync buffer
2518 * @wma: Global WMA Handle
2519 * @roam_synch_ind_ptr: Buffer to be filled
2520 * @param_buf: Source buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002521 *
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002522 * Firmware sends all the required information required for roam
2523 * synch propagation as TLV's and stored in param_buf. These
2524 * parameters are parsed and filled into the roam synch indication
2525 * buffer which will be used at different layers for propagation.
2526 *
2527 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002528 */
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002529void wma_fill_roam_synch_buffer(tp_wma_handle wma,
2530 roam_offload_synch_ind *roam_synch_ind_ptr,
2531 WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002532{
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002533 wmi_roam_synch_event_fixed_param *synch_event;
2534 uint8_t *bcn_probersp_ptr;
2535 uint8_t *reassoc_rsp_ptr;
2536 uint8_t *reassoc_req_ptr;
2537 wmi_channel *chan;
2538 wmi_key_material *key;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539
2540 synch_event = param_buf->fixed_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002541 roam_synch_ind_ptr->roamedVdevId = synch_event->vdev_id;
2542 roam_synch_ind_ptr->authStatus = synch_event->auth_status;
2543 roam_synch_ind_ptr->roamReason = synch_event->roam_reason;
2544 roam_synch_ind_ptr->rssi = synch_event->rssi;
2545 roam_synch_ind_ptr->isBeacon = synch_event->is_beacon;
2546 WMI_MAC_ADDR_TO_CHAR_ARRAY(&synch_event->bssid,
Srinivas Girigowda198b2032015-11-24 11:37:34 -08002547 roam_synch_ind_ptr->bssid.bytes);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002548 wma->csr_roam_synch_cb((tpAniSirGlobal)wma->mac_context,
2549 roam_synch_ind_ptr, NULL, ROAMING_TX_QUEUE_DISABLE);
Naveen Rawat14298b92015-11-25 16:27:41 -08002550 /* Beacon/Probe Rsp data */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002551 roam_synch_ind_ptr->beaconProbeRespOffset =
2552 sizeof(roam_offload_synch_ind);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002553 bcn_probersp_ptr = (uint8_t *) roam_synch_ind_ptr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554 roam_synch_ind_ptr->beaconProbeRespOffset;
2555 roam_synch_ind_ptr->beaconProbeRespLength =
2556 synch_event->bcn_probe_rsp_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302557 qdf_mem_copy(bcn_probersp_ptr, param_buf->bcn_probe_rsp_frame,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002558 roam_synch_ind_ptr->beaconProbeRespLength);
Naveen Rawat14298b92015-11-25 16:27:41 -08002559 /* ReAssoc Rsp data */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002560 roam_synch_ind_ptr->reassocRespOffset =
2561 sizeof(roam_offload_synch_ind) +
2562 roam_synch_ind_ptr->beaconProbeRespLength;
2563 roam_synch_ind_ptr->reassocRespLength = synch_event->reassoc_rsp_len;
2564 reassoc_rsp_ptr = (uint8_t *) roam_synch_ind_ptr +
2565 roam_synch_ind_ptr->reassocRespOffset;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302566 qdf_mem_copy(reassoc_rsp_ptr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002567 param_buf->reassoc_rsp_frame,
2568 roam_synch_ind_ptr->reassocRespLength);
Naveen Rawat14298b92015-11-25 16:27:41 -08002569
2570 /* ReAssoc Req data */
2571 roam_synch_ind_ptr->reassoc_req_offset =
2572 sizeof(roam_offload_synch_ind) +
2573 roam_synch_ind_ptr->beaconProbeRespLength +
2574 roam_synch_ind_ptr->reassocRespLength;
2575 roam_synch_ind_ptr->reassoc_req_length = synch_event->reassoc_req_len;
2576 reassoc_req_ptr = (uint8_t *) roam_synch_ind_ptr +
2577 roam_synch_ind_ptr->reassoc_req_offset;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302578 qdf_mem_copy(reassoc_req_ptr, param_buf->reassoc_req_frame,
Naveen Rawat14298b92015-11-25 16:27:41 -08002579 roam_synch_ind_ptr->reassoc_req_length);
2580
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002581 chan = (wmi_channel *) param_buf->chan;
2582 roam_synch_ind_ptr->chan_freq = chan->mhz;
2583 key = (wmi_key_material *) param_buf->key;
2584 if (key != NULL) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302585 qdf_mem_copy(roam_synch_ind_ptr->kck, key->kck,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002586 SIR_KCK_KEY_LEN);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302587 qdf_mem_copy(roam_synch_ind_ptr->kek, key->kek,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002588 SIR_KEK_KEY_LEN);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302589 qdf_mem_copy(roam_synch_ind_ptr->replay_ctr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002590 key->replay_counter, SIR_REPLAY_CTR_LEN);
Naveen Rawat14298b92015-11-25 16:27:41 -08002591 WMA_LOGD("%s: KCK dump", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302592 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
Naveen Rawat14298b92015-11-25 16:27:41 -08002593 key->kck, SIR_KCK_KEY_LEN);
2594 WMA_LOGD("%s: KEK dump", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302595 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
Naveen Rawat14298b92015-11-25 16:27:41 -08002596 key->kek, SIR_KEK_KEY_LEN);
2597 WMA_LOGD("%s: Key Replay Counter dump", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302598 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
Naveen Rawat14298b92015-11-25 16:27:41 -08002599 key->replay_counter, SIR_REPLAY_CTR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600 }
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002601}
2602
2603/**
2604 * wma_roam_update_vdev() - Update the STA and BSS
2605 * @wma: Global WMA Handle
2606 * @roam_synch_ind_ptr: Information needed for roam sync propagation
2607 *
2608 * This function will perform all the vdev related operations with
2609 * respect to the self sta and the peer after roaming and completes
2610 * the roam synch propagation with respect to WMA layer.
2611 *
2612 * Return: None
2613 */
2614void wma_roam_update_vdev(tp_wma_handle wma,
2615 roam_offload_synch_ind *roam_synch_ind_ptr)
2616{
2617 tDeleteBssParams *del_bss_params;
2618 tDeleteStaParams *del_sta_params;
2619 tLinkStateParams *set_link_params;
2620 tAddStaParams *add_sta_params;
2621 uint8_t vdev_id;
2622
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302623 del_bss_params = qdf_mem_malloc(sizeof(*del_bss_params));
2624 del_sta_params = qdf_mem_malloc(sizeof(*del_sta_params));
2625 set_link_params = qdf_mem_malloc(sizeof(*set_link_params));
2626 add_sta_params = qdf_mem_malloc(sizeof(*add_sta_params));
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002627 if (!del_bss_params || !del_sta_params ||
2628 !set_link_params || !add_sta_params) {
2629 WMA_LOGE("%s: failed to allocate memory", __func__);
2630 return;
2631 }
2632 vdev_id = roam_synch_ind_ptr->roamedVdevId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302633 qdf_mem_zero(del_bss_params, sizeof(*del_bss_params));
2634 qdf_mem_zero(del_sta_params, sizeof(*del_sta_params));
2635 qdf_mem_zero(set_link_params, sizeof(*set_link_params));
2636 qdf_mem_zero(add_sta_params, sizeof(*add_sta_params));
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002637
2638 del_bss_params->smesessionId = vdev_id;
2639 del_sta_params->smesessionId = vdev_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302640 qdf_mem_copy(del_bss_params->bssid, wma->interfaces[vdev_id].bssid,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002641 IEEE80211_ADDR_LEN);
2642 set_link_params->state = eSIR_LINK_PREASSOC_STATE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302643 qdf_mem_copy(set_link_params->selfMacAddr, wma->myaddr,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002644 IEEE80211_ADDR_LEN);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302645 qdf_mem_copy(set_link_params->bssid, roam_synch_ind_ptr->bssid.bytes,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002646 IEEE80211_ADDR_LEN);
2647 add_sta_params->staType = STA_ENTRY_SELF;
2648 add_sta_params->smesessionId = vdev_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302649 qdf_mem_copy(&add_sta_params->bssId, &roam_synch_ind_ptr->bssid.bytes,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002650 IEEE80211_ADDR_LEN);
2651 add_sta_params->staIdx = STA_INVALID_IDX;
2652 add_sta_params->assocId = roam_synch_ind_ptr->aid;
2653
2654 wma_delete_sta(wma, del_sta_params);
2655 wma_delete_bss(wma, del_bss_params);
2656 wma_set_linkstate(wma, set_link_params);
2657 wma_add_bss(wma, (tpAddBssParams)roam_synch_ind_ptr->add_bss_params);
2658 wma_add_sta(wma, add_sta_params);
2659 wma->interfaces[vdev_id].vdev_up = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302660 qdf_mem_copy(wma->interfaces[vdev_id].bssid,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002661 roam_synch_ind_ptr->bssid.bytes, IEEE80211_ADDR_LEN);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302662 qdf_mem_free(del_bss_params);
2663 qdf_mem_free(del_sta_params);
2664 qdf_mem_free(set_link_params);
2665 qdf_mem_free(add_sta_params);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002666}
2667
2668/**
2669 * wma_roam_synch_event_handler() - roam synch event handler
2670 * @handle: wma handle
2671 * @event: event data
2672 * @len: length of data
2673 *
2674 * This function is roam synch event handler. It sends roam
2675 * indication for upper layer.
2676 *
2677 * Return: Success or Failure status
2678 */
2679int wma_roam_synch_event_handler(void *handle, uint8_t *event,
2680 uint32_t len)
2681{
2682 WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf = NULL;
2683 wmi_roam_synch_event_fixed_param *synch_event = NULL;
2684 tp_wma_handle wma = (tp_wma_handle) handle;
2685 roam_offload_synch_ind *roam_synch_ind_ptr;
2686 tpSirBssDescription bss_desc_ptr = NULL;
2687 uint16_t ie_len = 0;
2688 int status = -EINVAL;
2689
2690 WMA_LOGD("LFR3:%s", __func__);
2691 if (!event) {
2692 WMA_LOGE("%s: event param null", __func__);
2693 return status;
2694 }
2695
2696 param_buf = (WMI_ROAM_SYNCH_EVENTID_param_tlvs *) event;
2697 if (!param_buf) {
2698 WMA_LOGE("%s: received null buf from target", __func__);
2699 return status;
2700 }
2701
2702 synch_event = param_buf->fixed_param;
2703 if (!synch_event) {
2704 WMA_LOGE("%s: received null event data from target", __func__);
2705 return status;
2706 }
2707
2708 if (wma_is_roam_synch_in_progress(wma, synch_event->vdev_id)) {
2709 WMA_LOGE("%s: Ignoring RSI since one is already in progress",
2710 __func__);
2711 return status;
2712 }
2713
2714 wma->interfaces[synch_event->vdev_id].roam_synch_in_progress = true;
2715 len = sizeof(roam_offload_synch_ind) +
2716 synch_event->bcn_probe_rsp_len + synch_event->reassoc_rsp_len +
2717 synch_event->reassoc_req_len;
2718 roam_synch_ind_ptr =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302719 (roam_offload_synch_ind *) qdf_mem_malloc(len);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002720 if (!roam_synch_ind_ptr) {
2721 WMA_LOGE("%s: failed to allocate memory for roam_synch_event",
2722 __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302723 QDF_ASSERT(roam_synch_ind_ptr != NULL);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002724 return -ENOMEM;
2725 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302726 qdf_mem_zero(roam_synch_ind_ptr, len);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002727 wma_fill_roam_synch_buffer(wma, roam_synch_ind_ptr, param_buf);
2728
2729 /* 24 byte MAC header and 12 byte to ssid IE */
2730 if (roam_synch_ind_ptr->beaconProbeRespLength >
2731 (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET)) {
2732 ie_len = roam_synch_ind_ptr->beaconProbeRespLength -
2733 (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET);
2734 } else {
2735 WMA_LOGE("LFR3: Invalid Beacon Length");
2736 goto cleanup_label;
2737 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302738 bss_desc_ptr = qdf_mem_malloc(sizeof(tSirBssDescription) + ie_len);
2739 roam_synch_ind_ptr->join_rsp = qdf_mem_malloc(sizeof(tSirSmeJoinRsp));
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002740 if ((NULL == roam_synch_ind_ptr->join_rsp) || (NULL == bss_desc_ptr)) {
2741 WMA_LOGE("LFR3: mem alloc failed!");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302742 QDF_ASSERT(bss_desc_ptr != NULL);
2743 QDF_ASSERT(roam_synch_ind_ptr->join_rsp != NULL);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002744 status = -ENOMEM;
2745 goto cleanup_label;
2746 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302747 qdf_mem_zero(roam_synch_ind_ptr->join_rsp, sizeof(tSirSmeJoinRsp));
2748 qdf_mem_zero(bss_desc_ptr, sizeof(tSirBssDescription) + ie_len);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002749 wma->pe_roam_synch_cb((tpAniSirGlobal)wma->mac_context,
2750 roam_synch_ind_ptr, bss_desc_ptr);
2751 wma_roam_update_vdev(wma, roam_synch_ind_ptr);
2752 wma->csr_roam_synch_cb((tpAniSirGlobal)wma->mac_context,
2753 roam_synch_ind_ptr, bss_desc_ptr, ROAM_SYNCH_PROPAGATION);
2754 wma_process_roam_synch_complete(wma, synch_event->vdev_id);
2755cleanup_label:
2756 if (roam_synch_ind_ptr->join_rsp)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302757 qdf_mem_free(roam_synch_ind_ptr->join_rsp);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002758 if (roam_synch_ind_ptr)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302759 qdf_mem_free(roam_synch_ind_ptr);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002760 if (bss_desc_ptr)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302761 qdf_mem_free(bss_desc_ptr);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002762 wma->interfaces[synch_event->vdev_id].roam_synch_in_progress = false;
2763
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002764 return 0;
2765}
2766
2767/**
2768 * wma_rssi_breached_event_handler() - rssi breached event handler
2769 * @handle: wma handle
2770 * @cmd_param_info: event handler data
2771 * @len: length of @cmd_param_info
2772 *
2773 * Return: 0 on success; error number otherwise
2774 */
2775int wma_rssi_breached_event_handler(void *handle,
2776 u_int8_t *cmd_param_info, u_int32_t len)
2777{
2778 WMI_RSSI_BREACH_EVENTID_param_tlvs *param_buf;
2779 wmi_rssi_breach_event_fixed_param *event;
2780 struct rssi_breach_event rssi;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302781 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002782
2783 if (!mac) {
2784 WMA_LOGE("%s: Invalid mac context", __func__);
2785 return -EINVAL;
2786 }
2787 if (!mac->sme.rssi_threshold_breached_cb) {
2788 WMA_LOGE("%s: Callback not registered", __func__);
2789 return -EINVAL;
2790 }
2791 param_buf = (WMI_RSSI_BREACH_EVENTID_param_tlvs *)cmd_param_info;
2792 if (!param_buf) {
2793 WMA_LOGE("%s: Invalid rssi breached event", __func__);
2794 return -EINVAL;
2795 }
2796 event = param_buf->fixed_param;
2797
2798 rssi.request_id = event->request_id;
2799 rssi.session_id = event->vdev_id;
2800 rssi.curr_rssi = event->rssi + WMA_TGT_NOISE_FLOOR_DBM;
2801 WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->bssid, rssi.curr_bssid.bytes);
2802
2803 WMA_LOGD("%s: req_id: %u vdev_id: %d curr_rssi: %d", __func__,
2804 rssi.request_id, rssi.session_id, rssi.curr_rssi);
2805 WMA_LOGI("%s: curr_bssid: %pM", __func__, rssi.curr_bssid.bytes);
2806
2807 mac->sme.rssi_threshold_breached_cb(mac->hHdd, &rssi);
2808 WMA_LOGD("%s: Invoke HDD rssi breached callback", __func__);
2809 return 0;
2810}
2811
2812/**
2813 * wma_roam_scan_fill_self_caps() - fill capabilities
2814 * @wma_handle: wma handle
2815 * @roam_offload_params: offload parameters
2816 * @roam_req: roam request
2817 *
2818 * This function fills roam self capablities.
2819 *
2820 * Return: CDF status
2821 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302822QDF_STATUS wma_roam_scan_fill_self_caps(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002823 wmi_roam_offload_tlv_param *
2824 roam_offload_params,
2825 tSirRoamOffloadScanReq *roam_req)
2826{
2827 struct sAniSirGlobal *pMac = NULL;
2828 tSirMacCapabilityInfo selfCaps;
2829 uint32_t val = 0;
2830 uint32_t nCfgValue;
2831 uint16_t *pCfgValue16;
2832 uint8_t nCfgValue8, *pCfgValue8;
2833 tSirMacQosInfoStation macQosInfoSta;
2834 union {
2835 uint16_t nCfgValue16;
2836 tSirMacHTCapabilityInfo htCapInfo;
2837 tSirMacExtendedHTCapabilityInfo extHtCapInfo;
2838 } uHTCapabilityInfo;
2839
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302840 qdf_mem_set(&macQosInfoSta, sizeof(tSirMacQosInfoStation), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002841 /* Roaming is done only for INFRA STA type.
2842 * So, ess will be one and ibss will be Zero */
Anurag Chouhan6d760662016-02-20 16:05:43 +05302843 pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002844 if (!pMac) {
2845 WMA_LOGE("%s:NULL pMac ptr. Exiting", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302846 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302847 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002848 }
2849
2850 if (wlan_cfg_get_int(pMac, WNI_CFG_PRIVACY_ENABLED, &val) != eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302851 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002852 "Failed to get WNI_CFG_PRIVACY_ENABLED");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302853 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002854 }
2855 selfCaps.ess = 1;
2856 selfCaps.ibss = 0;
2857 if (val)
2858 selfCaps.privacy = 1;
2859 if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302860 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002861 "Failed to get WNI_CFG_SHORT_PREAMBLE");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302862 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002863 }
2864 if (val)
2865 selfCaps.shortPreamble = 1;
2866
2867 selfCaps.pbcc = 0;
2868 selfCaps.channelAgility = 0;
2869 if (wlan_cfg_get_int(pMac, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED,
2870 &val) != eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302871 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002872 "Failed to get WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302873 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002874 }
2875 if (val)
2876 selfCaps.shortSlotTime = 1;
2877 if (wlan_cfg_get_int(pMac, WNI_CFG_11H_ENABLED, &val) != eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302878 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002879 "Failed to get WNI_CFG_11H_ENABLED");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302880 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002881 }
2882 if (val)
2883 selfCaps.spectrumMgt = 1;
2884 if (wlan_cfg_get_int(pMac, WNI_CFG_QOS_ENABLED, &val) != eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302885 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002886 "Failed to get WNI_CFG_QOS_ENABLED");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302887 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002888 }
2889 if (val)
2890 selfCaps.qos = 1;
2891 if (wlan_cfg_get_int(pMac, WNI_CFG_APSD_ENABLED, &val) != eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302892 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002893 "Failed to get WNI_CFG_APSD_ENABLED");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302894 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002895 }
2896 if (val)
2897 selfCaps.apsd = 1;
Krishna Kumaar Natarajan4340c682015-11-03 12:09:00 -08002898
2899 selfCaps.rrm = pMac->rrm.rrmSmeContext.rrmConfig.rrm_enabled;
2900
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002901 if (wlan_cfg_get_int(pMac, WNI_CFG_BLOCK_ACK_ENABLED, &val) !=
2902 eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302903 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002904 "Failed to get WNI_CFG_BLOCK_ACK_ENABLED");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302905 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002906 }
2907 selfCaps.delayedBA =
2908 (uint16_t) ((val >> WNI_CFG_BLOCK_ACK_ENABLED_DELAYED) & 1);
2909 selfCaps.immediateBA =
2910 (uint16_t) ((val >> WNI_CFG_BLOCK_ACK_ENABLED_IMMEDIATE) & 1);
2911 pCfgValue16 = (uint16_t *) &selfCaps;
2912 roam_offload_params->capability = (*pCfgValue16) & 0xFFFF;
2913
2914 if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &nCfgValue) !=
2915 eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302916 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002917 "Failed to get WNI_CFG_HT_CAP_INFO");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302918 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002919 }
2920 uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF;
2921 roam_offload_params->ht_caps_info =
2922 uHTCapabilityInfo.nCfgValue16 & 0xFFFF;
2923 if (wlan_cfg_get_int(pMac, WNI_CFG_HT_AMPDU_PARAMS, &nCfgValue) !=
2924 eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302925 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002926 "Failed to get WNI_CFG_HT_AMPDU_PARAMS");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302927 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002928 }
2929 /* tSirMacHTParametersInfo */
2930 nCfgValue8 = (uint8_t) nCfgValue;
2931 roam_offload_params->ampdu_param = (nCfgValue8) & 0xFF;
2932
2933 val = ROAM_OFFLOAD_NUM_MCS_SET;
2934 if (wlan_cfg_get_str(pMac, WNI_CFG_SUPPORTED_MCS_SET,
2935 (uint8_t *) roam_offload_params->mcsset,
2936 &val) != eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302937 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002938 "Failed to get WNI_CFG_SUPPORTED_MCS_SET");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302939 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002940 }
2941 if (wlan_cfg_get_int(pMac, WNI_CFG_EXT_HT_CAP_INFO, &nCfgValue) !=
2942 eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302943 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002944 "Failed to get WNI_CFG_EXT_HT_CAP_INFO");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302945 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002946 }
2947 /* uHTCapabilityInfo.extHtCapInfo */
2948 uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF;
2949 roam_offload_params->ht_ext_cap =
2950 uHTCapabilityInfo.nCfgValue16 & 0xFFFF;
2951
2952 if (wlan_cfg_get_int(pMac, WNI_CFG_TX_BF_CAP, &nCfgValue) != eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302953 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002954 "Failed to get WNI_CFG_TX_BF_CAP");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302955 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002956 }
2957 /* tSirMacTxBFCapabilityInfo */
2958 nCfgValue8 = (uint8_t) nCfgValue;
2959 roam_offload_params->ht_txbf = nCfgValue8 & 0xFF;
2960 if (wlan_cfg_get_int(pMac, WNI_CFG_AS_CAP, &nCfgValue) != eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302961 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002962 "Failed to get WNI_CFG_AS_CAP");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302963 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002964 }
2965 /* tSirMacASCapabilityInfo */
2966 nCfgValue8 = (uint8_t) nCfgValue;
2967 roam_offload_params->asel_cap = nCfgValue8 & 0xFF;
2968
2969 /* QOS Info */
2970 if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_SP_LENGTH, &nCfgValue) !=
2971 eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302972 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002973 "Failed to get WNI_CFG_MAX_SP_LENGTH");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302974 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002975 }
2976 nCfgValue8 = (uint8_t) nCfgValue;
2977 macQosInfoSta.maxSpLen = nCfgValue8;
2978 macQosInfoSta.moreDataAck = 0;
2979 macQosInfoSta.qack = 0;
2980 macQosInfoSta.acbe_uapsd = roam_req->AcUapsd.acbe_uapsd;
2981 macQosInfoSta.acbk_uapsd = roam_req->AcUapsd.acbk_uapsd;
2982 macQosInfoSta.acvi_uapsd = roam_req->AcUapsd.acvi_uapsd;
2983 macQosInfoSta.acvo_uapsd = roam_req->AcUapsd.acvo_uapsd;
2984 pCfgValue8 = (uint8_t *) &macQosInfoSta;
2985 /* macQosInfoSta Only queue_request is set.Refer to
2986 * populate_dot11f_wmm_caps for more details
2987 */
2988 roam_offload_params->qos_caps = (*pCfgValue8) & 0xFF;
2989 roam_offload_params->wmm_caps = 0x4 & 0xFF;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302990 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002991}
2992
2993/**
2994 * wma_set_ric_req() - set ric request element
2995 * @wma: wma handle
2996 * @msg: message
2997 * @is_add_ts: is addts required
2998 *
2999 * This function sets ric request element for 11r roaming.
3000 *
3001 * Return: none
3002 */
3003void wma_set_ric_req(tp_wma_handle wma, void *msg, uint8_t is_add_ts)
3004{
3005 wmi_ric_request_fixed_param *cmd;
3006 wmi_ric_tspec *tspec_param;
3007 wmi_buf_t buf;
3008 uint8_t *buf_ptr;
3009 tSirMacTspecIE *ptspecIE;
3010 int32_t len = sizeof(wmi_ric_request_fixed_param) +
3011 WMI_TLV_HDR_SIZE + sizeof(wmi_ric_tspec);
3012
3013 buf = wmi_buf_alloc(wma->wmi_handle, len);
3014 if (!buf) {
3015 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
3016 return;
3017 }
3018
3019 buf_ptr = (uint8_t *) wmi_buf_data(buf);
3020
3021 cmd = (wmi_ric_request_fixed_param *) buf_ptr;
3022 WMITLV_SET_HDR(&cmd->tlv_header,
3023 WMITLV_TAG_STRUC_wmi_ric_request_fixed_param,
3024 WMITLV_GET_STRUCT_TLVLEN(wmi_ric_request_fixed_param));
3025 if (is_add_ts)
3026 cmd->vdev_id = ((tAddTsParams *) msg)->sessionId;
3027 else
3028 cmd->vdev_id = ((tDelTsParams *) msg)->sessionId;
3029 cmd->num_ric_request = 1; /* Today we are sending only 1 ric at once */
3030 cmd->is_add_ric = is_add_ts;
3031
3032 buf_ptr += sizeof(wmi_ric_request_fixed_param);
3033 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, sizeof(wmi_ric_tspec));
3034
3035 buf_ptr += WMI_TLV_HDR_SIZE;
3036 tspec_param = (wmi_ric_tspec *) buf_ptr;
3037 WMITLV_SET_HDR(&tspec_param->tlv_header,
3038 WMITLV_TAG_STRUC_wmi_ric_tspec,
3039 WMITLV_GET_STRUCT_TLVLEN(wmi_ric_tspec));
3040
3041 if (is_add_ts)
3042 ptspecIE = &(((tAddTsParams *) msg)->tspec);
3043 else
3044 ptspecIE = &(((tDelTsParams *) msg)->delTsInfo.tspec);
3045
3046 /* Fill the tsinfo in the format expected by firmware */
3047#ifndef ANI_LITTLE_BIT_ENDIAN
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303048 qdf_mem_copy(((uint8_t *) &tspec_param->ts_info) + 1,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003049 ((uint8_t *) &ptspecIE->tsinfo) + 1, 2);
3050#else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303051 qdf_mem_copy(((uint8_t *) &tspec_param->ts_info),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003052 ((uint8_t *) &ptspecIE->tsinfo) + 1, 2);
3053#endif /* ANI_LITTLE_BIT_ENDIAN */
3054
3055 tspec_param->nominal_msdu_size = ptspecIE->nomMsduSz;
3056 tspec_param->maximum_msdu_size = ptspecIE->maxMsduSz;
3057 tspec_param->min_service_interval = ptspecIE->minSvcInterval;
3058 tspec_param->max_service_interval = ptspecIE->maxSvcInterval;
3059 tspec_param->inactivity_interval = ptspecIE->inactInterval;
3060 tspec_param->suspension_interval = ptspecIE->suspendInterval;
3061 tspec_param->svc_start_time = ptspecIE->svcStartTime;
3062 tspec_param->min_data_rate = ptspecIE->minDataRate;
3063 tspec_param->mean_data_rate = ptspecIE->meanDataRate;
3064 tspec_param->peak_data_rate = ptspecIE->peakDataRate;
3065 tspec_param->max_burst_size = ptspecIE->maxBurstSz;
3066 tspec_param->delay_bound = ptspecIE->delayBound;
3067 tspec_param->min_phy_rate = ptspecIE->minPhyRate;
3068 tspec_param->surplus_bw_allowance = ptspecIE->surplusBw;
3069 tspec_param->medium_time = 0;
3070
3071 WMA_LOGI("%s: Set RIC Req is_add_ts:%d", __func__, is_add_ts);
3072
3073 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3074 WMI_ROAM_SET_RIC_REQUEST_CMDID)) {
3075 WMA_LOGP("%s: Failed to send vdev Set RIC Req command",
3076 __func__);
3077 if (is_add_ts)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303078 ((tAddTsParams *) msg)->status = QDF_STATUS_E_FAILURE;
Nirav Shahcbc6d722016-03-01 16:24:53 +05303079 qdf_nbuf_free(buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003080 }
3081}
3082#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
3083
3084/**
3085 * wma_process_unit_test_cmd() - send unit test command to fw.
3086 * @handle: wma handle
3087 * @wma_utest: unit test command
3088 *
3089 * This function send unit test command to fw.
3090 *
3091 * Return: none
3092 */
3093void wma_process_unit_test_cmd(WMA_HANDLE handle,
3094 t_wma_unit_test_cmd *wma_utest)
3095{
3096 tp_wma_handle wma_handle = (tp_wma_handle) handle;
3097 wmi_unit_test_cmd_fixed_param *cmd;
3098 wmi_buf_t wmi_buf;
3099 uint8_t *buf_ptr;
3100 int i;
3101 uint16_t len, args_tlv_len;
3102 A_UINT32 *unit_test_cmd_args;
3103
3104 args_tlv_len =
3105 WMI_TLV_HDR_SIZE + wma_utest->num_args * sizeof(A_UINT32);
3106 len = sizeof(wmi_unit_test_cmd_fixed_param) + args_tlv_len;
3107 if (!wma_handle || !wma_handle->wmi_handle) {
3108 WMA_LOGE("%s: WMA is closed, can not issue fw unit test cmd",
3109 __func__);
3110 return;
3111 }
3112 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
3113 if (!wmi_buf) {
3114 WMA_LOGE("%s: wmai_buf_alloc failed", __func__);
3115 return;
3116 }
3117
3118 cmd = (wmi_unit_test_cmd_fixed_param *) wmi_buf_data(wmi_buf);
3119 buf_ptr = (uint8_t *) cmd;
3120 WMITLV_SET_HDR(&cmd->tlv_header,
3121 WMITLV_TAG_STRUC_wmi_unit_test_cmd_fixed_param,
3122 WMITLV_GET_STRUCT_TLVLEN(wmi_unit_test_cmd_fixed_param));
3123 cmd->vdev_id = wma_utest->vdev_id;
3124 cmd->module_id = wma_utest->module_id;
3125 cmd->num_args = wma_utest->num_args;
3126 buf_ptr += sizeof(wmi_unit_test_cmd_fixed_param);
3127 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
3128 (wma_utest->num_args * sizeof(uint32_t)));
3129 unit_test_cmd_args = (A_UINT32 *) (buf_ptr + WMI_TLV_HDR_SIZE);
3130 WMA_LOGI("%s: %d num of args = ", __func__, wma_utest->num_args);
3131 for (i = 0; (i < wma_utest->num_args && i < WMA_MAX_NUM_ARGS); i++) {
3132 unit_test_cmd_args[i] = wma_utest->args[i];
3133 WMA_LOGI("%d,", wma_utest->args[i]);
3134 }
3135 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
3136 WMI_UNIT_TEST_CMDID)) {
3137 WMA_LOGP("%s: failed to send unit test command", __func__);
Nirav Shahcbc6d722016-03-01 16:24:53 +05303138 qdf_nbuf_free(wmi_buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003139 return;
3140 }
3141 return;
3142}
3143
3144#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3145
3146/**
3147 * wma_roam_ho_fail_handler() - LFR3.0 roam hand off failed handler
3148 * @wma: wma handle
3149 * @vdev_id: vdev id
3150 *
3151 * Return: none
3152 */
3153static void wma_roam_ho_fail_handler(tp_wma_handle wma, uint32_t vdev_id)
3154{
3155 tSirSmeHOFailureInd *ho_failure_ind;
3156 cds_msg_t sme_msg = { 0 };
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303157 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003158
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303159 ho_failure_ind = qdf_mem_malloc(sizeof(tSirSmeHOFailureInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003160
3161 if (NULL == ho_failure_ind) {
3162 WMA_LOGE("%s: Memory allocation failure", __func__);
3163 return;
3164 }
3165 ho_failure_ind->sessionId = vdev_id;
3166 sme_msg.type = eWNI_SME_HO_FAIL_IND;
3167 sme_msg.bodyptr = ho_failure_ind;
3168 sme_msg.bodyval = 0;
3169
Anurag Chouhan6d760662016-02-20 16:05:43 +05303170 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303171 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003172 WMA_LOGE("Fail to post eWNI_SME_HO_FAIL_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303173 qdf_mem_free(ho_failure_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003174 return;
3175 }
3176 return;
3177}
3178
3179/**
3180 * wma_process_roam_synch_complete() - roam synch complete command to fw.
3181 * @handle: wma handle
3182 * @synchcnf: offload synch confirmation params
3183 *
3184 * This function sends roam synch complete event to fw.
3185 *
3186 * Return: none
3187 */
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003188void wma_process_roam_synch_complete(WMA_HANDLE handle, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003189{
3190 tp_wma_handle wma_handle = (tp_wma_handle) handle;
3191 wmi_roam_synch_complete_fixed_param *cmd;
3192 wmi_buf_t wmi_buf;
3193 uint8_t *buf_ptr;
3194 uint16_t len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003195 len = sizeof(wmi_roam_synch_complete_fixed_param);
3196
3197 if (!wma_handle || !wma_handle->wmi_handle) {
3198 WMA_LOGE("%s: WMA is closed, can not issue roam synch cnf",
3199 __func__);
3200 return;
3201 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
3203 if (!wmi_buf) {
3204 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
3205 return;
3206 }
3207 cmd = (wmi_roam_synch_complete_fixed_param *) wmi_buf_data(wmi_buf);
3208 buf_ptr = (uint8_t *) cmd;
3209 WMITLV_SET_HDR(&cmd->tlv_header,
3210 WMITLV_TAG_STRUC_wmi_roam_synch_complete_fixed_param,
3211 WMITLV_GET_STRUCT_TLVLEN
3212 (wmi_roam_synch_complete_fixed_param));
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003213 cmd->vdev_id = vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003214 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
3215 WMI_ROAM_SYNCH_COMPLETE)) {
3216 WMA_LOGP("%s: failed to send roam synch confirmation",
3217 __func__);
Nirav Shahcbc6d722016-03-01 16:24:53 +05303218 qdf_nbuf_free(wmi_buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003219 return;
3220 }
3221 return;
3222}
3223#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
3224
3225/**
3226 * wma_set_channel() - set channel
3227 * @wma: wma handle
3228 * @params: switch channel parameters
3229 *
3230 * Return: none
3231 */
3232void wma_set_channel(tp_wma_handle wma, tpSwitchChannelParams params)
3233{
3234 struct wma_vdev_start_req req;
3235 struct wma_target_req *msg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303236 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003237 uint8_t vdev_id, peer_id;
3238 ol_txrx_peer_handle peer;
3239 ol_txrx_pdev_handle pdev;
3240 struct wma_txrx_node *intr = wma->interfaces;
3241 struct sir_hw_mode_params hw_mode = {0};
3242
3243 WMA_LOGD("%s: Enter", __func__);
3244 if (!wma_find_vdev_by_addr(wma, params->selfStaMacAddr, &vdev_id)) {
3245 WMA_LOGP("%s: Failed to find vdev id for %pM",
3246 __func__, params->selfStaMacAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303247 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003248 goto send_resp;
3249 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05303250 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003251 if (NULL == pdev) {
3252 WMA_LOGE("%s: Failed to get pdev", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303253 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003254 goto send_resp;
3255 }
3256
3257 peer = ol_txrx_find_peer_by_addr(pdev, intr[vdev_id].bssid, &peer_id);
3258
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303259 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003260 req.vdev_id = vdev_id;
3261 msg = wma_fill_vdev_req(wma, req.vdev_id, WMA_CHNL_SWITCH_REQ,
3262 WMA_TARGET_REQ_TYPE_VDEV_START, params,
3263 WMA_VDEV_START_REQUEST_TIMEOUT);
3264 if (!msg) {
3265 WMA_LOGP("%s: Failed to fill channel switch request for vdev %d",
3266 __func__, req.vdev_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303267 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003268 goto send_resp;
3269 }
3270 req.chan = params->channelNumber;
3271 req.chan_width = params->ch_width;
3272 req.vht_capable = params->vhtCapable;
3273 req.ch_center_freq_seg0 = params->ch_center_freq_seg0;
3274 req.ch_center_freq_seg1 = params->ch_center_freq_seg1;
3275 req.dot11_mode = params->dot11_mode;
3276 status = wma_get_current_hw_mode(&hw_mode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303277 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278 WMA_LOGE("wma_get_current_hw_mode failed");
3279
3280 if ((params->nss == 2) && !hw_mode.dbs_cap) {
3281 req.preferred_rx_streams = 2;
3282 req.preferred_tx_streams = 2;
3283 } else {
3284 req.preferred_rx_streams = 1;
3285 req.preferred_tx_streams = 1;
3286 }
3287
3288#ifdef WLAN_FEATURE_VOWIFI
3289 req.max_txpow = params->maxTxPower;
3290#else
3291 req.max_txpow = params->localPowerConstraint;
3292#endif /* WLAN_FEATURE_VOWIFI */
3293 req.beacon_intval = 100;
3294 req.dtim_period = 1;
3295 req.is_dfs = params->isDfsChannel;
3296
3297 /* In case of AP mode, once radar is detected, we need to
3298 * issuse VDEV RESTART, so we making is_channel_switch as
3299 * true
3300 */
3301 if ((wma_is_vdev_in_ap_mode(wma, req.vdev_id) == true) ||
3302 (params->restart_on_chan_switch == true))
3303 wma->interfaces[req.vdev_id].is_channel_switch = true;
3304
3305 status = wma_vdev_start(wma, &req,
3306 wma->interfaces[req.vdev_id].is_channel_switch);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303307 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003308 wma_remove_vdev_req(wma, req.vdev_id,
3309 WMA_TARGET_REQ_TYPE_VDEV_START);
3310 WMA_LOGP("%s: vdev start failed status = %d", __func__, status);
3311 goto send_resp;
3312 }
3313
3314 if (wma->interfaces[req.vdev_id].is_channel_switch)
3315 wma->interfaces[req.vdev_id].is_channel_switch = false;
3316 return;
3317send_resp:
3318 WMA_LOGD("%s: channel %d ch_width %d txpower %d status %d", __func__,
3319 params->channelNumber, params->ch_width,
3320#ifdef WLAN_FEATURE_VOWIFI
3321 params->maxTxPower,
3322#else
3323 params->localPowerConstraint,
3324#endif /* WLAN_FEATURE_VOWIFI */
3325 status);
3326 params->status = status;
3327 WMA_LOGI("%s: sending WMA_SWITCH_CHANNEL_RSP, status = 0x%x",
3328 __func__, status);
3329 wma_send_msg(wma, WMA_SWITCH_CHANNEL_RSP, (void *)params, 0);
3330}
3331
3332#ifdef FEATURE_WLAN_SCAN_PNO
Varun Reddy Yeturub43fda12015-09-10 18:16:21 -07003333/**
3334 * wma_set_pno_channel_prediction() - Set PNO configuration
3335 * @buf_ptr: Buffer passed by upper layers
3336 * @pno: Buffer to be sent to the firmware
3337 *
3338 * Copy the PNO Channel prediction configuration parameters
3339 * passed by the upper layers to a WMI format TLV and send it
3340 * down to the firmware.
3341 *
3342 * Return: None
3343 */
3344void wma_set_pno_channel_prediction(uint8_t *buf_ptr,
3345 tpSirPNOScanReq pno)
3346{
3347 nlo_channel_prediction_cfg *channel_prediction_cfg =
3348 (nlo_channel_prediction_cfg *) buf_ptr;
3349 WMITLV_SET_HDR(&channel_prediction_cfg->tlv_header,
3350 WMITLV_TAG_ARRAY_BYTE,
3351 WMITLV_GET_STRUCT_TLVLEN(nlo_channel_prediction_cfg));
3352 channel_prediction_cfg->enable = pno->pno_channel_prediction;
3353 channel_prediction_cfg->top_k_num = pno->top_k_num_of_channels;
3354 channel_prediction_cfg->stationary_threshold = pno->stationary_thresh;
3355 channel_prediction_cfg->full_scan_period_ms =
3356 pno->channel_prediction_full_scan;
3357 buf_ptr += sizeof(nlo_channel_prediction_cfg);
3358 WMA_LOGD("enable: %d, top_k_num: %d, stat_thresh: %d, full_scan: %d",
3359 channel_prediction_cfg->enable,
3360 channel_prediction_cfg->top_k_num,
3361 channel_prediction_cfg->stationary_threshold,
3362 channel_prediction_cfg->full_scan_period_ms);
3363}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003364/**
3365 * wma_pno_start() - PNO start request
3366 * @wma: wma handle
3367 * @pno: PNO request
3368 *
3369 * This function request FW to start PNO request.
3370 * Request: CDF status
3371 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303372QDF_STATUS wma_pno_start(tp_wma_handle wma, tpSirPNOScanReq pno)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003373{
3374 wmi_nlo_config_cmd_fixed_param *cmd;
3375 nlo_configured_parameters *nlo_list;
3376 uint32_t *channel_list;
3377 int32_t len;
3378 wmi_buf_t buf;
3379 uint8_t *buf_ptr;
3380 uint8_t i;
3381 int ret;
3382
3383 WMA_LOGD("PNO Start");
3384
Varun Reddy Yeturub43fda12015-09-10 18:16:21 -07003385 /*
3386 * TLV place holder for array nlo_configured_parameters(nlo_list)
3387 * TLV place holder for array of uint32_t channel_list
3388 * TLV place holder for chnnl prediction cfg
3389 */
3390 len = sizeof(*cmd) +
3391 WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003392
Anurag Chouhan6d760662016-02-20 16:05:43 +05303393 len += sizeof(uint32_t) * QDF_MIN(pno->aNetworks[0].ucChannelCount,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003394 WMI_NLO_MAX_CHAN);
3395 len += sizeof(nlo_configured_parameters) *
Anurag Chouhan6d760662016-02-20 16:05:43 +05303396 QDF_MIN(pno->ucNetworksCount, WMI_NLO_MAX_SSIDS);
Varun Reddy Yeturub43fda12015-09-10 18:16:21 -07003397 len += sizeof(nlo_channel_prediction_cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003398
3399 buf = wmi_buf_alloc(wma->wmi_handle, len);
3400 if (!buf) {
3401 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303402 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003403 }
3404
3405 cmd = (wmi_nlo_config_cmd_fixed_param *) wmi_buf_data(buf);
3406
3407 buf_ptr = (uint8_t *) cmd;
3408 WMITLV_SET_HDR(&cmd->tlv_header,
3409 WMITLV_TAG_STRUC_wmi_nlo_config_cmd_fixed_param,
3410 WMITLV_GET_STRUCT_TLVLEN
3411 (wmi_nlo_config_cmd_fixed_param));
3412 cmd->vdev_id = pno->sessionId;
3413 cmd->flags = WMI_NLO_CONFIG_START | WMI_NLO_CONFIG_SSID_HIDE_EN;
3414
Naveen Rawatcf7d2d52015-11-13 06:57:32 -08003415 /* Current FW does not support min-max range for dwell time */
3416 cmd->active_dwell_time = pno->active_max_time;
3417 cmd->passive_dwell_time = pno->passive_max_time;
3418
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003419 /* Copy scan interval */
Srinivas Girigowdabdc98162015-09-17 11:06:07 -07003420 cmd->fast_scan_period = pno->fast_scan_period;
3421 cmd->slow_scan_period = pno->slow_scan_period;
3422 cmd->fast_scan_max_cycles = pno->fast_scan_max_cycles;
3423 WMA_LOGD("fast_scan_period: %d msec slow_scan_period: %d msec",
3424 cmd->fast_scan_period, cmd->slow_scan_period);
3425 WMA_LOGD("fast_scan_max_cycles: %d", cmd->fast_scan_max_cycles);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003426
3427 buf_ptr += sizeof(wmi_nlo_config_cmd_fixed_param);
3428
Anurag Chouhan6d760662016-02-20 16:05:43 +05303429 cmd->no_of_ssids = QDF_MIN(pno->ucNetworksCount, WMI_NLO_MAX_SSIDS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003430 WMA_LOGD("SSID count : %d", cmd->no_of_ssids);
3431 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
3432 cmd->no_of_ssids * sizeof(nlo_configured_parameters));
3433 buf_ptr += WMI_TLV_HDR_SIZE;
3434
3435 nlo_list = (nlo_configured_parameters *) buf_ptr;
3436 for (i = 0; i < cmd->no_of_ssids; i++) {
3437 WMITLV_SET_HDR(&nlo_list[i].tlv_header,
3438 WMITLV_TAG_ARRAY_BYTE,
3439 WMITLV_GET_STRUCT_TLVLEN
3440 (nlo_configured_parameters));
3441 /* Copy ssid and it's length */
3442 nlo_list[i].ssid.valid = true;
3443 nlo_list[i].ssid.ssid.ssid_len = pno->aNetworks[i].ssId.length;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303444 qdf_mem_copy(nlo_list[i].ssid.ssid.ssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003445 pno->aNetworks[i].ssId.ssId,
3446 nlo_list[i].ssid.ssid.ssid_len);
3447 WMA_LOGD("index: %d ssid: %.*s len: %d", i,
3448 nlo_list[i].ssid.ssid.ssid_len,
3449 (char *)nlo_list[i].ssid.ssid.ssid,
3450 nlo_list[i].ssid.ssid.ssid_len);
3451
3452 /* Copy rssi threshold */
3453 if (pno->aNetworks[i].rssiThreshold &&
3454 pno->aNetworks[i].rssiThreshold > WMA_RSSI_THOLD_DEFAULT) {
3455 nlo_list[i].rssi_cond.valid = true;
3456 nlo_list[i].rssi_cond.rssi =
3457 pno->aNetworks[i].rssiThreshold;
3458 WMA_LOGD("RSSI threshold : %d dBm",
3459 nlo_list[i].rssi_cond.rssi);
3460 }
3461 nlo_list[i].bcast_nw_type.valid = true;
3462 nlo_list[i].bcast_nw_type.bcast_nw_type =
3463 pno->aNetworks[i].bcastNetwType;
3464 WMA_LOGI("Broadcast NW type (%u)",
3465 nlo_list[i].bcast_nw_type.bcast_nw_type);
3466 }
3467 buf_ptr += cmd->no_of_ssids * sizeof(nlo_configured_parameters);
3468
3469 /* Copy channel info */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303470 cmd->num_of_channels = QDF_MIN(pno->aNetworks[0].ucChannelCount,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003471 WMI_NLO_MAX_CHAN);
3472 WMA_LOGD("Channel count: %d", cmd->num_of_channels);
3473 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
3474 (cmd->num_of_channels * sizeof(uint32_t)));
3475 buf_ptr += WMI_TLV_HDR_SIZE;
3476
3477 channel_list = (uint32_t *) buf_ptr;
3478 for (i = 0; i < cmd->num_of_channels; i++) {
3479 channel_list[i] = pno->aNetworks[0].aChannels[i];
3480
3481 if (channel_list[i] < WMA_NLO_FREQ_THRESH)
3482 channel_list[i] = cds_chan_to_freq(channel_list[i]);
3483
3484 WMA_LOGD("Ch[%d]: %d MHz", i, channel_list[i]);
3485 }
3486 buf_ptr += cmd->num_of_channels * sizeof(uint32_t);
Varun Reddy Yeturub43fda12015-09-10 18:16:21 -07003487 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
3488 sizeof(nlo_channel_prediction_cfg));
3489 buf_ptr += WMI_TLV_HDR_SIZE;
3490 wma_set_pno_channel_prediction(buf_ptr, pno);
3491 buf_ptr += WMI_TLV_HDR_SIZE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003492 /* TODO: Discrete firmware doesn't have command/option to configure
3493 * App IE which comes from wpa_supplicant as of part PNO start request.
3494 */
3495 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3496 WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
3497 if (ret) {
3498 WMA_LOGE("%s: Failed to send nlo wmi cmd", __func__);
3499 wmi_buf_free(buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303500 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003501 }
3502
3503 wma->interfaces[pno->sessionId].pno_in_progress = true;
3504
3505 WMA_LOGD("PNO start request sent successfully for vdev %d",
3506 pno->sessionId);
3507
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303508 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003509}
3510
3511/**
3512 * wma_pno_stop() - PNO stop request
3513 * @wma: wma handle
3514 * @vdev_id: vdev id
3515 *
3516 * This function request FW to stop ongoing PNO operation.
3517 *
3518 * Return: CDF status
3519 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303520QDF_STATUS wma_pno_stop(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003521{
3522 wmi_nlo_config_cmd_fixed_param *cmd;
3523 int32_t len = sizeof(*cmd);
3524 wmi_buf_t buf;
3525 uint8_t *buf_ptr;
3526 int ret;
3527
3528 if (!wma->interfaces[vdev_id].pno_in_progress) {
3529 WMA_LOGD("No active pno session found for vdev %d, skip pno stop request",
3530 vdev_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303531 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003532 }
3533
3534 WMA_LOGD("PNO Stop");
3535
Varun Reddy Yeturub43fda12015-09-10 18:16:21 -07003536 /*
3537 * TLV place holder for array of structures nlo_configured_parameters
3538 * TLV place holder for array of uint32_t channel_list
3539 * TLV place holder for chnl prediction cfg
3540 */
3541 len += WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003542 buf = wmi_buf_alloc(wma->wmi_handle, len);
3543 if (!buf) {
3544 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303545 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003546 }
3547
3548 cmd = (wmi_nlo_config_cmd_fixed_param *) wmi_buf_data(buf);
3549 buf_ptr = (uint8_t *) cmd;
3550
3551 WMITLV_SET_HDR(&cmd->tlv_header,
3552 WMITLV_TAG_STRUC_wmi_nlo_config_cmd_fixed_param,
3553 WMITLV_GET_STRUCT_TLVLEN
3554 (wmi_nlo_config_cmd_fixed_param));
3555
3556 cmd->vdev_id = vdev_id;
3557 cmd->flags = WMI_NLO_CONFIG_STOP;
3558 buf_ptr += sizeof(*cmd);
3559
3560 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
3561 buf_ptr += WMI_TLV_HDR_SIZE;
3562
3563 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
3564 buf_ptr += WMI_TLV_HDR_SIZE;
3565
Varun Reddy Yeturub43fda12015-09-10 18:16:21 -07003566 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
3567 buf_ptr += WMI_TLV_HDR_SIZE;
3568
3569
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003570 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3571 WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
3572 if (ret) {
3573 WMA_LOGE("%s: Failed to send nlo wmi cmd", __func__);
3574 wmi_buf_free(buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303575 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003576 }
3577
3578 wma->interfaces[vdev_id].pno_in_progress = false;
3579
3580 WMA_LOGD("PNO stop request sent successfully for vdev %d", vdev_id);
3581
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303582 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003583}
3584
3585/**
3586 * wma_config_pno() - config PNO
3587 * @wma: wma handle
3588 * @pno: PNO request parameters
3589 *
3590 * Return: none
3591 */
3592void wma_config_pno(tp_wma_handle wma, tpSirPNOScanReq pno)
3593{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303594 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003595
3596 if (pno->enable)
3597 ret = wma_pno_start(wma, pno);
3598 else
3599 ret = wma_pno_stop(wma, pno->sessionId);
3600
3601 if (ret)
3602 WMA_LOGE("%s: PNO %s failed %d", __func__,
3603 pno->enable ? "start" : "stop", ret);
3604
3605 /* SME expects WMA to free tpSirPNOScanReq memory after
3606 * processing PNO request. */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303607 qdf_mem_free(pno);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003608}
3609
3610#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
3611
3612/**
3613 * wma_plm_start() - plm start request
3614 * @wma: wma handle
3615 * @plm: plm request parameters
3616 *
3617 * This function request FW to start PLM.
3618 *
3619 * Return: CDF status
3620 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303621QDF_STATUS wma_plm_start(tp_wma_handle wma, const tpSirPlmReq plm)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003622{
3623 wmi_vdev_plmreq_start_cmd_fixed_param *cmd;
3624 uint32_t *channel_list;
3625 int32_t len;
3626 wmi_buf_t buf;
3627 uint8_t *buf_ptr;
3628 uint8_t count;
3629 int ret;
3630
3631 if (NULL == plm || NULL == wma) {
3632 WMA_LOGE("%s: input pointer is NULL ", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303633 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003634 }
3635 WMA_LOGD("PLM Start");
3636
3637 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE; /* TLV place holder for channel_list */
3638 len += sizeof(uint32_t) * plm->plmNumCh;
3639
3640 buf = wmi_buf_alloc(wma->wmi_handle, len);
3641 if (!buf) {
3642 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303643 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003644 }
3645 cmd = (wmi_vdev_plmreq_start_cmd_fixed_param *) wmi_buf_data(buf);
3646
3647 buf_ptr = (uint8_t *) cmd;
3648
3649 WMITLV_SET_HDR(&cmd->tlv_header,
3650 WMITLV_TAG_STRUC_wmi_vdev_plmreq_start_cmd_fixed_param,
3651 WMITLV_GET_STRUCT_TLVLEN
3652 (wmi_vdev_plmreq_start_cmd_fixed_param));
3653
3654 cmd->vdev_id = plm->sessionId;
3655
3656 cmd->meas_token = plm->meas_token;
3657 cmd->dialog_token = plm->diag_token;
3658 cmd->number_bursts = plm->numBursts;
3659 cmd->burst_interval = WMA_SEC_TO_MSEC(plm->burstInt);
3660 cmd->off_duration = plm->measDuration;
3661 cmd->burst_cycle = plm->burstLen;
3662 cmd->tx_power = plm->desiredTxPwr;
Srinivas Girigowda5146dee2015-11-18 21:46:48 -08003663 WMI_CHAR_ARRAY_TO_MAC_ADDR(plm->mac_addr.bytes, &cmd->dest_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003664 cmd->num_chans = plm->plmNumCh;
3665
3666 buf_ptr += sizeof(wmi_vdev_plmreq_start_cmd_fixed_param);
3667
3668 WMA_LOGD("vdev : %d measu token : %d", cmd->vdev_id, cmd->meas_token);
3669 WMA_LOGD("dialog_token: %d", cmd->dialog_token);
3670 WMA_LOGD("number_bursts: %d", cmd->number_bursts);
3671 WMA_LOGD("burst_interval: %d", cmd->burst_interval);
3672 WMA_LOGD("off_duration: %d", cmd->off_duration);
3673 WMA_LOGD("burst_cycle: %d", cmd->burst_cycle);
3674 WMA_LOGD("tx_power: %d", cmd->tx_power);
3675 WMA_LOGD("Number of channels : %d", cmd->num_chans);
3676
3677 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
3678 (cmd->num_chans * sizeof(uint32_t)));
3679
3680 buf_ptr += WMI_TLV_HDR_SIZE;
3681 if (cmd->num_chans) {
3682 channel_list = (uint32_t *) buf_ptr;
3683 for (count = 0; count < cmd->num_chans; count++) {
3684 channel_list[count] = plm->plmChList[count];
3685 if (channel_list[count] < WMA_NLO_FREQ_THRESH)
3686 channel_list[count] =
3687 cds_chan_to_freq(channel_list[count]);
3688 WMA_LOGD("Ch[%d]: %d MHz", count, channel_list[count]);
3689 }
3690 buf_ptr += cmd->num_chans * sizeof(uint32_t);
3691 }
3692
3693 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3694 WMI_VDEV_PLMREQ_START_CMDID);
3695 if (ret) {
3696 WMA_LOGE("%s: Failed to send plm start wmi cmd", __func__);
3697 wmi_buf_free(buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303698 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003699 }
3700 wma->interfaces[plm->sessionId].plm_in_progress = true;
3701
3702 WMA_LOGD("Plm start request sent successfully for vdev %d",
3703 plm->sessionId);
3704
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303705 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003706}
3707
3708/**
3709 * wma_plm_stop() - plm stop request
3710 * @wma: wma handle
3711 * @plm: plm request parameters
3712 *
3713 * This function request FW to stop PLM.
3714 *
3715 * Return: CDF status
3716 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303717QDF_STATUS wma_plm_stop(tp_wma_handle wma, const tpSirPlmReq plm)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003718{
3719 wmi_vdev_plmreq_stop_cmd_fixed_param *cmd;
3720 int32_t len;
3721 wmi_buf_t buf;
3722 uint8_t *buf_ptr;
3723 int ret;
3724
3725 if (NULL == plm || NULL == wma) {
3726 WMA_LOGE("%s: input pointer is NULL ", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303727 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003728 }
3729
3730 if (false == wma->interfaces[plm->sessionId].plm_in_progress) {
3731 WMA_LOGE("No active plm req found, skip plm stop req");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303732 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003733 }
3734
3735 WMA_LOGD("PLM Stop");
3736
3737 len = sizeof(*cmd);
3738 buf = wmi_buf_alloc(wma->wmi_handle, len);
3739 if (!buf) {
3740 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303741 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003742 }
3743
3744 cmd = (wmi_vdev_plmreq_stop_cmd_fixed_param *) wmi_buf_data(buf);
3745
3746 buf_ptr = (uint8_t *) cmd;
3747
3748 WMITLV_SET_HDR(&cmd->tlv_header,
3749 WMITLV_TAG_STRUC_wmi_vdev_plmreq_stop_cmd_fixed_param,
3750 WMITLV_GET_STRUCT_TLVLEN
3751 (wmi_vdev_plmreq_stop_cmd_fixed_param));
3752
3753 cmd->vdev_id = plm->sessionId;
3754
3755 cmd->meas_token = plm->meas_token;
3756 WMA_LOGD("vdev %d meas token %d", cmd->vdev_id, cmd->meas_token);
3757
3758 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3759 WMI_VDEV_PLMREQ_STOP_CMDID);
3760 if (ret) {
3761 WMA_LOGE("%s: Failed to send plm stop wmi cmd", __func__);
3762 wmi_buf_free(buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303763 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003764 }
3765 wma->interfaces[plm->sessionId].plm_in_progress = false;
3766
3767 WMA_LOGD("Plm stop request sent successfully for vdev %d",
3768 plm->sessionId);
3769
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303770 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003771}
3772
3773/**
3774 * wma_config_plm()- config PLM
3775 * @wma: wma handle
3776 * @plm: plm request parameters
3777 *
3778 * Return: none
3779 */
3780void wma_config_plm(tp_wma_handle wma, tpSirPlmReq plm)
3781{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303782 QDF_STATUS ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003783
3784 if (NULL == plm || NULL == wma)
3785 return;
3786
3787 if (plm->enable)
3788 ret = wma_plm_start(wma, plm);
3789 else
3790 ret = wma_plm_stop(wma, plm);
3791
3792 if (ret)
3793 WMA_LOGE("%s: PLM %s failed %d", __func__,
3794 plm->enable ? "start" : "stop", ret);
3795
3796 /* SME expects WMA to free tpSirPlmReq memory after
3797 * processing PLM request. */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303798 qdf_mem_free(plm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003799 plm = NULL;
3800}
3801#endif
3802
3803/**
3804 * wma_scan_cache_updated_ind() - scan update indication
3805 * @wma: wma handle
3806 * @sessionId: session ID
3807 *
3808 * After pushing cached scan results (that are stored in LIM) to SME,
3809 * PE will post WMA_SME_SCAN_CACHE_UPDATED message indication to
3810 * wma and intern this function handles that message. This function will
3811 * check for PNO completion (by checking NLO match event) and post PNO
3812 * completion back to SME if PNO operation is completed successfully.
3813 *
3814 * Return: none
3815 */
3816void wma_scan_cache_updated_ind(tp_wma_handle wma, uint8_t sessionId)
3817{
3818 tSirPrefNetworkFoundInd *nw_found_ind;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303819 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003820 cds_msg_t cds_msg;
3821 uint8_t len, i;
3822
3823 for (i = 0; i < wma->max_bssid; i++) {
3824 if (wma->interfaces[i].nlo_match_evt_received)
3825 break;
3826 }
3827
3828 if (i == wma->max_bssid) {
3829 WMA_LOGD("PNO match event is not received in any vdev, skip scan cache update indication");
3830 return;
3831 }
3832 wma->interfaces[i].nlo_match_evt_received = false;
3833
3834 WMA_LOGD("Posting PNO completion to umac");
3835
3836 len = sizeof(tSirPrefNetworkFoundInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303837 nw_found_ind = (tSirPrefNetworkFoundInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003838
3839 if (NULL == nw_found_ind) {
3840 WMA_LOGE("%s: Memory allocation failure", __func__);
3841 return;
3842 }
3843
3844 nw_found_ind->mesgType = eWNI_SME_PREF_NETWORK_FOUND_IND;
3845 nw_found_ind->mesgLen = len;
3846 nw_found_ind->sessionId = sessionId;
3847
3848 cds_msg.type = eWNI_SME_PREF_NETWORK_FOUND_IND;
3849 cds_msg.bodyptr = (void *)nw_found_ind;
3850 cds_msg.bodyval = 0;
3851
3852 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303853 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003854 WMA_LOGE("%s: Failed to post PNO completion match event to SME",
3855 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303856 qdf_mem_free(nw_found_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003857 }
3858}
3859
3860#ifdef FEATURE_WLAN_EXTSCAN
3861/**
3862 * wma_extscan_get_eventid_from_tlvtag() - map tlv tag to corresponding event id
3863 * @tag: WMI TLV tag
3864 *
3865 * Return:
3866 * 0 if TLV tag is invalid
3867 * else return corresponding WMI event id
3868 */
3869static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag)
3870{
3871 uint32_t event_id;
3872
3873 switch (tag) {
3874 case WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param:
3875 event_id = WMI_EXTSCAN_START_STOP_EVENTID;
3876 break;
3877
3878 case WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param:
3879 event_id = WMI_EXTSCAN_OPERATION_EVENTID;
3880 break;
3881
3882 case WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param:
3883 event_id = WMI_EXTSCAN_TABLE_USAGE_EVENTID;
3884 break;
3885
3886 case WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param:
3887 event_id = WMI_EXTSCAN_CACHED_RESULTS_EVENTID;
3888 break;
3889
3890 case WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param:
3891 event_id = WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID;
3892 break;
3893
3894 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param:
3895 event_id = WMI_EXTSCAN_HOTLIST_MATCH_EVENTID;
3896 break;
3897
3898 case WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param:
3899 event_id = WMI_EXTSCAN_CAPABILITIES_EVENTID;
3900 break;
3901
3902 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_ssid_match_event_fixed_param:
3903 event_id = WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID;
3904 break;
3905
3906 default:
3907 event_id = 0;
3908 WMA_LOGE("%s: Unknown tag: %d", __func__, tag);
3909 break;
3910 }
3911
3912 WMA_LOGI("%s: For tag %d WMI event 0x%x", __func__, tag, event_id);
3913 return event_id;
3914}
3915
3916/**
3917 * wma_extscan_wow_event_callback() - extscan wow event callback
3918 * @handle: WMA handle
3919 * @event: event buffer
3920 * @len: length of @event buffer
3921 *
3922 * In wow case, the wow event is followed by the payload of the event
3923 * which generated the wow event.
3924 * payload is 4 bytes of length followed by event buffer. the first 4 bytes
3925 * of event buffer is common tlv header, which is a combination
3926 * of tag (higher 2 bytes) and length (lower 2 bytes). The tag is used to
3927 * identify the event which triggered wow event.
3928 *
3929 * @Return: none
3930 */
3931void wma_extscan_wow_event_callback(void *handle, void *event, uint32_t len)
3932{
3933 uint32_t id;
3934 int tlv_ok_status = 0;
3935 void *wmi_cmd_struct_ptr = NULL;
3936 uint32_t tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(event));
3937
3938 id = wma_extscan_get_eventid_from_tlvtag(tag);
3939 if (!id) {
3940 WMA_LOGE("%s: Invalid Tag: %d", __func__, tag);
3941 return;
3942 }
3943
3944 tlv_ok_status = wmitlv_check_and_pad_event_tlvs(
3945 handle, event, len, id,
3946 &wmi_cmd_struct_ptr);
3947 if (tlv_ok_status != 0) {
3948 WMA_LOGE("%s: Invalid Tag: %d could not check and pad tlvs",
3949 __func__, tag);
3950 return;
3951 }
3952
3953 switch (tag) {
3954 case WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param:
3955 wma_extscan_start_stop_event_handler(handle,
3956 wmi_cmd_struct_ptr, len);
3957 break;
3958
3959 case WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param:
3960 wma_extscan_operations_event_handler(handle,
3961 wmi_cmd_struct_ptr, len);
3962 break;
3963
3964 case WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param:
3965 wma_extscan_table_usage_event_handler(handle,
3966 wmi_cmd_struct_ptr, len);
3967 break;
3968
3969 case WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param:
3970 wma_extscan_cached_results_event_handler(handle,
3971 wmi_cmd_struct_ptr, len);
3972 break;
3973
3974 case WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param:
3975 wma_extscan_change_results_event_handler(handle,
3976 wmi_cmd_struct_ptr, len);
3977 break;
3978
3979 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param:
3980 wma_extscan_hotlist_match_event_handler(handle,
3981 wmi_cmd_struct_ptr, len);
3982 break;
3983
3984 case WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param:
3985 wma_extscan_capabilities_event_handler(handle,
3986 wmi_cmd_struct_ptr, len);
3987 break;
3988
3989 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_ssid_match_event_fixed_param:
3990 wma_extscan_hotlist_ssid_match_event_handler(handle,
3991 wmi_cmd_struct_ptr, len);
3992 break;
3993
3994 default:
3995 WMA_LOGE("%s: Unknown tag: %d", __func__, tag);
3996 break;
3997 }
3998 wmitlv_free_allocated_event_tlvs(id, &wmi_cmd_struct_ptr);
3999
4000 return;
4001}
4002#endif
4003
4004/**
4005 * wma_nlo_match_evt_handler() - nlo match event handler
4006 * @handle: wma handle
4007 * @event: event data
4008 * @len: data length
4009 *
4010 * Record NLO match event comes from FW. It's a indication that
4011 * one of the profile is matched.
4012 *
4013 * Return: 0 for success or error code.
4014 */
4015int wma_nlo_match_evt_handler(void *handle, uint8_t *event,
4016 uint32_t len)
4017{
4018 tp_wma_handle wma = (tp_wma_handle) handle;
4019 wmi_nlo_event *nlo_event;
4020 WMI_NLO_MATCH_EVENTID_param_tlvs *param_buf =
4021 (WMI_NLO_MATCH_EVENTID_param_tlvs *) event;
4022 struct wma_txrx_node *node;
4023
4024 if (!param_buf) {
4025 WMA_LOGE("Invalid NLO match event buffer");
4026 return -EINVAL;
4027 }
4028
4029 nlo_event = param_buf->fixed_param;
4030 WMA_LOGD("PNO match event received for vdev %d", nlo_event->vdev_id);
4031
4032 node = &wma->interfaces[nlo_event->vdev_id];
4033 if (node)
4034 node->nlo_match_evt_received = true;
4035
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304036 qdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004037 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT,
4038 WIFI_POWER_EVENT_WAKELOCK_PNO);
4039
4040 return 0;
4041}
4042
4043/**
4044 * wma_nlo_scan_cmp_evt_handler() - nlo scan completion handler
4045 * @handle: wma handle
4046 * @event: event handler
4047 * @len: length of data
4048 *
4049 * This function handles NLO scan completion event.
4050 *
4051 * Return: 0 for success or error code.
4052 */
4053int wma_nlo_scan_cmp_evt_handler(void *handle, uint8_t *event,
4054 uint32_t len)
4055{
4056 tp_wma_handle wma = (tp_wma_handle) handle;
4057 wmi_nlo_event *nlo_event;
4058 WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs *param_buf =
4059 (WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs *) event;
4060 tSirScanOffloadEvent *scan_event;
4061 struct wma_txrx_node *node;
4062
4063 if (!param_buf) {
4064 WMA_LOGE("Invalid NLO scan comp event buffer");
4065 return -EINVAL;
4066 }
4067
4068 nlo_event = param_buf->fixed_param;
4069 WMA_LOGD("PNO scan completion event received for vdev %d",
4070 nlo_event->vdev_id);
4071
4072 node = &wma->interfaces[nlo_event->vdev_id];
4073
4074 /* Handle scan completion event only after NLO match event. */
4075 if (!node || !node->nlo_match_evt_received) {
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08004076 WMA_LOGD("NLO match not received skip PNO complete ind for vdev %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004077 nlo_event->vdev_id);
4078 goto skip_pno_cmp_ind;
4079 }
4080
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304081 qdf_wake_lock_release(&wma->pno_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004082 WIFI_POWER_EVENT_WAKELOCK_PNO);
4083 scan_event =
4084 (tSirScanOffloadEvent *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304085 qdf_mem_malloc(sizeof(tSirScanOffloadEvent));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004086 if (scan_event) {
4087 /* Posting scan completion msg would take scan cache result
4088 * from LIM module and update in scan cache maintained in SME.*/
4089 WMA_LOGE("Posting PNO Scan completion to umac");
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304090 qdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004091 WMA_PNO_SCAN_COMPLETE_WAKE_LOCK_TIMEOUT,
4092 WIFI_POWER_EVENT_WAKELOCK_PNO);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304093 qdf_mem_zero(scan_event, sizeof(tSirScanOffloadEvent));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004094 scan_event->reasonCode = eSIR_PNO_SCAN_SUCCESS;
4095 scan_event->event = SCAN_EVENT_COMPLETED;
4096 scan_event->sessionId = nlo_event->vdev_id;
4097 wma_send_msg(wma, WMA_RX_SCAN_EVENT, (void *)scan_event, 0);
4098 } else {
4099 WMA_LOGE("Memory allocation failed for tSirScanOffloadEvent");
4100 }
4101
4102skip_pno_cmp_ind:
4103 return 0;
4104}
4105
4106#endif
4107
4108/**
4109 * wma_register_extscan_event_handler() - register extscan event handler
4110 * @wma_handle: wma handle
4111 *
4112 * This function register extscan related event handlers.
4113 *
4114 * Return: none
4115 */
4116void wma_register_extscan_event_handler(tp_wma_handle wma_handle)
4117{
4118 if (!wma_handle) {
4119 WMA_LOGE("%s: extscan wma_handle is NULL", __func__);
4120 return;
4121 }
4122 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4123 WMI_EXTSCAN_START_STOP_EVENTID,
4124 wma_extscan_start_stop_event_handler);
4125
4126 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4127 WMI_EXTSCAN_CAPABILITIES_EVENTID,
4128 wma_extscan_capabilities_event_handler);
4129
4130 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4131 WMI_EXTSCAN_HOTLIST_MATCH_EVENTID,
4132 wma_extscan_hotlist_match_event_handler);
4133
4134 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4135 WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID,
4136 wma_extscan_change_results_event_handler);
4137
4138 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4139 WMI_EXTSCAN_OPERATION_EVENTID,
4140 wma_extscan_operations_event_handler);
4141 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4142 WMI_EXTSCAN_TABLE_USAGE_EVENTID,
4143 wma_extscan_table_usage_event_handler);
4144
4145 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4146 WMI_EXTSCAN_CACHED_RESULTS_EVENTID,
4147 wma_extscan_cached_results_event_handler);
4148
4149 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4150 WMI_PASSPOINT_MATCH_EVENTID,
4151 wma_passpoint_match_event_handler);
4152
4153
4154 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4155 WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID,
4156 wma_extscan_hotlist_ssid_match_event_handler);
4157
4158 return;
4159}
4160
4161#ifdef FEATURE_WLAN_EXTSCAN
4162
4163/**
4164 * wma_extscan_start_stop_event_handler() - extscan start/stop event handler
4165 * @handle: wma handle
4166 * @cmd_param_info: event buffer
4167 * @len: data length
4168 *
4169 * This function handles different extscan related commands
4170 * like start/stop/get results etc and indicate to upper layers.
4171 *
4172 * Return: 0 for success or error code.
4173 */
4174int wma_extscan_start_stop_event_handler(void *handle,
4175 uint8_t *cmd_param_info,
4176 uint32_t len)
4177{
4178 WMI_EXTSCAN_START_STOP_EVENTID_param_tlvs *param_buf;
4179 wmi_extscan_start_stop_event_fixed_param *event;
4180 struct sir_extscan_generic_response *extscan_ind;
4181 uint16_t event_type;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304182 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004183 if (!pMac) {
4184 WMA_LOGE("%s: Invalid pMac", __func__);
4185 return -EINVAL;
4186 }
4187 if (!pMac->sme.pExtScanIndCb) {
4188 WMA_LOGE("%s: Callback not registered", __func__);
4189 return -EINVAL;
4190 }
4191 param_buf = (WMI_EXTSCAN_START_STOP_EVENTID_param_tlvs *)
4192 cmd_param_info;
4193 if (!param_buf) {
4194 WMA_LOGE("%s: Invalid extscan event", __func__);
4195 return -EINVAL;
4196 }
4197 event = param_buf->fixed_param;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304198 extscan_ind = qdf_mem_malloc(sizeof(*extscan_ind));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004199 if (!extscan_ind) {
4200 WMA_LOGE("%s: extscan memory allocation failed", __func__);
4201 return -ENOMEM;
4202 }
4203 switch (event->command) {
4204 case WMI_EXTSCAN_START_CMDID:
4205 event_type = eSIR_EXTSCAN_START_RSP;
4206 extscan_ind->status = event->status;
4207 extscan_ind->request_id = event->request_id;
4208 break;
4209 case WMI_EXTSCAN_STOP_CMDID:
4210 event_type = eSIR_EXTSCAN_STOP_RSP;
4211 extscan_ind->status = event->status;
4212 extscan_ind->request_id = event->request_id;
4213 break;
4214 case WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID:
4215 extscan_ind->status = event->status;
4216 extscan_ind->request_id = event->request_id;
4217 if (event->mode == WMI_EXTSCAN_MODE_STOP) {
4218 event_type =
4219 eSIR_EXTSCAN_RESET_SIGNIFICANT_WIFI_CHANGE_RSP;
4220 } else {
4221 event_type =
4222 eSIR_EXTSCAN_SET_SIGNIFICANT_WIFI_CHANGE_RSP;
4223 }
4224 break;
4225 case WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID:
4226 extscan_ind->status = event->status;
4227 extscan_ind->request_id = event->request_id;
4228 if (event->mode == WMI_EXTSCAN_MODE_STOP) {
4229 event_type = eSIR_EXTSCAN_RESET_BSSID_HOTLIST_RSP;
4230 } else {
4231 event_type = eSIR_EXTSCAN_SET_BSSID_HOTLIST_RSP;
4232 }
4233 break;
4234 case WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID:
4235 extscan_ind->status = event->status;
4236 extscan_ind->request_id = event->request_id;
4237 event_type = eSIR_EXTSCAN_CACHED_RESULTS_RSP;
4238 break;
4239 case WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID:
4240 extscan_ind->status = event->status;
4241 extscan_ind->request_id = event->request_id;
4242 if (event->mode == WMI_EXTSCAN_MODE_STOP) {
4243 event_type =
4244 eSIR_EXTSCAN_RESET_SSID_HOTLIST_RSP;
4245 } else {
4246 event_type =
4247 eSIR_EXTSCAN_SET_SSID_HOTLIST_RSP;
4248 }
4249 break;
4250 default:
4251 WMA_LOGE("%s: Unknown event(%d) from target",
4252 __func__, event->status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304253 qdf_mem_free(extscan_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004254 return -EINVAL;
4255 }
4256 pMac->sme.pExtScanIndCb(pMac->hHdd, event_type, extscan_ind);
4257 WMA_LOGD("%s: sending event to umac for requestid %u"
4258 "with status %d", __func__,
4259 extscan_ind->request_id, extscan_ind->status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304260 qdf_mem_free(extscan_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004261 return 0;
4262}
4263
4264/**
4265 * wma_extscan_operations_event_handler() - extscan operation event handler
4266 * @handle: wma handle
4267 * @cmd_param_info: event buffer
4268 * @len: length
4269 *
4270 * This function handles different operations related event and indicate
4271 * upper layers with appropriate callback.
4272 *
4273 * Return: 0 for success or error code.
4274 */
4275int wma_extscan_operations_event_handler(void *handle,
4276 uint8_t *cmd_param_info,
4277 uint32_t len)
4278{
4279 tp_wma_handle wma = (tp_wma_handle) handle;
4280 WMI_EXTSCAN_OPERATION_EVENTID_param_tlvs *param_buf;
4281 wmi_extscan_operation_event_fixed_param *oprn_event;
4282 tSirExtScanOnScanEventIndParams *oprn_ind;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304283 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004284 if (!pMac) {
4285 WMA_LOGE("%s: Invalid pMac", __func__);
4286 return -EINVAL;
4287 }
4288 if (!pMac->sme.pExtScanIndCb) {
4289 WMA_LOGE("%s: Callback not registered", __func__);
4290 return -EINVAL;
4291 }
4292 param_buf = (WMI_EXTSCAN_OPERATION_EVENTID_param_tlvs *)
4293 cmd_param_info;
4294 if (!param_buf) {
4295 WMA_LOGE("%s: Invalid scan operation event", __func__);
4296 return -EINVAL;
4297 }
4298 oprn_event = param_buf->fixed_param;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304299 oprn_ind = qdf_mem_malloc(sizeof(*oprn_ind));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004300 if (!oprn_ind) {
4301 WMA_LOGE("%s: extscan memory allocation failed", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304302 qdf_mem_free(oprn_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004303 return -ENOMEM;
4304 }
4305
4306 oprn_ind->requestId = oprn_event->request_id;
4307
4308 switch (oprn_event->event) {
4309 case WMI_EXTSCAN_BUCKET_COMPLETED_EVENT:
4310 oprn_ind->scanEventType = WIFI_SCAN_COMPLETE;
4311 oprn_ind->status = 0;
4312 break;
4313 case WMI_EXTSCAN_CYCLE_STARTED_EVENT:
4314 WMA_LOGD("%s: received WMI_EXTSCAN_CYCLE_STARTED_EVENT",
4315 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304316 qdf_wake_lock_timeout_acquire(&wma->extscan_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004317 WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION,
4318 WIFI_POWER_EVENT_WAKELOCK_EXT_SCAN);
4319 goto exit_handler;
4320 case WMI_EXTSCAN_CYCLE_COMPLETED_EVENT:
4321 WMA_LOGD("%s: received WMI_EXTSCAN_CYCLE_COMPLETED_EVENT",
4322 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304323 qdf_wake_lock_release(&wma->extscan_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004324 WIFI_POWER_EVENT_WAKELOCK_EXT_SCAN);
4325 goto exit_handler;
4326 default:
4327 WMA_LOGE("%s: Unknown event(%d) from target",
4328 __func__, oprn_event->event);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304329 qdf_mem_free(oprn_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004330 return -EINVAL;
4331 }
4332 pMac->sme.pExtScanIndCb(pMac->hHdd,
4333 eSIR_EXTSCAN_SCAN_PROGRESS_EVENT_IND, oprn_ind);
4334 WMA_LOGI("%s: sending scan progress event to hdd", __func__);
4335exit_handler:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304336 qdf_mem_free(oprn_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004337 return 0;
4338}
4339
4340/**
4341 * wma_extscan_table_usage_event_handler() - extscan table usage event handler
4342 * @handle: wma handle
4343 * @cmd_param_info: event buffer
4344 * @len: length
4345 *
4346 * This function handles table usage related event and indicate
4347 * upper layers with appropriate callback.
4348 *
4349 * Return: 0 for success or error code.
4350 */
4351int wma_extscan_table_usage_event_handler(void *handle,
4352 uint8_t *cmd_param_info,
4353 uint32_t len)
4354{
4355 WMI_EXTSCAN_TABLE_USAGE_EVENTID_param_tlvs *param_buf;
4356 wmi_extscan_table_usage_event_fixed_param *event;
4357 tSirExtScanResultsAvailableIndParams *tbl_usg_ind;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304358 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004359 if (!pMac) {
4360 WMA_LOGE("%s: Invalid pMac", __func__);
4361 return -EINVAL;
4362 }
4363 if (!pMac->sme.pExtScanIndCb) {
4364 WMA_LOGE("%s: Callback not registered", __func__);
4365 return -EINVAL;
4366 }
4367 param_buf = (WMI_EXTSCAN_TABLE_USAGE_EVENTID_param_tlvs *)
4368 cmd_param_info;
4369 if (!param_buf) {
4370 WMA_LOGE("%s: Invalid table usage event", __func__);
4371 return -EINVAL;
4372 }
4373 event = param_buf->fixed_param;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304374 tbl_usg_ind = qdf_mem_malloc(sizeof(*tbl_usg_ind));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375 if (!tbl_usg_ind) {
4376 WMA_LOGE("%s: table usage allocation failed", __func__);
4377 return -ENOMEM;
4378 }
4379 tbl_usg_ind->requestId = event->request_id;
4380 tbl_usg_ind->numResultsAvailable = event->entries_in_use;
4381
4382 pMac->sme.pExtScanIndCb(pMac->hHdd,
4383 eSIR_EXTSCAN_SCAN_RES_AVAILABLE_IND,
4384 tbl_usg_ind);
4385 WMA_LOGI("%s: sending scan_res available event to hdd", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304386 qdf_mem_free(tbl_usg_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004387 return 0;
4388}
4389
4390/**
4391 * wma_extscan_capabilities_event_handler() - extscan capabilities event handler
4392 * @handle: wma handle
4393 * @cmd_param_info: event buffer
4394 * @len: length
4395 *
4396 * This function handles capabilities event and indicate
4397 * upper layers with registered callback.
4398 *
4399 * Return: 0 for success or error code.
4400 */
4401int wma_extscan_capabilities_event_handler(void *handle,
4402 uint8_t *cmd_param_info,
4403 uint32_t len)
4404{
4405 WMI_EXTSCAN_CAPABILITIES_EVENTID_param_tlvs *param_buf;
4406 wmi_extscan_capabilities_event_fixed_param *event;
4407 wmi_extscan_cache_capabilities *src_cache;
4408 wmi_extscan_hotlist_monitor_capabilities *src_hotlist;
4409 wmi_extscan_wlan_change_monitor_capabilities *src_change;
4410
4411 struct ext_scan_capabilities_response *dest_capab;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304412 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004413 if (!pMac) {
4414 WMA_LOGE("%s: Invalid pMac", __func__);
4415 return -EINVAL;
4416 }
4417 if (!pMac->sme.pExtScanIndCb) {
4418 WMA_LOGE("%s: Callback not registered", __func__);
4419 return -EINVAL;
4420 }
4421 param_buf = (WMI_EXTSCAN_CAPABILITIES_EVENTID_param_tlvs *)
4422 cmd_param_info;
4423 if (!param_buf) {
4424 WMA_LOGE("%s: Invalid capabilities event", __func__);
4425 return -EINVAL;
4426 }
4427 event = param_buf->fixed_param;
4428 src_cache = param_buf->extscan_cache_capabilities;
4429 src_hotlist = param_buf->hotlist_capabilities;
4430 src_change = param_buf->wlan_change_capabilities;
4431
4432 if (!src_cache || !src_hotlist || !src_change) {
4433 WMA_LOGE("%s: Invalid capabilities list", __func__);
4434 return -EINVAL;
4435 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304436 dest_capab = qdf_mem_malloc(sizeof(*dest_capab));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004437 if (!dest_capab) {
4438 WMA_LOGE("%s: Allocation failed for capabilities buffer",
4439 __func__);
4440 return -ENOMEM;
4441 }
4442 dest_capab->requestId = event->request_id;
4443 dest_capab->max_scan_buckets = src_cache->max_buckets;
4444 dest_capab->max_scan_cache_size = src_cache->scan_cache_entry_size;
4445 dest_capab->max_ap_cache_per_scan = src_cache->max_bssid_per_scan;
4446 dest_capab->max_scan_reporting_threshold =
4447 src_cache->max_table_usage_threshold;
4448
4449 dest_capab->max_hotlist_bssids = src_hotlist->max_hotlist_entries;
4450 dest_capab->max_rssi_sample_size = src_change->max_rssi_averaging_samples;
4451 dest_capab->max_bssid_history_entries =
4452 src_change->max_rssi_history_entries;
4453 dest_capab->max_significant_wifi_change_aps =
4454 src_change->max_wlan_change_entries;
4455 dest_capab->max_hotlist_ssids =
4456 event->num_extscan_hotlist_ssid;
4457 dest_capab->max_number_epno_networks =
4458 event->num_epno_networks;
4459 dest_capab->max_number_epno_networks_by_ssid =
4460 event->num_epno_networks;
4461 dest_capab->max_number_of_white_listed_ssid =
4462 event->num_roam_ssid_whitelist;
4463 dest_capab->status = 0;
4464
4465 WMA_LOGD("%s: request_id: %u status: %d",
4466 __func__, dest_capab->requestId, dest_capab->status);
4467
4468 WMA_LOGD("%s: Capabilities: max_scan_buckets: %d,"
4469 "max_hotlist_bssids: %d, max_scan_cache_size: %d,"
4470 "max_ap_cache_per_scan: %d, max_scan_reporting_threshold: %d,"
4471 "max_rssi_sample_size: %d, max_bssid_history_entries: %d,"
4472 "max_significant_wifi_change_aps: %d",
4473 __func__, dest_capab->max_scan_buckets,
4474 dest_capab->max_hotlist_bssids,
4475 dest_capab->max_scan_cache_size,
4476 dest_capab->max_ap_cache_per_scan,
4477 dest_capab->max_scan_reporting_threshold,
4478 dest_capab->max_rssi_sample_size,
4479 dest_capab->max_bssid_history_entries,
4480 dest_capab->max_significant_wifi_change_aps);
4481
4482 WMA_LOGD("%s: Capabilities: max_hotlist_ssids: %d,"
4483 "max_number_epno_networks: %d, max_number_epno_networks_by_ssid: %d,"
4484 "max_number_of_white_listed_ssid: %d",
4485 __func__, dest_capab->max_hotlist_ssids,
4486 dest_capab->max_number_epno_networks,
4487 dest_capab->max_number_epno_networks_by_ssid,
4488 dest_capab->max_number_of_white_listed_ssid);
4489
4490 pMac->sme.pExtScanIndCb(pMac->hHdd,
4491 eSIR_EXTSCAN_GET_CAPABILITIES_IND, dest_capab);
4492 WMA_LOGI("%s: sending capabilities event to hdd", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304493 qdf_mem_free(dest_capab);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004494 return 0;
4495}
4496
4497/**
4498 * wma_extscan_hotlist_match_event_handler() - hotlist match event handler
4499 * @handle: wma handle
4500 * @cmd_param_info: event buffer
4501 * @len: length
4502 *
4503 * This function handles hotlist match event and indicate
4504 * upper layers with registered callback.
4505 *
4506 * Return: 0 for success or error code.
4507 */
4508int wma_extscan_hotlist_match_event_handler(void *handle,
4509 uint8_t *cmd_param_info,
4510 uint32_t len)
4511{
4512 WMI_EXTSCAN_HOTLIST_MATCH_EVENTID_param_tlvs *param_buf;
4513 wmi_extscan_hotlist_match_event_fixed_param *event;
4514 struct extscan_hotlist_match *dest_hotlist;
4515 tSirWifiScanResult *dest_ap;
4516 wmi_extscan_wlan_descriptor *src_hotlist;
4517 int numap, j, ap_found = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304518 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004519
4520 if (!pMac) {
4521 WMA_LOGE("%s: Invalid pMac", __func__);
4522 return -EINVAL;
4523 }
4524 if (!pMac->sme.pExtScanIndCb) {
4525 WMA_LOGE("%s: Callback not registered", __func__);
4526 return -EINVAL;
4527 }
4528 param_buf = (WMI_EXTSCAN_HOTLIST_MATCH_EVENTID_param_tlvs *)
4529 cmd_param_info;
4530 if (!param_buf) {
4531 WMA_LOGE("%s: Invalid hotlist match event", __func__);
4532 return -EINVAL;
4533 }
4534 event = param_buf->fixed_param;
4535 src_hotlist = param_buf->hotlist_match;
4536 numap = event->total_entries;
4537
4538 if (!src_hotlist || !numap) {
4539 WMA_LOGE("%s: Hotlist AP's list invalid", __func__);
4540 return -EINVAL;
4541 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304542 dest_hotlist = qdf_mem_malloc(sizeof(*dest_hotlist) +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004543 sizeof(*dest_ap) * numap);
4544 if (!dest_hotlist) {
4545 WMA_LOGE("%s: Allocation failed for hotlist buffer", __func__);
4546 return -ENOMEM;
4547 }
4548 dest_ap = &dest_hotlist->ap[0];
4549 dest_hotlist->numOfAps = event->total_entries;
4550 dest_hotlist->requestId = event->config_request_id;
4551
4552 if (event->first_entry_index +
4553 event->num_entries_in_page < event->total_entries)
4554 dest_hotlist->moreData = 1;
4555 else
4556 dest_hotlist->moreData = 0;
4557
4558 WMA_LOGD("%s: Hotlist match: requestId: %u,"
4559 "numOfAps: %d", __func__,
4560 dest_hotlist->requestId, dest_hotlist->numOfAps);
4561
4562 /*
4563 * Currently firmware sends only one bss information in-case
4564 * of both hotlist ap found and lost.
4565 */
4566 for (j = 0; j < numap; j++) {
4567 dest_ap->rssi = 0;
4568 dest_ap->channel = src_hotlist->channel;
4569 dest_ap->ts = src_hotlist->tstamp;
4570 ap_found = src_hotlist->flags & WMI_HOTLIST_FLAG_PRESENCE;
4571 dest_ap->rtt = src_hotlist->rtt;
4572 dest_ap->rtt_sd = src_hotlist->rtt_sd;
4573 dest_ap->beaconPeriod = src_hotlist->beacon_interval;
4574 dest_ap->capability = src_hotlist->capabilities;
4575 dest_ap->ieLength = src_hotlist->ie_length;
4576 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_hotlist->bssid,
4577 dest_ap->bssid.bytes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304578 qdf_mem_copy(dest_ap->ssid, src_hotlist->ssid.ssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004579 src_hotlist->ssid.ssid_len);
4580 dest_ap->ssid[src_hotlist->ssid.ssid_len] = '\0';
4581 dest_ap++;
4582 src_hotlist++;
4583 }
4584 dest_hotlist->ap_found = ap_found;
4585 pMac->sme.pExtScanIndCb(pMac->hHdd,
4586 eSIR_EXTSCAN_HOTLIST_MATCH_IND, dest_hotlist);
4587 WMA_LOGI("%s: sending hotlist match event to hdd", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304588 qdf_mem_free(dest_hotlist);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004589 return 0;
4590}
4591
4592/** wma_extscan_find_unique_scan_ids() - find unique scan ids
4593 * @cmd_param_info: event data.
4594 *
4595 * This utility function parses the input bss table of information
4596 * and find the unique number of scan ids
4597 *
4598 * Return: 0 on success; error number otherwise
4599 */
4600static int wma_extscan_find_unique_scan_ids(const u_int8_t *cmd_param_info)
4601{
4602 WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf;
4603 wmi_extscan_cached_results_event_fixed_param *event;
4604 wmi_extscan_wlan_descriptor *src_hotlist;
4605 wmi_extscan_rssi_info *src_rssi;
4606 int prev_scan_id, scan_ids_cnt, i;
4607
4608 param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *)
4609 cmd_param_info;
4610 event = param_buf->fixed_param;
4611 src_hotlist = param_buf->bssid_list;
4612 src_rssi = param_buf->rssi_list;
4613
4614 /* Find the unique number of scan_id's for grouping */
4615 prev_scan_id = src_rssi->scan_cycle_id;
4616 scan_ids_cnt = 1;
4617 for (i = 1; i < event->num_entries_in_page; i++) {
4618 src_rssi++;
4619
4620 if (prev_scan_id != src_rssi->scan_cycle_id) {
4621 scan_ids_cnt++;
4622 prev_scan_id = src_rssi->scan_cycle_id;
4623 }
4624 }
4625
4626 return scan_ids_cnt;
4627}
4628
4629/** wma_fill_num_results_per_scan_id() - fill number of bss per scan id
4630 * @cmd_param_info: event data.
4631 * @scan_id_group: pointer to scan id group.
4632 *
4633 * This utility function parses the input bss table of information
4634 * and finds how many bss are there per unique scan id.
4635 *
4636 * Return: 0 on success; error number otherwise
4637 */
4638static int wma_fill_num_results_per_scan_id(const u_int8_t *cmd_param_info,
4639 struct extscan_cached_scan_result *scan_id_group)
4640{
4641 WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf;
4642 wmi_extscan_cached_results_event_fixed_param *event;
4643 wmi_extscan_wlan_descriptor *src_hotlist;
4644 wmi_extscan_rssi_info *src_rssi;
4645 struct extscan_cached_scan_result *t_scan_id_grp;
4646 int i, prev_scan_id;
4647
4648 param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *)
4649 cmd_param_info;
4650 event = param_buf->fixed_param;
4651 src_hotlist = param_buf->bssid_list;
4652 src_rssi = param_buf->rssi_list;
4653 t_scan_id_grp = scan_id_group;
4654
4655 prev_scan_id = src_rssi->scan_cycle_id;
4656
4657 t_scan_id_grp->scan_id = src_rssi->scan_cycle_id;
4658 t_scan_id_grp->flags = src_rssi->flags;
4659 t_scan_id_grp->num_results = 1;
4660 for (i = 1; i < event->num_entries_in_page; i++) {
4661 src_rssi++;
4662 if (prev_scan_id == src_rssi->scan_cycle_id) {
4663 t_scan_id_grp->num_results++;
4664 } else {
4665 t_scan_id_grp++;
4666 prev_scan_id = t_scan_id_grp->scan_id =
4667 src_rssi->scan_cycle_id;
4668 t_scan_id_grp->flags = src_rssi->flags;
4669 t_scan_id_grp->num_results = 1;
4670 }
4671 }
4672 return 0;
4673}
4674
4675/** wma_group_num_bss_to_scan_id() - group bss to scan id table
4676 * @cmd_param_info: event data.
4677 * @cached_result: pointer to cached table.
4678 *
4679 * This function reads the bss information from the format
4680 * ------------------------------------------------------------------------
4681 * | bss info {rssi, channel, ssid, bssid, timestamp} | scan id_1 | flags |
4682 * | bss info {rssi, channel, ssid, bssid, timestamp} | scan id_2 | flags |
4683 * ........................................................................
4684 * | bss info {rssi, channel, ssid, bssid, timestamp} | scan id_N | flags |
4685 * ------------------------------------------------------------------------
4686 *
4687 * and converts it into the below format and store it
4688 *
4689 * ------------------------------------------------------------------------
4690 * | scan id_1 | -> bss info_1 -> bss info_2 -> .... bss info_M1
4691 * | scan id_2 | -> bss info_1 -> bss info_2 -> .... bss info_M2
4692 * ......................
4693 * | scan id_N | -> bss info_1 -> bss info_2 -> .... bss info_Mn
4694 * ------------------------------------------------------------------------
4695 *
4696 * Return: 0 on success; error number otherwise
4697 */
4698static int wma_group_num_bss_to_scan_id(const u_int8_t *cmd_param_info,
4699 struct extscan_cached_scan_results *cached_result)
4700{
4701 WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf;
4702 wmi_extscan_cached_results_event_fixed_param *event;
4703 wmi_extscan_wlan_descriptor *src_hotlist;
4704 wmi_extscan_rssi_info *src_rssi;
4705 struct extscan_cached_scan_results *t_cached_result;
4706 struct extscan_cached_scan_result *t_scan_id_grp;
4707 int i, j;
4708 tSirWifiScanResult *ap;
4709
4710 param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *)
4711 cmd_param_info;
4712 event = param_buf->fixed_param;
4713 src_hotlist = param_buf->bssid_list;
4714 src_rssi = param_buf->rssi_list;
4715 t_cached_result = cached_result;
4716 t_scan_id_grp = &t_cached_result->result[0];
4717
4718 WMA_LOGD("%s: num_scan_ids:%d", __func__,
4719 t_cached_result->num_scan_ids);
4720 for (i = 0; i < t_cached_result->num_scan_ids; i++) {
4721 WMA_LOGD("%s: num_results:%d", __func__,
4722 t_scan_id_grp->num_results);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304723 t_scan_id_grp->ap = qdf_mem_malloc(t_scan_id_grp->num_results *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004724 sizeof(*ap));
4725 if (!t_scan_id_grp->ap) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304726 WMA_LOGD("%s: qdf_mem_malloc failed", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004727 return -ENOMEM;
4728 }
4729
4730 ap = &t_scan_id_grp->ap[0];
4731 for (j = 0; j < t_scan_id_grp->num_results; j++) {
4732 ap->channel = src_hotlist->channel;
4733 ap->ts = WMA_MSEC_TO_USEC(src_rssi->tstamp);
4734 ap->rtt = src_hotlist->rtt;
4735 ap->rtt_sd = src_hotlist->rtt_sd;
4736 ap->beaconPeriod = src_hotlist->beacon_interval;
4737 ap->capability = src_hotlist->capabilities;
4738 ap->ieLength = src_hotlist->ie_length;
4739
4740 /* Firmware already applied noise floor adjustment and
4741 * due to WMI interface "UINT32 rssi", host driver
4742 * receives a positive value, hence convert to
4743 * signed char to get the absolute rssi.
4744 */
4745 ap->rssi = (signed char) src_rssi->rssi;
4746 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_hotlist->bssid,
4747 ap->bssid.bytes);
4748
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304749 qdf_mem_copy(ap->ssid, src_hotlist->ssid.ssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004750 src_hotlist->ssid.ssid_len);
4751 ap->ssid[src_hotlist->ssid.ssid_len] = '\0';
4752 ap++;
4753 src_rssi++;
4754 src_hotlist++;
4755 }
4756 t_scan_id_grp++;
4757 }
4758 return 0;
4759}
4760
4761/**
4762 * wma_extscan_cached_results_event_handler() - cached results event handler
4763 * @handle: wma handle
4764 * @cmd_param_info: event buffer
4765 * @len: length of @cmd_param_info
4766 *
4767 * This function handles cached results event and indicate
4768 * cached results to upper layer.
4769 *
4770 * Return: 0 for success or error code.
4771 */
4772int wma_extscan_cached_results_event_handler(void *handle,
4773 uint8_t *cmd_param_info,
4774 uint32_t len)
4775{
4776 WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf;
4777 wmi_extscan_cached_results_event_fixed_param *event;
4778 struct extscan_cached_scan_results *dest_cachelist;
4779 struct extscan_cached_scan_result *dest_result;
4780 struct extscan_cached_scan_results empty_cachelist;
4781 wmi_extscan_wlan_descriptor *src_hotlist;
4782 wmi_extscan_rssi_info *src_rssi;
4783 int numap, i, moredata, scan_ids_cnt, buf_len;
4784
Anurag Chouhan6d760662016-02-20 16:05:43 +05304785 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004786 if (!pMac) {
4787 WMA_LOGE("%s: Invalid pMac", __func__);
4788 return -EINVAL;
4789 }
4790 if (!pMac->sme.pExtScanIndCb) {
4791 WMA_LOGE("%s: Callback not registered", __func__);
4792 return -EINVAL;
4793 }
4794 param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *)
4795 cmd_param_info;
4796 if (!param_buf) {
4797 WMA_LOGE("%s: Invalid cached results event", __func__);
4798 return -EINVAL;
4799 }
4800 event = param_buf->fixed_param;
4801 src_hotlist = param_buf->bssid_list;
4802 src_rssi = param_buf->rssi_list;
4803 numap = event->num_entries_in_page;
4804 WMA_LOGI("Total_entries %u first_entry_index %u", event->total_entries,
4805 event->first_entry_index);
4806 WMA_LOGI("num_entries_in_page %d", numap);
4807 if (!src_hotlist || !src_rssi || !numap) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004808 WMA_LOGW("%s: Cached results empty, send 0 results", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004809 goto noresults;
4810 }
4811 if (event->first_entry_index +
4812 event->num_entries_in_page < event->total_entries)
4813 moredata = 1;
4814 else
4815 moredata = 0;
4816
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304817 dest_cachelist = qdf_mem_malloc(sizeof(*dest_cachelist));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004818 if (!dest_cachelist) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304819 WMA_LOGE("%s: qdf_mem_malloc failed", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004820 return -ENOMEM;
4821 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304822 qdf_mem_zero(dest_cachelist, sizeof(*dest_cachelist));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004823 dest_cachelist->request_id = event->request_id;
4824 dest_cachelist->more_data = moredata;
4825
4826 scan_ids_cnt = wma_extscan_find_unique_scan_ids(cmd_param_info);
4827 WMA_LOGI("%s: scan_ids_cnt %d", __func__, scan_ids_cnt);
4828 dest_cachelist->num_scan_ids = scan_ids_cnt;
4829
4830 buf_len = sizeof(*dest_result) * scan_ids_cnt;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304831 dest_cachelist->result = qdf_mem_malloc(buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004832 if (!dest_cachelist->result) {
4833 WMA_LOGE("%s: Allocation failed for scanid grouping", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304834 qdf_mem_free(dest_cachelist);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004835 return -ENOMEM;
4836 }
4837
4838 dest_result = dest_cachelist->result;
4839 wma_fill_num_results_per_scan_id(cmd_param_info, dest_result);
4840 wma_group_num_bss_to_scan_id(cmd_param_info, dest_cachelist);
4841
4842 pMac->sme.pExtScanIndCb(pMac->hHdd,
4843 eSIR_EXTSCAN_CACHED_RESULTS_IND,
4844 dest_cachelist);
4845 WMA_LOGI("%s: sending cached results event", __func__);
4846 dest_result = dest_cachelist->result;
4847 for (i = 0; i < dest_cachelist->num_scan_ids; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304848 qdf_mem_free(dest_result->ap);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004849 dest_result++;
4850 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304851 qdf_mem_free(dest_cachelist->result);
4852 qdf_mem_free(dest_cachelist);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004853 return 0;
4854
4855noresults:
4856 empty_cachelist.request_id = event->request_id;
4857 empty_cachelist.more_data = 0;
4858 empty_cachelist.num_scan_ids = 0;
4859
4860 pMac->sme.pExtScanIndCb(pMac->hHdd,
4861 eSIR_EXTSCAN_CACHED_RESULTS_IND,
4862 &empty_cachelist);
4863 WMA_LOGI("%s: sending cached results event", __func__);
4864 return 0;
4865}
4866
4867/**
4868 * wma_extscan_change_results_event_handler() - change results event handler
4869 * @handle: wma handle
4870 * @cmd_param_info: event buffer
4871 * @len: length
4872 *
4873 * This function handles change results event and indicate
4874 * change results to upper layer.
4875 *
4876 * Return: 0 for success or error code.
4877 */
4878int wma_extscan_change_results_event_handler(void *handle,
4879 uint8_t *cmd_param_info,
4880 uint32_t len)
4881{
4882 WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID_param_tlvs *param_buf;
4883 wmi_extscan_wlan_change_results_event_fixed_param *event;
4884 tSirWifiSignificantChangeEvent *dest_chglist;
4885 tSirWifiSignificantChange *dest_ap;
4886 wmi_extscan_wlan_change_result_bssid *src_chglist;
4887
4888 int numap;
4889 int i, k;
4890 uint8_t *src_rssi;
4891 int count = 0;
4892 int moredata;
4893 int rssi_num = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304894 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004895 if (!pMac) {
4896 WMA_LOGE("%s: Invalid pMac", __func__);
4897 return -EINVAL;
4898 }
4899 if (!pMac->sme.pExtScanIndCb) {
4900 WMA_LOGE("%s: Callback not registered", __func__);
4901 return -EINVAL;
4902 }
4903 param_buf = (WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID_param_tlvs *)
4904 cmd_param_info;
4905 if (!param_buf) {
4906 WMA_LOGE("%s: Invalid change monitor event", __func__);
4907 return -EINVAL;
4908 }
4909 event = param_buf->fixed_param;
4910 src_chglist = param_buf->bssid_signal_descriptor_list;
4911 src_rssi = param_buf->rssi_list;
4912 numap = event->num_entries_in_page;
4913
4914 if (!src_chglist || !numap) {
4915 WMA_LOGE("%s: Results invalid", __func__);
4916 return -EINVAL;
4917 }
4918 for (i = 0; i < numap; i++) {
4919 rssi_num += src_chglist->num_rssi_samples;
4920 }
4921 if (event->first_entry_index +
4922 event->num_entries_in_page < event->total_entries) {
4923 moredata = 1;
4924 } else {
4925 moredata = 0;
4926 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304927 dest_chglist = qdf_mem_malloc(sizeof(*dest_chglist) +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004928 sizeof(*dest_ap) * numap +
4929 sizeof(int32_t) * rssi_num);
4930 if (!dest_chglist) {
4931 WMA_LOGE("%s: Allocation failed for change monitor", __func__);
4932 return -ENOMEM;
4933 }
4934 dest_ap = &dest_chglist->ap[0];
4935 for (i = 0; i < numap; i++) {
4936 dest_ap->channel = src_chglist->channel;
4937 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_chglist->bssid,
4938 dest_ap->bssid.bytes);
4939 dest_ap->numOfRssi = src_chglist->num_rssi_samples;
4940 if (dest_ap->numOfRssi) {
4941 for (k = 0; k < dest_ap->numOfRssi; k++) {
4942 dest_ap->rssi[k] = WMA_TGT_NOISE_FLOOR_DBM +
4943 src_rssi[count++];
4944 }
4945 }
4946 dest_ap += dest_ap->numOfRssi * sizeof(int32_t);
4947 src_chglist++;
4948 }
4949 dest_chglist->requestId = event->request_id;
4950 dest_chglist->moreData = moredata;
4951 dest_chglist->numResults = event->total_entries;
4952
4953 pMac->sme.pExtScanIndCb(pMac->hHdd,
4954 eSIR_EXTSCAN_SIGNIFICANT_WIFI_CHANGE_RESULTS_IND,
4955 dest_chglist);
4956 WMA_LOGI("%s: sending change monitor results", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304957 qdf_mem_free(dest_chglist);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004958 return 0;
4959}
4960
4961/**
4962 * wma_passpoint_match_event_handler() - passpoint match found event handler
4963 * @handle: WMA handle
4964 * @cmd_param_info: event data
4965 * @len: event data length
4966 *
4967 * This is the passpoint match found event handler; it reads event data from
4968 * @cmd_param_info and fill in the destination buffer and sends indication
4969 * up layer.
4970 *
4971 * Return: 0 on success; error number otherwise
4972 */
4973int wma_passpoint_match_event_handler(void *handle,
4974 uint8_t *cmd_param_info,
4975 uint32_t len)
4976{
4977 WMI_PASSPOINT_MATCH_EVENTID_param_tlvs *param_buf;
4978 wmi_passpoint_event_hdr *event;
4979 struct wifi_passpoint_match *dest_match;
4980 tSirWifiScanResult *dest_ap;
4981 uint8_t *buf_ptr;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304982 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004983
4984 if (!mac) {
4985 WMA_LOGE("%s: Invalid mac", __func__);
4986 return -EINVAL;
4987 }
4988 if (!mac->sme.pExtScanIndCb) {
4989 WMA_LOGE("%s: Callback not registered", __func__);
4990 return -EINVAL;
4991 }
4992
4993 param_buf = (WMI_PASSPOINT_MATCH_EVENTID_param_tlvs *) cmd_param_info;
4994 if (!param_buf) {
4995 WMA_LOGE("%s: Invalid passpoint match event", __func__);
4996 return -EINVAL;
4997 }
4998 event = param_buf->fixed_param;
4999 buf_ptr = (uint8_t *)param_buf->fixed_param;
5000
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305001 dest_match = qdf_mem_malloc(sizeof(*dest_match) +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005002 event->ie_length + event->anqp_length);
5003 if (!dest_match) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305004 WMA_LOGE("%s: qdf_mem_malloc failed", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005005 return -EINVAL;
5006 }
5007 dest_ap = &dest_match->ap;
5008 dest_match->request_id = 0;
5009 dest_match->id = event->id;
5010 dest_match->anqp_len = event->anqp_length;
5011 WMA_LOGI("%s: passpoint match: id: %u anqp length %u", __func__,
5012 dest_match->id, dest_match->anqp_len);
5013
5014 dest_ap->channel = event->channel_mhz;
5015 dest_ap->ts = event->timestamp;
5016 dest_ap->rtt = event->rtt;
5017 dest_ap->rssi = event->rssi;
5018 dest_ap->rtt_sd = event->rtt_sd;
5019 dest_ap->beaconPeriod = event->beacon_period;
5020 dest_ap->capability = event->capability;
5021 dest_ap->ieLength = event->ie_length;
5022 WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->bssid, dest_ap->bssid.bytes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305023 qdf_mem_copy(dest_ap->ssid, event->ssid.ssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005024 event->ssid.ssid_len);
5025 dest_ap->ssid[event->ssid.ssid_len] = '\0';
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305026 qdf_mem_copy(dest_ap->ieData, buf_ptr + sizeof(*event) +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005027 WMI_TLV_HDR_SIZE, dest_ap->ieLength);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305028 qdf_mem_copy(dest_match->anqp, buf_ptr + sizeof(*event) +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005029 WMI_TLV_HDR_SIZE + dest_ap->ieLength,
5030 dest_match->anqp_len);
5031
5032 mac->sme.pExtScanIndCb(mac->hHdd,
5033 eSIR_PASSPOINT_NETWORK_FOUND_IND,
5034 dest_match);
5035 WMA_LOGI("%s: sending passpoint match event to hdd", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305036 qdf_mem_free(dest_match);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005037 return 0;
5038}
5039
5040/**
5041 * wma_extscan_hotlist_ssid_match_event_handler() -
5042 * Handler for SSID hotlist match event from firmware
5043 * @handle: WMA handle
5044 * @cmd_param_info: WMI command buffer
5045 * @len: length of @cmd_param_info
5046 *
5047 * Return: 0 on success, non-zero on failure
5048 */
5049int
5050wma_extscan_hotlist_ssid_match_event_handler(void *handle,
5051 uint8_t *cmd_param_info,
5052 uint32_t len)
5053{
5054 WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID_param_tlvs *param_buf;
5055 wmi_extscan_hotlist_ssid_match_event_fixed_param *event;
5056 tSirWifiScanResultEvent *dest_hotlist;
5057 tSirWifiScanResult *dest_ap;
5058 wmi_extscan_wlan_descriptor *src_hotlist;
5059 int numap, j;
5060 bool ssid_found = false;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305061 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005062
5063 if (!mac) {
5064 WMA_LOGE("%s: Invalid mac", __func__);
5065 return -EINVAL;
5066 }
5067
5068 if (!mac->sme.pExtScanIndCb) {
5069 WMA_LOGE("%s: Callback not registered", __func__);
5070 return -EINVAL;
5071 }
5072
5073 param_buf = (WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID_param_tlvs *)
5074 cmd_param_info;
5075 if (!param_buf) {
5076 WMA_LOGE("%s: Invalid hotlist match event", __func__);
5077 return -EINVAL;
5078 }
5079
5080 event = param_buf->fixed_param;
5081 src_hotlist = param_buf->hotlist_ssid_match;
5082 numap = event->total_entries;
5083 if (!src_hotlist || !numap) {
5084 WMA_LOGE("%s: Hotlist AP's list invalid", __func__);
5085 return -EINVAL;
5086 }
5087
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305088 dest_hotlist = qdf_mem_malloc(sizeof(*dest_hotlist) +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005089 sizeof(*dest_ap) * numap);
5090 if (!dest_hotlist) {
5091 WMA_LOGE("%s: Allocation failed for hotlist buffer",
5092 __func__);
5093 return -EINVAL;
5094 }
5095
5096 dest_ap = &dest_hotlist->ap[0];
5097 dest_hotlist->numOfAps = event->total_entries;
5098 dest_hotlist->requestId = event->config_request_id;
5099
5100 if (event->first_entry_index +
5101 event->num_entries_in_page < event->total_entries)
5102 dest_hotlist->moreData = 1;
5103 else
5104 dest_hotlist->moreData = 0;
5105
5106 WMA_LOGD("%s: Hotlist match: requestId: %u,numOfAps: %d", __func__,
5107 dest_hotlist->requestId, dest_hotlist->numOfAps);
5108
5109 for (j = 0; j < numap; j++) {
5110 dest_ap->channel = src_hotlist->channel;
5111 dest_ap->ts = src_hotlist->tstamp;
5112 ssid_found = src_hotlist->flags & WMI_HOTLIST_FLAG_PRESENCE;
5113 dest_ap->rtt = src_hotlist->rtt;
5114 dest_ap->rtt_sd = src_hotlist->rtt_sd;
5115 dest_ap->beaconPeriod = src_hotlist->beacon_interval;
5116 dest_ap->capability = src_hotlist->capabilities;
5117 dest_ap->ieLength = src_hotlist->ie_length;
5118 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_hotlist->bssid,
5119 dest_ap->bssid.bytes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305120 qdf_mem_copy(dest_ap->ssid, src_hotlist->ssid.ssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005121 src_hotlist->ssid.ssid_len);
5122 dest_ap->ssid[src_hotlist->ssid.ssid_len] = '\0';
5123 dest_ap++;
5124 src_hotlist++;
5125 }
5126
5127 dest_hotlist->ap_found = ssid_found;
5128 mac->sme.pExtScanIndCb(mac->hHdd,
5129 eSIR_EXTSCAN_HOTLIST_SSID_MATCH_IND,
5130 dest_hotlist);
5131 WMA_LOGI("%s: sending hotlist ssid match event", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305132 qdf_mem_free(dest_hotlist);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005133 return 0;
5134}
5135
5136/**
5137 * wma_get_buf_extscan_start_cmd() - Fill extscan start request
5138 * @handle: wma handle
5139 * @pstart: scan command request params
5140 * @buf: event buffer
5141 * @buf_len: length of buffer
5142 *
5143 * This function fills individual elements of extscan request and
5144 * TLV for buckets, channel list.
5145 *
5146 * Return: CDF Status.
5147 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305148QDF_STATUS wma_get_buf_extscan_start_cmd(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005149 tSirWifiScanCmdReqParams *pstart,
5150 wmi_buf_t *buf, int *buf_len)
5151{
5152 wmi_extscan_start_cmd_fixed_param *cmd;
5153 wmi_extscan_bucket *dest_blist;
5154 wmi_extscan_bucket_channel *dest_clist;
5155 tSirWifiScanBucketSpec *src_bucket = pstart->buckets;
5156 tSirWifiScanChannelSpec *src_channel = src_bucket->channels;
5157 tSirWifiScanChannelSpec save_channel[WLAN_EXTSCAN_MAX_CHANNELS];
5158
5159 uint8_t *buf_ptr;
5160 int i, k, count = 0;
5161 int len = sizeof(*cmd);
5162 int nbuckets = pstart->numBuckets;
5163 int nchannels = 0;
5164
5165 /* These TLV's are are NULL by default */
5166 uint32_t ie_len_with_pad = 0;
5167 int num_ssid = 0;
5168 int num_bssid = 0;
5169 int ie_len = 0;
5170
5171 uint32_t base_period = pstart->basePeriod;
5172
5173 /* TLV placeholder for ssid_list (NULL) */
5174 len += WMI_TLV_HDR_SIZE;
5175 len += num_ssid * sizeof(wmi_ssid);
5176
5177 /* TLV placeholder for bssid_list (NULL) */
5178 len += WMI_TLV_HDR_SIZE;
5179 len += num_bssid * sizeof(wmi_mac_addr);
5180
5181 /* TLV placeholder for ie_data (NULL) */
5182 len += WMI_TLV_HDR_SIZE;
5183 len += ie_len * sizeof(uint32_t);
5184
5185 /* TLV placeholder for bucket */
5186 len += WMI_TLV_HDR_SIZE;
5187 len += nbuckets * sizeof(wmi_extscan_bucket);
5188
5189 /* TLV channel placeholder */
5190 len += WMI_TLV_HDR_SIZE;
5191 for (i = 0; i < nbuckets; i++) {
5192 nchannels += src_bucket->numChannels;
5193 src_bucket++;
5194 }
5195
5196 WMA_LOGD("%s: Total buckets: %d total #of channels is %d",
5197 __func__, nbuckets, nchannels);
5198 len += nchannels * sizeof(wmi_extscan_bucket_channel);
5199 /* Allocate the memory */
5200 *buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5201 if (!*buf) {
5202 WMA_LOGP("%s: failed to allocate memory"
5203 " for start extscan cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305204 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005205 }
5206 buf_ptr = (uint8_t *) wmi_buf_data(*buf);
5207 cmd = (wmi_extscan_start_cmd_fixed_param *) buf_ptr;
5208 WMITLV_SET_HDR(&cmd->tlv_header,
5209 WMITLV_TAG_STRUC_wmi_extscan_start_cmd_fixed_param,
5210 WMITLV_GET_STRUCT_TLVLEN
5211 (wmi_extscan_start_cmd_fixed_param));
5212
5213 cmd->request_id = pstart->requestId;
5214 cmd->vdev_id = pstart->sessionId;
5215 cmd->base_period = pstart->basePeriod;
5216 cmd->num_buckets = nbuckets;
5217 cmd->configuration_flags = 0;
5218 if (pstart->configuration_flags & EXTSCAN_LP_EXTENDED_BATCHING)
5219 cmd->configuration_flags |= WMI_EXTSCAN_EXTENDED_BATCHING_EN;
5220 WMA_LOGI("%s: configuration_flags: 0x%x", __func__,
5221 cmd->configuration_flags);
5222
5223 cmd->min_rest_time = WMA_EXTSCAN_REST_TIME;
5224 cmd->max_rest_time = WMA_EXTSCAN_REST_TIME;
5225 cmd->max_bssids_per_scan_cycle = pstart->maxAPperScan;
5226
5227 /* The max dwell time is retrieved from the first channel
5228 * of the first bucket and kept common for all channels.
5229 */
5230 cmd->min_dwell_time_active = pstart->min_dwell_time_active;
5231 cmd->max_dwell_time_active = pstart->max_dwell_time_active;
5232 cmd->min_dwell_time_passive = pstart->min_dwell_time_passive;
5233 cmd->max_dwell_time_passive = pstart->max_dwell_time_passive;
5234 cmd->max_bssids_per_scan_cycle = pstart->maxAPperScan;
5235 cmd->max_table_usage = pstart->report_threshold_percent;
5236 cmd->report_threshold_num_scans = pstart->report_threshold_num_scans;
5237
5238 cmd->repeat_probe_time = cmd->max_dwell_time_active /
5239 WMA_SCAN_NPROBES_DEFAULT;
5240 cmd->max_scan_time = WMA_EXTSCAN_MAX_SCAN_TIME;
5241 cmd->probe_delay = 0;
5242 cmd->probe_spacing_time = 0;
5243 cmd->idle_time = 0;
5244 cmd->burst_duration = WMA_EXTSCAN_BURST_DURATION;
5245 cmd->scan_ctrl_flags = WMI_SCAN_ADD_BCAST_PROBE_REQ |
5246 WMI_SCAN_ADD_CCK_RATES |
Sreelakshmi Konamki75deb332015-09-14 10:58:03 +05305247 WMI_SCAN_ADD_OFDM_RATES |
5248 WMI_SCAN_ADD_SPOOFED_MAC_IN_PROBE_REQ |
5249 WMI_SCAN_ADD_DS_IE_IN_PROBE_REQ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005250 cmd->scan_priority = WMI_SCAN_PRIORITY_HIGH;
5251 cmd->num_ssids = 0;
5252 cmd->num_bssid = 0;
5253 cmd->ie_len = 0;
5254 cmd->n_probes = (cmd->repeat_probe_time > 0) ?
5255 cmd->max_dwell_time_active / cmd->repeat_probe_time : 0;
5256
5257 buf_ptr += sizeof(*cmd);
5258 WMITLV_SET_HDR(buf_ptr,
5259 WMITLV_TAG_ARRAY_FIXED_STRUC,
5260 num_ssid * sizeof(wmi_ssid));
5261 buf_ptr += WMI_TLV_HDR_SIZE + (num_ssid * sizeof(wmi_ssid));
5262
5263 WMITLV_SET_HDR(buf_ptr,
5264 WMITLV_TAG_ARRAY_FIXED_STRUC,
5265 num_bssid * sizeof(wmi_mac_addr));
5266 buf_ptr += WMI_TLV_HDR_SIZE + (num_bssid * sizeof(wmi_mac_addr));
5267
5268 ie_len_with_pad = 0;
5269 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_with_pad);
5270 buf_ptr += WMI_TLV_HDR_SIZE + ie_len_with_pad;
5271
5272 WMITLV_SET_HDR(buf_ptr,
5273 WMITLV_TAG_ARRAY_STRUC,
5274 nbuckets * sizeof(wmi_extscan_bucket));
5275 dest_blist = (wmi_extscan_bucket *)
5276 (buf_ptr + WMI_TLV_HDR_SIZE);
5277 src_bucket = pstart->buckets;
5278
5279 /* Retrieve scanning information from each bucket and
5280 * channels and send it to the target
5281 */
5282 for (i = 0; i < nbuckets; i++) {
5283 WMITLV_SET_HDR(dest_blist,
5284 WMITLV_TAG_STRUC_wmi_extscan_bucket_cmd_fixed_param,
5285 WMITLV_GET_STRUCT_TLVLEN(wmi_extscan_bucket));
5286
5287 dest_blist->bucket_id = src_bucket->bucket;
5288 dest_blist->base_period_multiplier =
5289 src_bucket->period / base_period;
5290 dest_blist->min_period = src_bucket->period;
5291 dest_blist->max_period = src_bucket->max_period;
5292 dest_blist->exp_backoff = src_bucket->exponent;
5293 dest_blist->exp_max_step_count = src_bucket->step_count;
5294 dest_blist->channel_band = src_bucket->band;
5295 dest_blist->num_channels = src_bucket->numChannels;
5296 dest_blist->notify_extscan_events = 0;
5297
5298 if (src_bucket->reportEvents & EXTSCAN_REPORT_EVENTS_EACH_SCAN)
5299 dest_blist->notify_extscan_events =
5300 WMI_EXTSCAN_BUCKET_COMPLETED_EVENT;
5301
5302 if (src_bucket->reportEvents &
5303 EXTSCAN_REPORT_EVENTS_FULL_RESULTS) {
5304 dest_blist->forwarding_flags =
5305 WMI_EXTSCAN_FORWARD_FRAME_TO_HOST;
5306 dest_blist->notify_extscan_events |=
5307 WMI_EXTSCAN_BUCKET_COMPLETED_EVENT |
5308 WMI_EXTSCAN_CYCLE_STARTED_EVENT |
5309 WMI_EXTSCAN_CYCLE_COMPLETED_EVENT;
5310 } else {
5311 dest_blist->forwarding_flags =
5312 WMI_EXTSCAN_NO_FORWARDING;
5313 }
5314
5315 if (src_bucket->reportEvents & EXTSCAN_REPORT_EVENTS_NO_BATCH)
5316 dest_blist->configuration_flags = 0;
5317 else
5318 dest_blist->configuration_flags =
5319 WMI_EXTSCAN_BUCKET_CACHE_RESULTS;
5320
5321 WMA_LOGI("%s: ntfy_extscan_events:%u cfg_flags:%u fwd_flags:%u",
5322 __func__, dest_blist->notify_extscan_events,
5323 dest_blist->configuration_flags,
5324 dest_blist->forwarding_flags);
5325
5326 dest_blist->min_dwell_time_active = src_bucket->min_dwell_time_active;
5327 dest_blist->max_dwell_time_active = src_bucket->max_dwell_time_active;
5328 dest_blist->min_dwell_time_passive = src_bucket->min_dwell_time_passive;
5329 dest_blist->max_dwell_time_passive = src_bucket->max_dwell_time_passive;
5330 src_channel = src_bucket->channels;
5331
5332 /* save the channel info to later populate
5333 * the channel TLV
5334 */
5335 for (k = 0; k < src_bucket->numChannels; k++) {
5336 save_channel[count++].channel = src_channel->channel;
5337 src_channel++;
5338 }
5339 dest_blist++;
5340 src_bucket++;
5341 }
5342 buf_ptr += WMI_TLV_HDR_SIZE + (nbuckets * sizeof(wmi_extscan_bucket));
5343 WMITLV_SET_HDR(buf_ptr,
5344 WMITLV_TAG_ARRAY_STRUC,
5345 nchannels * sizeof(wmi_extscan_bucket_channel));
5346 dest_clist = (wmi_extscan_bucket_channel *)
5347 (buf_ptr + WMI_TLV_HDR_SIZE);
5348
5349 /* Active or passive scan is based on the bucket dwell time
5350 * and channel specific active,passive scans are not
5351 * supported yet
5352 */
5353 for (i = 0; i < nchannels; i++) {
5354 WMITLV_SET_HDR(dest_clist,
5355 WMITLV_TAG_STRUC_wmi_extscan_bucket_channel_event_fixed_param,
5356 WMITLV_GET_STRUCT_TLVLEN
5357 (wmi_extscan_bucket_channel));
5358 dest_clist->channel = save_channel[i].channel;
5359 dest_clist++;
5360 }
5361 buf_ptr += WMI_TLV_HDR_SIZE +
5362 (nchannels * sizeof(wmi_extscan_bucket_channel));
5363 *buf_len = len;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305364 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005365}
5366
5367/**
5368 * wma_start_extscan() - start extscan command to fw.
5369 * @handle: wma handle
5370 * @pstart: scan command request params
5371 *
5372 * This function sends start extscan request to fw.
5373 *
5374 * Return: CDF Status.
5375 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305376QDF_STATUS wma_start_extscan(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005377 tSirWifiScanCmdReqParams *pstart)
5378{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305379 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005380 wmi_buf_t buf;
5381 int len;
5382 if (!wma || !wma->wmi_handle) {
5383 WMA_LOGE("%s: WMA is closed,can not issue extscan cmd",
5384 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305385 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005386 }
5387 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
5388 WMI_SERVICE_EXTSCAN)) {
5389 WMA_LOGE("%s: extscan feature bit not enabled", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305390 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005391 }
5392 /* Fill individual elements of extscan request and
5393 * TLV for buckets, channel list.
5394 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305395 qdf_status = wma_get_buf_extscan_start_cmd(wma, pstart, &buf, &len);
5396 if (qdf_status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005397 WMA_LOGE("%s: Failed to get buffer for ext scan cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305398 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005399 }
5400 if (!buf) {
5401 WMA_LOGE("%s:Failed to get buffer"
5402 "for current extscan info", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305403 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005404 }
5405 if (wmi_unified_cmd_send(wma->wmi_handle, buf,
5406 len, WMI_EXTSCAN_START_CMDID)) {
5407 WMA_LOGE("%s: failed to send command", __func__);
Nirav Shahcbc6d722016-03-01 16:24:53 +05305408 qdf_nbuf_free(buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305409 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005410 }
5411 wma->interfaces[pstart->sessionId].extscan_in_progress = true;
5412 WMA_LOGD("Extscan start request sent successfully for vdev %d",
5413 pstart->sessionId);
5414
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305415 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005416}
5417
5418/**
5419 * wma_stop_extscan() - stop extscan command to fw.
5420 * @handle: wma handle
5421 * @pstopcmd: stop scan command request params
5422 *
5423 * This function sends stop extscan request to fw.
5424 *
5425 * Return: CDF Status.
5426 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305427QDF_STATUS wma_stop_extscan(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005428 tSirExtScanStopReqParams *pstopcmd)
5429{
5430 wmi_extscan_stop_cmd_fixed_param *cmd;
5431 wmi_buf_t wmi_buf;
5432 uint32_t len;
5433 uint8_t *buf_ptr;
5434
5435 if (!wma || !wma->wmi_handle) {
5436 WMA_LOGE("%s: WMA is closed, cannot issue cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305437 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005438 }
5439 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
5440 WMI_SERVICE_EXTSCAN)) {
5441 WMA_LOGE("%s: extscan not enabled", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305442 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005443 }
5444 len = sizeof(*cmd);
5445 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
5446 if (!wmi_buf) {
5447 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305448 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005449 }
5450 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
5451 cmd = (wmi_extscan_stop_cmd_fixed_param *) buf_ptr;
5452 WMITLV_SET_HDR(&cmd->tlv_header,
5453 WMITLV_TAG_STRUC_wmi_extscan_stop_cmd_fixed_param,
5454 WMITLV_GET_STRUCT_TLVLEN
5455 (wmi_extscan_stop_cmd_fixed_param));
5456
5457 cmd->request_id = pstopcmd->requestId;
5458 cmd->vdev_id = pstopcmd->sessionId;
5459
5460 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
5461 WMI_EXTSCAN_STOP_CMDID)) {
5462 WMA_LOGE("%s: failed to command", __func__);
Nirav Shahcbc6d722016-03-01 16:24:53 +05305463 qdf_nbuf_free(wmi_buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305464 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005465 }
5466 wma->interfaces[pstopcmd->sessionId].extscan_in_progress = false;
5467 WMA_LOGD("Extscan stop request sent successfully for vdev %d",
5468 pstopcmd->sessionId);
5469
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305470 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005471}
5472
5473/** wma_get_hotlist_entries_per_page() - hotlist entries per page
5474 * @wmi_handle: wmi handle.
5475 * @cmd: size of command structure.
5476 * @per_entry_size: per entry size.
5477 *
5478 * This utility function calculates how many hotlist entries can
5479 * fit in one page.
5480 *
5481 * Return: number of entries
5482 */
5483static inline int wma_get_hotlist_entries_per_page(wmi_unified_t wmi_handle,
5484 size_t cmd_size,
5485 size_t per_entry_size)
5486{
5487 uint32_t avail_space = 0;
5488 int num_entries = 0;
5489 uint16_t max_msg_len = wmi_get_max_msg_len(wmi_handle);
5490
5491 /* Calculate number of hotlist entries that can
5492 * be passed in wma message request.
5493 */
5494 avail_space = max_msg_len - cmd_size;
5495 num_entries = avail_space / per_entry_size;
5496 return num_entries;
5497}
5498
5499/**
5500 * wma_get_buf_extscan_hotlist_cmd() - prepare hotlist command
5501 * @handle: wma handle
5502 * @photlist: hotlist command params
5503 * @buf_len: buffer length
5504 *
5505 * This function fills individual elements for hotlist request and
5506 * TLV for bssid entries
5507 *
5508 * Return: CDF Status.
5509 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305510QDF_STATUS wma_get_buf_extscan_hotlist_cmd(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005511 tSirExtScanSetBssidHotListReqParams *
5512 photlist, int *buf_len)
5513{
5514 wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *cmd = NULL;
5515 wmi_extscan_hotlist_entry *dest_hotlist;
5516 tSirAPThresholdParam *src_ap = photlist->ap;
5517 wmi_buf_t buf;
5518 uint8_t *buf_ptr;
5519
5520 int j, index = 0;
5521 int cmd_len = 0;
5522 int num_entries = 0;
5523 int min_entries = 0;
5524 int numap = photlist->numAp;
5525 int len = sizeof(*cmd);
5526
5527 len += WMI_TLV_HDR_SIZE;
5528 cmd_len = len;
5529
5530 /* setbssid hotlist expects the bssid list
5531 * to be non zero value
5532 */
5533 if (!numap) {
5534 WMA_LOGE("%s: Invalid number of bssid's", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305535 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005536 }
5537 num_entries = wma_get_hotlist_entries_per_page(wma_handle->wmi_handle,
5538 cmd_len,
5539 sizeof(*dest_hotlist));
5540
5541 /* Split the hot list entry pages and send multiple command
5542 * requests if the buffer reaches the maximum request size
5543 */
5544 while (index < numap) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05305545 min_entries = QDF_MIN(num_entries, numap);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005546 len += min_entries * sizeof(wmi_extscan_hotlist_entry);
5547 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5548 if (!buf) {
5549 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305550 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005551 }
5552 buf_ptr = (uint8_t *) wmi_buf_data(buf);
5553 cmd = (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *)
5554 buf_ptr;
5555 WMITLV_SET_HDR(&cmd->tlv_header,
5556 WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_monitor_cmd_fixed_param,
5557 WMITLV_GET_STRUCT_TLVLEN
5558 (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param));
5559
5560 /* Multiple requests are sent until the num_entries_in_page
5561 * matches the total_entries
5562 */
5563 cmd->request_id = photlist->requestId;
5564 cmd->vdev_id = photlist->sessionId;
5565 cmd->total_entries = numap;
5566 cmd->mode = 1;
5567 cmd->num_entries_in_page = min_entries;
5568 cmd->lost_ap_scan_count = photlist->lost_ap_sample_size;
5569 cmd->first_entry_index = index;
5570
5571 WMA_LOGD("%s: vdev id:%d total_entries: %d num_entries: %d lost_ap_sample_size: %d",
5572 __func__, cmd->vdev_id, cmd->total_entries,
5573 cmd->num_entries_in_page,
5574 cmd->lost_ap_scan_count);
5575
5576 buf_ptr += sizeof(*cmd);
5577 WMITLV_SET_HDR(buf_ptr,
5578 WMITLV_TAG_ARRAY_STRUC,
5579 min_entries * sizeof(wmi_extscan_hotlist_entry));
5580 dest_hotlist = (wmi_extscan_hotlist_entry *)
5581 (buf_ptr + WMI_TLV_HDR_SIZE);
5582
5583 /* Populate bssid, channel info and rssi
5584 * for the bssid's that are sent as hotlists.
5585 */
5586 for (j = 0; j < min_entries; j++) {
5587 WMITLV_SET_HDR(dest_hotlist,
5588 WMITLV_TAG_STRUC_wmi_extscan_bucket_cmd_fixed_param,
5589 WMITLV_GET_STRUCT_TLVLEN
5590 (wmi_extscan_hotlist_entry));
5591
5592 dest_hotlist->min_rssi = src_ap->low;
5593 WMI_CHAR_ARRAY_TO_MAC_ADDR(src_ap->bssid.bytes,
5594 &dest_hotlist->bssid);
5595
5596 WMA_LOGD("%s:channel:%d min_rssi %d",
5597 __func__, dest_hotlist->channel,
5598 dest_hotlist->min_rssi);
5599 WMA_LOGD
5600 ("%s: bssid mac_addr31to0: 0x%x, mac_addr47to32: 0x%x",
5601 __func__, dest_hotlist->bssid.mac_addr31to0,
5602 dest_hotlist->bssid.mac_addr47to32);
5603 dest_hotlist++;
5604 src_ap++;
5605 }
5606 buf_ptr += WMI_TLV_HDR_SIZE +
5607 (min_entries * sizeof(wmi_extscan_hotlist_entry));
5608
5609 if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
5610 WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID)) {
5611 WMA_LOGE("%s: failed to send command", __func__);
Nirav Shahcbc6d722016-03-01 16:24:53 +05305612 qdf_nbuf_free(buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305613 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005614 }
5615 index = index + min_entries;
5616 num_entries = numap - min_entries;
5617 len = cmd_len;
5618 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305619 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005620}
5621
5622/**
5623 * wma_extscan_start_hotlist_monitor() - start hotlist monitor
5624 * @wma: wma handle
5625 * @photlist: hotlist request params
5626 *
5627 * This function configures hotlist monitor in fw.
5628 *
5629 * Return: CDF status
5630 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305631QDF_STATUS wma_extscan_start_hotlist_monitor(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005632 tSirExtScanSetBssidHotListReqParams
5633 *photlist)
5634{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305635 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005636 int len;
5637
5638 if (!wma || !wma->wmi_handle) {
5639 WMA_LOGE("%s: WMA is closed, can not issue hotlist cmd",
5640 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305641 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005642 }
5643 /* Fill individual elements for hotlist request and
5644 * TLV for bssid entries
5645 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305646 qdf_status = wma_get_buf_extscan_hotlist_cmd(wma, photlist, &len);
5647 if (qdf_status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005648 WMA_LOGE("%s: Failed to get buffer"
5649 "for hotlist scan cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305650 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005651 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305652 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005653}
5654
5655/**
5656 * wma_extscan_stop_hotlist_monitor() - stop hotlist monitor
5657 * @wma: wma handle
5658 * @photlist_reset: hotlist reset params
5659 *
5660 * This function configures hotlist monitor to stop in fw.
5661 *
5662 * Return: CDF status
5663 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305664QDF_STATUS wma_extscan_stop_hotlist_monitor(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005665 tSirExtScanResetBssidHotlistReqParams
5666 *photlist_reset)
5667{
5668 wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *cmd;
5669 wmi_buf_t wmi_buf;
5670 uint32_t len;
5671 uint8_t *buf_ptr;
5672 int hotlist_entries = 0;
5673
5674 if (!wma || !wma->wmi_handle) {
5675 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305676 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005677 }
5678 if (!photlist_reset) {
5679 WMA_LOGE("%s: Invalid reset hotlist buffer", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305680 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005681 }
5682 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
5683 WMI_SERVICE_EXTSCAN)) {
5684 WMA_LOGE("%s: extscan not enabled", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305685 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005686 }
5687 len = sizeof(*cmd);
5688
5689 /* reset bssid hotlist with tlv set to 0 */
5690 len += WMI_TLV_HDR_SIZE;
5691 len += hotlist_entries * sizeof(wmi_extscan_hotlist_entry);
5692
5693 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
5694 if (!wmi_buf) {
5695 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305696 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005697 }
5698
5699 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
5700 cmd = (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *)
5701 buf_ptr;
5702 WMITLV_SET_HDR(&cmd->tlv_header,
5703 WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_monitor_cmd_fixed_param,
5704 WMITLV_GET_STRUCT_TLVLEN
5705 (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param));
5706
5707 cmd->request_id = photlist_reset->requestId;
5708 cmd->vdev_id = photlist_reset->sessionId;
5709 cmd->mode = 0;
5710
5711 buf_ptr += sizeof(*cmd);
5712 WMITLV_SET_HDR(buf_ptr,
5713 WMITLV_TAG_ARRAY_STRUC,
5714 hotlist_entries * sizeof(wmi_extscan_hotlist_entry));
5715 buf_ptr += WMI_TLV_HDR_SIZE +
5716 (hotlist_entries * sizeof(wmi_extscan_hotlist_entry));
5717
5718 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
5719 WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID)) {
5720 WMA_LOGE("%s: failed to command", __func__);
Nirav Shahcbc6d722016-03-01 16:24:53 +05305721 qdf_nbuf_free(wmi_buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305722 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005723 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305724 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005725}
5726
5727/**
5728 * wma_get_buf_extscan_change_monitor_cmd() - fill change monitor request
5729 * @wma: wma handle
5730 * @psigchange: change monitor request params
5731 * @buf: wmi buffer
5732 * @buf_len: buffer length
5733 *
5734 * This function fills elements of change monitor request buffer.
5735 *
5736 * Return: CDF status
5737 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305738QDF_STATUS wma_get_buf_extscan_change_monitor_cmd(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005739 tSirExtScanSetSigChangeReqParams
5740 *psigchange, wmi_buf_t *buf,
5741 int *buf_len)
5742{
5743 wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *cmd;
5744 wmi_extscan_wlan_change_bssid_param *dest_chglist;
5745 uint8_t *buf_ptr;
5746 int j;
5747 int len = sizeof(*cmd);
5748 int numap = psigchange->numAp;
5749 tSirAPThresholdParam *src_ap = psigchange->ap;
5750
5751 if (!numap) {
5752 WMA_LOGE("%s: Invalid number of bssid's", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305753 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005754 }
5755 len += WMI_TLV_HDR_SIZE;
5756 len += numap * sizeof(wmi_extscan_wlan_change_bssid_param);
5757
5758 *buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5759 if (!*buf) {
5760 WMA_LOGP("%s: failed to allocate memory for change monitor cmd",
5761 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305762 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005763 }
5764 buf_ptr = (uint8_t *) wmi_buf_data(*buf);
5765 cmd =
5766 (wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *)
5767 buf_ptr;
5768 WMITLV_SET_HDR(&cmd->tlv_header,
5769 WMITLV_TAG_STRUC_wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param,
5770 WMITLV_GET_STRUCT_TLVLEN
5771 (wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param));
5772
5773 cmd->request_id = psigchange->requestId;
5774 cmd->vdev_id = psigchange->sessionId;
5775 cmd->total_entries = numap;
5776 cmd->mode = 1;
5777 cmd->num_entries_in_page = numap;
5778 cmd->lost_ap_scan_count = psigchange->lostApSampleSize;
5779 cmd->max_rssi_samples = psigchange->rssiSampleSize;
5780 cmd->rssi_averaging_samples = psigchange->rssiSampleSize;
5781 cmd->max_out_of_range_count = psigchange->minBreaching;
5782
5783 buf_ptr += sizeof(*cmd);
5784 WMITLV_SET_HDR(buf_ptr,
5785 WMITLV_TAG_ARRAY_STRUC,
5786 numap * sizeof(wmi_extscan_wlan_change_bssid_param));
5787 dest_chglist = (wmi_extscan_wlan_change_bssid_param *)
5788 (buf_ptr + WMI_TLV_HDR_SIZE);
5789
5790 for (j = 0; j < numap; j++) {
5791 WMITLV_SET_HDR(dest_chglist,
5792 WMITLV_TAG_STRUC_wmi_extscan_bucket_cmd_fixed_param,
5793 WMITLV_GET_STRUCT_TLVLEN
5794 (wmi_extscan_wlan_change_bssid_param));
5795
5796 dest_chglist->lower_rssi_limit = src_ap->low;
5797 dest_chglist->upper_rssi_limit = src_ap->high;
5798 WMI_CHAR_ARRAY_TO_MAC_ADDR(src_ap->bssid.bytes,
5799 &dest_chglist->bssid);
5800
5801 WMA_LOGD("%s: min_rssi %d", __func__,
5802 dest_chglist->lower_rssi_limit);
5803 dest_chglist++;
5804 src_ap++;
5805 }
5806 buf_ptr += WMI_TLV_HDR_SIZE +
5807 (numap * sizeof(wmi_extscan_wlan_change_bssid_param));
5808 *buf_len = len;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305809 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005810}
5811
5812/**
5813 * wma_extscan_start_change_monitor() - send start change monitor cmd
5814 * @wma: wma handle
5815 * @psigchange: change monitor request params
5816 *
5817 * This function sends start change monitor request to fw.
5818 *
5819 * Return: CDF status
5820 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305821QDF_STATUS wma_extscan_start_change_monitor(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005822 tSirExtScanSetSigChangeReqParams *
5823 psigchange)
5824{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305825 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005826 wmi_buf_t buf;
5827 int len;
5828
5829 if (!wma || !wma->wmi_handle) {
5830 WMA_LOGE("%s: WMA is closed,can not issue extscan cmd",
5831 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305832 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005833 }
5834 /* Fill individual elements of change monitor and
5835 * TLV info ... */
5836
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305837 qdf_status = wma_get_buf_extscan_change_monitor_cmd(wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005838 psigchange, &buf,
5839 &len);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305840 if (qdf_status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005841 WMA_LOGE("%s: Failed to get buffer for change monitor cmd",
5842 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305843 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005844 }
5845 if (!buf) {
5846 WMA_LOGE("%s: Failed to get buffer", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305847 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005848 }
5849 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5850 WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID)) {
5851 WMA_LOGE("%s: failed to send command", __func__);
Nirav Shahcbc6d722016-03-01 16:24:53 +05305852 qdf_nbuf_free(buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305853 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005854 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305855 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005856}
5857
5858/**
5859 * wma_extscan_stop_change_monitor() - send stop change monitor cmd
5860 * @wma: wma handle
5861 * @pResetReq: Reset change request params
5862 *
5863 * This function sends stop change monitor request to fw.
5864 *
5865 * Return: CDF status
5866 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305867QDF_STATUS wma_extscan_stop_change_monitor(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005868 tSirExtScanResetSignificantChangeReqParams
5869 *pResetReq)
5870{
5871 wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *cmd;
5872 wmi_buf_t wmi_buf;
5873 uint32_t len;
5874 uint8_t *buf_ptr;
5875 int change_list = 0;
5876
5877 if (!wma || !wma->wmi_handle) {
5878 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305879 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005880 }
5881 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
5882 WMI_SERVICE_EXTSCAN)) {
5883 WMA_LOGE("%s: ext scan not enabled", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305884 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005885 }
5886 len = sizeof(*cmd);
5887
5888 /* reset significant change tlv is set to 0 */
5889 len += WMI_TLV_HDR_SIZE;
5890 len += change_list * sizeof(wmi_extscan_wlan_change_bssid_param);
5891 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
5892 if (!wmi_buf) {
5893 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305894 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005895 }
5896 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
5897
5898 cmd = (wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *)
5899 buf_ptr;
5900 WMITLV_SET_HDR(&cmd->tlv_header,
5901 WMITLV_TAG_STRUC_wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param,
5902 WMITLV_GET_STRUCT_TLVLEN
5903 (wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param));
5904
5905 cmd->request_id = pResetReq->requestId;
5906 cmd->vdev_id = pResetReq->sessionId;
5907 cmd->mode = 0;
5908
5909 buf_ptr += sizeof(*cmd);
5910 WMITLV_SET_HDR(buf_ptr,
5911 WMITLV_TAG_ARRAY_STRUC,
5912 change_list *
5913 sizeof(wmi_extscan_wlan_change_bssid_param));
5914 buf_ptr += WMI_TLV_HDR_SIZE + (change_list *
5915 sizeof
5916 (wmi_extscan_wlan_change_bssid_param));
5917
5918 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
5919 WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID)) {
5920 WMA_LOGE("%s: failed to command", __func__);
Nirav Shahcbc6d722016-03-01 16:24:53 +05305921 qdf_nbuf_free(wmi_buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305922 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005923 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305924 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005925}
5926
5927/**
5928 * wma_extscan_get_cached_results() - extscan get cached results
5929 * @wma: wma handle
5930 * @pcached_results: cached results parameters
5931 *
5932 * This function send request to fw to get cached results.
5933 *
5934 * Return: CDF status
5935 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305936QDF_STATUS wma_extscan_get_cached_results(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005937 tSirExtScanGetCachedResultsReqParams *
5938 pcached_results)
5939{
5940 wmi_extscan_get_cached_results_cmd_fixed_param *cmd;
5941 wmi_buf_t wmi_buf;
5942 uint32_t len;
5943 uint8_t *buf_ptr;
5944
5945 if (!wma || !wma->wmi_handle) {
5946 WMA_LOGE("%s: WMA is closed, cannot issue cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305947 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005948 }
5949 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
5950 WMI_SERVICE_EXTSCAN)) {
5951 WMA_LOGE("%s: extscan not enabled", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305952 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005953 }
5954 len = sizeof(*cmd);
5955 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
5956 if (!wmi_buf) {
5957 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305958 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005959 }
5960 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
5961
5962 cmd = (wmi_extscan_get_cached_results_cmd_fixed_param *) buf_ptr;
5963 WMITLV_SET_HDR(&cmd->tlv_header,
5964 WMITLV_TAG_STRUC_wmi_extscan_get_cached_results_cmd_fixed_param,
5965 WMITLV_GET_STRUCT_TLVLEN
5966 (wmi_extscan_get_cached_results_cmd_fixed_param));
5967
5968 cmd->request_id = pcached_results->requestId;
5969 cmd->vdev_id = pcached_results->sessionId;
5970 cmd->control_flags = pcached_results->flush;
5971
5972 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
5973 WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID)) {
5974 WMA_LOGE("%s: failed to command", __func__);
Nirav Shahcbc6d722016-03-01 16:24:53 +05305975 qdf_nbuf_free(wmi_buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305976 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005977 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305978 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005979}
5980
5981/**
5982 * wma_extscan_get_capabilities() - extscan get capabilities
5983 * @wma: wma handle
5984 * @pgetcapab: get capabilities params
5985 *
5986 * This function send request to fw to get extscan capabilities.
5987 *
5988 * Return: CDF status
5989 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305990QDF_STATUS wma_extscan_get_capabilities(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005991 tSirGetExtScanCapabilitiesReqParams *
5992 pgetcapab)
5993{
5994 wmi_extscan_get_capabilities_cmd_fixed_param *cmd;
5995 wmi_buf_t wmi_buf;
5996 uint32_t len;
5997 uint8_t *buf_ptr;
5998
5999 if (!wma || !wma->wmi_handle) {
6000 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306001 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006002 }
6003 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
6004 WMI_SERVICE_EXTSCAN)) {
6005 WMA_LOGE("%s: extscan not enabled", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306006 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006007 }
6008 len = sizeof(*cmd);
6009 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
6010 if (!wmi_buf) {
6011 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306012 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006013 }
6014 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
6015
6016 cmd = (wmi_extscan_get_capabilities_cmd_fixed_param *) buf_ptr;
6017 WMITLV_SET_HDR(&cmd->tlv_header,
6018 WMITLV_TAG_STRUC_wmi_extscan_get_capabilities_cmd_fixed_param,
6019 WMITLV_GET_STRUCT_TLVLEN
6020 (wmi_extscan_get_capabilities_cmd_fixed_param));
6021
6022 cmd->request_id = pgetcapab->requestId;
6023
6024 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
6025 WMI_EXTSCAN_GET_CAPABILITIES_CMDID)) {
6026 WMA_LOGE("%s: failed to command", __func__);
Nirav Shahcbc6d722016-03-01 16:24:53 +05306027 qdf_nbuf_free(wmi_buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306028 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006029 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306030 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006031}
6032
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306033QDF_STATUS wma_ipa_offload_enable_disable(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006034 struct sir_ipa_offload_enable_disable *ipa_offload)
6035{
6036 wmi_ipa_offload_enable_disable_cmd_fixed_param *cmd;
6037 wmi_buf_t wmi_buf;
6038 uint32_t len;
6039 u_int8_t *buf_ptr;
6040 ol_txrx_vdev_handle vdev;
6041 struct txrx_pdev_cfg_t *cfg;
6042 int32_t intra_bss_fwd = 0;
6043
6044 if (!wma || !wma->wmi_handle) {
6045 WMA_LOGE("%s: WMA is closed, can not issue cmd",
6046 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306047 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006048 }
6049
6050 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
6051 ((ipa_offload->offload_type == AP_RX_DATA_OFFLOAD) ?
6052 WMI_SERVICE_HSOFFLOAD :
6053 WMI_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT))) {
6054 WMA_LOGE("%s: %s not supported", __func__,
6055 ((ipa_offload->offload_type == AP_RX_DATA_OFFLOAD) ?
6056 "WMI_SERVICE_HSOFFLOAD" :
6057 "WMI_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306058 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006059 }
6060
6061 if (ipa_offload->offload_type > STA_RX_DATA_OFFLOAD) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306062 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006063 }
6064
6065 len = sizeof(*cmd);
6066 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
6067 if (!wmi_buf) {
6068 WMA_LOGE("%s: wmi_buf_alloc failed (len=%d)", __func__, len);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306069 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006070 }
6071
6072 WMA_LOGE("%s: offload_type=%d, enable=%d", __func__,
6073 ipa_offload->offload_type, ipa_offload->enable);
6074
6075 buf_ptr = (u_int8_t *)wmi_buf_data(wmi_buf);
6076
6077 cmd = (wmi_ipa_offload_enable_disable_cmd_fixed_param *)buf_ptr;
6078 WMITLV_SET_HDR(&cmd->tlv_header,
6079 WMITLV_TAG_STRUCT_wmi_ipa_offload_enable_disable_cmd_fixed_param,
6080 WMITLV_GET_STRUCT_TLVLEN(
6081 wmi_ipa_offload_enable_disable_cmd_fixed_param));
6082
6083 cmd->offload_type = ipa_offload->offload_type;
6084 cmd->vdev_id = ipa_offload->vdev_id;
6085 cmd->enable = ipa_offload->enable;
6086
6087 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
6088 WMI_IPA_OFFLOAD_ENABLE_DISABLE_CMDID)) {
6089 WMA_LOGE("%s: failed to command", __func__);
6090 wmi_buf_free(wmi_buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306091 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006092 }
6093
6094 /*
6095 * Check if VDEV is already deleted. If deleted, don't
6096 * send INTRA BSS FWD WMI command
6097 */
6098 vdev = wma_find_vdev_by_id(wma, ipa_offload->vdev_id);
6099 if (!vdev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306100 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006101
6102 /* Disable Intra-BSS FWD offload when gDisableIntraBssFwd=1 in INI */
6103 cfg = (struct txrx_pdev_cfg_t *)vdev->pdev->ctrl_pdev;
6104 if (!ipa_offload->enable || cfg->rx_fwd_disabled) {
6105 WMA_LOGE("%s: ipa_offload->enable=%d, rx_fwd_disabled=%d",
6106 __func__,
6107 ipa_offload->enable, cfg->rx_fwd_disabled);
6108 intra_bss_fwd = 1;
6109 }
6110
6111 /* Disable/enable WMI_VDEV_PARAM_INTRA_BSS_FWD */
6112 if (wmi_unified_vdev_set_param_send(wma->wmi_handle,
6113 ipa_offload->vdev_id, WMI_VDEV_PARAM_INTRA_BSS_FWD,
6114 intra_bss_fwd)) {
6115 WMA_LOGE("Failed to disable WMI_VDEV_PARAM_INTRA_BSS_FWD");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306116 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006117 }
6118
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306119 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006120}
6121
6122/** wma_set_epno_network_list() - set epno network list
6123 * @wma: WMA handle
6124 * @req: epno config params request structure
6125 *
6126 * This function reads the incoming epno config request structure
6127 * and constructs the WMI message to the firmware.
6128 *
6129 * Returns: 0 on success, error number otherwise
6130 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306131QDF_STATUS wma_set_epno_network_list(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006132 struct wifi_epno_params *req)
6133{
6134 wmi_nlo_config_cmd_fixed_param *cmd;
6135 nlo_configured_parameters *nlo_list;
6136 u_int8_t i, *buf_ptr;
6137 wmi_buf_t buf;
6138 uint32_t len;
6139 int ret;
6140
6141 WMA_LOGD("wma_set_epno_network_list");
6142
6143 if (!wma || !wma->wmi_handle) {
6144 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306145 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006146 }
6147 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
6148 WMI_SERVICE_EXTSCAN)) {
6149 WMA_LOGE("%s: extscan not enabled", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306150 return QDF_STATUS_E_NOSUPPORT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006151 }
6152
6153 /* TLV place holder for array of structures
6154 * nlo_configured_parameters(nlo_list) */
6155 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
6156 len += sizeof(nlo_configured_parameters) *
Anurag Chouhan6d760662016-02-20 16:05:43 +05306157 QDF_MIN(req->num_networks, WMI_NLO_MAX_SSIDS);
Varun Reddy Yeturub43fda12015-09-10 18:16:21 -07006158 len += WMI_TLV_HDR_SIZE; /* TLV for channel_list */
6159 len += WMI_TLV_HDR_SIZE; /* TLV for channel prediction cfg*/
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006160
6161 buf = wmi_buf_alloc(wma->wmi_handle, len);
6162 if (!buf) {
6163 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306164 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006165 }
6166
6167 cmd = (wmi_nlo_config_cmd_fixed_param *) wmi_buf_data(buf);
6168
6169 buf_ptr = (u_int8_t *) cmd;
6170 WMITLV_SET_HDR(&cmd->tlv_header,
6171 WMITLV_TAG_STRUC_wmi_nlo_config_cmd_fixed_param,
6172 WMITLV_GET_STRUCT_TLVLEN(
6173 wmi_nlo_config_cmd_fixed_param));
6174 cmd->vdev_id = req->session_id;
6175 cmd->flags = WMI_NLO_CONFIG_ENLO;
6176
6177 buf_ptr += sizeof(wmi_nlo_config_cmd_fixed_param);
6178
Anurag Chouhan6d760662016-02-20 16:05:43 +05306179 cmd->no_of_ssids = QDF_MIN(req->num_networks, WMI_NLO_MAX_SSIDS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006180 WMA_LOGD("SSID count: %d", cmd->no_of_ssids);
6181 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
6182 cmd->no_of_ssids * sizeof(nlo_configured_parameters));
6183 buf_ptr += WMI_TLV_HDR_SIZE;
6184
6185 nlo_list = (nlo_configured_parameters *) buf_ptr;
6186 for (i = 0; i < cmd->no_of_ssids; i++) {
6187 WMITLV_SET_HDR(&nlo_list[i].tlv_header,
6188 WMITLV_TAG_ARRAY_BYTE,
6189 WMITLV_GET_STRUCT_TLVLEN(nlo_configured_parameters));
6190 /* Copy ssid and it's length */
6191 nlo_list[i].ssid.valid = true;
6192 nlo_list[i].ssid.ssid.ssid_len = req->networks[i].ssid.length;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306193 qdf_mem_copy(nlo_list[i].ssid.ssid.ssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006194 req->networks[i].ssid.ssId,
6195 nlo_list[i].ssid.ssid.ssid_len);
6196 WMA_LOGD("index: %d ssid: %.*s len: %d", i,
6197 nlo_list[i].ssid.ssid.ssid_len,
6198 (char *) nlo_list[i].ssid.ssid.ssid,
6199 nlo_list[i].ssid.ssid.ssid_len);
6200
6201 /* Copy rssi threshold */
6202 nlo_list[i].rssi_cond.valid = true;
6203 nlo_list[i].rssi_cond.rssi =
6204 req->networks[i].rssi_threshold;
6205 WMA_LOGD("RSSI threshold : %d dBm",
6206 nlo_list[i].rssi_cond.rssi);
6207
6208 /* Copy pno flags */
6209 nlo_list[i].bcast_nw_type.valid = true;
6210 nlo_list[i].bcast_nw_type.bcast_nw_type =
6211 req->networks[i].flags;
6212 WMA_LOGD("PNO flags (%u)",
6213 nlo_list[i].bcast_nw_type.bcast_nw_type);
6214
6215 /* Copy auth bit field */
6216 nlo_list[i].auth_type.valid = true;
6217 nlo_list[i].auth_type.auth_type =
6218 req->networks[i].auth_bit_field;
6219 WMA_LOGD("Auth bit field (%u)",
6220 nlo_list[i].auth_type.auth_type);
6221 }
Varun Reddy Yeturub43fda12015-09-10 18:16:21 -07006222
6223 buf_ptr += cmd->no_of_ssids * sizeof(nlo_configured_parameters);
6224 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
6225 buf_ptr += WMI_TLV_HDR_SIZE;
6226
6227 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
6228 buf_ptr += WMI_TLV_HDR_SIZE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006229 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
6230 WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
6231 if (ret) {
6232 WMA_LOGE("%s: Failed to send nlo wmi cmd", __func__);
6233 wmi_buf_free(buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306234 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006235 }
6236
6237 WMA_LOGD("set ePNO list request sent successfully for vdev %d",
6238 req->session_id);
6239
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306240 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006241}
6242
6243/**
6244 * wma_set_passpoint_network_list() - set passpoint network list
6245 * @handle: WMA handle
6246 * @req: passpoint network request structure
6247 *
6248 * This function reads the incoming @req and fill in the destination
6249 * WMI structure and send down the passpoint configs down to the firmware
6250 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306251 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006252 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306253QDF_STATUS wma_set_passpoint_network_list(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006254 struct wifi_passpoint_req *req)
6255{
6256 wmi_passpoint_config_cmd_fixed_param *cmd;
6257 u_int8_t i, j, *bytes;
6258 wmi_buf_t buf;
6259 uint32_t len;
6260 int ret;
6261
6262 WMA_LOGD("wma_set_passpoint_network_list");
6263
6264 if (!wma || !wma->wmi_handle) {
6265 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306266 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006267 }
6268 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
6269 WMI_SERVICE_EXTSCAN)) {
6270 WMA_LOGE("%s: extscan not enabled", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306271 return QDF_STATUS_E_NOSUPPORT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006272 }
6273
6274 len = sizeof(*cmd);
6275 for (i = 0; i < req->num_networks; i++) {
6276 buf = wmi_buf_alloc(wma->wmi_handle, len);
6277 if (!buf) {
6278 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306279 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006280 }
6281
6282 cmd = (wmi_passpoint_config_cmd_fixed_param *)
6283 wmi_buf_data(buf);
6284
6285 WMITLV_SET_HDR(&cmd->tlv_header,
6286 WMITLV_TAG_STRUC_wmi_passpoint_config_cmd_fixed_param,
6287 WMITLV_GET_STRUCT_TLVLEN(
6288 wmi_passpoint_config_cmd_fixed_param));
6289 cmd->id = req->networks[i].id;
6290 WMA_LOGD("%s: network id: %u", __func__, cmd->id);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306291 qdf_mem_copy(cmd->realm, req->networks[i].realm,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006292 strlen(req->networks[i].realm) + 1);
6293 WMA_LOGD("%s: realm: %s", __func__, cmd->realm);
6294 for (j = 0; j < PASSPOINT_ROAMING_CONSORTIUM_ID_NUM; j++) {
6295 bytes = (uint8_t *) &req->networks[i].roaming_consortium_ids[j];
6296 WMA_LOGD("index: %d rcids: %02x %02x %02x %02x %02x %02x %02x %02x",
6297 j, bytes[0], bytes[1], bytes[2], bytes[3],
6298 bytes[4], bytes[5], bytes[6], bytes[7]);
6299
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306300 qdf_mem_copy(&cmd->roaming_consortium_ids[j],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006301 &req->networks[i].roaming_consortium_ids[j],
6302 PASSPOINT_ROAMING_CONSORTIUM_ID_LEN);
6303 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306304 qdf_mem_copy(cmd->plmn, req->networks[i].plmn,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006305 PASSPOINT_PLMN_ID_LEN);
6306 WMA_LOGD("%s: plmn: %02x:%02x:%02x", __func__,
6307 cmd->plmn[0], cmd->plmn[1], cmd->plmn[2]);
6308
6309 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
6310 WMI_PASSPOINT_LIST_CONFIG_CMDID);
6311 if (ret) {
6312 WMA_LOGE("%s: Failed to send set passpoint network list wmi cmd",
6313 __func__);
6314 wmi_buf_free(buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306315 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006316 }
6317 }
6318
6319 WMA_LOGD("Set passpoint network list request is sent successfully for vdev %d",
6320 req->session_id);
6321
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306322 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006323}
6324
6325/**
6326 * wma_reset_passpoint_network_list() - reset passpoint network list
6327 * @handle: WMA handle
6328 * @req: passpoint network request structure
6329 *
6330 * This function sends down WMI command with network id set to wildcard id.
6331 * firmware shall clear all the config entries
6332 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306333 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006334 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306335QDF_STATUS wma_reset_passpoint_network_list(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006336 struct wifi_passpoint_req *req)
6337{
6338 wmi_passpoint_config_cmd_fixed_param *cmd;
6339 wmi_buf_t buf;
6340 uint32_t len;
6341 int ret;
6342
6343 WMA_LOGD("wma_reset_passpoint_network_list");
6344
6345 if (!wma || !wma->wmi_handle) {
6346 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306347 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006348 }
6349 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
6350 WMI_SERVICE_EXTSCAN)) {
6351 WMA_LOGE("%s: extscan not enabled", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306352 return QDF_STATUS_E_NOSUPPORT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006353 }
6354
6355 len = sizeof(*cmd);
6356 buf = wmi_buf_alloc(wma->wmi_handle, len);
6357 if (!buf) {
6358 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306359 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006360 }
6361
6362 cmd = (wmi_passpoint_config_cmd_fixed_param *) wmi_buf_data(buf);
6363
6364 WMITLV_SET_HDR(&cmd->tlv_header,
6365 WMITLV_TAG_STRUC_wmi_passpoint_config_cmd_fixed_param,
6366 WMITLV_GET_STRUCT_TLVLEN(
6367 wmi_passpoint_config_cmd_fixed_param));
6368 cmd->id = WMI_PASSPOINT_NETWORK_ID_WILDCARD;
6369
6370 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
6371 WMI_PASSPOINT_LIST_CONFIG_CMDID);
6372 if (ret) {
6373 WMA_LOGE("%s: Failed to send reset passpoint network list wmi cmd",
6374 __func__);
6375 wmi_buf_free(buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306376 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006377 }
6378
6379 WMA_LOGD("Reset passpoint network list request is sent successfully for vdev %d",
6380 req->session_id);
6381
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306382 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006383}
6384
6385/**
6386 * wma_set_ssid_hotlist() - Handle an SSID hotlist set request
6387 * @wma: WMA handle
6388 * @request: SSID hotlist set request from SME
6389 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306390 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006391 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306392QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006393wma_set_ssid_hotlist(tp_wma_handle wma,
6394 struct sir_set_ssid_hotlist_request *request)
6395{
6396 wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param *cmd;
6397 wmi_buf_t wmi_buf;
6398 uint32_t len;
6399 uint32_t array_size;
6400 uint8_t *buf_ptr;
6401
6402 if (!wma || !wma->wmi_handle) {
6403 WMA_LOGE("%s: WMA is closed, can not issue hotlist cmd",
6404 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306405 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006406 }
6407 if (!request) {
6408 WMA_LOGE("%s: Invalid request buffer", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306409 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006410 }
6411 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
6412 WMI_SERVICE_EXTSCAN)) {
6413 WMA_LOGE("%s: extscan not enabled",
6414 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306415 return QDF_STATUS_E_NOSUPPORT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006416 }
6417
6418 /* length of fixed portion */
6419 len = sizeof(*cmd);
6420
6421 /* length of variable portion */
6422 array_size =
6423 request->ssid_count * sizeof(wmi_extscan_hotlist_ssid_entry);
6424 len += WMI_TLV_HDR_SIZE + array_size;
6425
6426 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
6427 if (!wmi_buf) {
6428 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306429 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006430 }
6431
6432 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
6433 cmd = (wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param *)
6434 buf_ptr;
6435 WMITLV_SET_HDR
6436 (&cmd->tlv_header,
6437 WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param,
6438 WMITLV_GET_STRUCT_TLVLEN
6439 (wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param));
6440
6441 cmd->request_id = request->request_id;
6442 cmd->requestor_id = 0;
6443 cmd->vdev_id = request->session_id;
6444 cmd->table_id = 0;
6445 cmd->lost_ap_scan_count = request->lost_ssid_sample_size;
6446 cmd->total_entries = request->ssid_count;
6447 cmd->num_entries_in_page = request->ssid_count;
6448 cmd->first_entry_index = 0;
6449
6450 buf_ptr += sizeof(*cmd);
6451 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, array_size);
6452
6453 if (request->ssid_count) {
6454 wmi_extscan_hotlist_ssid_entry *entry;
6455 int i;
6456
6457 buf_ptr += WMI_TLV_HDR_SIZE;
6458 entry = (wmi_extscan_hotlist_ssid_entry *)buf_ptr;
6459 for (i = 0; i < request->ssid_count; i++) {
6460 WMITLV_SET_HDR
6461 (entry,
6462 WMITLV_TAG_ARRAY_STRUC,
6463 WMITLV_GET_STRUCT_TLVLEN
6464 (wmi_extscan_hotlist_ssid_entry));
6465 entry->ssid.ssid_len = request->ssids[i].ssid.length;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306466 qdf_mem_copy(entry->ssid.ssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006467 request->ssids[i].ssid.ssId,
6468 request->ssids[i].ssid.length);
6469 entry->band = request->ssids[i].band;
6470 entry->min_rssi = request->ssids[i].rssi_low;
6471 entry->max_rssi = request->ssids[i].rssi_high;
6472 entry++;
6473 }
6474 cmd->mode = WMI_EXTSCAN_MODE_START;
6475 } else {
6476 cmd->mode = WMI_EXTSCAN_MODE_STOP;
6477 }
6478
6479 if (wmi_unified_cmd_send
6480 (wma->wmi_handle, wmi_buf, len,
6481 WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID)) {
6482 WMA_LOGE("%s: failed to send command", __func__);
6483 wmi_buf_free(wmi_buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306484 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006485 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306486 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006487}
6488#endif
6489
6490/**
6491 * wma_scan_probe_setoui() - set scan probe OUI
6492 * @wma: wma handle
6493 * @psetoui: OUI parameters
6494 *
6495 * set scan probe OUI parameters in firmware
6496 *
6497 * Return: CDF status
6498 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306499QDF_STATUS wma_scan_probe_setoui(tp_wma_handle wma, tSirScanMacOui *psetoui)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006500{
6501 wmi_scan_prob_req_oui_cmd_fixed_param *cmd;
6502 wmi_buf_t wmi_buf;
6503 uint32_t len;
6504 uint8_t *buf_ptr;
6505 uint32_t *oui_buf;
6506
6507 if (!wma || !wma->wmi_handle) {
6508 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306509 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006510 }
6511 len = sizeof(*cmd);
6512 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
6513 if (!wmi_buf) {
6514 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306515 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006516 }
6517 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
6518 cmd = (wmi_scan_prob_req_oui_cmd_fixed_param *) buf_ptr;
6519 WMITLV_SET_HDR(&cmd->tlv_header,
6520 WMITLV_TAG_STRUC_wmi_scan_prob_req_oui_cmd_fixed_param,
6521 WMITLV_GET_STRUCT_TLVLEN
6522 (wmi_scan_prob_req_oui_cmd_fixed_param));
6523
6524 oui_buf = &cmd->prob_req_oui;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306525 qdf_mem_zero(oui_buf, sizeof(cmd->prob_req_oui));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006526 *oui_buf = psetoui->oui[0] << 16 | psetoui->oui[1] << 8
6527 | psetoui->oui[2];
6528 WMA_LOGD("%s: wma:oui received from hdd %08x", __func__,
6529 cmd->prob_req_oui);
6530
6531 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
6532 WMI_SCAN_PROB_REQ_OUI_CMDID)) {
6533 WMA_LOGE("%s: failed to send command", __func__);
Nirav Shahcbc6d722016-03-01 16:24:53 +05306534 qdf_nbuf_free(wmi_buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306535 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006536 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306537 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006538}
6539
6540/**
6541 * wma_scan_event_callback() - scan event callback
6542 * @handle: wma handle
6543 * @data: event data
6544 * @len: data length
6545 *
6546 * This function process scan event and provide indication
6547 * to upper layers.
6548 *
6549 * Return: 0 for success or error code.
6550 */
6551int wma_scan_event_callback(WMA_HANDLE handle, uint8_t *data,
6552 uint32_t len)
6553{
6554 tp_wma_handle wma_handle = (tp_wma_handle) handle;
6555 WMI_SCAN_EVENTID_param_tlvs *param_buf = NULL;
6556 wmi_scan_event_fixed_param *wmi_event = NULL;
6557 tSirScanOffloadEvent *scan_event;
6558 uint8_t vdev_id;
6559 uint32_t scan_id;
6560
6561 param_buf = (WMI_SCAN_EVENTID_param_tlvs *) data;
6562 wmi_event = param_buf->fixed_param;
6563 vdev_id = wmi_event->vdev_id;
6564 scan_id = wma_handle->interfaces[vdev_id].scan_info.scan_id;
6565
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306566 scan_event = (tSirScanOffloadEvent *) qdf_mem_malloc
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006567 (sizeof(tSirScanOffloadEvent));
6568 if (!scan_event) {
6569 WMA_LOGE("Memory allocation failed for tSirScanOffloadEvent");
6570 return -ENOMEM;
6571 }
6572
6573 scan_event->event = wmi_event->event;
6574
Deepak Dhamdhered97bfb32015-10-11 15:16:18 -07006575 WMA_LOGI("scan event %u, id 0x%x, requestor 0x%x, freq %u, reason %u",
6576 wmi_event->event, wmi_event->scan_id, wmi_event->requestor,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006577 wmi_event->channel_freq, wmi_event->reason);
6578
6579 scan_event->scanId = wmi_event->scan_id;
Deepak Dhamdhered97bfb32015-10-11 15:16:18 -07006580 scan_event->requestor = wmi_event->requestor;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006581 scan_event->chanFreq = wmi_event->channel_freq;
6582
6583 if (scan_event->scanId ==
6584 wma_handle->interfaces[vdev_id].p2p_scan_info.scan_id) {
6585 scan_event->p2pScanType = P2P_SCAN_TYPE_LISTEN;
6586 if (scan_event->event == SCAN_EVENT_COMPLETED)
6587 wma_reset_p2p_scan_info(wma_handle, vdev_id);
6588 }
6589 scan_event->sessionId = vdev_id;
6590
6591 if (wmi_event->reason == WMI_SCAN_REASON_COMPLETED ||
6592 wmi_event->reason == WMI_SCAN_REASON_TIMEDOUT)
6593 scan_event->reasonCode = eSIR_SME_SUCCESS;
6594 else
6595 scan_event->reasonCode = eSIR_SME_SCAN_FAILED;
6596
6597 switch (wmi_event->event) {
6598 case WMI_SCAN_EVENT_COMPLETED:
6599 case WMI_SCAN_EVENT_DEQUEUED:
6600 /*
6601 * return success always so that SME can pick whatever scan
6602 * results is available in scan cache(due to partial or
6603 * aborted scan)
6604 */
6605 scan_event->event = WMI_SCAN_EVENT_COMPLETED;
6606 scan_event->reasonCode = eSIR_SME_SUCCESS;
6607 break;
6608 case WMI_SCAN_EVENT_START_FAILED:
6609 scan_event->event = WMI_SCAN_EVENT_COMPLETED;
6610 scan_event->reasonCode = eSIR_SME_SCAN_FAILED;
6611 break;
6612 case WMI_SCAN_EVENT_PREEMPTED:
6613 WMA_LOGW("%s: Unhandled Scan Event WMI_SCAN_EVENT_PREEMPTED",
6614 __func__);
6615 break;
6616 case WMI_SCAN_EVENT_RESTARTED:
6617 WMA_LOGW("%s: Unhandled Scan Event WMI_SCAN_EVENT_RESTARTED",
6618 __func__);
6619 break;
6620 }
6621
Deepak Dhamdhered97bfb32015-10-11 15:16:18 -07006622 /* Stop scan completion timeout if event is WMI_SCAN_EVENT_COMPLETED */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006623 if (scan_event->event == (tSirScanEventType) WMI_SCAN_EVENT_COMPLETED) {
Deepak Dhamdhered97bfb32015-10-11 15:16:18 -07006624 WMA_LOGE("scan complete:scan_id 0x%x, requestor 0x%x, vdev %d",
6625 wmi_event->scan_id, wmi_event->requestor, vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006626 }
6627
6628 wma_send_msg(wma_handle, WMA_RX_SCAN_EVENT, (void *)scan_event, 0);
6629 return 0;
6630}
6631
6632
6633/**
6634 * wma_roam_better_ap_handler() - better ap event handler
6635 * @wma: wma handle
6636 * @vdev_id: vdev id
6637 *
6638 * Handler for WMI_ROAM_REASON_BETTER_AP event from roam firmware in Rome.
6639 * This event means roam algorithm in Rome has found a better matching
6640 * candidate AP. The indication is sent to SME.
6641 *
6642 * Return: none
6643 */
6644void wma_roam_better_ap_handler(tp_wma_handle wma, uint32_t vdev_id)
6645{
6646 cds_msg_t cds_msg;
6647 tSirSmeCandidateFoundInd *candidate_ind;
Deepak Dhamdhered97bfb32015-10-11 15:16:18 -07006648 struct scan_param *params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006649
Deepak Dhamdhered97bfb32015-10-11 15:16:18 -07006650 params = &wma->interfaces[vdev_id].scan_info;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006651 /* abort existing scans from GUI, but not roaming preauth scan */
Deepak Dhamdhered97bfb32015-10-11 15:16:18 -07006652 if (params->scan_id != 0 && params->chan_freq == 0 &&
6653 params->scan_requestor_id == USER_SCAN_REQUESTOR_ID) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006654 tAbortScanParams abortScan;
6655 abortScan.SessionId = vdev_id;
Deepak Dhamdhered97bfb32015-10-11 15:16:18 -07006656 abortScan.scan_id = params->scan_id;
6657 abortScan.scan_requestor_id = params->scan_requestor_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006658 wma_stop_scan(wma, &abortScan);
6659 }
6660
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306661 candidate_ind = qdf_mem_malloc(sizeof(tSirSmeCandidateFoundInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006662 if (!candidate_ind) {
6663 WMA_LOGE("%s: Alloc failed for tSirSmeCandidateFoundInd",
6664 __func__);
6665 return;
6666 }
6667
6668 candidate_ind->messageType = eWNI_SME_CANDIDATE_FOUND_IND;
6669 candidate_ind->sessionId = vdev_id;
6670 candidate_ind->length = sizeof(tSirSmeCandidateFoundInd);
6671
6672 cds_msg.type = eWNI_SME_CANDIDATE_FOUND_IND;
6673 cds_msg.bodyptr = candidate_ind;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306674 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006675 FL("posting candidate ind to SME"));
6676
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306677 if (QDF_STATUS_SUCCESS != cds_mq_post_message(CDS_MQ_ID_SME,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006678 (cds_msg_t *) &cds_msg)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306679 qdf_mem_free(candidate_ind);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306680 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006681 FL("Failed to post candidate ind to SME"));
6682 }
6683}
6684
6685/**
6686 * wma_roam_event_callback() - roam event callback
6687 * @handle: wma handle
6688 * @event_buf: event buffer
6689 * @len: buffer length
6690 *
6691 * Handler for all events from roam engine in firmware
6692 *
6693 * Return: 0 for success or error code
6694 */
6695int wma_roam_event_callback(WMA_HANDLE handle, uint8_t *event_buf,
6696 uint32_t len)
6697{
6698 tp_wma_handle wma_handle = (tp_wma_handle) handle;
6699 WMI_ROAM_EVENTID_param_tlvs *param_buf;
6700 wmi_roam_event_fixed_param *wmi_event;
6701
6702 param_buf = (WMI_ROAM_EVENTID_param_tlvs *) event_buf;
6703 if (!param_buf) {
6704 WMA_LOGE("Invalid roam event buffer");
6705 return -EINVAL;
6706 }
6707
6708 wmi_event = param_buf->fixed_param;
6709 WMA_LOGD("%s: Reason %x for vdevid %x, rssi %d",
6710 __func__, wmi_event->reason, wmi_event->vdev_id,
6711 wmi_event->rssi);
6712
6713 switch (wmi_event->reason) {
6714 case WMI_ROAM_REASON_BMISS:
6715 WMA_LOGD("Beacon Miss for vdevid %x", wmi_event->vdev_id);
6716 wma_beacon_miss_handler(wma_handle, wmi_event->vdev_id);
6717 break;
6718 case WMI_ROAM_REASON_BETTER_AP:
6719 WMA_LOGD("%s:Better AP found for vdevid %x, rssi %d", __func__,
6720 wmi_event->vdev_id, wmi_event->rssi);
6721 wma_handle->suitable_ap_hb_failure = false;
6722 wma_roam_better_ap_handler(wma_handle, wmi_event->vdev_id);
6723 break;
6724 case WMI_ROAM_REASON_SUITABLE_AP:
6725 wma_handle->suitable_ap_hb_failure = true;
6726 WMA_LOGD("%s:Bmiss scan AP found for vdevid %x, rssi %d",
6727 __func__, wmi_event->vdev_id, wmi_event->rssi);
6728 wma_roam_better_ap_handler(wma_handle, wmi_event->vdev_id);
6729 break;
6730#ifdef WLAN_FEATURE_ROAM_OFFLOAD
6731 case WMI_ROAM_REASON_HO_FAILED:
6732 WMA_LOGE("LFR3:Hand-Off Failed for vdevid %x",
6733 wmi_event->vdev_id);
6734 wma_roam_ho_fail_handler(wma_handle, wmi_event->vdev_id);
6735 break;
6736#endif
6737 default:
6738 WMA_LOGD("%s:Unhandled Roam Event %x for vdevid %x", __func__,
6739 wmi_event->reason, wmi_event->vdev_id);
6740 break;
6741 }
6742 return 0;
6743}
6744
6745
6746/**
6747 * wma_set_rssi_monitoring() - set rssi monitoring
6748 * @handle: WMA handle
6749 * @req: rssi monitoring request structure
6750 *
6751 * This function reads the incoming @req and fill in the destination
6752 * WMI structure and send down the rssi monitoring configs down to the firmware
6753 *
6754 * Return: 0 on success; error number otherwise
6755 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306756QDF_STATUS wma_set_rssi_monitoring(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006757 struct rssi_monitor_req *req)
6758{
6759 wmi_rssi_breach_monitor_config_fixed_param *cmd;
6760 wmi_buf_t buf;
6761 int ret, len = sizeof(*cmd);
6762
6763 buf = wmi_buf_alloc(wma->wmi_handle, len);
6764 if (!buf) {
6765 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306766 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006767 }
6768
6769 cmd = (wmi_rssi_breach_monitor_config_fixed_param *) wmi_buf_data(buf);
6770 WMITLV_SET_HDR(&cmd->tlv_header,
6771 WMITLV_TAG_STRUC_wmi_rssi_breach_monitor_config_fixed_param,
6772 WMITLV_GET_STRUCT_TLVLEN(
6773 wmi_rssi_breach_monitor_config_fixed_param));
6774
6775 cmd->vdev_id = req->session_id;
6776 cmd->request_id = req->request_id;
6777 cmd->lo_rssi_reenable_hysteresis = 0;
6778 cmd->hi_rssi_reenable_histeresis = 0;
6779 cmd->min_report_interval = 0;
6780 cmd->max_num_report = 1;
6781 if (req->control) {
6782 /* enable one threshold for each min/max */
6783 cmd->enabled_bitmap = 0x09;
6784 cmd->low_rssi_breach_threshold[0] = req->min_rssi;
6785 cmd->hi_rssi_breach_threshold[0] = req->max_rssi;
6786 } else {
6787 cmd->enabled_bitmap = 0;
6788 cmd->low_rssi_breach_threshold[0] = 0;
6789 cmd->hi_rssi_breach_threshold[0] = 0;
6790 }
6791
6792 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
6793 WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID);
6794 if (ret != EOK) {
6795 WMA_LOGE("Failed to send WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID");
6796 wmi_buf_free(buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306797 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006798 }
6799
6800 WMA_LOGI("Sent WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID to FW");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306801 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006802}
6803
6804/**
6805 * wma_get_scan_id() - Generates scan id
6806 * @scan_id: Scan id
6807 *
6808 * This function generates the scan id.
6809 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306810 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006811 */
6812
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306813QDF_STATUS wma_get_scan_id(uint32_t *scan_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006814{
Anurag Chouhan6d760662016-02-20 16:05:43 +05306815 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006816
6817 if (!scan_id) {
6818 WMA_LOGE("Scan_id is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306819 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006820 }
6821
6822 /* host need to cycle through the lower 12 bits to generate ids */
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05306823 *scan_id = qdf_atomic_inc_return(&wma->scan_id_counter) &
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006824 WMA_SCAN_ID_MASK;
6825 /*
6826 * Firmware expects the host scan request id appended
6827 * by PREFIX 0xA000
6828 */
6829 *scan_id = *scan_id | WMI_HOST_SCAN_REQ_ID_PREFIX;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306830 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006831}
6832
Ravi Joshi9e891ba2015-11-09 19:03:46 -08006833#ifdef FEATURE_LFR_SUBNET_DETECTION
6834/**
6835 * wma_set_gateway_params() - set gateway parameters
6836 * @wma: WMA handle
6837 * @req: gateway parameter update request structure
6838 *
6839 * This function reads the incoming @req and fill in the destination
6840 * WMI structure and sends down the gateway configs down to the firmware
6841 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306842 * Return: QDF_STATUS
Ravi Joshi9e891ba2015-11-09 19:03:46 -08006843 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306844QDF_STATUS wma_set_gateway_params(tp_wma_handle wma,
Ravi Joshi9e891ba2015-11-09 19:03:46 -08006845 struct gateway_param_update_req *req)
6846{
6847 wmi_roam_subnet_change_config_fixed_param *cmd;
6848 wmi_buf_t buf;
6849 int ret;
6850 int len = sizeof(*cmd);
6851
6852 buf = wmi_buf_alloc(wma->wmi_handle, len);
6853 if (!buf) {
6854 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306855 return QDF_STATUS_E_NOMEM;
Ravi Joshi9e891ba2015-11-09 19:03:46 -08006856 }
6857
6858 cmd = (wmi_roam_subnet_change_config_fixed_param *) wmi_buf_data(buf);
6859 WMITLV_SET_HDR(&cmd->tlv_header,
6860 WMITLV_TAG_STRUC_wmi_roam_subnet_change_config_fixed_param,
6861 WMITLV_GET_STRUCT_TLVLEN(
6862 wmi_roam_subnet_change_config_fixed_param));
6863
6864 cmd->vdev_id = req->session_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306865 qdf_mem_copy(&cmd->inet_gw_ip_v4_addr, req->ipv4_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306866 QDF_IPV4_ADDR_SIZE);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306867 qdf_mem_copy(&cmd->inet_gw_ip_v6_addr, req->ipv6_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306868 QDF_IPV6_ADDR_SIZE);
Ravi Joshi9e891ba2015-11-09 19:03:46 -08006869 WMI_CHAR_ARRAY_TO_MAC_ADDR(req->gw_mac_addr.bytes,
6870 &cmd->inet_gw_mac_addr);
6871 cmd->max_retries = req->max_retries;
6872 cmd->timeout = req->timeout;
6873 cmd->num_skip_subnet_change_detection_bssid_list = 0;
6874 cmd->flag = 0;
6875 if (req->ipv4_addr_type)
6876 WMI_SET_ROAM_SUBNET_CHANGE_FLAG_IP4_ENABLED(cmd->flag);
6877
6878 if (req->ipv6_addr_type)
6879 WMI_SET_ROAM_SUBNET_CHANGE_FLAG_IP6_ENABLED(cmd->flag);
6880
6881 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
6882 WMI_ROAM_SUBNET_CHANGE_CONFIG_CMDID);
6883 if (ret != EOK) {
6884 WMA_LOGE("Failed to send gw config parameter to fw, ret: %d",
6885 ret);
6886 wmi_buf_free(buf);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306887 return QDF_STATUS_E_FAILURE;
Ravi Joshi9e891ba2015-11-09 19:03:46 -08006888 }
6889
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306890 return QDF_STATUS_SUCCESS;
Ravi Joshi9e891ba2015-11-09 19:03:46 -08006891}
6892#endif /* FEATURE_LFR_SUBNET_DETECTION */
6893