1 /*
2 * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /**
21 * DOC: wma_scan_roam.c
22 * This file contains functions related to scan and
23 * roaming functionality.
24 */
25
26 /* Header files */
27
28 #include "wma.h"
29 #include "wma_api.h"
30 #include "cds_api.h"
31 #include "wmi_unified_api.h"
32 #include "wlan_qct_sys.h"
33 #include "wni_api.h"
34 #include "ani_global.h"
35 #include "wmi_unified.h"
36 #include "wni_cfg.h"
37 #include <cdp_txrx_peer_ops.h>
38 #include <cdp_txrx_cfg.h>
39 #include <cdp_txrx_ctrl.h>
40
41 #include "qdf_nbuf.h"
42 #include "qdf_types.h"
43 #include "qdf_mem.h"
44 #include "wlan_dlm_api.h"
45
46 #include "wma_types.h"
47 #include "lim_api.h"
48 #include "lim_session_utils.h"
49
50 #include "cds_utils.h"
51 #include "wlan_policy_mgr_api.h"
52 #include <wlan_utility.h>
53
54 #if !defined(REMOVE_PKT_LOG)
55 #include "pktlog_ac.h"
56 #endif /* REMOVE_PKT_LOG */
57
58 #include "dbglog_host.h"
59 #include "csr_api.h"
60 #include "ol_fw.h"
61
62 #include "wma_internal.h"
63 #if defined(CONFIG_HL_SUPPORT)
64 #include "wlan_tgt_def_config_hl.h"
65 #else
66 #include "wlan_tgt_def_config.h"
67 #endif
68 #include "wlan_reg_services_api.h"
69 #include "wlan_roam_debug.h"
70 #include "wlan_mlme_public_struct.h"
71 #include "wlan_mgmt_txrx_utils_api.h"
72
73 /* This is temporary, should be removed */
74 #include "ol_htt_api.h"
75 #include <cdp_txrx_handle.h>
76 #include "wma_he.h"
77 #include <wlan_scan_public_structs.h>
78 #include <wlan_scan_ucfg_api.h>
79 #include "wma_nan_datapath.h"
80 #include "wlan_mlme_api.h"
81 #include <wlan_mlme_main.h>
82 #include <wlan_crypto_global_api.h>
83 #include <cdp_txrx_mon.h>
84 #include <cdp_txrx_ctrl.h>
85 #include "wlan_dlm_api.h"
86 #include "wlan_cm_roam_api.h"
87 #ifdef FEATURE_WLAN_DIAG_SUPPORT /* FEATURE_WLAN_DIAG_SUPPORT */
88 #include "host_diag_core_log.h"
89 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
90 #include <../../core/src/wlan_cm_roam_i.h>
91 #include "wlan_cm_roam_api.h"
92 #include "wlan_mlo_mgr_roam.h"
93 #include "lim_mlo.h"
94 #include "wlan_dp_api.h"
95 #ifdef FEATURE_WLAN_EXTSCAN
96 #define WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION WAKELOCK_DURATION_RECOMMENDED
97
98 /*
99 * Maximum number of entries that could be present in the
100 * WMI_EXTSCAN_HOTLIST_MATCH_EVENT buffer from the firmware
101 */
102 #define WMA_EXTSCAN_MAX_HOTLIST_ENTRIES 10
103 #endif
104
105 static inline wmi_host_channel_width
wma_map_phy_ch_bw_to_wmi_channel_width(enum phy_ch_width ch_width)106 wma_map_phy_ch_bw_to_wmi_channel_width(enum phy_ch_width ch_width)
107 {
108 switch (ch_width) {
109 case CH_WIDTH_20MHZ:
110 return WMI_HOST_CHAN_WIDTH_20;
111 case CH_WIDTH_40MHZ:
112 return WMI_HOST_CHAN_WIDTH_40;
113 case CH_WIDTH_80MHZ:
114 return WMI_HOST_CHAN_WIDTH_80;
115 case CH_WIDTH_160MHZ:
116 return WMI_HOST_CHAN_WIDTH_160;
117 case CH_WIDTH_5MHZ:
118 return WMI_HOST_CHAN_WIDTH_5;
119 case CH_WIDTH_10MHZ:
120 return WMI_HOST_CHAN_WIDTH_10;
121 case CH_WIDTH_320MHZ:
122 return WMI_HOST_CHAN_WIDTH_320;
123 default:
124 return WMI_HOST_CHAN_WIDTH_20;
125 }
126 }
127
128 #define WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ 0
129 #define WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ 1
130 #define WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ 2
131 #define WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ 3
132
133 #if defined(WLAN_FEATURE_11BE)
wma_update_ch_list_11be_params(struct ch_params * ch)134 static void wma_update_ch_list_11be_params(struct ch_params *ch)
135 {
136 ch->ch_width = CH_WIDTH_320MHZ;
137 }
138 #else /* !WLAN_FEATURE_11BE */
wma_update_ch_list_11be_params(struct ch_params * ch)139 static void wma_update_ch_list_11be_params(struct ch_params *ch)
140 {
141 ch->ch_width = CH_WIDTH_160MHZ;
142 }
143 #endif /* WLAN_FEATURE_11BE */
144
145 /**
146 * wma_update_channel_list() - update channel list
147 * @handle: wma handle
148 * @chan_list: channel list
149 *
150 * Function is used to update the support channel list in fw.
151 *
152 * Return: QDF status
153 */
wma_update_channel_list(WMA_HANDLE handle,tSirUpdateChanList * chan_list)154 QDF_STATUS wma_update_channel_list(WMA_HANDLE handle,
155 tSirUpdateChanList *chan_list)
156 {
157 tp_wma_handle wma_handle = (tp_wma_handle) handle;
158 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
159 int i, len;
160 struct scan_chan_list_params *scan_ch_param;
161 struct channel_param *chan_p;
162 struct ch_params ch_params = {0};
163
164 len = sizeof(struct channel_param) * chan_list->numChan +
165 offsetof(struct scan_chan_list_params, ch_param[0]);
166 scan_ch_param = qdf_mem_malloc(len);
167 if (!scan_ch_param)
168 return QDF_STATUS_E_NOMEM;
169
170 qdf_mem_zero(scan_ch_param, len);
171 wma_debug("no of channels = %d", chan_list->numChan);
172 chan_p = &scan_ch_param->ch_param[0];
173 scan_ch_param->nallchans = chan_list->numChan;
174 scan_ch_param->max_bw_support_present = true;
175 wma_handle->saved_chan.num_channels = chan_list->numChan;
176 wma_debug("ht %d, vht %d, vht_24 %d", chan_list->ht_en,
177 chan_list->vht_en, chan_list->vht_24_en);
178
179 for (i = 0; i < chan_list->numChan; ++i) {
180 chan_p->mhz = chan_list->chanParam[i].freq;
181 chan_p->cfreq1 = chan_p->mhz;
182 chan_p->cfreq2 = 0;
183 wma_handle->saved_chan.ch_freq_list[i] =
184 chan_list->chanParam[i].freq;
185
186 if (chan_list->chanParam[i].dfsSet) {
187 chan_p->is_chan_passive = 1;
188 chan_p->dfs_set = 1;
189 }
190
191 if (chan_list->chanParam[i].nan_disabled)
192 chan_p->nan_disabled = 1;
193
194 if (chan_p->mhz < WMA_2_4_GHZ_MAX_FREQ) {
195 chan_p->phy_mode = MODE_11G;
196 if (chan_list->vht_en && chan_list->vht_24_en)
197 chan_p->allow_vht = 1;
198 } else {
199 chan_p->phy_mode = MODE_11A;
200 if (chan_list->vht_en &&
201 !(WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_p->mhz)))
202 chan_p->allow_vht = 1;
203 }
204
205 if (chan_list->ht_en &&
206 !(WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_p->mhz)))
207 chan_p->allow_ht = 1;
208
209 if (chan_list->he_en)
210 chan_p->allow_he = 1;
211
212 if (chan_list->eht_en)
213 chan_p->allow_eht = 1;
214
215 if (chan_list->chanParam[i].half_rate)
216 chan_p->half_rate = 1;
217 else if (chan_list->chanParam[i].quarter_rate)
218 chan_p->quarter_rate = 1;
219
220 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_p->mhz) &&
221 wlan_reg_is_6ghz_psc_chan_freq(chan_p->mhz))
222 chan_p->psc_channel = 1;
223
224 /*TODO: Set WMI_SET_CHANNEL_MIN_POWER */
225 /*TODO: Set WMI_SET_CHANNEL_ANTENNA_MAX */
226 /*TODO: WMI_SET_CHANNEL_REG_CLASSID */
227 chan_p->maxregpower = chan_list->chanParam[i].pwr;
228
229 wma_update_ch_list_11be_params(&ch_params);
230
231 wlan_reg_set_channel_params_for_pwrmode(wma_handle->pdev,
232 chan_p->mhz, 0,
233 &ch_params,
234 REG_CURRENT_PWR_MODE);
235
236 chan_p->max_bw_supported =
237 wma_map_phy_ch_bw_to_wmi_channel_width(ch_params.ch_width);
238 chan_p++;
239 }
240
241 qdf_status = wmi_unified_scan_chan_list_cmd_send(wma_handle->wmi_handle,
242 scan_ch_param);
243
244 if (QDF_IS_STATUS_ERROR(qdf_status))
245 wma_err("Failed to send WMI_SCAN_CHAN_LIST_CMDID");
246
247 qdf_mem_free(scan_ch_param);
248
249 return qdf_status;
250 }
251
252 /**
253 * wma_handle_disconnect_reason() - Send del sta msg to lim on receiving
254 * @wma_handle: wma handle
255 * @vdev_id: vdev id
256 * @reason: disconnection reason from fw
257 *
258 * Return: None
259 */
wma_handle_disconnect_reason(tp_wma_handle wma_handle,uint32_t vdev_id,uint32_t reason)260 static void wma_handle_disconnect_reason(tp_wma_handle wma_handle,
261 uint32_t vdev_id, uint32_t reason)
262 {
263 tpDeleteStaContext del_sta_ctx;
264
265 del_sta_ctx = qdf_mem_malloc(sizeof(tDeleteStaContext));
266 if (!del_sta_ctx)
267 return;
268
269 del_sta_ctx->vdev_id = vdev_id;
270 del_sta_ctx->reasonCode = reason;
271 wma_send_msg(wma_handle, SIR_LIM_DELETE_STA_CONTEXT_IND,
272 (void *)del_sta_ctx, 0);
273 }
274
275 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
276 QDF_STATUS
cm_handle_auth_offload(struct auth_offload_event * auth_event)277 cm_handle_auth_offload(struct auth_offload_event *auth_event)
278 {
279 QDF_STATUS status;
280 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
281 struct mac_context *mac_ctx;
282
283 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
284 if (!mac_ctx || !wma) {
285 QDF_ASSERT(0);
286 return QDF_STATUS_E_FAILURE;
287 }
288
289 cds_host_diag_log_work(&wma->roam_preauth_wl,
290 WMA_ROAM_PREAUTH_WAKE_LOCK_DURATION,
291 WIFI_POWER_EVENT_WAKELOCK_WOW);
292
293 qdf_wake_lock_timeout_acquire(&wma->roam_ho_wl,
294 WMA_ROAM_HO_WAKE_LOCK_DURATION);
295
296 lim_sae_auth_cleanup_retry(mac_ctx, auth_event->vdev_id);
297 wlan_cm_set_sae_auth_ta(mac_ctx->pdev,
298 auth_event->vdev_id,
299 auth_event->ta);
300
301 wlan_cm_store_mlo_roam_peer_address(mac_ctx->pdev, auth_event);
302
303 status =
304 wlan_cm_update_offload_ssid_from_candidate(mac_ctx->pdev,
305 auth_event->vdev_id,
306 &auth_event->ap_bssid);
307
308 if (QDF_IS_STATUS_ERROR(status)) {
309 wma_err_rl("Set offload ssid failed %d", status);
310 return QDF_STATUS_E_FAILURE;
311 }
312
313 status = wma->csr_roam_auth_event_handle_cb(mac_ctx, auth_event->vdev_id,
314 auth_event->ap_bssid,
315 auth_event->akm);
316 if (QDF_IS_STATUS_ERROR(status)) {
317 wma_err_rl("Trigger pre-auth failed");
318 return QDF_STATUS_E_FAILURE;
319 }
320 return QDF_STATUS_SUCCESS;
321 }
322
323 QDF_STATUS
cm_handle_disconnect_reason(struct vdev_disconnect_event_data * data)324 cm_handle_disconnect_reason(struct vdev_disconnect_event_data *data)
325 {
326 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
327
328 if (!wma) {
329 QDF_ASSERT(0);
330 return QDF_STATUS_E_FAILURE;
331 }
332 switch (data->reason) {
333 case CM_DISCONNECT_REASON_CSA_SA_QUERY_TIMEOUT:
334 wma_handle_disconnect_reason(wma, data->vdev_id,
335 HAL_DEL_STA_REASON_CODE_SA_QUERY_TIMEOUT);
336 break;
337 case CM_DISCONNECT_REASON_MOVE_TO_CELLULAR:
338 wma_handle_disconnect_reason(wma, data->vdev_id,
339 HAL_DEL_STA_REASON_CODE_BTM_DISASSOC_IMMINENT);
340 break;
341 default:
342 return QDF_STATUS_SUCCESS;
343 }
344
345 return QDF_STATUS_SUCCESS;
346 }
347
348 QDF_STATUS
cm_handle_scan_ch_list_data(struct cm_roam_scan_ch_resp * data)349 cm_handle_scan_ch_list_data(struct cm_roam_scan_ch_resp *data)
350 {
351 struct scheduler_msg sme_msg = {0};
352
353 sme_msg.type = eWNI_SME_GET_ROAM_SCAN_CH_LIST_EVENT;
354 sme_msg.bodyptr = data;
355
356 if (scheduler_post_message(QDF_MODULE_ID_WMA,
357 QDF_MODULE_ID_SME,
358 QDF_MODULE_ID_SME, &sme_msg)) {
359 wma_err("Failed to post msg to SME");
360 qdf_mem_free(sme_msg.bodyptr);
361 return -EINVAL;
362 }
363
364 return QDF_STATUS_SUCCESS;
365 }
366
367 #endif
368
369 /**
370 * wma_process_set_pdev_ie_req() - process the pdev set IE req
371 * @wma: Pointer to wma handle
372 * @ie_params: Pointer to IE data.
373 *
374 * Sends the WMI req to set the IE to FW.
375 *
376 * Return: None
377 */
wma_process_set_pdev_ie_req(tp_wma_handle wma,struct set_ie_param * ie_params)378 void wma_process_set_pdev_ie_req(tp_wma_handle wma,
379 struct set_ie_param *ie_params)
380 {
381 if (ie_params->ie_type == DOT11_HT_IE)
382 wma_process_set_pdev_ht_ie_req(wma, ie_params);
383 if (ie_params->ie_type == DOT11_VHT_IE)
384 wma_process_set_pdev_vht_ie_req(wma, ie_params);
385
386 qdf_mem_free(ie_params->ie_ptr);
387 }
388
389 /**
390 * wma_process_set_pdev_ht_ie_req() - sends HT IE data to FW
391 * @wma: Pointer to wma handle
392 * @ie_params: Pointer to IE data.
393 * @nss: Nss values to prepare the HT IE.
394 *
395 * Sends the WMI req to set the HT IE to FW.
396 *
397 * Return: None
398 */
wma_process_set_pdev_ht_ie_req(tp_wma_handle wma,struct set_ie_param * ie_params)399 void wma_process_set_pdev_ht_ie_req(tp_wma_handle wma,
400 struct set_ie_param *ie_params)
401 {
402 QDF_STATUS status;
403 wmi_pdev_set_ht_ie_cmd_fixed_param *cmd;
404 wmi_buf_t buf;
405 uint16_t len;
406 uint16_t ie_len_pad;
407 uint8_t *buf_ptr;
408
409 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
410 ie_len_pad = roundup(ie_params->ie_len, sizeof(uint32_t));
411 len += ie_len_pad;
412
413 buf = wmi_buf_alloc(wma->wmi_handle, len);
414 if (!buf)
415 return;
416
417 cmd = (wmi_pdev_set_ht_ie_cmd_fixed_param *)wmi_buf_data(buf);
418 WMITLV_SET_HDR(&cmd->tlv_header,
419 WMITLV_TAG_STRUC_wmi_pdev_set_ht_ie_cmd_fixed_param,
420 WMITLV_GET_STRUCT_TLVLEN(
421 wmi_pdev_set_ht_ie_cmd_fixed_param));
422 cmd->reserved0 = 0;
423 cmd->ie_len = ie_params->ie_len;
424 cmd->tx_streams = ie_params->nss;
425 cmd->rx_streams = ie_params->nss;
426 wma_debug("Setting pdev HT ie with Nss = %u", ie_params->nss);
427 buf_ptr = (uint8_t *)cmd + sizeof(*cmd);
428 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_pad);
429 if (ie_params->ie_len) {
430 qdf_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE,
431 (uint8_t *)ie_params->ie_ptr,
432 ie_params->ie_len);
433 }
434
435 status = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
436 WMI_PDEV_SET_HT_CAP_IE_CMDID);
437 if (QDF_IS_STATUS_ERROR(status))
438 wmi_buf_free(buf);
439 }
440
441 /**
442 * wma_process_set_pdev_vht_ie_req() - sends VHT IE data to FW
443 * @wma: Pointer to wma handle
444 * @ie_params: Pointer to IE data.
445 * @nss: Nss values to prepare the VHT IE.
446 *
447 * Sends the WMI req to set the VHT IE to FW.
448 *
449 * Return: None
450 */
wma_process_set_pdev_vht_ie_req(tp_wma_handle wma,struct set_ie_param * ie_params)451 void wma_process_set_pdev_vht_ie_req(tp_wma_handle wma,
452 struct set_ie_param *ie_params)
453 {
454 QDF_STATUS status;
455 wmi_pdev_set_vht_ie_cmd_fixed_param *cmd;
456 wmi_buf_t buf;
457 uint16_t len;
458 uint16_t ie_len_pad;
459 uint8_t *buf_ptr;
460
461 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
462 ie_len_pad = roundup(ie_params->ie_len, sizeof(uint32_t));
463 len += ie_len_pad;
464
465 buf = wmi_buf_alloc(wma->wmi_handle, len);
466 if (!buf)
467 return;
468
469 cmd = (wmi_pdev_set_vht_ie_cmd_fixed_param *)wmi_buf_data(buf);
470 WMITLV_SET_HDR(&cmd->tlv_header,
471 WMITLV_TAG_STRUC_wmi_pdev_set_vht_ie_cmd_fixed_param,
472 WMITLV_GET_STRUCT_TLVLEN(
473 wmi_pdev_set_vht_ie_cmd_fixed_param));
474 cmd->reserved0 = 0;
475 cmd->ie_len = ie_params->ie_len;
476 cmd->tx_streams = ie_params->nss;
477 cmd->rx_streams = ie_params->nss;
478 wma_debug("Setting pdev VHT ie with Nss = %u", ie_params->nss);
479 buf_ptr = (uint8_t *)cmd + sizeof(*cmd);
480 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_pad);
481 if (ie_params->ie_len) {
482 qdf_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE,
483 (uint8_t *)ie_params->ie_ptr, ie_params->ie_len);
484 }
485
486 status = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
487 WMI_PDEV_SET_VHT_CAP_IE_CMDID);
488 if (QDF_IS_STATUS_ERROR(status))
489 wmi_buf_free(buf);
490 }
491
492 #define MAX_VDEV_ROAM_SCAN_PARAMS 2
493 /* params being sent:
494 * wmi_vdev_param_bmiss_first_bcnt
495 * wmi_vdev_param_bmiss_final_bcnt
496 */
497
498 /**
499 * wma_roam_scan_bmiss_cnt() - set bmiss count to fw
500 * @wma_handle: wma handle
501 * @first_bcnt: first bmiss count
502 * @final_bcnt: final bmiss count
503 * @vdev_id: vdev id
504 *
505 * set first & final biss count to fw.
506 *
507 * Return: QDF status
508 */
wma_roam_scan_bmiss_cnt(tp_wma_handle wma_handle,A_INT32 first_bcnt,A_UINT32 final_bcnt,uint32_t vdev_id)509 QDF_STATUS wma_roam_scan_bmiss_cnt(tp_wma_handle wma_handle,
510 A_INT32 first_bcnt,
511 A_UINT32 final_bcnt, uint32_t vdev_id)
512 {
513 QDF_STATUS status = QDF_STATUS_SUCCESS;
514 struct dev_set_param setparam[MAX_VDEV_ROAM_SCAN_PARAMS] = {};
515 uint8_t index = 0;
516
517 wma_debug("first_bcnt: %d, final_bcnt: %d", first_bcnt, final_bcnt);
518
519 status = mlme_check_index_setparam(setparam,
520 wmi_vdev_param_bmiss_first_bcnt,
521 first_bcnt, index++,
522 MAX_VDEV_ROAM_SCAN_PARAMS);
523 if (QDF_IS_STATUS_ERROR(status)) {
524 wma_err("failed to set wmi_vdev_param_bmiss_first_bcnt");
525 goto error;
526 }
527 status = mlme_check_index_setparam(setparam,
528 wmi_vdev_param_bmiss_final_bcnt,
529 final_bcnt, index++,
530 MAX_VDEV_ROAM_SCAN_PARAMS);
531 if (QDF_IS_STATUS_ERROR(status)) {
532 wma_err("failed to set wmi_vdev_param_bmiss_final_bcnt");
533 goto error;
534 }
535 status = wma_send_multi_pdev_vdev_set_params(MLME_VDEV_SETPARAM,
536 vdev_id, setparam, index);
537 if (QDF_IS_STATUS_ERROR(status))
538 wma_err("Failed to set BMISS FIRST and FINAL vdev set params");
539 error:
540 return status;
541 }
542
543 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
544 void
wma_send_roam_preauth_status(tp_wma_handle wma_handle,struct wmi_roam_auth_status_params * params)545 wma_send_roam_preauth_status(tp_wma_handle wma_handle,
546 struct wmi_roam_auth_status_params *params)
547 {
548 QDF_STATUS status;
549 struct wmi_unified *wmi_handle;
550
551 if (wma_validate_handle(wma_handle))
552 return;
553
554 wmi_handle = wma_handle->wmi_handle;
555 if (wmi_validate_handle(wmi_handle))
556 return;
557
558 status = wmi_unified_send_roam_preauth_status(wmi_handle, params);
559 if (QDF_IS_STATUS_ERROR(status))
560 wma_err("failed to send disconnect roam preauth status");
561 }
562 #endif
563
564 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
565 /**
566 * wma_delete_bss_peer() Delete bss peer/s for Non ML interface
567 * @wma: Global WMA Handle
568 * @vdev_id: vdev id
569 *
570 * This function will perform cleanup of the peer corresponds
571 * to given vdev_id
572 *
573 * Return: QDF status
574 */
575 static
wma_delete_bss_peer(tp_wma_handle wma,uint8_t vdev_id)576 QDF_STATUS wma_delete_bss_peer(tp_wma_handle wma,
577 uint8_t vdev_id)
578 {
579 tDeleteStaParams *del_sta_params;
580
581 del_sta_params = qdf_mem_malloc(sizeof(*del_sta_params));
582 if (!del_sta_params)
583 return QDF_STATUS_E_NOMEM;
584
585 del_sta_params->smesessionId = vdev_id;
586 wma_delete_sta(wma, del_sta_params);
587 wma_delete_bss(wma, vdev_id);
588
589 return QDF_STATUS_SUCCESS;
590 }
591
592 #ifdef WLAN_FEATURE_11BE_MLO
593 /**
594 * wma_delete_all_peers() - Delete all bss peer/s
595 * @wma: Global WMA Handle
596 * @vdev_id: vdev id
597 * @del_sta_params: parameters required for del sta request
598 *
599 * This function will perform deleting of all the link peers
600 * after self roaming.
601 *
602 * Return: None
603 */
604 static QDF_STATUS
wma_delete_all_peers(tp_wma_handle wma,uint8_t vdev_id)605 wma_delete_all_peers(tp_wma_handle wma,
606 uint8_t vdev_id)
607 {
608 struct wlan_objmgr_vdev *vdev;
609 struct wlan_mlo_dev_context *mlo_dev_ctx;
610 uint8_t i;
611 uint8_t link_vdev_id;
612 tDeleteStaParams *del_sta_params;
613 QDF_STATUS status = QDF_STATUS_SUCCESS;
614 struct qdf_mac_addr bssid;
615 struct qdf_mac_addr *mld_addr;
616
617 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id,
618 WLAN_MLME_OBJMGR_ID);
619 if (!vdev) {
620 mlme_err("vdev object is NULL for vdev %d", vdev_id);
621 return QDF_STATUS_E_NULL_VALUE;
622 }
623
624 mlo_dev_ctx = vdev->mlo_dev_ctx;
625 if (!mlo_dev_ctx) {
626 mld_addr =
627 (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
628 /* It's not a ML interface*/
629 if (qdf_is_macaddr_zero(mld_addr)) {
630 mlme_debug("Non-ML STA vdev_id: %d", vdev_id);
631 status = wma_delete_bss_peer(wma, vdev_id);
632 goto end;
633 }
634
635 mlme_err("mlo_dev_ctx object is NULL for vdev %d", vdev_id);
636 status = QDF_STATUS_E_NULL_VALUE;
637 goto end;
638 }
639
640 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
641 if (!mlo_dev_ctx->wlan_vdev_list[i])
642 continue;
643
644 if (QDF_IS_STATUS_ERROR(wlan_vdev_get_bss_peer_mac(
645 mlo_dev_ctx->wlan_vdev_list[i],
646 &bssid))) {
647 pe_debug("bss peer is not present on vdev id %d, no need to cleanup",
648 wlan_vdev_get_id(
649 mlo_dev_ctx->wlan_vdev_list[i]));
650 continue;
651 }
652
653 del_sta_params = qdf_mem_malloc(sizeof(*del_sta_params));
654 if (!del_sta_params) {
655 status = QDF_STATUS_E_NOMEM;
656 goto end;
657 }
658 lim_mlo_roam_peer_disconn_del(mlo_dev_ctx->wlan_vdev_list[i]);
659 qdf_mem_zero(del_sta_params, sizeof(*del_sta_params));
660 link_vdev_id = wlan_vdev_get_id(mlo_dev_ctx->wlan_vdev_list[i]);
661 if (link_vdev_id == WLAN_INVALID_VDEV_ID) {
662 mlme_err("invalid vdev id");
663 status = QDF_STATUS_E_INVAL;
664 goto end;
665 }
666 del_sta_params->smesessionId = link_vdev_id;
667 wma_delete_sta(wma, del_sta_params);
668 wma_delete_bss(wma, link_vdev_id);
669 }
670
671 end:
672 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
673 return status;
674 }
675 #else
676 static inline QDF_STATUS
wma_delete_all_peers(tp_wma_handle wma,uint8_t vdev_id)677 wma_delete_all_peers(tp_wma_handle wma,
678 uint8_t vdev_id)
679 {
680 return wma_delete_bss_peer(wma, vdev_id);
681 }
682 #endif
683 /**
684 * wma_roam_update_vdev() - Update the STA and BSS
685 * @wma: Global WMA Handle
686 * @roam_synch_ind_ptr: Information needed for roam sync propagation
687 *
688 * This function will perform all the vdev related operations with
689 * respect to the self sta and the peer after roaming and completes
690 * the roam synch propagation with respect to WMA layer.
691 *
692 * Return: QDF_STATUS
693 */
694 static QDF_STATUS
wma_roam_update_vdev(tp_wma_handle wma,struct roam_offload_synch_ind * roam_synch_ind_ptr,uint8_t roamed_vdev_id)695 wma_roam_update_vdev(tp_wma_handle wma,
696 struct roam_offload_synch_ind *roam_synch_ind_ptr,
697 uint8_t roamed_vdev_id)
698 {
699 tAddStaParams *add_sta_params;
700 uint8_t vdev_id, *bssid;
701 int32_t uc_cipher, cipher_cap;
702 bool is_assoc_peer = false;
703 struct qdf_mac_addr mac_addr;
704 QDF_STATUS status = QDF_STATUS_SUCCESS;
705
706 vdev_id = roamed_vdev_id;
707 wma->interfaces[vdev_id].nss = roam_synch_ind_ptr->nss;
708
709 /* update channel width */
710 wma->interfaces[vdev_id].chan_width = roam_synch_ind_ptr->chan_width;
711 /* Fill link freq from roam_synch_ind */
712 if (is_multi_link_roam(roam_synch_ind_ptr))
713 wma->interfaces[vdev_id].ch_freq =
714 mlo_roam_get_chan_freq(vdev_id, roam_synch_ind_ptr);
715 else
716 wma->interfaces[vdev_id].ch_freq =
717 roam_synch_ind_ptr->chan_freq;
718
719 add_sta_params = qdf_mem_malloc(sizeof(*add_sta_params));
720 if (!add_sta_params)
721 return QDF_STATUS_E_INVAL;
722
723 if (is_multi_link_roam(roam_synch_ind_ptr))
724 mlo_get_sta_link_mac_addr(vdev_id, roam_synch_ind_ptr,
725 &mac_addr);
726 else
727 mac_addr = roam_synch_ind_ptr->bssid;
728
729 qdf_mem_zero(add_sta_params, sizeof(*add_sta_params));
730
731 /* With self roaming on multi link AP, as the same
732 * peer already exists, new peer creation fails
733 * To handle this delete all link peers,
734 * while doing roam sync on first link.
735 */
736 if (!is_multi_link_roam(roam_synch_ind_ptr) ||
737 wlan_vdev_mlme_get_is_mlo_link(wma->psoc, vdev_id) ||
738 mlo_get_single_link_ml_roaming(wma->psoc, vdev_id)) {
739 status = wma_delete_all_peers(wma, vdev_id);
740 if (QDF_IS_STATUS_ERROR(status))
741 goto end;
742 }
743
744 add_sta_params->staType = STA_ENTRY_SELF;
745 add_sta_params->smesessionId = vdev_id;
746 qdf_mem_copy(&add_sta_params->bssId, &mac_addr, QDF_MAC_ADDR_SIZE);
747 add_sta_params->assocId = roam_synch_ind_ptr->aid;
748
749 bssid = wma_get_vdev_bssid(wma->interfaces[vdev_id].vdev);
750 if (!bssid) {
751 wma_err("Failed to get bssid for vdev_%d", vdev_id);
752 return QDF_STATUS_E_INVAL;
753 }
754
755 is_assoc_peer = wlan_vdev_mlme_get_is_mlo_vdev(wma->psoc, vdev_id);
756 if (is_multi_link_roam(roam_synch_ind_ptr)) {
757 status = wma_create_peer(wma, mac_addr.bytes,
758 WMI_PEER_TYPE_DEFAULT, vdev_id,
759 roam_synch_ind_ptr->bssid.bytes,
760 is_assoc_peer);
761 } else {
762 status = wma_create_peer(wma, mac_addr.bytes,
763 WMI_PEER_TYPE_DEFAULT, vdev_id, NULL,
764 is_assoc_peer);
765 }
766
767 if (QDF_IS_STATUS_ERROR(status)) {
768 wma_err("Failed to create peer " QDF_MAC_ADDR_FMT,
769 QDF_MAC_ADDR_REF(mac_addr.bytes));
770 goto end;
771 }
772
773 if (is_multi_link_roam(roam_synch_ind_ptr)) {
774 status = lim_roam_mlo_create_peer(wma->mac_context,
775 roam_synch_ind_ptr, vdev_id,
776 mac_addr.bytes);
777
778 /* The created peer will be destroyed on HO failure cleanup */
779 if (QDF_IS_STATUS_ERROR(status)) {
780 wma_err("Failed to attach MLO peer " QDF_MAC_ADDR_FMT,
781 QDF_MAC_ADDR_REF(mac_addr.bytes));
782 goto end;
783 }
784 }
785
786 if (wlan_vdev_mlme_get_opmode(wma->interfaces[vdev_id].vdev) ==
787 QDF_STA_MODE)
788 wlan_cdp_set_peer_freq(wma->psoc, mac_addr.bytes,
789 wma->interfaces[vdev_id].ch_freq,
790 vdev_id);
791
792 /* Update new peer's uc cipher */
793 uc_cipher = wlan_crypto_get_param(wma->interfaces[vdev_id].vdev,
794 WLAN_CRYPTO_PARAM_UCAST_CIPHER);
795 cipher_cap = wlan_crypto_get_param(wma->interfaces[vdev_id].vdev,
796 WLAN_CRYPTO_PARAM_CIPHER_CAP);
797 wma_set_peer_ucast_cipher(mac_addr.bytes, uc_cipher,
798 cipher_cap);
799 wma_add_bss_lfr3(wma, roam_synch_ind_ptr->add_bss_params);
800 wma_add_sta(wma, add_sta_params);
801 qdf_mem_copy(bssid, mac_addr.bytes,
802 QDF_MAC_ADDR_SIZE);
803 lim_fill_roamed_peer_twt_caps(wma->mac_context, vdev_id,
804 roam_synch_ind_ptr);
805 end:
806 qdf_mem_free(add_sta_params);
807 return status;
808 }
809
wma_update_phymode_on_roam(tp_wma_handle wma,struct qdf_mac_addr * bssid,wmi_channel * chan,struct wma_txrx_node * iface)810 static void wma_update_phymode_on_roam(tp_wma_handle wma,
811 struct qdf_mac_addr *bssid,
812 wmi_channel *chan,
813 struct wma_txrx_node *iface)
814 {
815 enum wlan_phymode bss_phymode;
816 struct wlan_channel *des_chan;
817 struct wlan_channel *bss_chan;
818 struct vdev_mlme_obj *vdev_mlme;
819 uint8_t channel;
820 struct wlan_objmgr_pdev *pdev = NULL;
821 qdf_freq_t sec_ch_2g_freq = 0;
822 struct ch_params ch_params = {0};
823
824 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(iface->vdev);
825 if (!vdev_mlme)
826 return;
827
828 pdev = wlan_vdev_get_pdev(vdev_mlme->vdev);
829
830 channel = wlan_reg_freq_to_chan(pdev, iface->ch_freq);
831 if (chan)
832 bss_phymode =
833 wma_fw_to_host_phymode(WMI_GET_CHANNEL_MODE(chan));
834 else
835 wma_get_phy_mode_cb(iface->ch_freq,
836 iface->chan_width, &bss_phymode);
837
838 /* Update vdev mlme channel info after roaming */
839 des_chan = wlan_vdev_mlme_get_des_chan(iface->vdev);
840 bss_chan = wlan_vdev_mlme_get_bss_chan(iface->vdev);
841 des_chan->ch_phymode = bss_phymode;
842 des_chan->ch_width = iface->chan_width;
843 if (chan) {
844 des_chan->ch_freq = chan->mhz;
845 ch_params.ch_width = des_chan->ch_width;
846 if (wlan_reg_is_24ghz_ch_freq(des_chan->ch_freq) &&
847 des_chan->ch_width == CH_WIDTH_40MHZ &&
848 chan->band_center_freq1) {
849 if (des_chan->ch_freq < chan->band_center_freq1)
850 sec_ch_2g_freq = des_chan->ch_freq + 20;
851 else
852 sec_ch_2g_freq = des_chan->ch_freq - 20;
853 }
854 wlan_reg_set_channel_params_for_pwrmode(pdev, des_chan->ch_freq,
855 sec_ch_2g_freq,
856 &ch_params,
857 REG_CURRENT_PWR_MODE);
858 if (ch_params.ch_width != des_chan->ch_width ||
859 ch_params.mhz_freq_seg0 != chan->band_center_freq1 ||
860 ch_params.mhz_freq_seg1 != chan->band_center_freq2)
861 wma_err("ch mismatch host & fw bw (%d %d) seg0 (%d, %d) seg1 (%d, %d)",
862 ch_params.ch_width, des_chan->ch_width,
863 ch_params.mhz_freq_seg0,
864 chan->band_center_freq1,
865 ch_params.mhz_freq_seg1,
866 chan->band_center_freq2);
867 des_chan->ch_cfreq1 = ch_params.mhz_freq_seg0;
868 des_chan->ch_cfreq2 = ch_params.mhz_freq_seg1;
869 des_chan->ch_width = ch_params.ch_width;
870 } else {
871 wma_err("LFR3: invalid chan");
872 }
873 qdf_mem_copy(bss_chan, des_chan, sizeof(struct wlan_channel));
874
875 /* Till conversion is not done in WMI we need to fill fw phy mode */
876 vdev_mlme->mgmt.generic.phy_mode = wmi_host_to_fw_phymode(bss_phymode);
877
878 /* update new phymode to peer */
879 wma_objmgr_set_peer_mlme_phymode(wma, bssid->bytes, bss_phymode);
880
881 wma_debug("LFR3: new phymode %d freq %d (bw %d, %d %d)",
882 bss_phymode, des_chan->ch_freq, des_chan->ch_width,
883 des_chan->ch_cfreq1, des_chan->ch_cfreq2);
884 }
885
886 /**
887 * wma_set_ric_req() - set ric request element
888 * @wma: wma handle
889 * @msg: message
890 * @is_add_ts: is addts required
891 *
892 * This function sets ric request element for 11r roaming.
893 *
894 * Return: none
895 */
wma_set_ric_req(tp_wma_handle wma,void * msg,uint8_t is_add_ts)896 void wma_set_ric_req(tp_wma_handle wma, void *msg, uint8_t is_add_ts)
897 {
898 if (!wma) {
899 wma_err("wma handle is NULL");
900 return;
901 }
902
903 wmi_unified_set_ric_req_cmd(wma->wmi_handle, msg, is_add_ts);
904 }
905 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
906
907 #ifdef FEATURE_RSSI_MONITOR
wma_set_rssi_monitoring(tp_wma_handle wma,struct rssi_monitor_param * req)908 QDF_STATUS wma_set_rssi_monitoring(tp_wma_handle wma,
909 struct rssi_monitor_param *req)
910 {
911 if (!wma) {
912 wma_err("wma handle is NULL");
913 return QDF_STATUS_E_INVAL;
914 }
915
916 return wmi_unified_set_rssi_monitoring_cmd(wma->wmi_handle, req);
917 }
918
919 /**
920 * wma_rssi_breached_event_handler() - rssi breached event handler
921 * @handle: wma handle
922 * @cmd_param_info: event handler data
923 * @len: length of @cmd_param_info
924 *
925 * Return: 0 on success; error number otherwise
926 */
wma_rssi_breached_event_handler(void * handle,u_int8_t * cmd_param_info,u_int32_t len)927 int wma_rssi_breached_event_handler(void *handle,
928 u_int8_t *cmd_param_info, u_int32_t len)
929 {
930 WMI_RSSI_BREACH_EVENTID_param_tlvs *param_buf;
931 wmi_rssi_breach_event_fixed_param *event;
932 struct rssi_breach_event rssi;
933 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
934 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
935
936 if (!mac || !wma) {
937 wma_err("Invalid mac/wma context");
938 return -EINVAL;
939 }
940 if (!mac->sme.rssi_threshold_breached_cb) {
941 wma_err("Callback not registered");
942 return -EINVAL;
943 }
944 param_buf = (WMI_RSSI_BREACH_EVENTID_param_tlvs *)cmd_param_info;
945 if (!param_buf) {
946 wma_err("Invalid rssi breached event");
947 return -EINVAL;
948 }
949 event = param_buf->fixed_param;
950
951 rssi.request_id = event->request_id;
952 rssi.session_id = event->vdev_id;
953 if (wmi_service_enabled(wma->wmi_handle,
954 wmi_service_hw_db2dbm_support))
955 rssi.curr_rssi = event->rssi;
956 else
957 rssi.curr_rssi = event->rssi + WMA_TGT_NOISE_FLOOR_DBM;
958 WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->bssid, rssi.curr_bssid.bytes);
959
960 wma_debug("req_id: %u vdev_id: %d curr_rssi: %d",
961 rssi.request_id, rssi.session_id, rssi.curr_rssi);
962 wma_debug("curr_bssid: "QDF_MAC_ADDR_FMT,
963 QDF_MAC_ADDR_REF(rssi.curr_bssid.bytes));
964
965 mac->sme.rssi_threshold_breached_cb(mac->hdd_handle, &rssi);
966 wma_debug("Invoke HDD rssi breached callback");
967 return 0;
968 }
969 #endif /* FEATURE_RSSI_MONITOR */
970
wma_pre_chan_switch_setup(uint8_t vdev_id)971 QDF_STATUS wma_pre_chan_switch_setup(uint8_t vdev_id)
972 {
973 QDF_STATUS status = QDF_STATUS_SUCCESS;
974 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
975 struct wma_txrx_node *intr;
976 uint16_t beacon_interval_ori;
977 bool restart;
978 uint16_t reduced_beacon_interval;
979 struct vdev_mlme_obj *mlme_obj;
980 struct wlan_objmgr_vdev *vdev;
981
982 if (!wma) {
983 pe_err("wma is NULL");
984 return QDF_STATUS_E_FAILURE;
985 }
986 intr = &wma->interfaces[vdev_id];
987 if (!intr) {
988 pe_err("wma txrx node is NULL");
989 return QDF_STATUS_E_FAILURE;
990 }
991 vdev = intr->vdev;
992 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev);
993 if (!mlme_obj) {
994 pe_err("vdev component object is NULL");
995 return QDF_STATUS_E_FAILURE;
996 }
997
998 restart =
999 wma_get_channel_switch_in_progress(intr);
1000 if (restart && intr->beacon_filter_enabled)
1001 wma_remove_beacon_filter(wma, &intr->beacon_filter);
1002
1003 reduced_beacon_interval =
1004 wma->mac_context->sap.SapDfsInfo.reduced_beacon_interval;
1005 if (wma_is_vdev_in_ap_mode(wma, vdev_id) && reduced_beacon_interval) {
1006
1007
1008 /* Reduce the beacon interval just before the channel switch.
1009 * This would help in reducing the downtime on the STA side
1010 * (which is waiting for beacons from the AP to resume back
1011 * transmission). Switch back the beacon_interval to its
1012 * original value after the channel switch based on the
1013 * timeout. This would ensure there are atleast some beacons
1014 * sent with increased frequency.
1015 */
1016
1017 wma_debug("Changing beacon interval to %d",
1018 reduced_beacon_interval);
1019
1020 /* Add a timer to reset the beacon interval back*/
1021 beacon_interval_ori = mlme_obj->proto.generic.beacon_interval;
1022 mlme_obj->proto.generic.beacon_interval =
1023 reduced_beacon_interval;
1024 if (wma_fill_beacon_interval_reset_req(wma,
1025 vdev_id,
1026 beacon_interval_ori,
1027 RESET_BEACON_INTERVAL_TIMEOUT)) {
1028
1029 wma_debug("Failed to fill beacon interval reset req");
1030 }
1031 }
1032
1033 status = wma_vdev_pre_start(vdev_id, restart);
1034
1035 return status;
1036 }
1037
wma_post_chan_switch_setup(uint8_t vdev_id)1038 QDF_STATUS wma_post_chan_switch_setup(uint8_t vdev_id)
1039 {
1040 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
1041 struct wma_txrx_node *intr;
1042 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
1043 struct wlan_channel *des_chan;
1044 cdp_config_param_type val;
1045
1046 if (!wma) {
1047 pe_err("wma is NULL");
1048 return QDF_STATUS_E_FAILURE;
1049 }
1050 intr = &wma->interfaces[vdev_id];
1051 if (!intr) {
1052 pe_err("wma txrx node is NULL");
1053 return QDF_STATUS_E_FAILURE;
1054 }
1055 /*
1056 * Record monitor mode channel here in case HW
1057 * indicate RX PPDU TLV with invalid channel number.
1058 */
1059 if (intr->type == WMI_VDEV_TYPE_MONITOR) {
1060 des_chan = intr->vdev->vdev_mlme.des_chan;
1061 val.cdp_pdev_param_monitor_chan = des_chan->ch_ieee;
1062 cdp_txrx_set_pdev_param(soc,
1063 wlan_objmgr_pdev_get_pdev_id(wma->pdev),
1064 CDP_MONITOR_CHANNEL, val);
1065 val.cdp_pdev_param_mon_freq = des_chan->ch_freq;
1066 cdp_txrx_set_pdev_param(soc,
1067 wlan_objmgr_pdev_get_pdev_id(wma->pdev),
1068 CDP_MONITOR_FREQUENCY, val);
1069 }
1070 return QDF_STATUS_SUCCESS;
1071 }
1072
1073 #ifdef FEATURE_WLAN_ESE
1074 /**
1075 * wma_plm_start() - plm start request
1076 * @wma: wma handle
1077 * @params: plm request parameters
1078 *
1079 * This function request FW to start PLM.
1080 *
1081 * Return: QDF status
1082 */
wma_plm_start(tp_wma_handle wma,struct plm_req_params * params)1083 static QDF_STATUS wma_plm_start(tp_wma_handle wma,
1084 struct plm_req_params *params)
1085 {
1086 QDF_STATUS status;
1087
1088 wma_debug("PLM Start");
1089
1090 status = wmi_unified_plm_start_cmd(wma->wmi_handle, params);
1091 if (QDF_IS_STATUS_ERROR(status))
1092 return status;
1093
1094 wma->interfaces[params->vdev_id].plm_in_progress = true;
1095
1096 wma_debug("Plm start request sent successfully for vdev %d",
1097 params->vdev_id);
1098
1099 return status;
1100 }
1101
1102 /**
1103 * wma_plm_stop() - plm stop request
1104 * @wma: wma handle
1105 * @params: plm request parameters
1106 *
1107 * This function request FW to stop PLM.
1108 *
1109 * Return: QDF status
1110 */
wma_plm_stop(tp_wma_handle wma,struct plm_req_params * params)1111 static QDF_STATUS wma_plm_stop(tp_wma_handle wma,
1112 struct plm_req_params *params)
1113 {
1114 QDF_STATUS status;
1115
1116 if (!wma->interfaces[params->vdev_id].plm_in_progress) {
1117 wma_err("No active plm req found, skip plm stop req");
1118 return QDF_STATUS_E_FAILURE;
1119 }
1120
1121 wma_debug("PLM Stop");
1122
1123 status = wmi_unified_plm_stop_cmd(wma->wmi_handle, params);
1124 if (QDF_IS_STATUS_ERROR(status))
1125 return status;
1126
1127 wma->interfaces[params->vdev_id].plm_in_progress = false;
1128
1129 wma_debug("Plm stop request sent successfully for vdev %d",
1130 params->vdev_id);
1131
1132 return status;
1133 }
1134
1135 /**
1136 * wma_config_plm() - config PLM
1137 * @wma: wma handle
1138 * @params: plm request parameters
1139 *
1140 * Return: none
1141 */
wma_config_plm(tp_wma_handle wma,struct plm_req_params * params)1142 void wma_config_plm(tp_wma_handle wma, struct plm_req_params *params)
1143 {
1144 QDF_STATUS ret;
1145
1146 if (!params || !wma)
1147 return;
1148
1149 if (params->enable)
1150 ret = wma_plm_start(wma, params);
1151 else
1152 ret = wma_plm_stop(wma, params);
1153
1154 if (ret)
1155 wma_err("PLM %s failed %d",
1156 params->enable ? "start" : "stop", ret);
1157 }
1158 #endif
1159
1160 #ifdef FEATURE_WLAN_EXTSCAN
1161 /**
1162 * wma_extscan_wow_event_callback() - extscan wow event callback
1163 * @handle: WMA handle
1164 * @event: event buffer
1165 * @len: length of @event buffer
1166 *
1167 * In wow case, the wow event is followed by the payload of the event
1168 * which generated the wow event.
1169 * payload is 4 bytes of length followed by event buffer. the first 4 bytes
1170 * of event buffer is common tlv header, which is a combination
1171 * of tag (higher 2 bytes) and length (lower 2 bytes). The tag is used to
1172 * identify the event which triggered wow event.
1173 * Payload is extracted and converted into generic tlv structure before
1174 * being passed to this function.
1175 *
1176 * @Return: Errno
1177 */
wma_extscan_wow_event_callback(void * handle,void * event,uint32_t len)1178 int wma_extscan_wow_event_callback(void *handle, void *event, uint32_t len)
1179 {
1180 uint32_t tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(event));
1181
1182 switch (tag) {
1183 case WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param:
1184 return wma_extscan_start_stop_event_handler(handle, event, len);
1185
1186 case WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param:
1187 return wma_extscan_operations_event_handler(handle, event, len);
1188
1189 case WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param:
1190 return wma_extscan_table_usage_event_handler(handle, event,
1191 len);
1192
1193 case WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param:
1194 return wma_extscan_cached_results_event_handler(handle, event,
1195 len);
1196
1197 case WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param:
1198 return wma_extscan_change_results_event_handler(handle, event,
1199 len);
1200
1201 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param:
1202 return wma_extscan_hotlist_match_event_handler(handle, event,
1203 len);
1204
1205 case WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param:
1206 return wma_extscan_capabilities_event_handler(handle, event,
1207 len);
1208
1209 default:
1210 wma_err("Unknown tag: %d", tag);
1211 return 0;
1212 }
1213 }
1214
1215 /**
1216 * wma_register_extscan_event_handler() - register extscan event handler
1217 * @wma_handle: wma handle
1218 *
1219 * This function register extscan related event handlers.
1220 *
1221 * Return: none
1222 */
wma_register_extscan_event_handler(tp_wma_handle wma_handle)1223 void wma_register_extscan_event_handler(tp_wma_handle wma_handle)
1224 {
1225 if (wma_validate_handle(wma_handle))
1226 return;
1227
1228 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1229 wmi_extscan_start_stop_event_id,
1230 wma_extscan_start_stop_event_handler,
1231 WMA_RX_SERIALIZER_CTX);
1232
1233 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1234 wmi_extscan_capabilities_event_id,
1235 wma_extscan_capabilities_event_handler,
1236 WMA_RX_SERIALIZER_CTX);
1237
1238 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1239 wmi_extscan_hotlist_match_event_id,
1240 wma_extscan_hotlist_match_event_handler,
1241 WMA_RX_SERIALIZER_CTX);
1242
1243 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1244 wmi_extscan_wlan_change_results_event_id,
1245 wma_extscan_change_results_event_handler,
1246 WMA_RX_SERIALIZER_CTX);
1247
1248 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1249 wmi_extscan_operation_event_id,
1250 wma_extscan_operations_event_handler,
1251 WMA_RX_SERIALIZER_CTX);
1252 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1253 wmi_extscan_table_usage_event_id,
1254 wma_extscan_table_usage_event_handler,
1255 WMA_RX_SERIALIZER_CTX);
1256
1257 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1258 wmi_extscan_cached_results_event_id,
1259 wma_extscan_cached_results_event_handler,
1260 WMA_RX_SERIALIZER_CTX);
1261
1262 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1263 wmi_passpoint_match_event_id,
1264 wma_passpoint_match_event_handler,
1265 WMA_RX_SERIALIZER_CTX);
1266 }
1267
1268 /**
1269 * wma_extscan_start_stop_event_handler() - extscan start/stop event handler
1270 * @handle: wma handle
1271 * @cmd_param_info: event buffer
1272 * @len: data length
1273 *
1274 * This function handles different extscan related commands
1275 * like start/stop/get results etc and indicate to upper layers.
1276 *
1277 * Return: 0 for success or error code.
1278 */
wma_extscan_start_stop_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)1279 int wma_extscan_start_stop_event_handler(void *handle,
1280 uint8_t *cmd_param_info,
1281 uint32_t len)
1282 {
1283 WMI_EXTSCAN_START_STOP_EVENTID_param_tlvs *param_buf;
1284 wmi_extscan_start_stop_event_fixed_param *event;
1285 struct sir_extscan_generic_response *extscan_ind;
1286 uint16_t event_type;
1287 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
1288
1289 if (!mac)
1290 return -EINVAL;
1291
1292 if (!mac->sme.ext_scan_ind_cb) {
1293 wma_err("Callback not registered");
1294 return -EINVAL;
1295 }
1296 param_buf = (WMI_EXTSCAN_START_STOP_EVENTID_param_tlvs *)
1297 cmd_param_info;
1298 if (!param_buf) {
1299 wma_err("Invalid extscan event");
1300 return -EINVAL;
1301 }
1302 event = param_buf->fixed_param;
1303 extscan_ind = qdf_mem_malloc(sizeof(*extscan_ind));
1304 if (!extscan_ind)
1305 return -ENOMEM;
1306
1307 switch (event->command) {
1308 case WMI_EXTSCAN_START_CMDID:
1309 event_type = eSIR_EXTSCAN_START_RSP;
1310 extscan_ind->status = event->status;
1311 extscan_ind->request_id = event->request_id;
1312 break;
1313 case WMI_EXTSCAN_STOP_CMDID:
1314 event_type = eSIR_EXTSCAN_STOP_RSP;
1315 extscan_ind->status = event->status;
1316 extscan_ind->request_id = event->request_id;
1317 break;
1318 case WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID:
1319 extscan_ind->status = event->status;
1320 extscan_ind->request_id = event->request_id;
1321 if (event->mode == WMI_EXTSCAN_MODE_STOP)
1322 event_type =
1323 eSIR_EXTSCAN_RESET_SIGNIFICANT_WIFI_CHANGE_RSP;
1324 else
1325 event_type =
1326 eSIR_EXTSCAN_SET_SIGNIFICANT_WIFI_CHANGE_RSP;
1327 break;
1328 case WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID:
1329 extscan_ind->status = event->status;
1330 extscan_ind->request_id = event->request_id;
1331 if (event->mode == WMI_EXTSCAN_MODE_STOP)
1332 event_type = eSIR_EXTSCAN_RESET_BSSID_HOTLIST_RSP;
1333 else
1334 event_type = eSIR_EXTSCAN_SET_BSSID_HOTLIST_RSP;
1335 break;
1336 case WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID:
1337 extscan_ind->status = event->status;
1338 extscan_ind->request_id = event->request_id;
1339 event_type = eSIR_EXTSCAN_CACHED_RESULTS_RSP;
1340 break;
1341 case WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID:
1342 extscan_ind->status = event->status;
1343 extscan_ind->request_id = event->request_id;
1344 if (event->mode == WMI_EXTSCAN_MODE_STOP)
1345 event_type =
1346 eSIR_EXTSCAN_RESET_SSID_HOTLIST_RSP;
1347 else
1348 event_type =
1349 eSIR_EXTSCAN_SET_SSID_HOTLIST_RSP;
1350 break;
1351 default:
1352 wma_err("Unknown event(%d) from target", event->status);
1353 qdf_mem_free(extscan_ind);
1354 return -EINVAL;
1355 }
1356 mac->sme.ext_scan_ind_cb(mac->hdd_handle, event_type, extscan_ind);
1357 wma_debug("sending event to umac for requestid %u with status %d",
1358 extscan_ind->request_id, extscan_ind->status);
1359 qdf_mem_free(extscan_ind);
1360 return 0;
1361 }
1362
1363 /**
1364 * wma_extscan_operations_event_handler() - extscan operation event handler
1365 * @handle: wma handle
1366 * @cmd_param_info: event buffer
1367 * @len: length
1368 *
1369 * This function handles different operations related event and indicate
1370 * upper layers with appropriate callback.
1371 *
1372 * Return: 0 for success or error code.
1373 */
wma_extscan_operations_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)1374 int wma_extscan_operations_event_handler(void *handle,
1375 uint8_t *cmd_param_info,
1376 uint32_t len)
1377 {
1378 tp_wma_handle wma = (tp_wma_handle) handle;
1379 WMI_EXTSCAN_OPERATION_EVENTID_param_tlvs *param_buf;
1380 wmi_extscan_operation_event_fixed_param *oprn_event;
1381 tSirExtScanOnScanEventIndParams *oprn_ind;
1382 uint32_t cnt;
1383 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
1384
1385 if (!mac)
1386 return -EINVAL;
1387
1388 if (!mac->sme.ext_scan_ind_cb) {
1389 wma_err("Callback not registered");
1390 return -EINVAL;
1391 }
1392 param_buf = (WMI_EXTSCAN_OPERATION_EVENTID_param_tlvs *)
1393 cmd_param_info;
1394 if (!param_buf) {
1395 wma_err("Invalid scan operation event");
1396 return -EINVAL;
1397 }
1398 oprn_event = param_buf->fixed_param;
1399 oprn_ind = qdf_mem_malloc(sizeof(*oprn_ind));
1400 if (!oprn_ind)
1401 return -ENOMEM;
1402
1403 oprn_ind->requestId = oprn_event->request_id;
1404
1405 switch (oprn_event->event) {
1406 case WMI_EXTSCAN_BUCKET_COMPLETED_EVENT:
1407 oprn_ind->status = 0;
1408 goto exit_handler;
1409 case WMI_EXTSCAN_CYCLE_STARTED_EVENT:
1410 wma_debug("received WMI_EXTSCAN_CYCLE_STARTED_EVENT");
1411
1412 if (oprn_event->num_buckets > param_buf->num_bucket_id) {
1413 wma_err("FW mesg num_buk %d more than TLV hdr %d",
1414 oprn_event->num_buckets,
1415 param_buf->num_bucket_id);
1416 qdf_mem_free(oprn_ind);
1417 return -EINVAL;
1418 }
1419
1420 cds_host_diag_log_work(&wma->extscan_wake_lock,
1421 WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION,
1422 WIFI_POWER_EVENT_WAKELOCK_EXT_SCAN);
1423 qdf_wake_lock_timeout_acquire(&wma->extscan_wake_lock,
1424 WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION);
1425 oprn_ind->scanEventType = WIFI_EXTSCAN_CYCLE_STARTED_EVENT;
1426 oprn_ind->status = 0;
1427 oprn_ind->buckets_scanned = 0;
1428 for (cnt = 0; cnt < oprn_event->num_buckets; cnt++)
1429 oprn_ind->buckets_scanned |=
1430 (1 << param_buf->bucket_id[cnt]);
1431 wma_debug("num_buckets %u request_id %u buckets_scanned %u",
1432 oprn_event->num_buckets, oprn_ind->requestId,
1433 oprn_ind->buckets_scanned);
1434 break;
1435 case WMI_EXTSCAN_CYCLE_COMPLETED_EVENT:
1436 wma_debug("received WMI_EXTSCAN_CYCLE_COMPLETED_EVENT");
1437 qdf_wake_lock_release(&wma->extscan_wake_lock,
1438 WIFI_POWER_EVENT_WAKELOCK_EXT_SCAN);
1439 oprn_ind->scanEventType = WIFI_EXTSCAN_CYCLE_COMPLETED_EVENT;
1440 oprn_ind->status = 0;
1441 /* Set bucket scanned mask to zero on cycle complete */
1442 oprn_ind->buckets_scanned = 0;
1443 break;
1444 case WMI_EXTSCAN_BUCKET_STARTED_EVENT:
1445 wma_debug("received WMI_EXTSCAN_BUCKET_STARTED_EVENT");
1446 oprn_ind->scanEventType = WIFI_EXTSCAN_BUCKET_STARTED_EVENT;
1447 oprn_ind->status = 0;
1448 goto exit_handler;
1449 case WMI_EXTSCAN_THRESHOLD_NUM_SCANS:
1450 wma_debug("received WMI_EXTSCAN_THRESHOLD_NUM_SCANS");
1451 oprn_ind->scanEventType = WIFI_EXTSCAN_THRESHOLD_NUM_SCANS;
1452 oprn_ind->status = 0;
1453 break;
1454 case WMI_EXTSCAN_THRESHOLD_PERCENT:
1455 wma_debug("received WMI_EXTSCAN_THRESHOLD_PERCENT");
1456 oprn_ind->scanEventType = WIFI_EXTSCAN_THRESHOLD_PERCENT;
1457 oprn_ind->status = 0;
1458 break;
1459 default:
1460 wma_err("Unknown event(%d) from target", oprn_event->event);
1461 qdf_mem_free(oprn_ind);
1462 return -EINVAL;
1463 }
1464 mac->sme.ext_scan_ind_cb(mac->hdd_handle,
1465 eSIR_EXTSCAN_SCAN_PROGRESS_EVENT_IND, oprn_ind);
1466 wma_debug("sending scan progress event to hdd");
1467 exit_handler:
1468 qdf_mem_free(oprn_ind);
1469 return 0;
1470 }
1471
1472 /**
1473 * wma_extscan_table_usage_event_handler() - extscan table usage event handler
1474 * @handle: wma handle
1475 * @cmd_param_info: event buffer
1476 * @len: length
1477 *
1478 * This function handles table usage related event and indicate
1479 * upper layers with appropriate callback.
1480 *
1481 * Return: 0 for success or error code.
1482 */
wma_extscan_table_usage_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)1483 int wma_extscan_table_usage_event_handler(void *handle,
1484 uint8_t *cmd_param_info,
1485 uint32_t len)
1486 {
1487 WMI_EXTSCAN_TABLE_USAGE_EVENTID_param_tlvs *param_buf;
1488 wmi_extscan_table_usage_event_fixed_param *event;
1489 tSirExtScanResultsAvailableIndParams *tbl_usg_ind;
1490 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
1491
1492 if (!mac)
1493 return -EINVAL;
1494
1495 if (!mac->sme.ext_scan_ind_cb) {
1496 wma_err("Callback not registered");
1497 return -EINVAL;
1498 }
1499 param_buf = (WMI_EXTSCAN_TABLE_USAGE_EVENTID_param_tlvs *)
1500 cmd_param_info;
1501 if (!param_buf) {
1502 wma_err("Invalid table usage event");
1503 return -EINVAL;
1504 }
1505 event = param_buf->fixed_param;
1506 tbl_usg_ind = qdf_mem_malloc(sizeof(*tbl_usg_ind));
1507 if (!tbl_usg_ind)
1508 return -ENOMEM;
1509
1510 tbl_usg_ind->requestId = event->request_id;
1511 tbl_usg_ind->numResultsAvailable = event->entries_in_use;
1512 mac->sme.ext_scan_ind_cb(mac->hdd_handle,
1513 eSIR_EXTSCAN_SCAN_RES_AVAILABLE_IND,
1514 tbl_usg_ind);
1515 wma_debug("sending scan_res available event to hdd");
1516 qdf_mem_free(tbl_usg_ind);
1517 return 0;
1518 }
1519
1520 /**
1521 * wma_extscan_capabilities_event_handler() - extscan capabilities event handler
1522 * @handle: wma handle
1523 * @cmd_param_info: event buffer
1524 * @len: length
1525 *
1526 * This function handles capabilities event and indicate
1527 * upper layers with registered callback.
1528 *
1529 * Return: 0 for success or error code.
1530 */
wma_extscan_capabilities_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)1531 int wma_extscan_capabilities_event_handler(void *handle,
1532 uint8_t *cmd_param_info,
1533 uint32_t len)
1534 {
1535 WMI_EXTSCAN_CAPABILITIES_EVENTID_param_tlvs *param_buf;
1536 wmi_extscan_capabilities_event_fixed_param *event;
1537 wmi_extscan_cache_capabilities *src_cache;
1538 wmi_extscan_hotlist_monitor_capabilities *src_hotlist;
1539 wmi_extscan_wlan_change_monitor_capabilities *src_change;
1540 struct ext_scan_capabilities_response *dest_capab;
1541 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
1542
1543 if (!mac)
1544 return -EINVAL;
1545
1546 if (!mac->sme.ext_scan_ind_cb) {
1547 wma_err("Callback not registered");
1548 return -EINVAL;
1549 }
1550 param_buf = (WMI_EXTSCAN_CAPABILITIES_EVENTID_param_tlvs *)
1551 cmd_param_info;
1552 if (!param_buf) {
1553 wma_err("Invalid capabilities event");
1554 return -EINVAL;
1555 }
1556 event = param_buf->fixed_param;
1557 src_cache = param_buf->extscan_cache_capabilities;
1558 src_hotlist = param_buf->hotlist_capabilities;
1559 src_change = param_buf->wlan_change_capabilities;
1560
1561 if (!src_cache || !src_hotlist || !src_change) {
1562 wma_err("Invalid capabilities list");
1563 return -EINVAL;
1564 }
1565 dest_capab = qdf_mem_malloc(sizeof(*dest_capab));
1566 if (!dest_capab)
1567 return -ENOMEM;
1568
1569 dest_capab->requestId = event->request_id;
1570 dest_capab->max_scan_buckets = src_cache->max_buckets;
1571 dest_capab->max_scan_cache_size = src_cache->scan_cache_entry_size;
1572 dest_capab->max_ap_cache_per_scan = src_cache->max_bssid_per_scan;
1573 dest_capab->max_scan_reporting_threshold =
1574 src_cache->max_table_usage_threshold;
1575
1576 dest_capab->max_hotlist_bssids = src_hotlist->max_hotlist_entries;
1577 dest_capab->max_rssi_sample_size =
1578 src_change->max_rssi_averaging_samples;
1579 dest_capab->max_bssid_history_entries =
1580 src_change->max_rssi_history_entries;
1581 dest_capab->max_significant_wifi_change_aps =
1582 src_change->max_wlan_change_entries;
1583 dest_capab->max_hotlist_ssids =
1584 event->num_extscan_hotlist_ssid;
1585 dest_capab->max_number_epno_networks =
1586 event->num_epno_networks;
1587 dest_capab->max_number_epno_networks_by_ssid =
1588 event->num_epno_networks;
1589 dest_capab->max_number_of_allow_listed_ssid =
1590 event->num_roam_ssid_whitelist;
1591 dest_capab->max_number_of_deny_listed_bssid =
1592 event->num_roam_bssid_blacklist;
1593 dest_capab->status = 0;
1594
1595 wma_debug("request_id: %u status: %d",
1596 dest_capab->requestId, dest_capab->status);
1597
1598 wma_debug("Capabilities: max_scan_buckets: %d, max_hotlist_bssids: %d, max_scan_cache_size: %d, max_ap_cache_per_scan: %d",
1599 dest_capab->max_scan_buckets,
1600 dest_capab->max_hotlist_bssids, dest_capab->max_scan_cache_size,
1601 dest_capab->max_ap_cache_per_scan);
1602 wma_debug("max_scan_reporting_threshold: %d, max_rssi_sample_size: %d, max_bssid_history_entries: %d, max_significant_wifi_change_aps: %d",
1603 dest_capab->max_scan_reporting_threshold,
1604 dest_capab->max_rssi_sample_size,
1605 dest_capab->max_bssid_history_entries,
1606 dest_capab->max_significant_wifi_change_aps);
1607
1608 wma_debug("Capabilities: max_hotlist_ssids: %d, max_number_epno_networks: %d, max_number_epno_networks_by_ssid: %d",
1609 dest_capab->max_hotlist_ssids,
1610 dest_capab->max_number_epno_networks,
1611 dest_capab->max_number_epno_networks_by_ssid);
1612 wma_debug("max_number_of_allow_listed_ssid: %d, max_number_of_deny_listed_bssid: %d",
1613 dest_capab->max_number_of_allow_listed_ssid,
1614 dest_capab->max_number_of_deny_listed_bssid);
1615
1616 mac->sme.ext_scan_ind_cb(mac->hdd_handle,
1617 eSIR_EXTSCAN_GET_CAPABILITIES_IND, dest_capab);
1618 qdf_mem_free(dest_capab);
1619 return 0;
1620 }
1621
1622 /**
1623 * wma_extscan_hotlist_match_event_handler() - hotlist match event handler
1624 * @handle: wma handle
1625 * @cmd_param_info: event buffer
1626 * @len: length
1627 *
1628 * This function handles hotlist match event and indicate
1629 * upper layers with registered callback.
1630 *
1631 * Return: 0 for success or error code.
1632 */
wma_extscan_hotlist_match_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)1633 int wma_extscan_hotlist_match_event_handler(void *handle,
1634 uint8_t *cmd_param_info,
1635 uint32_t len)
1636 {
1637 WMI_EXTSCAN_HOTLIST_MATCH_EVENTID_param_tlvs *param_buf;
1638 wmi_extscan_hotlist_match_event_fixed_param *event;
1639 struct extscan_hotlist_match *dest_hotlist;
1640 tSirWifiScanResult *dest_ap;
1641 wmi_extscan_wlan_descriptor *src_hotlist;
1642 uint32_t numap;
1643 int j, ap_found = 0;
1644 uint32_t buf_len;
1645 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
1646
1647 if (!mac)
1648 return -EINVAL;
1649
1650 if (!mac->sme.ext_scan_ind_cb) {
1651 wma_err("Callback not registered");
1652 return -EINVAL;
1653 }
1654 param_buf = (WMI_EXTSCAN_HOTLIST_MATCH_EVENTID_param_tlvs *)
1655 cmd_param_info;
1656 if (!param_buf) {
1657 wma_err("Invalid hotlist match event");
1658 return -EINVAL;
1659 }
1660 event = param_buf->fixed_param;
1661 src_hotlist = param_buf->hotlist_match;
1662 numap = event->total_entries;
1663
1664 if (!src_hotlist || !numap) {
1665 wma_err("Hotlist AP's list invalid");
1666 return -EINVAL;
1667 }
1668 if (numap > param_buf->num_hotlist_match) {
1669 wma_err("Invalid no of total enteries %d", numap);
1670 return -EINVAL;
1671 }
1672 if (numap > WMA_EXTSCAN_MAX_HOTLIST_ENTRIES) {
1673 wma_err("Total Entries %u greater than max", numap);
1674 numap = WMA_EXTSCAN_MAX_HOTLIST_ENTRIES;
1675 }
1676
1677 buf_len = sizeof(wmi_extscan_hotlist_match_event_fixed_param) +
1678 WMI_TLV_HDR_SIZE +
1679 (numap * sizeof(wmi_extscan_wlan_descriptor));
1680
1681 if (buf_len > len) {
1682 wma_err("Invalid buf len from FW %d numap %d", len, numap);
1683 return -EINVAL;
1684 }
1685
1686 dest_hotlist = qdf_mem_malloc(sizeof(*dest_hotlist) +
1687 sizeof(*dest_ap) * numap);
1688 if (!dest_hotlist)
1689 return -ENOMEM;
1690
1691 dest_ap = &dest_hotlist->ap[0];
1692 dest_hotlist->numOfAps = numap;
1693 dest_hotlist->requestId = event->config_request_id;
1694
1695 if (event->first_entry_index +
1696 event->num_entries_in_page < event->total_entries)
1697 dest_hotlist->moreData = 1;
1698 else
1699 dest_hotlist->moreData = 0;
1700
1701 wma_debug("Hotlist match: requestId: %u numOfAps: %d",
1702 dest_hotlist->requestId, dest_hotlist->numOfAps);
1703
1704 /*
1705 * Currently firmware sends only one bss information in-case
1706 * of both hotlist ap found and lost.
1707 */
1708 for (j = 0; j < numap; j++) {
1709 dest_ap->rssi = 0;
1710 dest_ap->channel = src_hotlist->channel;
1711 dest_ap->ts = src_hotlist->tstamp;
1712 ap_found = src_hotlist->flags & WMI_HOTLIST_FLAG_PRESENCE;
1713 dest_ap->rtt = src_hotlist->rtt;
1714 dest_ap->rtt_sd = src_hotlist->rtt_sd;
1715 dest_ap->beaconPeriod = src_hotlist->beacon_interval;
1716 dest_ap->capability = src_hotlist->capabilities;
1717 dest_ap->ieLength = src_hotlist->ie_length;
1718 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_hotlist->bssid,
1719 dest_ap->bssid.bytes);
1720 if (src_hotlist->ssid.ssid_len > WLAN_SSID_MAX_LEN) {
1721 wma_err("Invalid SSID len %d, truncating",
1722 src_hotlist->ssid.ssid_len);
1723 src_hotlist->ssid.ssid_len = WLAN_SSID_MAX_LEN;
1724 }
1725 qdf_mem_copy(dest_ap->ssid, src_hotlist->ssid.ssid,
1726 src_hotlist->ssid.ssid_len);
1727 dest_ap->ssid[src_hotlist->ssid.ssid_len] = '\0';
1728 dest_ap++;
1729 src_hotlist++;
1730 }
1731 dest_hotlist->ap_found = ap_found;
1732 mac->sme.ext_scan_ind_cb(mac->hdd_handle,
1733 eSIR_EXTSCAN_HOTLIST_MATCH_IND, dest_hotlist);
1734 wma_debug("sending hotlist match event to hdd");
1735 qdf_mem_free(dest_hotlist);
1736 return 0;
1737 }
1738
1739 /** wma_extscan_find_unique_scan_ids() - find unique scan ids
1740 * @cmd_param_info: event data.
1741 *
1742 * This utility function parses the input bss table of information
1743 * and find the unique number of scan ids
1744 *
1745 * Return: 0 on success; error number otherwise
1746 */
wma_extscan_find_unique_scan_ids(const u_int8_t * cmd_param_info)1747 static int wma_extscan_find_unique_scan_ids(const u_int8_t *cmd_param_info)
1748 {
1749 WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf;
1750 wmi_extscan_cached_results_event_fixed_param *event;
1751 wmi_extscan_wlan_descriptor *src_hotlist;
1752 wmi_extscan_rssi_info *src_rssi;
1753 int prev_scan_id, scan_ids_cnt, i;
1754
1755 param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *)
1756 cmd_param_info;
1757 event = param_buf->fixed_param;
1758 src_hotlist = param_buf->bssid_list;
1759 src_rssi = param_buf->rssi_list;
1760
1761 /* Find the unique number of scan_id's for grouping */
1762 prev_scan_id = src_rssi->scan_cycle_id;
1763 scan_ids_cnt = 1;
1764 for (i = 1; i < param_buf->num_rssi_list; i++) {
1765 src_rssi++;
1766
1767 if (prev_scan_id != src_rssi->scan_cycle_id) {
1768 scan_ids_cnt++;
1769 prev_scan_id = src_rssi->scan_cycle_id;
1770 }
1771 }
1772
1773 return scan_ids_cnt;
1774 }
1775
1776 /** wma_fill_num_results_per_scan_id() - fill number of bss per scan id
1777 * @cmd_param_info: event data.
1778 * @scan_id_group: pointer to scan id group.
1779 *
1780 * This utility function parses the input bss table of information
1781 * and finds how many bss are there per unique scan id.
1782 *
1783 * Return: 0 on success; error number otherwise
1784 */
wma_fill_num_results_per_scan_id(const u_int8_t * cmd_param_info,struct extscan_cached_scan_result * scan_id_group)1785 static int wma_fill_num_results_per_scan_id(const u_int8_t *cmd_param_info,
1786 struct extscan_cached_scan_result *scan_id_group)
1787 {
1788 WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf;
1789 wmi_extscan_cached_results_event_fixed_param *event;
1790 wmi_extscan_wlan_descriptor *src_hotlist;
1791 wmi_extscan_rssi_info *src_rssi;
1792 struct extscan_cached_scan_result *t_scan_id_grp;
1793 int i, prev_scan_id;
1794
1795 param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *)
1796 cmd_param_info;
1797 event = param_buf->fixed_param;
1798 src_hotlist = param_buf->bssid_list;
1799 src_rssi = param_buf->rssi_list;
1800 t_scan_id_grp = scan_id_group;
1801
1802 prev_scan_id = src_rssi->scan_cycle_id;
1803
1804 t_scan_id_grp->scan_id = src_rssi->scan_cycle_id;
1805 t_scan_id_grp->flags = src_rssi->flags;
1806 t_scan_id_grp->buckets_scanned = src_rssi->buckets_scanned;
1807 t_scan_id_grp->num_results = 1;
1808 for (i = 1; i < param_buf->num_rssi_list; i++) {
1809 src_rssi++;
1810 if (prev_scan_id == src_rssi->scan_cycle_id) {
1811 t_scan_id_grp->num_results++;
1812 } else {
1813 t_scan_id_grp++;
1814 prev_scan_id = t_scan_id_grp->scan_id =
1815 src_rssi->scan_cycle_id;
1816 t_scan_id_grp->flags = src_rssi->flags;
1817 t_scan_id_grp->buckets_scanned =
1818 src_rssi->buckets_scanned;
1819 t_scan_id_grp->num_results = 1;
1820 }
1821 }
1822 return 0;
1823 }
1824
1825 /** wma_group_num_bss_to_scan_id() - group bss to scan id table
1826 * @cmd_param_info: event data.
1827 * @cached_result: pointer to cached table.
1828 *
1829 * This function reads the bss information from the format
1830 * ------------------------------------------------------------------------
1831 * | bss info {rssi, channel, ssid, bssid, timestamp} | scan id_1 | flags |
1832 * | bss info {rssi, channel, ssid, bssid, timestamp} | scan id_2 | flags |
1833 * ........................................................................
1834 * | bss info {rssi, channel, ssid, bssid, timestamp} | scan id_N | flags |
1835 * ------------------------------------------------------------------------
1836 *
1837 * and converts it into the below format and store it
1838 *
1839 * ------------------------------------------------------------------------
1840 * | scan id_1 | -> bss info_1 -> bss info_2 -> .... bss info_M1
1841 * | scan id_2 | -> bss info_1 -> bss info_2 -> .... bss info_M2
1842 * ......................
1843 * | scan id_N | -> bss info_1 -> bss info_2 -> .... bss info_Mn
1844 * ------------------------------------------------------------------------
1845 *
1846 * Return: 0 on success; error number otherwise
1847 */
wma_group_num_bss_to_scan_id(const u_int8_t * cmd_param_info,struct extscan_cached_scan_results * cached_result)1848 static int wma_group_num_bss_to_scan_id(const u_int8_t *cmd_param_info,
1849 struct extscan_cached_scan_results *cached_result)
1850 {
1851 WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf;
1852 wmi_extscan_cached_results_event_fixed_param *event;
1853 wmi_extscan_wlan_descriptor *src_hotlist;
1854 wmi_extscan_rssi_info *src_rssi;
1855 struct extscan_cached_scan_results *t_cached_result;
1856 struct extscan_cached_scan_result *t_scan_id_grp;
1857 int i, j;
1858 uint32_t total_scan_num_results = 0;
1859 tSirWifiScanResult *ap;
1860
1861 param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *)
1862 cmd_param_info;
1863 event = param_buf->fixed_param;
1864 src_hotlist = param_buf->bssid_list;
1865 src_rssi = param_buf->rssi_list;
1866 t_cached_result = cached_result;
1867 t_scan_id_grp = &t_cached_result->result[0];
1868
1869 for (i = 0; i < t_cached_result->num_scan_ids; i++) {
1870 total_scan_num_results += t_scan_id_grp->num_results;
1871 t_scan_id_grp++;
1872 }
1873
1874 if (total_scan_num_results > param_buf->num_bssid_list) {
1875 wma_err("total_scan_num_results %d, num_bssid_list %d",
1876 total_scan_num_results,
1877 param_buf->num_bssid_list);
1878 return -EINVAL;
1879 }
1880
1881 t_scan_id_grp = &t_cached_result->result[0];
1882 wma_debug("num_scan_ids:%d",
1883 t_cached_result->num_scan_ids);
1884 for (i = 0; i < t_cached_result->num_scan_ids; i++) {
1885 wma_debug("num_results:%d", t_scan_id_grp->num_results);
1886 t_scan_id_grp->ap = qdf_mem_malloc(t_scan_id_grp->num_results *
1887 sizeof(*ap));
1888 if (!t_scan_id_grp->ap)
1889 return -ENOMEM;
1890
1891 ap = &t_scan_id_grp->ap[0];
1892 for (j = 0; j < t_scan_id_grp->num_results; j++) {
1893 ap->channel = src_hotlist->channel;
1894 ap->ts = WMA_MSEC_TO_USEC(src_rssi->tstamp);
1895 ap->rtt = src_hotlist->rtt;
1896 ap->rtt_sd = src_hotlist->rtt_sd;
1897 ap->beaconPeriod = src_hotlist->beacon_interval;
1898 ap->capability = src_hotlist->capabilities;
1899 ap->ieLength = src_hotlist->ie_length;
1900
1901 /* Firmware already applied noise floor adjustment and
1902 * due to WMI interface "UINT32 rssi", host driver
1903 * receives a positive value, hence convert to
1904 * signed char to get the absolute rssi.
1905 */
1906 ap->rssi = (signed char) src_rssi->rssi;
1907 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_hotlist->bssid,
1908 ap->bssid.bytes);
1909
1910 if (src_hotlist->ssid.ssid_len >
1911 WLAN_SSID_MAX_LEN) {
1912 wma_debug("Invalid SSID len %d, truncating",
1913 src_hotlist->ssid.ssid_len);
1914 src_hotlist->ssid.ssid_len =
1915 WLAN_SSID_MAX_LEN;
1916 }
1917 qdf_mem_copy(ap->ssid, src_hotlist->ssid.ssid,
1918 src_hotlist->ssid.ssid_len);
1919 ap->ssid[src_hotlist->ssid.ssid_len] = '\0';
1920 ap++;
1921 src_rssi++;
1922 src_hotlist++;
1923 }
1924 t_scan_id_grp++;
1925 }
1926 return 0;
1927 }
1928
1929 /**
1930 * wma_extscan_cached_results_event_handler() - cached results event handler
1931 * @handle: wma handle
1932 * @cmd_param_info: event buffer
1933 * @len: length of @cmd_param_info
1934 *
1935 * This function handles cached results event and indicate
1936 * cached results to upper layer.
1937 *
1938 * Return: 0 for success or error code.
1939 */
wma_extscan_cached_results_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)1940 int wma_extscan_cached_results_event_handler(void *handle,
1941 uint8_t *cmd_param_info,
1942 uint32_t len)
1943 {
1944 WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf;
1945 wmi_extscan_cached_results_event_fixed_param *event;
1946 struct extscan_cached_scan_results *dest_cachelist;
1947 struct extscan_cached_scan_result *dest_result;
1948 struct extscan_cached_scan_results empty_cachelist;
1949 wmi_extscan_wlan_descriptor *src_hotlist;
1950 wmi_extscan_rssi_info *src_rssi;
1951 int i, moredata, scan_ids_cnt, buf_len, status;
1952 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
1953 uint32_t total_len;
1954 bool excess_data = false;
1955
1956 if (!mac) {
1957 wma_err("Invalid mac");
1958 return -EINVAL;
1959 }
1960 if (!mac->sme.ext_scan_ind_cb) {
1961 wma_err("Callback not registered");
1962 return -EINVAL;
1963 }
1964 param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *)
1965 cmd_param_info;
1966 if (!param_buf) {
1967 wma_err("Invalid cached results event");
1968 return -EINVAL;
1969 }
1970 event = param_buf->fixed_param;
1971 src_hotlist = param_buf->bssid_list;
1972 src_rssi = param_buf->rssi_list;
1973 wma_debug("Total_entries: %u first_entry_index: %u num_entries_in_page: %d",
1974 event->total_entries,
1975 event->first_entry_index,
1976 event->num_entries_in_page);
1977
1978 if (!src_hotlist || !src_rssi || !event->num_entries_in_page) {
1979 wma_warn("Cached results empty, send 0 results");
1980 goto noresults;
1981 }
1982
1983 if (event->num_entries_in_page >
1984 (WMI_SVC_MSG_MAX_SIZE - sizeof(*event))/sizeof(*src_hotlist) ||
1985 event->num_entries_in_page > param_buf->num_bssid_list) {
1986 wma_err("excess num_entries_in_page %d in WMI event. num_bssid_list %d",
1987 event->num_entries_in_page, param_buf->num_bssid_list);
1988 return -EINVAL;
1989 } else {
1990 total_len = sizeof(*event) +
1991 (event->num_entries_in_page * sizeof(*src_hotlist));
1992 }
1993 for (i = 0; i < event->num_entries_in_page; i++) {
1994 if (src_hotlist[i].ie_length >
1995 WMI_SVC_MSG_MAX_SIZE - total_len) {
1996 excess_data = true;
1997 break;
1998 } else {
1999 total_len += src_hotlist[i].ie_length;
2000 wma_debug("total len IE: %d", total_len);
2001 }
2002
2003 if (src_hotlist[i].number_rssi_samples >
2004 (WMI_SVC_MSG_MAX_SIZE - total_len) / sizeof(*src_rssi)) {
2005 excess_data = true;
2006 break;
2007 } else {
2008 total_len += (src_hotlist[i].number_rssi_samples *
2009 sizeof(*src_rssi));
2010 wma_debug("total len RSSI samples: %d", total_len);
2011 }
2012 }
2013 if (excess_data) {
2014 wma_err("excess data in WMI event");
2015 return -EINVAL;
2016 }
2017
2018 if (event->first_entry_index +
2019 event->num_entries_in_page < event->total_entries)
2020 moredata = 1;
2021 else
2022 moredata = 0;
2023
2024 dest_cachelist = qdf_mem_malloc(sizeof(*dest_cachelist));
2025 if (!dest_cachelist)
2026 return -ENOMEM;
2027
2028 qdf_mem_zero(dest_cachelist, sizeof(*dest_cachelist));
2029 dest_cachelist->request_id = event->request_id;
2030 dest_cachelist->more_data = moredata;
2031
2032 scan_ids_cnt = wma_extscan_find_unique_scan_ids(cmd_param_info);
2033 wma_debug("scan_ids_cnt %d", scan_ids_cnt);
2034 dest_cachelist->num_scan_ids = scan_ids_cnt;
2035
2036 buf_len = sizeof(*dest_result) * scan_ids_cnt;
2037 dest_cachelist->result = qdf_mem_malloc(buf_len);
2038 if (!dest_cachelist->result) {
2039 qdf_mem_free(dest_cachelist);
2040 return -ENOMEM;
2041 }
2042
2043 dest_result = dest_cachelist->result;
2044 wma_fill_num_results_per_scan_id(cmd_param_info, dest_result);
2045
2046 status = wma_group_num_bss_to_scan_id(cmd_param_info, dest_cachelist);
2047 if (!status)
2048 mac->sme.ext_scan_ind_cb(mac->hdd_handle,
2049 eSIR_EXTSCAN_CACHED_RESULTS_IND,
2050 dest_cachelist);
2051 else
2052 wma_debug("wma_group_num_bss_to_scan_id failed, not calling callback");
2053
2054 dest_result = dest_cachelist->result;
2055 for (i = 0; i < dest_cachelist->num_scan_ids; i++) {
2056 if (dest_result->ap)
2057 qdf_mem_free(dest_result->ap);
2058 dest_result++;
2059 }
2060 qdf_mem_free(dest_cachelist->result);
2061 qdf_mem_free(dest_cachelist);
2062 return status;
2063
2064 noresults:
2065 empty_cachelist.request_id = event->request_id;
2066 empty_cachelist.more_data = 0;
2067 empty_cachelist.num_scan_ids = 0;
2068
2069 mac->sme.ext_scan_ind_cb(mac->hdd_handle,
2070 eSIR_EXTSCAN_CACHED_RESULTS_IND,
2071 &empty_cachelist);
2072 return 0;
2073 }
2074
2075 /**
2076 * wma_extscan_change_results_event_handler() - change results event handler
2077 * @handle: wma handle
2078 * @cmd_param_info: event buffer
2079 * @len: length
2080 *
2081 * This function handles change results event and indicate
2082 * change results to upper layer.
2083 *
2084 * Return: 0 for success or error code.
2085 */
wma_extscan_change_results_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)2086 int wma_extscan_change_results_event_handler(void *handle,
2087 uint8_t *cmd_param_info,
2088 uint32_t len)
2089 {
2090 WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID_param_tlvs *param_buf;
2091 wmi_extscan_wlan_change_results_event_fixed_param *event;
2092 tSirWifiSignificantChangeEvent *dest_chglist;
2093 tSirWifiSignificantChange *dest_ap;
2094 wmi_extscan_wlan_change_result_bssid *src_chglist;
2095
2096 uint32_t numap;
2097 int i, k;
2098 uint8_t *src_rssi;
2099 int count = 0;
2100 int moredata;
2101 uint32_t rssi_num = 0;
2102 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
2103 uint32_t buf_len;
2104 bool excess_data = false;
2105
2106 if (!mac) {
2107 wma_err("Invalid mac");
2108 return -EINVAL;
2109 }
2110 if (!mac->sme.ext_scan_ind_cb) {
2111 wma_err("Callback not registered");
2112 return -EINVAL;
2113 }
2114 param_buf = (WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID_param_tlvs *)
2115 cmd_param_info;
2116 if (!param_buf) {
2117 wma_err("Invalid change monitor event");
2118 return -EINVAL;
2119 }
2120 event = param_buf->fixed_param;
2121 src_chglist = param_buf->bssid_signal_descriptor_list;
2122 src_rssi = param_buf->rssi_list;
2123 numap = event->num_entries_in_page;
2124
2125 if (!src_chglist || !numap) {
2126 wma_err("Results invalid");
2127 return -EINVAL;
2128 }
2129 if (numap > param_buf->num_bssid_signal_descriptor_list) {
2130 wma_err("Invalid num of entries in page: %d", numap);
2131 return -EINVAL;
2132 }
2133 for (i = 0; i < numap; i++) {
2134 if (src_chglist->num_rssi_samples > (UINT_MAX - rssi_num)) {
2135 wma_err("Invalid num of rssi samples %d numap %d rssi_num %d",
2136 src_chglist->num_rssi_samples,
2137 numap, rssi_num);
2138 return -EINVAL;
2139 }
2140 rssi_num += src_chglist->num_rssi_samples;
2141 src_chglist++;
2142 }
2143 src_chglist = param_buf->bssid_signal_descriptor_list;
2144
2145 if (event->first_entry_index +
2146 event->num_entries_in_page < event->total_entries) {
2147 moredata = 1;
2148 } else {
2149 moredata = 0;
2150 }
2151
2152 do {
2153 if (event->num_entries_in_page >
2154 (WMI_SVC_MSG_MAX_SIZE - sizeof(*event))/
2155 sizeof(*src_chglist)) {
2156 excess_data = true;
2157 break;
2158 } else {
2159 buf_len =
2160 sizeof(*event) + (event->num_entries_in_page *
2161 sizeof(*src_chglist));
2162 }
2163 if (rssi_num >
2164 (WMI_SVC_MSG_MAX_SIZE - buf_len)/sizeof(int32_t)) {
2165 excess_data = true;
2166 break;
2167 }
2168 } while (0);
2169
2170 if (excess_data) {
2171 wma_err("buffer len exceeds WMI payload,numap:%d, rssi_num:%d",
2172 numap, rssi_num);
2173 QDF_ASSERT(0);
2174 return -EINVAL;
2175 }
2176 dest_chglist = qdf_mem_malloc(sizeof(*dest_chglist) +
2177 sizeof(*dest_ap) * numap +
2178 sizeof(int32_t) * rssi_num);
2179 if (!dest_chglist)
2180 return -ENOMEM;
2181
2182 dest_ap = &dest_chglist->ap[0];
2183 for (i = 0; i < numap; i++) {
2184 dest_ap->channel = src_chglist->channel;
2185 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_chglist->bssid,
2186 dest_ap->bssid.bytes);
2187 dest_ap->numOfRssi = src_chglist->num_rssi_samples;
2188 if (dest_ap->numOfRssi) {
2189 if ((dest_ap->numOfRssi + count) >
2190 param_buf->num_rssi_list) {
2191 wma_err("Invalid num in rssi list: %d",
2192 dest_ap->numOfRssi);
2193 qdf_mem_free(dest_chglist);
2194 return -EINVAL;
2195 }
2196 for (k = 0; k < dest_ap->numOfRssi; k++) {
2197 dest_ap->rssi[k] = WMA_TGT_NOISE_FLOOR_DBM +
2198 src_rssi[count++];
2199 }
2200 }
2201 dest_ap = (tSirWifiSignificantChange *)((char *)dest_ap +
2202 dest_ap->numOfRssi * sizeof(int32_t) +
2203 sizeof(*dest_ap));
2204 src_chglist++;
2205 }
2206 dest_chglist->requestId = event->request_id;
2207 dest_chglist->moreData = moredata;
2208 dest_chglist->numResults = numap;
2209
2210 mac->sme.ext_scan_ind_cb(mac->hdd_handle,
2211 eSIR_EXTSCAN_SIGNIFICANT_WIFI_CHANGE_RESULTS_IND,
2212 dest_chglist);
2213 wma_debug("sending change monitor results");
2214 qdf_mem_free(dest_chglist);
2215 return 0;
2216 }
2217
2218 /**
2219 * wma_passpoint_match_event_handler() - passpoint match found event handler
2220 * @handle: WMA handle
2221 * @cmd_param_info: event data
2222 * @len: event data length
2223 *
2224 * This is the passpoint match found event handler; it reads event data from
2225 * @cmd_param_info and fill in the destination buffer and sends indication
2226 * up layer.
2227 *
2228 * Return: 0 on success; error number otherwise
2229 */
wma_passpoint_match_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)2230 int wma_passpoint_match_event_handler(void *handle,
2231 uint8_t *cmd_param_info,
2232 uint32_t len)
2233 {
2234 WMI_PASSPOINT_MATCH_EVENTID_param_tlvs *param_buf;
2235 wmi_passpoint_event_hdr *event;
2236 struct wifi_passpoint_match *dest_match;
2237 tSirWifiScanResult *dest_ap;
2238 uint8_t *buf_ptr;
2239 uint32_t buf_len = 0;
2240 bool excess_data = false;
2241 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
2242
2243 if (!mac) {
2244 wma_err("Invalid mac");
2245 return -EINVAL;
2246 }
2247 if (!mac->sme.ext_scan_ind_cb) {
2248 wma_err("Callback not registered");
2249 return -EINVAL;
2250 }
2251
2252 param_buf = (WMI_PASSPOINT_MATCH_EVENTID_param_tlvs *) cmd_param_info;
2253 if (!param_buf) {
2254 wma_err("Invalid passpoint match event");
2255 return -EINVAL;
2256 }
2257 event = param_buf->fixed_param;
2258 buf_ptr = (uint8_t *)param_buf->fixed_param;
2259
2260 do {
2261 if (event->ie_length > (WMI_SVC_MSG_MAX_SIZE)) {
2262 excess_data = true;
2263 break;
2264 } else {
2265 buf_len = event->ie_length;
2266 }
2267
2268 if (event->anqp_length > (WMI_SVC_MSG_MAX_SIZE)) {
2269 excess_data = true;
2270 break;
2271 } else {
2272 buf_len += event->anqp_length;
2273 }
2274
2275 } while (0);
2276
2277 if (excess_data || buf_len > (WMI_SVC_MSG_MAX_SIZE - sizeof(*event)) ||
2278 buf_len > (WMI_SVC_MSG_MAX_SIZE - sizeof(*dest_match)) ||
2279 (event->ie_length + event->anqp_length) > param_buf->num_bufp) {
2280 wma_err("IE Length: %u or ANQP Length: %u is huge, num_bufp: %u",
2281 event->ie_length, event->anqp_length,
2282 param_buf->num_bufp);
2283 return -EINVAL;
2284 }
2285
2286 if (event->ssid.ssid_len > WLAN_SSID_MAX_LEN) {
2287 wma_debug("Invalid ssid len %d, truncating",
2288 event->ssid.ssid_len);
2289 event->ssid.ssid_len = WLAN_SSID_MAX_LEN;
2290 }
2291
2292 dest_match = qdf_mem_malloc(sizeof(*dest_match) + buf_len);
2293 if (!dest_match)
2294 return -EINVAL;
2295
2296 dest_ap = &dest_match->ap;
2297 dest_match->request_id = 0;
2298 dest_match->id = event->id;
2299 dest_match->anqp_len = event->anqp_length;
2300 wma_info("passpoint match: id: %u anqp length %u",
2301 dest_match->id, dest_match->anqp_len);
2302
2303 dest_ap->channel = event->channel_mhz;
2304 dest_ap->ts = event->timestamp;
2305 dest_ap->rtt = event->rtt;
2306 dest_ap->rssi = event->rssi;
2307 dest_ap->rtt_sd = event->rtt_sd;
2308 dest_ap->beaconPeriod = event->beacon_period;
2309 dest_ap->capability = event->capability;
2310 dest_ap->ieLength = event->ie_length;
2311 WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->bssid, dest_ap->bssid.bytes);
2312 qdf_mem_copy(dest_ap->ssid, event->ssid.ssid,
2313 event->ssid.ssid_len);
2314 dest_ap->ssid[event->ssid.ssid_len] = '\0';
2315 qdf_mem_copy(dest_ap->ieData, buf_ptr + sizeof(*event) +
2316 WMI_TLV_HDR_SIZE, dest_ap->ieLength);
2317 qdf_mem_copy(dest_match->anqp, buf_ptr + sizeof(*event) +
2318 WMI_TLV_HDR_SIZE + dest_ap->ieLength,
2319 dest_match->anqp_len);
2320
2321 mac->sme.ext_scan_ind_cb(mac->hdd_handle,
2322 eSIR_PASSPOINT_NETWORK_FOUND_IND,
2323 dest_match);
2324 wma_debug("sending passpoint match event to hdd");
2325 qdf_mem_free(dest_match);
2326 return 0;
2327 }
2328
wma_start_extscan(tp_wma_handle wma,struct wifi_scan_cmd_req_params * params)2329 QDF_STATUS wma_start_extscan(tp_wma_handle wma,
2330 struct wifi_scan_cmd_req_params *params)
2331 {
2332 QDF_STATUS status;
2333 struct wmi_unified *wmi_handle;
2334
2335 if (wma_validate_handle(wma))
2336 return QDF_STATUS_E_INVAL;
2337
2338 wmi_handle = wma->wmi_handle;
2339 if (wmi_validate_handle(wmi_handle))
2340 return QDF_STATUS_E_INVAL;
2341
2342 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) {
2343 wma_err("extscan not enabled");
2344 return QDF_STATUS_E_FAILURE;
2345 }
2346
2347 if (!params) {
2348 wma_err("NULL param");
2349 return QDF_STATUS_E_NOMEM;
2350 }
2351
2352 status = wmi_unified_start_extscan_cmd(wmi_handle, params);
2353 if (QDF_IS_STATUS_SUCCESS(status))
2354 wma->interfaces[params->vdev_id].extscan_in_progress = true;
2355
2356 wma_debug("Exit, vdev %d, status %d", params->vdev_id, status);
2357
2358 return status;
2359 }
2360
wma_stop_extscan(tp_wma_handle wma,struct extscan_stop_req_params * params)2361 QDF_STATUS wma_stop_extscan(tp_wma_handle wma,
2362 struct extscan_stop_req_params *params)
2363 {
2364 QDF_STATUS status;
2365 struct wmi_unified *wmi_handle;
2366
2367 if (wma_validate_handle(wma))
2368 return QDF_STATUS_E_INVAL;
2369
2370 wmi_handle = wma->wmi_handle;
2371 if (wmi_validate_handle(wmi_handle))
2372 return QDF_STATUS_E_INVAL;
2373
2374 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) {
2375 wma_err("extscan not enabled");
2376 return QDF_STATUS_E_FAILURE;
2377 }
2378
2379 status = wmi_unified_stop_extscan_cmd(wmi_handle, params);
2380 if (QDF_IS_STATUS_ERROR(status))
2381 return status;
2382
2383 wma->interfaces[params->vdev_id].extscan_in_progress = false;
2384 wma_debug("Extscan stop request sent successfully for vdev %d",
2385 params->vdev_id);
2386
2387 return status;
2388 }
2389
wma_extscan_start_hotlist_monitor(tp_wma_handle wma,struct extscan_bssid_hotlist_set_params * params)2390 QDF_STATUS wma_extscan_start_hotlist_monitor(tp_wma_handle wma,
2391 struct extscan_bssid_hotlist_set_params *params)
2392 {
2393 struct wmi_unified *wmi_handle;
2394
2395 if (wma_validate_handle(wma))
2396 return QDF_STATUS_E_INVAL;
2397
2398 wmi_handle = wma->wmi_handle;
2399 if (wmi_validate_handle(wmi_handle))
2400 return QDF_STATUS_E_INVAL;
2401
2402 if (!params) {
2403 wma_err("Invalid params");
2404 return QDF_STATUS_E_INVAL;
2405 }
2406
2407 return wmi_unified_extscan_start_hotlist_monitor_cmd(wmi_handle,
2408 params);
2409 }
2410
wma_extscan_stop_hotlist_monitor(tp_wma_handle wma,struct extscan_bssid_hotlist_reset_params * params)2411 QDF_STATUS wma_extscan_stop_hotlist_monitor(tp_wma_handle wma,
2412 struct extscan_bssid_hotlist_reset_params *params)
2413 {
2414 struct wmi_unified *wmi_handle;
2415
2416 if (wma_validate_handle(wma))
2417 return QDF_STATUS_E_INVAL;
2418
2419 wmi_handle = wma->wmi_handle;
2420 if (wmi_validate_handle(wmi_handle))
2421 return QDF_STATUS_E_INVAL;
2422
2423 if (!params) {
2424 wma_err("Invalid params");
2425 return QDF_STATUS_E_INVAL;
2426 }
2427 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) {
2428 wma_err("extscan not enabled");
2429 return QDF_STATUS_E_FAILURE;
2430 }
2431
2432 return wmi_unified_extscan_stop_hotlist_monitor_cmd(wmi_handle,
2433 params);
2434 }
2435
2436 QDF_STATUS
wma_extscan_start_change_monitor(tp_wma_handle wma,struct extscan_set_sig_changereq_params * params)2437 wma_extscan_start_change_monitor(tp_wma_handle wma,
2438 struct extscan_set_sig_changereq_params *params)
2439 {
2440 QDF_STATUS status;
2441 struct wmi_unified *wmi_handle;
2442
2443 if (wma_validate_handle(wma))
2444 return QDF_STATUS_E_INVAL;
2445
2446 wmi_handle = wma->wmi_handle;
2447 if (wmi_validate_handle(wmi_handle))
2448 return QDF_STATUS_E_INVAL;
2449
2450 if (!params) {
2451 wma_err("NULL params");
2452 return QDF_STATUS_E_NOMEM;
2453 }
2454
2455 status = wmi_unified_extscan_start_change_monitor_cmd(wmi_handle,
2456 params);
2457 return status;
2458 }
2459
wma_extscan_stop_change_monitor(tp_wma_handle wma,struct extscan_capabilities_reset_params * params)2460 QDF_STATUS wma_extscan_stop_change_monitor(tp_wma_handle wma,
2461 struct extscan_capabilities_reset_params *params)
2462 {
2463 struct wmi_unified *wmi_handle;
2464
2465 if (wma_validate_handle(wma))
2466 return QDF_STATUS_E_INVAL;
2467
2468 wmi_handle = wma->wmi_handle;
2469 if (wmi_validate_handle(wmi_handle))
2470 return QDF_STATUS_E_INVAL;
2471
2472 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) {
2473 wma_err("ext scan not enabled");
2474 return QDF_STATUS_E_FAILURE;
2475 }
2476
2477 return wmi_unified_extscan_stop_change_monitor_cmd(wmi_handle,
2478 params);
2479 }
2480
2481 QDF_STATUS
wma_extscan_get_cached_results(tp_wma_handle wma,struct extscan_cached_result_params * params)2482 wma_extscan_get_cached_results(tp_wma_handle wma,
2483 struct extscan_cached_result_params *params)
2484 {
2485 struct wmi_unified *wmi_handle;
2486
2487 if (wma_validate_handle(wma))
2488 return QDF_STATUS_E_INVAL;
2489
2490 wmi_handle = wma->wmi_handle;
2491 if (wmi_validate_handle(wmi_handle))
2492 return QDF_STATUS_E_INVAL;
2493
2494 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) {
2495 wma_err("extscan not enabled");
2496 return QDF_STATUS_E_FAILURE;
2497 }
2498
2499 return wmi_unified_extscan_get_cached_results_cmd(wmi_handle,
2500 params);
2501 }
2502
2503 QDF_STATUS
wma_extscan_get_capabilities(tp_wma_handle wma,struct extscan_capabilities_params * params)2504 wma_extscan_get_capabilities(tp_wma_handle wma,
2505 struct extscan_capabilities_params *params)
2506 {
2507 struct wmi_unified *wmi_handle;
2508
2509 if (wma_validate_handle(wma))
2510 return QDF_STATUS_E_INVAL;
2511
2512 wmi_handle = wma->wmi_handle;
2513 if (wmi_validate_handle(wmi_handle))
2514 return QDF_STATUS_E_INVAL;
2515
2516 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) {
2517 wma_err("extscan not enabled");
2518 return QDF_STATUS_E_FAILURE;
2519 }
2520
2521 return wmi_unified_extscan_get_capabilities_cmd(wmi_handle,
2522 params);
2523 }
2524
wma_set_epno_network_list(tp_wma_handle wma,struct wifi_enhanced_pno_params * req)2525 QDF_STATUS wma_set_epno_network_list(tp_wma_handle wma,
2526 struct wifi_enhanced_pno_params *req)
2527 {
2528 QDF_STATUS status;
2529 struct wmi_unified *wmi_handle;
2530
2531 wma_debug("Enter");
2532
2533 if (wma_validate_handle(wma))
2534 return QDF_STATUS_E_FAILURE;
2535
2536 wmi_handle = wma->wmi_handle;
2537 if (wmi_validate_handle(wmi_handle))
2538 return QDF_STATUS_E_FAILURE;
2539
2540 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) {
2541 wma_err("extscan not enabled");
2542 return QDF_STATUS_E_NOSUPPORT;
2543 }
2544
2545 status = wmi_unified_set_epno_network_list_cmd(wmi_handle, req);
2546 wma_debug("Exit, vdev %d, status %d", req->vdev_id, status);
2547
2548 return status;
2549 }
2550
2551 QDF_STATUS
wma_set_passpoint_network_list(tp_wma_handle wma,struct wifi_passpoint_req_param * params)2552 wma_set_passpoint_network_list(tp_wma_handle wma,
2553 struct wifi_passpoint_req_param *params)
2554 {
2555 QDF_STATUS status;
2556 struct wmi_unified *wmi_handle;
2557
2558 wma_debug("Enter");
2559
2560 if (wma_validate_handle(wma))
2561 return QDF_STATUS_E_FAILURE;
2562
2563 wmi_handle = wma->wmi_handle;
2564 if (wmi_validate_handle(wmi_handle))
2565 return QDF_STATUS_E_FAILURE;
2566
2567 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) {
2568 wma_err("extscan not enabled");
2569 return QDF_STATUS_E_NOSUPPORT;
2570 }
2571
2572 status = wmi_unified_set_passpoint_network_list_cmd(wmi_handle,
2573 params);
2574 wma_debug("Exit, vdev %d, status %d", params->vdev_id, status);
2575
2576 return status;
2577 }
2578
2579 QDF_STATUS
wma_reset_passpoint_network_list(tp_wma_handle wma,struct wifi_passpoint_req_param * params)2580 wma_reset_passpoint_network_list(tp_wma_handle wma,
2581 struct wifi_passpoint_req_param *params)
2582 {
2583 QDF_STATUS status;
2584 struct wmi_unified *wmi_handle;
2585
2586 wma_debug("Enter");
2587
2588 if (wma_validate_handle(wma))
2589 return QDF_STATUS_E_FAILURE;
2590
2591 wmi_handle = wma->wmi_handle;
2592 if (wmi_validate_handle(wmi_handle))
2593 return QDF_STATUS_E_FAILURE;
2594
2595 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) {
2596 wma_err("extscan not enabled");
2597 return QDF_STATUS_E_NOSUPPORT;
2598 }
2599
2600 status = wmi_unified_reset_passpoint_network_list_cmd(wmi_handle,
2601 params);
2602 wma_debug("Exit, vdev %d, status %d", params->vdev_id, status);
2603
2604 return status;
2605 }
2606
2607 #endif
2608
wma_scan_probe_setoui(tp_wma_handle wma,struct scan_mac_oui * set_oui)2609 QDF_STATUS wma_scan_probe_setoui(tp_wma_handle wma,
2610 struct scan_mac_oui *set_oui)
2611 {
2612 struct wmi_unified *wmi_handle;
2613
2614 if (wma_validate_handle(wma))
2615 return QDF_STATUS_E_INVAL;
2616
2617 wmi_handle = wma->wmi_handle;
2618 if (wmi_validate_handle(wmi_handle))
2619 return QDF_STATUS_E_INVAL;
2620
2621 if (!wma_is_vdev_valid(set_oui->vdev_id)) {
2622 wma_err("vdev_id: %d is not active", set_oui->vdev_id);
2623 return QDF_STATUS_E_INVAL;
2624 }
2625
2626 return wmi_unified_scan_probe_setoui_cmd(wmi_handle, set_oui);
2627 }
2628
2629 /**
2630 * wma_roam_better_ap_handler() - better ap event handler
2631 * @wma: wma handle
2632 * @vdev_id: vdev id
2633 *
2634 * Handler for WMI_ROAM_REASON_BETTER_AP event from roam firmware in Rome.
2635 * This event means roam algorithm in Rome has found a better matching
2636 * candidate AP. The indication is sent to SME.
2637 *
2638 * Return: none
2639 */
wma_roam_better_ap_handler(tp_wma_handle wma,uint32_t vdev_id)2640 void wma_roam_better_ap_handler(tp_wma_handle wma, uint32_t vdev_id)
2641 {
2642 struct scheduler_msg msg = {0};
2643 QDF_STATUS status;
2644 struct cm_host_roam_start_ind *ind;
2645
2646 ind = qdf_mem_malloc(sizeof(*ind));
2647 if (!ind)
2648 return;
2649
2650 ind->pdev = wma->pdev;
2651 ind->vdev_id = vdev_id;
2652 msg.bodyptr = ind;
2653 msg.callback = wlan_cm_host_roam_start;
2654 wma_debug("Posting ROam start ind to connection manager, vdev %d",
2655 vdev_id);
2656 status = scheduler_post_message(QDF_MODULE_ID_WMA,
2657 QDF_MODULE_ID_OS_IF,
2658 QDF_MODULE_ID_SCAN, &msg);
2659
2660 if (QDF_IS_STATUS_ERROR(status))
2661 qdf_mem_free(msg.bodyptr);
2662 }
2663
2664 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
2665 /**
2666 * wma_invalid_roam_reason_handler() - Handle Invalid roam notification
2667 * @wma: wma handle
2668 * @vdev_id: vdev id
2669 * @op_code: Operation to be done by the callback
2670 *
2671 * This function calls pe and csr callbacks with proper op_code
2672 *
2673 * Return: None
2674 */
wma_invalid_roam_reason_handler(tp_wma_handle wma_handle,uint32_t vdev_id,enum cm_roam_notif notif)2675 static void wma_invalid_roam_reason_handler(tp_wma_handle wma_handle,
2676 uint32_t vdev_id,
2677 enum cm_roam_notif notif)
2678 {
2679 struct roam_offload_synch_ind *roam_synch_data;
2680 enum sir_roam_op_code op_code;
2681
2682 if (notif == CM_ROAM_NOTIF_ROAM_START) {
2683 op_code = SIR_ROAMING_START;
2684 } else if (notif == CM_ROAM_NOTIF_ROAM_ABORT) {
2685 op_code = SIR_ROAMING_ABORT;
2686 lim_sae_auth_cleanup_retry(wma_handle->mac_context, vdev_id);
2687 } else {
2688 wma_debug("Invalid notif %d", notif);
2689 return;
2690 }
2691 roam_synch_data = qdf_mem_malloc(sizeof(*roam_synch_data));
2692 if (!roam_synch_data)
2693 return;
2694
2695 roam_synch_data->roamed_vdev_id = vdev_id;
2696 if (notif != CM_ROAM_NOTIF_ROAM_START)
2697 wma_handle->pe_roam_synch_cb(wma_handle->mac_context,
2698 roam_synch_data->roamed_vdev_id,
2699 roam_synch_data, 0, op_code);
2700
2701 if (notif == CM_ROAM_NOTIF_ROAM_START)
2702 cm_fw_roam_start_req(wma_handle->psoc, vdev_id);
2703 else
2704 cm_fw_roam_abort_req(wma_handle->psoc, vdev_id);
2705
2706 qdf_mem_free(roam_synch_data);
2707 }
2708
wma_handle_roam_sync_timeout(tp_wma_handle wma_handle,struct roam_sync_timeout_timer_info * info)2709 void wma_handle_roam_sync_timeout(tp_wma_handle wma_handle,
2710 struct roam_sync_timeout_timer_info *info)
2711 {
2712 wma_invalid_roam_reason_handler(wma_handle, info->vdev_id,
2713 CM_ROAM_NOTIF_ROAM_ABORT);
2714 }
2715
cm_invalid_roam_reason_handler(uint32_t vdev_id,enum cm_roam_notif notif,uint32_t reason)2716 void cm_invalid_roam_reason_handler(uint32_t vdev_id, enum cm_roam_notif notif,
2717 uint32_t reason)
2718 {
2719 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
2720
2721 if (!wma_handle) {
2722 QDF_ASSERT(0);
2723 return;
2724 }
2725 wma_invalid_roam_reason_handler(wma_handle, vdev_id, notif);
2726
2727 if (notif == CM_ROAM_NOTIF_SCAN_START ||
2728 notif == CM_ROAM_NOTIF_SCAN_END)
2729 cm_report_roam_rt_stats(wma_handle->psoc, vdev_id,
2730 ROAM_RT_STATS_TYPE_SCAN_STATE,
2731 NULL, notif, 0, reason);
2732 }
2733 #endif
2734
2735 static void
wma_handle_roam_reason_invoke_roam_fail(tp_wma_handle wma_handle,uint8_t vdev_id,uint32_t notif_params)2736 wma_handle_roam_reason_invoke_roam_fail(tp_wma_handle wma_handle,
2737 uint8_t vdev_id, uint32_t notif_params)
2738 {
2739 struct roam_offload_synch_ind *roam_synch_data;
2740
2741 roam_synch_data = qdf_mem_malloc(sizeof(*roam_synch_data));
2742 if (!roam_synch_data)
2743 return;
2744
2745 lim_sae_auth_cleanup_retry(wma_handle->mac_context, vdev_id);
2746 roam_synch_data->roamed_vdev_id = vdev_id;
2747 cm_fw_roam_invoke_fail(wma_handle->psoc, vdev_id);
2748 wlan_cm_update_roam_states(wma_handle->psoc, vdev_id,
2749 notif_params,
2750 ROAM_INVOKE_FAIL_REASON);
2751 qdf_mem_free(roam_synch_data);
2752 }
2753
wma_handle_roam_reason_btm(uint8_t vdev_id)2754 static void wma_handle_roam_reason_btm(uint8_t vdev_id)
2755 {
2756 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
2757
2758 if (!wma_handle) {
2759 QDF_ASSERT(0);
2760 return;
2761 }
2762 /*
2763 * This event is received from firmware if firmware is unable to
2764 * find candidate AP after roam scan and BTM request from AP
2765 * has disassoc imminent bit set.
2766 */
2767 wma_debug("Kickout due to btm request");
2768 wma_sta_kickout_event(HOST_STA_KICKOUT_REASON_BTM, vdev_id, NULL);
2769 wma_handle_disconnect_reason(wma_handle, vdev_id,
2770 HAL_DEL_STA_REASON_CODE_BTM_DISASSOC_IMMINENT);
2771 }
2772
wma_handle_roam_reason_bmiss(uint8_t vdev_id,uint32_t rssi)2773 static void wma_handle_roam_reason_bmiss(uint8_t vdev_id, uint32_t rssi)
2774 {
2775 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
2776
2777 if (!wma_handle) {
2778 QDF_ASSERT(0);
2779 return;
2780 }
2781 /*
2782 * WMI_ROAM_REASON_BMISS can get called in soft IRQ context, so
2783 * avoid using CSR/PE structure directly
2784 */
2785 wma_debug("Beacon Miss for vdevid %x", vdev_id);
2786 mlme_set_hb_ap_rssi(wma_handle->interfaces[vdev_id].vdev, rssi);
2787 wma_beacon_miss_handler(wma_handle, vdev_id, rssi);
2788 wma_sta_kickout_event(HOST_STA_KICKOUT_REASON_BMISS, vdev_id, NULL);
2789 }
2790
wma_handle_roam_reason_better_ap(uint8_t vdev_id,uint32_t rssi)2791 static void wma_handle_roam_reason_better_ap(uint8_t vdev_id, uint32_t rssi)
2792 {
2793 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
2794
2795 if (!wma_handle) {
2796 QDF_ASSERT(0);
2797 return;
2798 }
2799 /*
2800 * WMI_ROAM_REASON_BETTER_AP can get called in soft IRQ context,
2801 * so avoid using CSR/PE structure directly.
2802 */
2803 wma_debug("Better AP found for vdevid %x, rssi %d", vdev_id, rssi);
2804 mlme_set_roam_reason_better_ap(wma_handle->interfaces[vdev_id].vdev,
2805 false);
2806 wma_roam_better_ap_handler(wma_handle, vdev_id);
2807 }
2808
wma_handle_roam_reason_suitable_ap(uint8_t vdev_id,uint32_t rssi)2809 static void wma_handle_roam_reason_suitable_ap(uint8_t vdev_id, uint32_t rssi)
2810 {
2811 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
2812
2813 if (!wma_handle) {
2814 QDF_ASSERT(0);
2815 return;
2816 }
2817 /*
2818 * WMI_ROAM_REASON_SUITABLE_AP can get called in soft IRQ
2819 * context, so avoid using CSR/PE structure directly.
2820 */
2821 mlme_set_roam_reason_better_ap(wma_handle->interfaces[vdev_id].vdev,
2822 true);
2823 mlme_set_hb_ap_rssi(wma_handle->interfaces[vdev_id].vdev, rssi);
2824 wma_debug("Bmiss scan AP found for vdevid %x, rssi %d", vdev_id, rssi);
2825 wma_roam_better_ap_handler(wma_handle, vdev_id);
2826 }
2827
2828 static void
wma_update_pdev_hw_mode_trans_ind(tp_wma_handle wma,struct cm_hw_mode_trans_ind * trans_ind)2829 wma_update_pdev_hw_mode_trans_ind(tp_wma_handle wma,
2830 struct cm_hw_mode_trans_ind *trans_ind)
2831 {
2832 uint32_t i;
2833
2834 /* Store the vdev-mac map in WMA and send to policy manager */
2835 for (i = 0; i < trans_ind->num_vdev_mac_entries; i++)
2836 wma_update_intf_hw_mode_params(
2837 trans_ind->vdev_mac_map[i].vdev_id,
2838 trans_ind->vdev_mac_map[i].mac_id,
2839 trans_ind->new_hw_mode_index);
2840
2841 wma->old_hw_mode_index = trans_ind->old_hw_mode_index;
2842 wma->new_hw_mode_index = trans_ind->new_hw_mode_index;
2843 policy_mgr_update_new_hw_mode_index(wma->psoc,
2844 trans_ind->new_hw_mode_index);
2845 policy_mgr_update_old_hw_mode_index(wma->psoc,
2846 trans_ind->old_hw_mode_index);
2847
2848 wma_debug("Updated: old_hw_mode_index:%d new_hw_mode_index:%d",
2849 wma->old_hw_mode_index, wma->new_hw_mode_index);
2850 }
2851
2852 static void
wma_handle_hw_mode_trans_ind(tp_wma_handle wma_handle,struct cm_hw_mode_trans_ind * hw_mode_trans_ind)2853 wma_handle_hw_mode_trans_ind(tp_wma_handle wma_handle,
2854 struct cm_hw_mode_trans_ind *hw_mode_trans_ind)
2855 {
2856 struct scheduler_msg sme_msg = {0};
2857 QDF_STATUS status;
2858
2859 if (hw_mode_trans_ind) {
2860 wma_update_pdev_hw_mode_trans_ind(wma_handle,
2861 hw_mode_trans_ind);
2862 wma_debug("Update HW mode");
2863 sme_msg.type = eWNI_SME_HW_MODE_TRANS_IND;
2864 sme_msg.bodyptr = hw_mode_trans_ind;
2865
2866 status = scheduler_post_message(QDF_MODULE_ID_WMA,
2867 QDF_MODULE_ID_SME,
2868 QDF_MODULE_ID_SME, &sme_msg);
2869 if (QDF_IS_STATUS_ERROR(status))
2870 qdf_mem_free(hw_mode_trans_ind);
2871 } else {
2872 wma_debug("hw_mode transition fixed param is NULL");
2873 }
2874 }
2875
cm_rso_cmd_status_event_handler(uint8_t vdev_id,enum cm_roam_notif notif)2876 int cm_rso_cmd_status_event_handler(uint8_t vdev_id, enum cm_roam_notif notif)
2877 {
2878 return wma_rso_cmd_status_event_handler(vdev_id, notif);
2879 }
2880
2881 void
cm_handle_roam_reason_invoke_roam_fail(uint8_t vdev_id,uint32_t notif_params,struct cm_hw_mode_trans_ind * trans_ind)2882 cm_handle_roam_reason_invoke_roam_fail(uint8_t vdev_id, uint32_t notif_params,
2883 struct cm_hw_mode_trans_ind *trans_ind)
2884 {
2885 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
2886
2887 if (!wma_handle) {
2888 QDF_ASSERT(0);
2889 return;
2890 }
2891 wma_handle_hw_mode_trans_ind(wma_handle, trans_ind);
2892 wma_handle_roam_reason_invoke_roam_fail(wma_handle, vdev_id,
2893 notif_params);
2894 cm_report_roam_rt_stats(wma_handle->psoc, vdev_id,
2895 ROAM_RT_STATS_TYPE_INVOKE_FAIL_REASON,
2896 NULL, notif_params, 0, 0);
2897 }
2898
2899 void
cm_handle_roam_sync_update_hw_mode(struct cm_hw_mode_trans_ind * trans_ind)2900 cm_handle_roam_sync_update_hw_mode(struct cm_hw_mode_trans_ind *trans_ind)
2901 {
2902 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
2903 struct cm_hw_mode_trans_ind *trans_ind_data;
2904
2905 if (!wma_handle) {
2906 wma_err("invalid wma handle");
2907 return;
2908 }
2909 trans_ind_data = qdf_mem_malloc(sizeof(*trans_ind_data));
2910 if (!trans_ind_data)
2911 return;
2912 qdf_mem_copy(trans_ind_data, trans_ind, sizeof(*trans_ind_data));
2913 wma_handle_hw_mode_trans_ind(wma_handle, trans_ind_data);
2914 }
2915
2916 static void
wma_handle_roam_reason_deauth(uint8_t vdev_id,uint32_t notif_params,uint32_t notif_params1,uint8_t * deauth_disassoc_frame)2917 wma_handle_roam_reason_deauth(uint8_t vdev_id, uint32_t notif_params,
2918 uint32_t notif_params1,
2919 uint8_t *deauth_disassoc_frame)
2920 {
2921 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
2922 struct roam_offload_synch_ind *roam_synch_data;
2923
2924 if (!wma_handle) {
2925 QDF_ASSERT(0);
2926 return;
2927 }
2928 wma_debug("Received disconnect roam event reason:%d", notif_params);
2929 wma_handle->pe_disconnect_cb(wma_handle->mac_context,
2930 vdev_id,
2931 deauth_disassoc_frame, notif_params1,
2932 notif_params);
2933 roam_synch_data = qdf_mem_malloc(sizeof(*roam_synch_data));
2934 if (!roam_synch_data)
2935 return;
2936
2937 roam_synch_data->roamed_vdev_id = vdev_id;
2938 qdf_mem_free(roam_synch_data);
2939 }
2940
cm_handle_roam_reason_deauth(uint8_t vdev_id,uint32_t notif_params,uint8_t * deauth_disassoc_frame,uint32_t frame_len)2941 void cm_handle_roam_reason_deauth(uint8_t vdev_id, uint32_t notif_params,
2942 uint8_t *deauth_disassoc_frame,
2943 uint32_t frame_len)
2944 {
2945 wma_handle_roam_reason_deauth(vdev_id, notif_params, frame_len,
2946 deauth_disassoc_frame);
2947 }
2948
cm_handle_roam_reason_btm(uint8_t vdev_id)2949 void cm_handle_roam_reason_btm(uint8_t vdev_id)
2950 {
2951 wma_handle_roam_reason_btm(vdev_id);
2952 }
2953
cm_handle_roam_reason_bmiss(uint8_t vdev_id,uint32_t rssi)2954 void cm_handle_roam_reason_bmiss(uint8_t vdev_id, uint32_t rssi)
2955 {
2956 wma_handle_roam_reason_bmiss(vdev_id, rssi);
2957 }
2958
cm_handle_roam_reason_better_ap(uint8_t vdev_id,uint32_t rssi)2959 void cm_handle_roam_reason_better_ap(uint8_t vdev_id, uint32_t rssi)
2960 {
2961 wma_handle_roam_reason_better_ap(vdev_id, rssi);
2962 }
2963
cm_handle_roam_reason_suitable_ap(uint8_t vdev_id,uint32_t rssi)2964 void cm_handle_roam_reason_suitable_ap(uint8_t vdev_id, uint32_t rssi)
2965 {
2966 wma_handle_roam_reason_suitable_ap(vdev_id, rssi);
2967 }
2968
2969 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
2970 static void
wma_handle_roam_reason_ho_failed(uint8_t vdev_id,struct qdf_mac_addr bssid,struct cm_hw_mode_trans_ind * hw_mode_trans_ind)2971 wma_handle_roam_reason_ho_failed(uint8_t vdev_id, struct qdf_mac_addr bssid,
2972 struct cm_hw_mode_trans_ind *hw_mode_trans_ind)
2973 {
2974 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
2975
2976 if (!wma_handle) {
2977 QDF_ASSERT(0);
2978 return;
2979 }
2980 /*
2981 * WMI_ROAM_REASON_HO_FAILED can get called in soft IRQ context,
2982 * so avoid using CSR/PE structure directly.
2983 */
2984 wma_err("LFR3:Hand-Off Failed for vdevid %x", vdev_id);
2985 wma_debug("mac addr to avoid " QDF_MAC_ADDR_FMT,
2986 QDF_MAC_ADDR_REF(bssid.bytes));
2987 wma_handle_hw_mode_trans_ind(wma_handle, hw_mode_trans_ind);
2988 cm_fw_ho_fail_req(wma_handle->psoc, vdev_id, bssid);
2989 lim_sae_auth_cleanup_retry(wma_handle->mac_context, vdev_id);
2990 }
2991
2992 void
cm_handle_roam_reason_ho_failed(uint8_t vdev_id,struct qdf_mac_addr bssid,struct cm_hw_mode_trans_ind * hw_mode_trans_ind)2993 cm_handle_roam_reason_ho_failed(uint8_t vdev_id, struct qdf_mac_addr bssid,
2994 struct cm_hw_mode_trans_ind *hw_mode_trans_ind)
2995 {
2996 wma_handle_roam_reason_ho_failed(vdev_id, bssid, hw_mode_trans_ind);
2997 }
2998 #endif
2999
3000 #ifdef FEATURE_LFR_SUBNET_DETECTION
wma_set_gateway_params(tp_wma_handle wma,struct gateway_update_req_param * req)3001 QDF_STATUS wma_set_gateway_params(tp_wma_handle wma,
3002 struct gateway_update_req_param *req)
3003 {
3004 if (wma_validate_handle(wma))
3005 return QDF_STATUS_E_INVAL;
3006
3007 return wmi_unified_set_gateway_params_cmd(wma->wmi_handle, req);
3008 }
3009 #endif /* FEATURE_LFR_SUBNET_DETECTION */
3010
3011 /**
3012 * wma_ht40_stop_obss_scan() - ht40 obss stop scan
3013 * @wma: WMA handle
3014 * @vdev_id: vdev identifier
3015 *
3016 * Return: Return QDF_STATUS, otherwise appropriate failure code
3017 */
wma_ht40_stop_obss_scan(tp_wma_handle wma,int32_t vdev_id)3018 QDF_STATUS wma_ht40_stop_obss_scan(tp_wma_handle wma, int32_t vdev_id)
3019 {
3020 QDF_STATUS status;
3021 wmi_buf_t buf;
3022 wmi_obss_scan_disable_cmd_fixed_param *cmd;
3023 int len = sizeof(*cmd);
3024
3025 buf = wmi_buf_alloc(wma->wmi_handle, len);
3026 if (!buf)
3027 return QDF_STATUS_E_NOMEM;
3028
3029 wma_debug("cmd %x vdev_id %d", WMI_OBSS_SCAN_DISABLE_CMDID, vdev_id);
3030
3031 cmd = (wmi_obss_scan_disable_cmd_fixed_param *) wmi_buf_data(buf);
3032 WMITLV_SET_HDR(&cmd->tlv_header,
3033 WMITLV_TAG_STRUC_wmi_obss_scan_disable_cmd_fixed_param,
3034 WMITLV_GET_STRUCT_TLVLEN(
3035 wmi_obss_scan_disable_cmd_fixed_param));
3036
3037 cmd->vdev_id = vdev_id;
3038 status = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3039 WMI_OBSS_SCAN_DISABLE_CMDID);
3040 if (QDF_IS_STATUS_ERROR(status))
3041 wmi_buf_free(buf);
3042
3043 return status;
3044 }
3045
3046 /**
3047 * wma_send_ht40_obss_scanind() - ht40 obss start scan indication
3048 * @wma: WMA handle
3049 * @req: start scan request
3050 *
3051 * Return: Return QDF_STATUS, otherwise appropriate failure code
3052 */
wma_send_ht40_obss_scanind(tp_wma_handle wma,struct obss_ht40_scanind * req)3053 QDF_STATUS wma_send_ht40_obss_scanind(tp_wma_handle wma,
3054 struct obss_ht40_scanind *req)
3055 {
3056 QDF_STATUS status;
3057 wmi_buf_t buf;
3058 wmi_obss_scan_enable_cmd_fixed_param *cmd;
3059 int len = 0;
3060 uint8_t *buf_ptr, i;
3061 uint8_t *channel_list;
3062 uint32_t *chan_freq_list;
3063
3064 len += sizeof(wmi_obss_scan_enable_cmd_fixed_param);
3065
3066 len += WMI_TLV_HDR_SIZE;
3067 len += qdf_roundup(sizeof(uint8_t) * req->channel_count,
3068 sizeof(uint32_t));
3069
3070 len += WMI_TLV_HDR_SIZE;
3071 len += qdf_roundup(sizeof(uint8_t) * 1, sizeof(uint32_t));
3072
3073 /* length calculation for chan_freqs */
3074 len += WMI_TLV_HDR_SIZE;
3075 len += sizeof(uint32_t) * req->channel_count;
3076
3077 wma_debug("cmdlen %d vdev_id %d channel count %d iefield_len %d",
3078 len, req->bss_id, req->channel_count, req->iefield_len);
3079
3080 wma_debug("scantype %d active_time %d passive %d Obss interval %d",
3081 req->scan_type, req->obss_active_dwelltime,
3082 req->obss_passive_dwelltime,
3083 req->obss_width_trigger_interval);
3084
3085 buf = wmi_buf_alloc(wma->wmi_handle, len);
3086 if (!buf)
3087 return QDF_STATUS_E_NOMEM;
3088
3089 cmd = (wmi_obss_scan_enable_cmd_fixed_param *) wmi_buf_data(buf);
3090 WMITLV_SET_HDR(&cmd->tlv_header,
3091 WMITLV_TAG_STRUC_wmi_obss_scan_enable_cmd_fixed_param,
3092 WMITLV_GET_STRUCT_TLVLEN(wmi_obss_scan_enable_cmd_fixed_param));
3093
3094 buf_ptr = (uint8_t *) cmd;
3095
3096 cmd->vdev_id = req->bss_id;
3097 cmd->scan_type = req->scan_type;
3098 cmd->obss_scan_active_dwell =
3099 req->obss_active_dwelltime;
3100 cmd->obss_scan_passive_dwell =
3101 req->obss_passive_dwelltime;
3102 cmd->bss_channel_width_trigger_scan_interval =
3103 req->obss_width_trigger_interval;
3104 cmd->bss_width_channel_transition_delay_factor =
3105 req->bsswidth_ch_trans_delay;
3106 cmd->obss_scan_active_total_per_channel =
3107 req->obss_active_total_per_channel;
3108 cmd->obss_scan_passive_total_per_channel =
3109 req->obss_passive_total_per_channel;
3110 cmd->obss_scan_activity_threshold =
3111 req->obss_activity_threshold;
3112
3113 cmd->channel_len = req->channel_count;
3114 cmd->forty_mhz_intolerant = req->fortymhz_intolerent;
3115 cmd->current_operating_class = req->current_operatingclass;
3116 cmd->ie_len = req->iefield_len;
3117
3118 buf_ptr += sizeof(wmi_obss_scan_enable_cmd_fixed_param);
3119 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
3120 qdf_roundup(req->channel_count, sizeof(uint32_t)));
3121
3122 buf_ptr += WMI_TLV_HDR_SIZE;
3123 channel_list = (uint8_t *) buf_ptr;
3124
3125 for (i = 0; i < req->channel_count; i++) {
3126 channel_list[i] =
3127 wlan_reg_freq_to_chan(wma->pdev, req->chan_freq_list[i]);
3128 wma_nofl_debug("Ch[%d]: %d ", i, channel_list[i]);
3129 }
3130
3131 buf_ptr += qdf_roundup(sizeof(uint8_t) * req->channel_count,
3132 sizeof(uint32_t));
3133 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
3134 qdf_roundup(1, sizeof(uint32_t)));
3135 buf_ptr += WMI_TLV_HDR_SIZE;
3136
3137 buf_ptr += qdf_roundup(sizeof(uint8_t) * 1, sizeof(uint32_t));
3138
3139 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
3140 sizeof(uint32_t) * req->channel_count);
3141 buf_ptr += WMI_TLV_HDR_SIZE;
3142
3143 chan_freq_list = (uint32_t *)buf_ptr;
3144 for (i = 0; i < req->channel_count; i++) {
3145 chan_freq_list[i] = req->chan_freq_list[i];
3146 wma_nofl_debug("freq[%u]: %u ", i, chan_freq_list[i]);
3147 }
3148
3149 buf_ptr += sizeof(uint32_t) * req->channel_count;
3150
3151 status = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3152 WMI_OBSS_SCAN_ENABLE_CMDID);
3153 if (QDF_IS_STATUS_ERROR(status))
3154 wmi_buf_free(buf);
3155
3156 return status;
3157 }
3158
3159 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
cm_roam_update_vdev(struct wlan_objmgr_vdev * vdev,struct roam_offload_synch_ind * sync_ind)3160 QDF_STATUS cm_roam_update_vdev(struct wlan_objmgr_vdev *vdev,
3161 struct roam_offload_synch_ind *sync_ind)
3162 {
3163 QDF_STATUS status;
3164 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
3165 struct qdf_mac_addr *self_mac_addr;
3166 uint8_t vdev_id;
3167
3168 if (!wma)
3169 return QDF_STATUS_E_INVAL;
3170
3171 vdev_id = wlan_vdev_get_id(vdev);
3172
3173 status = wma_roam_update_vdev(wma, sync_ind, vdev_id);
3174 if (QDF_IS_STATUS_ERROR(status)) {
3175 wma_debug("VDEV update failed for roam on %d", vdev_id);
3176 return status;
3177 }
3178
3179 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
3180 self_mac_addr =
3181 (struct qdf_mac_addr *)wlan_vdev_mlme_get_macaddr(vdev);
3182 goto update_deflink;
3183 }
3184
3185 if (wlan_vdev_mlme_is_mlo_vdev(vdev) &&
3186 wlan_vdev_mlme_is_mlo_link_vdev(vdev))
3187 return QDF_STATUS_SUCCESS;
3188
3189 self_mac_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
3190
3191 update_deflink:
3192 /* Set the assoc vdev as DP deflink after roaming */
3193 wlan_dp_update_def_link(wma->psoc, self_mac_addr, vdev);
3194
3195 return QDF_STATUS_SUCCESS;
3196 }
3197
3198 QDF_STATUS
cm_roam_pe_sync_callback(struct roam_offload_synch_ind * sync_ind,uint8_t vdev_id,uint16_t ie_len)3199 cm_roam_pe_sync_callback(struct roam_offload_synch_ind *sync_ind,
3200 uint8_t vdev_id, uint16_t ie_len)
3201 {
3202 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
3203 struct pe_session *pe_session;
3204 bool new_link_session = false;
3205 QDF_STATUS status;
3206
3207 if (!wma)
3208 return QDF_STATUS_E_INVAL;
3209
3210 pe_session = pe_find_session_by_vdev_id(wma->mac_context, vdev_id);
3211 if (!pe_session) {
3212 new_link_session = true;
3213 /* Legacy to MLO roaming: create new pe session */
3214 status = lim_create_and_fill_link_session(wma->mac_context,
3215 vdev_id,
3216 sync_ind, ie_len);
3217
3218 if (QDF_IS_STATUS_ERROR(status)) {
3219 wma_err("MLO ROAM: pe session creation failed vdev id %d",
3220 vdev_id);
3221 return status;
3222 }
3223 }
3224 status = wma->pe_roam_synch_cb(wma->mac_context,
3225 vdev_id, sync_ind, ie_len,
3226 SIR_ROAM_SYNCH_PROPAGATION);
3227
3228 /* delete newly added pe session in case of failure */
3229 if (new_link_session && QDF_IS_STATUS_ERROR(status)) {
3230 pe_session = pe_find_session_by_vdev_id(wma->mac_context,
3231 vdev_id);
3232 if (pe_session)
3233 pe_delete_session(wma->mac_context, pe_session);
3234 }
3235 return status;
3236 }
3237
cm_update_phymode_on_roam(uint8_t vdev_id,struct roam_offload_synch_ind * sync_ind)3238 void cm_update_phymode_on_roam(uint8_t vdev_id,
3239 struct roam_offload_synch_ind *sync_ind)
3240 {
3241 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
3242 struct qdf_mac_addr link_bssid;
3243 wmi_channel link_chan;
3244
3245 if (!wma)
3246 return;
3247
3248 if (is_multi_link_roam(sync_ind)) {
3249 mlo_roam_get_bssid_chan_for_link(vdev_id, sync_ind,
3250 &link_bssid,
3251 &link_chan);
3252 wma_update_phymode_on_roam(wma, &link_bssid,
3253 &link_chan,
3254 &wma->interfaces[vdev_id]);
3255 } else {
3256 wma_update_phymode_on_roam(wma, &sync_ind->bssid,
3257 &sync_ind->chan,
3258 &wma->interfaces[vdev_id]);
3259 }
3260 }
3261
3262 enum wlan_phymode
wlan_cm_fw_to_host_phymode(WMI_HOST_WLAN_PHY_MODE phymode)3263 wlan_cm_fw_to_host_phymode(WMI_HOST_WLAN_PHY_MODE phymode)
3264 {
3265 return wma_fw_to_host_phymode(phymode);
3266 }
3267 #endif
3268
3269 QDF_STATUS
wlan_update_peer_phy_mode(struct wlan_channel * des_chan,struct wlan_objmgr_vdev * vdev)3270 wlan_update_peer_phy_mode(struct wlan_channel *des_chan,
3271 struct wlan_objmgr_vdev *vdev)
3272 {
3273 return wma_update_bss_peer_phy_mode(des_chan, vdev);
3274 }
3275