xref: /wlan-driver/qcacld-3.0/core/sme/src/rrm/sme_rrm.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022-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: sme_rrm.c
22*5113495bSYour Name  *
23*5113495bSYour Name  * Implementation for SME RRM APIs
24*5113495bSYour Name  */
25*5113495bSYour Name 
26*5113495bSYour Name #include "ani_global.h"
27*5113495bSYour Name #include "sme_inside.h"
28*5113495bSYour Name #include "sme_api.h"
29*5113495bSYour Name 
30*5113495bSYour Name #ifdef FEATURE_WLAN_DIAG_SUPPORT
31*5113495bSYour Name #include "host_diag_core_event.h"
32*5113495bSYour Name #include "host_diag_core_log.h"
33*5113495bSYour Name #endif /* FEATURE_WLAN_DIAG_SUPPORT */
34*5113495bSYour Name 
35*5113495bSYour Name #include "csr_inside_api.h"
36*5113495bSYour Name 
37*5113495bSYour Name #include "rrm_global.h"
38*5113495bSYour Name #include <wlan_scan_api.h>
39*5113495bSYour Name #include <wlan_scan_utils_api.h>
40*5113495bSYour Name #include <wlan_reg_services_api.h>
41*5113495bSYour Name #include <wlan_utility.h>
42*5113495bSYour Name #include <../../core/src/wlan_cm_vdev_api.h>
43*5113495bSYour Name #include "rrm_api.h"
44*5113495bSYour Name #include "wlan_cp_stats_mc_ucfg_api.h"
45*5113495bSYour Name 
46*5113495bSYour Name /* Roam score for a neighbor AP will be calculated based on the below
47*5113495bSYour Name  * definitions. The calculated roam score will be used to select the
48*5113495bSYour Name  * roamable candidate from neighbor AP list
49*5113495bSYour Name  */
50*5113495bSYour Name #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_REACHABILITY             0
51*5113495bSYour Name /* When we support 11r over the DS, this should have a non-zero value */
52*5113495bSYour Name #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_SECURITY                 10
53*5113495bSYour Name #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_KEY_SCOPE                20
54*5113495bSYour Name #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_SPECTRUM_MGMT 0
55*5113495bSYour Name /* Not used */
56*5113495bSYour Name #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_QOS           5
57*5113495bSYour Name #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_APSD          3
58*5113495bSYour Name #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_RRM           8
59*5113495bSYour Name #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_DELAYED_BA    0
60*5113495bSYour Name /* We dont support delayed BA */
61*5113495bSYour Name #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_IMMEDIATE_BA  3
62*5113495bSYour Name #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_MOBILITY_DOMAIN          30
63*5113495bSYour Name 
64*5113495bSYour Name #ifdef FEATURE_WLAN_ESE
65*5113495bSYour Name #define RRM_ROAM_SCORE_NEIGHBOR_IAPP_LIST                       30
66*5113495bSYour Name #endif
67*5113495bSYour Name /* RRM SCAN DWELL TIME */
68*5113495bSYour Name #define RRM_SCAN_MIN_DWELL_TIME 20
69*5113495bSYour Name 
70*5113495bSYour Name uint64_t rrm_scan_timer;
71*5113495bSYour Name 
72*5113495bSYour Name /**
73*5113495bSYour Name  * rrm_ll_purge_neighbor_cache() -Purges all the entries in the neighbor cache
74*5113495bSYour Name  *
75*5113495bSYour Name  * @mac: Pointer to the Hal Handle.
76*5113495bSYour Name  * @pList: Pointer the List that should be purged.
77*5113495bSYour Name  *
78*5113495bSYour Name  * This function purges all the entries in the neighbor cache and frees up all
79*5113495bSYour Name  * the internal nodes
80*5113495bSYour Name  *
81*5113495bSYour Name  * Return: void
82*5113495bSYour Name  */
rrm_ll_purge_neighbor_cache(struct mac_context * mac,tDblLinkList * pList)83*5113495bSYour Name static void rrm_ll_purge_neighbor_cache(struct mac_context *mac,
84*5113495bSYour Name 	tDblLinkList *pList)
85*5113495bSYour Name {
86*5113495bSYour Name 	tListElem *pEntry;
87*5113495bSYour Name 	tRrmNeighborReportDesc *pNeighborReportDesc;
88*5113495bSYour Name 
89*5113495bSYour Name 	csr_ll_lock(pList);
90*5113495bSYour Name 	while ((pEntry = csr_ll_remove_head(pList, LL_ACCESS_NOLOCK)) != NULL) {
91*5113495bSYour Name 		pNeighborReportDesc =
92*5113495bSYour Name 			GET_BASE_ADDR(pEntry, tRrmNeighborReportDesc, List);
93*5113495bSYour Name 		qdf_mem_free(pNeighborReportDesc->pNeighborBssDescription);
94*5113495bSYour Name 		qdf_mem_free(pNeighborReportDesc);
95*5113495bSYour Name 	}
96*5113495bSYour Name 	csr_ll_unlock(pList);
97*5113495bSYour Name }
98*5113495bSYour Name 
99*5113495bSYour Name /**
100*5113495bSYour Name  * rrm_indicate_neighbor_report_result() -calls the callback registered for
101*5113495bSYour Name  *                                                      neighbor report
102*5113495bSYour Name  * @mac: Pointer to the Hal Handle.
103*5113495bSYour Name  * @qdf_status - QDF_STATUS_SUCCESS/QDF_STATUS_FAILURE based on whether a valid
104*5113495bSYour Name  *                       report is received or neighbor timer expired
105*5113495bSYour Name  *
106*5113495bSYour Name  * This function calls the callback register by the caller while requesting for
107*5113495bSYour Name  * neighbor report. This function gets invoked if a neighbor report is received
108*5113495bSYour Name  * from an AP or neighbor response wait timer expires.
109*5113495bSYour Name  *
110*5113495bSYour Name  * Return: void
111*5113495bSYour Name  */
rrm_indicate_neighbor_report_result(struct mac_context * mac,QDF_STATUS qdf_status)112*5113495bSYour Name static void rrm_indicate_neighbor_report_result(struct mac_context *mac,
113*5113495bSYour Name 						QDF_STATUS qdf_status)
114*5113495bSYour Name {
115*5113495bSYour Name 	NeighborReportRspCallback callback;
116*5113495bSYour Name 	void *callbackContext;
117*5113495bSYour Name 
118*5113495bSYour Name 	/* Reset the neighbor response pending status */
119*5113495bSYour Name 	mac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].
120*5113495bSYour Name 	neighborReqControlInfo.isNeighborRspPending = false;
121*5113495bSYour Name 
122*5113495bSYour Name 	/* Stop the timer if it is already running.
123*5113495bSYour Name 	 *  The timer should be running only in the SUCCESS case.
124*5113495bSYour Name 	 */
125*5113495bSYour Name 	if (QDF_TIMER_STATE_RUNNING ==
126*5113495bSYour Name 	    qdf_mc_timer_get_current_state(&mac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].
127*5113495bSYour Name 					   neighborReqControlInfo.
128*5113495bSYour Name 					   neighborRspWaitTimer)) {
129*5113495bSYour Name 		sme_debug("No entry in neighbor report cache");
130*5113495bSYour Name 		qdf_mc_timer_stop(&mac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].
131*5113495bSYour Name 				  neighborReqControlInfo.neighborRspWaitTimer);
132*5113495bSYour Name 	}
133*5113495bSYour Name 	callback =
134*5113495bSYour Name 		mac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].neighborReqControlInfo.
135*5113495bSYour Name 		neighborRspCallbackInfo.neighborRspCallback;
136*5113495bSYour Name 	callbackContext =
137*5113495bSYour Name 		mac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].neighborReqControlInfo.
138*5113495bSYour Name 		neighborRspCallbackInfo.neighborRspCallbackContext;
139*5113495bSYour Name 
140*5113495bSYour Name 	/* Reset the callback and the callback context before calling the
141*5113495bSYour Name 	 * callback. It is very likely that there may be a registration in
142*5113495bSYour Name 	 * callback itself.
143*5113495bSYour Name 	 */
144*5113495bSYour Name 	mac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].neighborReqControlInfo.
145*5113495bSYour Name 		neighborRspCallbackInfo.neighborRspCallback = NULL;
146*5113495bSYour Name 	mac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].neighborReqControlInfo.
147*5113495bSYour Name 		neighborRspCallbackInfo.neighborRspCallbackContext = NULL;
148*5113495bSYour Name 
149*5113495bSYour Name 	/* Call the callback with the status received from caller */
150*5113495bSYour Name 	if (callback)
151*5113495bSYour Name 		callback(callbackContext, qdf_status);
152*5113495bSYour Name }
153*5113495bSYour Name 
154*5113495bSYour Name /**
155*5113495bSYour Name  * sme_RrmBeaconReportXmitInd () - Send beacon report
156*5113495bSYour Name  * @mac_ctx  Pointer to mac context
157*5113495bSYour Name  * @measurement_index: Measurement index
158*5113495bSYour Name  * @result_arr scan results
159*5113495bSYour Name  * @msrmnt_status flag to indicate that the measurement is done.
160*5113495bSYour Name  * @bss_count  bss count
161*5113495bSYour Name  *
162*5113495bSYour Name  * Create and send the beacon report Xmit ind message to PE.
163*5113495bSYour Name  *
164*5113495bSYour Name  * Return: status
165*5113495bSYour Name  */
166*5113495bSYour Name 
167*5113495bSYour Name static QDF_STATUS
sme_rrm_send_beacon_report_xmit_ind(struct mac_context * mac_ctx,uint8_t measurement_index,tCsrScanResultInfo ** result_arr,uint8_t msrmnt_status,uint8_t bss_count)168*5113495bSYour Name sme_rrm_send_beacon_report_xmit_ind(struct mac_context *mac_ctx,
169*5113495bSYour Name 	uint8_t measurement_index, tCsrScanResultInfo **result_arr,
170*5113495bSYour Name 	uint8_t msrmnt_status, uint8_t bss_count)
171*5113495bSYour Name {
172*5113495bSYour Name 	struct bss_description *bss_desc = NULL;
173*5113495bSYour Name 	tpSirBeaconReportXmitInd beacon_rep;
174*5113495bSYour Name 	uint16_t length;
175*5113495bSYour Name 	uint32_t size;
176*5113495bSYour Name 	uint8_t  i = 0, j = 0, counter = 0;
177*5113495bSYour Name 	tCsrScanResultInfo *cur_result = NULL;
178*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
179*5113495bSYour Name 	tpRrmSMEContext rrm_ctx =
180*5113495bSYour Name 			&mac_ctx->rrm.rrmSmeContext[measurement_index];
181*5113495bSYour Name 	struct bss_description *tmp_bss_desc[SIR_BCN_REPORT_MAX_BSS_DESC] = {0};
182*5113495bSYour Name 
183*5113495bSYour Name 	if (!result_arr && !msrmnt_status) {
184*5113495bSYour Name 		sme_err("Beacon report xmit Ind to PE Failed");
185*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
186*5113495bSYour Name 	}
187*5113495bSYour Name 
188*5113495bSYour Name 	if (result_arr)
189*5113495bSYour Name 		cur_result = result_arr[j];
190*5113495bSYour Name 
191*5113495bSYour Name 	do {
192*5113495bSYour Name 		length = sizeof(tSirBeaconReportXmitInd);
193*5113495bSYour Name 		beacon_rep = qdf_mem_malloc(length);
194*5113495bSYour Name 		if (!beacon_rep)
195*5113495bSYour Name 			return QDF_STATUS_E_NOMEM;
196*5113495bSYour Name 
197*5113495bSYour Name 		beacon_rep->messageType = eWNI_SME_BEACON_REPORT_RESP_XMIT_IND;
198*5113495bSYour Name 		beacon_rep->length = length;
199*5113495bSYour Name 		beacon_rep->measurement_idx = measurement_index;
200*5113495bSYour Name 		beacon_rep->uDialogToken = rrm_ctx->token;
201*5113495bSYour Name 		beacon_rep->duration = rrm_ctx->duration[0];
202*5113495bSYour Name 		beacon_rep->regClass = rrm_ctx->regClass;
203*5113495bSYour Name 		qdf_mem_copy(beacon_rep->bssId, rrm_ctx->sessionBssId.bytes,
204*5113495bSYour Name 			QDF_MAC_ADDR_SIZE);
205*5113495bSYour Name 
206*5113495bSYour Name 		i = 0;
207*5113495bSYour Name 		while (cur_result) {
208*5113495bSYour Name 			bss_desc = &cur_result->BssDescriptor;
209*5113495bSYour Name 			if (!bss_desc)
210*5113495bSYour Name 				break;
211*5113495bSYour Name 			size =  bss_desc->length + sizeof(bss_desc->length);
212*5113495bSYour Name 			beacon_rep->pBssDescription[i] = qdf_mem_malloc(size);
213*5113495bSYour Name 			if (NULL ==
214*5113495bSYour Name 				beacon_rep->pBssDescription[i])
215*5113495bSYour Name 				break;
216*5113495bSYour Name 			qdf_mem_copy(beacon_rep->pBssDescription[i],
217*5113495bSYour Name 				bss_desc, size);
218*5113495bSYour Name 			tmp_bss_desc[i] =
219*5113495bSYour Name 				beacon_rep->pBssDescription[i];
220*5113495bSYour Name 			sme_debug("RRM Result Bssid = " QDF_MAC_ADDR_FMT
221*5113495bSYour Name 				  " freq= %d, rssi = -%d",
222*5113495bSYour Name 				  QDF_MAC_ADDR_REF(
223*5113495bSYour Name 				  beacon_rep->pBssDescription[i]->bssId),
224*5113495bSYour Name 				  beacon_rep->pBssDescription[i]->chan_freq,
225*5113495bSYour Name 				  beacon_rep->pBssDescription[i]->rssi * (-1));
226*5113495bSYour Name 			beacon_rep->numBssDesc++;
227*5113495bSYour Name 			if (++i >= SIR_BCN_REPORT_MAX_BSS_DESC)
228*5113495bSYour Name 				break;
229*5113495bSYour Name 			if (i + j >= bss_count)
230*5113495bSYour Name 				break;
231*5113495bSYour Name 			cur_result =
232*5113495bSYour Name 				result_arr[j + i];
233*5113495bSYour Name 		}
234*5113495bSYour Name 
235*5113495bSYour Name 		j += i;
236*5113495bSYour Name 		if (!result_arr || (!cur_result)
237*5113495bSYour Name 			|| (j >= bss_count)) {
238*5113495bSYour Name 			cur_result = NULL;
239*5113495bSYour Name 			sme_debug("Reached to  max/last BSS in cur_result list");
240*5113495bSYour Name 		} else {
241*5113495bSYour Name 			cur_result = result_arr[j];
242*5113495bSYour Name 			sme_debug("Move to the next BSS set in cur_result list");
243*5113495bSYour Name 		}
244*5113495bSYour Name 		beacon_rep->fMeasureDone =
245*5113495bSYour Name 			(cur_result) ? false : msrmnt_status;
246*5113495bSYour Name 		sme_debug("SME Sending BcnRepXmit to PE numBss %d i %d j %d",
247*5113495bSYour Name 			beacon_rep->numBssDesc, i, j);
248*5113495bSYour Name 		status = umac_send_mb_message_to_mac(beacon_rep);
249*5113495bSYour Name 		if (status != QDF_STATUS_SUCCESS)
250*5113495bSYour Name 			for (counter = 0; counter < i; ++counter)
251*5113495bSYour Name 				qdf_mem_free(tmp_bss_desc[counter]);
252*5113495bSYour Name 	} while (cur_result);
253*5113495bSYour Name 
254*5113495bSYour Name 	return status;
255*5113495bSYour Name }
256*5113495bSYour Name 
257*5113495bSYour Name #ifdef FEATURE_WLAN_ESE
258*5113495bSYour Name /**
259*5113495bSYour Name  * sme_ese_send_beacon_req_scan_results () - Send beacon report
260*5113495bSYour Name  * @mac_ctx: Pointer to mac context
261*5113495bSYour Name  * @measurement_index: Measurement request index
262*5113495bSYour Name  * @session_id: session id
263*5113495bSYour Name  * @freq: channel frequency
264*5113495bSYour Name  * @result_arr: scan results
265*5113495bSYour Name  * @msrmnt_status: flag to indicate that the measurement is done.
266*5113495bSYour Name  * @bss_count:  number of bss found
267*5113495bSYour Name  *
268*5113495bSYour Name  * This function sends up the scan results received as a part of
269*5113495bSYour Name  * beacon request scanning.
270*5113495bSYour Name  * This function is called after receiving the scan results per channel
271*5113495bSYour Name  * Due to the limitation on the size of the IWEVCUSTOM buffer, we send
272*5113495bSYour Name  * 3 BSSIDs of beacon report information in one custom event;
273*5113495bSYour Name  *
274*5113495bSYour Name  * Return: status
275*5113495bSYour Name  */
sme_ese_send_beacon_req_scan_results(struct mac_context * mac_ctx,uint8_t measurement_index,uint32_t session_id,uint32_t freq,tCsrScanResultInfo ** result_arr,uint8_t msrmnt_status,uint8_t bss_count)276*5113495bSYour Name static QDF_STATUS sme_ese_send_beacon_req_scan_results(
277*5113495bSYour Name 	struct mac_context *mac_ctx, uint8_t measurement_index,
278*5113495bSYour Name 	uint32_t session_id, uint32_t freq,
279*5113495bSYour Name 	tCsrScanResultInfo **result_arr,
280*5113495bSYour Name 	uint8_t msrmnt_status, uint8_t bss_count)
281*5113495bSYour Name {
282*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
283*5113495bSYour Name 	QDF_STATUS fill_ie_status;
284*5113495bSYour Name 	struct bss_description *bss_desc = NULL;
285*5113495bSYour Name 	uint32_t ie_len = 0;
286*5113495bSYour Name 	uint32_t out_ie_len = 0;
287*5113495bSYour Name 	uint8_t bss_counter = 0;
288*5113495bSYour Name 	tCsrScanResultInfo *cur_result = NULL;
289*5113495bSYour Name 	tpRrmSMEContext rrm_ctx =
290*5113495bSYour Name 		&mac_ctx->rrm.rrmSmeContext[measurement_index];
291*5113495bSYour Name 	struct csr_roam_info *roam_info;
292*5113495bSYour Name 	struct ese_bcn_report_rsp bcn_rpt_rsp;
293*5113495bSYour Name 	struct ese_bcn_report_rsp *bcn_report = &bcn_rpt_rsp;
294*5113495bSYour Name 	tpCsrEseBeaconReqParams cur_meas_req = NULL;
295*5113495bSYour Name 	uint8_t i = 0, j = 0;
296*5113495bSYour Name 	tBcnReportFields *bcn_rpt_fields;
297*5113495bSYour Name 
298*5113495bSYour Name 	if (!rrm_ctx) {
299*5113495bSYour Name 		sme_err("rrm_ctx is NULL");
300*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
301*5113495bSYour Name 	}
302*5113495bSYour Name 
303*5113495bSYour Name 	if (!result_arr && !msrmnt_status) {
304*5113495bSYour Name 		sme_err("Beacon report xmit Ind to HDD Failed");
305*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
306*5113495bSYour Name 	}
307*5113495bSYour Name 
308*5113495bSYour Name 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
309*5113495bSYour Name 	if (!roam_info)
310*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
311*5113495bSYour Name 
312*5113495bSYour Name 	if (result_arr)
313*5113495bSYour Name 		cur_result = result_arr[bss_counter];
314*5113495bSYour Name 
315*5113495bSYour Name 	do {
316*5113495bSYour Name 		cur_meas_req = NULL;
317*5113495bSYour Name 		/* memset bcn_rpt_rsp for each iteration */
318*5113495bSYour Name 		qdf_mem_zero(&bcn_rpt_rsp, sizeof(bcn_rpt_rsp));
319*5113495bSYour Name 
320*5113495bSYour Name 		for (i = 0; i < rrm_ctx->eseBcnReqInfo.numBcnReqIe; i++) {
321*5113495bSYour Name 			if (rrm_ctx->eseBcnReqInfo.bcnReq[i].ch_freq == freq) {
322*5113495bSYour Name 				cur_meas_req =
323*5113495bSYour Name 					&rrm_ctx->eseBcnReqInfo.bcnReq[i];
324*5113495bSYour Name 				break;
325*5113495bSYour Name 			}
326*5113495bSYour Name 		}
327*5113495bSYour Name 		if (cur_meas_req)
328*5113495bSYour Name 			bcn_report->measurementToken =
329*5113495bSYour Name 				cur_meas_req->measurementToken;
330*5113495bSYour Name 		sme_debug("freq: %d MeasToken: %d", freq,
331*5113495bSYour Name 			  bcn_report->measurementToken);
332*5113495bSYour Name 
333*5113495bSYour Name 		j = 0;
334*5113495bSYour Name 		while (cur_result) {
335*5113495bSYour Name 			bss_desc = &cur_result->BssDescriptor;
336*5113495bSYour Name 			if (!bss_desc) {
337*5113495bSYour Name 				cur_result = NULL;
338*5113495bSYour Name 				break;
339*5113495bSYour Name 			}
340*5113495bSYour Name 			ie_len = GET_IE_LEN_IN_BSS(bss_desc->length);
341*5113495bSYour Name 			bcn_rpt_fields =
342*5113495bSYour Name 				&bcn_report->bcnRepBssInfo[j].bcnReportFields;
343*5113495bSYour Name 			bcn_rpt_fields->ChanNum = wlan_reg_freq_to_chan(
344*5113495bSYour Name 					mac_ctx->pdev,
345*5113495bSYour Name 					bss_desc->chan_freq);
346*5113495bSYour Name 			bcn_report->bcnRepBssInfo[j].bcnReportFields.Spare = 0;
347*5113495bSYour Name 			if (cur_meas_req)
348*5113495bSYour Name 				bcn_rpt_fields->MeasDuration =
349*5113495bSYour Name 					cur_meas_req->measurementDuration;
350*5113495bSYour Name 			bcn_rpt_fields->PhyType = bss_desc->nwType;
351*5113495bSYour Name 			bcn_rpt_fields->RecvSigPower = bss_desc->rssi;
352*5113495bSYour Name 			bcn_rpt_fields->ParentTsf = bss_desc->parentTSF;
353*5113495bSYour Name 			bcn_rpt_fields->TargetTsf[0] = bss_desc->timeStamp[0];
354*5113495bSYour Name 			bcn_rpt_fields->TargetTsf[1] = bss_desc->timeStamp[1];
355*5113495bSYour Name 			bcn_rpt_fields->BcnInterval = bss_desc->beaconInterval;
356*5113495bSYour Name 			bcn_rpt_fields->CapabilityInfo =
357*5113495bSYour Name 				bss_desc->capabilityInfo;
358*5113495bSYour Name 
359*5113495bSYour Name 			qdf_mem_copy(bcn_rpt_fields->Bssid,
360*5113495bSYour Name 				bss_desc->bssId, sizeof(tSirMacAddr));
361*5113495bSYour Name 				fill_ie_status =
362*5113495bSYour Name 					sir_beacon_ie_ese_bcn_report(mac_ctx,
363*5113495bSYour Name 						(uint8_t *) bss_desc->ieFields,
364*5113495bSYour Name 						ie_len,
365*5113495bSYour Name 						&(bcn_report->bcnRepBssInfo[j].
366*5113495bSYour Name 						pBuf),
367*5113495bSYour Name 						&out_ie_len);
368*5113495bSYour Name 			if (QDF_STATUS_E_FAILURE == fill_ie_status)
369*5113495bSYour Name 				continue;
370*5113495bSYour Name 			bcn_report->bcnRepBssInfo[j].ieLen = out_ie_len;
371*5113495bSYour Name 
372*5113495bSYour Name 			sme_debug("Bssid"QDF_MAC_ADDR_FMT" Freq:%d Rssi:%d",
373*5113495bSYour Name 				  QDF_MAC_ADDR_REF(bss_desc->bssId),
374*5113495bSYour Name 				  bss_desc->chan_freq, (-1) * bss_desc->rssi);
375*5113495bSYour Name 			bcn_report->numBss++;
376*5113495bSYour Name 			if (++j >= SIR_BCN_REPORT_MAX_BSS_DESC)
377*5113495bSYour Name 				break;
378*5113495bSYour Name 			if ((bss_counter + j) >= bss_count)
379*5113495bSYour Name 				break;
380*5113495bSYour Name 			cur_result = result_arr[bss_counter + j];
381*5113495bSYour Name 		}
382*5113495bSYour Name 
383*5113495bSYour Name 		bss_counter += j;
384*5113495bSYour Name 		if (!result_arr || !cur_result || (bss_counter >= bss_count)) {
385*5113495bSYour Name 			cur_result = NULL;
386*5113495bSYour Name 			sme_err("Reached to the max/last BSS in cur_result list");
387*5113495bSYour Name 		} else {
388*5113495bSYour Name 			cur_result = result_arr[bss_counter];
389*5113495bSYour Name 			sme_err("Move to the next BSS set in cur_result list");
390*5113495bSYour Name 		}
391*5113495bSYour Name 
392*5113495bSYour Name 		bcn_report->flag =
393*5113495bSYour Name 			(msrmnt_status << 1) | ((cur_result) ? true : false);
394*5113495bSYour Name 
395*5113495bSYour Name 		sme_debug("SME Sending BcnRep to HDD numBss: %d j: %d bss_counter: %d flag: %d",
396*5113495bSYour Name 			bcn_report->numBss, j, bss_counter,
397*5113495bSYour Name 			bcn_report->flag);
398*5113495bSYour Name 
399*5113495bSYour Name 		roam_info->pEseBcnReportRsp = bcn_report;
400*5113495bSYour Name 		status = csr_roam_call_callback(mac_ctx, session_id, roam_info,
401*5113495bSYour Name 						eCSR_ROAM_ESE_BCN_REPORT_IND, 0);
402*5113495bSYour Name 
403*5113495bSYour Name 		/* Free the memory allocated to IE */
404*5113495bSYour Name 		for (i = 0; i < j; i++)
405*5113495bSYour Name 			if (bcn_report->bcnRepBssInfo[i].pBuf)
406*5113495bSYour Name 				qdf_mem_free(bcn_report->bcnRepBssInfo[i].pBuf);
407*5113495bSYour Name 	} while (cur_result);
408*5113495bSYour Name 	qdf_mem_free(roam_info);
409*5113495bSYour Name 	return status;
410*5113495bSYour Name }
411*5113495bSYour Name 
412*5113495bSYour Name static inline
sme_reset_ese_bcn_req_in_progress(tpRrmSMEContext sme_rrm_ctx)413*5113495bSYour Name void sme_reset_ese_bcn_req_in_progress(tpRrmSMEContext sme_rrm_ctx)
414*5113495bSYour Name {
415*5113495bSYour Name 	if (sme_rrm_ctx)
416*5113495bSYour Name 		sme_rrm_ctx->eseBcnReqInProgress = false;
417*5113495bSYour Name }
418*5113495bSYour Name 
419*5113495bSYour Name #else
420*5113495bSYour Name 
421*5113495bSYour Name static inline
sme_reset_ese_bcn_req_in_progress(tpRrmSMEContext sme_rrm_ctx)422*5113495bSYour Name void sme_reset_ese_bcn_req_in_progress(tpRrmSMEContext sme_rrm_ctx)
423*5113495bSYour Name {}
424*5113495bSYour Name #endif /* FEATURE_WLAN_ESE */
425*5113495bSYour Name 
426*5113495bSYour Name /**
427*5113495bSYour Name  * sme_rrm_send_scan_result() - to get scan result and send the beacon report
428*5113495bSYour Name  * @mac_ctx: pointer to mac context
429*5113495bSYour Name  * @measurement_index: Measurement request number
430*5113495bSYour Name  * @num_chan: number of channels
431*5113495bSYour Name  * @freq_list: list of channel frequencies to fetch the result from
432*5113495bSYour Name  * @measurementdone: Flag to indicate measurement done or no
433*5113495bSYour Name  *
434*5113495bSYour Name  * This function is called to get the scan result from CSR and send the beacon
435*5113495bSYour Name  * report xmit ind message to PE
436*5113495bSYour Name  *
437*5113495bSYour Name  * Return: QDF_STATUS
438*5113495bSYour Name  */
sme_rrm_send_scan_result(struct mac_context * mac_ctx,uint8_t measurement_index,uint8_t num_chan,uint32_t * freq_list,uint8_t measurementdone)439*5113495bSYour Name static QDF_STATUS sme_rrm_send_scan_result(struct mac_context *mac_ctx,
440*5113495bSYour Name 					   uint8_t measurement_index,
441*5113495bSYour Name 					   uint8_t num_chan,
442*5113495bSYour Name 					   uint32_t *freq_list,
443*5113495bSYour Name 					   uint8_t measurementdone)
444*5113495bSYour Name {
445*5113495bSYour Name 	struct scan_filter *filter;
446*5113495bSYour Name 	tScanResultHandle result_handle;
447*5113495bSYour Name 	tCsrScanResultInfo *scan_results, *next_result;
448*5113495bSYour Name 	tCsrScanResultInfo **scanresults_arr = NULL;
449*5113495bSYour Name 	struct scan_result_list *result_list;
450*5113495bSYour Name 	QDF_STATUS status;
451*5113495bSYour Name 	uint32_t num_scan_results, counter = 0;
452*5113495bSYour Name 	tpRrmSMEContext rrm_ctx =
453*5113495bSYour Name 		&mac_ctx->rrm.rrmSmeContext[measurement_index];
454*5113495bSYour Name 	uint32_t session_id;
455*5113495bSYour Name 	tSirScanType scan_type;
456*5113495bSYour Name 	struct qdf_mac_addr bss_peer_mac;
457*5113495bSYour Name 
458*5113495bSYour Name 	filter = qdf_mem_malloc(sizeof(*filter));
459*5113495bSYour Name 	if (!filter)
460*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
461*5113495bSYour Name 
462*5113495bSYour Name 	if (qdf_is_macaddr_zero(filter->bssid_list) ||
463*5113495bSYour Name 	    qdf_is_macaddr_group(filter->bssid_list)) {
464*5113495bSYour Name 		filter->num_of_bssid = 0;
465*5113495bSYour Name 	} else {
466*5113495bSYour Name 		/* update filter to get scan result with just target BSSID */
467*5113495bSYour Name 		filter->num_of_bssid = 1;
468*5113495bSYour Name 		qdf_mem_copy(filter->bssid_list[0].bytes,
469*5113495bSYour Name 			     rrm_ctx->bssId, sizeof(struct qdf_mac_addr));
470*5113495bSYour Name 	}
471*5113495bSYour Name 
472*5113495bSYour Name 	if (rrm_ctx->ssId.length) {
473*5113495bSYour Name 		filter->num_of_ssid = 1;
474*5113495bSYour Name 		filter->ssid_list[0].length = rrm_ctx->ssId.length;
475*5113495bSYour Name 		if (filter->ssid_list[0].length > WLAN_SSID_MAX_LEN)
476*5113495bSYour Name 			filter->ssid_list[0].length = WLAN_SSID_MAX_LEN;
477*5113495bSYour Name 		qdf_mem_copy(filter->ssid_list[0].ssid,
478*5113495bSYour Name 			     rrm_ctx->ssId.ssId, filter->ssid_list[0].length);
479*5113495bSYour Name 	}
480*5113495bSYour Name 
481*5113495bSYour Name 	filter->num_of_channels = num_chan;
482*5113495bSYour Name 	if (filter->num_of_channels > NUM_CHANNELS)
483*5113495bSYour Name 		filter->num_of_channels = NUM_CHANNELS;
484*5113495bSYour Name 	qdf_mem_copy(filter->chan_freq_list, freq_list,
485*5113495bSYour Name 		     filter->num_of_channels *
486*5113495bSYour Name 		     sizeof(filter->chan_freq_list[0]));
487*5113495bSYour Name 	filter->rrm_measurement_filter = true;
488*5113495bSYour Name 
489*5113495bSYour Name 	if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource ||
490*5113495bSYour Name 	    eRRM_MSG_SOURCE_LEGACY_ESE == rrm_ctx->msgSource)
491*5113495bSYour Name 		scan_type = rrm_ctx->measMode[rrm_ctx->currentIndex];
492*5113495bSYour Name 	else
493*5113495bSYour Name 		scan_type = rrm_ctx->measMode[0];
494*5113495bSYour Name 
495*5113495bSYour Name 	if (scan_type == eSIR_BEACON_TABLE)
496*5113495bSYour Name 		filter->age_threshold =
497*5113495bSYour Name 			wlan_scan_get_aging_time(mac_ctx->psoc);
498*5113495bSYour Name 
499*5113495bSYour Name 
500*5113495bSYour Name 	/*
501*5113495bSYour Name 	 * In case this is beacon report request from last AP (before roaming)
502*5113495bSYour Name 	 * following call to csr_roam_get_session_id_from_bssid will fail,
503*5113495bSYour Name 	 * hence use current session ID instead of one stored in SME rrm context
504*5113495bSYour Name 	 */
505*5113495bSYour Name 	if (QDF_STATUS_E_FAILURE == csr_roam_get_session_id_from_bssid(mac_ctx,
506*5113495bSYour Name 			&rrm_ctx->sessionBssId, &session_id)) {
507*5113495bSYour Name 		sme_debug("BSSID mismatch, using current session_id");
508*5113495bSYour Name 		session_id = mac_ctx->roam.roamSession->vdev_id;
509*5113495bSYour Name 	}
510*5113495bSYour Name 	status = csr_scan_get_result(mac_ctx, filter, &result_handle);
511*5113495bSYour Name 	qdf_mem_free(filter);
512*5113495bSYour Name 
513*5113495bSYour Name 	sme_debug("RRM Measurement Done %d for index:%d",
514*5113495bSYour Name 		  measurementdone, measurement_index);
515*5113495bSYour Name 	if (!result_handle) {
516*5113495bSYour Name 		/*
517*5113495bSYour Name 		 * no scan results
518*5113495bSYour Name 		 * Spec. doesn't say anything about such condition
519*5113495bSYour Name 		 * Since section 7.4.6.2 (IEEE802.11k-2008) says-rrm report
520*5113495bSYour Name 		 * frame should contain one or more report IEs. It probably
521*5113495bSYour Name 		 * means dont send any response if no matching BSS found.
522*5113495bSYour Name 		 * Moreover, there is no flag or field in measurement report
523*5113495bSYour Name 		 * IE(7.3.2.22) OR beacon report IE(7.3.2.22.6) that can be set
524*5113495bSYour Name 		 * to indicate no BSS found on a given channel. If we finished
525*5113495bSYour Name 		 * measurement on all the channels, we still need to send a
526*5113495bSYour Name 		 * xmit indication with moreToFollow set to MEASURMENT_DONE so
527*5113495bSYour Name 		 * that PE can clean any context allocated.
528*5113495bSYour Name 		 */
529*5113495bSYour Name 		if (!measurementdone)
530*5113495bSYour Name 			return status;
531*5113495bSYour Name #ifdef FEATURE_WLAN_ESE
532*5113495bSYour Name 		if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource)
533*5113495bSYour Name 			status = sme_ese_send_beacon_req_scan_results(mac_ctx,
534*5113495bSYour Name 					measurement_index, session_id,
535*5113495bSYour Name 					freq_list[0], NULL,
536*5113495bSYour Name 					measurementdone, 0);
537*5113495bSYour Name 		else
538*5113495bSYour Name #endif /* FEATURE_WLAN_ESE */
539*5113495bSYour Name 			status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx,
540*5113495bSYour Name 							measurement_index, NULL,
541*5113495bSYour Name 							measurementdone, 0);
542*5113495bSYour Name 		return status;
543*5113495bSYour Name 	}
544*5113495bSYour Name 	scan_results = csr_scan_result_get_first(mac_ctx, result_handle);
545*5113495bSYour Name 	if (!scan_results && measurementdone) {
546*5113495bSYour Name #ifdef FEATURE_WLAN_ESE
547*5113495bSYour Name 		if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource) {
548*5113495bSYour Name 			status = sme_ese_send_beacon_req_scan_results(mac_ctx,
549*5113495bSYour Name 					measurement_index, session_id,
550*5113495bSYour Name 					freq_list[0], NULL,
551*5113495bSYour Name 					measurementdone, 0);
552*5113495bSYour Name 		} else
553*5113495bSYour Name #endif /* FEATURE_WLAN_ESE */
554*5113495bSYour Name 			status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx,
555*5113495bSYour Name 						measurement_index,
556*5113495bSYour Name 						NULL, measurementdone, 0);
557*5113495bSYour Name 	}
558*5113495bSYour Name 
559*5113495bSYour Name 	result_list = (struct scan_result_list *)result_handle;
560*5113495bSYour Name 	num_scan_results = csr_ll_count(&result_list->List);
561*5113495bSYour Name 	if (!num_scan_results) {
562*5113495bSYour Name 		sme_err("num_scan_results is %d", num_scan_results);
563*5113495bSYour Name 		status = QDF_STATUS_E_FAILURE;
564*5113495bSYour Name 		goto rrm_send_scan_results_done;
565*5113495bSYour Name 	}
566*5113495bSYour Name 
567*5113495bSYour Name 	sme_debug("num_scan_results %d", num_scan_results);
568*5113495bSYour Name 	scanresults_arr = qdf_mem_malloc(num_scan_results *
569*5113495bSYour Name 					 sizeof(next_result));
570*5113495bSYour Name 	if (!scanresults_arr) {
571*5113495bSYour Name 		status = QDF_STATUS_E_NOMEM;
572*5113495bSYour Name 		goto send_scan_results;
573*5113495bSYour Name 	}
574*5113495bSYour Name 
575*5113495bSYour Name 	status = wlan_mlme_get_bssid_vdev_id(mac_ctx->pdev, session_id,
576*5113495bSYour Name 					     &bss_peer_mac);
577*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
578*5113495bSYour Name 		sme_err("BSSID not found for vdev: %d", session_id);
579*5113495bSYour Name 		status = QDF_STATUS_E_FAILURE;
580*5113495bSYour Name 		goto send_scan_results;
581*5113495bSYour Name 	}
582*5113495bSYour Name 
583*5113495bSYour Name 	if (!cm_is_vdevid_connected(mac_ctx->pdev, session_id)) {
584*5113495bSYour Name 		sme_err("vdev:%d is not connected", session_id);
585*5113495bSYour Name 		status = QDF_STATUS_E_FAILURE;
586*5113495bSYour Name 		goto send_scan_results;
587*5113495bSYour Name 	}
588*5113495bSYour Name 
589*5113495bSYour Name 	while (scan_results) {
590*5113495bSYour Name 		/*
591*5113495bSYour Name 		 * Connected AP beacon is offloaded to firmware.
592*5113495bSYour Name 		 * Firmware will discard connected AP beacon except that
593*5113495bSYour Name 		 * special IE exists Connected AP beacon will not be sent
594*5113495bSYour Name 		 * to host. Hence, timer of connected AP in scan results is
595*5113495bSYour Name 		 * not updated and can not meet
596*5113495bSYour Name 		 * "pScanResult->timer >= RRM_scan_timer".
597*5113495bSYour Name 		 */
598*5113495bSYour Name 		uint8_t is_conn_bss_found = false;
599*5113495bSYour Name 		uint8_t is_nontx_of_conn_bss = false;
600*5113495bSYour Name 
601*5113495bSYour Name 		if (!qdf_mem_cmp(scan_results->BssDescriptor.bssId,
602*5113495bSYour Name 				 bss_peer_mac.bytes,
603*5113495bSYour Name 		    sizeof(struct qdf_mac_addr))) {
604*5113495bSYour Name 			is_conn_bss_found = true;
605*5113495bSYour Name 			sme_debug("Connected BSS in scan results");
606*5113495bSYour Name 		}
607*5113495bSYour Name 		if (scan_results->BssDescriptor.mbssid_info.profile_num) {
608*5113495bSYour Name 			if (!qdf_mem_cmp(scan_results->BssDescriptor.
609*5113495bSYour Name 					 mbssid_info.trans_bssid,
610*5113495bSYour Name 					 bss_peer_mac.bytes,
611*5113495bSYour Name 					 QDF_MAC_ADDR_SIZE)) {
612*5113495bSYour Name 				is_nontx_of_conn_bss = true;
613*5113495bSYour Name 				sme_debug("Non Tx BSS of Conn AP in results");
614*5113495bSYour Name 			}
615*5113495bSYour Name 		}
616*5113495bSYour Name 		next_result = csr_scan_result_get_next(mac_ctx,
617*5113495bSYour Name 						       result_handle);
618*5113495bSYour Name 		sme_debug("Scan res timer:%lu, rrm scan timer:%llu",
619*5113495bSYour Name 				scan_results->timer, rrm_scan_timer);
620*5113495bSYour Name 		if ((scan_results->timer >= rrm_scan_timer) ||
621*5113495bSYour Name 		    (is_conn_bss_found == true) || is_nontx_of_conn_bss)
622*5113495bSYour Name 			scanresults_arr[counter++] = scan_results;
623*5113495bSYour Name 		scan_results = next_result;
624*5113495bSYour Name 		if (counter >= num_scan_results)
625*5113495bSYour Name 			break;
626*5113495bSYour Name 	}
627*5113495bSYour Name 
628*5113495bSYour Name send_scan_results:
629*5113495bSYour Name 	/*
630*5113495bSYour Name 	 * The beacon report should be sent whether the counter is zero or
631*5113495bSYour Name 	 * non-zero. There might be a few scan results in the cache but not
632*5113495bSYour Name 	 * actually are a result of this scan. During that scenario, the
633*5113495bSYour Name 	 * counter will be zero. The report should be sent and LIM will further
634*5113495bSYour Name 	 * cleanup the RRM to accept the further incoming requests
635*5113495bSYour Name 	 * In case the counter is Zero, the pScanResultsArr will be NULL.
636*5113495bSYour Name 	 * The next level routine does a check for the measurementDone to
637*5113495bSYour Name 	 * determine whether to send a report or not.
638*5113495bSYour Name 	 */
639*5113495bSYour Name 	sme_debug("Number of BSS Desc with RRM Scan %d", counter);
640*5113495bSYour Name 	if (counter || measurementdone) {
641*5113495bSYour Name #ifdef FEATURE_WLAN_ESE
642*5113495bSYour Name 		if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource)
643*5113495bSYour Name 			status = sme_ese_send_beacon_req_scan_results(mac_ctx,
644*5113495bSYour Name 					measurement_index, session_id,
645*5113495bSYour Name 					freq_list[0], scanresults_arr,
646*5113495bSYour Name 					measurementdone, counter);
647*5113495bSYour Name 		else
648*5113495bSYour Name #endif /* FEATURE_WLAN_ESE */
649*5113495bSYour Name 			status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx,
650*5113495bSYour Name 					measurement_index, scanresults_arr,
651*5113495bSYour Name 					measurementdone, counter);
652*5113495bSYour Name 	}
653*5113495bSYour Name 
654*5113495bSYour Name rrm_send_scan_results_done:
655*5113495bSYour Name 	if (scanresults_arr)
656*5113495bSYour Name 		qdf_mem_free(scanresults_arr);
657*5113495bSYour Name 	csr_scan_result_purge(mac_ctx, result_handle);
658*5113495bSYour Name 
659*5113495bSYour Name 	return status;
660*5113495bSYour Name }
661*5113495bSYour Name 
662*5113495bSYour Name /**
663*5113495bSYour Name  * sme_rrm_scan_request_callback() -Sends the beacon report xmit to PE
664*5113495bSYour Name  * @mac_handle: Opaque handle to the MAC context
665*5113495bSYour Name  * @pSmeRrmContext: SME rrm context for measurement request
666*5113495bSYour Name  * @sessionId: session id
667*5113495bSYour Name  * @scanId: Scan ID.
668*5113495bSYour Name  * @status: CSR Status.
669*5113495bSYour Name  *
670*5113495bSYour Name  * The sme module calls this callback function once it finish the scan request
671*5113495bSYour Name  * and this function send the beacon report xmit to PE and starts a timer of
672*5113495bSYour Name  * random interval to issue next request.
673*5113495bSYour Name  *
674*5113495bSYour Name  * Return : 0 for success, non zero for failure
675*5113495bSYour Name  */
sme_rrm_scan_request_callback(struct mac_context * mac,tpRrmSMEContext pSmeRrmContext,uint8_t sessionId,uint32_t scanId,eCsrScanStatus status)676*5113495bSYour Name static QDF_STATUS sme_rrm_scan_request_callback(struct mac_context *mac,
677*5113495bSYour Name 						tpRrmSMEContext pSmeRrmContext,
678*5113495bSYour Name 						uint8_t sessionId,
679*5113495bSYour Name 						uint32_t scanId,
680*5113495bSYour Name 						eCsrScanStatus status)
681*5113495bSYour Name {
682*5113495bSYour Name 	uint8_t num_chan;
683*5113495bSYour Name 	uint32_t *freq_list;
684*5113495bSYour Name 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
685*5113495bSYour Name 
686*5113495bSYour Name 	/*
687*5113495bSYour Name 	 * Even if RRM scan response is received after roaming to different AP
688*5113495bSYour Name 	 * the messege shall be posted to PE for rrm cleanup.
689*5113495bSYour Name 	 */
690*5113495bSYour Name 
691*5113495bSYour Name 	freq_list = pSmeRrmContext->channelList.freq_list;
692*5113495bSYour Name 	if (!freq_list) {
693*5113495bSYour Name 		sme_err("[802.11 RRM]: Global freq list is null");
694*5113495bSYour Name 		pSmeRrmContext->channelList.numOfChannels = 0;
695*5113495bSYour Name 		qdf_status = QDF_STATUS_E_FAILURE;
696*5113495bSYour Name 		goto end;
697*5113495bSYour Name 	}
698*5113495bSYour Name 	/* Sending the beacon report xmit for the all the valid channel
699*5113495bSYour Name 	 * scan results within randomization interval.
700*5113495bSYour Name 	 */
701*5113495bSYour Name 	num_chan = pSmeRrmContext->channelList.numOfChannels;
702*5113495bSYour Name 	sme_rrm_send_scan_result(mac, pSmeRrmContext->measurement_idx,
703*5113495bSYour Name 				 num_chan, &freq_list[0], true);
704*5113495bSYour Name 
705*5113495bSYour Name 	/* Clean up all context and send a
706*5113495bSYour Name 	 * message to PE with measurement done flag set.
707*5113495bSYour Name 	 */
708*5113495bSYour Name 	qdf_mem_free(pSmeRrmContext->channelList.freq_list);
709*5113495bSYour Name 	pSmeRrmContext->channelList.freq_list = NULL;
710*5113495bSYour Name end:
711*5113495bSYour Name 	pSmeRrmContext->channelList.numOfChannels = 0;
712*5113495bSYour Name 	sme_reset_ese_bcn_req_in_progress(pSmeRrmContext);
713*5113495bSYour Name 
714*5113495bSYour Name 	return qdf_status;
715*5113495bSYour Name }
716*5113495bSYour Name 
717*5113495bSYour Name /**
718*5113495bSYour Name  * sme_rrm_send_chan_load_report_xmit_ind() -Sends the chan load report xmit
719*5113495bSYour Name  * to PE
720*5113495bSYour Name  * @mac: global mac context
721*5113495bSYour Name  * @rrm_sme_ctx: SME rrm context for measurement request
722*5113495bSYour Name  * @vdev_id: vdev id
723*5113495bSYour Name  * @is_report_success: need to send failure report or not
724*5113495bSYour Name  *
725*5113495bSYour Name  * The sme module calls this function once it finish the scan request
726*5113495bSYour Name  * and this function send the chan load report xmit to PE.
727*5113495bSYour Name  *
728*5113495bSYour Name  * Return : None
729*5113495bSYour Name  */
730*5113495bSYour Name static void
sme_rrm_send_chan_load_report_xmit_ind(struct mac_context * mac,tpRrmSMEContext rrm_sme_ctx,uint8_t vdev_id,bool is_report_success)731*5113495bSYour Name sme_rrm_send_chan_load_report_xmit_ind(struct mac_context *mac,
732*5113495bSYour Name 				       tpRrmSMEContext rrm_sme_ctx,
733*5113495bSYour Name 				       uint8_t vdev_id,
734*5113495bSYour Name 				       bool is_report_success)
735*5113495bSYour Name {
736*5113495bSYour Name 	uint8_t measurement_index = rrm_sme_ctx->measurement_idx;
737*5113495bSYour Name 	struct chan_load_xmit_ind *chan_load_resp;
738*5113495bSYour Name 	uint16_t length;
739*5113495bSYour Name 	tpRrmSMEContext rrm_ctx = &mac->rrm.rrmSmeContext[measurement_index];
740*5113495bSYour Name 	const struct bonded_channel_freq *range;
741*5113495bSYour Name 	uint8_t chan_load = 0, temp_chan_load;
742*5113495bSYour Name 	qdf_freq_t start_freq, end_freq, op_freq;
743*5113495bSYour Name 	enum phy_ch_width req_chan_width;
744*5113495bSYour Name 
745*5113495bSYour Name 	length = sizeof(struct chan_load_xmit_ind);
746*5113495bSYour Name 	chan_load_resp = qdf_mem_malloc(length);
747*5113495bSYour Name 	if (!chan_load_resp)
748*5113495bSYour Name 		return;
749*5113495bSYour Name 
750*5113495bSYour Name 	chan_load_resp->messageType = eWNI_SME_CHAN_LOAD_REPORT_RESP_XMIT_IND;
751*5113495bSYour Name 	chan_load_resp->is_report_success = is_report_success;
752*5113495bSYour Name 	chan_load_resp->length = length;
753*5113495bSYour Name 	chan_load_resp->measurement_idx = measurement_index;
754*5113495bSYour Name 	chan_load_resp->dialog_token = rrm_ctx->token;
755*5113495bSYour Name 	chan_load_resp->duration = rrm_ctx->duration[0];
756*5113495bSYour Name 	chan_load_resp->op_class = rrm_ctx->regClass;
757*5113495bSYour Name 	chan_load_resp->channel = rrm_ctx->chan_load_req_info.channel;
758*5113495bSYour Name 	chan_load_resp->rrm_scan_tsf = rrm_ctx->chan_load_req_info.rrm_scan_tsf;
759*5113495bSYour Name 
760*5113495bSYour Name 	op_freq = rrm_ctx->chan_load_req_info.req_freq;
761*5113495bSYour Name 	req_chan_width = rrm_ctx->chan_load_req_info.req_chan_width;
762*5113495bSYour Name 	if (req_chan_width == CH_WIDTH_INVALID) {
763*5113495bSYour Name 		sme_debug("Invalid scanned_ch_width");
764*5113495bSYour Name 		return;
765*5113495bSYour Name 	}
766*5113495bSYour Name 
767*5113495bSYour Name 	if (req_chan_width == CH_WIDTH_20MHZ) {
768*5113495bSYour Name 		start_freq = op_freq;
769*5113495bSYour Name 		end_freq = op_freq;
770*5113495bSYour Name 		sme_debug("cw %d: start_freq %d, end_freq %d", req_chan_width,
771*5113495bSYour Name 			  start_freq, end_freq);
772*5113495bSYour Name 	} else if (req_chan_width == CH_WIDTH_320MHZ) {
773*5113495bSYour Name 		if (!rrm_ctx->chan_load_req_info.bw_ind.is_bw_ind_element) {
774*5113495bSYour Name 			sme_debug("is_bw_ind_element is false");
775*5113495bSYour Name 			return;
776*5113495bSYour Name 		}
777*5113495bSYour Name 
778*5113495bSYour Name 		qdf_mem_copy(&chan_load_resp->bw_ind,
779*5113495bSYour Name 			     &rrm_ctx->chan_load_req_info.bw_ind,
780*5113495bSYour Name 			     sizeof(chan_load_resp->bw_ind));
781*5113495bSYour Name 		range = wlan_reg_get_bonded_chan_entry(op_freq,
782*5113495bSYour Name 			  rrm_ctx->chan_load_req_info.bw_ind.channel_width,
783*5113495bSYour Name 			  rrm_ctx->chan_load_req_info.bw_ind.center_freq);
784*5113495bSYour Name 		if (!range) {
785*5113495bSYour Name 			sme_debug("vdev %d : range is null for freq %d",
786*5113495bSYour Name 				  vdev_id, op_freq);
787*5113495bSYour Name 			return;
788*5113495bSYour Name 		}
789*5113495bSYour Name 
790*5113495bSYour Name 		start_freq = range->start_freq;
791*5113495bSYour Name 		end_freq = range->end_freq;
792*5113495bSYour Name 		sme_debug("cw %d: start_freq %d, end_freq %d", req_chan_width,
793*5113495bSYour Name 			  start_freq, end_freq);
794*5113495bSYour Name 	} else {
795*5113495bSYour Name 		if (rrm_ctx->chan_load_req_info.wide_bw.is_wide_bw_chan_switch) {
796*5113495bSYour Name 			qdf_mem_copy(&chan_load_resp->wide_bw,
797*5113495bSYour Name 				     &rrm_ctx->chan_load_req_info.wide_bw,
798*5113495bSYour Name 				     sizeof(chan_load_resp->wide_bw));
799*5113495bSYour Name 			req_chan_width =
800*5113495bSYour Name 			    rrm_ctx->chan_load_req_info.wide_bw.channel_width;
801*5113495bSYour Name 			sme_debug("Fill wide_bw_chan_switch IE for cw:%d",
802*5113495bSYour Name 				  req_chan_width);
803*5113495bSYour Name 		}
804*5113495bSYour Name 
805*5113495bSYour Name 		range =
806*5113495bSYour Name 		   wlan_reg_get_bonded_chan_entry(op_freq, req_chan_width, 0);
807*5113495bSYour Name 		if (!range) {
808*5113495bSYour Name 			sme_debug("range is NULL for freq %d, ch_width %d",
809*5113495bSYour Name 				  op_freq, req_chan_width);
810*5113495bSYour Name 			return;
811*5113495bSYour Name 		}
812*5113495bSYour Name 		start_freq = range->start_freq;
813*5113495bSYour Name 		end_freq = range->end_freq;
814*5113495bSYour Name 		sme_debug("cw %d: start_freq %d, end_freq %d",
815*5113495bSYour Name 			  req_chan_width, start_freq, end_freq);
816*5113495bSYour Name 	}
817*5113495bSYour Name 
818*5113495bSYour Name 	for (; start_freq <= end_freq;) {
819*5113495bSYour Name 		temp_chan_load =
820*5113495bSYour Name 			wlan_cp_stats_get_rx_clear_count(mac->psoc,
821*5113495bSYour Name 							 vdev_id,
822*5113495bSYour Name 							 start_freq);
823*5113495bSYour Name 		if (chan_load < temp_chan_load)
824*5113495bSYour Name 			chan_load = temp_chan_load;
825*5113495bSYour Name 
826*5113495bSYour Name 		start_freq += BW_20_MHZ;
827*5113495bSYour Name 	}
828*5113495bSYour Name 
829*5113495bSYour Name 	chan_load_resp->chan_load = chan_load;
830*5113495bSYour Name 
831*5113495bSYour Name 	sme_debug("SME Sending CHAN_LOAD_REPORT_RESP_XMIT_IND to PE");
832*5113495bSYour Name 	umac_send_mb_message_to_mac(chan_load_resp);
833*5113495bSYour Name }
834*5113495bSYour Name 
sme_rrm_scan_event_callback(struct wlan_objmgr_vdev * vdev,struct scan_event * event,void * arg)835*5113495bSYour Name static void sme_rrm_scan_event_callback(struct wlan_objmgr_vdev *vdev,
836*5113495bSYour Name 			struct scan_event *event, void *arg)
837*5113495bSYour Name {
838*5113495bSYour Name 	struct mac_context *mac_ctx;
839*5113495bSYour Name 	uint32_t scan_id;
840*5113495bSYour Name 	uint8_t vdev_id, i;
841*5113495bSYour Name 	eCsrScanStatus scan_status = eCSR_SCAN_FAILURE;
842*5113495bSYour Name 	bool success = false;
843*5113495bSYour Name 	tpRrmSMEContext smerrmctx;
844*5113495bSYour Name 
845*5113495bSYour Name 	mac_ctx = (struct mac_context *)arg;
846*5113495bSYour Name 	if (!mac_ctx) {
847*5113495bSYour Name 		sme_err("invalid mac_ctx");
848*5113495bSYour Name 		return;
849*5113495bSYour Name 	}
850*5113495bSYour Name 
851*5113495bSYour Name 	vdev_id = wlan_vdev_get_id(vdev);
852*5113495bSYour Name 	scan_id = event->scan_id;
853*5113495bSYour Name 
854*5113495bSYour Name 	qdf_mtrace(QDF_MODULE_ID_SCAN, QDF_MODULE_ID_SME, event->type,
855*5113495bSYour Name 		   event->vdev_id, event->scan_id);
856*5113495bSYour Name 
857*5113495bSYour Name 	if (!util_is_scan_completed(event, &success))
858*5113495bSYour Name 		return;
859*5113495bSYour Name 
860*5113495bSYour Name 	if (success)
861*5113495bSYour Name 		scan_status = eCSR_SCAN_SUCCESS;
862*5113495bSYour Name 
863*5113495bSYour Name 	for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) {
864*5113495bSYour Name 		smerrmctx = &mac_ctx->rrm.rrmSmeContext[i];
865*5113495bSYour Name 		if (smerrmctx->scan_id == scan_id)
866*5113495bSYour Name 			break;
867*5113495bSYour Name 
868*5113495bSYour Name 		if (i == (MAX_MEASUREMENT_REQUEST - 1))
869*5113495bSYour Name 			return;
870*5113495bSYour Name 	}
871*5113495bSYour Name 
872*5113495bSYour Name 	sme_debug("vdev: %d : Scan completed for scan_id:%d idx:%d, type:%d",
873*5113495bSYour Name 		  vdev_id, scan_id, smerrmctx->measurement_idx,
874*5113495bSYour Name 		  smerrmctx->measurement_type);
875*5113495bSYour Name 
876*5113495bSYour Name 	switch (smerrmctx->measurement_type) {
877*5113495bSYour Name 	case RRM_CHANNEL_LOAD:
878*5113495bSYour Name 		sme_rrm_send_chan_load_report_xmit_ind(mac_ctx, smerrmctx,
879*5113495bSYour Name 						       vdev_id, true);
880*5113495bSYour Name 		break;
881*5113495bSYour Name 	case RRM_BEACON_REPORT:
882*5113495bSYour Name 		sme_rrm_scan_request_callback(mac_ctx, smerrmctx, vdev_id,
883*5113495bSYour Name 					      scan_id, scan_status);
884*5113495bSYour Name 		break;
885*5113495bSYour Name 	default:
886*5113495bSYour Name 		sme_err("Unknown measurement_type: %d",
887*5113495bSYour Name 			smerrmctx->measurement_type);
888*5113495bSYour Name 		break;
889*5113495bSYour Name 	}
890*5113495bSYour Name }
891*5113495bSYour Name 
892*5113495bSYour Name #define RRM_CHAN_WEIGHT_CHAR_LEN 5
893*5113495bSYour Name #define RRM_MAX_CHAN_TO_PRINT 39
894*5113495bSYour Name 
sme_rrm_issue_scan_req(struct mac_context * mac_ctx,uint8_t idx)895*5113495bSYour Name QDF_STATUS sme_rrm_issue_scan_req(struct mac_context *mac_ctx, uint8_t idx)
896*5113495bSYour Name {
897*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
898*5113495bSYour Name 	tpRrmSMEContext sme_rrm_ctx = &mac_ctx->rrm.rrmSmeContext[idx];
899*5113495bSYour Name 	uint32_t session_id;
900*5113495bSYour Name 	tSirScanType scan_type;
901*5113495bSYour Name 	uint8_t ch_idx;
902*5113495bSYour Name 	uint32_t *freq_list;
903*5113495bSYour Name 
904*5113495bSYour Name 	status = csr_roam_get_session_id_from_bssid(mac_ctx,
905*5113495bSYour Name 			&sme_rrm_ctx->sessionBssId, &session_id);
906*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS) {
907*5113495bSYour Name 		sme_err("sme session ID not found for bssid= "QDF_MAC_ADDR_FMT,
908*5113495bSYour Name 			QDF_MAC_ADDR_REF(sme_rrm_ctx->sessionBssId.bytes));
909*5113495bSYour Name 		status = QDF_STATUS_E_FAILURE;
910*5113495bSYour Name 		goto send_ind;
911*5113495bSYour Name 	}
912*5113495bSYour Name 
913*5113495bSYour Name 	if ((sme_rrm_ctx->currentIndex) >=
914*5113495bSYour Name 			sme_rrm_ctx->channelList.numOfChannels) {
915*5113495bSYour Name 		sme_rrm_send_beacon_report_xmit_ind(mac_ctx, idx, NULL,
916*5113495bSYour Name 						    true, 0);
917*5113495bSYour Name 		sme_debug("done with the complete ch lt. finish and fee now");
918*5113495bSYour Name 		goto free_ch_lst;
919*5113495bSYour Name 	}
920*5113495bSYour Name 
921*5113495bSYour Name 	if (eRRM_MSG_SOURCE_ESE_UPLOAD == sme_rrm_ctx->msgSource ||
922*5113495bSYour Name 		eRRM_MSG_SOURCE_LEGACY_ESE == sme_rrm_ctx->msgSource)
923*5113495bSYour Name 		scan_type = sme_rrm_ctx->measMode[sme_rrm_ctx->currentIndex];
924*5113495bSYour Name 	else
925*5113495bSYour Name 		scan_type = sme_rrm_ctx->measMode[0];
926*5113495bSYour Name 
927*5113495bSYour Name 	if ((eSIR_ACTIVE_SCAN == scan_type) ||
928*5113495bSYour Name 	    (eSIR_PASSIVE_SCAN == scan_type)) {
929*5113495bSYour Name 		uint32_t max_chan_time, buff_len, buff_num = 0, chan_count = 0;
930*5113495bSYour Name 		uint64_t current_time;
931*5113495bSYour Name 		struct scan_start_request *req;
932*5113495bSYour Name 		struct wlan_objmgr_vdev *vdev;
933*5113495bSYour Name 		uint16_t i;
934*5113495bSYour Name 		char *chan_buff = NULL;
935*5113495bSYour Name 
936*5113495bSYour Name 		if (!sme_rrm_ctx->channelList.numOfChannels ||
937*5113495bSYour Name 		    !sme_rrm_ctx->channelList.freq_list) {
938*5113495bSYour Name 			sme_err("[802.11 RRM]: Global freq list is null");
939*5113495bSYour Name 			status = QDF_STATUS_E_FAILURE;
940*5113495bSYour Name 			goto send_ind;
941*5113495bSYour Name 		}
942*5113495bSYour Name 
943*5113495bSYour Name 		req = qdf_mem_malloc(sizeof(*req));
944*5113495bSYour Name 		if (!req) {
945*5113495bSYour Name 			status = QDF_STATUS_E_NOMEM;
946*5113495bSYour Name 			goto send_ind;
947*5113495bSYour Name 		}
948*5113495bSYour Name 
949*5113495bSYour Name 		vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
950*5113495bSYour Name 						mac_ctx->psoc,
951*5113495bSYour Name 						session_id,
952*5113495bSYour Name 						WLAN_LEGACY_SME_ID);
953*5113495bSYour Name 		if (!vdev) {
954*5113495bSYour Name 			sme_err("VDEV is null %d", session_id);
955*5113495bSYour Name 			status = QDF_STATUS_E_INVAL;
956*5113495bSYour Name 			qdf_mem_free(req);
957*5113495bSYour Name 			goto send_ind;
958*5113495bSYour Name 		}
959*5113495bSYour Name 		wlan_scan_init_default_params(vdev, req);
960*5113495bSYour Name 		req->scan_req.scan_id = wlan_scan_get_scan_id(mac_ctx->psoc);
961*5113495bSYour Name 		sme_rrm_ctx->scan_id = req->scan_req.scan_id;
962*5113495bSYour Name 
963*5113495bSYour Name 		sme_debug("RRM_SCN: rrm_idx:%d scan_id:%d",
964*5113495bSYour Name 			  sme_rrm_ctx->measurement_idx, sme_rrm_ctx->scan_id);
965*5113495bSYour Name 		req->scan_req.scan_f_passive =
966*5113495bSYour Name 				(scan_type == eSIR_ACTIVE_SCAN) ? false : true;
967*5113495bSYour Name 		req->scan_req.vdev_id = wlan_vdev_get_id(vdev);
968*5113495bSYour Name 		req->scan_req.scan_req_id = sme_rrm_ctx->req_id;
969*5113495bSYour Name 		qdf_mem_copy(&req->scan_req.bssid_list[0], sme_rrm_ctx->bssId,
970*5113495bSYour Name 				QDF_MAC_ADDR_SIZE);
971*5113495bSYour Name 		req->scan_req.num_bssid = 1;
972*5113495bSYour Name 		if (sme_rrm_ctx->ssId.length) {
973*5113495bSYour Name 			req->scan_req.num_ssids = 1;
974*5113495bSYour Name 			qdf_mem_copy(&req->scan_req.ssid[0].ssid,
975*5113495bSYour Name 					sme_rrm_ctx->ssId.ssId,
976*5113495bSYour Name 					sme_rrm_ctx->ssId.length);
977*5113495bSYour Name 			req->scan_req.ssid[0].length = sme_rrm_ctx->ssId.length;
978*5113495bSYour Name 		}
979*5113495bSYour Name 
980*5113495bSYour Name 		/*
981*5113495bSYour Name 		 * set min and max channel time
982*5113495bSYour Name 		 * sme_rrm_ctx->duration; Dont use min timeout.
983*5113495bSYour Name 		 */
984*5113495bSYour Name 		if (eRRM_MSG_SOURCE_ESE_UPLOAD == sme_rrm_ctx->msgSource ||
985*5113495bSYour Name 			eRRM_MSG_SOURCE_LEGACY_ESE == sme_rrm_ctx->msgSource)
986*5113495bSYour Name 			max_chan_time =
987*5113495bSYour Name 			      sme_rrm_ctx->duration[sme_rrm_ctx->currentIndex];
988*5113495bSYour Name 		else
989*5113495bSYour Name 			max_chan_time = sme_rrm_ctx->duration[0];
990*5113495bSYour Name 
991*5113495bSYour Name 		/*
992*5113495bSYour Name 		 * Use max_chan_time if max_chan_time is more than def value
993*5113495bSYour Name 		 * depending on type of scan.
994*5113495bSYour Name 		 */
995*5113495bSYour Name 		if (req->scan_req.scan_f_passive) {
996*5113495bSYour Name 			if (max_chan_time >= RRM_SCAN_MIN_DWELL_TIME) {
997*5113495bSYour Name 				req->scan_req.dwell_time_passive =
998*5113495bSYour Name 								max_chan_time;
999*5113495bSYour Name 				req->scan_req.dwell_time_passive_6g =
1000*5113495bSYour Name 								max_chan_time;
1001*5113495bSYour Name 			}
1002*5113495bSYour Name 			sme_debug("Passive Max Dwell Time(%d)",
1003*5113495bSYour Name 				  req->scan_req.dwell_time_passive);
1004*5113495bSYour Name 		} else {
1005*5113495bSYour Name 			if (max_chan_time >= RRM_SCAN_MIN_DWELL_TIME) {
1006*5113495bSYour Name 				req->scan_req.dwell_time_active = max_chan_time;
1007*5113495bSYour Name 				req->scan_req.dwell_time_active_2g =
1008*5113495bSYour Name 								max_chan_time;
1009*5113495bSYour Name 				req->scan_req.dwell_time_active_6g =
1010*5113495bSYour Name 								max_chan_time;
1011*5113495bSYour Name 			}
1012*5113495bSYour Name 			sme_debug("Active Max Dwell Time(%d) 2G Dwell time %d",
1013*5113495bSYour Name 				  req->scan_req.dwell_time_active,
1014*5113495bSYour Name 				  req->scan_req.dwell_time_active_2g);
1015*5113495bSYour Name 		}
1016*5113495bSYour Name 
1017*5113495bSYour Name 		req->scan_req.adaptive_dwell_time_mode = SCAN_DWELL_MODE_STATIC;
1018*5113495bSYour Name 		/*
1019*5113495bSYour Name 		 * For RRM scans timing is very important especially when the
1020*5113495bSYour Name 		 * request is for limited channels. There is no need for
1021*5113495bSYour Name 		 * firmware to rest for about 100-200 ms on the home channel.
1022*5113495bSYour Name 		 * Instead, it can start the scan right away which will make the
1023*5113495bSYour Name 		 * host to respond with the beacon report as quickly as
1024*5113495bSYour Name 		 * possible. Ensure that the scan requests are not back to back
1025*5113495bSYour Name 		 * and hence there is a check to see if the requests are atleast
1026*5113495bSYour Name 		 * 1 second apart.
1027*5113495bSYour Name 		 */
1028*5113495bSYour Name 		current_time = (uint64_t)qdf_mc_timer_get_system_time();
1029*5113495bSYour Name 		sme_debug("prev scan triggered before %llu ms, totalchannels %d",
1030*5113495bSYour Name 				current_time - rrm_scan_timer,
1031*5113495bSYour Name 				sme_rrm_ctx->channelList.numOfChannels);
1032*5113495bSYour Name 		if ((abs(current_time - rrm_scan_timer) > 1000) &&
1033*5113495bSYour Name 				(sme_rrm_ctx->channelList.numOfChannels == 1)) {
1034*5113495bSYour Name 			req->scan_req.max_rest_time = 1;
1035*5113495bSYour Name 			req->scan_req.min_rest_time = 1;
1036*5113495bSYour Name 			req->scan_req.idle_time = 1;
1037*5113495bSYour Name 		}
1038*5113495bSYour Name 
1039*5113495bSYour Name 		rrm_scan_timer = (uint64_t)qdf_mc_timer_get_system_time();
1040*5113495bSYour Name 
1041*5113495bSYour Name 		/* set requestType to full scan */
1042*5113495bSYour Name 		req->scan_req.chan_list.num_chan =
1043*5113495bSYour Name 			sme_rrm_ctx->channelList.numOfChannels;
1044*5113495bSYour Name 		buff_len = (QDF_MIN(req->scan_req.chan_list.num_chan,
1045*5113495bSYour Name 			    RRM_MAX_CHAN_TO_PRINT) * RRM_CHAN_WEIGHT_CHAR_LEN)
1046*5113495bSYour Name 			    + 1;
1047*5113495bSYour Name 		chan_buff = qdf_mem_malloc(buff_len);
1048*5113495bSYour Name 		if (!chan_buff) {
1049*5113495bSYour Name 			status = QDF_STATUS_E_NOMEM;
1050*5113495bSYour Name 			goto send_ind;
1051*5113495bSYour Name 		}
1052*5113495bSYour Name 		sme_debug("Number of chan %d active duration %d passive %d",
1053*5113495bSYour Name 			  req->scan_req.chan_list.num_chan,
1054*5113495bSYour Name 			  req->scan_req.dwell_time_active,
1055*5113495bSYour Name 			  req->scan_req.dwell_time_passive);
1056*5113495bSYour Name 
1057*5113495bSYour Name 		for (i = 0; i < req->scan_req.chan_list.num_chan; i++) {
1058*5113495bSYour Name 			req->scan_req.chan_list.chan[i].freq =
1059*5113495bSYour Name 			    (qdf_freq_t)sme_rrm_ctx->channelList.freq_list[i];
1060*5113495bSYour Name 			buff_num += qdf_scnprintf(chan_buff + buff_num,
1061*5113495bSYour Name 						  buff_len - buff_num, " %d",
1062*5113495bSYour Name 						  req->scan_req.chan_list.chan[i].freq);
1063*5113495bSYour Name 			chan_count++;
1064*5113495bSYour Name 			if (chan_count >= RRM_MAX_CHAN_TO_PRINT) {
1065*5113495bSYour Name 				sme_debug("RRM Scan Req for channels: %s",
1066*5113495bSYour Name 					  chan_buff);
1067*5113495bSYour Name 				buff_num = 0;
1068*5113495bSYour Name 				chan_count = 0;
1069*5113495bSYour Name 			}
1070*5113495bSYour Name 		}
1071*5113495bSYour Name 		if (buff_num)
1072*5113495bSYour Name 			sme_debug("RRM Freq scan req channels: %s", chan_buff);
1073*5113495bSYour Name 		qdf_mem_free(chan_buff);
1074*5113495bSYour Name 		/*
1075*5113495bSYour Name 		 * Fill RRM scan type for these requests. This is done
1076*5113495bSYour Name 		 * because in scan concurrency update params we update the
1077*5113495bSYour Name 		 * dwell time active which was not the expectation.
1078*5113495bSYour Name 		 * So doing a check of RRM scan request, we would not
1079*5113495bSYour Name 		 * update the dwell time.
1080*5113495bSYour Name 		 */
1081*5113495bSYour Name 		req->scan_req.scan_type = SCAN_TYPE_RRM;
1082*5113495bSYour Name 
1083*5113495bSYour Name 		status = wlan_scan_start(req);
1084*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
1085*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
1086*5113495bSYour Name 			goto send_ind;
1087*5113495bSYour Name 
1088*5113495bSYour Name 		return status;
1089*5113495bSYour Name 	} else if (eSIR_BEACON_TABLE == scan_type) {
1090*5113495bSYour Name 		/*
1091*5113495bSYour Name 		 * In beacon table mode, scan results are taken directly from
1092*5113495bSYour Name 		 * scan cache without issuing any scan request. So, it is not
1093*5113495bSYour Name 		 * proper to update rrm_scan_timer with latest time and hence
1094*5113495bSYour Name 		 * made it to zero to satisfy
1095*5113495bSYour Name 		 * pScanResult->timer >= rrm_scan_timer
1096*5113495bSYour Name 		 */
1097*5113495bSYour Name 		rrm_scan_timer = 0;
1098*5113495bSYour Name 		freq_list = sme_rrm_ctx->channelList.freq_list;
1099*5113495bSYour Name 		if (!freq_list) {
1100*5113495bSYour Name 			sme_err("[802.11 RRM]: Global freq list is null");
1101*5113495bSYour Name 			sme_reset_ese_bcn_req_in_progress(sme_rrm_ctx);
1102*5113495bSYour Name 			status = QDF_STATUS_E_FAILURE;
1103*5113495bSYour Name 			goto send_ind;
1104*5113495bSYour Name 		}
1105*5113495bSYour Name 
1106*5113495bSYour Name 		ch_idx = sme_rrm_ctx->currentIndex;
1107*5113495bSYour Name 		for (; ch_idx < sme_rrm_ctx->channelList.numOfChannels; ch_idx++) {
1108*5113495bSYour Name 			if ((ch_idx + 1) <
1109*5113495bSYour Name 			    sme_rrm_ctx->channelList.numOfChannels) {
1110*5113495bSYour Name 				sme_rrm_send_scan_result(mac_ctx, idx, 1,
1111*5113495bSYour Name 							 &freq_list[ch_idx],
1112*5113495bSYour Name 							 false);
1113*5113495bSYour Name 				/* Advance the current index. */
1114*5113495bSYour Name 				sme_rrm_ctx->currentIndex++;
1115*5113495bSYour Name 			} else {
1116*5113495bSYour Name 				/*
1117*5113495bSYour Name 				 * Done with the measurement. Clean up all
1118*5113495bSYour Name 				 * context and send a message to PE with
1119*5113495bSYour Name 				 * measurement done flag set.
1120*5113495bSYour Name 				 */
1121*5113495bSYour Name 				sme_rrm_send_scan_result(mac_ctx, idx, 1,
1122*5113495bSYour Name 							 &freq_list[ch_idx],
1123*5113495bSYour Name 							 true);
1124*5113495bSYour Name 				sme_reset_ese_bcn_req_in_progress(sme_rrm_ctx);
1125*5113495bSYour Name 				goto free_ch_lst;
1126*5113495bSYour Name 			}
1127*5113495bSYour Name 		}
1128*5113495bSYour Name 	}
1129*5113495bSYour Name 
1130*5113495bSYour Name 	sme_err("Unknown beacon report req mode(%d)", scan_type);
1131*5113495bSYour Name 	/*
1132*5113495bSYour Name 	 * Indicate measurement completion to PE
1133*5113495bSYour Name 	 * If this is not done, pCurrentReq pointer will not be freed
1134*5113495bSYour Name 	 * and PE will not handle subsequent Beacon requests
1135*5113495bSYour Name 	 */
1136*5113495bSYour Name send_ind:
1137*5113495bSYour Name 	sme_rrm_send_beacon_report_xmit_ind(mac_ctx, idx, NULL, true, 0);
1138*5113495bSYour Name free_ch_lst:
1139*5113495bSYour Name 	qdf_mem_free(sme_rrm_ctx->channelList.freq_list);
1140*5113495bSYour Name 	sme_rrm_ctx->channelList.freq_list = NULL;
1141*5113495bSYour Name 	sme_rrm_ctx->channelList.numOfChannels = 0;
1142*5113495bSYour Name 	return status;
1143*5113495bSYour Name }
1144*5113495bSYour Name 
sme_rrm_fill_scan_channels(struct mac_context * mac,uint8_t * country,tpRrmSMEContext sme_rrm_context,uint8_t op_class,uint32_t num_channels)1145*5113495bSYour Name static QDF_STATUS sme_rrm_fill_scan_channels(struct mac_context *mac,
1146*5113495bSYour Name 					     uint8_t *country,
1147*5113495bSYour Name 					     tpRrmSMEContext sme_rrm_context,
1148*5113495bSYour Name 					     uint8_t op_class,
1149*5113495bSYour Name 					     uint32_t num_channels)
1150*5113495bSYour Name {
1151*5113495bSYour Name 	uint32_t num_chan = 0;
1152*5113495bSYour Name 	uint32_t i;
1153*5113495bSYour Name 	uint32_t *freq_list;
1154*5113495bSYour Name 	bool found;
1155*5113495bSYour Name 
1156*5113495bSYour Name 	freq_list = sme_rrm_context->channelList.freq_list;
1157*5113495bSYour Name 	found = false;
1158*5113495bSYour Name 	for (i = 0; i < num_channels; i++) {
1159*5113495bSYour Name 		found = wlan_reg_is_freq_in_country_opclass(mac->pdev,
1160*5113495bSYour Name 							    country,
1161*5113495bSYour Name 							    op_class,
1162*5113495bSYour Name 							    freq_list[i]);
1163*5113495bSYour Name 		if (found) {
1164*5113495bSYour Name 			freq_list[num_chan] = freq_list[i];
1165*5113495bSYour Name 			num_chan++;
1166*5113495bSYour Name 		}
1167*5113495bSYour Name 		found = false;
1168*5113495bSYour Name 	}
1169*5113495bSYour Name 
1170*5113495bSYour Name 	sme_rrm_context->channelList.numOfChannels = num_chan;
1171*5113495bSYour Name 	if (sme_rrm_context->channelList.numOfChannels == 0) {
1172*5113495bSYour Name 		qdf_mem_free(sme_rrm_context->channelList.freq_list);
1173*5113495bSYour Name 		sme_rrm_context->channelList.freq_list = NULL;
1174*5113495bSYour Name 		sme_err_rl("No channels populated with requested operation class and current country, Hence abort the rrm operation");
1175*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1176*5113495bSYour Name 	}
1177*5113495bSYour Name 
1178*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1179*5113495bSYour Name }
1180*5113495bSYour Name 
sme_rrm_get_meas_mode_string(uint8_t meas_mode)1181*5113495bSYour Name static uint8_t *sme_rrm_get_meas_mode_string(uint8_t meas_mode)
1182*5113495bSYour Name {
1183*5113495bSYour Name 	switch (meas_mode) {
1184*5113495bSYour Name 		CASE_RETURN_STRING(eSIR_PASSIVE_SCAN);
1185*5113495bSYour Name 		CASE_RETURN_STRING(eSIR_ACTIVE_SCAN);
1186*5113495bSYour Name 		CASE_RETURN_STRING(eSIR_BEACON_TABLE);
1187*5113495bSYour Name 	default:
1188*5113495bSYour Name 		return (uint8_t *)"UNKNOWN";
1189*5113495bSYour Name 		break;
1190*5113495bSYour Name 	}
1191*5113495bSYour Name }
1192*5113495bSYour Name 
1193*5113495bSYour Name /**
1194*5113495bSYour Name  * sme_rrm_fill_freq_list_for_channel_load() : Trigger wide band scan request
1195*5113495bSYour Name  * to measure channel load
1196*5113495bSYour Name  * @mac_ctx: global mac structure
1197*5113495bSYour Name  * @sme_rrm_ctx: pointer to sme rrm context structure
1198*5113495bSYour Name  * @vdev: vdev common object
1199*5113495bSYour Name  * @req: scan request config
1200*5113495bSYour Name  *
1201*5113495bSYour Name  * Return : QDF_STATUS
1202*5113495bSYour Name  */
1203*5113495bSYour Name static QDF_STATUS
sme_rrm_fill_freq_list_for_channel_load(struct mac_context * mac_ctx,tpRrmSMEContext sme_rrm_ctx,struct wlan_objmgr_vdev * vdev,struct scan_start_request * req)1204*5113495bSYour Name sme_rrm_fill_freq_list_for_channel_load(struct mac_context *mac_ctx,
1205*5113495bSYour Name 					tpRrmSMEContext sme_rrm_ctx,
1206*5113495bSYour Name 					struct wlan_objmgr_vdev *vdev,
1207*5113495bSYour Name 					struct scan_start_request *req)
1208*5113495bSYour Name {
1209*5113495bSYour Name 	struct bw_ind_element *bw_ind;
1210*5113495bSYour Name 	struct wide_bw_chan_switch *wide_bw;
1211*5113495bSYour Name 	uint16_t c_space = 0;
1212*5113495bSYour Name 	uint8_t country_code[REG_ALPHA2_LEN + 1];
1213*5113495bSYour Name 	enum phy_ch_width chan_width = CH_WIDTH_INVALID;
1214*5113495bSYour Name 	qdf_freq_t scan_freq;
1215*5113495bSYour Name 	uint8_t channel = sme_rrm_ctx->chan_load_req_info.channel;
1216*5113495bSYour Name 	qdf_freq_t cen320_freq = 0;
1217*5113495bSYour Name 
1218*5113495bSYour Name 	rrm_get_country_code_from_connected_profile(mac_ctx,
1219*5113495bSYour Name 						    wlan_vdev_get_id(vdev),
1220*5113495bSYour Name 						    country_code);
1221*5113495bSYour Name 	scan_freq = wlan_reg_country_chan_opclass_to_freq(mac_ctx->pdev,
1222*5113495bSYour Name 							  country_code,
1223*5113495bSYour Name 							  channel,
1224*5113495bSYour Name 							  sme_rrm_ctx->regClass,
1225*5113495bSYour Name 							  false);
1226*5113495bSYour Name 	if (!scan_freq) {
1227*5113495bSYour Name 		sme_debug("invalid scan freq");
1228*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1229*5113495bSYour Name 	}
1230*5113495bSYour Name 
1231*5113495bSYour Name 	bw_ind = &sme_rrm_ctx->chan_load_req_info.bw_ind;
1232*5113495bSYour Name 	wide_bw = &sme_rrm_ctx->chan_load_req_info.wide_bw;
1233*5113495bSYour Name 	if (!bw_ind->is_bw_ind_element && !wide_bw->is_wide_bw_chan_switch) {
1234*5113495bSYour Name 		if (wlan_reg_is_6ghz_op_class(mac_ctx->pdev,
1235*5113495bSYour Name 					      sme_rrm_ctx->regClass))
1236*5113495bSYour Name 			c_space =
1237*5113495bSYour Name 			    wlan_reg_get_op_class_width(mac_ctx->pdev,
1238*5113495bSYour Name 							sme_rrm_ctx->regClass,
1239*5113495bSYour Name 							true);
1240*5113495bSYour Name 		else
1241*5113495bSYour Name 			c_space = wlan_reg_dmn_get_chanwidth_from_opclass_auto(
1242*5113495bSYour Name 							country_code,
1243*5113495bSYour Name 							channel,
1244*5113495bSYour Name 							sme_rrm_ctx->regClass);
1245*5113495bSYour Name 
1246*5113495bSYour Name 		sme_debug("op: %d, ch: %d freq:%d, cc %c%c 0x%x, c_space:%d",
1247*5113495bSYour Name 			  sme_rrm_ctx->regClass, channel, scan_freq,
1248*5113495bSYour Name 			  country_code[0], country_code[1], country_code[2],
1249*5113495bSYour Name 			  c_space);
1250*5113495bSYour Name 
1251*5113495bSYour Name 		switch (c_space) {
1252*5113495bSYour Name 		case 320:
1253*5113495bSYour Name 			fallthrough;
1254*5113495bSYour Name 		case 160:
1255*5113495bSYour Name 			chan_width = CH_WIDTH_160MHZ;
1256*5113495bSYour Name 			break;
1257*5113495bSYour Name 		case 80:
1258*5113495bSYour Name 			chan_width = CH_WIDTH_80MHZ;
1259*5113495bSYour Name 			break;
1260*5113495bSYour Name 		case 40:
1261*5113495bSYour Name 			chan_width = CH_WIDTH_40MHZ;
1262*5113495bSYour Name 			break;
1263*5113495bSYour Name 		case 20:
1264*5113495bSYour Name 		case 25:
1265*5113495bSYour Name 			chan_width = CH_WIDTH_20MHZ;
1266*5113495bSYour Name 			break;
1267*5113495bSYour Name 		default:
1268*5113495bSYour Name 			sme_err("invalid chan_space: %d", c_space);
1269*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
1270*5113495bSYour Name 		}
1271*5113495bSYour Name 	} else {
1272*5113495bSYour Name 		if (bw_ind->is_bw_ind_element) {
1273*5113495bSYour Name 			chan_width = bw_ind->channel_width;
1274*5113495bSYour Name 			cen320_freq = bw_ind->center_freq;
1275*5113495bSYour Name 		}
1276*5113495bSYour Name 
1277*5113495bSYour Name 		if (wide_bw->is_wide_bw_chan_switch)
1278*5113495bSYour Name 			chan_width = wide_bw->channel_width;
1279*5113495bSYour Name 	}
1280*5113495bSYour Name 
1281*5113495bSYour Name 	sme_rrm_ctx->chan_load_req_info.req_chan_width = chan_width;
1282*5113495bSYour Name 	return mlme_update_freq_in_scan_start_req(vdev, req, chan_width,
1283*5113495bSYour Name 						  scan_freq, cen320_freq);
1284*5113495bSYour Name }
1285*5113495bSYour Name 
1286*5113495bSYour Name /**
1287*5113495bSYour Name  * sme_rrm_issue_chan_load_measurement_scan() : Trigger wide band scan request
1288*5113495bSYour Name  * to measure channel load
1289*5113495bSYour Name  * @mac_ctx: global mac structure
1290*5113495bSYour Name  * @idx: measurement request index
1291*5113495bSYour Name  *
1292*5113495bSYour Name  * Return : QDF_STATUS
1293*5113495bSYour Name  */
1294*5113495bSYour Name static QDF_STATUS
sme_rrm_issue_chan_load_measurement_scan(struct mac_context * mac_ctx,uint8_t idx)1295*5113495bSYour Name sme_rrm_issue_chan_load_measurement_scan(struct mac_context *mac_ctx,
1296*5113495bSYour Name 					 uint8_t idx)
1297*5113495bSYour Name {
1298*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1299*5113495bSYour Name 	tpRrmSMEContext sme_rrm_ctx = &mac_ctx->rrm.rrmSmeContext[idx];
1300*5113495bSYour Name 	uint32_t max_chan_time;
1301*5113495bSYour Name 	struct scan_start_request *req;
1302*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1303*5113495bSYour Name 	uint32_t vdev_id;
1304*5113495bSYour Name 
1305*5113495bSYour Name 	status = csr_roam_get_session_id_from_bssid(mac_ctx,
1306*5113495bSYour Name 						    &sme_rrm_ctx->sessionBssId,
1307*5113495bSYour Name 						    &vdev_id);
1308*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
1309*5113495bSYour Name 		sme_err("sme session ID not found for bssid "QDF_MAC_ADDR_FMT"",
1310*5113495bSYour Name 			QDF_MAC_ADDR_REF(sme_rrm_ctx->sessionBssId.bytes));
1311*5113495bSYour Name 		goto send_ind;
1312*5113495bSYour Name 	}
1313*5113495bSYour Name 
1314*5113495bSYour Name 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, vdev_id,
1315*5113495bSYour Name 						    WLAN_LEGACY_SME_ID);
1316*5113495bSYour Name 	if (!vdev) {
1317*5113495bSYour Name 		sme_err("VDEV is null %d", vdev_id);
1318*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
1319*5113495bSYour Name 		goto send_ind;
1320*5113495bSYour Name 	}
1321*5113495bSYour Name 
1322*5113495bSYour Name 	req = qdf_mem_malloc(sizeof(*req));
1323*5113495bSYour Name 	if (!req) {
1324*5113495bSYour Name 		status = QDF_STATUS_E_NOMEM;
1325*5113495bSYour Name 		goto error_handle;
1326*5113495bSYour Name 	}
1327*5113495bSYour Name 
1328*5113495bSYour Name 	status = wlan_scan_init_default_params(vdev, req);
1329*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
1330*5113495bSYour Name 		goto error_handle;
1331*5113495bSYour Name 
1332*5113495bSYour Name 	req->scan_req.scan_id = wlan_scan_get_scan_id(mac_ctx->psoc);
1333*5113495bSYour Name 	sme_rrm_ctx->scan_id = req->scan_req.scan_id;
1334*5113495bSYour Name 	req->scan_req.vdev_id = wlan_vdev_get_id(vdev);
1335*5113495bSYour Name 	req->scan_req.scan_req_id = sme_rrm_ctx->req_id;
1336*5113495bSYour Name 	req->scan_req.scan_f_passive = true;
1337*5113495bSYour Name 	max_chan_time = sme_rrm_ctx->duration[0];
1338*5113495bSYour Name 	req->scan_req.dwell_time_passive = max_chan_time;
1339*5113495bSYour Name 	req->scan_req.dwell_time_passive_6g = max_chan_time;
1340*5113495bSYour Name 	req->scan_req.adaptive_dwell_time_mode = SCAN_DWELL_MODE_STATIC;
1341*5113495bSYour Name 	req->scan_req.scan_type = SCAN_TYPE_RRM;
1342*5113495bSYour Name 	req->scan_req.scan_f_wide_band = true;
1343*5113495bSYour Name 	/*
1344*5113495bSYour Name 	 * FW report CCA busy for each possible 20Mhz subbands of the
1345*5113495bSYour Name 	 * wideband scan channel if below flag is true
1346*5113495bSYour Name 	 */
1347*5113495bSYour Name 	req->scan_req.scan_f_report_cca_busy_for_each_20mhz = true;
1348*5113495bSYour Name 
1349*5113495bSYour Name 	status = sme_rrm_fill_freq_list_for_channel_load(mac_ctx, sme_rrm_ctx,
1350*5113495bSYour Name 							 vdev, req);
1351*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
1352*5113495bSYour Name 		goto error_handle;
1353*5113495bSYour Name 	sme_debug("vdev:%d, rrm_idx:%d scan_id:%d num chan: %d dwell_time: %d",
1354*5113495bSYour Name 		  req->scan_req.vdev_id, sme_rrm_ctx->measurement_idx,
1355*5113495bSYour Name 		  sme_rrm_ctx->scan_id,
1356*5113495bSYour Name 		  req->scan_req.chan_list.num_chan,
1357*5113495bSYour Name 		  req->scan_req.dwell_time_passive);
1358*5113495bSYour Name 	/* store jiffies to send it in channel load report */
1359*5113495bSYour Name 	sme_rrm_ctx->chan_load_req_info.rrm_scan_tsf =
1360*5113495bSYour Name 				(uint32_t)qdf_system_ticks();
1361*5113495bSYour Name 	status = wlan_scan_start(req);
1362*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
1363*5113495bSYour Name 		goto error_handle;
1364*5113495bSYour Name 
1365*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
1366*5113495bSYour Name 	return status;
1367*5113495bSYour Name error_handle:
1368*5113495bSYour Name 	qdf_mem_free(req);
1369*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
1370*5113495bSYour Name send_ind:
1371*5113495bSYour Name 	sme_rrm_send_chan_load_report_xmit_ind(mac_ctx, sme_rrm_ctx,
1372*5113495bSYour Name 					       vdev_id, false);
1373*5113495bSYour Name 	rrm_cleanup(mac_ctx, idx);
1374*5113495bSYour Name 	return status;
1375*5113495bSYour Name }
1376*5113495bSYour Name 
1377*5113495bSYour Name /**
1378*5113495bSYour Name  * sme_rrm_process_chan_load_req_ind() -Process beacon report request
1379*5113495bSYour Name  * @mac: Global Mac structure
1380*5113495bSYour Name  * @msg_buf: a pointer to a buffer that maps to various structures base
1381*5113495bSYour Name  * on the message type.The beginning of the buffer can always
1382*5113495bSYour Name  * map to tSirSmeRsp.
1383*5113495bSYour Name  *
1384*5113495bSYour Name  * This is called to process the channel load report request from peer AP
1385*5113495bSYour Name  * forwarded through PE .
1386*5113495bSYour Name  *
1387*5113495bSYour Name  * Return : QDF_STATUS_SUCCESS - Validation is successful.
1388*5113495bSYour Name  */
sme_rrm_process_chan_load_req_ind(struct mac_context * mac,void * msg_buf)1389*5113495bSYour Name static QDF_STATUS sme_rrm_process_chan_load_req_ind(struct mac_context *mac,
1390*5113495bSYour Name 						    void *msg_buf)
1391*5113495bSYour Name {
1392*5113495bSYour Name 	struct ch_load_ind *chan_load;
1393*5113495bSYour Name 	tpRrmSMEContext sme_rrm_ctx;
1394*5113495bSYour Name 	tpRrmPEContext rrm_ctx;
1395*5113495bSYour Name 	struct channel_load_req_info *req_info;
1396*5113495bSYour Name 
1397*5113495bSYour Name 	chan_load = (struct ch_load_ind *)msg_buf;
1398*5113495bSYour Name 	sme_rrm_ctx = &mac->rrm.rrmSmeContext[chan_load->measurement_idx];
1399*5113495bSYour Name 	rrm_ctx = &mac->rrm.rrmPEContext;
1400*5113495bSYour Name 	qdf_mem_copy(sme_rrm_ctx->sessionBssId.bytes,
1401*5113495bSYour Name 		     chan_load->peer_addr.bytes, sizeof(struct qdf_mac_addr));
1402*5113495bSYour Name 
1403*5113495bSYour Name 	sme_rrm_ctx->token = chan_load->dialog_token;
1404*5113495bSYour Name 	sme_rrm_ctx->regClass = chan_load->op_class;
1405*5113495bSYour Name 	sme_rrm_ctx->randnIntvl = QDF_MAX(chan_load->randomization_intv,
1406*5113495bSYour Name 			mac->rrm.rrmConfig.max_randn_interval);
1407*5113495bSYour Name 	sme_rrm_ctx->currentIndex = 0;
1408*5113495bSYour Name 	qdf_mem_copy((uint8_t *)&sme_rrm_ctx->duration,
1409*5113495bSYour Name 		     (uint8_t *)&chan_load->meas_duration,
1410*5113495bSYour Name 		     SIR_ESE_MAX_MEAS_IE_REQS);
1411*5113495bSYour Name 	sme_rrm_ctx->measurement_type = RRM_CHANNEL_LOAD;
1412*5113495bSYour Name 	req_info = &sme_rrm_ctx->chan_load_req_info;
1413*5113495bSYour Name 	req_info->channel = chan_load->channel;
1414*5113495bSYour Name 	req_info->req_freq = chan_load->req_freq;
1415*5113495bSYour Name 
1416*5113495bSYour Name 	qdf_mem_copy(&req_info->bw_ind, &chan_load->bw_ind,
1417*5113495bSYour Name 		     sizeof(req_info->bw_ind));
1418*5113495bSYour Name 	qdf_mem_copy(&req_info->wide_bw, &chan_load->wide_bw,
1419*5113495bSYour Name 		     sizeof(req_info->wide_bw));
1420*5113495bSYour Name 
1421*5113495bSYour Name 	sme_debug("idx:%d, token: %d randnIntvl: %d meas_duration %d, rrm_ctx dur %d reg_class: %d, type: %d, channel: %d, freq: %d, [bw_ind present: %d, cw: %d, ccfs0: %d], [wide_bw present: %d, cw: %d]",
1422*5113495bSYour Name 		  chan_load->measurement_idx, sme_rrm_ctx->token,
1423*5113495bSYour Name 		  sme_rrm_ctx->randnIntvl,
1424*5113495bSYour Name 		  chan_load->meas_duration,
1425*5113495bSYour Name 		  sme_rrm_ctx->duration[0], sme_rrm_ctx->regClass,
1426*5113495bSYour Name 		  sme_rrm_ctx->measurement_type,
1427*5113495bSYour Name 		  req_info->channel, req_info->req_freq,
1428*5113495bSYour Name 		  req_info->bw_ind.is_bw_ind_element,
1429*5113495bSYour Name 		  req_info->bw_ind.channel_width,
1430*5113495bSYour Name 		  req_info->bw_ind.center_freq,
1431*5113495bSYour Name 		  req_info->wide_bw.is_wide_bw_chan_switch,
1432*5113495bSYour Name 		  req_info->wide_bw.channel_width);
1433*5113495bSYour Name 
1434*5113495bSYour Name 	return sme_rrm_issue_chan_load_measurement_scan(mac,
1435*5113495bSYour Name 						chan_load->measurement_idx);
1436*5113495bSYour Name }
1437*5113495bSYour Name 
1438*5113495bSYour Name /**
1439*5113495bSYour Name  * sme_rrm_process_beacon_report_req_ind() -Process beacon report request
1440*5113495bSYour Name  * @mac:- Global Mac structure
1441*5113495bSYour Name  * @msg_buf:- a pointer to a buffer that maps to various structures base
1442*5113495bSYour Name  *                  on the message type.The beginning of the buffer can always
1443*5113495bSYour Name  *                  map to tSirSmeRsp.
1444*5113495bSYour Name  *
1445*5113495bSYour Name  * This is called to process the Beacon
1446*5113495bSYour Name  * report request from peer AP forwarded through PE .
1447*5113495bSYour Name  *
1448*5113495bSYour Name  * Return : QDF_STATUS_SUCCESS - Validation is successful.
1449*5113495bSYour Name  */
sme_rrm_process_beacon_report_req_ind(struct mac_context * mac,void * msg_buf)1450*5113495bSYour Name QDF_STATUS sme_rrm_process_beacon_report_req_ind(struct mac_context *mac,
1451*5113495bSYour Name 						 void *msg_buf)
1452*5113495bSYour Name {
1453*5113495bSYour Name 	tpSirBeaconReportReqInd beacon_req = (tpSirBeaconReportReqInd)msg_buf;
1454*5113495bSYour Name 	tpRrmSMEContext sme_rrm_ctx;
1455*5113495bSYour Name 	uint32_t len = 0, i = 0, j = 0;
1456*5113495bSYour Name 	uint8_t country[WNI_CFG_COUNTRY_CODE_LEN];
1457*5113495bSYour Name 	uint32_t session_id;
1458*5113495bSYour Name 	struct csr_roam_session *session;
1459*5113495bSYour Name 	QDF_STATUS status;
1460*5113495bSYour Name 	uint32_t num_chan, local_num_channel;
1461*5113495bSYour Name 	bool chan_valid;
1462*5113495bSYour Name 	uint32_t *rrm_freq_list, *local_rrm_freq_list;
1463*5113495bSYour Name 	uint32_t bcn_chan_freq, local_bcn_chan_freq;
1464*5113495bSYour Name 	tpRrmPEContext rrm_ctx;
1465*5113495bSYour Name 
1466*5113495bSYour Name 	sme_rrm_ctx = &mac->rrm.rrmSmeContext[beacon_req->measurement_idx];
1467*5113495bSYour Name 	rrm_ctx = &mac->rrm.rrmPEContext;
1468*5113495bSYour Name 
1469*5113495bSYour Name 	status = csr_roam_get_session_id_from_bssid(mac, (struct qdf_mac_addr *)
1470*5113495bSYour Name 						    beacon_req->bssId,
1471*5113495bSYour Name 						    &session_id);
1472*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
1473*5113495bSYour Name 		sme_err("sme session ID not found for bssid");
1474*5113495bSYour Name 		goto cleanup;
1475*5113495bSYour Name 	}
1476*5113495bSYour Name 
1477*5113495bSYour Name 	session = CSR_GET_SESSION(mac, session_id);
1478*5113495bSYour Name 	if (!session) {
1479*5113495bSYour Name 		sme_err("Invalid session id %d", session_id);
1480*5113495bSYour Name 		status = QDF_STATUS_E_FAILURE;
1481*5113495bSYour Name 		goto cleanup;
1482*5113495bSYour Name 	}
1483*5113495bSYour Name 
1484*5113495bSYour Name 	rrm_get_country_code_from_connected_profile(mac, session_id, country);
1485*5113495bSYour Name 
1486*5113495bSYour Name 	if (wlan_reg_is_6ghz_op_class(mac->pdev,
1487*5113495bSYour Name 				      beacon_req->channel_info.reg_class))
1488*5113495bSYour Name 		country[2] = OP_CLASS_GLOBAL;
1489*5113495bSYour Name 
1490*5113495bSYour Name 	sme_debug("RRM_SCN: Index:%d Request Reg class %d, AP's country code %c%c 0x%x, channel = %d",
1491*5113495bSYour Name 		  beacon_req->measurement_idx,
1492*5113495bSYour Name 		  beacon_req->channel_info.reg_class,
1493*5113495bSYour Name 		  country[0], country[1], country[2],
1494*5113495bSYour Name 		  beacon_req->channel_info.chan_num);
1495*5113495bSYour Name 
1496*5113495bSYour Name 	if (beacon_req->channel_list.num_channels > SIR_ESE_MAX_MEAS_IE_REQS) {
1497*5113495bSYour Name 		sme_err("Beacon report request numChannels:%u exceeds max num channels",
1498*5113495bSYour Name 			beacon_req->channel_list.num_channels);
1499*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
1500*5113495bSYour Name 		goto cleanup;
1501*5113495bSYour Name 	}
1502*5113495bSYour Name 
1503*5113495bSYour Name 	/* section 11.10.8.1 (IEEE Std 802.11k-2008) */
1504*5113495bSYour Name 	/* channel 0 and 255 has special meaning. */
1505*5113495bSYour Name 	if ((beacon_req->channel_info.chan_num == 0) ||
1506*5113495bSYour Name 	    ((beacon_req->channel_info.chan_num == 255) &&
1507*5113495bSYour Name 	     (beacon_req->channel_list.num_channels == 0))) {
1508*5113495bSYour Name 		/* Add all the channel in the regulatory domain. */
1509*5113495bSYour Name 		len = mac->mlme_cfg->reg.valid_channel_list_num;
1510*5113495bSYour Name 		if (sme_rrm_ctx->channelList.freq_list) {
1511*5113495bSYour Name 			qdf_mem_free(sme_rrm_ctx->channelList.freq_list);
1512*5113495bSYour Name 			sme_rrm_ctx->channelList.freq_list = NULL;
1513*5113495bSYour Name 		}
1514*5113495bSYour Name 		sme_rrm_ctx->channelList.freq_list =
1515*5113495bSYour Name 			qdf_mem_malloc(sizeof(uint32_t) * len);
1516*5113495bSYour Name 		if (!sme_rrm_ctx->channelList.freq_list) {
1517*5113495bSYour Name 			status = QDF_STATUS_E_NOMEM;
1518*5113495bSYour Name 			sme_rrm_ctx->channelList.numOfChannels = 0;
1519*5113495bSYour Name 			goto cleanup;
1520*5113495bSYour Name 		}
1521*5113495bSYour Name 
1522*5113495bSYour Name 		csr_get_cfg_valid_channels(
1523*5113495bSYour Name 			mac, sme_rrm_ctx->channelList.freq_list, &len);
1524*5113495bSYour Name 
1525*5113495bSYour Name 		if (beacon_req->channel_info.reg_class) {
1526*5113495bSYour Name 			if (sme_rrm_fill_scan_channels(
1527*5113495bSYour Name 				mac, country, sme_rrm_ctx,
1528*5113495bSYour Name 				beacon_req->channel_info.reg_class, len) !=
1529*5113495bSYour Name 			    QDF_STATUS_SUCCESS)
1530*5113495bSYour Name 				goto cleanup;
1531*5113495bSYour Name 		} else {
1532*5113495bSYour Name 			sme_rrm_ctx->channelList.numOfChannels = len;
1533*5113495bSYour Name 		}
1534*5113495bSYour Name 	} else {
1535*5113495bSYour Name 		len = 0;
1536*5113495bSYour Name 		sme_rrm_ctx->channelList.numOfChannels = 0;
1537*5113495bSYour Name 		num_chan = 0;
1538*5113495bSYour Name 
1539*5113495bSYour Name 		/* If valid channel is present. We first Measure on the given
1540*5113495bSYour Name 		 * channel and if there are additional channels present in
1541*5113495bSYour Name 		 * APchannelreport, measure on these also.
1542*5113495bSYour Name 		 */
1543*5113495bSYour Name 		if (beacon_req->channel_info.chan_num != 255)
1544*5113495bSYour Name 			len = 1;
1545*5113495bSYour Name 
1546*5113495bSYour Name 		len += beacon_req->channel_list.num_channels;
1547*5113495bSYour Name 
1548*5113495bSYour Name 		if (sme_rrm_ctx->channelList.freq_list) {
1549*5113495bSYour Name 			qdf_mem_free(sme_rrm_ctx->channelList.freq_list);
1550*5113495bSYour Name 			sme_rrm_ctx->channelList.freq_list = NULL;
1551*5113495bSYour Name 		}
1552*5113495bSYour Name 		sme_rrm_ctx->channelList.freq_list =
1553*5113495bSYour Name 			qdf_mem_malloc(sizeof(uint32_t) * len);
1554*5113495bSYour Name 		if (!sme_rrm_ctx->channelList.freq_list) {
1555*5113495bSYour Name 			sme_rrm_ctx->channelList.numOfChannels = 0;
1556*5113495bSYour Name 			status = QDF_STATUS_E_NOMEM;
1557*5113495bSYour Name 			goto cleanup;
1558*5113495bSYour Name 		}
1559*5113495bSYour Name 
1560*5113495bSYour Name 		rrm_freq_list = sme_rrm_ctx->channelList.freq_list;
1561*5113495bSYour Name 		bcn_chan_freq = beacon_req->channel_info.chan_freq;
1562*5113495bSYour Name 
1563*5113495bSYour Name 		if (beacon_req->channel_info.chan_num != 255) {
1564*5113495bSYour Name 			chan_valid =
1565*5113495bSYour Name 				wlan_roam_is_channel_valid(&mac->mlme_cfg->reg,
1566*5113495bSYour Name 							   bcn_chan_freq);
1567*5113495bSYour Name 
1568*5113495bSYour Name 			if (chan_valid) {
1569*5113495bSYour Name 				rrm_freq_list[num_chan] = bcn_chan_freq;
1570*5113495bSYour Name 				num_chan++;
1571*5113495bSYour Name 			} else {
1572*5113495bSYour Name 				sme_err("Invalid channel: %d",
1573*5113495bSYour Name 					beacon_req->channel_info.chan_num);
1574*5113495bSYour Name 			}
1575*5113495bSYour Name 		}
1576*5113495bSYour Name 
1577*5113495bSYour Name 		for (i = 0; i < beacon_req->channel_list.num_channels; i++) {
1578*5113495bSYour Name 			bcn_chan_freq =
1579*5113495bSYour Name 				beacon_req->channel_list.chan_freq_lst[i];
1580*5113495bSYour Name 			chan_valid =
1581*5113495bSYour Name 				wlan_roam_is_channel_valid(&mac->mlme_cfg->reg,
1582*5113495bSYour Name 							   bcn_chan_freq);
1583*5113495bSYour Name 
1584*5113495bSYour Name 			if (chan_valid) {
1585*5113495bSYour Name 				rrm_freq_list[num_chan] = bcn_chan_freq;
1586*5113495bSYour Name 				num_chan++;
1587*5113495bSYour Name 			}
1588*5113495bSYour Name 		}
1589*5113495bSYour Name 
1590*5113495bSYour Name 		sme_rrm_ctx->channelList.numOfChannels = num_chan;
1591*5113495bSYour Name 	}
1592*5113495bSYour Name 
1593*5113495bSYour Name 	local_rrm_freq_list = sme_rrm_ctx->channelList.freq_list;
1594*5113495bSYour Name 	local_num_channel = 0;
1595*5113495bSYour Name 	for (i = 0; i < sme_rrm_ctx->channelList.numOfChannels; i++) {
1596*5113495bSYour Name 		local_bcn_chan_freq = local_rrm_freq_list[i];
1597*5113495bSYour Name 		chan_valid = true;
1598*5113495bSYour Name 
1599*5113495bSYour Name 		if (beacon_req->measurement_idx > 0) {
1600*5113495bSYour Name 			for (j = 0; j < rrm_ctx->beacon_rpt_chan_num; j++) {
1601*5113495bSYour Name 				if (rrm_ctx->beacon_rpt_chan_list[j] ==
1602*5113495bSYour Name 				    local_bcn_chan_freq) {
1603*5113495bSYour Name 				/*
1604*5113495bSYour Name 				 * Ignore this channel, As this is already
1605*5113495bSYour Name 				 * included in previous request
1606*5113495bSYour Name 				 */
1607*5113495bSYour Name 					chan_valid = false;
1608*5113495bSYour Name 					break;
1609*5113495bSYour Name 				}
1610*5113495bSYour Name 			}
1611*5113495bSYour Name 		}
1612*5113495bSYour Name 
1613*5113495bSYour Name 		if (chan_valid) {
1614*5113495bSYour Name 			uint8_t beacon_rpt_chan_num;
1615*5113495bSYour Name 
1616*5113495bSYour Name 			beacon_rpt_chan_num = rrm_ctx->beacon_rpt_chan_num;
1617*5113495bSYour Name 			rrm_ctx->beacon_rpt_chan_list[beacon_rpt_chan_num] =
1618*5113495bSYour Name 						local_bcn_chan_freq;
1619*5113495bSYour Name 			rrm_ctx->beacon_rpt_chan_num++;
1620*5113495bSYour Name 
1621*5113495bSYour Name 			if (rrm_ctx->beacon_rpt_chan_num >=
1622*5113495bSYour Name 			    MAX_NUM_CHANNELS) {
1623*5113495bSYour Name 			    /* this should never happen */
1624*5113495bSYour Name 				sme_err("Reset beacon_rpt_chan_num : %d",
1625*5113495bSYour Name 					rrm_ctx->beacon_rpt_chan_num);
1626*5113495bSYour Name 				rrm_ctx->beacon_rpt_chan_num = 0;
1627*5113495bSYour Name 			}
1628*5113495bSYour Name 			local_rrm_freq_list[local_num_channel] =
1629*5113495bSYour Name 							local_bcn_chan_freq;
1630*5113495bSYour Name 			local_num_channel++;
1631*5113495bSYour Name 		}
1632*5113495bSYour Name 	}
1633*5113495bSYour Name 
1634*5113495bSYour Name 	if (local_num_channel == 0)
1635*5113495bSYour Name 		goto cleanup;
1636*5113495bSYour Name 
1637*5113495bSYour Name 	sme_rrm_ctx->channelList.numOfChannels = local_num_channel;
1638*5113495bSYour Name 
1639*5113495bSYour Name 	/* Copy session bssid */
1640*5113495bSYour Name 	qdf_mem_copy(sme_rrm_ctx->sessionBssId.bytes, beacon_req->bssId,
1641*5113495bSYour Name 		     sizeof(tSirMacAddr));
1642*5113495bSYour Name 
1643*5113495bSYour Name 	/* copy measurement bssid */
1644*5113495bSYour Name 	qdf_mem_copy(sme_rrm_ctx->bssId, beacon_req->macaddrBssid,
1645*5113495bSYour Name 		     sizeof(tSirMacAddr));
1646*5113495bSYour Name 
1647*5113495bSYour Name 	/* Copy ssid */
1648*5113495bSYour Name 	qdf_mem_copy(&sme_rrm_ctx->ssId, &beacon_req->ssId,
1649*5113495bSYour Name 		     sizeof(tAniSSID));
1650*5113495bSYour Name 
1651*5113495bSYour Name 	sme_rrm_ctx->token = beacon_req->uDialogToken;
1652*5113495bSYour Name 	sme_rrm_ctx->regClass = beacon_req->channel_info.reg_class;
1653*5113495bSYour Name 	sme_rrm_ctx->randnIntvl =
1654*5113495bSYour Name 		QDF_MAX(beacon_req->randomizationInterval,
1655*5113495bSYour Name 			mac->rrm.rrmConfig.max_randn_interval);
1656*5113495bSYour Name 	sme_rrm_ctx->currentIndex = 0;
1657*5113495bSYour Name 	sme_rrm_ctx->msgSource = beacon_req->msgSource;
1658*5113495bSYour Name 	qdf_mem_copy((uint8_t *)&sme_rrm_ctx->measMode,
1659*5113495bSYour Name 		     (uint8_t *)&beacon_req->fMeasurementtype,
1660*5113495bSYour Name 		     SIR_ESE_MAX_MEAS_IE_REQS);
1661*5113495bSYour Name 	qdf_mem_copy((uint8_t *)&sme_rrm_ctx->duration,
1662*5113495bSYour Name 		     (uint8_t *)&beacon_req->measurementDuration,
1663*5113495bSYour Name 		     SIR_ESE_MAX_MEAS_IE_REQS);
1664*5113495bSYour Name 
1665*5113495bSYour Name 	sme_rrm_ctx->measurement_type = RRM_BEACON_REPORT;
1666*5113495bSYour Name 
1667*5113495bSYour Name 	sme_debug("token: %d randnIntvl: %d msgSource: %d measurementduration %d, rrm_ctx duration %d Meas_mode: %s, type: %d",
1668*5113495bSYour Name 		  sme_rrm_ctx->token, sme_rrm_ctx->randnIntvl,
1669*5113495bSYour Name 		  sme_rrm_ctx->msgSource, beacon_req->measurementDuration[0],
1670*5113495bSYour Name 		  sme_rrm_ctx->duration[0],
1671*5113495bSYour Name 		  sme_rrm_get_meas_mode_string(sme_rrm_ctx->measMode[0]),
1672*5113495bSYour Name 		  sme_rrm_ctx->measurement_type);
1673*5113495bSYour Name 
1674*5113495bSYour Name 	return sme_rrm_issue_scan_req(mac, beacon_req->measurement_idx);
1675*5113495bSYour Name 
1676*5113495bSYour Name cleanup:
1677*5113495bSYour Name 	if (beacon_req->msgSource == eRRM_MSG_SOURCE_11K) {
1678*5113495bSYour Name 		/* Copy session bssid */
1679*5113495bSYour Name 		qdf_mem_copy(sme_rrm_ctx->sessionBssId.bytes,
1680*5113495bSYour Name 			     beacon_req->bssId, sizeof(tSirMacAddr));
1681*5113495bSYour Name 
1682*5113495bSYour Name 		/* copy measurement bssid */
1683*5113495bSYour Name 		qdf_mem_copy(sme_rrm_ctx->bssId, beacon_req->macaddrBssid,
1684*5113495bSYour Name 			     sizeof(tSirMacAddr));
1685*5113495bSYour Name 		sme_rrm_ctx->token = beacon_req->uDialogToken;
1686*5113495bSYour Name 		sme_rrm_ctx->regClass =
1687*5113495bSYour Name 			beacon_req->channel_info.reg_class;
1688*5113495bSYour Name 		sme_rrm_ctx->randnIntvl =
1689*5113495bSYour Name 			QDF_MAX(beacon_req->randomizationInterval,
1690*5113495bSYour Name 			mac->rrm.rrmConfig.max_randn_interval);
1691*5113495bSYour Name 
1692*5113495bSYour Name 		sme_rrm_send_beacon_report_xmit_ind(mac,
1693*5113495bSYour Name 			     sme_rrm_ctx->measurement_idx, NULL, true, 0);
1694*5113495bSYour Name 	}
1695*5113495bSYour Name 
1696*5113495bSYour Name 	return status;
1697*5113495bSYour Name }
1698*5113495bSYour Name 
1699*5113495bSYour Name /**
1700*5113495bSYour Name  * sme_rrm_neighbor_report_request() - This is API can be used to trigger a
1701*5113495bSYour Name  *        Neighbor report from the peer.
1702*5113495bSYour Name  * @sessionId: session identifier on which the request should be made.
1703*5113495bSYour Name  * @pNeighborReq: a pointer to a neighbor report request.
1704*5113495bSYour Name  *
1705*5113495bSYour Name  * This is API can be used to trigger a  Neighbor report from the peer.
1706*5113495bSYour Name  *
1707*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS - Validation is successful.
1708*5113495bSYour Name  */
sme_rrm_neighbor_report_request(struct mac_context * mac,uint8_t sessionId,tpRrmNeighborReq pNeighborReq,tpRrmNeighborRspCallbackInfo callbackInfo)1709*5113495bSYour Name QDF_STATUS sme_rrm_neighbor_report_request(struct mac_context *mac, uint8_t
1710*5113495bSYour Name 					sessionId, tpRrmNeighborReq
1711*5113495bSYour Name 					pNeighborReq,
1712*5113495bSYour Name 					tpRrmNeighborRspCallbackInfo
1713*5113495bSYour Name 					callbackInfo)
1714*5113495bSYour Name {
1715*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1716*5113495bSYour Name 	tpSirNeighborReportReqInd pMsg;
1717*5113495bSYour Name 
1718*5113495bSYour Name 	sme_debug("Request to send Neighbor report request received ");
1719*5113495bSYour Name 	if (!CSR_IS_SESSION_VALID(mac, sessionId)) {
1720*5113495bSYour Name 		sme_err("Invalid session %d", sessionId);
1721*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1722*5113495bSYour Name 	}
1723*5113495bSYour Name 
1724*5113495bSYour Name 	/* If already a report is pending, return failure */
1725*5113495bSYour Name 	if (true ==
1726*5113495bSYour Name 	    mac->rrm.rrmSmeContext[0].neighborReqControlInfo.
1727*5113495bSYour Name 	    isNeighborRspPending) {
1728*5113495bSYour Name 		sme_err("Neighbor request already pending.. Not allowed");
1729*5113495bSYour Name 		return QDF_STATUS_E_AGAIN;
1730*5113495bSYour Name 	}
1731*5113495bSYour Name 
1732*5113495bSYour Name 	pMsg = qdf_mem_malloc(sizeof(tSirNeighborReportReqInd));
1733*5113495bSYour Name 	if (!pMsg)
1734*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
1735*5113495bSYour Name 
1736*5113495bSYour Name 	rrm_ll_purge_neighbor_cache(mac,
1737*5113495bSYour Name 			    &mac->rrm.rrmSmeContext[0].neighborReportCache);
1738*5113495bSYour Name 
1739*5113495bSYour Name 	pMsg->messageType = eWNI_SME_NEIGHBOR_REPORT_REQ_IND;
1740*5113495bSYour Name 	pMsg->length = sizeof(tSirNeighborReportReqInd);
1741*5113495bSYour Name 	wlan_mlme_get_bssid_vdev_id(mac->pdev, sessionId,
1742*5113495bSYour Name 				    (struct qdf_mac_addr *)&pMsg->bssId);
1743*5113495bSYour Name 	pMsg->noSSID = pNeighborReq->no_ssid;
1744*5113495bSYour Name 	qdf_mem_copy(&pMsg->ucSSID, &pNeighborReq->ssid, sizeof(tSirMacSSid));
1745*5113495bSYour Name 
1746*5113495bSYour Name 	status = umac_send_mb_message_to_mac(pMsg);
1747*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS)
1748*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1749*5113495bSYour Name 
1750*5113495bSYour Name 	/* Neighbor report request message sent successfully to PE.
1751*5113495bSYour Name 	 * Now register the callbacks
1752*5113495bSYour Name 	 */
1753*5113495bSYour Name 	mac->rrm.rrmSmeContext[0].neighborReqControlInfo.
1754*5113495bSYour Name 		neighborRspCallbackInfo.neighborRspCallback =
1755*5113495bSYour Name 			callbackInfo->neighborRspCallback;
1756*5113495bSYour Name 	mac->rrm.rrmSmeContext[0].neighborReqControlInfo.
1757*5113495bSYour Name 		neighborRspCallbackInfo.neighborRspCallbackContext =
1758*5113495bSYour Name 			callbackInfo->neighborRspCallbackContext;
1759*5113495bSYour Name 	mac->rrm.rrmSmeContext[0].neighborReqControlInfo.isNeighborRspPending =
1760*5113495bSYour Name 		true;
1761*5113495bSYour Name 
1762*5113495bSYour Name 	/* Start neighbor response wait timer now */
1763*5113495bSYour Name 	qdf_mc_timer_start(&mac->rrm.rrmSmeContext[0].neighborReqControlInfo.
1764*5113495bSYour Name 			   neighborRspWaitTimer, callbackInfo->timeout);
1765*5113495bSYour Name 
1766*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1767*5113495bSYour Name }
1768*5113495bSYour Name 
1769*5113495bSYour Name /**
1770*5113495bSYour Name  * rrm_calculate_neighbor_ap_roam_score() - calculates roam score
1771*5113495bSYour Name  * @mac_ctx:                mac global context
1772*5113495bSYour Name  * @pNeighborReportDesc:    Neighbor BSS Descriptor node for which roam score
1773*5113495bSYour Name  *                          should be calculated
1774*5113495bSYour Name  *
1775*5113495bSYour Name  * This API is called while handling individual neighbor reports from the APs
1776*5113495bSYour Name  * neighbor AP report to calculate the cumulative roam score before storing it
1777*5113495bSYour Name  * in neighbor cache.
1778*5113495bSYour Name  *
1779*5113495bSYour Name  * Return: void
1780*5113495bSYour Name  */
1781*5113495bSYour Name static void
rrm_calculate_neighbor_ap_roam_score(struct mac_context * mac_ctx,tpRrmNeighborReportDesc nbr_report_desc)1782*5113495bSYour Name rrm_calculate_neighbor_ap_roam_score(struct mac_context *mac_ctx,
1783*5113495bSYour Name 				tpRrmNeighborReportDesc nbr_report_desc)
1784*5113495bSYour Name {
1785*5113495bSYour Name 	tpSirNeighborBssDescripton nbr_bss_desc;
1786*5113495bSYour Name 	uint32_t roam_score = 0;
1787*5113495bSYour Name #ifdef FEATURE_WLAN_ESE
1788*5113495bSYour Name 	uint8_t session_id;
1789*5113495bSYour Name 	struct cm_roam_values_copy config;
1790*5113495bSYour Name #endif
1791*5113495bSYour Name 
1792*5113495bSYour Name 	if (!nbr_report_desc) {
1793*5113495bSYour Name 		QDF_ASSERT(0);
1794*5113495bSYour Name 		return;
1795*5113495bSYour Name 	}
1796*5113495bSYour Name 
1797*5113495bSYour Name 	if (!nbr_report_desc->pNeighborBssDescription) {
1798*5113495bSYour Name 		QDF_ASSERT(0);
1799*5113495bSYour Name 		return;
1800*5113495bSYour Name 	}
1801*5113495bSYour Name 
1802*5113495bSYour Name 	nbr_bss_desc = nbr_report_desc->pNeighborBssDescription;
1803*5113495bSYour Name 	if (!nbr_bss_desc->bssidInfo.rrmInfo.fMobilityDomain)
1804*5113495bSYour Name 		goto check_11r_assoc;
1805*5113495bSYour Name 
1806*5113495bSYour Name 	roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_MOBILITY_DOMAIN;
1807*5113495bSYour Name 	if (!nbr_bss_desc->bssidInfo.rrmInfo.fSameSecurityMode)
1808*5113495bSYour Name 		goto check_11r_assoc;
1809*5113495bSYour Name 
1810*5113495bSYour Name 	roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_SECURITY;
1811*5113495bSYour Name 	if (!nbr_bss_desc->bssidInfo.rrmInfo.fSameAuthenticator)
1812*5113495bSYour Name 		goto check_11r_assoc;
1813*5113495bSYour Name 
1814*5113495bSYour Name 	roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_KEY_SCOPE;
1815*5113495bSYour Name 	if (!nbr_bss_desc->bssidInfo.rrmInfo.fCapRadioMeasurement)
1816*5113495bSYour Name 		goto check_11r_assoc;
1817*5113495bSYour Name 
1818*5113495bSYour Name 	roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_RRM;
1819*5113495bSYour Name 	if (nbr_bss_desc->bssidInfo.rrmInfo.fCapSpectrumMeasurement)
1820*5113495bSYour Name 		roam_score +=
1821*5113495bSYour Name 			RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_SPECTRUM_MGMT;
1822*5113495bSYour Name 
1823*5113495bSYour Name 	if (nbr_bss_desc->bssidInfo.rrmInfo.fCapQos)
1824*5113495bSYour Name 		roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_QOS;
1825*5113495bSYour Name 
1826*5113495bSYour Name 	if (nbr_bss_desc->bssidInfo.rrmInfo.fCapApsd)
1827*5113495bSYour Name 		roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_APSD;
1828*5113495bSYour Name 
1829*5113495bSYour Name 	if (nbr_bss_desc->bssidInfo.rrmInfo.fCapDelayedBlockAck)
1830*5113495bSYour Name 		roam_score +=
1831*5113495bSYour Name 			RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_DELAYED_BA;
1832*5113495bSYour Name 
1833*5113495bSYour Name 	if (nbr_bss_desc->bssidInfo.rrmInfo.fCapImmediateBlockAck)
1834*5113495bSYour Name 		roam_score +=
1835*5113495bSYour Name 			RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_IMMEDIATE_BA;
1836*5113495bSYour Name 
1837*5113495bSYour Name 	if (nbr_bss_desc->bssidInfo.rrmInfo.fApPreauthReachable)
1838*5113495bSYour Name 		roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_REACHABILITY;
1839*5113495bSYour Name 
1840*5113495bSYour Name check_11r_assoc:
1841*5113495bSYour Name #ifdef FEATURE_WLAN_ESE
1842*5113495bSYour Name 	session_id = nbr_report_desc->sessionId;
1843*5113495bSYour Name 	wlan_cm_roam_cfg_get_value(mac_ctx->psoc, session_id, IS_11R_CONNECTION,
1844*5113495bSYour Name 				   &config);
1845*5113495bSYour Name 	/* It has come in the report so its the best score */
1846*5113495bSYour Name 	if (!config.bool_value) {
1847*5113495bSYour Name 		/* IAPP Route so lets make use of this info save all AP, as the
1848*5113495bSYour Name 		 * list does not come all the time. Save and reuse till the next
1849*5113495bSYour Name 		 * AP List comes to us. Even save our own MAC address. Will be
1850*5113495bSYour Name 		 * useful next time around.
1851*5113495bSYour Name 		 */
1852*5113495bSYour Name 		roam_score += RRM_ROAM_SCORE_NEIGHBOR_IAPP_LIST;
1853*5113495bSYour Name 	}
1854*5113495bSYour Name #endif
1855*5113495bSYour Name 	nbr_report_desc->roamScore = roam_score;
1856*5113495bSYour Name }
1857*5113495bSYour Name 
1858*5113495bSYour Name /**
1859*5113495bSYour Name  * rrm_store_neighbor_rpt_by_roam_score()-store Neighbor BSS descriptor
1860*5113495bSYour Name  * @mac: Pointer to mac context
1861*5113495bSYour Name  * @pNeighborReportDesc - Neighbor BSS Descriptor node to be stored in cache
1862*5113495bSYour Name  * @index: RRM sme context index
1863*5113495bSYour Name  *
1864*5113495bSYour Name  * This API is called to store a given
1865*5113495bSYour Name  * Neighbor BSS descriptor to the neighbor cache. This function
1866*5113495bSYour Name  * stores the neighbor BSS descriptors in such a way that descriptors
1867*5113495bSYour Name  * are sorted by roamScore in descending order
1868*5113495bSYour Name  *
1869*5113495bSYour Name  * Return: void.
1870*5113495bSYour Name  */
rrm_store_neighbor_rpt_by_roam_score(struct mac_context * mac,tpRrmNeighborReportDesc pNeighborReportDesc,uint8_t index)1871*5113495bSYour Name static void rrm_store_neighbor_rpt_by_roam_score(struct mac_context *mac,
1872*5113495bSYour Name 				tpRrmNeighborReportDesc pNeighborReportDesc,
1873*5113495bSYour Name 				uint8_t index)
1874*5113495bSYour Name {
1875*5113495bSYour Name 	tpRrmSMEContext pSmeRrmContext = &mac->rrm.rrmSmeContext[0];
1876*5113495bSYour Name 	tListElem *pEntry;
1877*5113495bSYour Name 	tRrmNeighborReportDesc *pTempNeighborReportDesc;
1878*5113495bSYour Name 
1879*5113495bSYour Name 	if (!pNeighborReportDesc) {
1880*5113495bSYour Name 		QDF_ASSERT(0);
1881*5113495bSYour Name 		return;
1882*5113495bSYour Name 	}
1883*5113495bSYour Name 	if (!pNeighborReportDesc->pNeighborBssDescription) {
1884*5113495bSYour Name 		QDF_ASSERT(0);
1885*5113495bSYour Name 		return;
1886*5113495bSYour Name 	}
1887*5113495bSYour Name 
1888*5113495bSYour Name 	if (csr_ll_is_list_empty
1889*5113495bSYour Name 		    (&pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK)) {
1890*5113495bSYour Name 		sme_err("Neighbor report cache is empty.. Adding a entry now");
1891*5113495bSYour Name 		/* Neighbor list cache is empty. Insert this entry
1892*5113495bSYour Name 		 * in the tail
1893*5113495bSYour Name 		 */
1894*5113495bSYour Name 		csr_ll_insert_tail(&pSmeRrmContext->neighborReportCache,
1895*5113495bSYour Name 				   &pNeighborReportDesc->List, LL_ACCESS_LOCK);
1896*5113495bSYour Name 		return;
1897*5113495bSYour Name 	}
1898*5113495bSYour Name 	/* Should store the neighbor BSS description in the order
1899*5113495bSYour Name 	 * sorted by roamScore in descending order. APs with highest
1900*5113495bSYour Name 	 * roamScore should be the 1st entry in the list
1901*5113495bSYour Name 	 */
1902*5113495bSYour Name 	pEntry = csr_ll_peek_head(&pSmeRrmContext->neighborReportCache,
1903*5113495bSYour Name 				LL_ACCESS_LOCK);
1904*5113495bSYour Name 	while (pEntry) {
1905*5113495bSYour Name 		pTempNeighborReportDesc = GET_BASE_ADDR(pEntry,
1906*5113495bSYour Name 					tRrmNeighborReportDesc, List);
1907*5113495bSYour Name 		if (pTempNeighborReportDesc->roamScore <
1908*5113495bSYour Name 				pNeighborReportDesc->roamScore)
1909*5113495bSYour Name 			break;
1910*5113495bSYour Name 		pEntry = csr_ll_next(&pSmeRrmContext->
1911*5113495bSYour Name 				neighborReportCache, pEntry, LL_ACCESS_LOCK);
1912*5113495bSYour Name 		}
1913*5113495bSYour Name 
1914*5113495bSYour Name 	if (pEntry)
1915*5113495bSYour Name 		/* This BSS roamscore is better than something in the
1916*5113495bSYour Name 		 * list. Insert this before that one
1917*5113495bSYour Name 		 */
1918*5113495bSYour Name 		csr_ll_insert_entry(&pSmeRrmContext->neighborReportCache,
1919*5113495bSYour Name 					pEntry, &pNeighborReportDesc->List,
1920*5113495bSYour Name 					LL_ACCESS_LOCK);
1921*5113495bSYour Name 	else
1922*5113495bSYour Name 		/* All the entries in the list has a better roam Score
1923*5113495bSYour Name 		 * than this one. Insert this at the last
1924*5113495bSYour Name 		 */
1925*5113495bSYour Name 		csr_ll_insert_tail(&pSmeRrmContext->neighborReportCache,
1926*5113495bSYour Name 					&pNeighborReportDesc->List,
1927*5113495bSYour Name 					LL_ACCESS_LOCK);
1928*5113495bSYour Name }
1929*5113495bSYour Name 
1930*5113495bSYour Name /**
1931*5113495bSYour Name  * sme_rrm_process_neighbor_report() -Process the Neighbor report received
1932*5113495bSYour Name  *                                                     from PE
1933*5113495bSYour Name  * @mac - Global MAC structure
1934*5113495bSYour Name  * @msg_buf - a pointer to a buffer that maps to various structures base
1935*5113495bSYour Name  *                  on the message type.
1936*5113495bSYour Name  *                  The beginning of the buffer can always map to tSirSmeRsp.
1937*5113495bSYour Name  * This is called to process the Neighbor report received from PE.
1938*5113495bSYour Name  *
1939*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS - Validation is successful
1940*5113495bSYour Name  */
sme_rrm_process_neighbor_report(struct mac_context * mac,void * msg_buf)1941*5113495bSYour Name static QDF_STATUS sme_rrm_process_neighbor_report(struct mac_context *mac,
1942*5113495bSYour Name 						  void *msg_buf)
1943*5113495bSYour Name {
1944*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1945*5113495bSYour Name 	tpSirNeighborReportInd neighbor_rpt = (tpSirNeighborReportInd)msg_buf;
1946*5113495bSYour Name 	tpRrmNeighborReportDesc neighbor_rpt_desc;
1947*5113495bSYour Name 	uint8_t i = 0;
1948*5113495bSYour Name 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1949*5113495bSYour Name 
1950*5113495bSYour Name 	/* Purge the cache on reception of unsolicited neighbor report */
1951*5113495bSYour Name 	if (!mac->rrm.rrmSmeContext[neighbor_rpt->measurement_idx].
1952*5113495bSYour Name 	    neighborReqControlInfo.isNeighborRspPending)
1953*5113495bSYour Name 		rrm_ll_purge_neighbor_cache(mac,
1954*5113495bSYour Name 			&mac->rrm.rrmSmeContext[neighbor_rpt->measurement_idx].
1955*5113495bSYour Name 			neighborReportCache);
1956*5113495bSYour Name 
1957*5113495bSYour Name 	for (i = 0; i < neighbor_rpt->numNeighborReports; i++) {
1958*5113495bSYour Name 		neighbor_rpt_desc =
1959*5113495bSYour Name 			qdf_mem_malloc(sizeof(tRrmNeighborReportDesc));
1960*5113495bSYour Name 		if (!neighbor_rpt_desc) {
1961*5113495bSYour Name 			status = QDF_STATUS_E_NOMEM;
1962*5113495bSYour Name 			goto end;
1963*5113495bSYour Name 
1964*5113495bSYour Name 		}
1965*5113495bSYour Name 
1966*5113495bSYour Name 		neighbor_rpt_desc->pNeighborBssDescription =
1967*5113495bSYour Name 			qdf_mem_malloc(sizeof(tSirNeighborBssDescription));
1968*5113495bSYour Name 		if (!neighbor_rpt_desc->pNeighborBssDescription) {
1969*5113495bSYour Name 			qdf_mem_free(neighbor_rpt_desc);
1970*5113495bSYour Name 			status = QDF_STATUS_E_NOMEM;
1971*5113495bSYour Name 			goto end;
1972*5113495bSYour Name 		}
1973*5113495bSYour Name 		qdf_mem_copy(neighbor_rpt_desc->pNeighborBssDescription,
1974*5113495bSYour Name 			     &neighbor_rpt->sNeighborBssDescription[i],
1975*5113495bSYour Name 			     sizeof(tSirNeighborBssDescription));
1976*5113495bSYour Name 
1977*5113495bSYour Name 		sme_debug("Received neighbor report with Neighbor BSSID: "
1978*5113495bSYour Name 			QDF_MAC_ADDR_FMT,
1979*5113495bSYour Name 			QDF_MAC_ADDR_REF(
1980*5113495bSYour Name 			       neighbor_rpt->sNeighborBssDescription[i].bssId));
1981*5113495bSYour Name 
1982*5113495bSYour Name 		rrm_calculate_neighbor_ap_roam_score(mac, neighbor_rpt_desc);
1983*5113495bSYour Name 
1984*5113495bSYour Name 		if (neighbor_rpt_desc->roamScore > 0) {
1985*5113495bSYour Name 			rrm_store_neighbor_rpt_by_roam_score(
1986*5113495bSYour Name 					mac, neighbor_rpt_desc,
1987*5113495bSYour Name 					neighbor_rpt->measurement_idx);
1988*5113495bSYour Name 		} else {
1989*5113495bSYour Name 			sme_err("Roam score of BSSID  " QDF_MAC_ADDR_FMT
1990*5113495bSYour Name 				" is 0, Ignoring..",
1991*5113495bSYour Name 				QDF_MAC_ADDR_REF(neighbor_rpt->
1992*5113495bSYour Name 					       sNeighborBssDescription[i].
1993*5113495bSYour Name 					       bssId));
1994*5113495bSYour Name 
1995*5113495bSYour Name 			qdf_mem_free(
1996*5113495bSYour Name 				neighbor_rpt_desc->pNeighborBssDescription);
1997*5113495bSYour Name 			qdf_mem_free(neighbor_rpt_desc);
1998*5113495bSYour Name 		}
1999*5113495bSYour Name 	}
2000*5113495bSYour Name end:
2001*5113495bSYour Name 
2002*5113495bSYour Name 	if (!csr_ll_count(
2003*5113495bSYour Name 		&mac->rrm.rrmSmeContext[neighbor_rpt->measurement_idx].
2004*5113495bSYour Name 		neighborReportCache))
2005*5113495bSYour Name 		qdf_status = QDF_STATUS_E_FAILURE;
2006*5113495bSYour Name 
2007*5113495bSYour Name 	rrm_indicate_neighbor_report_result(mac, qdf_status);
2008*5113495bSYour Name 
2009*5113495bSYour Name 	return status;
2010*5113495bSYour Name }
2011*5113495bSYour Name 
2012*5113495bSYour Name /**
2013*5113495bSYour Name  * sme_rrm_msg_processor()-Process RRM message
2014*5113495bSYour Name  * @mac - Pointer to the global MAC parameter structure.
2015*5113495bSYour Name  * @msg_type - the type of msg passed by PE as defined in wni_api.h
2016*5113495bSYour Name  * @msg_buf - a pointer to a buffer that maps to various structures base
2017*5113495bSYour Name  *                  on the message type.
2018*5113495bSYour Name  *                  The beginning of the buffer can always map to tSirSmeRsp.
2019*5113495bSYour Name  * sme_process_msg() calls this function for the
2020*5113495bSYour Name  * messages that are handled by SME RRM module.
2021*5113495bSYour Name  *
2022*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS - Validation is successful.
2023*5113495bSYour Name  */
sme_rrm_msg_processor(struct mac_context * mac,uint16_t msg_type,void * msg_buf)2024*5113495bSYour Name QDF_STATUS sme_rrm_msg_processor(struct mac_context *mac, uint16_t msg_type,
2025*5113495bSYour Name 				 void *msg_buf)
2026*5113495bSYour Name {
2027*5113495bSYour Name 	sme_debug("Msg = %d for RRM measurement", msg_type);
2028*5113495bSYour Name 
2029*5113495bSYour Name 	/* switch on the msg type & make the state transition accordingly */
2030*5113495bSYour Name 	switch (msg_type) {
2031*5113495bSYour Name 	case eWNI_SME_NEIGHBOR_REPORT_IND:
2032*5113495bSYour Name 		sme_rrm_process_neighbor_report(mac, msg_buf);
2033*5113495bSYour Name 		break;
2034*5113495bSYour Name 
2035*5113495bSYour Name 	case eWNI_SME_BEACON_REPORT_REQ_IND:
2036*5113495bSYour Name 		sme_rrm_process_beacon_report_req_ind(mac, msg_buf);
2037*5113495bSYour Name 		break;
2038*5113495bSYour Name 
2039*5113495bSYour Name 	case eWNI_SME_CHAN_LOAD_REQ_IND:
2040*5113495bSYour Name 		sme_rrm_process_chan_load_req_ind(mac, msg_buf);
2041*5113495bSYour Name 		break;
2042*5113495bSYour Name 
2043*5113495bSYour Name 	default:
2044*5113495bSYour Name 		sme_err("Unknown msg type: %d", msg_type);
2045*5113495bSYour Name 		break;
2046*5113495bSYour Name 	}
2047*5113495bSYour Name 
2048*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2049*5113495bSYour Name }
2050*5113495bSYour Name 
2051*5113495bSYour Name /**
2052*5113495bSYour Name  * rrm_neighbor_rsp_timeout_handler() - Timer handler to handlet the timeout
2053*5113495bSYour Name  * @mac - The handle returned by mac_open.
2054*5113495bSYour Name  *
2055*5113495bSYour Name  * Timer handler to handle the timeout condition when a neighbor request is sent
2056*5113495bSYour Name  * and no neighbor response is received from the AP
2057*5113495bSYour Name  *
2058*5113495bSYour Name  * Return: NULL
2059*5113495bSYour Name  */
rrm_neighbor_rsp_timeout_handler(void * userData)2060*5113495bSYour Name static void rrm_neighbor_rsp_timeout_handler(void *userData)
2061*5113495bSYour Name {
2062*5113495bSYour Name 	struct mac_context *mac = (struct mac_context *) userData;
2063*5113495bSYour Name 
2064*5113495bSYour Name 	sme_warn("Neighbor Response timed out");
2065*5113495bSYour Name 	rrm_indicate_neighbor_report_result(mac, QDF_STATUS_E_FAILURE);
2066*5113495bSYour Name }
2067*5113495bSYour Name 
2068*5113495bSYour Name /**
2069*5113495bSYour Name  * rrm_change_default_config_param() - Changing default config param to new
2070*5113495bSYour Name  * @mac - The handle returned by mac_open.
2071*5113495bSYour Name  *
2072*5113495bSYour Name  * Return: None
2073*5113495bSYour Name  */
rrm_change_default_config_param(struct mac_context * mac)2074*5113495bSYour Name static void rrm_change_default_config_param(struct mac_context *mac)
2075*5113495bSYour Name {
2076*5113495bSYour Name 	mac->rrm.rrmConfig.rrm_enabled =
2077*5113495bSYour Name 			mac->mlme_cfg->rrm_config.rrm_enabled;
2078*5113495bSYour Name 	mac->rrm.rrmConfig.sap_rrm_enabled =
2079*5113495bSYour Name 			mac->mlme_cfg->rrm_config.sap_rrm_enabled;
2080*5113495bSYour Name 	mac->rrm.rrmConfig.max_randn_interval =
2081*5113495bSYour Name 			mac->mlme_cfg->rrm_config.rrm_rand_interval;
2082*5113495bSYour Name 
2083*5113495bSYour Name 	qdf_mem_copy(&mac->rrm.rrmConfig.rm_capability,
2084*5113495bSYour Name 		     &mac->mlme_cfg->rrm_config.rm_capability,
2085*5113495bSYour Name 		     RMENABLEDCAP_MAX_LEN);
2086*5113495bSYour Name }
2087*5113495bSYour Name 
2088*5113495bSYour Name /**
2089*5113495bSYour Name  * rrm_open() - Initialize all RRM module
2090*5113495bSYour Name  * @ mac: The handle returned by mac_open.
2091*5113495bSYour Name  *
2092*5113495bSYour Name  * Initialize all RRM module.
2093*5113495bSYour Name  *
2094*5113495bSYour Name  * Return: QDF_STATUS
2095*5113495bSYour Name  */
rrm_open(struct mac_context * mac)2096*5113495bSYour Name QDF_STATUS rrm_open(struct mac_context *mac)
2097*5113495bSYour Name {
2098*5113495bSYour Name 
2099*5113495bSYour Name 	QDF_STATUS qdf_status;
2100*5113495bSYour Name 	tpRrmSMEContext pSmeRrmContext;
2101*5113495bSYour Name 	QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
2102*5113495bSYour Name 	uint8_t i;
2103*5113495bSYour Name 
2104*5113495bSYour Name 	mac->rrm.rrmConfig.max_randn_interval = 50;        /* ms */
2105*5113495bSYour Name 
2106*5113495bSYour Name 	for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) {
2107*5113495bSYour Name 		pSmeRrmContext = &mac->rrm.rrmSmeContext[i];
2108*5113495bSYour Name 
2109*5113495bSYour Name 		qdf_status =
2110*5113495bSYour Name 		    qdf_mc_timer_init(&pSmeRrmContext->neighborReqControlInfo.
2111*5113495bSYour Name 				      neighborRspWaitTimer, QDF_TIMER_TYPE_SW,
2112*5113495bSYour Name 				      rrm_neighbor_rsp_timeout_handler,
2113*5113495bSYour Name 				      (void *)mac);
2114*5113495bSYour Name 
2115*5113495bSYour Name 		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2116*5113495bSYour Name 			sme_err("Fail to init neighbor rsp wait timer");
2117*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
2118*5113495bSYour Name 		}
2119*5113495bSYour Name 
2120*5113495bSYour Name 		pSmeRrmContext->measurement_idx = i;
2121*5113495bSYour Name 		pSmeRrmContext->neighborReqControlInfo.isNeighborRspPending =
2122*5113495bSYour Name 						false;
2123*5113495bSYour Name 
2124*5113495bSYour Name 		qdf_ret_status =
2125*5113495bSYour Name 			csr_ll_open(&pSmeRrmContext->neighborReportCache);
2126*5113495bSYour Name 		if (QDF_STATUS_SUCCESS != qdf_ret_status) {
2127*5113495bSYour Name 			sme_err("Fail to open neighbor cache result");
2128*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
2129*5113495bSYour Name 		}
2130*5113495bSYour Name 	}
2131*5113495bSYour Name 
2132*5113495bSYour Name 	rrm_change_default_config_param(mac);
2133*5113495bSYour Name 
2134*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2135*5113495bSYour Name }
2136*5113495bSYour Name 
2137*5113495bSYour Name /**
2138*5113495bSYour Name  * rrm_close() - Release all RRM modules and their resources.
2139*5113495bSYour Name  * @mac - The handle returned by mac_open.
2140*5113495bSYour Name  *
2141*5113495bSYour Name  * Release all RRM modules and their resources.
2142*5113495bSYour Name  *
2143*5113495bSYour Name  * Return: QDF_STATUS
2144*5113495bSYour Name  *           QDF_STATUS_E_FAILURE  success
2145*5113495bSYour Name  *           QDF_STATUS_SUCCESS  failure
2146*5113495bSYour Name  */
2147*5113495bSYour Name 
rrm_close(struct mac_context * mac)2148*5113495bSYour Name QDF_STATUS rrm_close(struct mac_context *mac)
2149*5113495bSYour Name {
2150*5113495bSYour Name 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
2151*5113495bSYour Name 	tpRrmSMEContext pSmeRrmContext;
2152*5113495bSYour Name 	uint8_t i;
2153*5113495bSYour Name 
2154*5113495bSYour Name 	for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) {
2155*5113495bSYour Name 		pSmeRrmContext = &mac->rrm.rrmSmeContext[i];
2156*5113495bSYour Name 
2157*5113495bSYour Name 		if (pSmeRrmContext->channelList.freq_list) {
2158*5113495bSYour Name 			qdf_mem_free(pSmeRrmContext->channelList.freq_list);
2159*5113495bSYour Name 			pSmeRrmContext->channelList.freq_list = NULL;
2160*5113495bSYour Name 			pSmeRrmContext->channelList.numOfChannels = 0;
2161*5113495bSYour Name 		}
2162*5113495bSYour Name 
2163*5113495bSYour Name 		if (QDF_TIMER_STATE_RUNNING ==
2164*5113495bSYour Name 		    qdf_mc_timer_get_current_state(&pSmeRrmContext->
2165*5113495bSYour Name 						   neighborReqControlInfo.
2166*5113495bSYour Name 						   neighborRspWaitTimer)) {
2167*5113495bSYour Name 			qdf_status = qdf_mc_timer_stop(&pSmeRrmContext->
2168*5113495bSYour Name 						neighborReqControlInfo.
2169*5113495bSYour Name 						neighborRspWaitTimer);
2170*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(qdf_status))
2171*5113495bSYour Name 				sme_err("Timer stop fail");
2172*5113495bSYour Name 		}
2173*5113495bSYour Name 
2174*5113495bSYour Name 		qdf_status = qdf_mc_timer_destroy(
2175*5113495bSYour Name 				&pSmeRrmContext->neighborReqControlInfo.
2176*5113495bSYour Name 				neighborRspWaitTimer);
2177*5113495bSYour Name 		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
2178*5113495bSYour Name 			sme_err("Fail to destroy timer");
2179*5113495bSYour Name 
2180*5113495bSYour Name 		rrm_ll_purge_neighbor_cache(
2181*5113495bSYour Name 				mac, &pSmeRrmContext->neighborReportCache);
2182*5113495bSYour Name 		csr_ll_close(&pSmeRrmContext->neighborReportCache);
2183*5113495bSYour Name 	}
2184*5113495bSYour Name 
2185*5113495bSYour Name 	return qdf_status;
2186*5113495bSYour Name 
2187*5113495bSYour Name }
2188*5113495bSYour Name 
rrm_start(struct mac_context * mac_ctx)2189*5113495bSYour Name QDF_STATUS rrm_start(struct mac_context *mac_ctx)
2190*5113495bSYour Name {
2191*5113495bSYour Name 	tpRrmSMEContext smerrmctx;
2192*5113495bSYour Name 	wlan_scan_requester req_id;
2193*5113495bSYour Name 	uint8_t i;
2194*5113495bSYour Name 
2195*5113495bSYour Name 
2196*5113495bSYour Name 	/* Register with scan component */
2197*5113495bSYour Name 	req_id = wlan_scan_register_requester(mac_ctx->psoc,
2198*5113495bSYour Name 					      "RRM",
2199*5113495bSYour Name 					      sme_rrm_scan_event_callback,
2200*5113495bSYour Name 					      mac_ctx);
2201*5113495bSYour Name 
2202*5113495bSYour Name 	for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) {
2203*5113495bSYour Name 		smerrmctx = &mac_ctx->rrm.rrmSmeContext[i];
2204*5113495bSYour Name 		smerrmctx->req_id = req_id;
2205*5113495bSYour Name 	}
2206*5113495bSYour Name 
2207*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2208*5113495bSYour Name }
2209*5113495bSYour Name 
rrm_stop(struct mac_context * mac_ctx)2210*5113495bSYour Name QDF_STATUS rrm_stop(struct mac_context *mac_ctx)
2211*5113495bSYour Name {
2212*5113495bSYour Name 	tpRrmSMEContext smerrmctx;
2213*5113495bSYour Name 	wlan_scan_requester req_id;
2214*5113495bSYour Name 	uint8_t i;
2215*5113495bSYour Name 
2216*5113495bSYour Name 	for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) {
2217*5113495bSYour Name 		smerrmctx = &mac_ctx->rrm.rrmSmeContext[i];
2218*5113495bSYour Name 		req_id = smerrmctx->req_id;
2219*5113495bSYour Name 		smerrmctx->req_id = 0;
2220*5113495bSYour Name 	}
2221*5113495bSYour Name 
2222*5113495bSYour Name 	wlan_scan_unregister_requester(mac_ctx->psoc, req_id);
2223*5113495bSYour Name 
2224*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2225*5113495bSYour Name }
2226