blob: f5c2ff56ec697604f2fa4d6f26d2de866b2c6460 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved.
3 *
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
49#include "cdf_nbuf.h"
50#include "cdf_types.h"
51#include "ol_txrx_api.h"
52#include "cdf_memory.h"
53#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{
129 cdf_mem_zero((void *)&(wma_handle->interfaces[vdev_id].p2p_scan_info),
130 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 */
176CDF_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle,
177 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;
185 CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE;
186 uint8_t *buf_ptr;
187 uint32_t dwell_time;
188 uint8_t SSID_num;
189 int i;
190 int len = sizeof(*cmd);
191 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
192
193 if (!pMac) {
194 WMA_LOGP("%s: pMac is NULL!", __func__);
195 return CDF_STATUS_E_FAILURE;
196 }
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__);
219 return CDF_STATUS_E_FAILURE;
220 }
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;
244 cmd->scan_req_id = WMA_HOST_SCAN_REQUESTOR_ID_PREFIX |
245 WMA_DEFAULT_SCAN_REQUESTER_ID;
246
247 /* Set the scan events which the driver is intereseted to receive */
248 /* TODO: handle all the other flags also */
249 cmd->notify_scan_events = WMI_SCAN_EVENT_STARTED |
250 WMI_SCAN_EVENT_START_FAILED |
251 WMI_SCAN_EVENT_FOREIGN_CHANNEL |
252 WMI_SCAN_EVENT_COMPLETED |
253 WMI_SCAN_EVENT_DEQUEUED |
254 WMI_SCAN_EVENT_PREEMPTED | WMI_SCAN_EVENT_RESTARTED;
255
256 cmd->dwell_time_active = scan_req->maxChannelTime;
257
258 if (scan_req->scanType == eSIR_ACTIVE_SCAN) {
259 /* In Active scan case, the firmware has to do passive scan on DFS channels
260 * So the passive scan duration should be updated properly so that the duration
261 * will be sufficient enough to receive the beacon from AP */
262
263 if (wlan_cfg_get_int(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME,
264 &dwell_time) != eSIR_SUCCESS) {
265 WMA_LOGE("Failed to get passive max channel value"
266 "using default value");
267 dwell_time = WMA_DWELL_TIME_PASSIVE_DEFAULT;
268 }
269 cmd->dwell_time_passive = dwell_time;
270 } else
271 cmd->dwell_time_passive = scan_req->maxChannelTime;
272
273 WMA_LOGI("Scan Type %x, Active dwell time %u, Passive dwell time %u",
274 scan_req->scanType, cmd->dwell_time_active,
275 cmd->dwell_time_passive);
276
277 /* Ensure correct number of probes are sent on active channel */
278 cmd->repeat_probe_time =
279 cmd->dwell_time_active / WMA_SCAN_NPROBES_DEFAULT;
280
281 /* CSR sends only one value restTime for staying on home channel
282 * to continue data traffic. Rome fw has facility to monitor the traffic
283 * and move to next channel. Stay on the channel for at least half
284 * of the requested time and then leave if there is no traffic.
285 */
286 cmd->min_rest_time = scan_req->restTime / 2;
287 cmd->max_rest_time = scan_req->restTime;
288
289 /* Check for traffic at idle_time interval after min_rest_time.
290 * Default value is 25 ms to allow full use of max_rest_time
291 * when voice packets are running at 20 ms interval.
292 */
293 cmd->idle_time = WMA_SCAN_IDLE_TIME_DEFAULT;
294
295 /* Large timeout value for full scan cycle, 30 seconds */
296 cmd->max_scan_time = WMA_HW_DEF_SCAN_MAX_DURATION;
297
Sreelakshmi Konamki75deb332015-09-14 10:58:03 +0530298 /* add DS param IE in probe req frame */
299 cmd->scan_ctrl_flags |= WMI_SCAN_ADD_DS_IE_IN_PROBE_REQ;
300
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800301 /* do not add OFDM rates in 11B mode */
302 if (scan_req->dot11mode != WNI_CFG_DOT11_MODE_11B)
303 cmd->scan_ctrl_flags |= WMI_SCAN_ADD_OFDM_RATES;
304 else
305 WMA_LOGD("OFDM_RATES not included in 11B mode");
306
307 /* Do not combine multiple channels in a single burst. Come back
308 * to home channel for data traffic after every foreign channel.
309 * By default, prefer throughput performance over scan cycle time.
310 */
311 cmd->burst_duration = 0;
312
313 if (!scan_req->p2pScanType) {
314 WMA_LOGD("Normal Scan request");
315 cmd->scan_ctrl_flags |= WMI_SCAN_ADD_CCK_RATES;
316 if (!scan_req->numSsid)
317 cmd->scan_ctrl_flags |= WMI_SCAN_ADD_BCAST_PROBE_REQ;
318 if (scan_req->scanType == eSIR_PASSIVE_SCAN)
319 cmd->scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE;
320 cmd->scan_ctrl_flags |= WMI_SCAN_FILTER_PROBE_REQ;
321
322 /*
323 * Decide burst_duration and dwell_time_active based on
324 * what type of devices are active.
325 */
326 do {
327 if (wma_is_sap_active(wma_handle) &&
328 wma_is_p2p_go_active(wma_handle) &&
329 wma_is_sta_active(wma_handle)) {
330 if (scan_req->maxChannelTime <=
331 WMA_3PORT_CONC_SCAN_MAX_BURST_DURATION)
332 cmd->burst_duration =
333 scan_req->maxChannelTime;
334 else
335 cmd->burst_duration =
336 WMA_3PORT_CONC_SCAN_MAX_BURST_DURATION;
337 break;
338 }
339 if (wma_is_sap_active(wma_handle)) {
340 /* Background scan while SoftAP is sending beacons.
341 * Max duration of CTS2self is 32 ms, which limits
342 * the dwell time.
343 */
344 cmd->dwell_time_active =
345 CDF_MIN(scan_req->maxChannelTime,
346 (WMA_CTS_DURATION_MS_MAX -
347 WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME));
348 cmd->dwell_time_passive =
349 cmd->dwell_time_active;
350 cmd->burst_duration = 0;
351 break;
352 }
353 if (wma_handle->miracast_value &&
354 wma_is_mcc_24G(wma_handle)) {
355 cmd->max_rest_time =
356 pMac->f_sta_miracast_mcc_rest_time_val;
357 }
358 if (wma_is_p2p_go_active(wma_handle)) {
359 /* Background scan while GO is sending beacons.
360 * Every off-channel transition has overhead of 2 beacon
361 * intervals for NOA. Maximize number of channels in
362 * every transition by using burst scan.
363 */
364 if (wma_handle->miracast_value) {
365 /* When miracast is running, burst duration
366 * needs to be minimum to avoid any stutter
367 * or glitch in miracast during station scan
368 */
369 if (scan_req->maxChannelTime <=
370 WMA_GO_MIN_ACTIVE_SCAN_BURST_DURATION)
371 cmd->burst_duration =
372 scan_req->maxChannelTime;
373 else
374 cmd->burst_duration =
375 WMA_GO_MIN_ACTIVE_SCAN_BURST_DURATION;
376 } else {
377 /* If miracast is not running, accomodate max
378 * stations to make the scans faster
379 */
380 cmd->burst_duration =
381 WMA_BURST_SCAN_MAX_NUM_OFFCHANNELS *
382 scan_req->maxChannelTime;
383 if (cmd->burst_duration >
384 WMA_GO_MAX_ACTIVE_SCAN_BURST_DURATION) {
385 uint8_t channels =
386 WMA_P2P_SCAN_MAX_BURST_DURATION
387 / scan_req->maxChannelTime;
388 if (channels)
389 cmd->burst_duration =
390 channels *
391 scan_req->maxChannelTime;
392 else
393 cmd->burst_duration =
394 WMA_GO_MAX_ACTIVE_SCAN_BURST_DURATION;
395 }
396 }
397 break;
398 }
399 if (wma_is_sta_active(wma_handle) ||
400 wma_is_p2p_cli_active(wma_handle)) {
401 /* Typical background scan. Disable burst scan for now. */
402 cmd->burst_duration = 0;
403 break;
404 }
405 } while (0);
406
407 } else {
408 WMA_LOGD("P2P Scan");
409 switch (scan_req->p2pScanType) {
410 case P2P_SCAN_TYPE_LISTEN:
411 WMA_LOGD("P2P_SCAN_TYPE_LISTEN");
412 cmd->scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE;
413 cmd->notify_scan_events |=
414 WMI_SCAN_EVENT_FOREIGN_CHANNEL;
415 cmd->repeat_probe_time = 0;
416 break;
417 case P2P_SCAN_TYPE_SEARCH:
418 WMA_LOGD("P2P_SCAN_TYPE_SEARCH");
419 cmd->scan_ctrl_flags |= WMI_SCAN_FILTER_PROBE_REQ;
420 /* Default P2P burst duration of 120 ms will cover
421 * 3 channels with default max dwell time 40 ms.
422 * Cap limit will be set by
423 * WMA_P2P_SCAN_MAX_BURST_DURATION. Burst duration
424 * should be such that no channel is scanned less
425 * than the dwell time in normal scenarios.
426 */
427 if (scan_req->channelList.numChannels ==
428 P2P_SOCIAL_CHANNELS
429 && (!(wma_handle->miracast_value)))
430 cmd->repeat_probe_time =
431 scan_req->maxChannelTime / 5;
432 else
433 cmd->repeat_probe_time =
434 scan_req->maxChannelTime / 3;
435
436 cmd->burst_duration =
437 WMA_BURST_SCAN_MAX_NUM_OFFCHANNELS *
438 scan_req->maxChannelTime;
439 if (cmd->burst_duration >
440 WMA_P2P_SCAN_MAX_BURST_DURATION) {
441 uint8_t channels =
442 WMA_P2P_SCAN_MAX_BURST_DURATION /
443 scan_req->maxChannelTime;
444 if (channels)
445 cmd->burst_duration =
446 channels * scan_req->maxChannelTime;
447 else
448 cmd->burst_duration =
449 WMA_P2P_SCAN_MAX_BURST_DURATION;
450 }
451 break;
452 default:
453 WMA_LOGE("Invalid scan type");
454 goto error;
455 }
456 }
457
458 cmd->n_probes = (cmd->repeat_probe_time > 0) ?
459 cmd->dwell_time_active / cmd->repeat_probe_time : 0;
460
461 buf_ptr += sizeof(*cmd);
462 tmp_ptr = (uint32_t *) (buf_ptr + WMI_TLV_HDR_SIZE);
463
464 if (scan_req->channelList.numChannels) {
465 chan_list = (wmi_chan_list *) tmp_ptr;
466 cmd->num_chan = scan_req->channelList.numChannels;
467 for (i = 0; i < scan_req->channelList.numChannels; ++i) {
468 tmp_ptr[i] =
469 cds_chan_to_freq(scan_req->channelList.
470 channelNumber[i]);
471 }
472 }
473 WMITLV_SET_HDR(buf_ptr,
474 WMITLV_TAG_ARRAY_UINT32,
475 (cmd->num_chan * sizeof(uint32_t)));
476 buf_ptr += WMI_TLV_HDR_SIZE + (cmd->num_chan * sizeof(uint32_t));
477 if (scan_req->numSsid > SIR_SCAN_MAX_NUM_SSID) {
478 WMA_LOGE("Invalid value for numSsid");
479 goto error;
480 }
481 cmd->num_ssids = scan_req->numSsid;
482 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
483 (cmd->num_ssids * sizeof(wmi_ssid)));
484 if (scan_req->numSsid) {
485 ssid = (wmi_ssid *) (buf_ptr + WMI_TLV_HDR_SIZE);
486 for (i = 0; i < scan_req->numSsid; ++i) {
487 ssid->ssid_len = scan_req->ssId[i].length;
488 cdf_mem_copy(ssid->ssid, scan_req->ssId[i].ssId,
489 scan_req->ssId[i].length);
490 ssid++;
491 }
492 }
493 buf_ptr += WMI_TLV_HDR_SIZE + (cmd->num_ssids * sizeof(wmi_ssid));
494
495 cmd->num_bssid = 1;
496
497 if (!scan_req->p2pScanType) {
498 if (wma_is_sap_active(wma_handle)) {
499 SSID_num = cmd->num_ssids * cmd->num_bssid;
500 cmd->repeat_probe_time = probe_time_dwell_time_map[
501 CDF_MIN(SSID_num,
502 WMA_DWELL_TIME_PROBE_TIME_MAP_SIZE
503 - 1)].probe_time;
504 }
505 }
506
507 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
508 (cmd->num_bssid * sizeof(wmi_mac_addr)));
509 bssid = (wmi_mac_addr *) (buf_ptr + WMI_TLV_HDR_SIZE);
510 WMI_CHAR_ARRAY_TO_MAC_ADDR(scan_req->bssId, bssid);
511 buf_ptr += WMI_TLV_HDR_SIZE + (cmd->num_bssid * sizeof(wmi_mac_addr));
512
513 cmd->ie_len = scan_req->uIEFieldLen;
514 ie_len_with_pad = roundup(scan_req->uIEFieldLen, sizeof(uint32_t));
515 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_with_pad);
516 if (scan_req->uIEFieldLen) {
517 cdf_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE,
518 (uint8_t *) scan_req +
519 (scan_req->uIEFieldOffset), scan_req->uIEFieldLen);
520 }
521 buf_ptr += WMI_TLV_HDR_SIZE + ie_len_with_pad;
522
523 *buf_len = len;
524 return CDF_STATUS_SUCCESS;
525error:
526 cdf_mem_free(*buf);
527 *buf = NULL;
528 return cdf_status;
529}
530
531/**
532 * wma_get_buf_stop_scan_cmd() - Fill stop scan command
533 * @wma_handle: wma handle
534 * @buf: wmi buffer to be filled in
535 * @buf_len: buf length
536 * @abort_scan_req: abort scan request
537 *
538 * Fill wmi_stop_scan_cmd buffer.
539 *
540 * Return: CDF status
541 */
542CDF_STATUS wma_get_buf_stop_scan_cmd(tp_wma_handle wma_handle,
543 wmi_buf_t *buf,
544 int *buf_len,
545 tAbortScanParams *abort_scan_req)
546{
547 wmi_stop_scan_cmd_fixed_param *cmd;
548 CDF_STATUS cdf_status;
549 int len = sizeof(*cmd);
550
551 /* Allocate the memory */
552 *buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
553 if (!*buf) {
554 WMA_LOGP("%s: failed to allocate memory for stop scan cmd",
555 __func__);
556 cdf_status = CDF_STATUS_E_FAILURE;
557 goto error;
558 }
559
560 cmd = (wmi_stop_scan_cmd_fixed_param *) wmi_buf_data(*buf);
561 WMITLV_SET_HDR(&cmd->tlv_header,
562 WMITLV_TAG_STRUC_wmi_stop_scan_cmd_fixed_param,
563 WMITLV_GET_STRUCT_TLVLEN(wmi_stop_scan_cmd_fixed_param));
564 cmd->vdev_id = abort_scan_req->SessionId;
565 cmd->requestor = WMA_HOST_SCAN_REQUESTOR_ID_PREFIX |
566 WMA_DEFAULT_SCAN_REQUESTER_ID;
567 cmd->scan_id = abort_scan_req->scan_id;
568 /* stop the scan with the corresponding scan_id */
569 cmd->req_type = WMI_SCAN_STOP_ONE;
570
571 *buf_len = len;
572 cdf_status = CDF_STATUS_SUCCESS;
573error:
574 return cdf_status;
575
576}
577
578
579/**
580 * wma_start_scan() - start scan command
581 * @wma_handle: wma handle
582 * @scan_req: scan request params
583 * @msg_type: message time
584 *
585 * Send start scan command to fw.
586 *
587 * Return: CDF status
588 */
589CDF_STATUS wma_start_scan(tp_wma_handle wma_handle,
590 tSirScanOffloadReq *scan_req, uint16_t msg_type)
591{
592 uint32_t vdev_id, scan_id;
593 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
594 wmi_buf_t buf = NULL;
595 wmi_start_scan_cmd_fixed_param *cmd;
596 int status = 0;
597 int len;
598 tSirScanOffloadEvent *scan_event;
599
600 if (scan_req->sessionId > wma_handle->max_bssid) {
601 WMA_LOGE("%s: Invalid vdev_id %d, msg_type : 0x%x", __func__,
602 scan_req->sessionId, msg_type);
603 goto error;
604 }
605
606 /* Sanity check to find whether vdev id active or not */
607 if (msg_type != WMA_START_SCAN_OFFLOAD_REQ &&
608 !wma_handle->interfaces[scan_req->sessionId].handle) {
609 WMA_LOGA("vdev id [%d] is not active", scan_req->sessionId);
610 goto error;
611 }
612
613 /* Fill individual elements of wmi_start_scan_req and
614 * TLV for channel list, bssid, ssid etc ... */
615 cdf_status = wma_get_buf_start_scan_cmd(wma_handle, scan_req,
616 &buf, &len);
617 if (cdf_status != CDF_STATUS_SUCCESS) {
618 WMA_LOGE("Failed to get buffer for start scan cmd");
619 goto error;
620 }
621
622 if (NULL == buf) {
623 WMA_LOGE("Failed to get buffer for saving current scan info");
624 goto error;
625 }
626
627 /* Save current scan info */
628 cmd = (wmi_start_scan_cmd_fixed_param *) wmi_buf_data(buf);
629 if (msg_type == WMA_CHNL_SWITCH_REQ) {
630 /* Adjust parameters for channel switch scan */
631 cmd->min_rest_time = WMA_ROAM_PREAUTH_REST_TIME;
632 cmd->max_rest_time = WMA_ROAM_PREAUTH_REST_TIME;
633 cmd->max_scan_time = WMA_ROAM_PREAUTH_MAX_SCAN_TIME;
634 cmd->scan_priority = WMI_SCAN_PRIORITY_HIGH;
635 cmd->scan_id = scan_req->scan_id;
636 wma_handle->roam_preauth_scan_id = cmd->scan_id;
637 }
638 if (scan_req->p2pScanType == P2P_SCAN_TYPE_LISTEN)
639 wma_set_p2p_scan_info(wma_handle, cmd->scan_id,
640 cmd->vdev_id, P2P_SCAN_TYPE_LISTEN);
641 WMA_LOGE("scan_id 0x%x, vdev_id %d, p2pScanType %d, msg_type 0x%x",
642 cmd->scan_id, cmd->vdev_id, scan_req->p2pScanType, msg_type);
643 /*
644 * Cache vdev_id and scan_id because cmd is freed after calling
645 * wmi_unified_cmd_send cmd. WMI internally frees cmd buffer after
646 * getting TX complete from CE
647 */
648 vdev_id = cmd->vdev_id;
649 scan_id = cmd->scan_id;
650 WMA_LOGI("ActiveDwell %d, PassiveDwell %d, ScanFlags 0x%x NumChan %d",
651 cmd->dwell_time_active, cmd->dwell_time_passive,
652 cmd->scan_ctrl_flags, cmd->num_chan);
653
654 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
655 len, WMI_START_SCAN_CMDID);
656 /* Call the wmi api to request the scan */
657 if (status != EOK) {
658 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
659 cdf_status = CDF_STATUS_E_FAILURE;
660 goto error;
661 }
662
663 WMA_LOGI("WMA --> WMI_START_SCAN_CMDID");
664
665 return CDF_STATUS_SUCCESS;
666error:
667 /* Send completion event for only for start scan request */
668 if (msg_type == WMA_START_SCAN_OFFLOAD_REQ) {
669 scan_event =
670 (tSirScanOffloadEvent *)
671 cdf_mem_malloc(sizeof(tSirScanOffloadEvent));
672 if (!scan_event) {
673 WMA_LOGP("%s: Failed to allocate memory for scan rsp",
674 __func__);
675 return CDF_STATUS_E_NOMEM;
676 }
677 memset(scan_event, 0x00, sizeof(*scan_event));
678 scan_event->event = WMI_SCAN_EVENT_COMPLETED;
679 scan_event->reasonCode = eSIR_SME_SCAN_FAILED;
680 scan_event->sessionId = scan_req->sessionId;
681 scan_event->p2pScanType = scan_req->p2pScanType;
682 scan_event->scanId = scan_req->scan_id;
683 wma_send_msg(wma_handle, WMA_RX_SCAN_EVENT, (void *)scan_event,
684 0);
685 }
686 return cdf_status;
687}
688
689/**
690 * wma_stop_scan() - stop scan command
691 * @wma_handle: wma handle
692 * @abort_scan_req: abort scan params
693 *
694 * Send stop scan command to fw.
695 *
696 * Return: CDF status
697 */
698CDF_STATUS wma_stop_scan(tp_wma_handle wma_handle,
699 tAbortScanParams *abort_scan_req)
700{
701 CDF_STATUS cdf_status;
702 wmi_buf_t buf;
703 int status = 0;
704 int len;
705
706 cdf_status = wma_get_buf_stop_scan_cmd(wma_handle, &buf, &len,
707 abort_scan_req);
708 if (cdf_status != CDF_STATUS_SUCCESS) {
709 WMA_LOGE("Failed to get buffer for stop scan cmd");
710 goto error1;
711 }
712
713 if (NULL == buf) {
714 WMA_LOGE("Failed to get buffer for stop scan cmd");
715 cdf_status = CDF_STATUS_E_FAULT;
716 goto error1;
717 }
718
719 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
720 len, WMI_STOP_SCAN_CMDID);
721 /* Call the wmi api to request the scan */
722 if (status != EOK) {
723 WMA_LOGE("wmi_unified_cmd_send WMI_STOP_SCAN_CMDID returned Error %d",
724 status);
725 cdf_status = CDF_STATUS_E_FAILURE;
726 goto error;
727 }
728 WMA_LOGE("scan_id %x, vdev_id %x",
729 abort_scan_req->scan_id, abort_scan_req->SessionId);
730 WMA_LOGI("WMA --> WMI_STOP_SCAN_CMDID");
731
732 return CDF_STATUS_SUCCESS;
733error:
734 if (buf)
735 cdf_nbuf_free(buf);
736error1:
737 return cdf_status;
738}
739
740/**
741 * wma_update_channel_list() - update channel list
742 * @handle: wma handle
743 * @chan_list: channel list
744 *
745 * Function is used to update the support channel list in fw.
746 *
747 * Return: CDF status
748 */
749CDF_STATUS wma_update_channel_list(WMA_HANDLE handle,
750 tSirUpdateChanList *chan_list)
751{
752 tp_wma_handle wma_handle = (tp_wma_handle) handle;
753 wmi_buf_t buf;
754 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
755 wmi_scan_chan_list_cmd_fixed_param *cmd;
756 int status, i;
757 uint8_t *buf_ptr;
758 wmi_channel *chan_info;
759 uint16_t len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
760
761 len += sizeof(wmi_channel) * chan_list->numChan;
762 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
763 if (!buf) {
764 WMA_LOGE("Failed to allocate memory");
765 cdf_status = CDF_STATUS_E_NOMEM;
766 goto end;
767 }
768
769 buf_ptr = (uint8_t *) wmi_buf_data(buf);
770 cmd = (wmi_scan_chan_list_cmd_fixed_param *) buf_ptr;
771 WMITLV_SET_HDR(&cmd->tlv_header,
772 WMITLV_TAG_STRUC_wmi_scan_chan_list_cmd_fixed_param,
773 WMITLV_GET_STRUCT_TLVLEN
774 (wmi_scan_chan_list_cmd_fixed_param));
775
776 WMA_LOGD("no of channels = %d, len = %d", chan_list->numChan, len);
777
778 cmd->num_scan_chans = chan_list->numChan;
779 WMITLV_SET_HDR((buf_ptr + sizeof(wmi_scan_chan_list_cmd_fixed_param)),
780 WMITLV_TAG_ARRAY_STRUC,
781 sizeof(wmi_channel) * chan_list->numChan);
782 chan_info = (wmi_channel *) (buf_ptr + sizeof(*cmd) + WMI_TLV_HDR_SIZE);
783
784 for (i = 0; i < chan_list->numChan; ++i) {
785 WMITLV_SET_HDR(&chan_info->tlv_header,
786 WMITLV_TAG_STRUC_wmi_channel,
787 WMITLV_GET_STRUCT_TLVLEN(wmi_channel));
788 chan_info->mhz =
789 cds_chan_to_freq(chan_list->chanParam[i].chanId);
790 chan_info->band_center_freq1 = chan_info->mhz;
791 chan_info->band_center_freq2 = 0;
792
793 WMA_LOGD("chan[%d] = %u", i, chan_info->mhz);
794 if (chan_list->chanParam[i].dfsSet) {
795 WMI_SET_CHANNEL_FLAG(chan_info, WMI_CHAN_FLAG_PASSIVE);
796 WMA_LOGI("chan[%d] DFS[%d]\n",
797 chan_list->chanParam[i].chanId,
798 chan_list->chanParam[i].dfsSet);
799 }
800
801 if (chan_info->mhz < WMA_2_4_GHZ_MAX_FREQ)
802 WMI_SET_CHANNEL_MODE(chan_info, MODE_11G);
803 else
804 WMI_SET_CHANNEL_MODE(chan_info, MODE_11A);
805
806 if (chan_list->chanParam[i].half_rate)
807 WMI_SET_CHANNEL_FLAG(chan_info,
808 WMI_CHAN_FLAG_HALF_RATE);
809 else if (chan_list->chanParam[i].quarter_rate)
810 WMI_SET_CHANNEL_FLAG(chan_info,
811 WMI_CHAN_FLAG_QUARTER_RATE);
812
813 WMI_SET_CHANNEL_MAX_TX_POWER(chan_info,
814 chan_list->chanParam[i].pwr);
815
816 WMI_SET_CHANNEL_REG_POWER(chan_info,
817 chan_list->chanParam[i].pwr);
818 WMA_LOGD("Channel TX power[%d] = %u: %d", i, chan_info->mhz,
819 chan_list->chanParam[i].pwr);
820 /*TODO: Set WMI_SET_CHANNEL_MIN_POWER */
821 /*TODO: Set WMI_SET_CHANNEL_ANTENNA_MAX */
822 /*TODO: WMI_SET_CHANNEL_REG_CLASSID */
823 chan_info++;
824 }
825
826 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
827 WMI_SCAN_CHAN_LIST_CMDID);
828
829 if (status != EOK) {
830 cdf_status = CDF_STATUS_E_FAILURE;
831 WMA_LOGE("Failed to send WMI_SCAN_CHAN_LIST_CMDID");
832 wmi_buf_free(buf);
833 }
834end:
835 return cdf_status;
836}
837
838
839/**
840 * wma_roam_scan_offload_mode() - send roam scan mode request to fw
841 * @wma_handle: wma handle
842 * @scan_cmd_fp: start scan command ptr
843 * @roam_req: roam request param
844 * @mode: mode
845 * @vdev_id: vdev id
846 *
847 * send WMI_ROAM_SCAN_MODE TLV to firmware. It has a piggyback
848 * of WMI_ROAM_SCAN_MODE.
849 *
850 * Return: CDF status
851 */
852CDF_STATUS wma_roam_scan_offload_mode(tp_wma_handle wma_handle,
853 wmi_start_scan_cmd_fixed_param *
854 scan_cmd_fp,
855 tSirRoamOffloadScanReq *roam_req,
856 uint32_t mode, uint32_t vdev_id)
857{
858 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
859 wmi_buf_t buf = NULL;
860 int status = 0;
861 int len;
862 uint8_t *buf_ptr;
863 wmi_roam_scan_mode_fixed_param *roam_scan_mode_fp;
864#ifdef WLAN_FEATURE_ROAM_OFFLOAD
865 int auth_mode = WMI_AUTH_NONE;
866 wmi_roam_offload_tlv_param *roam_offload_params;
867 wmi_roam_11i_offload_tlv_param *roam_offload_11i;
868 wmi_roam_11r_offload_tlv_param *roam_offload_11r;
869 wmi_roam_ese_offload_tlv_param *roam_offload_ese;
870 if (roam_req)
871 auth_mode = e_csr_auth_type_to_rsn_authmode
872 (roam_req->ConnectedNetwork.authentication,
873 roam_req->ConnectedNetwork.encryption);
874 WMA_LOGD("%s : auth mode = %d", __func__, auth_mode);
875#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
876 /* Need to create a buf with roam_scan command at
877 * front and piggyback with scan command */
878 len = sizeof(wmi_roam_scan_mode_fixed_param) +
879#ifdef WLAN_FEATURE_ROAM_OFFLOAD
880 (2 * WMI_TLV_HDR_SIZE) +
881#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
882 sizeof(wmi_start_scan_cmd_fixed_param);
883#ifdef WLAN_FEATURE_ROAM_OFFLOAD
884 if (roam_req && roam_req->RoamOffloadEnabled) {
885 len += sizeof(wmi_roam_offload_tlv_param);
886 len += WMI_TLV_HDR_SIZE;
887 if ((auth_mode != WMI_AUTH_NONE) &&
888 ((auth_mode != WMI_AUTH_OPEN) ||
889 (auth_mode == WMI_AUTH_OPEN &&
890 roam_req->MDID.mdiePresent) || roam_req->IsESEAssoc)) {
891 len += WMI_TLV_HDR_SIZE;
892 if (roam_req->IsESEAssoc)
893 len += sizeof(wmi_roam_ese_offload_tlv_param);
894 else if (auth_mode == WMI_AUTH_FT_RSNA ||
895 auth_mode == WMI_AUTH_FT_RSNA_PSK ||
896 (auth_mode == WMI_AUTH_OPEN &&
897 roam_req->MDID.mdiePresent))
898 len += sizeof(wmi_roam_11r_offload_tlv_param);
899 else
900 len += sizeof(wmi_roam_11i_offload_tlv_param);
901 } else {
902 len += WMI_TLV_HDR_SIZE;
903 }
904 } else {
905 if (roam_req)
906 WMA_LOGD("%s : roam offload = %d",
907 __func__, roam_req->RoamOffloadEnabled);
908 else
909 WMA_LOGD("%s : roam_req is NULL", __func__);
910 len += (2 * WMI_TLV_HDR_SIZE);
911 }
912 if (roam_req && roam_req->RoamOffloadEnabled) {
913 mode = mode | WMI_ROAM_SCAN_MODE_ROAMOFFLOAD;
914 }
915#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
916 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
917 if (!buf) {
918 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
919 return CDF_STATUS_E_NOMEM;
920 }
921
922 buf_ptr = (uint8_t *) wmi_buf_data(buf);
923 roam_scan_mode_fp = (wmi_roam_scan_mode_fixed_param *) buf_ptr;
924 WMITLV_SET_HDR(&roam_scan_mode_fp->tlv_header,
925 WMITLV_TAG_STRUC_wmi_roam_scan_mode_fixed_param,
926 WMITLV_GET_STRUCT_TLVLEN
927 (wmi_roam_scan_mode_fixed_param));
928
929 roam_scan_mode_fp->roam_scan_mode = mode;
930 roam_scan_mode_fp->vdev_id = vdev_id;
931 /* Fill in scan parameters suitable for roaming scan */
932 buf_ptr += sizeof(wmi_roam_scan_mode_fixed_param);
933 cdf_mem_copy(buf_ptr, scan_cmd_fp,
934 sizeof(wmi_start_scan_cmd_fixed_param));
935 /* Ensure there is no additional IEs */
936 scan_cmd_fp->ie_len = 0;
937 WMITLV_SET_HDR(buf_ptr,
938 WMITLV_TAG_STRUC_wmi_start_scan_cmd_fixed_param,
939 WMITLV_GET_STRUCT_TLVLEN
940 (wmi_start_scan_cmd_fixed_param));
941#ifdef WLAN_FEATURE_ROAM_OFFLOAD
942 buf_ptr += sizeof(wmi_start_scan_cmd_fixed_param);
943 if (roam_req && roam_req->RoamOffloadEnabled) {
944 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
945 sizeof(wmi_roam_offload_tlv_param));
946 buf_ptr += WMI_TLV_HDR_SIZE;
947 roam_offload_params = (wmi_roam_offload_tlv_param *) buf_ptr;
948 WMITLV_SET_HDR(buf_ptr,
949 WMITLV_TAG_STRUC_wmi_roam_offload_tlv_param,
950 WMITLV_GET_STRUCT_TLVLEN
951 (wmi_roam_offload_tlv_param));
952 roam_offload_params->prefer_5g = roam_req->Prefer5GHz;
953 roam_offload_params->rssi_cat_gap = roam_req->RoamRssiCatGap;
954 roam_offload_params->select_5g_margin =
955 roam_req->Select5GHzMargin;
956 roam_offload_params->reassoc_failure_timeout =
957 roam_req->ReassocFailureTimeout;
958 /* Fill the capabilities */
959 wma_roam_scan_fill_self_caps(wma_handle, roam_offload_params,
960 roam_req);
961 buf_ptr += sizeof(wmi_roam_offload_tlv_param);
962 /* The TLV's are in the order of 11i, 11R, ESE. Hence,
963 * they are filled in the same order.Depending on the
964 * authentication type, the other mode TLV's are nullified
965 * and only headers are filled.*/
966 if ((auth_mode != WMI_AUTH_NONE) &&
967 ((auth_mode != WMI_AUTH_OPEN) ||
968 (auth_mode == WMI_AUTH_OPEN
969 && roam_req->MDID.mdiePresent) || roam_req->IsESEAssoc)) {
970 if (roam_req->IsESEAssoc) {
971 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
972 WMITLV_GET_STRUCT_TLVLEN(0));
973 buf_ptr += WMI_TLV_HDR_SIZE;
974 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
975 WMITLV_GET_STRUCT_TLVLEN(0));
976 buf_ptr += WMI_TLV_HDR_SIZE;
977 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
978 sizeof(wmi_roam_ese_offload_tlv_param));
979 buf_ptr += WMI_TLV_HDR_SIZE;
980 roam_offload_ese =
981 (wmi_roam_ese_offload_tlv_param *) buf_ptr;
982 cdf_mem_copy(roam_offload_ese->krk,
983 roam_req->KRK,
984 sizeof(roam_req->KRK));
985 cdf_mem_copy(roam_offload_ese->btk,
986 roam_req->BTK,
987 sizeof(roam_req->BTK));
988 WMITLV_SET_HDR(&roam_offload_ese->tlv_header,
989 WMITLV_TAG_STRUC_wmi_roam_ese_offload_tlv_param,
990 WMITLV_GET_STRUCT_TLVLEN
991 (wmi_roam_ese_offload_tlv_param));
992 buf_ptr +=
993 sizeof(wmi_roam_ese_offload_tlv_param);
994 } else if (auth_mode == WMI_AUTH_FT_RSNA
995 || auth_mode == WMI_AUTH_FT_RSNA_PSK
996 || (auth_mode == WMI_AUTH_OPEN
997 && roam_req->MDID.mdiePresent)) {
998 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
999 0);
1000 buf_ptr += WMI_TLV_HDR_SIZE;
1001 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1002 sizeof(wmi_roam_11r_offload_tlv_param));
1003 buf_ptr += WMI_TLV_HDR_SIZE;
1004 roam_offload_11r =
1005 (wmi_roam_11r_offload_tlv_param *) buf_ptr;
1006 roam_offload_11r->r0kh_id_len =
1007 roam_req->R0KH_ID_Length;
1008 cdf_mem_copy(roam_offload_11r->r0kh_id,
1009 roam_req->R0KH_ID,
1010 roam_offload_11r->r0kh_id_len);
1011 cdf_mem_copy(roam_offload_11r->psk_msk,
1012 roam_req->PSK_PMK,
1013 sizeof(roam_req->PSK_PMK));
1014 roam_offload_11r->psk_msk_len =
1015 roam_req->pmk_len;
1016 roam_offload_11r->mdie_present =
1017 roam_req->MDID.mdiePresent;
1018 roam_offload_11r->mdid =
1019 roam_req->MDID.mobilityDomain;
1020 if (auth_mode == WMI_AUTH_OPEN) {
1021 /* If FT-Open ensure pmk length
1022 and r0khid len are zero */
1023 roam_offload_11r->r0kh_id_len = 0;
1024 roam_offload_11r->psk_msk_len = 0;
1025 }
1026 WMITLV_SET_HDR(&roam_offload_11r->tlv_header,
1027 WMITLV_TAG_STRUC_wmi_roam_11r_offload_tlv_param,
1028 WMITLV_GET_STRUCT_TLVLEN
1029 (wmi_roam_11r_offload_tlv_param));
1030 buf_ptr +=
1031 sizeof(wmi_roam_11r_offload_tlv_param);
1032 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1033 WMITLV_GET_STRUCT_TLVLEN(0));
1034 buf_ptr += WMI_TLV_HDR_SIZE;
1035 } else {
1036 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1037 sizeof(wmi_roam_11i_offload_tlv_param));
1038 buf_ptr += WMI_TLV_HDR_SIZE;
1039 roam_offload_11i =
1040 (wmi_roam_11i_offload_tlv_param *) buf_ptr;
1041 if (roam_req->RoamKeyMgmtOffloadEnabled) {
1042 WMI_SET_ROAM_OFFLOAD_OKC_ENABLED
1043 (roam_offload_11i->flags);
1044 WMA_LOGE("LFR3:OKC Enabled");
1045 } else {
1046 WMI_SET_ROAM_OFFLOAD_OKC_DISABLED
1047 (roam_offload_11i->flags);
1048 WMA_LOGE("LFR3:OKC Disabled");
1049 }
1050
1051 cdf_mem_copy(roam_offload_11i->pmk,
1052 roam_req->PSK_PMK,
1053 sizeof(roam_req->PSK_PMK));
1054 roam_offload_11i->pmk_len = roam_req->pmk_len;
1055 WMITLV_SET_HDR(&roam_offload_11i->tlv_header,
1056 WMITLV_TAG_STRUC_wmi_roam_11i_offload_tlv_param,
1057 WMITLV_GET_STRUCT_TLVLEN
1058 (wmi_roam_11i_offload_tlv_param));
1059 buf_ptr +=
1060 sizeof(wmi_roam_11i_offload_tlv_param);
1061 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1062 0);
1063 buf_ptr += WMI_TLV_HDR_SIZE;
1064 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1065 0);
1066 buf_ptr += WMI_TLV_HDR_SIZE;
1067 }
1068 } else {
1069 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1070 WMITLV_GET_STRUCT_TLVLEN(0));
1071 buf_ptr += WMI_TLV_HDR_SIZE;
1072 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1073 WMITLV_GET_STRUCT_TLVLEN(0));
1074 buf_ptr += WMI_TLV_HDR_SIZE;
1075 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1076 WMITLV_GET_STRUCT_TLVLEN(0));
1077 }
1078 } else {
1079 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1080 WMITLV_GET_STRUCT_TLVLEN(0));
1081 buf_ptr += WMI_TLV_HDR_SIZE;
1082 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1083 WMITLV_GET_STRUCT_TLVLEN(0));
1084 buf_ptr += WMI_TLV_HDR_SIZE;
1085 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1086 WMITLV_GET_STRUCT_TLVLEN(0));
1087 buf_ptr += WMI_TLV_HDR_SIZE;
1088 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1089 WMITLV_GET_STRUCT_TLVLEN(0));
1090 }
1091#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
1092 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
1093 len, WMI_ROAM_SCAN_MODE);
1094 if (status != EOK) {
1095 WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_SCAN_MODE returned Error %d",
1096 status);
1097 cdf_status = CDF_STATUS_E_FAILURE;
1098 goto error;
1099 }
1100
1101 WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_MODE", __func__);
1102 return CDF_STATUS_SUCCESS;
1103error:
1104 wmi_buf_free(buf);
1105
1106 return cdf_status;
1107}
1108
1109/**
1110 * wma_roam_scan_offload_rssi_threshold() - set scan offload rssi threashold
1111 * @wma_handle: wma handle
1112 * @roam_req: Roaming request buffer
1113 *
1114 * Send WMI_ROAM_SCAN_RSSI_THRESHOLD TLV to firmware
1115 *
1116 * Return: CDF status
1117 */
1118CDF_STATUS wma_roam_scan_offload_rssi_thresh(tp_wma_handle wma_handle,
1119 tSirRoamOffloadScanReq *roam_req)
1120{
1121 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
1122 wmi_buf_t buf = NULL;
1123 int status = 0;
1124 int len, rssi_thresh, rssi_thresh_diff;
1125 uint8_t *buf_ptr;
1126 wmi_roam_scan_rssi_threshold_fixed_param *rssi_threshold_fp;
1127 wmi_roam_scan_extended_threshold_param *ext_thresholds = NULL;
Varun Reddy Yeturu05186292015-09-28 17:12:33 -07001128 wmi_roam_earlystop_rssi_thres_param *early_stop_thresholds = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001129 struct roam_ext_params *roam_params;
1130 int32_t good_rssi_threshold;
1131 uint32_t hirssi_scan_max_count;
1132 uint32_t hirssi_scan_delta;
1133 int32_t hirssi_upper_bound;
1134
1135 /* Send rssi threshold */
1136 roam_params = &roam_req->roam_params;
1137 rssi_thresh = roam_req->LookupThreshold - WMA_NOISE_FLOOR_DBM_DEFAULT;
1138 rssi_thresh_diff = roam_req->OpportunisticScanThresholdDiff;
1139 hirssi_scan_max_count = roam_req->hi_rssi_scan_max_count;
1140 hirssi_scan_delta = roam_req->hi_rssi_scan_rssi_delta;
1141 hirssi_upper_bound = roam_req->hi_rssi_scan_rssi_ub -
1142 WMA_NOISE_FLOOR_DBM_DEFAULT;
1143 len = sizeof(wmi_roam_scan_rssi_threshold_fixed_param);
1144 len += WMI_TLV_HDR_SIZE; /* TLV for ext_thresholds*/
1145 len += sizeof(wmi_roam_scan_extended_threshold_param);
Varun Reddy Yeturu05186292015-09-28 17:12:33 -07001146 len += WMI_TLV_HDR_SIZE;
1147 len += sizeof(wmi_roam_earlystop_rssi_thres_param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001148 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
1149 if (!buf) {
1150 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
1151 return CDF_STATUS_E_NOMEM;
1152 }
1153
1154 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1155 rssi_threshold_fp =
1156 (wmi_roam_scan_rssi_threshold_fixed_param *) buf_ptr;
1157 WMITLV_SET_HDR(&rssi_threshold_fp->tlv_header,
1158 WMITLV_TAG_STRUC_wmi_roam_scan_rssi_threshold_fixed_param,
1159 WMITLV_GET_STRUCT_TLVLEN
1160 (wmi_roam_scan_rssi_threshold_fixed_param));
1161 /* fill in threshold values */
1162 rssi_threshold_fp->vdev_id = roam_req->sessionId;
1163 rssi_threshold_fp->roam_scan_rssi_thresh = rssi_thresh & 0x000000ff;
1164 rssi_threshold_fp->roam_rssi_thresh_diff =
1165 rssi_thresh_diff & 0x000000ff;
1166 rssi_threshold_fp->hirssi_scan_max_count = hirssi_scan_max_count;
1167 rssi_threshold_fp->hirssi_scan_delta = hirssi_scan_delta;
1168 rssi_threshold_fp->hirssi_upper_bound = hirssi_upper_bound & 0x00000ff;
1169
1170 buf_ptr += sizeof(wmi_roam_scan_rssi_threshold_fixed_param);
1171 WMITLV_SET_HDR(buf_ptr,
1172 WMITLV_TAG_ARRAY_STRUC,
1173 sizeof(wmi_roam_scan_extended_threshold_param));
1174 buf_ptr += WMI_TLV_HDR_SIZE;
1175 ext_thresholds = (wmi_roam_scan_extended_threshold_param *) buf_ptr;
1176 /*
1177 * The current Noise floor in firmware is -96dBm. Penalty/Boost
1178 * threshold is applied on a weaker signal to make it even more weaker.
1179 * So, there is a chance that the user may configure a very low
1180 * Penalty/Boost threshold beyond the noise floor. If that is the case,
1181 * then suppress the penalty/boost threshold to the noise floor.
1182 */
1183 if (roam_params->raise_rssi_thresh_5g < WMA_NOISE_FLOOR_DBM_DEFAULT)
1184 ext_thresholds->penalty_threshold_5g = 0;
1185 else
1186 ext_thresholds->boost_threshold_5g =
1187 (roam_params->raise_rssi_thresh_5g -
1188 WMA_NOISE_FLOOR_DBM_DEFAULT) & 0x000000ff;
1189 if (roam_params->drop_rssi_thresh_5g < WMA_NOISE_FLOOR_DBM_DEFAULT)
1190 ext_thresholds->penalty_threshold_5g = 0;
1191 else
1192 ext_thresholds->penalty_threshold_5g =
1193 (roam_params->drop_rssi_thresh_5g -
1194 WMA_NOISE_FLOOR_DBM_DEFAULT) & 0x000000ff;
1195 ext_thresholds->boost_algorithm_5g =
1196 WMI_ROAM_5G_BOOST_PENALIZE_ALGO_LINEAR;
1197 ext_thresholds->boost_factor_5g = roam_params->raise_factor_5g;
1198 ext_thresholds->penalty_algorithm_5g =
1199 WMI_ROAM_5G_BOOST_PENALIZE_ALGO_LINEAR;
1200 ext_thresholds->penalty_factor_5g = roam_params->drop_factor_5g;
1201 ext_thresholds->max_boost_5g = roam_params->max_raise_rssi_5g;
1202 ext_thresholds->max_penalty_5g = roam_params->max_drop_rssi_5g;
1203
1204 if (roam_params->good_rssi_roam)
1205 good_rssi_threshold = WMA_NOISE_FLOOR_DBM_DEFAULT;
1206 else
1207 good_rssi_threshold = 0;
1208 ext_thresholds->good_rssi_threshold =
1209 (good_rssi_threshold - WMA_NOISE_FLOOR_DBM_DEFAULT) & 0x000000ff;
1210
1211 WMA_LOGD("WMA --> good_rssi_threshold=%d",
1212 ext_thresholds->good_rssi_threshold);
1213
1214 WMITLV_SET_HDR(&ext_thresholds->tlv_header,
1215 WMITLV_TAG_STRUC_wmi_roam_scan_extended_threshold_param,
1216 WMITLV_GET_STRUCT_TLVLEN
1217 (wmi_roam_scan_extended_threshold_param));
Varun Reddy Yeturu05186292015-09-28 17:12:33 -07001218 buf_ptr += sizeof(wmi_roam_scan_extended_threshold_param);
1219 WMITLV_SET_HDR(buf_ptr,
1220 WMITLV_TAG_ARRAY_STRUC,
1221 sizeof(wmi_roam_earlystop_rssi_thres_param));
1222 buf_ptr += WMI_TLV_HDR_SIZE;
1223 early_stop_thresholds = (wmi_roam_earlystop_rssi_thres_param *) buf_ptr;
1224 early_stop_thresholds->roam_earlystop_thres_min =
1225 roam_req->early_stop_scan_min_threshold -
1226 WMA_NOISE_FLOOR_DBM_DEFAULT;
1227 early_stop_thresholds->roam_earlystop_thres_max =
1228 roam_req->early_stop_scan_max_threshold -
1229 WMA_NOISE_FLOOR_DBM_DEFAULT;
1230 WMITLV_SET_HDR(&early_stop_thresholds->tlv_header,
1231 WMITLV_TAG_STRUC_wmi_roam_earlystop_rssi_thres_param,
1232 WMITLV_GET_STRUCT_TLVLEN
1233 (wmi_roam_earlystop_rssi_thres_param));
1234 WMA_LOGD("early_stop_thresholds en=%d, min=%d, max=%d",
1235 roam_req->early_stop_scan_enable,
1236 early_stop_thresholds->roam_earlystop_thres_min,
1237 early_stop_thresholds->roam_earlystop_thres_max);
1238
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001239 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
1240 len, WMI_ROAM_SCAN_RSSI_THRESHOLD);
1241 if (status != EOK) {
1242 WMA_LOGE("cmd WMI_ROAM_SCAN_RSSI_THRESHOLD returned Error %d",
1243 status);
1244 cdf_status = CDF_STATUS_E_FAILURE;
1245 goto error;
1246 }
1247
1248 WMA_LOGI(FL("roam_scan_rssi_thresh=%d, roam_rssi_thresh_diff=%d"),
1249 rssi_thresh, rssi_thresh_diff);
1250 WMA_LOGI(
1251 FL("hirssi_scan max_count=%d, delta=%d, hirssi_upper_bound=%d"),
1252 hirssi_scan_max_count, hirssi_scan_delta, hirssi_upper_bound);
1253 return CDF_STATUS_SUCCESS;
1254error:
1255 wmi_buf_free(buf);
1256
1257 return cdf_status;
1258}
1259
1260/**
1261 * wma_roam_scan_offload_scan_period() - set roam offload scan period
1262 * @wma_handle: wma handle
1263 * @scan_period: scan period
1264 * @scan_age: scan age
1265 * @vdev_id: vdev id
1266 *
1267 * Send WMI_ROAM_SCAN_PERIOD parameters to fw.
1268 *
1269 * Return: CDF status
1270 */
1271CDF_STATUS wma_roam_scan_offload_scan_period(tp_wma_handle wma_handle,
1272 uint32_t scan_period,
1273 uint32_t scan_age,
1274 uint32_t vdev_id)
1275{
1276 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
1277 wmi_buf_t buf = NULL;
1278 int status = 0;
1279 int len;
1280 uint8_t *buf_ptr;
1281 wmi_roam_scan_period_fixed_param *scan_period_fp;
1282
1283 /* Send scan period values */
1284 len = sizeof(wmi_roam_scan_period_fixed_param);
1285 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
1286 if (!buf) {
1287 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
1288 return CDF_STATUS_E_NOMEM;
1289 }
1290
1291 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1292 scan_period_fp = (wmi_roam_scan_period_fixed_param *) buf_ptr;
1293 WMITLV_SET_HDR(&scan_period_fp->tlv_header,
1294 WMITLV_TAG_STRUC_wmi_roam_scan_period_fixed_param,
1295 WMITLV_GET_STRUCT_TLVLEN
1296 (wmi_roam_scan_period_fixed_param));
1297 /* fill in scan period values */
1298 scan_period_fp->vdev_id = vdev_id;
1299 scan_period_fp->roam_scan_period = scan_period; /* 20 seconds */
1300 scan_period_fp->roam_scan_age = scan_age;
1301
1302 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
1303 len, WMI_ROAM_SCAN_PERIOD);
1304 if (status != EOK) {
1305 WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_SCAN_PERIOD returned Error %d",
1306 status);
1307 cdf_status = CDF_STATUS_E_FAILURE;
1308 goto error;
1309 }
1310
1311 WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_PERIOD roam_scan_period=%d, roam_scan_age=%d",
1312 __func__, scan_period, scan_age);
1313 return CDF_STATUS_SUCCESS;
1314error:
1315 wmi_buf_free(buf);
1316
1317 return cdf_status;
1318}
1319
1320/**
1321 * wma_roam_scan_offload_rssi_change() - set roam offload RSSI change threshold
1322 * @wma_handle: wma handle
1323 * @rssi_change_thresh: RSSI Change threshold
1324 * @bcn_rssi_weight: beacon RSSI weight
1325 * @vdev_id: vdev id
1326 *
1327 * Send WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD parameters to fw.
1328 *
1329 * Return: CDF status
1330 */
1331CDF_STATUS wma_roam_scan_offload_rssi_change(tp_wma_handle wma_handle,
1332 uint32_t vdev_id,
1333 int32_t rssi_change_thresh,
1334 uint32_t bcn_rssi_weight,
1335 uint32_t hirssi_delay_btw_scans)
1336{
1337 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
1338 wmi_buf_t buf = NULL;
1339 int status = 0;
1340 int len;
1341 uint8_t *buf_ptr;
1342 wmi_roam_scan_rssi_change_threshold_fixed_param *rssi_change_fp;
1343
1344 /* Send rssi change parameters */
1345 len = sizeof(wmi_roam_scan_rssi_change_threshold_fixed_param);
1346 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
1347 if (!buf) {
1348 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
1349 return CDF_STATUS_E_NOMEM;
1350 }
1351
1352 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1353 rssi_change_fp =
1354 (wmi_roam_scan_rssi_change_threshold_fixed_param *) buf_ptr;
1355 WMITLV_SET_HDR(&rssi_change_fp->tlv_header,
1356 WMITLV_TAG_STRUC_wmi_roam_scan_rssi_change_threshold_fixed_param,
1357 WMITLV_GET_STRUCT_TLVLEN
1358 (wmi_roam_scan_rssi_change_threshold_fixed_param));
1359 /* fill in rssi change threshold (hysteresis) values */
1360 rssi_change_fp->vdev_id = vdev_id;
1361 rssi_change_fp->roam_scan_rssi_change_thresh = rssi_change_thresh;
1362 rssi_change_fp->bcn_rssi_weight = bcn_rssi_weight;
1363 rssi_change_fp->hirssi_delay_btw_scans = hirssi_delay_btw_scans;
1364
1365 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
1366 len, WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD);
1367 if (status != EOK) {
1368 WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD returned Error %d",
1369 status);
1370 cdf_status = CDF_STATUS_E_FAILURE;
1371 goto error;
1372 }
1373
1374 WMA_LOGI(FL("roam_scan_rssi_change_thresh=%d, bcn_rssi_weight=%d"),
1375 rssi_change_thresh, bcn_rssi_weight);
1376 WMA_LOGI(FL("hirssi_delay_btw_scans=%d"), hirssi_delay_btw_scans);
1377 return CDF_STATUS_SUCCESS;
1378error:
1379 wmi_buf_free(buf);
1380
1381 return cdf_status;
1382}
1383
1384/**
1385 * wma_roam_scan_offload_chan_list() - set roam offload channel list
1386 * @wma_handle: wma handle
1387 * @chan_count: channel count
1388 * @chan_list: channel list
1389 * @list_type: list type
1390 * @vdev_id: vdev id
1391 *
1392 * Set roam offload channel list.
1393 *
1394 * Return: CDF status
1395 */
1396CDF_STATUS wma_roam_scan_offload_chan_list(tp_wma_handle wma_handle,
1397 uint8_t chan_count,
1398 uint8_t *chan_list,
1399 uint8_t list_type, uint32_t vdev_id)
1400{
1401 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
1402 wmi_buf_t buf = NULL;
1403 int status = 0;
1404 int len, list_tlv_len;
1405 int i;
1406 uint8_t *buf_ptr;
1407 wmi_roam_chan_list_fixed_param *chan_list_fp;
1408 A_UINT32 *roam_chan_list_array;
1409
1410 if (chan_count == 0) {
1411 WMA_LOGD("%s : invalid number of channels %d", __func__,
1412 chan_count);
1413 return CDF_STATUS_E_EMPTY;
1414 }
1415 /* Channel list is a table of 2 TLV's */
1416 list_tlv_len = WMI_TLV_HDR_SIZE + chan_count * sizeof(A_UINT32);
1417 len = sizeof(wmi_roam_chan_list_fixed_param) + list_tlv_len;
1418 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
1419 if (!buf) {
1420 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
1421 return CDF_STATUS_E_NOMEM;
1422 }
1423
1424 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1425 chan_list_fp = (wmi_roam_chan_list_fixed_param *) buf_ptr;
1426 WMITLV_SET_HDR(&chan_list_fp->tlv_header,
1427 WMITLV_TAG_STRUC_wmi_roam_chan_list_fixed_param,
1428 WMITLV_GET_STRUCT_TLVLEN
1429 (wmi_roam_chan_list_fixed_param));
1430 chan_list_fp->vdev_id = vdev_id;
1431 chan_list_fp->num_chan = chan_count;
1432 if (chan_count > 0 && list_type == CHANNEL_LIST_STATIC) {
1433 /* external app is controlling channel list */
1434 chan_list_fp->chan_list_type =
1435 WMI_ROAM_SCAN_CHAN_LIST_TYPE_STATIC;
1436 } else {
1437 /* umac supplied occupied channel list in LFR */
1438 chan_list_fp->chan_list_type =
1439 WMI_ROAM_SCAN_CHAN_LIST_TYPE_DYNAMIC;
1440 }
1441
1442 buf_ptr += sizeof(wmi_roam_chan_list_fixed_param);
1443 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
1444 (chan_list_fp->num_chan * sizeof(uint32_t)));
1445 roam_chan_list_array = (A_UINT32 *) (buf_ptr + WMI_TLV_HDR_SIZE);
1446 WMA_LOGI("%s: %d channels = ", __func__, chan_list_fp->num_chan);
1447 for (i = 0; ((i < chan_list_fp->num_chan) &&
1448 (i < SIR_ROAM_MAX_CHANNELS)); i++) {
1449 roam_chan_list_array[i] = cds_chan_to_freq(chan_list[i]);
1450 WMA_LOGI("%d,", roam_chan_list_array[i]);
1451 }
1452
1453 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
1454 len, WMI_ROAM_CHAN_LIST);
1455 if (status != EOK) {
1456 WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_CHAN_LIST returned Error %d",
1457 status);
1458 cdf_status = CDF_STATUS_E_FAILURE;
1459 goto error;
1460 }
1461
1462 WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_CHAN_LIST", __func__);
1463 return CDF_STATUS_SUCCESS;
1464error:
1465 wmi_buf_free(buf);
1466
1467 return cdf_status;
1468}
1469
1470/**
1471 * e_csr_auth_type_to_rsn_authmode() - map csr auth type to rsn authmode
1472 * @authtype: CSR authtype
1473 * @encr: CSR Encryption
1474 *
1475 * Map CSR's authentication type into RSN auth mode used by firmware
1476 *
1477 * Return: WMI RSN auth mode
1478 */
1479A_UINT32 e_csr_auth_type_to_rsn_authmode(eCsrAuthType authtype,
1480 eCsrEncryptionType encr)
1481{
1482 switch (authtype) {
1483 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
1484 return WMI_AUTH_OPEN;
1485 case eCSR_AUTH_TYPE_WPA:
1486 return WMI_AUTH_WPA;
1487 case eCSR_AUTH_TYPE_WPA_PSK:
1488 return WMI_AUTH_WPA_PSK;
1489 case eCSR_AUTH_TYPE_RSN:
1490 return WMI_AUTH_RSNA;
1491 case eCSR_AUTH_TYPE_RSN_PSK:
1492 return WMI_AUTH_RSNA_PSK;
1493#if defined WLAN_FEATURE_VOWIFI_11R
1494 case eCSR_AUTH_TYPE_FT_RSN:
1495 return WMI_AUTH_FT_RSNA;
1496 case eCSR_AUTH_TYPE_FT_RSN_PSK:
1497 return WMI_AUTH_FT_RSNA_PSK;
1498#endif /* WLAN_FEATURE_VOWIFI_11R */
1499#ifdef FEATURE_WLAN_WAPI
1500 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
1501 return WMI_AUTH_WAPI;
1502 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
1503 return WMI_AUTH_WAPI_PSK;
1504#endif /* FEATURE_WLAN_WAPI */
1505#ifdef FEATURE_WLAN_ESE
1506 case eCSR_AUTH_TYPE_CCKM_WPA:
1507 case eCSR_AUTH_TYPE_CCKM_RSN:
1508 return WMI_AUTH_CCKM;
1509#endif /* FEATURE_WLAN_ESE */
1510#ifdef WLAN_FEATURE_11W
1511 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
1512 return WMI_AUTH_RSNA_PSK_SHA256;
1513 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
1514 return WMI_AUTH_RSNA_8021X_SHA256;
1515#endif /* WLAN_FEATURE_11W */
1516 case eCSR_AUTH_TYPE_NONE:
1517 case eCSR_AUTH_TYPE_AUTOSWITCH:
1518 /* In case of WEP and other keys, NONE means OPEN auth */
1519 if (encr == eCSR_ENCRYPT_TYPE_WEP40_STATICKEY ||
1520 encr == eCSR_ENCRYPT_TYPE_WEP104_STATICKEY ||
1521 encr == eCSR_ENCRYPT_TYPE_WEP40 ||
1522 encr == eCSR_ENCRYPT_TYPE_WEP104 ||
1523 encr == eCSR_ENCRYPT_TYPE_TKIP ||
1524 encr == eCSR_ENCRYPT_TYPE_AES) {
1525 return WMI_AUTH_OPEN;
1526 }
1527 return WMI_AUTH_NONE;
1528 default:
1529 return WMI_AUTH_NONE;
1530 }
1531}
1532
1533/**
1534 * e_csr_encryption_type_to_rsn_cipherset() - map csr enc type to ESN cipher
1535 * @encr: CSR Encryption
1536 *
1537 * Map CSR's encryption type into RSN cipher types used by firmware
1538 *
1539 * Return: WMI RSN cipher
1540 */
1541A_UINT32 e_csr_encryption_type_to_rsn_cipherset(eCsrEncryptionType encr)
1542{
1543
1544 switch (encr) {
1545 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
1546 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
1547 case eCSR_ENCRYPT_TYPE_WEP40:
1548 case eCSR_ENCRYPT_TYPE_WEP104:
1549 return WMI_CIPHER_WEP;
1550 case eCSR_ENCRYPT_TYPE_TKIP:
1551 return WMI_CIPHER_TKIP;
1552 case eCSR_ENCRYPT_TYPE_AES:
1553 return WMI_CIPHER_AES_CCM;
1554#ifdef FEATURE_WLAN_WAPI
1555 case eCSR_ENCRYPT_TYPE_WPI:
1556 return WMI_CIPHER_WAPI;
1557#endif /* FEATURE_WLAN_WAPI */
1558 case eCSR_ENCRYPT_TYPE_ANY:
1559 return WMI_CIPHER_ANY;
1560 case eCSR_ENCRYPT_TYPE_NONE:
1561 default:
1562 return WMI_CIPHER_NONE;
1563 }
1564}
1565
1566/**
1567 * wma_roam_scan_fill_ap_profile() - fill ap_profile
1568 * @wma_handle: wma handle
1569 * @pMac: Mac ptr
1570 * @roam_req: roam offload scan request
1571 * @ap_profile_p: ap profile
1572 *
1573 * Fill ap_profile structure from configured parameters
1574 *
1575 * Return: none
1576 */
1577void wma_roam_scan_fill_ap_profile(tp_wma_handle wma_handle,
1578 tpAniSirGlobal pMac,
1579 tSirRoamOffloadScanReq *roam_req,
1580 wmi_ap_profile *ap_profile_p)
1581{
1582 cdf_mem_zero(ap_profile_p, sizeof(wmi_ap_profile));
1583 if (roam_req == NULL) {
1584 ap_profile_p->ssid.ssid_len = 0;
1585 ap_profile_p->ssid.ssid[0] = 0;
1586 ap_profile_p->rsn_authmode = WMI_AUTH_NONE;
1587 ap_profile_p->rsn_ucastcipherset = WMI_CIPHER_NONE;
1588 ap_profile_p->rsn_mcastcipherset = WMI_CIPHER_NONE;
1589 ap_profile_p->rsn_mcastmgmtcipherset = WMI_CIPHER_NONE;
1590 ap_profile_p->rssi_threshold = WMA_ROAM_RSSI_DIFF_DEFAULT;
1591 } else {
1592 ap_profile_p->ssid.ssid_len =
1593 roam_req->ConnectedNetwork.ssId.length;
1594 cdf_mem_copy(ap_profile_p->ssid.ssid,
1595 roam_req->ConnectedNetwork.ssId.ssId,
1596 ap_profile_p->ssid.ssid_len);
1597 ap_profile_p->rsn_authmode =
1598 e_csr_auth_type_to_rsn_authmode(roam_req->ConnectedNetwork.authentication,
1599 roam_req->ConnectedNetwork.encryption);
1600 ap_profile_p->rsn_ucastcipherset =
1601 e_csr_encryption_type_to_rsn_cipherset(roam_req->ConnectedNetwork.encryption);
1602 ap_profile_p->rsn_mcastcipherset =
1603 e_csr_encryption_type_to_rsn_cipherset(roam_req->ConnectedNetwork.mcencryption);
1604 ap_profile_p->rsn_mcastmgmtcipherset =
1605 ap_profile_p->rsn_mcastcipherset;
1606 ap_profile_p->rssi_threshold = roam_req->RoamRssiDiff;
1607#ifdef WLAN_FEATURE_11W
1608 if (roam_req->ConnectedNetwork.mfp_enabled)
1609 ap_profile_p->flags |= WMI_AP_PROFILE_FLAG_PMF;
1610#endif
1611 }
1612}
1613
1614/**
1615 * wma_roam_scan_scan_params() - fill roam scan params
1616 * @wma_handle: wma handle
1617 * @pMac: Mac ptr
1618 * @scan_params: scan parameters
1619 * @roam_req: NULL if this routine is called before connect
1620 * It will be non-NULL if called after assoc.
1621 *
1622 * Fill scan_params structure from configured parameters
1623 *
1624 * Return: none
1625 */
1626void wma_roam_scan_fill_scan_params(tp_wma_handle wma_handle,
1627 tpAniSirGlobal pMac,
1628 tSirRoamOffloadScanReq *roam_req,
1629 wmi_start_scan_cmd_fixed_param *
1630 scan_params)
1631{
1632 uint8_t channels_per_burst = 0;
1633 uint32_t val = 0;
1634
1635 if (NULL == pMac) {
1636 WMA_LOGE("%s: pMac is NULL", __func__);
1637 return;
1638 }
1639
1640 cdf_mem_zero(scan_params, sizeof(wmi_start_scan_cmd_fixed_param));
1641 scan_params->scan_ctrl_flags = WMI_SCAN_ADD_CCK_RATES |
Sreelakshmi Konamki75deb332015-09-14 10:58:03 +05301642 WMI_SCAN_ADD_OFDM_RATES |
1643 WMI_SCAN_ADD_DS_IE_IN_PROBE_REQ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001644 if (roam_req != NULL) {
1645 /* Parameters updated after association is complete */
1646 WMA_LOGI("%s: Input parameters: NeighborScanChannelMinTime"
1647 " = %d, NeighborScanChannelMaxTime = %d",
1648 __func__,
1649 roam_req->NeighborScanChannelMinTime,
1650 roam_req->NeighborScanChannelMaxTime);
1651 WMA_LOGI("%s: Input parameters: NeighborScanTimerPeriod ="
1652 " %d, HomeAwayTime = %d, nProbes = %d",
1653 __func__,
1654 roam_req->NeighborScanTimerPeriod,
1655 roam_req->HomeAwayTime, roam_req->nProbes);
1656
1657 /*
1658 * roam_req->NeighborScanChannelMaxTime = SCAN_CHANNEL_TIME
1659 * roam_req->HomeAwayTime = SCAN_HOME_AWAY_TIME
1660 * roam_req->NeighborScanTimerPeriod = SCAN_HOME_TIME
1661 *
1662 * scan_params->dwell_time_active = time station stays on channel
1663 * and sends probes;
1664 * scan_params->dwell_time_passive = time station stays on channel
1665 * and listens probes;
1666 * scan_params->burst_duration = time station goes off channel
1667 * to scan;
1668 */
1669
1670 if (wlan_cfg_get_int
1671 (pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME,
1672 &val) != eSIR_SUCCESS) {
1673 /*
1674 * Could not get max channel value from CFG. Log error.
1675 */
1676 WMA_LOGE
1677 ("could not retrieve passive max channel value");
1678
1679 /* use a default value of 110ms */
1680 val = WMA_ROAM_DWELL_TIME_PASSIVE_DEFAULT;
1681 }
1682
1683 scan_params->dwell_time_passive = val;
1684 /*
1685 * Here is the formula,
1686 * T(HomeAway) = N * T(dwell) + (N+1) * T(cs)
1687 * where N is number of channels scanned in single burst
1688 */
1689 scan_params->dwell_time_active =
1690 roam_req->NeighborScanChannelMaxTime;
1691 if (roam_req->HomeAwayTime <
1692 2 * WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME) {
1693 /* clearly we can't follow home away time.
1694 * Make it a split scan.
1695 */
1696 scan_params->burst_duration = 0;
1697 } else {
1698 channels_per_burst =
1699 (roam_req->HomeAwayTime -
1700 WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME)
1701 / (scan_params->dwell_time_active +
1702 WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME);
1703
1704 if (channels_per_burst < 1) {
1705 /* dwell time and home away time conflicts */
1706 /* we will override dwell time */
1707 scan_params->dwell_time_active =
1708 roam_req->HomeAwayTime -
1709 2 * WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME;
1710 scan_params->burst_duration =
1711 scan_params->dwell_time_active;
1712 } else {
1713 scan_params->burst_duration =
1714 channels_per_burst *
1715 scan_params->dwell_time_active;
1716 }
1717 }
1718 if (roam_req->allowDFSChannelRoam ==
1719 SIR_ROAMING_DFS_CHANNEL_ENABLED_NORMAL
1720 && roam_req->HomeAwayTime > 0
1721 && roam_req->ChannelCacheType != CHANNEL_LIST_STATIC) {
1722 /* Roaming on DFS channels is supported and it is not
1723 * app channel list. It is ok to override homeAwayTime
1724 * to accomodate DFS dwell time in burst
1725 * duration.
1726 */
1727 scan_params->burst_duration =
1728 CDF_MAX(scan_params->burst_duration,
1729 scan_params->dwell_time_passive);
1730 }
1731 scan_params->min_rest_time = roam_req->NeighborScanTimerPeriod;
1732 scan_params->max_rest_time = roam_req->NeighborScanTimerPeriod;
1733 scan_params->repeat_probe_time = (roam_req->nProbes > 0) ?
1734 CDF_MAX(scan_params->dwell_time_active / roam_req->nProbes,
1735 1) : 0;
1736 scan_params->probe_spacing_time = 0;
1737 scan_params->probe_delay = 0;
1738 /* 30 seconds for full scan cycle */
1739 scan_params->max_scan_time = WMA_HW_DEF_SCAN_MAX_DURATION;
1740 scan_params->idle_time = scan_params->min_rest_time;
1741 scan_params->n_probes = roam_req->nProbes;
1742 if (roam_req->allowDFSChannelRoam ==
1743 SIR_ROAMING_DFS_CHANNEL_DISABLED) {
1744 scan_params->scan_ctrl_flags |= WMI_SCAN_BYPASS_DFS_CHN;
1745 } else {
1746 /* Roaming scan on DFS channel is allowed.
1747 * No need to change any flags for default
1748 * allowDFSChannelRoam = 1.
1749 * Special case where static channel list is given by\
1750 * application that contains DFS channels.
1751 * Assume that the application has knowledge of matching
1752 * APs being active and that probe request transmission
1753 * is permitted on those channel.
1754 * Force active scans on those channels.
1755 */
1756
1757 if (roam_req->allowDFSChannelRoam ==
1758 SIR_ROAMING_DFS_CHANNEL_ENABLED_ACTIVE &&
1759 roam_req->ChannelCacheType == CHANNEL_LIST_STATIC &&
1760 roam_req->ConnectedNetwork.ChannelCount > 0) {
1761 scan_params->scan_ctrl_flags |=
1762 WMI_SCAN_FLAG_FORCE_ACTIVE_ON_DFS;
1763 }
1764 }
1765 } else {
1766 /* roam_req = NULL during initial or pre-assoc invocation */
1767 scan_params->dwell_time_active =
1768 WMA_ROAM_DWELL_TIME_ACTIVE_DEFAULT;
1769 scan_params->dwell_time_passive =
1770 WMA_ROAM_DWELL_TIME_PASSIVE_DEFAULT;
1771 scan_params->min_rest_time = WMA_ROAM_MIN_REST_TIME_DEFAULT;
1772 scan_params->max_rest_time = WMA_ROAM_MAX_REST_TIME_DEFAULT;
1773 scan_params->repeat_probe_time = 0;
1774 scan_params->probe_spacing_time = 0;
1775 scan_params->probe_delay = 0;
1776 scan_params->max_scan_time = WMA_HW_DEF_SCAN_MAX_DURATION;
1777 scan_params->idle_time = scan_params->min_rest_time;
1778 scan_params->burst_duration = 0;
1779 scan_params->n_probes = 0;
1780 }
1781
1782 WMA_LOGI("%s: Rome roam scan parameters:"
1783 " dwell_time_active = %d, dwell_time_passive = %d",
1784 __func__,
1785 scan_params->dwell_time_active,
1786 scan_params->dwell_time_passive);
1787 WMA_LOGI("%s: min_rest_time = %d, max_rest_time = %d,"
1788 " repeat_probe_time = %d n_probes = %d",
1789 __func__,
1790 scan_params->min_rest_time,
1791 scan_params->max_rest_time,
1792 scan_params->repeat_probe_time, scan_params->n_probes);
1793 WMA_LOGI("%s: max_scan_time = %d, idle_time = %d,"
1794 " burst_duration = %d, scan_ctrl_flags = 0x%x",
1795 __func__,
1796 scan_params->max_scan_time,
1797 scan_params->idle_time,
1798 scan_params->burst_duration, scan_params->scan_ctrl_flags);
1799}
1800
1801/**
1802 * wma_roam_scan_offload_ap_profile() - set roam ap profile in fw
1803 * @wma_handle: wma handle
1804 * @ap_profile_p: ap profile
1805 * @vdev_id: vdev id
1806 *
1807 * Send WMI_ROAM_AP_PROFILE to firmware
1808 *
1809 * Return: CDF status
1810 */
1811CDF_STATUS wma_roam_scan_offload_ap_profile(tp_wma_handle wma_handle,
1812 wmi_ap_profile *ap_profile_p,
1813 uint32_t vdev_id)
1814{
1815 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
1816 wmi_buf_t buf = NULL;
1817 int status = 0;
1818 int len;
1819 uint8_t *buf_ptr;
1820 wmi_roam_ap_profile_fixed_param *roam_ap_profile_fp;
1821
1822 len = sizeof(wmi_roam_ap_profile_fixed_param) + sizeof(wmi_ap_profile);
1823
1824 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
1825 if (!buf) {
1826 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
1827 return CDF_STATUS_E_NOMEM;
1828 }
1829
1830 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1831 roam_ap_profile_fp = (wmi_roam_ap_profile_fixed_param *) buf_ptr;
1832 WMITLV_SET_HDR(&roam_ap_profile_fp->tlv_header,
1833 WMITLV_TAG_STRUC_wmi_roam_ap_profile_fixed_param,
1834 WMITLV_GET_STRUCT_TLVLEN
1835 (wmi_roam_ap_profile_fixed_param));
1836 /* fill in threshold values */
1837 roam_ap_profile_fp->vdev_id = vdev_id;
1838 roam_ap_profile_fp->id = 0;
1839 buf_ptr += sizeof(wmi_roam_ap_profile_fixed_param);
1840
1841 cdf_mem_copy(buf_ptr, ap_profile_p, sizeof(wmi_ap_profile));
1842 WMITLV_SET_HDR(buf_ptr,
1843 WMITLV_TAG_STRUC_wmi_ap_profile,
1844 WMITLV_GET_STRUCT_TLVLEN(wmi_ap_profile));
1845 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
1846 len, WMI_ROAM_AP_PROFILE);
1847 if (status != EOK) {
1848 WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_AP_PROFILE returned Error %d",
1849 status);
1850 cdf_status = CDF_STATUS_E_FAILURE;
1851 goto error;
1852 }
1853
1854 WMA_LOGI("WMA --> WMI_ROAM_AP_PROFILE and other parameters");
1855 return CDF_STATUS_SUCCESS;
1856error:
1857 wmi_buf_free(buf);
1858
1859 return cdf_status;
1860}
1861
1862/**
1863 * wma_roam_scan_filter() - Filter to be applied while roaming
1864 * @wma_handle: Global WMA Handle
1865 * @roam_req: Request which contains the filters
1866 *
1867 * There are filters such as whitelist, blacklist and preferred
1868 * list that need to be applied to the scan results to form the
1869 * probable candidates for roaming.
1870 *
1871 * Return: Return success upon succesfully passing the
1872 * parameters to the firmware, otherwise failure.
1873 */
1874CDF_STATUS wma_roam_scan_filter(tp_wma_handle wma_handle,
1875 tSirRoamOffloadScanReq *roam_req)
1876{
1877 wmi_buf_t buf = NULL;
1878 int status = 0, i;
1879 uint32_t len, num_bssid_black_list = 0, num_ssid_white_list = 0,
1880 num_bssid_preferred_list = 0;
1881 uint32_t op_bitmap = 0;
1882 uint8_t *buf_ptr;
1883 wmi_roam_filter_fixed_param *roam_filter;
1884 uint8_t *bssid_src_ptr = NULL;
1885 wmi_mac_addr *bssid_dst_ptr = NULL;
1886 wmi_ssid *ssid_ptr = NULL;
1887 uint32_t *bssid_preferred_factor_ptr = NULL;
1888 struct roam_ext_params *roam_params;
1889
1890 roam_params = &roam_req->roam_params;
1891 len = sizeof(wmi_roam_filter_fixed_param);
1892 len += WMI_TLV_HDR_SIZE;
1893 if (roam_req->Command != ROAM_SCAN_OFFLOAD_STOP) {
1894 switch (roam_req->reason) {
1895 case REASON_ROAM_SET_BLACKLIST_BSSID:
1896 op_bitmap |= 0x1;
1897 num_bssid_black_list =
1898 roam_params->num_bssid_avoid_list;
1899 len += num_bssid_black_list * sizeof(wmi_mac_addr);
1900 len += WMI_TLV_HDR_SIZE;
1901 break;
1902 case REASON_ROAM_SET_SSID_ALLOWED:
1903 op_bitmap |= 0x2;
1904 num_ssid_white_list =
1905 roam_params->num_ssid_allowed_list;
1906 len += num_ssid_white_list * sizeof(wmi_ssid);
1907 len += WMI_TLV_HDR_SIZE;
1908 break;
1909 case REASON_ROAM_SET_FAVORED_BSSID:
1910 op_bitmap |= 0x4;
1911 num_bssid_preferred_list =
1912 roam_params->num_bssid_favored;
1913 len += num_bssid_preferred_list * sizeof(wmi_mac_addr);
1914 len += WMI_TLV_HDR_SIZE;
1915 len += num_bssid_preferred_list * sizeof(A_UINT32);
1916 break;
1917 default:
1918 WMA_LOGD("%s : Roam Filter need not be sent", __func__);
1919 return CDF_STATUS_SUCCESS;
1920 break;
1921 }
1922 } else {
1923 /* In case of STOP command, reset all the variables
1924 * except for blacklist BSSID which should be retained
1925 * across connections.*/
1926 op_bitmap = 0x2 | 0x4;
1927 num_ssid_white_list = roam_params->num_ssid_allowed_list;
1928 len += num_ssid_white_list * sizeof(wmi_ssid);
1929 num_bssid_preferred_list = roam_params->num_bssid_favored;
1930 len += num_bssid_preferred_list * sizeof(wmi_mac_addr);
1931 len += num_bssid_preferred_list * sizeof(A_UINT32);
1932 len += (2 * WMI_TLV_HDR_SIZE);
1933 }
1934 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
1935 if (!buf) {
1936 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
1937 return CDF_STATUS_E_NOMEM;
1938 }
1939
1940 buf_ptr = (u_int8_t *) wmi_buf_data(buf);
1941 roam_filter = (wmi_roam_filter_fixed_param *) buf_ptr;
1942 WMITLV_SET_HDR(&roam_filter->tlv_header,
1943 WMITLV_TAG_STRUC_wmi_roam_filter_fixed_param,
1944 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_filter_fixed_param));
1945 /* fill in fixed values */
1946 roam_filter->vdev_id = roam_req->sessionId;
1947 roam_filter->flags = 0;
1948 roam_filter->op_bitmap = op_bitmap;
1949 roam_filter->num_bssid_black_list = num_bssid_black_list;
1950 roam_filter->num_ssid_white_list = num_ssid_white_list;
1951 roam_filter->num_bssid_preferred_list = num_bssid_preferred_list;
1952 buf_ptr += sizeof(wmi_roam_filter_fixed_param);
1953
1954 WMITLV_SET_HDR((buf_ptr),
1955 WMITLV_TAG_ARRAY_FIXED_STRUC,
1956 (num_bssid_black_list * sizeof(wmi_mac_addr)));
1957 bssid_src_ptr = (uint8_t *)&roam_params->bssid_avoid_list;
1958 bssid_dst_ptr = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE);
1959 for (i = 0; i < num_bssid_black_list; i++) {
1960 WMI_CHAR_ARRAY_TO_MAC_ADDR(bssid_src_ptr, bssid_dst_ptr);
1961 bssid_src_ptr += ATH_MAC_LEN;
1962 bssid_dst_ptr++;
1963 }
1964 buf_ptr += WMI_TLV_HDR_SIZE +
1965 (num_bssid_black_list * sizeof(wmi_mac_addr));
1966 WMITLV_SET_HDR((buf_ptr),
1967 WMITLV_TAG_ARRAY_FIXED_STRUC,
1968 (num_ssid_white_list * sizeof(wmi_ssid)));
1969 ssid_ptr = (wmi_ssid *)(buf_ptr + WMI_TLV_HDR_SIZE);
1970 for (i = 0; i < num_ssid_white_list; i++) {
1971 memcpy(&ssid_ptr->ssid, &roam_params->ssid_allowed_list[i].ssId,
1972 roam_params->ssid_allowed_list[i].length);
1973 ssid_ptr->ssid_len = roam_params->ssid_allowed_list[i].length;
1974 WMA_LOGD("%s: SSID length=%d", __func__, ssid_ptr->ssid_len);
1975 CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_DEBUG,
1976 (uint8_t *)ssid_ptr->ssid,
1977 ssid_ptr->ssid_len);
1978 ssid_ptr++;
1979 }
1980 buf_ptr += WMI_TLV_HDR_SIZE + (num_ssid_white_list * sizeof(wmi_ssid));
1981 WMITLV_SET_HDR((buf_ptr),
1982 WMITLV_TAG_ARRAY_FIXED_STRUC,
1983 (num_bssid_preferred_list * sizeof(wmi_mac_addr)));
1984 bssid_src_ptr = (uint8_t *)&roam_params->bssid_favored;
1985 bssid_dst_ptr = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE);
1986 for (i = 0; i < num_bssid_preferred_list; i++) {
1987 WMI_CHAR_ARRAY_TO_MAC_ADDR(bssid_src_ptr,
1988 (wmi_mac_addr *)bssid_dst_ptr);
1989 bssid_src_ptr += ATH_MAC_LEN;
1990 bssid_dst_ptr++;
1991 }
1992 buf_ptr += WMI_TLV_HDR_SIZE +
1993 (num_bssid_preferred_list * sizeof(wmi_mac_addr));
1994 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
1995 (num_bssid_preferred_list * sizeof(uint32_t)));
1996 bssid_preferred_factor_ptr = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE);
1997 for (i = 0; i < num_bssid_preferred_list; i++) {
1998 *bssid_preferred_factor_ptr =
1999 roam_params->bssid_favored_factor[i];
2000 bssid_preferred_factor_ptr++;
2001 }
2002 buf_ptr += WMI_TLV_HDR_SIZE +
2003 (num_bssid_preferred_list * sizeof(uint32_t));
2004 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
2005 len, WMI_ROAM_FILTER_CMDID);
2006 if (status != EOK) {
2007 WMA_LOGE("cmd WMI_ROAM_FILTER_CMDID returned Error %d",
2008 status);
2009 goto error;
2010 }
2011 return CDF_STATUS_SUCCESS;
2012error:
2013 wmi_buf_free(buf);
2014 return CDF_STATUS_E_FAILURE;
2015}
2016
2017/**
2018 * wma_roam_scan_bmiss_cnt() - set bmiss count to fw
2019 * @wma_handle: wma handle
2020 * @first_bcnt: first bmiss count
2021 * @final_bcnt: final bmiss count
2022 * @vdev_id: vdev id
2023 *
2024 * set first & final biss count to fw.
2025 *
2026 * Return: CDF status
2027 */
2028CDF_STATUS wma_roam_scan_bmiss_cnt(tp_wma_handle wma_handle,
2029 A_INT32 first_bcnt,
2030 A_UINT32 final_bcnt, uint32_t vdev_id)
2031{
2032 int status = 0;
2033
2034 WMA_LOGI("%s: first_bcnt=%d, final_bcnt=%d", __func__, first_bcnt,
2035 final_bcnt);
2036
2037 status = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle,
2038 vdev_id,
2039 WMI_VDEV_PARAM_BMISS_FIRST_BCNT,
2040 first_bcnt);
2041 if (status != EOK) {
2042 WMA_LOGE("wmi_unified_vdev_set_param_send WMI_VDEV_PARAM_BMISS_FIRST_BCNT returned Error %d",
2043 status);
2044 return CDF_STATUS_E_FAILURE;
2045 }
2046
2047 status = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle,
2048 vdev_id,
2049 WMI_VDEV_PARAM_BMISS_FINAL_BCNT,
2050 final_bcnt);
2051 if (status != EOK) {
2052 WMA_LOGE("wmi_unified_vdev_set_param_send WMI_VDEV_PARAM_BMISS_FINAL_BCNT returned Error %d",
2053 status);
2054 return CDF_STATUS_E_FAILURE;
2055 }
2056
2057 return CDF_STATUS_SUCCESS;
2058}
2059
2060/**
2061 * wma_roam_scan_offload_command() - set roam offload command
2062 * @wma_handle: wma handle
2063 * @command: command
2064 * @vdev_id: vdev id
2065 *
2066 * This function set roam offload command to fw.
2067 *
2068 * Return: CDF status
2069 */
2070CDF_STATUS wma_roam_scan_offload_command(tp_wma_handle wma_handle,
2071 uint32_t command, uint32_t vdev_id)
2072{
2073 CDF_STATUS cdf_status;
2074 wmi_roam_scan_cmd_fixed_param *cmd_fp;
2075 wmi_buf_t buf = NULL;
2076 int status = 0;
2077 int len;
2078 uint8_t *buf_ptr;
2079
2080 len = sizeof(wmi_roam_scan_cmd_fixed_param);
2081 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
2082 if (!buf) {
2083 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
2084 return CDF_STATUS_E_NOMEM;
2085 }
2086
2087 buf_ptr = (uint8_t *) wmi_buf_data(buf);
2088
2089 cmd_fp = (wmi_roam_scan_cmd_fixed_param *) buf_ptr;
2090 WMITLV_SET_HDR(&cmd_fp->tlv_header,
2091 WMITLV_TAG_STRUC_wmi_roam_scan_cmd_fixed_param,
2092 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_scan_cmd_fixed_param));
2093 cmd_fp->vdev_id = vdev_id;
2094 cmd_fp->command_arg = command;
2095
2096 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
2097 len, WMI_ROAM_SCAN_CMD);
2098 if (status != EOK) {
2099 WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_SCAN_CMD returned Error %d",
2100 status);
2101 cdf_status = CDF_STATUS_E_FAILURE;
2102 goto error;
2103 }
2104
2105 WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_CMD", __func__);
2106 return CDF_STATUS_SUCCESS;
2107
2108error:
2109 wmi_buf_free(buf);
2110
2111 return cdf_status;
2112}
2113
2114/**
2115 * wma_process_roam_scan_req() - process roam request
2116 * @wma_handle: wma handle
2117 * @roam_req: roam request parameters
2118 *
2119 * Main routine to handle ROAM commands coming from CSR module.
2120 *
2121 * Return: CDF status
2122 */
2123CDF_STATUS wma_process_roam_scan_req(tp_wma_handle wma_handle,
2124 tSirRoamOffloadScanReq *roam_req)
2125{
2126 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
2127 wmi_start_scan_cmd_fixed_param scan_params;
2128 wmi_ap_profile ap_profile;
2129 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
2130 uint32_t mode = 0;
2131 struct wma_txrx_node *intr = NULL;
2132
2133 WMA_LOGI("%s: command 0x%x, reason %d", __func__, roam_req->Command,
2134 roam_req->reason);
2135
2136 if (NULL == pMac) {
2137 WMA_LOGE("%s: pMac is NULL", __func__);
2138 return CDF_STATUS_E_FAILURE;
2139 }
2140
2141 if (!wma_handle->roam_offload_enabled) {
2142 /* roam scan offload is not enabled in firmware.
2143 * Cannot initialize it in the middle of connection.
2144 */
2145 cdf_mem_free(roam_req);
2146 return CDF_STATUS_E_PERM;
2147 }
2148 switch (roam_req->Command) {
2149 case ROAM_SCAN_OFFLOAD_START:
2150 intr = &wma_handle->interfaces[roam_req->sessionId];
2151 intr->delay_before_vdev_stop = roam_req->delay_before_vdev_stop;
2152 /*
2153 * Scan/Roam threshold parameters are translated from fields of
2154 * tSirRoamOffloadScanReq to WMITLV values sent to Rome firmware.
2155 * some of these parameters are configurable in qcom_cfg.ini file.
2156 */
2157
2158 /* First parameter is positive rssi value to trigger rssi based scan.
2159 * Opportunistic scan is started at 30 dB higher that trigger rssi.
2160 */
2161 wma_handle->suitable_ap_hb_failure = false;
2162
2163 cdf_status = wma_roam_scan_offload_rssi_thresh(wma_handle,
2164 roam_req);
2165 if (cdf_status != CDF_STATUS_SUCCESS)
2166 break;
2167 cdf_status = wma_roam_scan_bmiss_cnt(wma_handle,
2168 roam_req->RoamBmissFirstBcnt,
2169 roam_req->RoamBmissFinalBcnt,
2170 roam_req->sessionId);
2171 if (cdf_status != CDF_STATUS_SUCCESS)
2172 break;
2173
2174 /* Opportunistic scan runs on a timer, value set by
2175 * EmptyRefreshScanPeriod. Age out the entries after 3 such
2176 * cycles.
2177 */
2178 if (roam_req->EmptyRefreshScanPeriod > 0) {
2179 cdf_status =
2180 wma_roam_scan_offload_scan_period(wma_handle,
2181 roam_req->EmptyRefreshScanPeriod,
2182 roam_req->EmptyRefreshScanPeriod * 3,
2183 roam_req->sessionId);
2184 if (cdf_status != CDF_STATUS_SUCCESS)
2185 break;
2186
2187 mode = WMI_ROAM_SCAN_MODE_PERIODIC;
2188 /* Don't use rssi triggered roam scans if external app
2189 * is in control of channel list.
2190 */
2191 if (roam_req->ChannelCacheType != CHANNEL_LIST_STATIC)
2192 mode |= WMI_ROAM_SCAN_MODE_RSSI_CHANGE;
2193
2194 } else {
2195 mode = WMI_ROAM_SCAN_MODE_RSSI_CHANGE;
2196 }
2197
2198 /* Start new rssi triggered scan only if it changes by RoamRssiDiff value.
2199 * Beacon weight of 14 means average rssi is taken over 14 previous samples +
2200 * 2 times the current beacon's rssi.
2201 */
2202 cdf_status = wma_roam_scan_offload_rssi_change(wma_handle,
2203 roam_req->sessionId,
2204 roam_req->RoamRescanRssiDiff,
2205 roam_req->RoamBeaconRssiWeight,
2206 roam_req->hi_rssi_scan_delay);
2207
2208 if (cdf_status != CDF_STATUS_SUCCESS)
2209 break;
2210
2211 wma_roam_scan_fill_ap_profile(wma_handle, pMac, roam_req,
2212 &ap_profile);
2213
2214 cdf_status = wma_roam_scan_offload_ap_profile(wma_handle,
2215 &ap_profile,
2216 roam_req->sessionId);
2217 if (cdf_status != CDF_STATUS_SUCCESS)
2218 break;
2219
2220 cdf_status = wma_roam_scan_offload_chan_list(wma_handle,
2221 roam_req->ConnectedNetwork.ChannelCount,
2222 &roam_req->ConnectedNetwork.ChannelCache[0],
2223 roam_req->ChannelCacheType,
2224 roam_req->sessionId);
2225 if ((cdf_status != CDF_STATUS_SUCCESS) &&
2226 (cdf_status != CDF_STATUS_E_EMPTY))
2227 break;
2228
2229
2230 wma_roam_scan_fill_scan_params(wma_handle, pMac, roam_req,
2231 &scan_params);
2232 cdf_status =
2233 wma_roam_scan_offload_mode(wma_handle, &scan_params,
2234 roam_req, mode,
2235 roam_req->sessionId);
2236 if (cdf_status != CDF_STATUS_SUCCESS)
2237 break;
2238 cdf_status = wma_roam_scan_filter(wma_handle, roam_req);
2239 if (cdf_status != CDF_STATUS_SUCCESS) {
2240 WMA_LOGE("Sending start for roam scan filter failed");
2241 break;
2242 }
2243 break;
2244
2245 case ROAM_SCAN_OFFLOAD_STOP:
2246 wma_handle->suitable_ap_hb_failure = false;
2247 if (wma_handle->roam_offload_enabled) {
2248
2249 wma_roam_scan_fill_scan_params(wma_handle, pMac,
2250 NULL, &scan_params);
2251 cdf_status = wma_roam_scan_offload_mode(wma_handle,
2252 &scan_params,
2253 NULL,
2254 WMI_ROAM_SCAN_MODE_NONE,
2255 roam_req->sessionId);
2256 }
2257 /*
2258 * If the STOP command is due to a disconnect, then
2259 * send the filter command to clear all the filter
2260 * entries. If it is roaming scenario, then do not
2261 * send the cleared entries.
2262 */
2263 if (!roam_req->middle_of_roaming) {
2264 cdf_status = wma_roam_scan_filter(wma_handle, roam_req);
2265 if (cdf_status != CDF_STATUS_SUCCESS) {
2266 WMA_LOGE("clear for roam scan filter failed");
2267 break;
2268 }
2269 }
2270
2271 if (roam_req->reason ==
2272 REASON_OS_REQUESTED_ROAMING_NOW) {
2273 cds_msg_t cds_msg;
2274 tSirRoamOffloadScanRsp *scan_offload_rsp;
2275 scan_offload_rsp =
2276 cdf_mem_malloc(sizeof(*scan_offload_rsp));
2277 if (!scan_offload_rsp) {
2278 WMA_LOGE("%s: Alloc failed for scan_offload_rsp",
2279 __func__);
2280 cdf_mem_free(roam_req);
2281 return CDF_STATUS_E_NOMEM;
2282 }
2283 cds_msg.type = eWNI_SME_ROAM_SCAN_OFFLOAD_RSP;
2284 scan_offload_rsp->sessionId = roam_req->sessionId;
2285 scan_offload_rsp->reason = roam_req->reason;
2286 cds_msg.bodyptr = scan_offload_rsp;
2287 /*
2288 * Since REASSOC request is processed in
2289 * Roam_Scan_Offload_Rsp post a dummy rsp msg back to
2290 * SME with proper reason code.
2291 */
2292 if (CDF_STATUS_SUCCESS !=
2293 cds_mq_post_message(CDS_MQ_ID_SME,
2294 (cds_msg_t *) &cds_msg)) {
2295 cdf_mem_free(scan_offload_rsp);
2296 CDF_TRACE(CDF_MODULE_ID_WMA,
2297 CDF_TRACE_LEVEL_INFO,
2298 "%s: Failed to post Scan Offload Rsp to UMAC",
2299 __func__);
2300 }
2301 }
2302 break;
2303
2304 case ROAM_SCAN_OFFLOAD_ABORT_SCAN:
2305 /* If roam scan is running, stop that cycle.
2306 * It will continue automatically on next trigger.
2307 */
2308 cdf_status = wma_roam_scan_offload_command(wma_handle,
2309 WMI_ROAM_SCAN_STOP_CMD,
2310 roam_req->sessionId);
2311 break;
2312
2313 case ROAM_SCAN_OFFLOAD_RESTART:
2314 /* Rome offload engine does not stop after any scan.
2315 * If this command is sent because all preauth attempts failed
2316 * and WMI_ROAM_REASON_SUITABLE_AP event was received earlier,
2317 * now it is time to call it heartbeat failure.
2318 */
2319 if ((roam_req->reason == REASON_PREAUTH_FAILED_FOR_ALL)
2320 && wma_handle->suitable_ap_hb_failure) {
2321 WMA_LOGE("%s: Sending heartbeat failure after preauth failures",
2322 __func__);
2323 wma_beacon_miss_handler(wma_handle,
2324 roam_req->sessionId);
2325 wma_handle->suitable_ap_hb_failure = false;
2326 }
2327 break;
2328
2329 case ROAM_SCAN_OFFLOAD_UPDATE_CFG:
2330 wma_handle->suitable_ap_hb_failure = false;
2331 wma_roam_scan_fill_scan_params(wma_handle, pMac, roam_req,
2332 &scan_params);
2333 cdf_status =
2334 wma_roam_scan_offload_mode(wma_handle, &scan_params,
2335 roam_req,
2336 WMI_ROAM_SCAN_MODE_NONE,
2337 roam_req->sessionId);
2338 if (cdf_status != CDF_STATUS_SUCCESS)
2339 break;
2340
2341 if (roam_req->RoamScanOffloadEnabled == false)
2342 break;
2343
2344 cdf_status = wma_roam_scan_bmiss_cnt(wma_handle,
2345 roam_req->RoamBmissFirstBcnt,
2346 roam_req->RoamBmissFinalBcnt,
2347 roam_req->sessionId);
2348 if (cdf_status != CDF_STATUS_SUCCESS)
2349 break;
2350 cdf_status = wma_roam_scan_filter(wma_handle, roam_req);
2351 if (cdf_status != CDF_STATUS_SUCCESS) {
2352 WMA_LOGE("Sending update for roam scan filter failed");
2353 break;
2354 }
2355
2356
2357 /*
2358 * Runtime (after association) changes to rssi thresholds and
2359 * other parameters.
2360 */
2361 cdf_status = wma_roam_scan_offload_chan_list(wma_handle,
2362 roam_req->ConnectedNetwork.ChannelCount,
2363 &roam_req->ConnectedNetwork.ChannelCache[0],
2364 roam_req->ChannelCacheType,
2365 roam_req->sessionId);
2366 /*
2367 * Even though the channel list is empty, we can
2368 * still go ahead and start Roaming.
2369 */
2370 if ((cdf_status != CDF_STATUS_SUCCESS) &&
2371 (cdf_status != CDF_STATUS_E_EMPTY))
2372 break;
2373
2374
2375 cdf_status = wma_roam_scan_offload_rssi_thresh(wma_handle,
2376 roam_req);
2377 if (cdf_status != CDF_STATUS_SUCCESS)
2378 break;
2379
2380 if (roam_req->EmptyRefreshScanPeriod > 0) {
2381 cdf_status =
2382 wma_roam_scan_offload_scan_period(wma_handle,
2383 roam_req->EmptyRefreshScanPeriod,
2384 roam_req->EmptyRefreshScanPeriod * 3,
2385 roam_req->sessionId);
2386 if (cdf_status != CDF_STATUS_SUCCESS)
2387 break;
2388
2389 mode = WMI_ROAM_SCAN_MODE_PERIODIC;
2390 /* Don't use rssi triggered roam scans if external app
2391 * is in control of channel list.
2392 */
2393 if (roam_req->ChannelCacheType != CHANNEL_LIST_STATIC)
2394 mode |= WMI_ROAM_SCAN_MODE_RSSI_CHANGE;
2395
2396 } else {
2397 mode = WMI_ROAM_SCAN_MODE_RSSI_CHANGE;
2398 }
2399
2400 cdf_status = wma_roam_scan_offload_rssi_change(wma_handle,
2401 roam_req->sessionId,
2402 roam_req->RoamRescanRssiDiff,
2403 roam_req->RoamBeaconRssiWeight,
2404 roam_req->hi_rssi_scan_delay);
2405 if (cdf_status != CDF_STATUS_SUCCESS)
2406 break;
2407
2408 wma_roam_scan_fill_ap_profile(wma_handle, pMac, roam_req,
2409 &ap_profile);
2410 cdf_status =
2411 wma_roam_scan_offload_ap_profile(wma_handle, &ap_profile,
2412 roam_req->sessionId);
2413 if (cdf_status != CDF_STATUS_SUCCESS)
2414 break;
2415
2416 wma_roam_scan_fill_scan_params(wma_handle, pMac, roam_req,
2417 &scan_params);
2418 cdf_status =
2419 wma_roam_scan_offload_mode(wma_handle, &scan_params,
2420 roam_req, mode,
2421 roam_req->sessionId);
2422
2423 break;
2424
2425 default:
2426 break;
2427 }
2428 cdf_mem_free(roam_req);
2429 return cdf_status;
2430}
2431
2432/**
2433 * wma_roam_preauth_chan_set() - set preauth channel
2434 * @wma_handle: wma handle
2435 * @params: switch channel params
2436 * @vdev_id: vdev id
2437 *
2438 * Send a single channel passive scan request
2439 * to handle set_channel operation for preauth
2440 *
2441 * Return: CDF atatus
2442 */
2443CDF_STATUS wma_roam_preauth_chan_set(tp_wma_handle wma_handle,
2444 tpSwitchChannelParams params,
2445 uint8_t vdev_id)
2446{
2447 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
2448 tSirScanOffloadReq scan_req;
2449 uint8_t bssid[IEEE80211_ADDR_LEN] = {
2450 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2451
2452 WMA_LOGI("%s: channel %d", __func__, params->channelNumber);
2453
2454 /* Check for prior operation in progress */
2455 if (wma_handle->roam_preauth_chan_context != NULL) {
2456 cdf_status = CDF_STATUS_E_FAILURE;
2457 WMA_LOGE("%s: Rejected request. Previous operation in progress",
2458 __func__);
2459 goto send_resp;
2460 }
2461 wma_handle->roam_preauth_chan_context = params;
2462
2463 /* Prepare a dummy scan request and get the
2464 * wmi_start_scan_cmd_fixed_param structure filled properly
2465 */
2466 cdf_mem_zero(&scan_req, sizeof(scan_req));
2467 cdf_copy_macaddr((struct cdf_mac_addr *) &scan_req.bssId,
2468 (struct cdf_mac_addr *) bssid);
2469 cdf_copy_macaddr((struct cdf_mac_addr *) &scan_req.selfMacAddr,
2470 (struct cdf_mac_addr *) &params->selfStaMacAddr);
2471 scan_req.channelList.numChannels = 1;
2472 scan_req.channelList.channelNumber[0] = params->channelNumber;
2473 scan_req.numSsid = 0;
2474 scan_req.minChannelTime = WMA_ROAM_PREAUTH_SCAN_TIME;
2475 scan_req.maxChannelTime = WMA_ROAM_PREAUTH_SCAN_TIME;
2476 scan_req.scanType = eSIR_PASSIVE_SCAN;
2477 scan_req.p2pScanType = P2P_SCAN_TYPE_LISTEN;
2478 scan_req.sessionId = vdev_id;
2479 wma_get_scan_id(&scan_req.scan_id);
2480 wma_handle->roam_preauth_chanfreq =
2481 cds_chan_to_freq(params->channelNumber);
2482
2483 /* set the state in advance before calling wma_start_scan and be ready
2484 * to handle scan events from firmware. Otherwise print statments
2485 * in wma_start_can create a race condition.
2486 */
2487 wma_handle->roam_preauth_scan_state = WMA_ROAM_PREAUTH_CHAN_REQUESTED;
2488 cdf_status = wma_start_scan(wma_handle, &scan_req, WMA_CHNL_SWITCH_REQ);
2489
2490 if (cdf_status == CDF_STATUS_SUCCESS)
2491 return cdf_status;
2492 wma_handle->roam_preauth_scan_state = WMA_ROAM_PREAUTH_CHAN_NONE;
2493 /* Failed operation. Safely clear context */
2494 wma_handle->roam_preauth_chan_context = NULL;
2495
2496send_resp:
2497 WMA_LOGI("%s: sending WMA_SWITCH_CHANNEL_RSP, status = 0x%x",
2498 __func__, cdf_status);
2499 params->chainMask = wma_handle->pdevconfig.txchainmask;
2500 params->smpsMode = SMPS_MODE_DISABLED;
2501 params->status = cdf_status;
2502 wma_send_msg(wma_handle, WMA_SWITCH_CHANNEL_RSP, (void *)params, 0);
2503 return cdf_status;
2504}
2505
2506/**
2507 * wma_roam_preauth_chan_cancel() - cancel preauth scan
2508 * @wma_handle: wma handle
2509 * @params: switch channel parameters
2510 * @vdev_id: vdev id
2511 *
2512 * Return: CDF status
2513 */
2514CDF_STATUS wma_roam_preauth_chan_cancel(tp_wma_handle wma_handle,
2515 tpSwitchChannelParams params,
2516 uint8_t vdev_id)
2517{
2518 tAbortScanParams abort_scan_req;
2519 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
2520
2521 WMA_LOGI("%s: channel %d", __func__, params->channelNumber);
2522 /* Check for prior operation in progress */
2523 if (wma_handle->roam_preauth_chan_context != NULL) {
2524 cdf_status = CDF_STATUS_E_FAILURE;
2525 WMA_LOGE("%s: Rejected request. Previous operation in progress",
2526 __func__);
2527 goto send_resp;
2528 }
2529 wma_handle->roam_preauth_chan_context = params;
2530
2531 abort_scan_req.SessionId = vdev_id;
2532 wma_handle->roam_preauth_scan_state =
2533 WMA_ROAM_PREAUTH_CHAN_CANCEL_REQUESTED;
2534 cdf_status = wma_stop_scan(wma_handle, &abort_scan_req);
2535 if (cdf_status == CDF_STATUS_SUCCESS)
2536 return cdf_status;
2537 /* Failed operation. Safely clear context */
2538 wma_handle->roam_preauth_chan_context = NULL;
2539
2540send_resp:
2541 WMA_LOGI("%s: sending WMA_SWITCH_CHANNEL_RSP, status = 0x%x",
2542 __func__, cdf_status);
2543 params->chainMask = wma_handle->pdevconfig.txchainmask;
2544 params->smpsMode = SMPS_MODE_DISABLED;
2545 params->status = cdf_status;
2546 wma_send_msg(wma_handle, WMA_SWITCH_CHANNEL_RSP, (void *)params, 0);
2547 return cdf_status;
2548}
2549
2550/**
2551 * wma_roam_preauth_scan_event_handler() - preauth scan event handler
2552 * @wma_handle: wma handle
2553 * @vdev_id: vdev id
2554 * @wmi_event: event data
2555 *
2556 * This function handles preauth scan event and send appropriate
2557 * message to upper layers.
2558 *
2559 * Return: none
2560 */
2561void wma_roam_preauth_scan_event_handler(tp_wma_handle wma_handle,
2562 uint8_t vdev_id,
2563 wmi_scan_event_fixed_param *
2564 wmi_event)
2565{
2566 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
2567 tSwitchChannelParams *params;
2568
2569 WMA_LOGI("%s: preauth_scan_state %d, event 0x%x, reason 0x%x",
2570 __func__, wma_handle->roam_preauth_scan_state,
2571 wmi_event->event, wmi_event->reason);
2572 switch (wma_handle->roam_preauth_scan_state) {
2573 case WMA_ROAM_PREAUTH_CHAN_REQUESTED:
2574 if (wmi_event->event & WMI_SCAN_EVENT_FOREIGN_CHANNEL) {
2575 /* complete set_chan request */
2576 wma_handle->roam_preauth_scan_state =
2577 WMA_ROAM_PREAUTH_ON_CHAN;
2578 cdf_status = CDF_STATUS_SUCCESS;
2579 } else if (wmi_event->event & WMI_SCAN_FINISH_EVENTS) {
2580 /* Failed to get preauth channel or finished (unlikely) */
2581 wma_handle->roam_preauth_scan_state =
2582 WMA_ROAM_PREAUTH_CHAN_NONE;
2583 cdf_status = CDF_STATUS_E_FAILURE;
2584 } else
2585 return;
2586 break;
2587 case WMA_ROAM_PREAUTH_CHAN_CANCEL_REQUESTED:
2588 /* Completed or cancelled, complete set_chan cancel request */
2589 wma_handle->roam_preauth_scan_state =
2590 WMA_ROAM_PREAUTH_CHAN_NONE;
2591 break;
2592
2593 case WMA_ROAM_PREAUTH_ON_CHAN:
2594 if ((wmi_event->event & WMI_SCAN_EVENT_BSS_CHANNEL) ||
2595 (wmi_event->event & WMI_SCAN_FINISH_EVENTS))
2596 wma_handle->roam_preauth_scan_state =
2597 WMA_ROAM_PREAUTH_CHAN_COMPLETED;
2598
2599 /* There is no WMA request to complete. Next set channel request will
2600 * look at this state and complete it.
2601 */
2602 break;
2603 default:
2604 WMA_LOGE("%s: unhandled event 0x%x, reason 0x%x",
2605 __func__, wmi_event->event, wmi_event->reason);
2606 return;
2607 }
2608
2609 params = (tpSwitchChannelParams) wma_handle->roam_preauth_chan_context;
2610 if (params) {
2611 WMA_LOGI("%s: sending WMA_SWITCH_CHANNEL_RSP, status = 0x%x",
2612 __func__, cdf_status);
2613 params->chainMask = wma_handle->pdevconfig.txchainmask;
2614 params->smpsMode = SMPS_MODE_DISABLED;
2615 params->status = cdf_status;
2616 wma_send_msg(wma_handle, WMA_SWITCH_CHANNEL_RSP, (void *)params,
2617 0);
2618 wma_handle->roam_preauth_chan_context = NULL;
2619 }
2620
2621}
2622
2623#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2624
2625/**
2626 * wma_process_roam_invoke() - send roam invoke command to fw.
2627 * @handle: wma handle
2628 * @roaminvoke: roam invoke command
2629 *
2630 * Send roam invoke command to fw for fastreassoc.
2631 *
2632 * Return: none
2633 */
2634void wma_process_roam_invoke(WMA_HANDLE handle,
2635 struct wma_roam_invoke_cmd *roaminvoke)
2636{
2637 tp_wma_handle wma_handle = (tp_wma_handle) handle;
2638 wmi_roam_invoke_cmd_fixed_param *cmd;
2639 wmi_buf_t wmi_buf;
2640 u_int8_t *buf_ptr;
2641 u_int16_t len, args_tlv_len;
2642 A_UINT32 *channel_list;
2643 wmi_mac_addr *bssid_list;
2644
2645 if (!wma_handle || !wma_handle->wmi_handle) {
2646 WMA_LOGE("%s: WMA is closed, can not send roam invoke",
2647 __func__);
2648 return;
2649 }
2650 /* Host sends only one channel and one bssid */
2651 args_tlv_len = 2 * WMI_TLV_HDR_SIZE + sizeof(A_UINT32) +
2652 sizeof(wmi_mac_addr);
2653 len = sizeof(wmi_roam_invoke_cmd_fixed_param) + args_tlv_len;
2654 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
2655 if (!wmi_buf) {
2656 WMA_LOGE("%s: wmai_buf_alloc failed", __func__);
2657 return;
2658 }
2659
2660 cmd = (wmi_roam_invoke_cmd_fixed_param *)wmi_buf_data(wmi_buf);
2661 buf_ptr = (u_int8_t *) cmd;
2662 WMITLV_SET_HDR(&cmd->tlv_header,
2663 WMITLV_TAG_STRUC_wmi_roam_invoke_cmd_fixed_param,
2664 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_invoke_cmd_fixed_param));
2665 cmd->vdev_id = roaminvoke->vdev_id;
2666 cmd->flags = 0;
2667 cmd->roam_scan_mode = 0;
2668 cmd->roam_ap_sel_mode = 0;
2669 cmd->roam_delay = 0;
2670 cmd->num_chan = 1;
2671 cmd->num_bssid = 1;
2672 buf_ptr += sizeof(wmi_roam_invoke_cmd_fixed_param);
2673 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
2674 (sizeof(u_int32_t)));
2675 channel_list = (A_UINT32 *)(buf_ptr + WMI_TLV_HDR_SIZE);
2676 *channel_list = (A_UINT32)cds_chan_to_freq(roaminvoke->channel);
2677 buf_ptr += sizeof(A_UINT32) + WMI_TLV_HDR_SIZE;
2678 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
2679 (sizeof(wmi_mac_addr)));
2680 bssid_list = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE);
2681 WMI_CHAR_ARRAY_TO_MAC_ADDR(roaminvoke->bssid, bssid_list);
2682 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
2683 WMI_ROAM_INVOKE_CMDID)) {
2684 WMA_LOGP("%s: failed to send roam invoke command", __func__);
2685 wmi_buf_free(wmi_buf);
2686 return;
2687 }
2688 return;
2689}
2690
2691/**
2692 * wma_process_roam_synch_fail() -roam synch failure handle
2693 * @handle: wma handle
2694 * @synch_fail: roam synch fail parameters
2695 *
2696 * Return: none
2697 */
2698void wma_process_roam_synch_fail(WMA_HANDLE handle,
2699 struct roam_offload_synch_fail *synch_fail)
2700{
2701 tp_wma_handle wma_handle = (tp_wma_handle) handle;
2702 if (!wma_handle || !wma_handle->wmi_handle) {
2703 WMA_LOGE("%s: WMA is closed, can not clean-up roam synch",
2704 __func__);
2705 return;
2706 }
2707 /* Hand Off Failure could happen as an exception, when a roam synch
2708 * indication is posted to Host, but a roam synch complete is not
2709 * posted to the firmware.So, clear the roam synch in progress
2710 * flag before disconnecting the session through this event.*/
2711 wma_handle->interfaces[synch_fail->session_id].roam_synch_in_progress =
2712 false;
2713}
2714
2715/**
2716 * wma_roam_synch_event_handler() - roam synch event handler
2717 * @handle: wma handle
2718 * @event: event data
2719 * @len: length of data
2720 *
2721 * This function is roam synch event handler. It sends roam
2722 * indication for upper layer.
2723 */
2724int wma_roam_synch_event_handler(void *handle, uint8_t *event,
2725 uint32_t len)
2726{
2727 WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf = NULL;
2728 wmi_roam_synch_event_fixed_param *synch_event = NULL;
2729 uint8_t *bcn_probersp_ptr = NULL;
2730 uint8_t *reassoc_rsp_ptr = NULL;
2731 tp_wma_handle wma = (tp_wma_handle) handle;
2732 wmi_channel *chan = NULL;
2733 wmi_key_material *key = NULL;
2734 int size = 0;
2735 roam_offload_synch_ind *roam_synch_ind_ptr;
2736
2737 WMA_LOGD("LFR3:%s", __func__);
2738 if (!event) {
2739 WMA_LOGE("%s: event param null", __func__);
2740 return -EINVAL;
2741 }
2742
2743 param_buf = (WMI_ROAM_SYNCH_EVENTID_param_tlvs *) event;
2744 if (!param_buf) {
2745 WMA_LOGE("%s: received null buf from target", __func__);
2746 return -EINVAL;
2747 }
2748
2749 synch_event = param_buf->fixed_param;
2750 if (!synch_event) {
2751 WMA_LOGE("%s: received null event data from target", __func__);
2752 return -EINVAL;
2753 }
2754
2755 if (wma->interfaces[synch_event->vdev_id].roam_synch_in_progress) {
2756 WMA_LOGE("%s: Ignoring RSI since one is already in progress",
2757 __func__);
2758 return -EINVAL;
2759 }
2760 wma->interfaces[synch_event->vdev_id].roam_synch_in_progress = true;
2761 len = sizeof(roam_offload_synch_ind) +
2762 synch_event->bcn_probe_rsp_len + synch_event->reassoc_rsp_len;
2763 roam_synch_ind_ptr =
2764 (roam_offload_synch_ind *) cdf_mem_malloc(len);
2765 if (!roam_synch_ind_ptr) {
2766 WMA_LOGE("%s: failed to allocate memory for roam_synch_event",
2767 __func__);
2768 return -ENOMEM;
2769 }
2770
2771 /* abort existing scan if any */
2772 if (wma->interfaces[synch_event->vdev_id].scan_info.scan_id != 0) {
2773 tAbortScanParams abort_scan;
2774 WMA_LOGD("LFR3: Aborting Scan with scan_id=%d\n",
2775 wma->interfaces[synch_event->vdev_id].scan_info.scan_id);
2776 abort_scan.SessionId = synch_event->vdev_id;
2777 wma_stop_scan(wma, &abort_scan);
2778 }
2779
2780 roam_synch_ind_ptr->messageType = eWNI_SME_ROAM_OFFLOAD_SYNCH_IND;
2781 roam_synch_ind_ptr->length = size;
2782 roam_synch_ind_ptr->roamedVdevId = synch_event->vdev_id;
2783 roam_synch_ind_ptr->authStatus = synch_event->auth_status;
2784 roam_synch_ind_ptr->roamReason = synch_event->roam_reason;
2785 roam_synch_ind_ptr->rssi = synch_event->rssi;
2786 roam_synch_ind_ptr->isBeacon = synch_event->is_beacon;
2787 WMI_MAC_ADDR_TO_CHAR_ARRAY(&synch_event->bssid,
2788 roam_synch_ind_ptr->bssId);
2789 roam_synch_ind_ptr->beaconProbeRespOffset =
2790 sizeof(roam_offload_synch_ind);
2791 bcn_probersp_ptr =
2792 (uint8_t *) roam_synch_ind_ptr +
2793 roam_synch_ind_ptr->beaconProbeRespOffset;
2794 roam_synch_ind_ptr->beaconProbeRespLength =
2795 synch_event->bcn_probe_rsp_len;
2796 cdf_mem_copy(bcn_probersp_ptr, param_buf->bcn_probe_rsp_frame,
2797 roam_synch_ind_ptr->beaconProbeRespLength);
2798 roam_synch_ind_ptr->reassocRespOffset =
2799 sizeof(roam_offload_synch_ind) +
2800 roam_synch_ind_ptr->beaconProbeRespLength;
2801 roam_synch_ind_ptr->reassocRespLength = synch_event->reassoc_rsp_len;
2802 reassoc_rsp_ptr = (uint8_t *) roam_synch_ind_ptr +
2803 roam_synch_ind_ptr->reassocRespOffset;
2804 cdf_mem_copy(reassoc_rsp_ptr,
2805 param_buf->reassoc_rsp_frame,
2806 roam_synch_ind_ptr->reassocRespLength);
2807 chan = (wmi_channel *) param_buf->chan;
2808 roam_synch_ind_ptr->chan_freq = chan->mhz;
2809 key = (wmi_key_material *) param_buf->key;
2810 if (key != NULL) {
2811 CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_DEBUG,
2812 key->replay_counter, SIR_REPLAY_CTR_LEN);
2813 cdf_mem_copy(roam_synch_ind_ptr->kck, key->kck,
2814 SIR_KCK_KEY_LEN);
2815 cdf_mem_copy(roam_synch_ind_ptr->kek, key->kek,
2816 SIR_KEK_KEY_LEN);
2817 cdf_mem_copy(roam_synch_ind_ptr->replay_ctr,
2818 key->replay_counter, SIR_REPLAY_CTR_LEN);
2819 }
2820 wma_send_msg(wma, WMA_ROAM_OFFLOAD_SYNCH_IND,
2821 (void *) roam_synch_ind_ptr, 0);
2822 return 0;
2823}
2824
2825/**
2826 * wma_rssi_breached_event_handler() - rssi breached event handler
2827 * @handle: wma handle
2828 * @cmd_param_info: event handler data
2829 * @len: length of @cmd_param_info
2830 *
2831 * Return: 0 on success; error number otherwise
2832 */
2833int wma_rssi_breached_event_handler(void *handle,
2834 u_int8_t *cmd_param_info, u_int32_t len)
2835{
2836 WMI_RSSI_BREACH_EVENTID_param_tlvs *param_buf;
2837 wmi_rssi_breach_event_fixed_param *event;
2838 struct rssi_breach_event rssi;
2839 tpAniSirGlobal mac = cds_get_context(CDF_MODULE_ID_PE);
2840
2841 if (!mac) {
2842 WMA_LOGE("%s: Invalid mac context", __func__);
2843 return -EINVAL;
2844 }
2845 if (!mac->sme.rssi_threshold_breached_cb) {
2846 WMA_LOGE("%s: Callback not registered", __func__);
2847 return -EINVAL;
2848 }
2849 param_buf = (WMI_RSSI_BREACH_EVENTID_param_tlvs *)cmd_param_info;
2850 if (!param_buf) {
2851 WMA_LOGE("%s: Invalid rssi breached event", __func__);
2852 return -EINVAL;
2853 }
2854 event = param_buf->fixed_param;
2855
2856 rssi.request_id = event->request_id;
2857 rssi.session_id = event->vdev_id;
2858 rssi.curr_rssi = event->rssi + WMA_TGT_NOISE_FLOOR_DBM;
2859 WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->bssid, rssi.curr_bssid.bytes);
2860
2861 WMA_LOGD("%s: req_id: %u vdev_id: %d curr_rssi: %d", __func__,
2862 rssi.request_id, rssi.session_id, rssi.curr_rssi);
2863 WMA_LOGI("%s: curr_bssid: %pM", __func__, rssi.curr_bssid.bytes);
2864
2865 mac->sme.rssi_threshold_breached_cb(mac->hHdd, &rssi);
2866 WMA_LOGD("%s: Invoke HDD rssi breached callback", __func__);
2867 return 0;
2868}
2869
2870/**
2871 * wma_roam_scan_fill_self_caps() - fill capabilities
2872 * @wma_handle: wma handle
2873 * @roam_offload_params: offload parameters
2874 * @roam_req: roam request
2875 *
2876 * This function fills roam self capablities.
2877 *
2878 * Return: CDF status
2879 */
2880CDF_STATUS wma_roam_scan_fill_self_caps(tp_wma_handle wma_handle,
2881 wmi_roam_offload_tlv_param *
2882 roam_offload_params,
2883 tSirRoamOffloadScanReq *roam_req)
2884{
2885 struct sAniSirGlobal *pMac = NULL;
2886 tSirMacCapabilityInfo selfCaps;
2887 uint32_t val = 0;
2888 uint32_t nCfgValue;
2889 uint16_t *pCfgValue16;
2890 uint8_t nCfgValue8, *pCfgValue8;
2891 tSirMacQosInfoStation macQosInfoSta;
2892 union {
2893 uint16_t nCfgValue16;
2894 tSirMacHTCapabilityInfo htCapInfo;
2895 tSirMacExtendedHTCapabilityInfo extHtCapInfo;
2896 } uHTCapabilityInfo;
2897
2898 cdf_mem_set(&macQosInfoSta, sizeof(tSirMacQosInfoStation), 0);
2899 /* Roaming is done only for INFRA STA type.
2900 * So, ess will be one and ibss will be Zero */
2901 pMac = cds_get_context(CDF_MODULE_ID_PE);
2902 if (!pMac) {
2903 WMA_LOGE("%s:NULL pMac ptr. Exiting", __func__);
2904 CDF_ASSERT(0);
2905 return CDF_STATUS_E_FAILURE;
2906 }
2907
2908 if (wlan_cfg_get_int(pMac, WNI_CFG_PRIVACY_ENABLED, &val) != eSIR_SUCCESS) {
2909 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
2910 "Failed to get WNI_CFG_PRIVACY_ENABLED");
2911 return CDF_STATUS_E_FAILURE;
2912 }
2913 selfCaps.ess = 1;
2914 selfCaps.ibss = 0;
2915 if (val)
2916 selfCaps.privacy = 1;
2917 if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS) {
2918 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
2919 "Failed to get WNI_CFG_SHORT_PREAMBLE");
2920 return CDF_STATUS_E_FAILURE;
2921 }
2922 if (val)
2923 selfCaps.shortPreamble = 1;
2924
2925 selfCaps.pbcc = 0;
2926 selfCaps.channelAgility = 0;
2927 if (wlan_cfg_get_int(pMac, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED,
2928 &val) != eSIR_SUCCESS) {
2929 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
2930 "Failed to get WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED");
2931 return CDF_STATUS_E_FAILURE;
2932 }
2933 if (val)
2934 selfCaps.shortSlotTime = 1;
2935 if (wlan_cfg_get_int(pMac, WNI_CFG_11H_ENABLED, &val) != eSIR_SUCCESS) {
2936 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
2937 "Failed to get WNI_CFG_11H_ENABLED");
2938 return CDF_STATUS_E_FAILURE;
2939 }
2940 if (val)
2941 selfCaps.spectrumMgt = 1;
2942 if (wlan_cfg_get_int(pMac, WNI_CFG_QOS_ENABLED, &val) != eSIR_SUCCESS) {
2943 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
2944 "Failed to get WNI_CFG_QOS_ENABLED");
2945 return CDF_STATUS_E_FAILURE;
2946 }
2947 if (val)
2948 selfCaps.qos = 1;
2949 if (wlan_cfg_get_int(pMac, WNI_CFG_APSD_ENABLED, &val) != eSIR_SUCCESS) {
2950 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
2951 "Failed to get WNI_CFG_APSD_ENABLED");
2952 return CDF_STATUS_E_FAILURE;
2953 }
2954 if (val)
2955 selfCaps.apsd = 1;
Krishna Kumaar Natarajan4340c682015-11-03 12:09:00 -08002956
2957 selfCaps.rrm = pMac->rrm.rrmSmeContext.rrmConfig.rrm_enabled;
2958
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002959 if (wlan_cfg_get_int(pMac, WNI_CFG_BLOCK_ACK_ENABLED, &val) !=
2960 eSIR_SUCCESS) {
2961 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
2962 "Failed to get WNI_CFG_BLOCK_ACK_ENABLED");
2963 return CDF_STATUS_E_FAILURE;
2964 }
2965 selfCaps.delayedBA =
2966 (uint16_t) ((val >> WNI_CFG_BLOCK_ACK_ENABLED_DELAYED) & 1);
2967 selfCaps.immediateBA =
2968 (uint16_t) ((val >> WNI_CFG_BLOCK_ACK_ENABLED_IMMEDIATE) & 1);
2969 pCfgValue16 = (uint16_t *) &selfCaps;
2970 roam_offload_params->capability = (*pCfgValue16) & 0xFFFF;
2971
2972 if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &nCfgValue) !=
2973 eSIR_SUCCESS) {
2974 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
2975 "Failed to get WNI_CFG_HT_CAP_INFO");
2976 return CDF_STATUS_E_FAILURE;
2977 }
2978 uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF;
2979 roam_offload_params->ht_caps_info =
2980 uHTCapabilityInfo.nCfgValue16 & 0xFFFF;
2981 if (wlan_cfg_get_int(pMac, WNI_CFG_HT_AMPDU_PARAMS, &nCfgValue) !=
2982 eSIR_SUCCESS) {
2983 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
2984 "Failed to get WNI_CFG_HT_AMPDU_PARAMS");
2985 return CDF_STATUS_E_FAILURE;
2986 }
2987 /* tSirMacHTParametersInfo */
2988 nCfgValue8 = (uint8_t) nCfgValue;
2989 roam_offload_params->ampdu_param = (nCfgValue8) & 0xFF;
2990
2991 val = ROAM_OFFLOAD_NUM_MCS_SET;
2992 if (wlan_cfg_get_str(pMac, WNI_CFG_SUPPORTED_MCS_SET,
2993 (uint8_t *) roam_offload_params->mcsset,
2994 &val) != eSIR_SUCCESS) {
2995 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
2996 "Failed to get WNI_CFG_SUPPORTED_MCS_SET");
2997 return CDF_STATUS_E_FAILURE;
2998 }
2999 if (wlan_cfg_get_int(pMac, WNI_CFG_EXT_HT_CAP_INFO, &nCfgValue) !=
3000 eSIR_SUCCESS) {
3001 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
3002 "Failed to get WNI_CFG_EXT_HT_CAP_INFO");
3003 return CDF_STATUS_E_FAILURE;
3004 }
3005 /* uHTCapabilityInfo.extHtCapInfo */
3006 uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF;
3007 roam_offload_params->ht_ext_cap =
3008 uHTCapabilityInfo.nCfgValue16 & 0xFFFF;
3009
3010 if (wlan_cfg_get_int(pMac, WNI_CFG_TX_BF_CAP, &nCfgValue) != eSIR_SUCCESS) {
3011 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
3012 "Failed to get WNI_CFG_TX_BF_CAP");
3013 return CDF_STATUS_E_FAILURE;
3014 }
3015 /* tSirMacTxBFCapabilityInfo */
3016 nCfgValue8 = (uint8_t) nCfgValue;
3017 roam_offload_params->ht_txbf = nCfgValue8 & 0xFF;
3018 if (wlan_cfg_get_int(pMac, WNI_CFG_AS_CAP, &nCfgValue) != eSIR_SUCCESS) {
3019 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
3020 "Failed to get WNI_CFG_AS_CAP");
3021 return CDF_STATUS_E_FAILURE;
3022 }
3023 /* tSirMacASCapabilityInfo */
3024 nCfgValue8 = (uint8_t) nCfgValue;
3025 roam_offload_params->asel_cap = nCfgValue8 & 0xFF;
3026
3027 /* QOS Info */
3028 if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_SP_LENGTH, &nCfgValue) !=
3029 eSIR_SUCCESS) {
3030 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
3031 "Failed to get WNI_CFG_MAX_SP_LENGTH");
3032 return CDF_STATUS_E_FAILURE;
3033 }
3034 nCfgValue8 = (uint8_t) nCfgValue;
3035 macQosInfoSta.maxSpLen = nCfgValue8;
3036 macQosInfoSta.moreDataAck = 0;
3037 macQosInfoSta.qack = 0;
3038 macQosInfoSta.acbe_uapsd = roam_req->AcUapsd.acbe_uapsd;
3039 macQosInfoSta.acbk_uapsd = roam_req->AcUapsd.acbk_uapsd;
3040 macQosInfoSta.acvi_uapsd = roam_req->AcUapsd.acvi_uapsd;
3041 macQosInfoSta.acvo_uapsd = roam_req->AcUapsd.acvo_uapsd;
3042 pCfgValue8 = (uint8_t *) &macQosInfoSta;
3043 /* macQosInfoSta Only queue_request is set.Refer to
3044 * populate_dot11f_wmm_caps for more details
3045 */
3046 roam_offload_params->qos_caps = (*pCfgValue8) & 0xFF;
3047 roam_offload_params->wmm_caps = 0x4 & 0xFF;
3048 return CDF_STATUS_SUCCESS;
3049}
3050
3051/**
3052 * wma_set_ric_req() - set ric request element
3053 * @wma: wma handle
3054 * @msg: message
3055 * @is_add_ts: is addts required
3056 *
3057 * This function sets ric request element for 11r roaming.
3058 *
3059 * Return: none
3060 */
3061void wma_set_ric_req(tp_wma_handle wma, void *msg, uint8_t is_add_ts)
3062{
3063 wmi_ric_request_fixed_param *cmd;
3064 wmi_ric_tspec *tspec_param;
3065 wmi_buf_t buf;
3066 uint8_t *buf_ptr;
3067 tSirMacTspecIE *ptspecIE;
3068 int32_t len = sizeof(wmi_ric_request_fixed_param) +
3069 WMI_TLV_HDR_SIZE + sizeof(wmi_ric_tspec);
3070
3071 buf = wmi_buf_alloc(wma->wmi_handle, len);
3072 if (!buf) {
3073 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
3074 return;
3075 }
3076
3077 buf_ptr = (uint8_t *) wmi_buf_data(buf);
3078
3079 cmd = (wmi_ric_request_fixed_param *) buf_ptr;
3080 WMITLV_SET_HDR(&cmd->tlv_header,
3081 WMITLV_TAG_STRUC_wmi_ric_request_fixed_param,
3082 WMITLV_GET_STRUCT_TLVLEN(wmi_ric_request_fixed_param));
3083 if (is_add_ts)
3084 cmd->vdev_id = ((tAddTsParams *) msg)->sessionId;
3085 else
3086 cmd->vdev_id = ((tDelTsParams *) msg)->sessionId;
3087 cmd->num_ric_request = 1; /* Today we are sending only 1 ric at once */
3088 cmd->is_add_ric = is_add_ts;
3089
3090 buf_ptr += sizeof(wmi_ric_request_fixed_param);
3091 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, sizeof(wmi_ric_tspec));
3092
3093 buf_ptr += WMI_TLV_HDR_SIZE;
3094 tspec_param = (wmi_ric_tspec *) buf_ptr;
3095 WMITLV_SET_HDR(&tspec_param->tlv_header,
3096 WMITLV_TAG_STRUC_wmi_ric_tspec,
3097 WMITLV_GET_STRUCT_TLVLEN(wmi_ric_tspec));
3098
3099 if (is_add_ts)
3100 ptspecIE = &(((tAddTsParams *) msg)->tspec);
3101 else
3102 ptspecIE = &(((tDelTsParams *) msg)->delTsInfo.tspec);
3103
3104 /* Fill the tsinfo in the format expected by firmware */
3105#ifndef ANI_LITTLE_BIT_ENDIAN
3106 cdf_mem_copy(((uint8_t *) &tspec_param->ts_info) + 1,
3107 ((uint8_t *) &ptspecIE->tsinfo) + 1, 2);
3108#else
3109 cdf_mem_copy(((uint8_t *) &tspec_param->ts_info),
3110 ((uint8_t *) &ptspecIE->tsinfo) + 1, 2);
3111#endif /* ANI_LITTLE_BIT_ENDIAN */
3112
3113 tspec_param->nominal_msdu_size = ptspecIE->nomMsduSz;
3114 tspec_param->maximum_msdu_size = ptspecIE->maxMsduSz;
3115 tspec_param->min_service_interval = ptspecIE->minSvcInterval;
3116 tspec_param->max_service_interval = ptspecIE->maxSvcInterval;
3117 tspec_param->inactivity_interval = ptspecIE->inactInterval;
3118 tspec_param->suspension_interval = ptspecIE->suspendInterval;
3119 tspec_param->svc_start_time = ptspecIE->svcStartTime;
3120 tspec_param->min_data_rate = ptspecIE->minDataRate;
3121 tspec_param->mean_data_rate = ptspecIE->meanDataRate;
3122 tspec_param->peak_data_rate = ptspecIE->peakDataRate;
3123 tspec_param->max_burst_size = ptspecIE->maxBurstSz;
3124 tspec_param->delay_bound = ptspecIE->delayBound;
3125 tspec_param->min_phy_rate = ptspecIE->minPhyRate;
3126 tspec_param->surplus_bw_allowance = ptspecIE->surplusBw;
3127 tspec_param->medium_time = 0;
3128
3129 WMA_LOGI("%s: Set RIC Req is_add_ts:%d", __func__, is_add_ts);
3130
3131 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3132 WMI_ROAM_SET_RIC_REQUEST_CMDID)) {
3133 WMA_LOGP("%s: Failed to send vdev Set RIC Req command",
3134 __func__);
3135 if (is_add_ts)
3136 ((tAddTsParams *) msg)->status = CDF_STATUS_E_FAILURE;
3137 cdf_nbuf_free(buf);
3138 }
3139}
3140#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
3141
3142/**
3143 * wma_process_unit_test_cmd() - send unit test command to fw.
3144 * @handle: wma handle
3145 * @wma_utest: unit test command
3146 *
3147 * This function send unit test command to fw.
3148 *
3149 * Return: none
3150 */
3151void wma_process_unit_test_cmd(WMA_HANDLE handle,
3152 t_wma_unit_test_cmd *wma_utest)
3153{
3154 tp_wma_handle wma_handle = (tp_wma_handle) handle;
3155 wmi_unit_test_cmd_fixed_param *cmd;
3156 wmi_buf_t wmi_buf;
3157 uint8_t *buf_ptr;
3158 int i;
3159 uint16_t len, args_tlv_len;
3160 A_UINT32 *unit_test_cmd_args;
3161
3162 args_tlv_len =
3163 WMI_TLV_HDR_SIZE + wma_utest->num_args * sizeof(A_UINT32);
3164 len = sizeof(wmi_unit_test_cmd_fixed_param) + args_tlv_len;
3165 if (!wma_handle || !wma_handle->wmi_handle) {
3166 WMA_LOGE("%s: WMA is closed, can not issue fw unit test cmd",
3167 __func__);
3168 return;
3169 }
3170 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
3171 if (!wmi_buf) {
3172 WMA_LOGE("%s: wmai_buf_alloc failed", __func__);
3173 return;
3174 }
3175
3176 cmd = (wmi_unit_test_cmd_fixed_param *) wmi_buf_data(wmi_buf);
3177 buf_ptr = (uint8_t *) cmd;
3178 WMITLV_SET_HDR(&cmd->tlv_header,
3179 WMITLV_TAG_STRUC_wmi_unit_test_cmd_fixed_param,
3180 WMITLV_GET_STRUCT_TLVLEN(wmi_unit_test_cmd_fixed_param));
3181 cmd->vdev_id = wma_utest->vdev_id;
3182 cmd->module_id = wma_utest->module_id;
3183 cmd->num_args = wma_utest->num_args;
3184 buf_ptr += sizeof(wmi_unit_test_cmd_fixed_param);
3185 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
3186 (wma_utest->num_args * sizeof(uint32_t)));
3187 unit_test_cmd_args = (A_UINT32 *) (buf_ptr + WMI_TLV_HDR_SIZE);
3188 WMA_LOGI("%s: %d num of args = ", __func__, wma_utest->num_args);
3189 for (i = 0; (i < wma_utest->num_args && i < WMA_MAX_NUM_ARGS); i++) {
3190 unit_test_cmd_args[i] = wma_utest->args[i];
3191 WMA_LOGI("%d,", wma_utest->args[i]);
3192 }
3193 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
3194 WMI_UNIT_TEST_CMDID)) {
3195 WMA_LOGP("%s: failed to send unit test command", __func__);
3196 cdf_nbuf_free(wmi_buf);
3197 return;
3198 }
3199 return;
3200}
3201
3202#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3203
3204/**
3205 * wma_roam_ho_fail_handler() - LFR3.0 roam hand off failed handler
3206 * @wma: wma handle
3207 * @vdev_id: vdev id
3208 *
3209 * Return: none
3210 */
3211static void wma_roam_ho_fail_handler(tp_wma_handle wma, uint32_t vdev_id)
3212{
3213 tSirSmeHOFailureInd *ho_failure_ind;
3214 cds_msg_t sme_msg = { 0 };
3215 CDF_STATUS cdf_status;
3216
3217 ho_failure_ind = cdf_mem_malloc(sizeof(tSirSmeHOFailureInd));
3218
3219 if (NULL == ho_failure_ind) {
3220 WMA_LOGE("%s: Memory allocation failure", __func__);
3221 return;
3222 }
3223 ho_failure_ind->sessionId = vdev_id;
3224 sme_msg.type = eWNI_SME_HO_FAIL_IND;
3225 sme_msg.bodyptr = ho_failure_ind;
3226 sme_msg.bodyval = 0;
3227
3228 cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg);
3229 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
3230 WMA_LOGE("Fail to post eWNI_SME_HO_FAIL_IND msg to SME");
3231 cdf_mem_free(ho_failure_ind);
3232 return;
3233 }
3234 return;
3235}
3236
3237/**
3238 * wma_process_roam_synch_complete() - roam synch complete command to fw.
3239 * @handle: wma handle
3240 * @synchcnf: offload synch confirmation params
3241 *
3242 * This function sends roam synch complete event to fw.
3243 *
3244 * Return: none
3245 */
3246void wma_process_roam_synch_complete(WMA_HANDLE handle,
3247 tSirSmeRoamOffloadSynchCnf *synchcnf)
3248{
3249 tp_wma_handle wma_handle = (tp_wma_handle) handle;
3250 wmi_roam_synch_complete_fixed_param *cmd;
3251 wmi_buf_t wmi_buf;
3252 uint8_t *buf_ptr;
3253 uint16_t len;
3254 bool roam_synch_in_progress;
3255 len = sizeof(wmi_roam_synch_complete_fixed_param);
3256
3257 if (!wma_handle || !wma_handle->wmi_handle) {
3258 WMA_LOGE("%s: WMA is closed, can not issue roam synch cnf",
3259 __func__);
3260 return;
3261 }
3262 roam_synch_in_progress =
3263 wma_handle->interfaces[synchcnf->sessionId].roam_synch_in_progress;
3264 if (roam_synch_in_progress == false) {
3265 WMA_LOGE("%s: Dont send roam synch complete", __func__);
3266 return;
3267 } else {
3268 wma_handle->interfaces[synchcnf->sessionId].roam_synch_in_progress =
3269 false;
3270 }
3271 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
3272 if (!wmi_buf) {
3273 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
3274 return;
3275 }
3276 cmd = (wmi_roam_synch_complete_fixed_param *) wmi_buf_data(wmi_buf);
3277 buf_ptr = (uint8_t *) cmd;
3278 WMITLV_SET_HDR(&cmd->tlv_header,
3279 WMITLV_TAG_STRUC_wmi_roam_synch_complete_fixed_param,
3280 WMITLV_GET_STRUCT_TLVLEN
3281 (wmi_roam_synch_complete_fixed_param));
3282 cmd->vdev_id = synchcnf->sessionId;
3283 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
3284 WMI_ROAM_SYNCH_COMPLETE)) {
3285 WMA_LOGP("%s: failed to send roam synch confirmation",
3286 __func__);
3287 cdf_nbuf_free(wmi_buf);
3288 return;
3289 }
3290 return;
3291}
3292#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
3293
3294/**
3295 * wma_set_channel() - set channel
3296 * @wma: wma handle
3297 * @params: switch channel parameters
3298 *
3299 * Return: none
3300 */
3301void wma_set_channel(tp_wma_handle wma, tpSwitchChannelParams params)
3302{
3303 struct wma_vdev_start_req req;
3304 struct wma_target_req *msg;
3305 CDF_STATUS status = CDF_STATUS_SUCCESS;
3306 uint8_t vdev_id, peer_id;
3307 ol_txrx_peer_handle peer;
3308 ol_txrx_pdev_handle pdev;
3309 struct wma_txrx_node *intr = wma->interfaces;
3310 struct sir_hw_mode_params hw_mode = {0};
3311
3312 WMA_LOGD("%s: Enter", __func__);
3313 if (!wma_find_vdev_by_addr(wma, params->selfStaMacAddr, &vdev_id)) {
3314 WMA_LOGP("%s: Failed to find vdev id for %pM",
3315 __func__, params->selfStaMacAddr);
3316 status = CDF_STATUS_E_FAILURE;
3317 goto send_resp;
3318 }
3319 pdev = cds_get_context(CDF_MODULE_ID_TXRX);
3320 if (NULL == pdev) {
3321 WMA_LOGE("%s: Failed to get pdev", __func__);
3322 status = CDF_STATUS_E_FAILURE;
3323 goto send_resp;
3324 }
3325
3326 peer = ol_txrx_find_peer_by_addr(pdev, intr[vdev_id].bssid, &peer_id);
3327
3328 /*
3329 * Roam offload feature is currently supported
3330 * only in STA mode. Other modes still require
3331 * to issue a Vdev Start/Vdev Restart for
3332 * channel change.
3333 */
3334 if (((wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA) &&
3335 (wma->interfaces[vdev_id].sub_type == 0)) &&
3336 !wma->interfaces[vdev_id].is_channel_switch) {
3337
3338 if (peer && (peer->state == ol_txrx_peer_state_conn ||
3339 peer->state == ol_txrx_peer_state_auth)) {
3340 /* Trying to change channel while connected
3341 * should not invoke VDEV_START.
3342 * Instead, use start scan command in passive
3343 * mode to park station on that channel
3344 */
3345 WMA_LOGI("%s: calling set_scan, state 0x%x",
3346 __func__, wma->roam_preauth_scan_state);
3347 if (wma->roam_preauth_scan_state ==
3348 WMA_ROAM_PREAUTH_CHAN_NONE) {
3349 /* Is channel change required?
3350 */
3351 if (cds_chan_to_freq(params->channelNumber) !=
3352 wma->interfaces[vdev_id].mhz) {
3353 status = wma_roam_preauth_chan_set(wma,
3354 params,
3355 vdev_id);
3356 /* response will be asynchronous */
3357 return;
3358 }
3359 } else if (wma->roam_preauth_scan_state ==
3360 WMA_ROAM_PREAUTH_CHAN_REQUESTED ||
3361 wma->roam_preauth_scan_state ==
3362 WMA_ROAM_PREAUTH_ON_CHAN) {
3363 status =
3364 wma_roam_preauth_chan_cancel(wma, params,
3365 vdev_id);
3366 /* response will be asynchronous */
3367 return;
3368 } else if (wma->roam_preauth_scan_state ==
3369 WMA_ROAM_PREAUTH_CHAN_COMPLETED) {
3370 /* Already back on home channel. Complete the request */
3371 wma->roam_preauth_scan_state =
3372 WMA_ROAM_PREAUTH_CHAN_NONE;
3373 status = CDF_STATUS_SUCCESS;
3374 }
3375 goto send_resp;
3376 }
3377 }
3378 cdf_mem_zero(&req, sizeof(req));
3379 req.vdev_id = vdev_id;
3380 msg = wma_fill_vdev_req(wma, req.vdev_id, WMA_CHNL_SWITCH_REQ,
3381 WMA_TARGET_REQ_TYPE_VDEV_START, params,
3382 WMA_VDEV_START_REQUEST_TIMEOUT);
3383 if (!msg) {
3384 WMA_LOGP("%s: Failed to fill channel switch request for vdev %d",
3385 __func__, req.vdev_id);
3386 status = CDF_STATUS_E_NOMEM;
3387 goto send_resp;
3388 }
3389 req.chan = params->channelNumber;
3390 req.chan_width = params->ch_width;
3391 req.vht_capable = params->vhtCapable;
3392 req.ch_center_freq_seg0 = params->ch_center_freq_seg0;
3393 req.ch_center_freq_seg1 = params->ch_center_freq_seg1;
3394 req.dot11_mode = params->dot11_mode;
3395 status = wma_get_current_hw_mode(&hw_mode);
3396 if (!CDF_IS_STATUS_SUCCESS(status))
3397 WMA_LOGE("wma_get_current_hw_mode failed");
3398
3399 if ((params->nss == 2) && !hw_mode.dbs_cap) {
3400 req.preferred_rx_streams = 2;
3401 req.preferred_tx_streams = 2;
3402 } else {
3403 req.preferred_rx_streams = 1;
3404 req.preferred_tx_streams = 1;
3405 }
3406
3407#ifdef WLAN_FEATURE_VOWIFI
3408 req.max_txpow = params->maxTxPower;
3409#else
3410 req.max_txpow = params->localPowerConstraint;
3411#endif /* WLAN_FEATURE_VOWIFI */
3412 req.beacon_intval = 100;
3413 req.dtim_period = 1;
3414 req.is_dfs = params->isDfsChannel;
3415
3416 /* In case of AP mode, once radar is detected, we need to
3417 * issuse VDEV RESTART, so we making is_channel_switch as
3418 * true
3419 */
3420 if ((wma_is_vdev_in_ap_mode(wma, req.vdev_id) == true) ||
3421 (params->restart_on_chan_switch == true))
3422 wma->interfaces[req.vdev_id].is_channel_switch = true;
3423
3424 status = wma_vdev_start(wma, &req,
3425 wma->interfaces[req.vdev_id].is_channel_switch);
3426 if (status != CDF_STATUS_SUCCESS) {
3427 wma_remove_vdev_req(wma, req.vdev_id,
3428 WMA_TARGET_REQ_TYPE_VDEV_START);
3429 WMA_LOGP("%s: vdev start failed status = %d", __func__, status);
3430 goto send_resp;
3431 }
3432
3433 if (wma->interfaces[req.vdev_id].is_channel_switch)
3434 wma->interfaces[req.vdev_id].is_channel_switch = false;
3435 return;
3436send_resp:
3437 WMA_LOGD("%s: channel %d ch_width %d txpower %d status %d", __func__,
3438 params->channelNumber, params->ch_width,
3439#ifdef WLAN_FEATURE_VOWIFI
3440 params->maxTxPower,
3441#else
3442 params->localPowerConstraint,
3443#endif /* WLAN_FEATURE_VOWIFI */
3444 status);
3445 params->status = status;
3446 WMA_LOGI("%s: sending WMA_SWITCH_CHANNEL_RSP, status = 0x%x",
3447 __func__, status);
3448 wma_send_msg(wma, WMA_SWITCH_CHANNEL_RSP, (void *)params, 0);
3449}
3450
3451#ifdef FEATURE_WLAN_SCAN_PNO
Varun Reddy Yeturub43fda12015-09-10 18:16:21 -07003452/**
3453 * wma_set_pno_channel_prediction() - Set PNO configuration
3454 * @buf_ptr: Buffer passed by upper layers
3455 * @pno: Buffer to be sent to the firmware
3456 *
3457 * Copy the PNO Channel prediction configuration parameters
3458 * passed by the upper layers to a WMI format TLV and send it
3459 * down to the firmware.
3460 *
3461 * Return: None
3462 */
3463void wma_set_pno_channel_prediction(uint8_t *buf_ptr,
3464 tpSirPNOScanReq pno)
3465{
3466 nlo_channel_prediction_cfg *channel_prediction_cfg =
3467 (nlo_channel_prediction_cfg *) buf_ptr;
3468 WMITLV_SET_HDR(&channel_prediction_cfg->tlv_header,
3469 WMITLV_TAG_ARRAY_BYTE,
3470 WMITLV_GET_STRUCT_TLVLEN(nlo_channel_prediction_cfg));
3471 channel_prediction_cfg->enable = pno->pno_channel_prediction;
3472 channel_prediction_cfg->top_k_num = pno->top_k_num_of_channels;
3473 channel_prediction_cfg->stationary_threshold = pno->stationary_thresh;
3474 channel_prediction_cfg->full_scan_period_ms =
3475 pno->channel_prediction_full_scan;
3476 buf_ptr += sizeof(nlo_channel_prediction_cfg);
3477 WMA_LOGD("enable: %d, top_k_num: %d, stat_thresh: %d, full_scan: %d",
3478 channel_prediction_cfg->enable,
3479 channel_prediction_cfg->top_k_num,
3480 channel_prediction_cfg->stationary_threshold,
3481 channel_prediction_cfg->full_scan_period_ms);
3482}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003483/**
3484 * wma_pno_start() - PNO start request
3485 * @wma: wma handle
3486 * @pno: PNO request
3487 *
3488 * This function request FW to start PNO request.
3489 * Request: CDF status
3490 */
3491CDF_STATUS wma_pno_start(tp_wma_handle wma, tpSirPNOScanReq pno)
3492{
3493 wmi_nlo_config_cmd_fixed_param *cmd;
3494 nlo_configured_parameters *nlo_list;
3495 uint32_t *channel_list;
3496 int32_t len;
3497 wmi_buf_t buf;
3498 uint8_t *buf_ptr;
3499 uint8_t i;
3500 int ret;
3501
3502 WMA_LOGD("PNO Start");
3503
Varun Reddy Yeturub43fda12015-09-10 18:16:21 -07003504 /*
3505 * TLV place holder for array nlo_configured_parameters(nlo_list)
3506 * TLV place holder for array of uint32_t channel_list
3507 * TLV place holder for chnnl prediction cfg
3508 */
3509 len = sizeof(*cmd) +
3510 WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003511
3512 len += sizeof(uint32_t) * CDF_MIN(pno->aNetworks[0].ucChannelCount,
3513 WMI_NLO_MAX_CHAN);
3514 len += sizeof(nlo_configured_parameters) *
3515 CDF_MIN(pno->ucNetworksCount, WMI_NLO_MAX_SSIDS);
Varun Reddy Yeturub43fda12015-09-10 18:16:21 -07003516 len += sizeof(nlo_channel_prediction_cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003517
3518 buf = wmi_buf_alloc(wma->wmi_handle, len);
3519 if (!buf) {
3520 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
3521 return CDF_STATUS_E_NOMEM;
3522 }
3523
3524 cmd = (wmi_nlo_config_cmd_fixed_param *) wmi_buf_data(buf);
3525
3526 buf_ptr = (uint8_t *) cmd;
3527 WMITLV_SET_HDR(&cmd->tlv_header,
3528 WMITLV_TAG_STRUC_wmi_nlo_config_cmd_fixed_param,
3529 WMITLV_GET_STRUCT_TLVLEN
3530 (wmi_nlo_config_cmd_fixed_param));
3531 cmd->vdev_id = pno->sessionId;
3532 cmd->flags = WMI_NLO_CONFIG_START | WMI_NLO_CONFIG_SSID_HIDE_EN;
3533
Naveen Rawatcf7d2d52015-11-13 06:57:32 -08003534 /* Current FW does not support min-max range for dwell time */
3535 cmd->active_dwell_time = pno->active_max_time;
3536 cmd->passive_dwell_time = pno->passive_max_time;
3537
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003538 /* Copy scan interval */
3539 if (pno->scanTimers.ucScanTimersCount) {
3540 cmd->fast_scan_period =
3541 WMA_SEC_TO_MSEC(pno->scanTimers.aTimerValues[0].
3542 uTimerValue);
3543 cmd->slow_scan_period = cmd->fast_scan_period;
3544 WMA_LOGD("Scan period : %d msec", cmd->slow_scan_period);
3545 }
3546
3547 buf_ptr += sizeof(wmi_nlo_config_cmd_fixed_param);
3548
3549 cmd->no_of_ssids = CDF_MIN(pno->ucNetworksCount, WMI_NLO_MAX_SSIDS);
3550 WMA_LOGD("SSID count : %d", cmd->no_of_ssids);
3551 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
3552 cmd->no_of_ssids * sizeof(nlo_configured_parameters));
3553 buf_ptr += WMI_TLV_HDR_SIZE;
3554
3555 nlo_list = (nlo_configured_parameters *) buf_ptr;
3556 for (i = 0; i < cmd->no_of_ssids; i++) {
3557 WMITLV_SET_HDR(&nlo_list[i].tlv_header,
3558 WMITLV_TAG_ARRAY_BYTE,
3559 WMITLV_GET_STRUCT_TLVLEN
3560 (nlo_configured_parameters));
3561 /* Copy ssid and it's length */
3562 nlo_list[i].ssid.valid = true;
3563 nlo_list[i].ssid.ssid.ssid_len = pno->aNetworks[i].ssId.length;
3564 cdf_mem_copy(nlo_list[i].ssid.ssid.ssid,
3565 pno->aNetworks[i].ssId.ssId,
3566 nlo_list[i].ssid.ssid.ssid_len);
3567 WMA_LOGD("index: %d ssid: %.*s len: %d", i,
3568 nlo_list[i].ssid.ssid.ssid_len,
3569 (char *)nlo_list[i].ssid.ssid.ssid,
3570 nlo_list[i].ssid.ssid.ssid_len);
3571
3572 /* Copy rssi threshold */
3573 if (pno->aNetworks[i].rssiThreshold &&
3574 pno->aNetworks[i].rssiThreshold > WMA_RSSI_THOLD_DEFAULT) {
3575 nlo_list[i].rssi_cond.valid = true;
3576 nlo_list[i].rssi_cond.rssi =
3577 pno->aNetworks[i].rssiThreshold;
3578 WMA_LOGD("RSSI threshold : %d dBm",
3579 nlo_list[i].rssi_cond.rssi);
3580 }
3581 nlo_list[i].bcast_nw_type.valid = true;
3582 nlo_list[i].bcast_nw_type.bcast_nw_type =
3583 pno->aNetworks[i].bcastNetwType;
3584 WMA_LOGI("Broadcast NW type (%u)",
3585 nlo_list[i].bcast_nw_type.bcast_nw_type);
3586 }
3587 buf_ptr += cmd->no_of_ssids * sizeof(nlo_configured_parameters);
3588
3589 /* Copy channel info */
3590 cmd->num_of_channels = CDF_MIN(pno->aNetworks[0].ucChannelCount,
3591 WMI_NLO_MAX_CHAN);
3592 WMA_LOGD("Channel count: %d", cmd->num_of_channels);
3593 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
3594 (cmd->num_of_channels * sizeof(uint32_t)));
3595 buf_ptr += WMI_TLV_HDR_SIZE;
3596
3597 channel_list = (uint32_t *) buf_ptr;
3598 for (i = 0; i < cmd->num_of_channels; i++) {
3599 channel_list[i] = pno->aNetworks[0].aChannels[i];
3600
3601 if (channel_list[i] < WMA_NLO_FREQ_THRESH)
3602 channel_list[i] = cds_chan_to_freq(channel_list[i]);
3603
3604 WMA_LOGD("Ch[%d]: %d MHz", i, channel_list[i]);
3605 }
3606 buf_ptr += cmd->num_of_channels * sizeof(uint32_t);
Varun Reddy Yeturub43fda12015-09-10 18:16:21 -07003607 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
3608 sizeof(nlo_channel_prediction_cfg));
3609 buf_ptr += WMI_TLV_HDR_SIZE;
3610 wma_set_pno_channel_prediction(buf_ptr, pno);
3611 buf_ptr += WMI_TLV_HDR_SIZE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003612 /* TODO: Discrete firmware doesn't have command/option to configure
3613 * App IE which comes from wpa_supplicant as of part PNO start request.
3614 */
3615 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3616 WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
3617 if (ret) {
3618 WMA_LOGE("%s: Failed to send nlo wmi cmd", __func__);
3619 wmi_buf_free(buf);
3620 return CDF_STATUS_E_FAILURE;
3621 }
3622
3623 wma->interfaces[pno->sessionId].pno_in_progress = true;
3624
3625 WMA_LOGD("PNO start request sent successfully for vdev %d",
3626 pno->sessionId);
3627
3628 return CDF_STATUS_SUCCESS;
3629}
3630
3631/**
3632 * wma_pno_stop() - PNO stop request
3633 * @wma: wma handle
3634 * @vdev_id: vdev id
3635 *
3636 * This function request FW to stop ongoing PNO operation.
3637 *
3638 * Return: CDF status
3639 */
3640CDF_STATUS wma_pno_stop(tp_wma_handle wma, uint8_t vdev_id)
3641{
3642 wmi_nlo_config_cmd_fixed_param *cmd;
3643 int32_t len = sizeof(*cmd);
3644 wmi_buf_t buf;
3645 uint8_t *buf_ptr;
3646 int ret;
3647
3648 if (!wma->interfaces[vdev_id].pno_in_progress) {
3649 WMA_LOGD("No active pno session found for vdev %d, skip pno stop request",
3650 vdev_id);
3651 return CDF_STATUS_SUCCESS;
3652 }
3653
3654 WMA_LOGD("PNO Stop");
3655
Varun Reddy Yeturub43fda12015-09-10 18:16:21 -07003656 /*
3657 * TLV place holder for array of structures nlo_configured_parameters
3658 * TLV place holder for array of uint32_t channel_list
3659 * TLV place holder for chnl prediction cfg
3660 */
3661 len += WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003662 buf = wmi_buf_alloc(wma->wmi_handle, len);
3663 if (!buf) {
3664 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
3665 return CDF_STATUS_E_NOMEM;
3666 }
3667
3668 cmd = (wmi_nlo_config_cmd_fixed_param *) wmi_buf_data(buf);
3669 buf_ptr = (uint8_t *) cmd;
3670
3671 WMITLV_SET_HDR(&cmd->tlv_header,
3672 WMITLV_TAG_STRUC_wmi_nlo_config_cmd_fixed_param,
3673 WMITLV_GET_STRUCT_TLVLEN
3674 (wmi_nlo_config_cmd_fixed_param));
3675
3676 cmd->vdev_id = vdev_id;
3677 cmd->flags = WMI_NLO_CONFIG_STOP;
3678 buf_ptr += sizeof(*cmd);
3679
3680 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
3681 buf_ptr += WMI_TLV_HDR_SIZE;
3682
3683 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
3684 buf_ptr += WMI_TLV_HDR_SIZE;
3685
Varun Reddy Yeturub43fda12015-09-10 18:16:21 -07003686 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
3687 buf_ptr += WMI_TLV_HDR_SIZE;
3688
3689
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003690 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3691 WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
3692 if (ret) {
3693 WMA_LOGE("%s: Failed to send nlo wmi cmd", __func__);
3694 wmi_buf_free(buf);
3695 return CDF_STATUS_E_FAILURE;
3696 }
3697
3698 wma->interfaces[vdev_id].pno_in_progress = false;
3699
3700 WMA_LOGD("PNO stop request sent successfully for vdev %d", vdev_id);
3701
3702 return CDF_STATUS_SUCCESS;
3703}
3704
3705/**
3706 * wma_config_pno() - config PNO
3707 * @wma: wma handle
3708 * @pno: PNO request parameters
3709 *
3710 * Return: none
3711 */
3712void wma_config_pno(tp_wma_handle wma, tpSirPNOScanReq pno)
3713{
3714 CDF_STATUS ret;
3715
3716 if (pno->enable)
3717 ret = wma_pno_start(wma, pno);
3718 else
3719 ret = wma_pno_stop(wma, pno->sessionId);
3720
3721 if (ret)
3722 WMA_LOGE("%s: PNO %s failed %d", __func__,
3723 pno->enable ? "start" : "stop", ret);
3724
3725 /* SME expects WMA to free tpSirPNOScanReq memory after
3726 * processing PNO request. */
3727 cdf_mem_free(pno);
3728}
3729
3730#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
3731
3732/**
3733 * wma_plm_start() - plm start request
3734 * @wma: wma handle
3735 * @plm: plm request parameters
3736 *
3737 * This function request FW to start PLM.
3738 *
3739 * Return: CDF status
3740 */
3741CDF_STATUS wma_plm_start(tp_wma_handle wma, const tpSirPlmReq plm)
3742{
3743 wmi_vdev_plmreq_start_cmd_fixed_param *cmd;
3744 uint32_t *channel_list;
3745 int32_t len;
3746 wmi_buf_t buf;
3747 uint8_t *buf_ptr;
3748 uint8_t count;
3749 int ret;
3750
3751 if (NULL == plm || NULL == wma) {
3752 WMA_LOGE("%s: input pointer is NULL ", __func__);
3753 return CDF_STATUS_E_FAILURE;
3754 }
3755 WMA_LOGD("PLM Start");
3756
3757 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE; /* TLV place holder for channel_list */
3758 len += sizeof(uint32_t) * plm->plmNumCh;
3759
3760 buf = wmi_buf_alloc(wma->wmi_handle, len);
3761 if (!buf) {
3762 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
3763 return CDF_STATUS_E_NOMEM;
3764 }
3765 cmd = (wmi_vdev_plmreq_start_cmd_fixed_param *) wmi_buf_data(buf);
3766
3767 buf_ptr = (uint8_t *) cmd;
3768
3769 WMITLV_SET_HDR(&cmd->tlv_header,
3770 WMITLV_TAG_STRUC_wmi_vdev_plmreq_start_cmd_fixed_param,
3771 WMITLV_GET_STRUCT_TLVLEN
3772 (wmi_vdev_plmreq_start_cmd_fixed_param));
3773
3774 cmd->vdev_id = plm->sessionId;
3775
3776 cmd->meas_token = plm->meas_token;
3777 cmd->dialog_token = plm->diag_token;
3778 cmd->number_bursts = plm->numBursts;
3779 cmd->burst_interval = WMA_SEC_TO_MSEC(plm->burstInt);
3780 cmd->off_duration = plm->measDuration;
3781 cmd->burst_cycle = plm->burstLen;
3782 cmd->tx_power = plm->desiredTxPwr;
3783 WMI_CHAR_ARRAY_TO_MAC_ADDR(plm->macAddr, &cmd->dest_mac);
3784 cmd->num_chans = plm->plmNumCh;
3785
3786 buf_ptr += sizeof(wmi_vdev_plmreq_start_cmd_fixed_param);
3787
3788 WMA_LOGD("vdev : %d measu token : %d", cmd->vdev_id, cmd->meas_token);
3789 WMA_LOGD("dialog_token: %d", cmd->dialog_token);
3790 WMA_LOGD("number_bursts: %d", cmd->number_bursts);
3791 WMA_LOGD("burst_interval: %d", cmd->burst_interval);
3792 WMA_LOGD("off_duration: %d", cmd->off_duration);
3793 WMA_LOGD("burst_cycle: %d", cmd->burst_cycle);
3794 WMA_LOGD("tx_power: %d", cmd->tx_power);
3795 WMA_LOGD("Number of channels : %d", cmd->num_chans);
3796
3797 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
3798 (cmd->num_chans * sizeof(uint32_t)));
3799
3800 buf_ptr += WMI_TLV_HDR_SIZE;
3801 if (cmd->num_chans) {
3802 channel_list = (uint32_t *) buf_ptr;
3803 for (count = 0; count < cmd->num_chans; count++) {
3804 channel_list[count] = plm->plmChList[count];
3805 if (channel_list[count] < WMA_NLO_FREQ_THRESH)
3806 channel_list[count] =
3807 cds_chan_to_freq(channel_list[count]);
3808 WMA_LOGD("Ch[%d]: %d MHz", count, channel_list[count]);
3809 }
3810 buf_ptr += cmd->num_chans * sizeof(uint32_t);
3811 }
3812
3813 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3814 WMI_VDEV_PLMREQ_START_CMDID);
3815 if (ret) {
3816 WMA_LOGE("%s: Failed to send plm start wmi cmd", __func__);
3817 wmi_buf_free(buf);
3818 return CDF_STATUS_E_FAILURE;
3819 }
3820 wma->interfaces[plm->sessionId].plm_in_progress = true;
3821
3822 WMA_LOGD("Plm start request sent successfully for vdev %d",
3823 plm->sessionId);
3824
3825 return CDF_STATUS_SUCCESS;
3826}
3827
3828/**
3829 * wma_plm_stop() - plm stop request
3830 * @wma: wma handle
3831 * @plm: plm request parameters
3832 *
3833 * This function request FW to stop PLM.
3834 *
3835 * Return: CDF status
3836 */
3837CDF_STATUS wma_plm_stop(tp_wma_handle wma, const tpSirPlmReq plm)
3838{
3839 wmi_vdev_plmreq_stop_cmd_fixed_param *cmd;
3840 int32_t len;
3841 wmi_buf_t buf;
3842 uint8_t *buf_ptr;
3843 int ret;
3844
3845 if (NULL == plm || NULL == wma) {
3846 WMA_LOGE("%s: input pointer is NULL ", __func__);
3847 return CDF_STATUS_E_FAILURE;
3848 }
3849
3850 if (false == wma->interfaces[plm->sessionId].plm_in_progress) {
3851 WMA_LOGE("No active plm req found, skip plm stop req");
3852 return CDF_STATUS_E_FAILURE;
3853 }
3854
3855 WMA_LOGD("PLM Stop");
3856
3857 len = sizeof(*cmd);
3858 buf = wmi_buf_alloc(wma->wmi_handle, len);
3859 if (!buf) {
3860 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
3861 return CDF_STATUS_E_NOMEM;
3862 }
3863
3864 cmd = (wmi_vdev_plmreq_stop_cmd_fixed_param *) wmi_buf_data(buf);
3865
3866 buf_ptr = (uint8_t *) cmd;
3867
3868 WMITLV_SET_HDR(&cmd->tlv_header,
3869 WMITLV_TAG_STRUC_wmi_vdev_plmreq_stop_cmd_fixed_param,
3870 WMITLV_GET_STRUCT_TLVLEN
3871 (wmi_vdev_plmreq_stop_cmd_fixed_param));
3872
3873 cmd->vdev_id = plm->sessionId;
3874
3875 cmd->meas_token = plm->meas_token;
3876 WMA_LOGD("vdev %d meas token %d", cmd->vdev_id, cmd->meas_token);
3877
3878 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3879 WMI_VDEV_PLMREQ_STOP_CMDID);
3880 if (ret) {
3881 WMA_LOGE("%s: Failed to send plm stop wmi cmd", __func__);
3882 wmi_buf_free(buf);
3883 return CDF_STATUS_E_FAILURE;
3884 }
3885 wma->interfaces[plm->sessionId].plm_in_progress = false;
3886
3887 WMA_LOGD("Plm stop request sent successfully for vdev %d",
3888 plm->sessionId);
3889
3890 return CDF_STATUS_SUCCESS;
3891}
3892
3893/**
3894 * wma_config_plm()- config PLM
3895 * @wma: wma handle
3896 * @plm: plm request parameters
3897 *
3898 * Return: none
3899 */
3900void wma_config_plm(tp_wma_handle wma, tpSirPlmReq plm)
3901{
3902 CDF_STATUS ret = 0;
3903
3904 if (NULL == plm || NULL == wma)
3905 return;
3906
3907 if (plm->enable)
3908 ret = wma_plm_start(wma, plm);
3909 else
3910 ret = wma_plm_stop(wma, plm);
3911
3912 if (ret)
3913 WMA_LOGE("%s: PLM %s failed %d", __func__,
3914 plm->enable ? "start" : "stop", ret);
3915
3916 /* SME expects WMA to free tpSirPlmReq memory after
3917 * processing PLM request. */
3918 cdf_mem_free(plm);
3919 plm = NULL;
3920}
3921#endif
3922
3923/**
3924 * wma_scan_cache_updated_ind() - scan update indication
3925 * @wma: wma handle
3926 * @sessionId: session ID
3927 *
3928 * After pushing cached scan results (that are stored in LIM) to SME,
3929 * PE will post WMA_SME_SCAN_CACHE_UPDATED message indication to
3930 * wma and intern this function handles that message. This function will
3931 * check for PNO completion (by checking NLO match event) and post PNO
3932 * completion back to SME if PNO operation is completed successfully.
3933 *
3934 * Return: none
3935 */
3936void wma_scan_cache_updated_ind(tp_wma_handle wma, uint8_t sessionId)
3937{
3938 tSirPrefNetworkFoundInd *nw_found_ind;
3939 CDF_STATUS status;
3940 cds_msg_t cds_msg;
3941 uint8_t len, i;
3942
3943 for (i = 0; i < wma->max_bssid; i++) {
3944 if (wma->interfaces[i].nlo_match_evt_received)
3945 break;
3946 }
3947
3948 if (i == wma->max_bssid) {
3949 WMA_LOGD("PNO match event is not received in any vdev, skip scan cache update indication");
3950 return;
3951 }
3952 wma->interfaces[i].nlo_match_evt_received = false;
3953
3954 WMA_LOGD("Posting PNO completion to umac");
3955
3956 len = sizeof(tSirPrefNetworkFoundInd);
3957 nw_found_ind = (tSirPrefNetworkFoundInd *) cdf_mem_malloc(len);
3958
3959 if (NULL == nw_found_ind) {
3960 WMA_LOGE("%s: Memory allocation failure", __func__);
3961 return;
3962 }
3963
3964 nw_found_ind->mesgType = eWNI_SME_PREF_NETWORK_FOUND_IND;
3965 nw_found_ind->mesgLen = len;
3966 nw_found_ind->sessionId = sessionId;
3967
3968 cds_msg.type = eWNI_SME_PREF_NETWORK_FOUND_IND;
3969 cds_msg.bodyptr = (void *)nw_found_ind;
3970 cds_msg.bodyval = 0;
3971
3972 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
3973 if (status != CDF_STATUS_SUCCESS) {
3974 WMA_LOGE("%s: Failed to post PNO completion match event to SME",
3975 __func__);
3976 cdf_mem_free(nw_found_ind);
3977 }
3978}
3979
3980#ifdef FEATURE_WLAN_EXTSCAN
3981/**
3982 * wma_extscan_get_eventid_from_tlvtag() - map tlv tag to corresponding event id
3983 * @tag: WMI TLV tag
3984 *
3985 * Return:
3986 * 0 if TLV tag is invalid
3987 * else return corresponding WMI event id
3988 */
3989static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag)
3990{
3991 uint32_t event_id;
3992
3993 switch (tag) {
3994 case WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param:
3995 event_id = WMI_EXTSCAN_START_STOP_EVENTID;
3996 break;
3997
3998 case WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param:
3999 event_id = WMI_EXTSCAN_OPERATION_EVENTID;
4000 break;
4001
4002 case WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param:
4003 event_id = WMI_EXTSCAN_TABLE_USAGE_EVENTID;
4004 break;
4005
4006 case WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param:
4007 event_id = WMI_EXTSCAN_CACHED_RESULTS_EVENTID;
4008 break;
4009
4010 case WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param:
4011 event_id = WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID;
4012 break;
4013
4014 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param:
4015 event_id = WMI_EXTSCAN_HOTLIST_MATCH_EVENTID;
4016 break;
4017
4018 case WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param:
4019 event_id = WMI_EXTSCAN_CAPABILITIES_EVENTID;
4020 break;
4021
4022 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_ssid_match_event_fixed_param:
4023 event_id = WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID;
4024 break;
4025
4026 default:
4027 event_id = 0;
4028 WMA_LOGE("%s: Unknown tag: %d", __func__, tag);
4029 break;
4030 }
4031
4032 WMA_LOGI("%s: For tag %d WMI event 0x%x", __func__, tag, event_id);
4033 return event_id;
4034}
4035
4036/**
4037 * wma_extscan_wow_event_callback() - extscan wow event callback
4038 * @handle: WMA handle
4039 * @event: event buffer
4040 * @len: length of @event buffer
4041 *
4042 * In wow case, the wow event is followed by the payload of the event
4043 * which generated the wow event.
4044 * payload is 4 bytes of length followed by event buffer. the first 4 bytes
4045 * of event buffer is common tlv header, which is a combination
4046 * of tag (higher 2 bytes) and length (lower 2 bytes). The tag is used to
4047 * identify the event which triggered wow event.
4048 *
4049 * @Return: none
4050 */
4051void wma_extscan_wow_event_callback(void *handle, void *event, uint32_t len)
4052{
4053 uint32_t id;
4054 int tlv_ok_status = 0;
4055 void *wmi_cmd_struct_ptr = NULL;
4056 uint32_t tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(event));
4057
4058 id = wma_extscan_get_eventid_from_tlvtag(tag);
4059 if (!id) {
4060 WMA_LOGE("%s: Invalid Tag: %d", __func__, tag);
4061 return;
4062 }
4063
4064 tlv_ok_status = wmitlv_check_and_pad_event_tlvs(
4065 handle, event, len, id,
4066 &wmi_cmd_struct_ptr);
4067 if (tlv_ok_status != 0) {
4068 WMA_LOGE("%s: Invalid Tag: %d could not check and pad tlvs",
4069 __func__, tag);
4070 return;
4071 }
4072
4073 switch (tag) {
4074 case WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param:
4075 wma_extscan_start_stop_event_handler(handle,
4076 wmi_cmd_struct_ptr, len);
4077 break;
4078
4079 case WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param:
4080 wma_extscan_operations_event_handler(handle,
4081 wmi_cmd_struct_ptr, len);
4082 break;
4083
4084 case WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param:
4085 wma_extscan_table_usage_event_handler(handle,
4086 wmi_cmd_struct_ptr, len);
4087 break;
4088
4089 case WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param:
4090 wma_extscan_cached_results_event_handler(handle,
4091 wmi_cmd_struct_ptr, len);
4092 break;
4093
4094 case WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param:
4095 wma_extscan_change_results_event_handler(handle,
4096 wmi_cmd_struct_ptr, len);
4097 break;
4098
4099 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param:
4100 wma_extscan_hotlist_match_event_handler(handle,
4101 wmi_cmd_struct_ptr, len);
4102 break;
4103
4104 case WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param:
4105 wma_extscan_capabilities_event_handler(handle,
4106 wmi_cmd_struct_ptr, len);
4107 break;
4108
4109 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_ssid_match_event_fixed_param:
4110 wma_extscan_hotlist_ssid_match_event_handler(handle,
4111 wmi_cmd_struct_ptr, len);
4112 break;
4113
4114 default:
4115 WMA_LOGE("%s: Unknown tag: %d", __func__, tag);
4116 break;
4117 }
4118 wmitlv_free_allocated_event_tlvs(id, &wmi_cmd_struct_ptr);
4119
4120 return;
4121}
4122#endif
4123
4124/**
4125 * wma_nlo_match_evt_handler() - nlo match event handler
4126 * @handle: wma handle
4127 * @event: event data
4128 * @len: data length
4129 *
4130 * Record NLO match event comes from FW. It's a indication that
4131 * one of the profile is matched.
4132 *
4133 * Return: 0 for success or error code.
4134 */
4135int wma_nlo_match_evt_handler(void *handle, uint8_t *event,
4136 uint32_t len)
4137{
4138 tp_wma_handle wma = (tp_wma_handle) handle;
4139 wmi_nlo_event *nlo_event;
4140 WMI_NLO_MATCH_EVENTID_param_tlvs *param_buf =
4141 (WMI_NLO_MATCH_EVENTID_param_tlvs *) event;
4142 struct wma_txrx_node *node;
4143
4144 if (!param_buf) {
4145 WMA_LOGE("Invalid NLO match event buffer");
4146 return -EINVAL;
4147 }
4148
4149 nlo_event = param_buf->fixed_param;
4150 WMA_LOGD("PNO match event received for vdev %d", nlo_event->vdev_id);
4151
4152 node = &wma->interfaces[nlo_event->vdev_id];
4153 if (node)
4154 node->nlo_match_evt_received = true;
4155
4156 cdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
4157 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT,
4158 WIFI_POWER_EVENT_WAKELOCK_PNO);
4159
4160 return 0;
4161}
4162
4163/**
4164 * wma_nlo_scan_cmp_evt_handler() - nlo scan completion handler
4165 * @handle: wma handle
4166 * @event: event handler
4167 * @len: length of data
4168 *
4169 * This function handles NLO scan completion event.
4170 *
4171 * Return: 0 for success or error code.
4172 */
4173int wma_nlo_scan_cmp_evt_handler(void *handle, uint8_t *event,
4174 uint32_t len)
4175{
4176 tp_wma_handle wma = (tp_wma_handle) handle;
4177 wmi_nlo_event *nlo_event;
4178 WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs *param_buf =
4179 (WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs *) event;
4180 tSirScanOffloadEvent *scan_event;
4181 struct wma_txrx_node *node;
4182
4183 if (!param_buf) {
4184 WMA_LOGE("Invalid NLO scan comp event buffer");
4185 return -EINVAL;
4186 }
4187
4188 nlo_event = param_buf->fixed_param;
4189 WMA_LOGD("PNO scan completion event received for vdev %d",
4190 nlo_event->vdev_id);
4191
4192 node = &wma->interfaces[nlo_event->vdev_id];
4193
4194 /* Handle scan completion event only after NLO match event. */
4195 if (!node || !node->nlo_match_evt_received) {
4196
4197 WMA_LOGD("NLO match not recieved skipping PNO complete ind for vdev %d",
4198 nlo_event->vdev_id);
4199 goto skip_pno_cmp_ind;
4200 }
4201
4202 cdf_wake_lock_release(&wma->pno_wake_lock,
4203 WIFI_POWER_EVENT_WAKELOCK_PNO);
4204 scan_event =
4205 (tSirScanOffloadEvent *)
4206 cdf_mem_malloc(sizeof(tSirScanOffloadEvent));
4207 if (scan_event) {
4208 /* Posting scan completion msg would take scan cache result
4209 * from LIM module and update in scan cache maintained in SME.*/
4210 WMA_LOGE("Posting PNO Scan completion to umac");
4211 cdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
4212 WMA_PNO_SCAN_COMPLETE_WAKE_LOCK_TIMEOUT,
4213 WIFI_POWER_EVENT_WAKELOCK_PNO);
4214 cdf_mem_zero(scan_event, sizeof(tSirScanOffloadEvent));
4215 scan_event->reasonCode = eSIR_PNO_SCAN_SUCCESS;
4216 scan_event->event = SCAN_EVENT_COMPLETED;
4217 scan_event->sessionId = nlo_event->vdev_id;
4218 wma_send_msg(wma, WMA_RX_SCAN_EVENT, (void *)scan_event, 0);
4219 } else {
4220 WMA_LOGE("Memory allocation failed for tSirScanOffloadEvent");
4221 }
4222
4223skip_pno_cmp_ind:
4224 return 0;
4225}
4226
4227#endif
4228
4229/**
4230 * wma_register_extscan_event_handler() - register extscan event handler
4231 * @wma_handle: wma handle
4232 *
4233 * This function register extscan related event handlers.
4234 *
4235 * Return: none
4236 */
4237void wma_register_extscan_event_handler(tp_wma_handle wma_handle)
4238{
4239 if (!wma_handle) {
4240 WMA_LOGE("%s: extscan wma_handle is NULL", __func__);
4241 return;
4242 }
4243 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4244 WMI_EXTSCAN_START_STOP_EVENTID,
4245 wma_extscan_start_stop_event_handler);
4246
4247 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4248 WMI_EXTSCAN_CAPABILITIES_EVENTID,
4249 wma_extscan_capabilities_event_handler);
4250
4251 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4252 WMI_EXTSCAN_HOTLIST_MATCH_EVENTID,
4253 wma_extscan_hotlist_match_event_handler);
4254
4255 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4256 WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID,
4257 wma_extscan_change_results_event_handler);
4258
4259 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4260 WMI_EXTSCAN_OPERATION_EVENTID,
4261 wma_extscan_operations_event_handler);
4262 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4263 WMI_EXTSCAN_TABLE_USAGE_EVENTID,
4264 wma_extscan_table_usage_event_handler);
4265
4266 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4267 WMI_EXTSCAN_CACHED_RESULTS_EVENTID,
4268 wma_extscan_cached_results_event_handler);
4269
4270 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4271 WMI_PASSPOINT_MATCH_EVENTID,
4272 wma_passpoint_match_event_handler);
4273
4274
4275 wmi_unified_register_event_handler(wma_handle->wmi_handle,
4276 WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID,
4277 wma_extscan_hotlist_ssid_match_event_handler);
4278
4279 return;
4280}
4281
4282#ifdef FEATURE_WLAN_EXTSCAN
4283
4284/**
4285 * wma_extscan_start_stop_event_handler() - extscan start/stop event handler
4286 * @handle: wma handle
4287 * @cmd_param_info: event buffer
4288 * @len: data length
4289 *
4290 * This function handles different extscan related commands
4291 * like start/stop/get results etc and indicate to upper layers.
4292 *
4293 * Return: 0 for success or error code.
4294 */
4295int wma_extscan_start_stop_event_handler(void *handle,
4296 uint8_t *cmd_param_info,
4297 uint32_t len)
4298{
4299 WMI_EXTSCAN_START_STOP_EVENTID_param_tlvs *param_buf;
4300 wmi_extscan_start_stop_event_fixed_param *event;
4301 struct sir_extscan_generic_response *extscan_ind;
4302 uint16_t event_type;
4303 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
4304 if (!pMac) {
4305 WMA_LOGE("%s: Invalid pMac", __func__);
4306 return -EINVAL;
4307 }
4308 if (!pMac->sme.pExtScanIndCb) {
4309 WMA_LOGE("%s: Callback not registered", __func__);
4310 return -EINVAL;
4311 }
4312 param_buf = (WMI_EXTSCAN_START_STOP_EVENTID_param_tlvs *)
4313 cmd_param_info;
4314 if (!param_buf) {
4315 WMA_LOGE("%s: Invalid extscan event", __func__);
4316 return -EINVAL;
4317 }
4318 event = param_buf->fixed_param;
4319 extscan_ind = cdf_mem_malloc(sizeof(*extscan_ind));
4320 if (!extscan_ind) {
4321 WMA_LOGE("%s: extscan memory allocation failed", __func__);
4322 return -ENOMEM;
4323 }
4324 switch (event->command) {
4325 case WMI_EXTSCAN_START_CMDID:
4326 event_type = eSIR_EXTSCAN_START_RSP;
4327 extscan_ind->status = event->status;
4328 extscan_ind->request_id = event->request_id;
4329 break;
4330 case WMI_EXTSCAN_STOP_CMDID:
4331 event_type = eSIR_EXTSCAN_STOP_RSP;
4332 extscan_ind->status = event->status;
4333 extscan_ind->request_id = event->request_id;
4334 break;
4335 case WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID:
4336 extscan_ind->status = event->status;
4337 extscan_ind->request_id = event->request_id;
4338 if (event->mode == WMI_EXTSCAN_MODE_STOP) {
4339 event_type =
4340 eSIR_EXTSCAN_RESET_SIGNIFICANT_WIFI_CHANGE_RSP;
4341 } else {
4342 event_type =
4343 eSIR_EXTSCAN_SET_SIGNIFICANT_WIFI_CHANGE_RSP;
4344 }
4345 break;
4346 case WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID:
4347 extscan_ind->status = event->status;
4348 extscan_ind->request_id = event->request_id;
4349 if (event->mode == WMI_EXTSCAN_MODE_STOP) {
4350 event_type = eSIR_EXTSCAN_RESET_BSSID_HOTLIST_RSP;
4351 } else {
4352 event_type = eSIR_EXTSCAN_SET_BSSID_HOTLIST_RSP;
4353 }
4354 break;
4355 case WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID:
4356 extscan_ind->status = event->status;
4357 extscan_ind->request_id = event->request_id;
4358 event_type = eSIR_EXTSCAN_CACHED_RESULTS_RSP;
4359 break;
4360 case WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID:
4361 extscan_ind->status = event->status;
4362 extscan_ind->request_id = event->request_id;
4363 if (event->mode == WMI_EXTSCAN_MODE_STOP) {
4364 event_type =
4365 eSIR_EXTSCAN_RESET_SSID_HOTLIST_RSP;
4366 } else {
4367 event_type =
4368 eSIR_EXTSCAN_SET_SSID_HOTLIST_RSP;
4369 }
4370 break;
4371 default:
4372 WMA_LOGE("%s: Unknown event(%d) from target",
4373 __func__, event->status);
4374 cdf_mem_free(extscan_ind);
4375 return -EINVAL;
4376 }
4377 pMac->sme.pExtScanIndCb(pMac->hHdd, event_type, extscan_ind);
4378 WMA_LOGD("%s: sending event to umac for requestid %u"
4379 "with status %d", __func__,
4380 extscan_ind->request_id, extscan_ind->status);
4381 cdf_mem_free(extscan_ind);
4382 return 0;
4383}
4384
4385/**
4386 * wma_extscan_operations_event_handler() - extscan operation event handler
4387 * @handle: wma handle
4388 * @cmd_param_info: event buffer
4389 * @len: length
4390 *
4391 * This function handles different operations related event and indicate
4392 * upper layers with appropriate callback.
4393 *
4394 * Return: 0 for success or error code.
4395 */
4396int wma_extscan_operations_event_handler(void *handle,
4397 uint8_t *cmd_param_info,
4398 uint32_t len)
4399{
4400 tp_wma_handle wma = (tp_wma_handle) handle;
4401 WMI_EXTSCAN_OPERATION_EVENTID_param_tlvs *param_buf;
4402 wmi_extscan_operation_event_fixed_param *oprn_event;
4403 tSirExtScanOnScanEventIndParams *oprn_ind;
4404 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
4405 if (!pMac) {
4406 WMA_LOGE("%s: Invalid pMac", __func__);
4407 return -EINVAL;
4408 }
4409 if (!pMac->sme.pExtScanIndCb) {
4410 WMA_LOGE("%s: Callback not registered", __func__);
4411 return -EINVAL;
4412 }
4413 param_buf = (WMI_EXTSCAN_OPERATION_EVENTID_param_tlvs *)
4414 cmd_param_info;
4415 if (!param_buf) {
4416 WMA_LOGE("%s: Invalid scan operation event", __func__);
4417 return -EINVAL;
4418 }
4419 oprn_event = param_buf->fixed_param;
4420 oprn_ind = cdf_mem_malloc(sizeof(*oprn_ind));
4421 if (!oprn_ind) {
4422 WMA_LOGE("%s: extscan memory allocation failed", __func__);
4423 cdf_mem_free(oprn_ind);
4424 return -ENOMEM;
4425 }
4426
4427 oprn_ind->requestId = oprn_event->request_id;
4428
4429 switch (oprn_event->event) {
4430 case WMI_EXTSCAN_BUCKET_COMPLETED_EVENT:
4431 oprn_ind->scanEventType = WIFI_SCAN_COMPLETE;
4432 oprn_ind->status = 0;
4433 break;
4434 case WMI_EXTSCAN_CYCLE_STARTED_EVENT:
4435 WMA_LOGD("%s: received WMI_EXTSCAN_CYCLE_STARTED_EVENT",
4436 __func__);
4437 cdf_wake_lock_timeout_acquire(&wma->extscan_wake_lock,
4438 WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION,
4439 WIFI_POWER_EVENT_WAKELOCK_EXT_SCAN);
4440 goto exit_handler;
4441 case WMI_EXTSCAN_CYCLE_COMPLETED_EVENT:
4442 WMA_LOGD("%s: received WMI_EXTSCAN_CYCLE_COMPLETED_EVENT",
4443 __func__);
4444 cdf_wake_lock_release(&wma->extscan_wake_lock,
4445 WIFI_POWER_EVENT_WAKELOCK_EXT_SCAN);
4446 goto exit_handler;
4447 default:
4448 WMA_LOGE("%s: Unknown event(%d) from target",
4449 __func__, oprn_event->event);
4450 cdf_mem_free(oprn_ind);
4451 return -EINVAL;
4452 }
4453 pMac->sme.pExtScanIndCb(pMac->hHdd,
4454 eSIR_EXTSCAN_SCAN_PROGRESS_EVENT_IND, oprn_ind);
4455 WMA_LOGI("%s: sending scan progress event to hdd", __func__);
4456exit_handler:
4457 cdf_mem_free(oprn_ind);
4458 return 0;
4459}
4460
4461/**
4462 * wma_extscan_table_usage_event_handler() - extscan table usage event handler
4463 * @handle: wma handle
4464 * @cmd_param_info: event buffer
4465 * @len: length
4466 *
4467 * This function handles table usage related event and indicate
4468 * upper layers with appropriate callback.
4469 *
4470 * Return: 0 for success or error code.
4471 */
4472int wma_extscan_table_usage_event_handler(void *handle,
4473 uint8_t *cmd_param_info,
4474 uint32_t len)
4475{
4476 WMI_EXTSCAN_TABLE_USAGE_EVENTID_param_tlvs *param_buf;
4477 wmi_extscan_table_usage_event_fixed_param *event;
4478 tSirExtScanResultsAvailableIndParams *tbl_usg_ind;
4479 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
4480 if (!pMac) {
4481 WMA_LOGE("%s: Invalid pMac", __func__);
4482 return -EINVAL;
4483 }
4484 if (!pMac->sme.pExtScanIndCb) {
4485 WMA_LOGE("%s: Callback not registered", __func__);
4486 return -EINVAL;
4487 }
4488 param_buf = (WMI_EXTSCAN_TABLE_USAGE_EVENTID_param_tlvs *)
4489 cmd_param_info;
4490 if (!param_buf) {
4491 WMA_LOGE("%s: Invalid table usage event", __func__);
4492 return -EINVAL;
4493 }
4494 event = param_buf->fixed_param;
4495 tbl_usg_ind = cdf_mem_malloc(sizeof(*tbl_usg_ind));
4496 if (!tbl_usg_ind) {
4497 WMA_LOGE("%s: table usage allocation failed", __func__);
4498 return -ENOMEM;
4499 }
4500 tbl_usg_ind->requestId = event->request_id;
4501 tbl_usg_ind->numResultsAvailable = event->entries_in_use;
4502
4503 pMac->sme.pExtScanIndCb(pMac->hHdd,
4504 eSIR_EXTSCAN_SCAN_RES_AVAILABLE_IND,
4505 tbl_usg_ind);
4506 WMA_LOGI("%s: sending scan_res available event to hdd", __func__);
4507 cdf_mem_free(tbl_usg_ind);
4508 return 0;
4509}
4510
4511/**
4512 * wma_extscan_capabilities_event_handler() - extscan capabilities event handler
4513 * @handle: wma handle
4514 * @cmd_param_info: event buffer
4515 * @len: length
4516 *
4517 * This function handles capabilities event and indicate
4518 * upper layers with registered callback.
4519 *
4520 * Return: 0 for success or error code.
4521 */
4522int wma_extscan_capabilities_event_handler(void *handle,
4523 uint8_t *cmd_param_info,
4524 uint32_t len)
4525{
4526 WMI_EXTSCAN_CAPABILITIES_EVENTID_param_tlvs *param_buf;
4527 wmi_extscan_capabilities_event_fixed_param *event;
4528 wmi_extscan_cache_capabilities *src_cache;
4529 wmi_extscan_hotlist_monitor_capabilities *src_hotlist;
4530 wmi_extscan_wlan_change_monitor_capabilities *src_change;
4531
4532 struct ext_scan_capabilities_response *dest_capab;
4533 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
4534 if (!pMac) {
4535 WMA_LOGE("%s: Invalid pMac", __func__);
4536 return -EINVAL;
4537 }
4538 if (!pMac->sme.pExtScanIndCb) {
4539 WMA_LOGE("%s: Callback not registered", __func__);
4540 return -EINVAL;
4541 }
4542 param_buf = (WMI_EXTSCAN_CAPABILITIES_EVENTID_param_tlvs *)
4543 cmd_param_info;
4544 if (!param_buf) {
4545 WMA_LOGE("%s: Invalid capabilities event", __func__);
4546 return -EINVAL;
4547 }
4548 event = param_buf->fixed_param;
4549 src_cache = param_buf->extscan_cache_capabilities;
4550 src_hotlist = param_buf->hotlist_capabilities;
4551 src_change = param_buf->wlan_change_capabilities;
4552
4553 if (!src_cache || !src_hotlist || !src_change) {
4554 WMA_LOGE("%s: Invalid capabilities list", __func__);
4555 return -EINVAL;
4556 }
4557 dest_capab = cdf_mem_malloc(sizeof(*dest_capab));
4558 if (!dest_capab) {
4559 WMA_LOGE("%s: Allocation failed for capabilities buffer",
4560 __func__);
4561 return -ENOMEM;
4562 }
4563 dest_capab->requestId = event->request_id;
4564 dest_capab->max_scan_buckets = src_cache->max_buckets;
4565 dest_capab->max_scan_cache_size = src_cache->scan_cache_entry_size;
4566 dest_capab->max_ap_cache_per_scan = src_cache->max_bssid_per_scan;
4567 dest_capab->max_scan_reporting_threshold =
4568 src_cache->max_table_usage_threshold;
4569
4570 dest_capab->max_hotlist_bssids = src_hotlist->max_hotlist_entries;
4571 dest_capab->max_rssi_sample_size = src_change->max_rssi_averaging_samples;
4572 dest_capab->max_bssid_history_entries =
4573 src_change->max_rssi_history_entries;
4574 dest_capab->max_significant_wifi_change_aps =
4575 src_change->max_wlan_change_entries;
4576 dest_capab->max_hotlist_ssids =
4577 event->num_extscan_hotlist_ssid;
4578 dest_capab->max_number_epno_networks =
4579 event->num_epno_networks;
4580 dest_capab->max_number_epno_networks_by_ssid =
4581 event->num_epno_networks;
4582 dest_capab->max_number_of_white_listed_ssid =
4583 event->num_roam_ssid_whitelist;
4584 dest_capab->status = 0;
4585
4586 WMA_LOGD("%s: request_id: %u status: %d",
4587 __func__, dest_capab->requestId, dest_capab->status);
4588
4589 WMA_LOGD("%s: Capabilities: max_scan_buckets: %d,"
4590 "max_hotlist_bssids: %d, max_scan_cache_size: %d,"
4591 "max_ap_cache_per_scan: %d, max_scan_reporting_threshold: %d,"
4592 "max_rssi_sample_size: %d, max_bssid_history_entries: %d,"
4593 "max_significant_wifi_change_aps: %d",
4594 __func__, dest_capab->max_scan_buckets,
4595 dest_capab->max_hotlist_bssids,
4596 dest_capab->max_scan_cache_size,
4597 dest_capab->max_ap_cache_per_scan,
4598 dest_capab->max_scan_reporting_threshold,
4599 dest_capab->max_rssi_sample_size,
4600 dest_capab->max_bssid_history_entries,
4601 dest_capab->max_significant_wifi_change_aps);
4602
4603 WMA_LOGD("%s: Capabilities: max_hotlist_ssids: %d,"
4604 "max_number_epno_networks: %d, max_number_epno_networks_by_ssid: %d,"
4605 "max_number_of_white_listed_ssid: %d",
4606 __func__, dest_capab->max_hotlist_ssids,
4607 dest_capab->max_number_epno_networks,
4608 dest_capab->max_number_epno_networks_by_ssid,
4609 dest_capab->max_number_of_white_listed_ssid);
4610
4611 pMac->sme.pExtScanIndCb(pMac->hHdd,
4612 eSIR_EXTSCAN_GET_CAPABILITIES_IND, dest_capab);
4613 WMA_LOGI("%s: sending capabilities event to hdd", __func__);
4614 cdf_mem_free(dest_capab);
4615 return 0;
4616}
4617
4618/**
4619 * wma_extscan_hotlist_match_event_handler() - hotlist match event handler
4620 * @handle: wma handle
4621 * @cmd_param_info: event buffer
4622 * @len: length
4623 *
4624 * This function handles hotlist match event and indicate
4625 * upper layers with registered callback.
4626 *
4627 * Return: 0 for success or error code.
4628 */
4629int wma_extscan_hotlist_match_event_handler(void *handle,
4630 uint8_t *cmd_param_info,
4631 uint32_t len)
4632{
4633 WMI_EXTSCAN_HOTLIST_MATCH_EVENTID_param_tlvs *param_buf;
4634 wmi_extscan_hotlist_match_event_fixed_param *event;
4635 struct extscan_hotlist_match *dest_hotlist;
4636 tSirWifiScanResult *dest_ap;
4637 wmi_extscan_wlan_descriptor *src_hotlist;
4638 int numap, j, ap_found = 0;
4639 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
4640
4641 if (!pMac) {
4642 WMA_LOGE("%s: Invalid pMac", __func__);
4643 return -EINVAL;
4644 }
4645 if (!pMac->sme.pExtScanIndCb) {
4646 WMA_LOGE("%s: Callback not registered", __func__);
4647 return -EINVAL;
4648 }
4649 param_buf = (WMI_EXTSCAN_HOTLIST_MATCH_EVENTID_param_tlvs *)
4650 cmd_param_info;
4651 if (!param_buf) {
4652 WMA_LOGE("%s: Invalid hotlist match event", __func__);
4653 return -EINVAL;
4654 }
4655 event = param_buf->fixed_param;
4656 src_hotlist = param_buf->hotlist_match;
4657 numap = event->total_entries;
4658
4659 if (!src_hotlist || !numap) {
4660 WMA_LOGE("%s: Hotlist AP's list invalid", __func__);
4661 return -EINVAL;
4662 }
4663 dest_hotlist = cdf_mem_malloc(sizeof(*dest_hotlist) +
4664 sizeof(*dest_ap) * numap);
4665 if (!dest_hotlist) {
4666 WMA_LOGE("%s: Allocation failed for hotlist buffer", __func__);
4667 return -ENOMEM;
4668 }
4669 dest_ap = &dest_hotlist->ap[0];
4670 dest_hotlist->numOfAps = event->total_entries;
4671 dest_hotlist->requestId = event->config_request_id;
4672
4673 if (event->first_entry_index +
4674 event->num_entries_in_page < event->total_entries)
4675 dest_hotlist->moreData = 1;
4676 else
4677 dest_hotlist->moreData = 0;
4678
4679 WMA_LOGD("%s: Hotlist match: requestId: %u,"
4680 "numOfAps: %d", __func__,
4681 dest_hotlist->requestId, dest_hotlist->numOfAps);
4682
4683 /*
4684 * Currently firmware sends only one bss information in-case
4685 * of both hotlist ap found and lost.
4686 */
4687 for (j = 0; j < numap; j++) {
4688 dest_ap->rssi = 0;
4689 dest_ap->channel = src_hotlist->channel;
4690 dest_ap->ts = src_hotlist->tstamp;
4691 ap_found = src_hotlist->flags & WMI_HOTLIST_FLAG_PRESENCE;
4692 dest_ap->rtt = src_hotlist->rtt;
4693 dest_ap->rtt_sd = src_hotlist->rtt_sd;
4694 dest_ap->beaconPeriod = src_hotlist->beacon_interval;
4695 dest_ap->capability = src_hotlist->capabilities;
4696 dest_ap->ieLength = src_hotlist->ie_length;
4697 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_hotlist->bssid,
4698 dest_ap->bssid.bytes);
4699 cdf_mem_copy(dest_ap->ssid, src_hotlist->ssid.ssid,
4700 src_hotlist->ssid.ssid_len);
4701 dest_ap->ssid[src_hotlist->ssid.ssid_len] = '\0';
4702 dest_ap++;
4703 src_hotlist++;
4704 }
4705 dest_hotlist->ap_found = ap_found;
4706 pMac->sme.pExtScanIndCb(pMac->hHdd,
4707 eSIR_EXTSCAN_HOTLIST_MATCH_IND, dest_hotlist);
4708 WMA_LOGI("%s: sending hotlist match event to hdd", __func__);
4709 cdf_mem_free(dest_hotlist);
4710 return 0;
4711}
4712
4713/** wma_extscan_find_unique_scan_ids() - find unique scan ids
4714 * @cmd_param_info: event data.
4715 *
4716 * This utility function parses the input bss table of information
4717 * and find the unique number of scan ids
4718 *
4719 * Return: 0 on success; error number otherwise
4720 */
4721static int wma_extscan_find_unique_scan_ids(const u_int8_t *cmd_param_info)
4722{
4723 WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf;
4724 wmi_extscan_cached_results_event_fixed_param *event;
4725 wmi_extscan_wlan_descriptor *src_hotlist;
4726 wmi_extscan_rssi_info *src_rssi;
4727 int prev_scan_id, scan_ids_cnt, i;
4728
4729 param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *)
4730 cmd_param_info;
4731 event = param_buf->fixed_param;
4732 src_hotlist = param_buf->bssid_list;
4733 src_rssi = param_buf->rssi_list;
4734
4735 /* Find the unique number of scan_id's for grouping */
4736 prev_scan_id = src_rssi->scan_cycle_id;
4737 scan_ids_cnt = 1;
4738 for (i = 1; i < event->num_entries_in_page; i++) {
4739 src_rssi++;
4740
4741 if (prev_scan_id != src_rssi->scan_cycle_id) {
4742 scan_ids_cnt++;
4743 prev_scan_id = src_rssi->scan_cycle_id;
4744 }
4745 }
4746
4747 return scan_ids_cnt;
4748}
4749
4750/** wma_fill_num_results_per_scan_id() - fill number of bss per scan id
4751 * @cmd_param_info: event data.
4752 * @scan_id_group: pointer to scan id group.
4753 *
4754 * This utility function parses the input bss table of information
4755 * and finds how many bss are there per unique scan id.
4756 *
4757 * Return: 0 on success; error number otherwise
4758 */
4759static int wma_fill_num_results_per_scan_id(const u_int8_t *cmd_param_info,
4760 struct extscan_cached_scan_result *scan_id_group)
4761{
4762 WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf;
4763 wmi_extscan_cached_results_event_fixed_param *event;
4764 wmi_extscan_wlan_descriptor *src_hotlist;
4765 wmi_extscan_rssi_info *src_rssi;
4766 struct extscan_cached_scan_result *t_scan_id_grp;
4767 int i, prev_scan_id;
4768
4769 param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *)
4770 cmd_param_info;
4771 event = param_buf->fixed_param;
4772 src_hotlist = param_buf->bssid_list;
4773 src_rssi = param_buf->rssi_list;
4774 t_scan_id_grp = scan_id_group;
4775
4776 prev_scan_id = src_rssi->scan_cycle_id;
4777
4778 t_scan_id_grp->scan_id = src_rssi->scan_cycle_id;
4779 t_scan_id_grp->flags = src_rssi->flags;
4780 t_scan_id_grp->num_results = 1;
4781 for (i = 1; i < event->num_entries_in_page; i++) {
4782 src_rssi++;
4783 if (prev_scan_id == src_rssi->scan_cycle_id) {
4784 t_scan_id_grp->num_results++;
4785 } else {
4786 t_scan_id_grp++;
4787 prev_scan_id = t_scan_id_grp->scan_id =
4788 src_rssi->scan_cycle_id;
4789 t_scan_id_grp->flags = src_rssi->flags;
4790 t_scan_id_grp->num_results = 1;
4791 }
4792 }
4793 return 0;
4794}
4795
4796/** wma_group_num_bss_to_scan_id() - group bss to scan id table
4797 * @cmd_param_info: event data.
4798 * @cached_result: pointer to cached table.
4799 *
4800 * This function reads the bss information from the format
4801 * ------------------------------------------------------------------------
4802 * | bss info {rssi, channel, ssid, bssid, timestamp} | scan id_1 | flags |
4803 * | bss info {rssi, channel, ssid, bssid, timestamp} | scan id_2 | flags |
4804 * ........................................................................
4805 * | bss info {rssi, channel, ssid, bssid, timestamp} | scan id_N | flags |
4806 * ------------------------------------------------------------------------
4807 *
4808 * and converts it into the below format and store it
4809 *
4810 * ------------------------------------------------------------------------
4811 * | scan id_1 | -> bss info_1 -> bss info_2 -> .... bss info_M1
4812 * | scan id_2 | -> bss info_1 -> bss info_2 -> .... bss info_M2
4813 * ......................
4814 * | scan id_N | -> bss info_1 -> bss info_2 -> .... bss info_Mn
4815 * ------------------------------------------------------------------------
4816 *
4817 * Return: 0 on success; error number otherwise
4818 */
4819static int wma_group_num_bss_to_scan_id(const u_int8_t *cmd_param_info,
4820 struct extscan_cached_scan_results *cached_result)
4821{
4822 WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf;
4823 wmi_extscan_cached_results_event_fixed_param *event;
4824 wmi_extscan_wlan_descriptor *src_hotlist;
4825 wmi_extscan_rssi_info *src_rssi;
4826 struct extscan_cached_scan_results *t_cached_result;
4827 struct extscan_cached_scan_result *t_scan_id_grp;
4828 int i, j;
4829 tSirWifiScanResult *ap;
4830
4831 param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *)
4832 cmd_param_info;
4833 event = param_buf->fixed_param;
4834 src_hotlist = param_buf->bssid_list;
4835 src_rssi = param_buf->rssi_list;
4836 t_cached_result = cached_result;
4837 t_scan_id_grp = &t_cached_result->result[0];
4838
4839 WMA_LOGD("%s: num_scan_ids:%d", __func__,
4840 t_cached_result->num_scan_ids);
4841 for (i = 0; i < t_cached_result->num_scan_ids; i++) {
4842 WMA_LOGD("%s: num_results:%d", __func__,
4843 t_scan_id_grp->num_results);
4844 t_scan_id_grp->ap = cdf_mem_malloc(t_scan_id_grp->num_results *
4845 sizeof(*ap));
4846 if (!t_scan_id_grp->ap) {
4847 WMA_LOGD("%s: cdf_mem_malloc failed", __func__);
4848 return -ENOMEM;
4849 }
4850
4851 ap = &t_scan_id_grp->ap[0];
4852 for (j = 0; j < t_scan_id_grp->num_results; j++) {
4853 ap->channel = src_hotlist->channel;
4854 ap->ts = WMA_MSEC_TO_USEC(src_rssi->tstamp);
4855 ap->rtt = src_hotlist->rtt;
4856 ap->rtt_sd = src_hotlist->rtt_sd;
4857 ap->beaconPeriod = src_hotlist->beacon_interval;
4858 ap->capability = src_hotlist->capabilities;
4859 ap->ieLength = src_hotlist->ie_length;
4860
4861 /* Firmware already applied noise floor adjustment and
4862 * due to WMI interface "UINT32 rssi", host driver
4863 * receives a positive value, hence convert to
4864 * signed char to get the absolute rssi.
4865 */
4866 ap->rssi = (signed char) src_rssi->rssi;
4867 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_hotlist->bssid,
4868 ap->bssid.bytes);
4869
4870 cdf_mem_copy(ap->ssid, src_hotlist->ssid.ssid,
4871 src_hotlist->ssid.ssid_len);
4872 ap->ssid[src_hotlist->ssid.ssid_len] = '\0';
4873 ap++;
4874 src_rssi++;
4875 src_hotlist++;
4876 }
4877 t_scan_id_grp++;
4878 }
4879 return 0;
4880}
4881
4882/**
4883 * wma_extscan_cached_results_event_handler() - cached results event handler
4884 * @handle: wma handle
4885 * @cmd_param_info: event buffer
4886 * @len: length of @cmd_param_info
4887 *
4888 * This function handles cached results event and indicate
4889 * cached results to upper layer.
4890 *
4891 * Return: 0 for success or error code.
4892 */
4893int wma_extscan_cached_results_event_handler(void *handle,
4894 uint8_t *cmd_param_info,
4895 uint32_t len)
4896{
4897 WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf;
4898 wmi_extscan_cached_results_event_fixed_param *event;
4899 struct extscan_cached_scan_results *dest_cachelist;
4900 struct extscan_cached_scan_result *dest_result;
4901 struct extscan_cached_scan_results empty_cachelist;
4902 wmi_extscan_wlan_descriptor *src_hotlist;
4903 wmi_extscan_rssi_info *src_rssi;
4904 int numap, i, moredata, scan_ids_cnt, buf_len;
4905
4906 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
4907 if (!pMac) {
4908 WMA_LOGE("%s: Invalid pMac", __func__);
4909 return -EINVAL;
4910 }
4911 if (!pMac->sme.pExtScanIndCb) {
4912 WMA_LOGE("%s: Callback not registered", __func__);
4913 return -EINVAL;
4914 }
4915 param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *)
4916 cmd_param_info;
4917 if (!param_buf) {
4918 WMA_LOGE("%s: Invalid cached results event", __func__);
4919 return -EINVAL;
4920 }
4921 event = param_buf->fixed_param;
4922 src_hotlist = param_buf->bssid_list;
4923 src_rssi = param_buf->rssi_list;
4924 numap = event->num_entries_in_page;
4925 WMA_LOGI("Total_entries %u first_entry_index %u", event->total_entries,
4926 event->first_entry_index);
4927 WMA_LOGI("num_entries_in_page %d", numap);
4928 if (!src_hotlist || !src_rssi || !numap) {
4929 WMA_LOGE("%s: Cached results empty, send 0 results", __func__);
4930 goto noresults;
4931 }
4932 if (event->first_entry_index +
4933 event->num_entries_in_page < event->total_entries)
4934 moredata = 1;
4935 else
4936 moredata = 0;
4937
4938 dest_cachelist = cdf_mem_malloc(sizeof(*dest_cachelist));
4939 if (!dest_cachelist) {
4940 WMA_LOGE("%s: cdf_mem_malloc failed", __func__);
4941 return -ENOMEM;
4942 }
4943 cdf_mem_zero(dest_cachelist, sizeof(*dest_cachelist));
4944 dest_cachelist->request_id = event->request_id;
4945 dest_cachelist->more_data = moredata;
4946
4947 scan_ids_cnt = wma_extscan_find_unique_scan_ids(cmd_param_info);
4948 WMA_LOGI("%s: scan_ids_cnt %d", __func__, scan_ids_cnt);
4949 dest_cachelist->num_scan_ids = scan_ids_cnt;
4950
4951 buf_len = sizeof(*dest_result) * scan_ids_cnt;
4952 dest_cachelist->result = cdf_mem_malloc(buf_len);
4953 if (!dest_cachelist->result) {
4954 WMA_LOGE("%s: Allocation failed for scanid grouping", __func__);
4955 cdf_mem_free(dest_cachelist);
4956 return -ENOMEM;
4957 }
4958
4959 dest_result = dest_cachelist->result;
4960 wma_fill_num_results_per_scan_id(cmd_param_info, dest_result);
4961 wma_group_num_bss_to_scan_id(cmd_param_info, dest_cachelist);
4962
4963 pMac->sme.pExtScanIndCb(pMac->hHdd,
4964 eSIR_EXTSCAN_CACHED_RESULTS_IND,
4965 dest_cachelist);
4966 WMA_LOGI("%s: sending cached results event", __func__);
4967 dest_result = dest_cachelist->result;
4968 for (i = 0; i < dest_cachelist->num_scan_ids; i++) {
4969 cdf_mem_free(dest_result->ap);
4970 dest_result++;
4971 }
4972 cdf_mem_free(dest_cachelist->result);
4973 cdf_mem_free(dest_cachelist);
4974 return 0;
4975
4976noresults:
4977 empty_cachelist.request_id = event->request_id;
4978 empty_cachelist.more_data = 0;
4979 empty_cachelist.num_scan_ids = 0;
4980
4981 pMac->sme.pExtScanIndCb(pMac->hHdd,
4982 eSIR_EXTSCAN_CACHED_RESULTS_IND,
4983 &empty_cachelist);
4984 WMA_LOGI("%s: sending cached results event", __func__);
4985 return 0;
4986}
4987
4988/**
4989 * wma_extscan_change_results_event_handler() - change results event handler
4990 * @handle: wma handle
4991 * @cmd_param_info: event buffer
4992 * @len: length
4993 *
4994 * This function handles change results event and indicate
4995 * change results to upper layer.
4996 *
4997 * Return: 0 for success or error code.
4998 */
4999int wma_extscan_change_results_event_handler(void *handle,
5000 uint8_t *cmd_param_info,
5001 uint32_t len)
5002{
5003 WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID_param_tlvs *param_buf;
5004 wmi_extscan_wlan_change_results_event_fixed_param *event;
5005 tSirWifiSignificantChangeEvent *dest_chglist;
5006 tSirWifiSignificantChange *dest_ap;
5007 wmi_extscan_wlan_change_result_bssid *src_chglist;
5008
5009 int numap;
5010 int i, k;
5011 uint8_t *src_rssi;
5012 int count = 0;
5013 int moredata;
5014 int rssi_num = 0;
5015 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
5016 if (!pMac) {
5017 WMA_LOGE("%s: Invalid pMac", __func__);
5018 return -EINVAL;
5019 }
5020 if (!pMac->sme.pExtScanIndCb) {
5021 WMA_LOGE("%s: Callback not registered", __func__);
5022 return -EINVAL;
5023 }
5024 param_buf = (WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID_param_tlvs *)
5025 cmd_param_info;
5026 if (!param_buf) {
5027 WMA_LOGE("%s: Invalid change monitor event", __func__);
5028 return -EINVAL;
5029 }
5030 event = param_buf->fixed_param;
5031 src_chglist = param_buf->bssid_signal_descriptor_list;
5032 src_rssi = param_buf->rssi_list;
5033 numap = event->num_entries_in_page;
5034
5035 if (!src_chglist || !numap) {
5036 WMA_LOGE("%s: Results invalid", __func__);
5037 return -EINVAL;
5038 }
5039 for (i = 0; i < numap; i++) {
5040 rssi_num += src_chglist->num_rssi_samples;
5041 }
5042 if (event->first_entry_index +
5043 event->num_entries_in_page < event->total_entries) {
5044 moredata = 1;
5045 } else {
5046 moredata = 0;
5047 }
5048 dest_chglist = cdf_mem_malloc(sizeof(*dest_chglist) +
5049 sizeof(*dest_ap) * numap +
5050 sizeof(int32_t) * rssi_num);
5051 if (!dest_chglist) {
5052 WMA_LOGE("%s: Allocation failed for change monitor", __func__);
5053 return -ENOMEM;
5054 }
5055 dest_ap = &dest_chglist->ap[0];
5056 for (i = 0; i < numap; i++) {
5057 dest_ap->channel = src_chglist->channel;
5058 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_chglist->bssid,
5059 dest_ap->bssid.bytes);
5060 dest_ap->numOfRssi = src_chglist->num_rssi_samples;
5061 if (dest_ap->numOfRssi) {
5062 for (k = 0; k < dest_ap->numOfRssi; k++) {
5063 dest_ap->rssi[k] = WMA_TGT_NOISE_FLOOR_DBM +
5064 src_rssi[count++];
5065 }
5066 }
5067 dest_ap += dest_ap->numOfRssi * sizeof(int32_t);
5068 src_chglist++;
5069 }
5070 dest_chglist->requestId = event->request_id;
5071 dest_chglist->moreData = moredata;
5072 dest_chglist->numResults = event->total_entries;
5073
5074 pMac->sme.pExtScanIndCb(pMac->hHdd,
5075 eSIR_EXTSCAN_SIGNIFICANT_WIFI_CHANGE_RESULTS_IND,
5076 dest_chglist);
5077 WMA_LOGI("%s: sending change monitor results", __func__);
5078 cdf_mem_free(dest_chglist);
5079 return 0;
5080}
5081
5082/**
5083 * wma_passpoint_match_event_handler() - passpoint match found event handler
5084 * @handle: WMA handle
5085 * @cmd_param_info: event data
5086 * @len: event data length
5087 *
5088 * This is the passpoint match found event handler; it reads event data from
5089 * @cmd_param_info and fill in the destination buffer and sends indication
5090 * up layer.
5091 *
5092 * Return: 0 on success; error number otherwise
5093 */
5094int wma_passpoint_match_event_handler(void *handle,
5095 uint8_t *cmd_param_info,
5096 uint32_t len)
5097{
5098 WMI_PASSPOINT_MATCH_EVENTID_param_tlvs *param_buf;
5099 wmi_passpoint_event_hdr *event;
5100 struct wifi_passpoint_match *dest_match;
5101 tSirWifiScanResult *dest_ap;
5102 uint8_t *buf_ptr;
5103 tpAniSirGlobal mac = cds_get_context(CDF_MODULE_ID_PE);
5104
5105 if (!mac) {
5106 WMA_LOGE("%s: Invalid mac", __func__);
5107 return -EINVAL;
5108 }
5109 if (!mac->sme.pExtScanIndCb) {
5110 WMA_LOGE("%s: Callback not registered", __func__);
5111 return -EINVAL;
5112 }
5113
5114 param_buf = (WMI_PASSPOINT_MATCH_EVENTID_param_tlvs *) cmd_param_info;
5115 if (!param_buf) {
5116 WMA_LOGE("%s: Invalid passpoint match event", __func__);
5117 return -EINVAL;
5118 }
5119 event = param_buf->fixed_param;
5120 buf_ptr = (uint8_t *)param_buf->fixed_param;
5121
5122 dest_match = cdf_mem_malloc(sizeof(*dest_match) +
5123 event->ie_length + event->anqp_length);
5124 if (!dest_match) {
5125 WMA_LOGE("%s: cdf_mem_malloc failed", __func__);
5126 return -EINVAL;
5127 }
5128 dest_ap = &dest_match->ap;
5129 dest_match->request_id = 0;
5130 dest_match->id = event->id;
5131 dest_match->anqp_len = event->anqp_length;
5132 WMA_LOGI("%s: passpoint match: id: %u anqp length %u", __func__,
5133 dest_match->id, dest_match->anqp_len);
5134
5135 dest_ap->channel = event->channel_mhz;
5136 dest_ap->ts = event->timestamp;
5137 dest_ap->rtt = event->rtt;
5138 dest_ap->rssi = event->rssi;
5139 dest_ap->rtt_sd = event->rtt_sd;
5140 dest_ap->beaconPeriod = event->beacon_period;
5141 dest_ap->capability = event->capability;
5142 dest_ap->ieLength = event->ie_length;
5143 WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->bssid, dest_ap->bssid.bytes);
5144 cdf_mem_copy(dest_ap->ssid, event->ssid.ssid,
5145 event->ssid.ssid_len);
5146 dest_ap->ssid[event->ssid.ssid_len] = '\0';
5147 cdf_mem_copy(dest_ap->ieData, buf_ptr + sizeof(*event) +
5148 WMI_TLV_HDR_SIZE, dest_ap->ieLength);
5149 cdf_mem_copy(dest_match->anqp, buf_ptr + sizeof(*event) +
5150 WMI_TLV_HDR_SIZE + dest_ap->ieLength,
5151 dest_match->anqp_len);
5152
5153 mac->sme.pExtScanIndCb(mac->hHdd,
5154 eSIR_PASSPOINT_NETWORK_FOUND_IND,
5155 dest_match);
5156 WMA_LOGI("%s: sending passpoint match event to hdd", __func__);
5157 cdf_mem_free(dest_match);
5158 return 0;
5159}
5160
5161/**
5162 * wma_extscan_hotlist_ssid_match_event_handler() -
5163 * Handler for SSID hotlist match event from firmware
5164 * @handle: WMA handle
5165 * @cmd_param_info: WMI command buffer
5166 * @len: length of @cmd_param_info
5167 *
5168 * Return: 0 on success, non-zero on failure
5169 */
5170int
5171wma_extscan_hotlist_ssid_match_event_handler(void *handle,
5172 uint8_t *cmd_param_info,
5173 uint32_t len)
5174{
5175 WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID_param_tlvs *param_buf;
5176 wmi_extscan_hotlist_ssid_match_event_fixed_param *event;
5177 tSirWifiScanResultEvent *dest_hotlist;
5178 tSirWifiScanResult *dest_ap;
5179 wmi_extscan_wlan_descriptor *src_hotlist;
5180 int numap, j;
5181 bool ssid_found = false;
5182 tpAniSirGlobal mac = cds_get_context(CDF_MODULE_ID_PE);
5183
5184 if (!mac) {
5185 WMA_LOGE("%s: Invalid mac", __func__);
5186 return -EINVAL;
5187 }
5188
5189 if (!mac->sme.pExtScanIndCb) {
5190 WMA_LOGE("%s: Callback not registered", __func__);
5191 return -EINVAL;
5192 }
5193
5194 param_buf = (WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID_param_tlvs *)
5195 cmd_param_info;
5196 if (!param_buf) {
5197 WMA_LOGE("%s: Invalid hotlist match event", __func__);
5198 return -EINVAL;
5199 }
5200
5201 event = param_buf->fixed_param;
5202 src_hotlist = param_buf->hotlist_ssid_match;
5203 numap = event->total_entries;
5204 if (!src_hotlist || !numap) {
5205 WMA_LOGE("%s: Hotlist AP's list invalid", __func__);
5206 return -EINVAL;
5207 }
5208
5209 dest_hotlist = cdf_mem_malloc(sizeof(*dest_hotlist) +
5210 sizeof(*dest_ap) * numap);
5211 if (!dest_hotlist) {
5212 WMA_LOGE("%s: Allocation failed for hotlist buffer",
5213 __func__);
5214 return -EINVAL;
5215 }
5216
5217 dest_ap = &dest_hotlist->ap[0];
5218 dest_hotlist->numOfAps = event->total_entries;
5219 dest_hotlist->requestId = event->config_request_id;
5220
5221 if (event->first_entry_index +
5222 event->num_entries_in_page < event->total_entries)
5223 dest_hotlist->moreData = 1;
5224 else
5225 dest_hotlist->moreData = 0;
5226
5227 WMA_LOGD("%s: Hotlist match: requestId: %u,numOfAps: %d", __func__,
5228 dest_hotlist->requestId, dest_hotlist->numOfAps);
5229
5230 for (j = 0; j < numap; j++) {
5231 dest_ap->channel = src_hotlist->channel;
5232 dest_ap->ts = src_hotlist->tstamp;
5233 ssid_found = src_hotlist->flags & WMI_HOTLIST_FLAG_PRESENCE;
5234 dest_ap->rtt = src_hotlist->rtt;
5235 dest_ap->rtt_sd = src_hotlist->rtt_sd;
5236 dest_ap->beaconPeriod = src_hotlist->beacon_interval;
5237 dest_ap->capability = src_hotlist->capabilities;
5238 dest_ap->ieLength = src_hotlist->ie_length;
5239 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_hotlist->bssid,
5240 dest_ap->bssid.bytes);
5241 cdf_mem_copy(dest_ap->ssid, src_hotlist->ssid.ssid,
5242 src_hotlist->ssid.ssid_len);
5243 dest_ap->ssid[src_hotlist->ssid.ssid_len] = '\0';
5244 dest_ap++;
5245 src_hotlist++;
5246 }
5247
5248 dest_hotlist->ap_found = ssid_found;
5249 mac->sme.pExtScanIndCb(mac->hHdd,
5250 eSIR_EXTSCAN_HOTLIST_SSID_MATCH_IND,
5251 dest_hotlist);
5252 WMA_LOGI("%s: sending hotlist ssid match event", __func__);
5253 cdf_mem_free(dest_hotlist);
5254 return 0;
5255}
5256
5257/**
5258 * wma_get_buf_extscan_start_cmd() - Fill extscan start request
5259 * @handle: wma handle
5260 * @pstart: scan command request params
5261 * @buf: event buffer
5262 * @buf_len: length of buffer
5263 *
5264 * This function fills individual elements of extscan request and
5265 * TLV for buckets, channel list.
5266 *
5267 * Return: CDF Status.
5268 */
5269CDF_STATUS wma_get_buf_extscan_start_cmd(tp_wma_handle wma_handle,
5270 tSirWifiScanCmdReqParams *pstart,
5271 wmi_buf_t *buf, int *buf_len)
5272{
5273 wmi_extscan_start_cmd_fixed_param *cmd;
5274 wmi_extscan_bucket *dest_blist;
5275 wmi_extscan_bucket_channel *dest_clist;
5276 tSirWifiScanBucketSpec *src_bucket = pstart->buckets;
5277 tSirWifiScanChannelSpec *src_channel = src_bucket->channels;
5278 tSirWifiScanChannelSpec save_channel[WLAN_EXTSCAN_MAX_CHANNELS];
5279
5280 uint8_t *buf_ptr;
5281 int i, k, count = 0;
5282 int len = sizeof(*cmd);
5283 int nbuckets = pstart->numBuckets;
5284 int nchannels = 0;
5285
5286 /* These TLV's are are NULL by default */
5287 uint32_t ie_len_with_pad = 0;
5288 int num_ssid = 0;
5289 int num_bssid = 0;
5290 int ie_len = 0;
5291
5292 uint32_t base_period = pstart->basePeriod;
5293
5294 /* TLV placeholder for ssid_list (NULL) */
5295 len += WMI_TLV_HDR_SIZE;
5296 len += num_ssid * sizeof(wmi_ssid);
5297
5298 /* TLV placeholder for bssid_list (NULL) */
5299 len += WMI_TLV_HDR_SIZE;
5300 len += num_bssid * sizeof(wmi_mac_addr);
5301
5302 /* TLV placeholder for ie_data (NULL) */
5303 len += WMI_TLV_HDR_SIZE;
5304 len += ie_len * sizeof(uint32_t);
5305
5306 /* TLV placeholder for bucket */
5307 len += WMI_TLV_HDR_SIZE;
5308 len += nbuckets * sizeof(wmi_extscan_bucket);
5309
5310 /* TLV channel placeholder */
5311 len += WMI_TLV_HDR_SIZE;
5312 for (i = 0; i < nbuckets; i++) {
5313 nchannels += src_bucket->numChannels;
5314 src_bucket++;
5315 }
5316
5317 WMA_LOGD("%s: Total buckets: %d total #of channels is %d",
5318 __func__, nbuckets, nchannels);
5319 len += nchannels * sizeof(wmi_extscan_bucket_channel);
5320 /* Allocate the memory */
5321 *buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5322 if (!*buf) {
5323 WMA_LOGP("%s: failed to allocate memory"
5324 " for start extscan cmd", __func__);
5325 return CDF_STATUS_E_NOMEM;
5326 }
5327 buf_ptr = (uint8_t *) wmi_buf_data(*buf);
5328 cmd = (wmi_extscan_start_cmd_fixed_param *) buf_ptr;
5329 WMITLV_SET_HDR(&cmd->tlv_header,
5330 WMITLV_TAG_STRUC_wmi_extscan_start_cmd_fixed_param,
5331 WMITLV_GET_STRUCT_TLVLEN
5332 (wmi_extscan_start_cmd_fixed_param));
5333
5334 cmd->request_id = pstart->requestId;
5335 cmd->vdev_id = pstart->sessionId;
5336 cmd->base_period = pstart->basePeriod;
5337 cmd->num_buckets = nbuckets;
5338 cmd->configuration_flags = 0;
5339 if (pstart->configuration_flags & EXTSCAN_LP_EXTENDED_BATCHING)
5340 cmd->configuration_flags |= WMI_EXTSCAN_EXTENDED_BATCHING_EN;
5341 WMA_LOGI("%s: configuration_flags: 0x%x", __func__,
5342 cmd->configuration_flags);
5343
5344 cmd->min_rest_time = WMA_EXTSCAN_REST_TIME;
5345 cmd->max_rest_time = WMA_EXTSCAN_REST_TIME;
5346 cmd->max_bssids_per_scan_cycle = pstart->maxAPperScan;
5347
5348 /* The max dwell time is retrieved from the first channel
5349 * of the first bucket and kept common for all channels.
5350 */
5351 cmd->min_dwell_time_active = pstart->min_dwell_time_active;
5352 cmd->max_dwell_time_active = pstart->max_dwell_time_active;
5353 cmd->min_dwell_time_passive = pstart->min_dwell_time_passive;
5354 cmd->max_dwell_time_passive = pstart->max_dwell_time_passive;
5355 cmd->max_bssids_per_scan_cycle = pstart->maxAPperScan;
5356 cmd->max_table_usage = pstart->report_threshold_percent;
5357 cmd->report_threshold_num_scans = pstart->report_threshold_num_scans;
5358
5359 cmd->repeat_probe_time = cmd->max_dwell_time_active /
5360 WMA_SCAN_NPROBES_DEFAULT;
5361 cmd->max_scan_time = WMA_EXTSCAN_MAX_SCAN_TIME;
5362 cmd->probe_delay = 0;
5363 cmd->probe_spacing_time = 0;
5364 cmd->idle_time = 0;
5365 cmd->burst_duration = WMA_EXTSCAN_BURST_DURATION;
5366 cmd->scan_ctrl_flags = WMI_SCAN_ADD_BCAST_PROBE_REQ |
5367 WMI_SCAN_ADD_CCK_RATES |
Sreelakshmi Konamki75deb332015-09-14 10:58:03 +05305368 WMI_SCAN_ADD_OFDM_RATES |
5369 WMI_SCAN_ADD_SPOOFED_MAC_IN_PROBE_REQ |
5370 WMI_SCAN_ADD_DS_IE_IN_PROBE_REQ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005371 cmd->scan_priority = WMI_SCAN_PRIORITY_HIGH;
5372 cmd->num_ssids = 0;
5373 cmd->num_bssid = 0;
5374 cmd->ie_len = 0;
5375 cmd->n_probes = (cmd->repeat_probe_time > 0) ?
5376 cmd->max_dwell_time_active / cmd->repeat_probe_time : 0;
5377
5378 buf_ptr += sizeof(*cmd);
5379 WMITLV_SET_HDR(buf_ptr,
5380 WMITLV_TAG_ARRAY_FIXED_STRUC,
5381 num_ssid * sizeof(wmi_ssid));
5382 buf_ptr += WMI_TLV_HDR_SIZE + (num_ssid * sizeof(wmi_ssid));
5383
5384 WMITLV_SET_HDR(buf_ptr,
5385 WMITLV_TAG_ARRAY_FIXED_STRUC,
5386 num_bssid * sizeof(wmi_mac_addr));
5387 buf_ptr += WMI_TLV_HDR_SIZE + (num_bssid * sizeof(wmi_mac_addr));
5388
5389 ie_len_with_pad = 0;
5390 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_with_pad);
5391 buf_ptr += WMI_TLV_HDR_SIZE + ie_len_with_pad;
5392
5393 WMITLV_SET_HDR(buf_ptr,
5394 WMITLV_TAG_ARRAY_STRUC,
5395 nbuckets * sizeof(wmi_extscan_bucket));
5396 dest_blist = (wmi_extscan_bucket *)
5397 (buf_ptr + WMI_TLV_HDR_SIZE);
5398 src_bucket = pstart->buckets;
5399
5400 /* Retrieve scanning information from each bucket and
5401 * channels and send it to the target
5402 */
5403 for (i = 0; i < nbuckets; i++) {
5404 WMITLV_SET_HDR(dest_blist,
5405 WMITLV_TAG_STRUC_wmi_extscan_bucket_cmd_fixed_param,
5406 WMITLV_GET_STRUCT_TLVLEN(wmi_extscan_bucket));
5407
5408 dest_blist->bucket_id = src_bucket->bucket;
5409 dest_blist->base_period_multiplier =
5410 src_bucket->period / base_period;
5411 dest_blist->min_period = src_bucket->period;
5412 dest_blist->max_period = src_bucket->max_period;
5413 dest_blist->exp_backoff = src_bucket->exponent;
5414 dest_blist->exp_max_step_count = src_bucket->step_count;
5415 dest_blist->channel_band = src_bucket->band;
5416 dest_blist->num_channels = src_bucket->numChannels;
5417 dest_blist->notify_extscan_events = 0;
5418
5419 if (src_bucket->reportEvents & EXTSCAN_REPORT_EVENTS_EACH_SCAN)
5420 dest_blist->notify_extscan_events =
5421 WMI_EXTSCAN_BUCKET_COMPLETED_EVENT;
5422
5423 if (src_bucket->reportEvents &
5424 EXTSCAN_REPORT_EVENTS_FULL_RESULTS) {
5425 dest_blist->forwarding_flags =
5426 WMI_EXTSCAN_FORWARD_FRAME_TO_HOST;
5427 dest_blist->notify_extscan_events |=
5428 WMI_EXTSCAN_BUCKET_COMPLETED_EVENT |
5429 WMI_EXTSCAN_CYCLE_STARTED_EVENT |
5430 WMI_EXTSCAN_CYCLE_COMPLETED_EVENT;
5431 } else {
5432 dest_blist->forwarding_flags =
5433 WMI_EXTSCAN_NO_FORWARDING;
5434 }
5435
5436 if (src_bucket->reportEvents & EXTSCAN_REPORT_EVENTS_NO_BATCH)
5437 dest_blist->configuration_flags = 0;
5438 else
5439 dest_blist->configuration_flags =
5440 WMI_EXTSCAN_BUCKET_CACHE_RESULTS;
5441
5442 WMA_LOGI("%s: ntfy_extscan_events:%u cfg_flags:%u fwd_flags:%u",
5443 __func__, dest_blist->notify_extscan_events,
5444 dest_blist->configuration_flags,
5445 dest_blist->forwarding_flags);
5446
5447 dest_blist->min_dwell_time_active = src_bucket->min_dwell_time_active;
5448 dest_blist->max_dwell_time_active = src_bucket->max_dwell_time_active;
5449 dest_blist->min_dwell_time_passive = src_bucket->min_dwell_time_passive;
5450 dest_blist->max_dwell_time_passive = src_bucket->max_dwell_time_passive;
5451 src_channel = src_bucket->channels;
5452
5453 /* save the channel info to later populate
5454 * the channel TLV
5455 */
5456 for (k = 0; k < src_bucket->numChannels; k++) {
5457 save_channel[count++].channel = src_channel->channel;
5458 src_channel++;
5459 }
5460 dest_blist++;
5461 src_bucket++;
5462 }
5463 buf_ptr += WMI_TLV_HDR_SIZE + (nbuckets * sizeof(wmi_extscan_bucket));
5464 WMITLV_SET_HDR(buf_ptr,
5465 WMITLV_TAG_ARRAY_STRUC,
5466 nchannels * sizeof(wmi_extscan_bucket_channel));
5467 dest_clist = (wmi_extscan_bucket_channel *)
5468 (buf_ptr + WMI_TLV_HDR_SIZE);
5469
5470 /* Active or passive scan is based on the bucket dwell time
5471 * and channel specific active,passive scans are not
5472 * supported yet
5473 */
5474 for (i = 0; i < nchannels; i++) {
5475 WMITLV_SET_HDR(dest_clist,
5476 WMITLV_TAG_STRUC_wmi_extscan_bucket_channel_event_fixed_param,
5477 WMITLV_GET_STRUCT_TLVLEN
5478 (wmi_extscan_bucket_channel));
5479 dest_clist->channel = save_channel[i].channel;
5480 dest_clist++;
5481 }
5482 buf_ptr += WMI_TLV_HDR_SIZE +
5483 (nchannels * sizeof(wmi_extscan_bucket_channel));
5484 *buf_len = len;
5485 return CDF_STATUS_SUCCESS;
5486}
5487
5488/**
5489 * wma_start_extscan() - start extscan command to fw.
5490 * @handle: wma handle
5491 * @pstart: scan command request params
5492 *
5493 * This function sends start extscan request to fw.
5494 *
5495 * Return: CDF Status.
5496 */
5497CDF_STATUS wma_start_extscan(tp_wma_handle wma,
5498 tSirWifiScanCmdReqParams *pstart)
5499{
5500 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
5501 wmi_buf_t buf;
5502 int len;
5503 if (!wma || !wma->wmi_handle) {
5504 WMA_LOGE("%s: WMA is closed,can not issue extscan cmd",
5505 __func__);
5506 return CDF_STATUS_E_INVAL;
5507 }
5508 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
5509 WMI_SERVICE_EXTSCAN)) {
5510 WMA_LOGE("%s: extscan feature bit not enabled", __func__);
5511 return CDF_STATUS_E_FAILURE;
5512 }
5513 /* Fill individual elements of extscan request and
5514 * TLV for buckets, channel list.
5515 */
5516 cdf_status = wma_get_buf_extscan_start_cmd(wma, pstart, &buf, &len);
5517 if (cdf_status != CDF_STATUS_SUCCESS) {
5518 WMA_LOGE("%s: Failed to get buffer for ext scan cmd", __func__);
5519 return CDF_STATUS_E_FAILURE;
5520 }
5521 if (!buf) {
5522 WMA_LOGE("%s:Failed to get buffer"
5523 "for current extscan info", __func__);
5524 return CDF_STATUS_E_FAILURE;
5525 }
5526 if (wmi_unified_cmd_send(wma->wmi_handle, buf,
5527 len, WMI_EXTSCAN_START_CMDID)) {
5528 WMA_LOGE("%s: failed to send command", __func__);
5529 cdf_nbuf_free(buf);
5530 return CDF_STATUS_E_FAILURE;
5531 }
5532 wma->interfaces[pstart->sessionId].extscan_in_progress = true;
5533 WMA_LOGD("Extscan start request sent successfully for vdev %d",
5534 pstart->sessionId);
5535
5536 return CDF_STATUS_SUCCESS;
5537}
5538
5539/**
5540 * wma_stop_extscan() - stop extscan command to fw.
5541 * @handle: wma handle
5542 * @pstopcmd: stop scan command request params
5543 *
5544 * This function sends stop extscan request to fw.
5545 *
5546 * Return: CDF Status.
5547 */
5548CDF_STATUS wma_stop_extscan(tp_wma_handle wma,
5549 tSirExtScanStopReqParams *pstopcmd)
5550{
5551 wmi_extscan_stop_cmd_fixed_param *cmd;
5552 wmi_buf_t wmi_buf;
5553 uint32_t len;
5554 uint8_t *buf_ptr;
5555
5556 if (!wma || !wma->wmi_handle) {
5557 WMA_LOGE("%s: WMA is closed, cannot issue cmd", __func__);
5558 return CDF_STATUS_E_INVAL;
5559 }
5560 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
5561 WMI_SERVICE_EXTSCAN)) {
5562 WMA_LOGE("%s: extscan not enabled", __func__);
5563 return CDF_STATUS_E_FAILURE;
5564 }
5565 len = sizeof(*cmd);
5566 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
5567 if (!wmi_buf) {
5568 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
5569 return CDF_STATUS_E_NOMEM;
5570 }
5571 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
5572 cmd = (wmi_extscan_stop_cmd_fixed_param *) buf_ptr;
5573 WMITLV_SET_HDR(&cmd->tlv_header,
5574 WMITLV_TAG_STRUC_wmi_extscan_stop_cmd_fixed_param,
5575 WMITLV_GET_STRUCT_TLVLEN
5576 (wmi_extscan_stop_cmd_fixed_param));
5577
5578 cmd->request_id = pstopcmd->requestId;
5579 cmd->vdev_id = pstopcmd->sessionId;
5580
5581 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
5582 WMI_EXTSCAN_STOP_CMDID)) {
5583 WMA_LOGE("%s: failed to command", __func__);
5584 cdf_nbuf_free(wmi_buf);
5585 return CDF_STATUS_E_FAILURE;
5586 }
5587 wma->interfaces[pstopcmd->sessionId].extscan_in_progress = false;
5588 WMA_LOGD("Extscan stop request sent successfully for vdev %d",
5589 pstopcmd->sessionId);
5590
5591 return CDF_STATUS_SUCCESS;
5592}
5593
5594/** wma_get_hotlist_entries_per_page() - hotlist entries per page
5595 * @wmi_handle: wmi handle.
5596 * @cmd: size of command structure.
5597 * @per_entry_size: per entry size.
5598 *
5599 * This utility function calculates how many hotlist entries can
5600 * fit in one page.
5601 *
5602 * Return: number of entries
5603 */
5604static inline int wma_get_hotlist_entries_per_page(wmi_unified_t wmi_handle,
5605 size_t cmd_size,
5606 size_t per_entry_size)
5607{
5608 uint32_t avail_space = 0;
5609 int num_entries = 0;
5610 uint16_t max_msg_len = wmi_get_max_msg_len(wmi_handle);
5611
5612 /* Calculate number of hotlist entries that can
5613 * be passed in wma message request.
5614 */
5615 avail_space = max_msg_len - cmd_size;
5616 num_entries = avail_space / per_entry_size;
5617 return num_entries;
5618}
5619
5620/**
5621 * wma_get_buf_extscan_hotlist_cmd() - prepare hotlist command
5622 * @handle: wma handle
5623 * @photlist: hotlist command params
5624 * @buf_len: buffer length
5625 *
5626 * This function fills individual elements for hotlist request and
5627 * TLV for bssid entries
5628 *
5629 * Return: CDF Status.
5630 */
5631CDF_STATUS wma_get_buf_extscan_hotlist_cmd(tp_wma_handle wma_handle,
5632 tSirExtScanSetBssidHotListReqParams *
5633 photlist, int *buf_len)
5634{
5635 wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *cmd = NULL;
5636 wmi_extscan_hotlist_entry *dest_hotlist;
5637 tSirAPThresholdParam *src_ap = photlist->ap;
5638 wmi_buf_t buf;
5639 uint8_t *buf_ptr;
5640
5641 int j, index = 0;
5642 int cmd_len = 0;
5643 int num_entries = 0;
5644 int min_entries = 0;
5645 int numap = photlist->numAp;
5646 int len = sizeof(*cmd);
5647
5648 len += WMI_TLV_HDR_SIZE;
5649 cmd_len = len;
5650
5651 /* setbssid hotlist expects the bssid list
5652 * to be non zero value
5653 */
5654 if (!numap) {
5655 WMA_LOGE("%s: Invalid number of bssid's", __func__);
5656 return CDF_STATUS_E_INVAL;
5657 }
5658 num_entries = wma_get_hotlist_entries_per_page(wma_handle->wmi_handle,
5659 cmd_len,
5660 sizeof(*dest_hotlist));
5661
5662 /* Split the hot list entry pages and send multiple command
5663 * requests if the buffer reaches the maximum request size
5664 */
5665 while (index < numap) {
5666 min_entries = CDF_MIN(num_entries, numap);
5667 len += min_entries * sizeof(wmi_extscan_hotlist_entry);
5668 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5669 if (!buf) {
5670 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
5671 return CDF_STATUS_E_FAILURE;
5672 }
5673 buf_ptr = (uint8_t *) wmi_buf_data(buf);
5674 cmd = (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *)
5675 buf_ptr;
5676 WMITLV_SET_HDR(&cmd->tlv_header,
5677 WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_monitor_cmd_fixed_param,
5678 WMITLV_GET_STRUCT_TLVLEN
5679 (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param));
5680
5681 /* Multiple requests are sent until the num_entries_in_page
5682 * matches the total_entries
5683 */
5684 cmd->request_id = photlist->requestId;
5685 cmd->vdev_id = photlist->sessionId;
5686 cmd->total_entries = numap;
5687 cmd->mode = 1;
5688 cmd->num_entries_in_page = min_entries;
5689 cmd->lost_ap_scan_count = photlist->lost_ap_sample_size;
5690 cmd->first_entry_index = index;
5691
5692 WMA_LOGD("%s: vdev id:%d total_entries: %d num_entries: %d lost_ap_sample_size: %d",
5693 __func__, cmd->vdev_id, cmd->total_entries,
5694 cmd->num_entries_in_page,
5695 cmd->lost_ap_scan_count);
5696
5697 buf_ptr += sizeof(*cmd);
5698 WMITLV_SET_HDR(buf_ptr,
5699 WMITLV_TAG_ARRAY_STRUC,
5700 min_entries * sizeof(wmi_extscan_hotlist_entry));
5701 dest_hotlist = (wmi_extscan_hotlist_entry *)
5702 (buf_ptr + WMI_TLV_HDR_SIZE);
5703
5704 /* Populate bssid, channel info and rssi
5705 * for the bssid's that are sent as hotlists.
5706 */
5707 for (j = 0; j < min_entries; j++) {
5708 WMITLV_SET_HDR(dest_hotlist,
5709 WMITLV_TAG_STRUC_wmi_extscan_bucket_cmd_fixed_param,
5710 WMITLV_GET_STRUCT_TLVLEN
5711 (wmi_extscan_hotlist_entry));
5712
5713 dest_hotlist->min_rssi = src_ap->low;
5714 WMI_CHAR_ARRAY_TO_MAC_ADDR(src_ap->bssid.bytes,
5715 &dest_hotlist->bssid);
5716
5717 WMA_LOGD("%s:channel:%d min_rssi %d",
5718 __func__, dest_hotlist->channel,
5719 dest_hotlist->min_rssi);
5720 WMA_LOGD
5721 ("%s: bssid mac_addr31to0: 0x%x, mac_addr47to32: 0x%x",
5722 __func__, dest_hotlist->bssid.mac_addr31to0,
5723 dest_hotlist->bssid.mac_addr47to32);
5724 dest_hotlist++;
5725 src_ap++;
5726 }
5727 buf_ptr += WMI_TLV_HDR_SIZE +
5728 (min_entries * sizeof(wmi_extscan_hotlist_entry));
5729
5730 if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
5731 WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID)) {
5732 WMA_LOGE("%s: failed to send command", __func__);
5733 cdf_nbuf_free(buf);
5734 return CDF_STATUS_E_FAILURE;
5735 }
5736 index = index + min_entries;
5737 num_entries = numap - min_entries;
5738 len = cmd_len;
5739 }
5740 return CDF_STATUS_SUCCESS;
5741}
5742
5743/**
5744 * wma_extscan_start_hotlist_monitor() - start hotlist monitor
5745 * @wma: wma handle
5746 * @photlist: hotlist request params
5747 *
5748 * This function configures hotlist monitor in fw.
5749 *
5750 * Return: CDF status
5751 */
5752CDF_STATUS wma_extscan_start_hotlist_monitor(tp_wma_handle wma,
5753 tSirExtScanSetBssidHotListReqParams
5754 *photlist)
5755{
5756 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
5757 int len;
5758
5759 if (!wma || !wma->wmi_handle) {
5760 WMA_LOGE("%s: WMA is closed, can not issue hotlist cmd",
5761 __func__);
5762 return CDF_STATUS_E_INVAL;
5763 }
5764 /* Fill individual elements for hotlist request and
5765 * TLV for bssid entries
5766 */
5767 cdf_status = wma_get_buf_extscan_hotlist_cmd(wma, photlist, &len);
5768 if (cdf_status != CDF_STATUS_SUCCESS) {
5769 WMA_LOGE("%s: Failed to get buffer"
5770 "for hotlist scan cmd", __func__);
5771 return CDF_STATUS_E_FAILURE;
5772 }
5773 return CDF_STATUS_SUCCESS;
5774}
5775
5776/**
5777 * wma_extscan_stop_hotlist_monitor() - stop hotlist monitor
5778 * @wma: wma handle
5779 * @photlist_reset: hotlist reset params
5780 *
5781 * This function configures hotlist monitor to stop in fw.
5782 *
5783 * Return: CDF status
5784 */
5785CDF_STATUS wma_extscan_stop_hotlist_monitor(tp_wma_handle wma,
5786 tSirExtScanResetBssidHotlistReqParams
5787 *photlist_reset)
5788{
5789 wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *cmd;
5790 wmi_buf_t wmi_buf;
5791 uint32_t len;
5792 uint8_t *buf_ptr;
5793 int hotlist_entries = 0;
5794
5795 if (!wma || !wma->wmi_handle) {
5796 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
5797 return CDF_STATUS_E_INVAL;
5798 }
5799 if (!photlist_reset) {
5800 WMA_LOGE("%s: Invalid reset hotlist buffer", __func__);
5801 return CDF_STATUS_E_INVAL;
5802 }
5803 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
5804 WMI_SERVICE_EXTSCAN)) {
5805 WMA_LOGE("%s: extscan not enabled", __func__);
5806 return CDF_STATUS_E_FAILURE;
5807 }
5808 len = sizeof(*cmd);
5809
5810 /* reset bssid hotlist with tlv set to 0 */
5811 len += WMI_TLV_HDR_SIZE;
5812 len += hotlist_entries * sizeof(wmi_extscan_hotlist_entry);
5813
5814 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
5815 if (!wmi_buf) {
5816 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
5817 return CDF_STATUS_E_NOMEM;
5818 }
5819
5820 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
5821 cmd = (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *)
5822 buf_ptr;
5823 WMITLV_SET_HDR(&cmd->tlv_header,
5824 WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_monitor_cmd_fixed_param,
5825 WMITLV_GET_STRUCT_TLVLEN
5826 (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param));
5827
5828 cmd->request_id = photlist_reset->requestId;
5829 cmd->vdev_id = photlist_reset->sessionId;
5830 cmd->mode = 0;
5831
5832 buf_ptr += sizeof(*cmd);
5833 WMITLV_SET_HDR(buf_ptr,
5834 WMITLV_TAG_ARRAY_STRUC,
5835 hotlist_entries * sizeof(wmi_extscan_hotlist_entry));
5836 buf_ptr += WMI_TLV_HDR_SIZE +
5837 (hotlist_entries * sizeof(wmi_extscan_hotlist_entry));
5838
5839 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
5840 WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID)) {
5841 WMA_LOGE("%s: failed to command", __func__);
5842 cdf_nbuf_free(wmi_buf);
5843 return CDF_STATUS_E_FAILURE;
5844 }
5845 return CDF_STATUS_SUCCESS;
5846}
5847
5848/**
5849 * wma_get_buf_extscan_change_monitor_cmd() - fill change monitor request
5850 * @wma: wma handle
5851 * @psigchange: change monitor request params
5852 * @buf: wmi buffer
5853 * @buf_len: buffer length
5854 *
5855 * This function fills elements of change monitor request buffer.
5856 *
5857 * Return: CDF status
5858 */
5859CDF_STATUS wma_get_buf_extscan_change_monitor_cmd(tp_wma_handle wma_handle,
5860 tSirExtScanSetSigChangeReqParams
5861 *psigchange, wmi_buf_t *buf,
5862 int *buf_len)
5863{
5864 wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *cmd;
5865 wmi_extscan_wlan_change_bssid_param *dest_chglist;
5866 uint8_t *buf_ptr;
5867 int j;
5868 int len = sizeof(*cmd);
5869 int numap = psigchange->numAp;
5870 tSirAPThresholdParam *src_ap = psigchange->ap;
5871
5872 if (!numap) {
5873 WMA_LOGE("%s: Invalid number of bssid's", __func__);
5874 return CDF_STATUS_E_INVAL;
5875 }
5876 len += WMI_TLV_HDR_SIZE;
5877 len += numap * sizeof(wmi_extscan_wlan_change_bssid_param);
5878
5879 *buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5880 if (!*buf) {
5881 WMA_LOGP("%s: failed to allocate memory for change monitor cmd",
5882 __func__);
5883 return CDF_STATUS_E_FAILURE;
5884 }
5885 buf_ptr = (uint8_t *) wmi_buf_data(*buf);
5886 cmd =
5887 (wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *)
5888 buf_ptr;
5889 WMITLV_SET_HDR(&cmd->tlv_header,
5890 WMITLV_TAG_STRUC_wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param,
5891 WMITLV_GET_STRUCT_TLVLEN
5892 (wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param));
5893
5894 cmd->request_id = psigchange->requestId;
5895 cmd->vdev_id = psigchange->sessionId;
5896 cmd->total_entries = numap;
5897 cmd->mode = 1;
5898 cmd->num_entries_in_page = numap;
5899 cmd->lost_ap_scan_count = psigchange->lostApSampleSize;
5900 cmd->max_rssi_samples = psigchange->rssiSampleSize;
5901 cmd->rssi_averaging_samples = psigchange->rssiSampleSize;
5902 cmd->max_out_of_range_count = psigchange->minBreaching;
5903
5904 buf_ptr += sizeof(*cmd);
5905 WMITLV_SET_HDR(buf_ptr,
5906 WMITLV_TAG_ARRAY_STRUC,
5907 numap * sizeof(wmi_extscan_wlan_change_bssid_param));
5908 dest_chglist = (wmi_extscan_wlan_change_bssid_param *)
5909 (buf_ptr + WMI_TLV_HDR_SIZE);
5910
5911 for (j = 0; j < numap; j++) {
5912 WMITLV_SET_HDR(dest_chglist,
5913 WMITLV_TAG_STRUC_wmi_extscan_bucket_cmd_fixed_param,
5914 WMITLV_GET_STRUCT_TLVLEN
5915 (wmi_extscan_wlan_change_bssid_param));
5916
5917 dest_chglist->lower_rssi_limit = src_ap->low;
5918 dest_chglist->upper_rssi_limit = src_ap->high;
5919 WMI_CHAR_ARRAY_TO_MAC_ADDR(src_ap->bssid.bytes,
5920 &dest_chglist->bssid);
5921
5922 WMA_LOGD("%s: min_rssi %d", __func__,
5923 dest_chglist->lower_rssi_limit);
5924 dest_chglist++;
5925 src_ap++;
5926 }
5927 buf_ptr += WMI_TLV_HDR_SIZE +
5928 (numap * sizeof(wmi_extscan_wlan_change_bssid_param));
5929 *buf_len = len;
5930 return CDF_STATUS_SUCCESS;
5931}
5932
5933/**
5934 * wma_extscan_start_change_monitor() - send start change monitor cmd
5935 * @wma: wma handle
5936 * @psigchange: change monitor request params
5937 *
5938 * This function sends start change monitor request to fw.
5939 *
5940 * Return: CDF status
5941 */
5942CDF_STATUS wma_extscan_start_change_monitor(tp_wma_handle wma,
5943 tSirExtScanSetSigChangeReqParams *
5944 psigchange)
5945{
5946 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
5947 wmi_buf_t buf;
5948 int len;
5949
5950 if (!wma || !wma->wmi_handle) {
5951 WMA_LOGE("%s: WMA is closed,can not issue extscan cmd",
5952 __func__);
5953 return CDF_STATUS_E_INVAL;
5954 }
5955 /* Fill individual elements of change monitor and
5956 * TLV info ... */
5957
5958 cdf_status = wma_get_buf_extscan_change_monitor_cmd(wma,
5959 psigchange, &buf,
5960 &len);
5961 if (cdf_status != CDF_STATUS_SUCCESS) {
5962 WMA_LOGE("%s: Failed to get buffer for change monitor cmd",
5963 __func__);
5964 return CDF_STATUS_E_FAILURE;
5965 }
5966 if (!buf) {
5967 WMA_LOGE("%s: Failed to get buffer", __func__);
5968 return CDF_STATUS_E_FAILURE;
5969 }
5970 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5971 WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID)) {
5972 WMA_LOGE("%s: failed to send command", __func__);
5973 cdf_nbuf_free(buf);
5974 return CDF_STATUS_E_FAILURE;
5975 }
5976 return CDF_STATUS_SUCCESS;
5977}
5978
5979/**
5980 * wma_extscan_stop_change_monitor() - send stop change monitor cmd
5981 * @wma: wma handle
5982 * @pResetReq: Reset change request params
5983 *
5984 * This function sends stop change monitor request to fw.
5985 *
5986 * Return: CDF status
5987 */
5988CDF_STATUS wma_extscan_stop_change_monitor(tp_wma_handle wma,
5989 tSirExtScanResetSignificantChangeReqParams
5990 *pResetReq)
5991{
5992 wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *cmd;
5993 wmi_buf_t wmi_buf;
5994 uint32_t len;
5995 uint8_t *buf_ptr;
5996 int change_list = 0;
5997
5998 if (!wma || !wma->wmi_handle) {
5999 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
6000 return CDF_STATUS_E_INVAL;
6001 }
6002 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
6003 WMI_SERVICE_EXTSCAN)) {
6004 WMA_LOGE("%s: ext scan not enabled", __func__);
6005 return CDF_STATUS_E_FAILURE;
6006 }
6007 len = sizeof(*cmd);
6008
6009 /* reset significant change tlv is set to 0 */
6010 len += WMI_TLV_HDR_SIZE;
6011 len += change_list * sizeof(wmi_extscan_wlan_change_bssid_param);
6012 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
6013 if (!wmi_buf) {
6014 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
6015 return CDF_STATUS_E_NOMEM;
6016 }
6017 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
6018
6019 cmd = (wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *)
6020 buf_ptr;
6021 WMITLV_SET_HDR(&cmd->tlv_header,
6022 WMITLV_TAG_STRUC_wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param,
6023 WMITLV_GET_STRUCT_TLVLEN
6024 (wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param));
6025
6026 cmd->request_id = pResetReq->requestId;
6027 cmd->vdev_id = pResetReq->sessionId;
6028 cmd->mode = 0;
6029
6030 buf_ptr += sizeof(*cmd);
6031 WMITLV_SET_HDR(buf_ptr,
6032 WMITLV_TAG_ARRAY_STRUC,
6033 change_list *
6034 sizeof(wmi_extscan_wlan_change_bssid_param));
6035 buf_ptr += WMI_TLV_HDR_SIZE + (change_list *
6036 sizeof
6037 (wmi_extscan_wlan_change_bssid_param));
6038
6039 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
6040 WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID)) {
6041 WMA_LOGE("%s: failed to command", __func__);
6042 cdf_nbuf_free(wmi_buf);
6043 return CDF_STATUS_E_FAILURE;
6044 }
6045 return CDF_STATUS_SUCCESS;
6046}
6047
6048/**
6049 * wma_extscan_get_cached_results() - extscan get cached results
6050 * @wma: wma handle
6051 * @pcached_results: cached results parameters
6052 *
6053 * This function send request to fw to get cached results.
6054 *
6055 * Return: CDF status
6056 */
6057CDF_STATUS wma_extscan_get_cached_results(tp_wma_handle wma,
6058 tSirExtScanGetCachedResultsReqParams *
6059 pcached_results)
6060{
6061 wmi_extscan_get_cached_results_cmd_fixed_param *cmd;
6062 wmi_buf_t wmi_buf;
6063 uint32_t len;
6064 uint8_t *buf_ptr;
6065
6066 if (!wma || !wma->wmi_handle) {
6067 WMA_LOGE("%s: WMA is closed, cannot issue cmd", __func__);
6068 return CDF_STATUS_E_INVAL;
6069 }
6070 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
6071 WMI_SERVICE_EXTSCAN)) {
6072 WMA_LOGE("%s: extscan not enabled", __func__);
6073 return CDF_STATUS_E_FAILURE;
6074 }
6075 len = sizeof(*cmd);
6076 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
6077 if (!wmi_buf) {
6078 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
6079 return CDF_STATUS_E_NOMEM;
6080 }
6081 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
6082
6083 cmd = (wmi_extscan_get_cached_results_cmd_fixed_param *) buf_ptr;
6084 WMITLV_SET_HDR(&cmd->tlv_header,
6085 WMITLV_TAG_STRUC_wmi_extscan_get_cached_results_cmd_fixed_param,
6086 WMITLV_GET_STRUCT_TLVLEN
6087 (wmi_extscan_get_cached_results_cmd_fixed_param));
6088
6089 cmd->request_id = pcached_results->requestId;
6090 cmd->vdev_id = pcached_results->sessionId;
6091 cmd->control_flags = pcached_results->flush;
6092
6093 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
6094 WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID)) {
6095 WMA_LOGE("%s: failed to command", __func__);
6096 cdf_nbuf_free(wmi_buf);
6097 return CDF_STATUS_E_FAILURE;
6098 }
6099 return CDF_STATUS_SUCCESS;
6100}
6101
6102/**
6103 * wma_extscan_get_capabilities() - extscan get capabilities
6104 * @wma: wma handle
6105 * @pgetcapab: get capabilities params
6106 *
6107 * This function send request to fw to get extscan capabilities.
6108 *
6109 * Return: CDF status
6110 */
6111CDF_STATUS wma_extscan_get_capabilities(tp_wma_handle wma,
6112 tSirGetExtScanCapabilitiesReqParams *
6113 pgetcapab)
6114{
6115 wmi_extscan_get_capabilities_cmd_fixed_param *cmd;
6116 wmi_buf_t wmi_buf;
6117 uint32_t len;
6118 uint8_t *buf_ptr;
6119
6120 if (!wma || !wma->wmi_handle) {
6121 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
6122 return CDF_STATUS_E_INVAL;
6123 }
6124 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
6125 WMI_SERVICE_EXTSCAN)) {
6126 WMA_LOGE("%s: extscan not enabled", __func__);
6127 return CDF_STATUS_E_FAILURE;
6128 }
6129 len = sizeof(*cmd);
6130 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
6131 if (!wmi_buf) {
6132 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
6133 return CDF_STATUS_E_NOMEM;
6134 }
6135 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
6136
6137 cmd = (wmi_extscan_get_capabilities_cmd_fixed_param *) buf_ptr;
6138 WMITLV_SET_HDR(&cmd->tlv_header,
6139 WMITLV_TAG_STRUC_wmi_extscan_get_capabilities_cmd_fixed_param,
6140 WMITLV_GET_STRUCT_TLVLEN
6141 (wmi_extscan_get_capabilities_cmd_fixed_param));
6142
6143 cmd->request_id = pgetcapab->requestId;
6144
6145 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
6146 WMI_EXTSCAN_GET_CAPABILITIES_CMDID)) {
6147 WMA_LOGE("%s: failed to command", __func__);
6148 cdf_nbuf_free(wmi_buf);
6149 return CDF_STATUS_E_FAILURE;
6150 }
6151 return CDF_STATUS_SUCCESS;
6152}
6153
6154CDF_STATUS wma_ipa_offload_enable_disable(tp_wma_handle wma,
6155 struct sir_ipa_offload_enable_disable *ipa_offload)
6156{
6157 wmi_ipa_offload_enable_disable_cmd_fixed_param *cmd;
6158 wmi_buf_t wmi_buf;
6159 uint32_t len;
6160 u_int8_t *buf_ptr;
6161 ol_txrx_vdev_handle vdev;
6162 struct txrx_pdev_cfg_t *cfg;
6163 int32_t intra_bss_fwd = 0;
6164
6165 if (!wma || !wma->wmi_handle) {
6166 WMA_LOGE("%s: WMA is closed, can not issue cmd",
6167 __func__);
6168 return CDF_STATUS_E_INVAL;
6169 }
6170
6171 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
6172 ((ipa_offload->offload_type == AP_RX_DATA_OFFLOAD) ?
6173 WMI_SERVICE_HSOFFLOAD :
6174 WMI_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT))) {
6175 WMA_LOGE("%s: %s not supported", __func__,
6176 ((ipa_offload->offload_type == AP_RX_DATA_OFFLOAD) ?
6177 "WMI_SERVICE_HSOFFLOAD" :
6178 "WMI_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT"));
6179 return CDF_STATUS_E_FAILURE;
6180 }
6181
6182 if (ipa_offload->offload_type > STA_RX_DATA_OFFLOAD) {
6183 return CDF_STATUS_E_INVAL;
6184 }
6185
6186 len = sizeof(*cmd);
6187 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
6188 if (!wmi_buf) {
6189 WMA_LOGE("%s: wmi_buf_alloc failed (len=%d)", __func__, len);
6190 return CDF_STATUS_E_NOMEM;
6191 }
6192
6193 WMA_LOGE("%s: offload_type=%d, enable=%d", __func__,
6194 ipa_offload->offload_type, ipa_offload->enable);
6195
6196 buf_ptr = (u_int8_t *)wmi_buf_data(wmi_buf);
6197
6198 cmd = (wmi_ipa_offload_enable_disable_cmd_fixed_param *)buf_ptr;
6199 WMITLV_SET_HDR(&cmd->tlv_header,
6200 WMITLV_TAG_STRUCT_wmi_ipa_offload_enable_disable_cmd_fixed_param,
6201 WMITLV_GET_STRUCT_TLVLEN(
6202 wmi_ipa_offload_enable_disable_cmd_fixed_param));
6203
6204 cmd->offload_type = ipa_offload->offload_type;
6205 cmd->vdev_id = ipa_offload->vdev_id;
6206 cmd->enable = ipa_offload->enable;
6207
6208 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
6209 WMI_IPA_OFFLOAD_ENABLE_DISABLE_CMDID)) {
6210 WMA_LOGE("%s: failed to command", __func__);
6211 wmi_buf_free(wmi_buf);
6212 return CDF_STATUS_E_FAILURE;
6213 }
6214
6215 /*
6216 * Check if VDEV is already deleted. If deleted, don't
6217 * send INTRA BSS FWD WMI command
6218 */
6219 vdev = wma_find_vdev_by_id(wma, ipa_offload->vdev_id);
6220 if (!vdev)
6221 return CDF_STATUS_SUCCESS;
6222
6223 /* Disable Intra-BSS FWD offload when gDisableIntraBssFwd=1 in INI */
6224 cfg = (struct txrx_pdev_cfg_t *)vdev->pdev->ctrl_pdev;
6225 if (!ipa_offload->enable || cfg->rx_fwd_disabled) {
6226 WMA_LOGE("%s: ipa_offload->enable=%d, rx_fwd_disabled=%d",
6227 __func__,
6228 ipa_offload->enable, cfg->rx_fwd_disabled);
6229 intra_bss_fwd = 1;
6230 }
6231
6232 /* Disable/enable WMI_VDEV_PARAM_INTRA_BSS_FWD */
6233 if (wmi_unified_vdev_set_param_send(wma->wmi_handle,
6234 ipa_offload->vdev_id, WMI_VDEV_PARAM_INTRA_BSS_FWD,
6235 intra_bss_fwd)) {
6236 WMA_LOGE("Failed to disable WMI_VDEV_PARAM_INTRA_BSS_FWD");
6237 return CDF_STATUS_E_FAILURE;
6238 }
6239
6240 return CDF_STATUS_SUCCESS;
6241}
6242
6243/** wma_set_epno_network_list() - set epno network list
6244 * @wma: WMA handle
6245 * @req: epno config params request structure
6246 *
6247 * This function reads the incoming epno config request structure
6248 * and constructs the WMI message to the firmware.
6249 *
6250 * Returns: 0 on success, error number otherwise
6251 */
6252CDF_STATUS wma_set_epno_network_list(tp_wma_handle wma,
6253 struct wifi_epno_params *req)
6254{
6255 wmi_nlo_config_cmd_fixed_param *cmd;
6256 nlo_configured_parameters *nlo_list;
6257 u_int8_t i, *buf_ptr;
6258 wmi_buf_t buf;
6259 uint32_t len;
6260 int ret;
6261
6262 WMA_LOGD("wma_set_epno_network_list");
6263
6264 if (!wma || !wma->wmi_handle) {
6265 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
6266 return CDF_STATUS_E_FAILURE;
6267 }
6268 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
6269 WMI_SERVICE_EXTSCAN)) {
6270 WMA_LOGE("%s: extscan not enabled", __func__);
6271 return CDF_STATUS_E_NOSUPPORT;
6272 }
6273
6274 /* TLV place holder for array of structures
6275 * nlo_configured_parameters(nlo_list) */
6276 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
6277 len += sizeof(nlo_configured_parameters) *
6278 CDF_MIN(req->num_networks, WMI_NLO_MAX_SSIDS);
Varun Reddy Yeturub43fda12015-09-10 18:16:21 -07006279 len += WMI_TLV_HDR_SIZE; /* TLV for channel_list */
6280 len += WMI_TLV_HDR_SIZE; /* TLV for channel prediction cfg*/
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006281
6282 buf = wmi_buf_alloc(wma->wmi_handle, len);
6283 if (!buf) {
6284 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
6285 return CDF_STATUS_E_NOMEM;
6286 }
6287
6288 cmd = (wmi_nlo_config_cmd_fixed_param *) wmi_buf_data(buf);
6289
6290 buf_ptr = (u_int8_t *) cmd;
6291 WMITLV_SET_HDR(&cmd->tlv_header,
6292 WMITLV_TAG_STRUC_wmi_nlo_config_cmd_fixed_param,
6293 WMITLV_GET_STRUCT_TLVLEN(
6294 wmi_nlo_config_cmd_fixed_param));
6295 cmd->vdev_id = req->session_id;
6296 cmd->flags = WMI_NLO_CONFIG_ENLO;
6297
6298 buf_ptr += sizeof(wmi_nlo_config_cmd_fixed_param);
6299
6300 cmd->no_of_ssids = CDF_MIN(req->num_networks, WMI_NLO_MAX_SSIDS);
6301 WMA_LOGD("SSID count: %d", cmd->no_of_ssids);
6302 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
6303 cmd->no_of_ssids * sizeof(nlo_configured_parameters));
6304 buf_ptr += WMI_TLV_HDR_SIZE;
6305
6306 nlo_list = (nlo_configured_parameters *) buf_ptr;
6307 for (i = 0; i < cmd->no_of_ssids; i++) {
6308 WMITLV_SET_HDR(&nlo_list[i].tlv_header,
6309 WMITLV_TAG_ARRAY_BYTE,
6310 WMITLV_GET_STRUCT_TLVLEN(nlo_configured_parameters));
6311 /* Copy ssid and it's length */
6312 nlo_list[i].ssid.valid = true;
6313 nlo_list[i].ssid.ssid.ssid_len = req->networks[i].ssid.length;
6314 cdf_mem_copy(nlo_list[i].ssid.ssid.ssid,
6315 req->networks[i].ssid.ssId,
6316 nlo_list[i].ssid.ssid.ssid_len);
6317 WMA_LOGD("index: %d ssid: %.*s len: %d", i,
6318 nlo_list[i].ssid.ssid.ssid_len,
6319 (char *) nlo_list[i].ssid.ssid.ssid,
6320 nlo_list[i].ssid.ssid.ssid_len);
6321
6322 /* Copy rssi threshold */
6323 nlo_list[i].rssi_cond.valid = true;
6324 nlo_list[i].rssi_cond.rssi =
6325 req->networks[i].rssi_threshold;
6326 WMA_LOGD("RSSI threshold : %d dBm",
6327 nlo_list[i].rssi_cond.rssi);
6328
6329 /* Copy pno flags */
6330 nlo_list[i].bcast_nw_type.valid = true;
6331 nlo_list[i].bcast_nw_type.bcast_nw_type =
6332 req->networks[i].flags;
6333 WMA_LOGD("PNO flags (%u)",
6334 nlo_list[i].bcast_nw_type.bcast_nw_type);
6335
6336 /* Copy auth bit field */
6337 nlo_list[i].auth_type.valid = true;
6338 nlo_list[i].auth_type.auth_type =
6339 req->networks[i].auth_bit_field;
6340 WMA_LOGD("Auth bit field (%u)",
6341 nlo_list[i].auth_type.auth_type);
6342 }
Varun Reddy Yeturub43fda12015-09-10 18:16:21 -07006343
6344 buf_ptr += cmd->no_of_ssids * sizeof(nlo_configured_parameters);
6345 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
6346 buf_ptr += WMI_TLV_HDR_SIZE;
6347
6348 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
6349 buf_ptr += WMI_TLV_HDR_SIZE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006350 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
6351 WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
6352 if (ret) {
6353 WMA_LOGE("%s: Failed to send nlo wmi cmd", __func__);
6354 wmi_buf_free(buf);
6355 return CDF_STATUS_E_FAILURE;
6356 }
6357
6358 WMA_LOGD("set ePNO list request sent successfully for vdev %d",
6359 req->session_id);
6360
6361 return CDF_STATUS_SUCCESS;
6362}
6363
6364/**
6365 * wma_set_passpoint_network_list() - set passpoint network list
6366 * @handle: WMA handle
6367 * @req: passpoint network request structure
6368 *
6369 * This function reads the incoming @req and fill in the destination
6370 * WMI structure and send down the passpoint configs down to the firmware
6371 *
6372 * Return: CDF_STATUS enumeration
6373 */
6374CDF_STATUS wma_set_passpoint_network_list(tp_wma_handle wma,
6375 struct wifi_passpoint_req *req)
6376{
6377 wmi_passpoint_config_cmd_fixed_param *cmd;
6378 u_int8_t i, j, *bytes;
6379 wmi_buf_t buf;
6380 uint32_t len;
6381 int ret;
6382
6383 WMA_LOGD("wma_set_passpoint_network_list");
6384
6385 if (!wma || !wma->wmi_handle) {
6386 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
6387 return CDF_STATUS_E_FAILURE;
6388 }
6389 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
6390 WMI_SERVICE_EXTSCAN)) {
6391 WMA_LOGE("%s: extscan not enabled", __func__);
6392 return CDF_STATUS_E_NOSUPPORT;
6393 }
6394
6395 len = sizeof(*cmd);
6396 for (i = 0; i < req->num_networks; i++) {
6397 buf = wmi_buf_alloc(wma->wmi_handle, len);
6398 if (!buf) {
6399 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
6400 return CDF_STATUS_E_NOMEM;
6401 }
6402
6403 cmd = (wmi_passpoint_config_cmd_fixed_param *)
6404 wmi_buf_data(buf);
6405
6406 WMITLV_SET_HDR(&cmd->tlv_header,
6407 WMITLV_TAG_STRUC_wmi_passpoint_config_cmd_fixed_param,
6408 WMITLV_GET_STRUCT_TLVLEN(
6409 wmi_passpoint_config_cmd_fixed_param));
6410 cmd->id = req->networks[i].id;
6411 WMA_LOGD("%s: network id: %u", __func__, cmd->id);
6412 cdf_mem_copy(cmd->realm, req->networks[i].realm,
6413 strlen(req->networks[i].realm) + 1);
6414 WMA_LOGD("%s: realm: %s", __func__, cmd->realm);
6415 for (j = 0; j < PASSPOINT_ROAMING_CONSORTIUM_ID_NUM; j++) {
6416 bytes = (uint8_t *) &req->networks[i].roaming_consortium_ids[j];
6417 WMA_LOGD("index: %d rcids: %02x %02x %02x %02x %02x %02x %02x %02x",
6418 j, bytes[0], bytes[1], bytes[2], bytes[3],
6419 bytes[4], bytes[5], bytes[6], bytes[7]);
6420
6421 cdf_mem_copy(&cmd->roaming_consortium_ids[j],
6422 &req->networks[i].roaming_consortium_ids[j],
6423 PASSPOINT_ROAMING_CONSORTIUM_ID_LEN);
6424 }
6425 cdf_mem_copy(cmd->plmn, req->networks[i].plmn,
6426 PASSPOINT_PLMN_ID_LEN);
6427 WMA_LOGD("%s: plmn: %02x:%02x:%02x", __func__,
6428 cmd->plmn[0], cmd->plmn[1], cmd->plmn[2]);
6429
6430 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
6431 WMI_PASSPOINT_LIST_CONFIG_CMDID);
6432 if (ret) {
6433 WMA_LOGE("%s: Failed to send set passpoint network list wmi cmd",
6434 __func__);
6435 wmi_buf_free(buf);
6436 return CDF_STATUS_E_FAILURE;
6437 }
6438 }
6439
6440 WMA_LOGD("Set passpoint network list request is sent successfully for vdev %d",
6441 req->session_id);
6442
6443 return CDF_STATUS_SUCCESS;
6444}
6445
6446/**
6447 * wma_reset_passpoint_network_list() - reset passpoint network list
6448 * @handle: WMA handle
6449 * @req: passpoint network request structure
6450 *
6451 * This function sends down WMI command with network id set to wildcard id.
6452 * firmware shall clear all the config entries
6453 *
6454 * Return: CDF_STATUS enumeration
6455 */
6456CDF_STATUS wma_reset_passpoint_network_list(tp_wma_handle wma,
6457 struct wifi_passpoint_req *req)
6458{
6459 wmi_passpoint_config_cmd_fixed_param *cmd;
6460 wmi_buf_t buf;
6461 uint32_t len;
6462 int ret;
6463
6464 WMA_LOGD("wma_reset_passpoint_network_list");
6465
6466 if (!wma || !wma->wmi_handle) {
6467 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
6468 return CDF_STATUS_E_FAILURE;
6469 }
6470 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
6471 WMI_SERVICE_EXTSCAN)) {
6472 WMA_LOGE("%s: extscan not enabled", __func__);
6473 return CDF_STATUS_E_NOSUPPORT;
6474 }
6475
6476 len = sizeof(*cmd);
6477 buf = wmi_buf_alloc(wma->wmi_handle, len);
6478 if (!buf) {
6479 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
6480 return CDF_STATUS_E_NOMEM;
6481 }
6482
6483 cmd = (wmi_passpoint_config_cmd_fixed_param *) wmi_buf_data(buf);
6484
6485 WMITLV_SET_HDR(&cmd->tlv_header,
6486 WMITLV_TAG_STRUC_wmi_passpoint_config_cmd_fixed_param,
6487 WMITLV_GET_STRUCT_TLVLEN(
6488 wmi_passpoint_config_cmd_fixed_param));
6489 cmd->id = WMI_PASSPOINT_NETWORK_ID_WILDCARD;
6490
6491 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
6492 WMI_PASSPOINT_LIST_CONFIG_CMDID);
6493 if (ret) {
6494 WMA_LOGE("%s: Failed to send reset passpoint network list wmi cmd",
6495 __func__);
6496 wmi_buf_free(buf);
6497 return CDF_STATUS_E_FAILURE;
6498 }
6499
6500 WMA_LOGD("Reset passpoint network list request is sent successfully for vdev %d",
6501 req->session_id);
6502
6503 return CDF_STATUS_SUCCESS;
6504}
6505
6506/**
6507 * wma_set_ssid_hotlist() - Handle an SSID hotlist set request
6508 * @wma: WMA handle
6509 * @request: SSID hotlist set request from SME
6510 *
6511 * Return: CDF_STATUS enumeration
6512 */
6513CDF_STATUS
6514wma_set_ssid_hotlist(tp_wma_handle wma,
6515 struct sir_set_ssid_hotlist_request *request)
6516{
6517 wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param *cmd;
6518 wmi_buf_t wmi_buf;
6519 uint32_t len;
6520 uint32_t array_size;
6521 uint8_t *buf_ptr;
6522
6523 if (!wma || !wma->wmi_handle) {
6524 WMA_LOGE("%s: WMA is closed, can not issue hotlist cmd",
6525 __func__);
6526 return CDF_STATUS_E_FAILURE;
6527 }
6528 if (!request) {
6529 WMA_LOGE("%s: Invalid request buffer", __func__);
6530 return CDF_STATUS_E_FAILURE;
6531 }
6532 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
6533 WMI_SERVICE_EXTSCAN)) {
6534 WMA_LOGE("%s: extscan not enabled",
6535 __func__);
6536 return CDF_STATUS_E_NOSUPPORT;
6537 }
6538
6539 /* length of fixed portion */
6540 len = sizeof(*cmd);
6541
6542 /* length of variable portion */
6543 array_size =
6544 request->ssid_count * sizeof(wmi_extscan_hotlist_ssid_entry);
6545 len += WMI_TLV_HDR_SIZE + array_size;
6546
6547 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
6548 if (!wmi_buf) {
6549 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
6550 return CDF_STATUS_E_NOMEM;
6551 }
6552
6553 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
6554 cmd = (wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param *)
6555 buf_ptr;
6556 WMITLV_SET_HDR
6557 (&cmd->tlv_header,
6558 WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param,
6559 WMITLV_GET_STRUCT_TLVLEN
6560 (wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param));
6561
6562 cmd->request_id = request->request_id;
6563 cmd->requestor_id = 0;
6564 cmd->vdev_id = request->session_id;
6565 cmd->table_id = 0;
6566 cmd->lost_ap_scan_count = request->lost_ssid_sample_size;
6567 cmd->total_entries = request->ssid_count;
6568 cmd->num_entries_in_page = request->ssid_count;
6569 cmd->first_entry_index = 0;
6570
6571 buf_ptr += sizeof(*cmd);
6572 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, array_size);
6573
6574 if (request->ssid_count) {
6575 wmi_extscan_hotlist_ssid_entry *entry;
6576 int i;
6577
6578 buf_ptr += WMI_TLV_HDR_SIZE;
6579 entry = (wmi_extscan_hotlist_ssid_entry *)buf_ptr;
6580 for (i = 0; i < request->ssid_count; i++) {
6581 WMITLV_SET_HDR
6582 (entry,
6583 WMITLV_TAG_ARRAY_STRUC,
6584 WMITLV_GET_STRUCT_TLVLEN
6585 (wmi_extscan_hotlist_ssid_entry));
6586 entry->ssid.ssid_len = request->ssids[i].ssid.length;
6587 cdf_mem_copy(entry->ssid.ssid,
6588 request->ssids[i].ssid.ssId,
6589 request->ssids[i].ssid.length);
6590 entry->band = request->ssids[i].band;
6591 entry->min_rssi = request->ssids[i].rssi_low;
6592 entry->max_rssi = request->ssids[i].rssi_high;
6593 entry++;
6594 }
6595 cmd->mode = WMI_EXTSCAN_MODE_START;
6596 } else {
6597 cmd->mode = WMI_EXTSCAN_MODE_STOP;
6598 }
6599
6600 if (wmi_unified_cmd_send
6601 (wma->wmi_handle, wmi_buf, len,
6602 WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID)) {
6603 WMA_LOGE("%s: failed to send command", __func__);
6604 wmi_buf_free(wmi_buf);
6605 return CDF_STATUS_E_FAILURE;
6606 }
6607 return CDF_STATUS_SUCCESS;
6608}
6609#endif
6610
6611/**
6612 * wma_scan_probe_setoui() - set scan probe OUI
6613 * @wma: wma handle
6614 * @psetoui: OUI parameters
6615 *
6616 * set scan probe OUI parameters in firmware
6617 *
6618 * Return: CDF status
6619 */
6620CDF_STATUS wma_scan_probe_setoui(tp_wma_handle wma, tSirScanMacOui *psetoui)
6621{
6622 wmi_scan_prob_req_oui_cmd_fixed_param *cmd;
6623 wmi_buf_t wmi_buf;
6624 uint32_t len;
6625 uint8_t *buf_ptr;
6626 uint32_t *oui_buf;
6627
6628 if (!wma || !wma->wmi_handle) {
6629 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
6630 return CDF_STATUS_E_INVAL;
6631 }
6632 len = sizeof(*cmd);
6633 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
6634 if (!wmi_buf) {
6635 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
6636 return CDF_STATUS_E_NOMEM;
6637 }
6638 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
6639 cmd = (wmi_scan_prob_req_oui_cmd_fixed_param *) buf_ptr;
6640 WMITLV_SET_HDR(&cmd->tlv_header,
6641 WMITLV_TAG_STRUC_wmi_scan_prob_req_oui_cmd_fixed_param,
6642 WMITLV_GET_STRUCT_TLVLEN
6643 (wmi_scan_prob_req_oui_cmd_fixed_param));
6644
6645 oui_buf = &cmd->prob_req_oui;
6646 cdf_mem_zero(oui_buf, sizeof(cmd->prob_req_oui));
6647 *oui_buf = psetoui->oui[0] << 16 | psetoui->oui[1] << 8
6648 | psetoui->oui[2];
6649 WMA_LOGD("%s: wma:oui received from hdd %08x", __func__,
6650 cmd->prob_req_oui);
6651
6652 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
6653 WMI_SCAN_PROB_REQ_OUI_CMDID)) {
6654 WMA_LOGE("%s: failed to send command", __func__);
6655 cdf_nbuf_free(wmi_buf);
6656 return CDF_STATUS_E_FAILURE;
6657 }
6658 return CDF_STATUS_SUCCESS;
6659}
6660
6661/**
6662 * wma_scan_event_callback() - scan event callback
6663 * @handle: wma handle
6664 * @data: event data
6665 * @len: data length
6666 *
6667 * This function process scan event and provide indication
6668 * to upper layers.
6669 *
6670 * Return: 0 for success or error code.
6671 */
6672int wma_scan_event_callback(WMA_HANDLE handle, uint8_t *data,
6673 uint32_t len)
6674{
6675 tp_wma_handle wma_handle = (tp_wma_handle) handle;
6676 WMI_SCAN_EVENTID_param_tlvs *param_buf = NULL;
6677 wmi_scan_event_fixed_param *wmi_event = NULL;
6678 tSirScanOffloadEvent *scan_event;
6679 uint8_t vdev_id;
6680 uint32_t scan_id;
6681
6682 param_buf = (WMI_SCAN_EVENTID_param_tlvs *) data;
6683 wmi_event = param_buf->fixed_param;
6684 vdev_id = wmi_event->vdev_id;
6685 scan_id = wma_handle->interfaces[vdev_id].scan_info.scan_id;
6686
6687 if (wma_handle->roam_preauth_scan_id == wmi_event->scan_id) {
6688 /* This is the scan requested by roam preauth set_channel operation */
6689
6690 if (wmi_event->event & WMI_SCAN_FINISH_EVENTS) {
6691 WMA_LOGE("roam scan complete: scan_id 0x%x, vdev_id %d",
6692 wmi_event->scan_id, vdev_id);
6693 /*wma_reset_scan_info(wma_handle, vdev_id);*/
6694 }
6695
6696 vdev_id = wmi_event->vdev_id;
6697 if (vdev_id >= wma_handle->max_bssid) {
6698 WMA_LOGE("%s:Invalid vdev_id %d wmi_event %p", __func__,
6699 vdev_id, wmi_event);
6700 return -EFAULT;
6701 }
6702
6703 wma_roam_preauth_scan_event_handler(wma_handle,
6704 vdev_id, wmi_event);
6705 return 0;
6706
6707 }
6708
6709 scan_event = (tSirScanOffloadEvent *) cdf_mem_malloc
6710 (sizeof(tSirScanOffloadEvent));
6711 if (!scan_event) {
6712 WMA_LOGE("Memory allocation failed for tSirScanOffloadEvent");
6713 return -ENOMEM;
6714 }
6715
6716 scan_event->event = wmi_event->event;
6717
6718 WMA_LOGI("WMA <-- wmi_scan_event : event %u, scan_id %u, "
6719 "freq %u, reason %u",
6720 wmi_event->event, wmi_event->scan_id,
6721 wmi_event->channel_freq, wmi_event->reason);
6722
6723 scan_event->scanId = wmi_event->scan_id;
6724 scan_event->chanFreq = wmi_event->channel_freq;
6725
6726 if (scan_event->scanId ==
6727 wma_handle->interfaces[vdev_id].p2p_scan_info.scan_id) {
6728 scan_event->p2pScanType = P2P_SCAN_TYPE_LISTEN;
6729 if (scan_event->event == SCAN_EVENT_COMPLETED)
6730 wma_reset_p2p_scan_info(wma_handle, vdev_id);
6731 }
6732 scan_event->sessionId = vdev_id;
6733
6734 if (wmi_event->reason == WMI_SCAN_REASON_COMPLETED ||
6735 wmi_event->reason == WMI_SCAN_REASON_TIMEDOUT)
6736 scan_event->reasonCode = eSIR_SME_SUCCESS;
6737 else
6738 scan_event->reasonCode = eSIR_SME_SCAN_FAILED;
6739
6740 switch (wmi_event->event) {
6741 case WMI_SCAN_EVENT_COMPLETED:
6742 case WMI_SCAN_EVENT_DEQUEUED:
6743 /*
6744 * return success always so that SME can pick whatever scan
6745 * results is available in scan cache(due to partial or
6746 * aborted scan)
6747 */
6748 scan_event->event = WMI_SCAN_EVENT_COMPLETED;
6749 scan_event->reasonCode = eSIR_SME_SUCCESS;
6750 break;
6751 case WMI_SCAN_EVENT_START_FAILED:
6752 scan_event->event = WMI_SCAN_EVENT_COMPLETED;
6753 scan_event->reasonCode = eSIR_SME_SCAN_FAILED;
6754 break;
6755 case WMI_SCAN_EVENT_PREEMPTED:
6756 WMA_LOGW("%s: Unhandled Scan Event WMI_SCAN_EVENT_PREEMPTED",
6757 __func__);
6758 break;
6759 case WMI_SCAN_EVENT_RESTARTED:
6760 WMA_LOGW("%s: Unhandled Scan Event WMI_SCAN_EVENT_RESTARTED",
6761 __func__);
6762 break;
6763 }
6764
6765 /* Stop the scan completion timeout if the event is WMI_SCAN_EVENT_COMPLETED */
6766 if (scan_event->event == (tSirScanEventType) WMI_SCAN_EVENT_COMPLETED) {
6767 WMA_LOGE(" scan complete - scan_id 0x%x, vdev_id %d",
6768 wmi_event->scan_id, vdev_id);
6769 }
6770
6771 wma_send_msg(wma_handle, WMA_RX_SCAN_EVENT, (void *)scan_event, 0);
6772 return 0;
6773}
6774
6775
6776/**
6777 * wma_roam_better_ap_handler() - better ap event handler
6778 * @wma: wma handle
6779 * @vdev_id: vdev id
6780 *
6781 * Handler for WMI_ROAM_REASON_BETTER_AP event from roam firmware in Rome.
6782 * This event means roam algorithm in Rome has found a better matching
6783 * candidate AP. The indication is sent to SME.
6784 *
6785 * Return: none
6786 */
6787void wma_roam_better_ap_handler(tp_wma_handle wma, uint32_t vdev_id)
6788{
6789 cds_msg_t cds_msg;
6790 tSirSmeCandidateFoundInd *candidate_ind;
6791
6792 /* abort existing scans from GUI, but not roaming preauth scan */
6793 if (wma->interfaces[vdev_id].scan_info.scan_id != 0 &&
6794 (wma->interfaces[vdev_id].scan_info.scan_id &
6795 WMA_HOST_ROAM_SCAN_REQID_PREFIX) !=
6796 WMA_HOST_ROAM_SCAN_REQID_PREFIX) {
6797 tAbortScanParams abortScan;
6798 abortScan.SessionId = vdev_id;
6799 wma_stop_scan(wma, &abortScan);
6800 }
6801
6802 candidate_ind = cdf_mem_malloc(sizeof(tSirSmeCandidateFoundInd));
6803 if (!candidate_ind) {
6804 WMA_LOGE("%s: Alloc failed for tSirSmeCandidateFoundInd",
6805 __func__);
6806 return;
6807 }
6808
6809 candidate_ind->messageType = eWNI_SME_CANDIDATE_FOUND_IND;
6810 candidate_ind->sessionId = vdev_id;
6811 candidate_ind->length = sizeof(tSirSmeCandidateFoundInd);
6812
6813 cds_msg.type = eWNI_SME_CANDIDATE_FOUND_IND;
6814 cds_msg.bodyptr = candidate_ind;
6815 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_INFO,
6816 FL("posting candidate ind to SME"));
6817
6818 if (CDF_STATUS_SUCCESS != cds_mq_post_message(CDS_MQ_ID_SME,
6819 (cds_msg_t *) &cds_msg)) {
6820 cdf_mem_free(candidate_ind);
6821 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
6822 FL("Failed to post candidate ind to SME"));
6823 }
6824}
6825
6826/**
6827 * wma_roam_event_callback() - roam event callback
6828 * @handle: wma handle
6829 * @event_buf: event buffer
6830 * @len: buffer length
6831 *
6832 * Handler for all events from roam engine in firmware
6833 *
6834 * Return: 0 for success or error code
6835 */
6836int wma_roam_event_callback(WMA_HANDLE handle, uint8_t *event_buf,
6837 uint32_t len)
6838{
6839 tp_wma_handle wma_handle = (tp_wma_handle) handle;
6840 WMI_ROAM_EVENTID_param_tlvs *param_buf;
6841 wmi_roam_event_fixed_param *wmi_event;
6842
6843 param_buf = (WMI_ROAM_EVENTID_param_tlvs *) event_buf;
6844 if (!param_buf) {
6845 WMA_LOGE("Invalid roam event buffer");
6846 return -EINVAL;
6847 }
6848
6849 wmi_event = param_buf->fixed_param;
6850 WMA_LOGD("%s: Reason %x for vdevid %x, rssi %d",
6851 __func__, wmi_event->reason, wmi_event->vdev_id,
6852 wmi_event->rssi);
6853
6854 switch (wmi_event->reason) {
6855 case WMI_ROAM_REASON_BMISS:
6856 WMA_LOGD("Beacon Miss for vdevid %x", wmi_event->vdev_id);
6857 wma_beacon_miss_handler(wma_handle, wmi_event->vdev_id);
6858 break;
6859 case WMI_ROAM_REASON_BETTER_AP:
6860 WMA_LOGD("%s:Better AP found for vdevid %x, rssi %d", __func__,
6861 wmi_event->vdev_id, wmi_event->rssi);
6862 wma_handle->suitable_ap_hb_failure = false;
6863 wma_roam_better_ap_handler(wma_handle, wmi_event->vdev_id);
6864 break;
6865 case WMI_ROAM_REASON_SUITABLE_AP:
6866 wma_handle->suitable_ap_hb_failure = true;
6867 WMA_LOGD("%s:Bmiss scan AP found for vdevid %x, rssi %d",
6868 __func__, wmi_event->vdev_id, wmi_event->rssi);
6869 wma_roam_better_ap_handler(wma_handle, wmi_event->vdev_id);
6870 break;
6871#ifdef WLAN_FEATURE_ROAM_OFFLOAD
6872 case WMI_ROAM_REASON_HO_FAILED:
6873 WMA_LOGE("LFR3:Hand-Off Failed for vdevid %x",
6874 wmi_event->vdev_id);
6875 wma_roam_ho_fail_handler(wma_handle, wmi_event->vdev_id);
6876 break;
6877#endif
6878 default:
6879 WMA_LOGD("%s:Unhandled Roam Event %x for vdevid %x", __func__,
6880 wmi_event->reason, wmi_event->vdev_id);
6881 break;
6882 }
6883 return 0;
6884}
6885
6886
6887/**
6888 * wma_set_rssi_monitoring() - set rssi monitoring
6889 * @handle: WMA handle
6890 * @req: rssi monitoring request structure
6891 *
6892 * This function reads the incoming @req and fill in the destination
6893 * WMI structure and send down the rssi monitoring configs down to the firmware
6894 *
6895 * Return: 0 on success; error number otherwise
6896 */
6897CDF_STATUS wma_set_rssi_monitoring(tp_wma_handle wma,
6898 struct rssi_monitor_req *req)
6899{
6900 wmi_rssi_breach_monitor_config_fixed_param *cmd;
6901 wmi_buf_t buf;
6902 int ret, len = sizeof(*cmd);
6903
6904 buf = wmi_buf_alloc(wma->wmi_handle, len);
6905 if (!buf) {
6906 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
6907 return CDF_STATUS_E_NOMEM;
6908 }
6909
6910 cmd = (wmi_rssi_breach_monitor_config_fixed_param *) wmi_buf_data(buf);
6911 WMITLV_SET_HDR(&cmd->tlv_header,
6912 WMITLV_TAG_STRUC_wmi_rssi_breach_monitor_config_fixed_param,
6913 WMITLV_GET_STRUCT_TLVLEN(
6914 wmi_rssi_breach_monitor_config_fixed_param));
6915
6916 cmd->vdev_id = req->session_id;
6917 cmd->request_id = req->request_id;
6918 cmd->lo_rssi_reenable_hysteresis = 0;
6919 cmd->hi_rssi_reenable_histeresis = 0;
6920 cmd->min_report_interval = 0;
6921 cmd->max_num_report = 1;
6922 if (req->control) {
6923 /* enable one threshold for each min/max */
6924 cmd->enabled_bitmap = 0x09;
6925 cmd->low_rssi_breach_threshold[0] = req->min_rssi;
6926 cmd->hi_rssi_breach_threshold[0] = req->max_rssi;
6927 } else {
6928 cmd->enabled_bitmap = 0;
6929 cmd->low_rssi_breach_threshold[0] = 0;
6930 cmd->hi_rssi_breach_threshold[0] = 0;
6931 }
6932
6933 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
6934 WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID);
6935 if (ret != EOK) {
6936 WMA_LOGE("Failed to send WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID");
6937 wmi_buf_free(buf);
6938 return CDF_STATUS_E_FAILURE;
6939 }
6940
6941 WMA_LOGI("Sent WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID to FW");
6942 return CDF_STATUS_SUCCESS;
6943}
6944
6945/**
6946 * wma_get_scan_id() - Generates scan id
6947 * @scan_id: Scan id
6948 *
6949 * This function generates the scan id.
6950 *
6951 * Return: CDF_STATUS
6952 */
6953
6954CDF_STATUS wma_get_scan_id(uint32_t *scan_id)
6955{
6956 tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA);
6957
6958 if (!scan_id) {
6959 WMA_LOGE("Scan_id is NULL");
6960 return CDF_STATUS_E_FAULT;
6961 }
6962
6963 /* host need to cycle through the lower 12 bits to generate ids */
6964 *scan_id = cdf_atomic_inc_return(&wma->scan_id_counter) &
6965 WMA_SCAN_ID_MASK;
6966 /*
6967 * Firmware expects the host scan request id appended
6968 * by PREFIX 0xA000
6969 */
6970 *scan_id = *scan_id | WMI_HOST_SCAN_REQ_ID_PREFIX;
6971 return CDF_STATUS_SUCCESS;
6972}
6973