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