1 /*
2  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: lim_process_mlm_host_roam.c
22  *
23  * Host based roaming MLM implementation
24  */
25 #include "cds_api.h"
26 #include "wni_cfg.h"
27 #include "ani_global.h"
28 #include "sir_api.h"
29 #include "sir_params.h"
30 
31 #include "sch_api.h"
32 #include "utils_api.h"
33 #include "lim_utils.h"
34 #include "lim_assoc_utils.h"
35 #include "lim_prop_exts_utils.h"
36 #include "lim_security_utils.h"
37 #include "lim_send_messages.h"
38 #include "lim_send_messages.h"
39 #include "lim_session_utils.h"
40 #include <lim_ft.h>
41 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
42 #include "host_diag_core_log.h"
43 #endif
44 #include "wma_if.h"
45 #include "rrm_api.h"
46 #include "wma.h"
47 #include <lim_mlo.h>
48 
49 static void lim_handle_sme_reaasoc_result(struct mac_context *, tSirResultCodes,
50 		uint16_t, struct pe_session *);
51 /**
52  * lim_process_mlm_reassoc_req() - process mlm reassoc request.
53  *
54  * @mac_ctx:     pointer to Global MAC structure
55  * @msg:  pointer to the MLM message buffer
56  *
57  * This function is called to process MLM_REASSOC_REQ message
58  * from SME
59  *
60  * Return: None
61  */
lim_process_mlm_reassoc_req(struct mac_context * mac_ctx,tLimMlmReassocReq * reassoc_req)62 void lim_process_mlm_reassoc_req(struct mac_context *mac_ctx,
63 				 tLimMlmReassocReq *reassoc_req)
64 {
65 	struct tLimPreAuthNode *auth_node;
66 	tLimMlmReassocCnf reassoc_cnf;
67 	struct pe_session *session;
68 
69 	session = pe_find_session_by_session_id(mac_ctx,
70 			reassoc_req->sessionId);
71 	if (!session) {
72 		pe_err("Session Does not exist for given sessionId: %d",
73 			reassoc_req->sessionId);
74 		qdf_mem_free(reassoc_req);
75 		return;
76 	}
77 
78 	pe_debug("ReAssoc Req on session: %d role: %d mlm: %d " QDF_MAC_ADDR_FMT,
79 		reassoc_req->sessionId, GET_LIM_SYSTEM_ROLE(session),
80 		session->limMlmState,
81 		QDF_MAC_ADDR_REF(reassoc_req->peerMacAddr));
82 
83 	if (LIM_IS_AP_ROLE(session) ||
84 		(session->limMlmState !=
85 		eLIM_MLM_LINK_ESTABLISHED_STATE)) {
86 		/*
87 		 * Received Reassoc request in invalid state or
88 		 * in AP role.Return Reassoc confirm with Invalid
89 		 * parameters code.
90 		 */
91 
92 		pe_warn("unexpected msg state: %X role: %d MAC "
93 			QDF_MAC_ADDR_FMT,
94 			session->limMlmState, GET_LIM_SYSTEM_ROLE(session),
95 			QDF_MAC_ADDR_REF(reassoc_req->peerMacAddr));
96 		lim_print_mlm_state(mac_ctx, LOGW, session->limMlmState);
97 		reassoc_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
98 		reassoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
99 		goto end;
100 	}
101 
102 	if (session->pLimMlmReassocReq)
103 		qdf_mem_free(session->pLimMlmReassocReq);
104 
105 	/*
106 	 * Hold Re-Assoc request as part of Session, knock-out mac_ctx
107 	 * Hold onto Reassoc request parameters
108 	 */
109 	session->pLimMlmReassocReq = reassoc_req;
110 
111 	/* See if we have pre-auth context with new AP */
112 	auth_node = lim_search_pre_auth_list(mac_ctx, session->limReAssocbssId);
113 
114 	if (!auth_node && (qdf_mem_cmp(reassoc_req->peerMacAddr,
115 					    session->bssId,
116 					    sizeof(tSirMacAddr)))) {
117 		/*
118 		 * Either pre-auth context does not exist AND
119 		 * we are not reassociating with currently
120 		 * associated AP.
121 		 * Return Reassoc confirm with not authenticated
122 		 */
123 		reassoc_cnf.resultCode = eSIR_SME_STA_NOT_AUTHENTICATED;
124 		reassoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
125 
126 		goto end;
127 	}
128 	/* assign the sessionId to the timer object */
129 	mac_ctx->lim.lim_timers.gLimReassocFailureTimer.sessionId =
130 		reassoc_req->sessionId;
131 	session->limPrevMlmState = session->limMlmState;
132 	session->limMlmState = eLIM_MLM_WT_REASSOC_RSP_STATE;
133 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session->peSessionId,
134 			 session->limMlmState));
135 
136 	/* Apply previously set configuration at HW */
137 	lim_apply_configuration(mac_ctx, session);
138 
139 	/* store the channel switch reason code in the lim global var */
140 	session->channelChangeReasonCode = LIM_SWITCH_CHANNEL_REASSOC;
141 	mlme_set_chan_switch_in_progress(session->vdev, true);
142 	wlan_vdev_mlme_sm_deliver_evt(session->vdev,
143 				      WLAN_VDEV_SM_EV_FW_VDEV_RESTART,
144 				      sizeof(struct pe_session), session);
145 	return;
146 end:
147 	reassoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
148 	/* Update PE session Id */
149 	reassoc_cnf.sessionId = reassoc_req->sessionId;
150 	/* Free up buffer allocated for reassocReq */
151 	qdf_mem_free(reassoc_req);
152 	session->pLimReAssocReq = NULL;
153 	lim_post_sme_message(mac_ctx, LIM_MLM_REASSOC_CNF,
154 			     (uint32_t *) &reassoc_cnf);
155 }
156 
157 /**
158  * lim_handle_sme_reaasoc_result() - Handle the reassoc result
159  * @mac: Global MAC Context
160  * @resultCode: Result code
161  * @protStatusCode: Protocol Status Code
162  * @pe_session: PE Session
163  *
164  * This function is called to process reassoc failures
165  * upon receiving REASSOC_CNF with a failure code or
166  * MLM_REASSOC_CNF with a success code in case of STA role
167  *
168  * Return: None
169  */
lim_handle_sme_reaasoc_result(struct mac_context * mac,tSirResultCodes resultCode,uint16_t protStatusCode,struct pe_session * pe_session)170 static void lim_handle_sme_reaasoc_result(struct mac_context *mac,
171 		tSirResultCodes resultCode, uint16_t protStatusCode,
172 		struct pe_session *pe_session)
173 {
174 	tpDphHashNode sta = NULL;
175 	uint8_t smesessionId;
176 
177 	if (!pe_session) {
178 		pe_err("pe_session is NULL");
179 		return;
180 	}
181 	smesessionId = pe_session->smeSessionId;
182 	if (resultCode != eSIR_SME_SUCCESS) {
183 		sta =
184 			dph_get_hash_entry(mac, DPH_STA_HASH_INDEX_PEER,
185 					   &pe_session->dph.dphHashTable);
186 		if (sta) {
187 			sta->mlmStaContext.disassocReason =
188 				REASON_UNSPEC_FAILURE;
189 			sta->mlmStaContext.cleanupTrigger =
190 				eLIM_JOIN_FAILURE;
191 			sta->mlmStaContext.resultCode = resultCode;
192 			sta->mlmStaContext.protStatusCode = protStatusCode;
193 			lim_mlo_notify_peer_disconn(pe_session, sta);
194 			lim_cleanup_rx_path(mac, sta, pe_session, true);
195 			/* Cleanup if add bss failed */
196 			if (pe_session->add_bss_failed) {
197 				dph_delete_hash_entry(mac,
198 					 sta->staAddr, sta->assocId,
199 					 &pe_session->dph.dphHashTable);
200 				goto error;
201 			}
202 			return;
203 		}
204 	}
205 error:
206 	/* Delete the session if REASSOC failure occurred. */
207 	if (resultCode != eSIR_SME_SUCCESS) {
208 		if (pe_session) {
209 			pe_delete_session(mac, pe_session);
210 			pe_session = NULL;
211 		}
212 	}
213 	lim_send_sme_join_reassoc_rsp(mac, eWNI_SME_REASSOC_RSP, resultCode,
214 		protStatusCode, pe_session, smesessionId);
215 }
216 
217 /**
218  * lim_process_mlm_reassoc_cnf() - process mlm reassoc cnf msg
219  *
220  * @mac_ctx:       Pointer to Global MAC structure
221  * @msg_buf:       A pointer to the MLM message buffer
222  *
223  * This function is called to process MLM_REASSOC_CNF message from MLM State
224  * machine.
225  *
226  * @Return: void
227  */
lim_process_mlm_reassoc_cnf(struct mac_context * mac_ctx,uint32_t * msg_buf)228 void lim_process_mlm_reassoc_cnf(struct mac_context *mac_ctx, uint32_t *msg_buf)
229 {
230 	struct pe_session *session;
231 	tLimMlmReassocCnf *lim_mlm_reassoc_cnf;
232 	struct reassoc_params param;
233 	QDF_STATUS status;
234 	enum wlan_vdev_state sub_state;
235 
236 	if (!msg_buf) {
237 		pe_err("Buffer is Pointing to NULL");
238 		return;
239 	}
240 	lim_mlm_reassoc_cnf = (tLimMlmReassocCnf *)msg_buf;
241 	session = pe_find_session_by_session_id(
242 					mac_ctx,
243 					lim_mlm_reassoc_cnf->sessionId);
244 	if (!session) {
245 		pe_err("session Does not exist for given session Id");
246 		return;
247 	}
248 	if (session->limSmeState != eLIM_SME_WT_REASSOC_STATE ||
249 	    LIM_IS_AP_ROLE(session)) {
250 		/*
251 		 * Should not have received Reassocication confirm
252 		 * from MLM in other states OR on AP.
253 		 */
254 		pe_err("Rcv unexpected MLM_REASSOC_CNF role: %d sme 0x%X",
255 		       GET_LIM_SYSTEM_ROLE(session), session->limSmeState);
256 		return;
257 	}
258 
259 	/*
260 	 * Upon Reassoc success or failure, freeup the cached preauth request,
261 	 * to ensure that channel switch is now allowed following any change in
262 	 * HT params.
263 	 */
264 	if (session->ftPEContext.pFTPreAuthReq) {
265 		pe_debug("Freeing pFTPreAuthReq: %pK",
266 			 session->ftPEContext.pFTPreAuthReq);
267 		if (session->ftPEContext.pFTPreAuthReq->pbssDescription) {
268 			qdf_mem_free(
269 			  session->ftPEContext.pFTPreAuthReq->pbssDescription);
270 			session->ftPEContext.pFTPreAuthReq->pbssDescription =
271 									NULL;
272 		}
273 		qdf_mem_free(session->ftPEContext.pFTPreAuthReq);
274 		session->ftPEContext.pFTPreAuthReq = NULL;
275 		session->ftPEContext.ftPreAuthSession = false;
276 	}
277 
278 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
279 	if (session->bRoamSynchInProgress) {
280 		pe_debug("LFR3:Re-set the LIM Ctxt Roam Synch In Progress");
281 		session->bRoamSynchInProgress = false;
282 	}
283 #endif
284 
285 	sub_state = wlan_vdev_mlme_get_substate(session->vdev);
286 	pe_debug("Rcv MLM_REASSOC_CNF with result code: %d vdev SS %d",
287 		 lim_mlm_reassoc_cnf->resultCode, sub_state);
288 	if (lim_mlm_reassoc_cnf->resultCode == eSIR_SME_SUCCESS) {
289 		/* Successful Reassociation */
290 		pe_debug("*** Reassociated with new BSS ***");
291 
292 		session->limSmeState = eLIM_SME_LINK_EST_STATE;
293 		MTRACE(mac_trace(
294 			mac_ctx, TRACE_CODE_SME_STATE,
295 			session->peSessionId, session->limSmeState));
296 
297 		wlan_vdev_mlme_sm_deliver_evt(session->vdev,
298 					      WLAN_VDEV_SM_EV_START_SUCCESS,
299 					      0, NULL);
300 
301 		/* Need to send Reassoc rsp with Reassoc success to Host. */
302 		lim_send_sme_join_reassoc_rsp(
303 					mac_ctx, eWNI_SME_REASSOC_RSP,
304 					lim_mlm_reassoc_cnf->resultCode,
305 					lim_mlm_reassoc_cnf->protStatusCode,
306 					session, session->smeSessionId);
307 	} else if (sub_state == WLAN_VDEV_SS_START_CONN_PROGRESS ||
308 		   sub_state == WLAN_VDEV_SS_START_RESTART_PROGRESS) {
309 		session->limSmeState = eLIM_SME_LINK_EST_STATE;
310 		/*
311 		 * Need to send Reassoc rsp with re-Assoc failure to CM
312 		 * so that disconnect can be initiated.
313 		 */
314 		lim_send_sme_join_reassoc_rsp(
315 					mac_ctx, eWNI_SME_REASSOC_RSP,
316 					lim_mlm_reassoc_cnf->resultCode,
317 					lim_mlm_reassoc_cnf->protStatusCode,
318 					session, session->smeSessionId);
319 	} else {
320 		param.result_code = lim_mlm_reassoc_cnf->resultCode;
321 		param.prot_status_code = lim_mlm_reassoc_cnf->protStatusCode;
322 		param.session = session;
323 
324 		mlme_set_connection_fail(session->vdev, true);
325 
326 		if (sub_state == WLAN_VDEV_SS_START_START_PROGRESS)
327 			status = wlan_vdev_mlme_sm_deliver_evt(session->vdev,
328 						WLAN_VDEV_SM_EV_START_REQ_FAIL,
329 						sizeof(param), &param);
330 		else
331 			status = wlan_vdev_mlme_sm_deliver_evt(session->vdev,
332 						WLAN_VDEV_SM_EV_CONNECTION_FAIL,
333 						sizeof(param), &param);
334 	}
335 
336 	if (session->pLimReAssocReq) {
337 		qdf_mem_free(session->pLimReAssocReq);
338 		session->pLimReAssocReq = NULL;
339 	}
340 }
341 
lim_sta_reassoc_error_handler(struct reassoc_params * param)342 QDF_STATUS lim_sta_reassoc_error_handler(struct reassoc_params *param)
343 {
344 	struct pe_session *session;
345 	struct mac_context *mac_ctx;
346 
347 	if (!param) {
348 		pe_err("param is NULL");
349 		return QDF_STATUS_E_INVAL;
350 	}
351 
352 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
353 	if (!mac_ctx)
354 		return QDF_STATUS_E_INVAL;
355 
356 	session = param->session;
357 	if (param->result_code
358 			== eSIR_SME_REASSOC_REFUSED) {
359 		/*
360 		 * Reassociation failure With the New AP but we still have the
361 		 * link with the Older AP
362 		 */
363 		session->limSmeState = eLIM_SME_LINK_EST_STATE;
364 		MTRACE(mac_trace(
365 			mac_ctx, TRACE_CODE_SME_STATE,
366 			session->peSessionId, session->limSmeState));
367 
368 		/* Need to send Reassoc rsp with Assoc failure to Host. */
369 		lim_send_sme_join_reassoc_rsp(
370 					mac_ctx, eWNI_SME_REASSOC_RSP,
371 					param->result_code,
372 					param->prot_status_code,
373 					session, session->smeSessionId);
374 	} else {
375 		/* Reassociation failure */
376 		session->limSmeState = eLIM_SME_JOIN_FAILURE_STATE;
377 		MTRACE(mac_trace(
378 			mac_ctx, TRACE_CODE_SME_STATE,
379 			session->peSessionId, session->limSmeState));
380 		/* Need to send Reassoc rsp with Assoc failure to Host. */
381 		lim_handle_sme_reaasoc_result(
382 					mac_ctx,
383 					param->result_code,
384 					param->prot_status_code,
385 					session);
386 	}
387 	return QDF_STATUS_SUCCESS;
388 }
389 
lim_process_sta_mlm_add_bss_rsp_ft(struct mac_context * mac,struct add_bss_rsp * add_bss_rsp,struct pe_session * pe_session)390 void lim_process_sta_mlm_add_bss_rsp_ft(struct mac_context *mac,
391 					struct add_bss_rsp *add_bss_rsp,
392 					struct pe_session *pe_session)
393 {
394 	tLimMlmReassocCnf mlmReassocCnf; /* keep sme */
395 	tpDphHashNode sta = NULL;
396 	tpAddStaParams pAddStaParams = NULL;
397 	uint32_t listenInterval = MLME_CFG_LISTEN_INTERVAL;
398 	struct bss_description *bss_desc = NULL;
399 
400 	/* Sanity Checks */
401 
402 	if (!add_bss_rsp) {
403 		pe_err("add_bss_rsp is NULL");
404 		goto end;
405 	}
406 	if (eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE !=
407 	    pe_session->limMlmState) {
408 		goto end;
409 	}
410 
411 	sta = dph_add_hash_entry(mac, pe_session->bssId,
412 				 DPH_STA_HASH_INDEX_PEER,
413 				 &pe_session->dph.dphHashTable);
414 	if (!sta) {
415 		/* Could not add hash table entry */
416 		pe_err("could not add hash entry at DPH for "QDF_MAC_ADDR_FMT,
417 		       QDF_MAC_ADDR_REF(pe_session->bssId));
418 		goto end;
419 	}
420 
421 	/* Prepare and send Reassociation request frame */
422 	/* start reassoc timer. */
423 	mac->lim.lim_timers.gLimReassocFailureTimer.sessionId =
424 			pe_session->peSessionId;
425 	/* / Start reassociation failure timer */
426 	MTRACE(mac_trace
427 		(mac, TRACE_CODE_TIMER_ACTIVATE,
428 		 pe_session->peSessionId, eLIM_REASSOC_FAIL_TIMER));
429 
430 	if (tx_timer_activate(&mac->lim.lim_timers.gLimReassocFailureTimer) !=
431 	    TX_SUCCESS) {
432 		/* / Could not start reassoc failure timer. */
433 		/* Log error */
434 		pe_err("could not start Reassoc failure timer");
435 		/* Return Reassoc confirm with */
436 		/* Resources Unavailable */
437 		mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
438 		mlmReassocCnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
439 		goto end;
440 	}
441 
442 	mac->lim.pe_session = pe_session;
443 	if (!mac->lim.pe_session->pLimMlmReassocRetryReq) {
444 		/* Take a copy of reassoc request for retrying */
445 		mac->lim.pe_session->pLimMlmReassocRetryReq =
446 			qdf_mem_malloc(sizeof(tLimMlmReassocReq));
447 		if (!mac->lim.pe_session->pLimMlmReassocRetryReq)
448 			goto end;
449 
450 		qdf_mem_copy(mac->lim.pe_session->pLimMlmReassocRetryReq,
451 			     pe_session->pLimMlmReassocReq,
452 			     sizeof(tLimMlmReassocReq));
453 	}
454 	mac->lim.reAssocRetryAttempt = 0;
455 	lim_send_reassoc_req_with_ft_ies_mgmt_frame(
456 		mac, pe_session->pLimMlmReassocReq, pe_session);
457 
458 	pe_session->limPrevMlmState = pe_session->limMlmState;
459 	pe_session->limMlmState = eLIM_MLM_WT_FT_REASSOC_RSP_STATE;
460 	MTRACE(mac_trace
461 		       (mac, TRACE_CODE_MLM_STATE, pe_session->peSessionId,
462 		       eLIM_MLM_WT_FT_REASSOC_RSP_STATE));
463 	pe_debug("Set the mlm state: %d session: %d",
464 		       pe_session->limMlmState, pe_session->peSessionId);
465 
466 	/* Success, handle below */
467 
468 	pAddStaParams = qdf_mem_malloc(sizeof(tAddStaParams));
469 	if (!pAddStaParams)
470 		goto end;
471 
472 	/* / Add STA context at MAC HW (BMU, RHP & TFP) */
473 	qdf_mem_copy((uint8_t *)pAddStaParams->staMac,
474 		     (uint8_t *)pe_session->self_mac_addr,
475 		     sizeof(tSirMacAddr));
476 
477 	qdf_mem_copy((uint8_t *)pAddStaParams->bssId,
478 		     pe_session->bssId, sizeof(tSirMacAddr));
479 
480 	pAddStaParams->staType = STA_ENTRY_SELF;
481 	pAddStaParams->status = QDF_STATUS_SUCCESS;
482 
483 	/* Update  PE session ID */
484 	pAddStaParams->sessionId = pe_session->peSessionId;
485 	pAddStaParams->smesessionId = pe_session->smeSessionId;
486 
487 	pAddStaParams->updateSta = false;
488 
489 	if (pe_session->lim_join_req)
490 		bss_desc = &pe_session->lim_join_req->bssDescription;
491 
492 	lim_populate_peer_rate_set(mac, &pAddStaParams->supportedRates, NULL,
493 				   false, pe_session, NULL, NULL, NULL, NULL,
494 				   bss_desc);
495 
496 	if (pe_session->htCapability) {
497 		pAddStaParams->htCapable = pe_session->htCapability;
498 		pAddStaParams->vhtCapable = pe_session->vhtCapability;
499 		pAddStaParams->ch_width = pe_session->ch_width;
500 
501 		pAddStaParams->mimoPS =
502 			lim_get_ht_capability(mac, eHT_MIMO_POWER_SAVE,
503 					      pe_session);
504 		pAddStaParams->maxAmpduDensity =
505 			lim_get_ht_capability(mac, eHT_MPDU_DENSITY,
506 					pe_session);
507 		pAddStaParams->maxAmpduSize =
508 			lim_get_ht_capability(mac, eHT_MAX_RX_AMPDU_FACTOR,
509 					      pe_session);
510 		pAddStaParams->fShortGI20Mhz =
511 			lim_get_ht_capability(mac, eHT_SHORT_GI_20MHZ,
512 					pe_session);
513 		pAddStaParams->fShortGI40Mhz =
514 			lim_get_ht_capability(mac, eHT_SHORT_GI_40MHZ,
515 					pe_session);
516 	}
517 
518 	listenInterval = mac->mlme_cfg->sap_cfg.listen_interval;
519 	pAddStaParams->listenInterval = (uint16_t) listenInterval;
520 
521 	pAddStaParams->encryptType = pe_session->encryptType;
522 	pAddStaParams->maxTxPower = pe_session->maxTxPower;
523 
524 	/* Lets save this for when we receive the Reassoc Rsp */
525 	pe_session->ftPEContext.pAddStaReq = pAddStaParams;
526 
527 	return;
528 
529 end:
530 	/* Free up buffer allocated for reassocReq */
531 	if (pe_session)
532 		if (pe_session->pLimMlmReassocReq) {
533 			qdf_mem_free(pe_session->pLimMlmReassocReq);
534 			pe_session->pLimMlmReassocReq = NULL;
535 		}
536 
537 	mlmReassocCnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE;
538 	mlmReassocCnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
539 	/* Update PE session Id */
540 	if (pe_session)
541 		mlmReassocCnf.sessionId = pe_session->peSessionId;
542 	else
543 		mlmReassocCnf.sessionId = 0;
544 
545 	lim_post_sme_message(mac, LIM_MLM_REASSOC_CNF,
546 			     (uint32_t *) &mlmReassocCnf);
547 }
548 
lim_process_mlm_ft_reassoc_req(struct mac_context * mac,tLimMlmReassocReq * reassoc_req)549 void lim_process_mlm_ft_reassoc_req(struct mac_context *mac,
550 				    tLimMlmReassocReq *reassoc_req)
551 {
552 	struct pe_session *session;
553 	uint16_t caps;
554 	uint32_t val;
555 	QDF_STATUS status;
556 	uint32_t teleBcnEn = 0;
557 	struct wlan_objmgr_vdev *vdev;
558 	struct vdev_mlme_obj *mlme_obj;
559 
560 	if (!reassoc_req) {
561 		pe_err("reassoc_req is NULL");
562 		return;
563 	}
564 
565 	session = pe_find_session_by_session_id(mac, reassoc_req->sessionId);
566 	if (!session) {
567 		pe_err("session Does not exist for given session Id");
568 		qdf_mem_free(reassoc_req);
569 		return;
570 	}
571 
572 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
573 	lim_diag_event_report(mac, WLAN_PE_DIAG_REASSOCIATING,
574 			session, 0, 0);
575 #endif
576 
577 	/* Nothing to be done if the session is not in STA mode */
578 	if (!LIM_IS_STA_ROLE(session)) {
579 		pe_err("pe_session is not in STA mode");
580 		qdf_mem_free(reassoc_req);
581 		return;
582 	}
583 
584 	if (!session->ftPEContext.pAddBssReq) {
585 		pe_err("pAddBssReq is NULL");
586 		return;
587 	}
588 
589 	qdf_mem_copy(reassoc_req->peerMacAddr,
590 		     session->bssId, sizeof(tSirMacAddr));
591 
592 	if (lim_get_capability_info(mac, &caps, session) !=
593 			QDF_STATUS_SUCCESS) {
594 		/**
595 		 * Could not get Capabilities value
596 		 * from CFG. Log error.
597 		 */
598 		pe_err("could not get Capabilities value");
599 		qdf_mem_free(reassoc_req);
600 		return;
601 	}
602 
603 	lim_update_caps_info_for_bss(mac, &caps,
604 		session->pLimReAssocReq->bssDescription.capabilityInfo);
605 	pe_debug("Capabilities info FT Reassoc: 0x%X", caps);
606 
607 	reassoc_req->capabilityInfo = caps;
608 
609 	/* If telescopic beaconing is enabled, set listen interval
610 	   to CFG_TELE_BCN_MAX_LI
611 	 */
612 	teleBcnEn = mac->mlme_cfg->sap_cfg.tele_bcn_wakeup_en;
613 	if (teleBcnEn)
614 		val = mac->mlme_cfg->sap_cfg.tele_bcn_max_li;
615 	else
616 		val = mac->mlme_cfg->sap_cfg.listen_interval;
617 
618 	reassoc_req->listenInterval = (uint16_t) val;
619 
620 	vdev = session->vdev;
621 	if (!vdev) {
622 		pe_err("vdev is NULL");
623 		qdf_mem_free(reassoc_req);
624 		return;
625 	}
626 	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev);
627 	if (!mlme_obj) {
628 		pe_err("vdev component object is NULL");
629 		return;
630 	}
631 
632 	status = lim_pre_vdev_start(mac, mlme_obj, session);
633 	if (QDF_IS_STATUS_ERROR(status)) {
634 		qdf_mem_free(reassoc_req);
635 		return;
636 	}
637 	qdf_mem_copy(mlme_obj->mgmt.generic.bssid, session->bssId,
638 		     QDF_MAC_ADDR_SIZE);
639 
640 	session->pLimMlmReassocReq = reassoc_req;
641 	/* we need to defer the message until we get response back from HAL */
642 	SET_LIM_PROCESS_DEFD_MESGS(mac, false);
643 	status = wma_add_bss_lfr2_vdev_start(session->vdev,
644 					     session->ftPEContext.pAddBssReq);
645 	if (QDF_IS_STATUS_ERROR(status)) {
646 		SET_LIM_PROCESS_DEFD_MESGS(mac, true);
647 		pe_err("wma_add_bss_lfr2_vdev_start, reason: %X", status);
648 		session->pLimMlmReassocReq = NULL;
649 		qdf_mem_free(reassoc_req);
650 	}
651 	qdf_mem_free(session->ftPEContext.pAddBssReq);
652 
653 	session->ftPEContext.pAddBssReq = NULL;
654 	return;
655 }
656 
657