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