1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * This file lim_link_monitoring_algo.cc contains the code for
22  * Link monitoring algorithm on AP and heart beat failure
23  * handling on STA.
24  * Author:        Chandra Modumudi
25  * Date:          03/01/02
26  * History:-
27  * Date           Modified by    Modification Information
28  * --------------------------------------------------------------------
29  *
30  */
31 
32 #include "ani_global.h"
33 #include "wni_cfg.h"
34 
35 #include "sch_api.h"
36 #include "utils_api.h"
37 #include "lim_assoc_utils.h"
38 #include "lim_types.h"
39 #include "lim_utils.h"
40 #include "lim_prop_exts_utils.h"
41 
42 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
43 #include "host_diag_core_log.h"
44 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
45 #include "lim_ft_defs.h"
46 #include "lim_session.h"
47 #include "lim_ser_des_utils.h"
48 #include "wlan_dlm_api.h"
49 
50 /**
51  * lim_delete_sta_util - utility function for deleting station context
52  *
53  * @mac_ctx: global MAC context
54  * @msg: pointer to delete station context
55  * @session_entry: PE session entry
56  *
57  * utility function called to clear up station context.
58  *
59  * Return: None.
60  */
lim_delete_sta_util(struct mac_context * mac_ctx,tpDeleteStaContext msg,struct pe_session * session_entry)61 static void lim_delete_sta_util(struct mac_context *mac_ctx, tpDeleteStaContext msg,
62 				struct pe_session *session_entry)
63 {
64 	tpDphHashNode stads;
65 
66 	pe_debug("Deleting station: reasonCode: %d", msg->reasonCode);
67 
68 	stads = dph_lookup_hash_entry(mac_ctx, msg->addr2, &msg->assocId,
69 				      &session_entry->dph.dphHashTable);
70 
71 	if (!stads) {
72 		pe_err("Invalid STA limSystemRole: %d",
73 			GET_LIM_SYSTEM_ROLE(session_entry));
74 		return;
75 	}
76 	stads->del_sta_ctx_rssi = msg->rssi;
77 
78 	if (LIM_IS_AP_ROLE(session_entry)) {
79 		pe_debug("Delete Station assocId: %d", msg->assocId);
80 		/*
81 		 * Check if Deauth/Disassoc is triggered from Host.
82 		 * If mlmState is in some transient state then
83 		 * don't trigger STA deletion to avoid the race
84 		 * condition.
85 		 */
86 		if ((stads &&
87 		     ((stads->mlmStaContext.mlmState !=
88 			eLIM_MLM_LINK_ESTABLISHED_STATE) &&
89 		      (stads->mlmStaContext.mlmState !=
90 			eLIM_MLM_WT_ASSOC_CNF_STATE) &&
91 		      (stads->mlmStaContext.mlmState !=
92 			eLIM_MLM_ASSOCIATED_STATE)))) {
93 			pe_err("Inv Del STA assocId: %d", msg->assocId);
94 			return;
95 		} else {
96 			if (stads->ocv_enabled && stads->last_ocv_done_freq !=
97 			    session_entry->curr_op_freq) {
98 				lim_send_deauth_mgmt_frame(
99 						mac_ctx,
100 						REASON_PREV_AUTH_NOT_VALID,
101 						stads->staAddr,
102 						session_entry, true);
103 				stads->is_disassoc_deauth_in_progress = 1;
104 			} else {
105 				lim_send_disassoc_mgmt_frame(
106 					mac_ctx,
107 					REASON_DISASSOC_DUE_TO_INACTIVITY,
108 					stads->staAddr, session_entry, false);
109 				lim_trigger_sta_deletion(mac_ctx, stads,
110 							 session_entry);
111 			}
112 		}
113 	} else {
114 #ifdef FEATURE_WLAN_TDLS
115 		if (LIM_IS_STA_ROLE(session_entry) &&
116 		    STA_ENTRY_TDLS_PEER == stads->staType) {
117 			/*
118 			 * TeardownLink with PEER reason code
119 			 * HAL_DEL_STA_REASON_CODE_KEEP_ALIVE means
120 			 * eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE
121 			 */
122 			lim_send_sme_tdls_del_sta_ind(mac_ctx, stads,
123 			    session_entry, REASON_TDLS_PEER_UNREACHABLE);
124 		} else {
125 #endif
126 		/* TearDownLink with AP */
127 		tLimMlmDeauthInd mlm_deauth_ind;
128 
129 		pe_debug("Delete Station (assocId: %d)", msg->assocId);
130 
131 		if ((stads &&
132 			((stads->mlmStaContext.mlmState !=
133 					eLIM_MLM_LINK_ESTABLISHED_STATE) &&
134 			(stads->mlmStaContext.mlmState !=
135 					eLIM_MLM_WT_ASSOC_CNF_STATE) &&
136 			(stads->mlmStaContext.mlmState !=
137 					eLIM_MLM_ASSOCIATED_STATE)))) {
138 
139 			/*
140 			 * Received SIR_LIM_DELETE_STA_CONTEXT_IND for STA that
141 			 * does not have context or in some transit state.
142 			 * Log error
143 			 */
144 			pe_debug("Received SIR_LIM_DELETE_STA_CONTEXT_IND for "
145 					"STA that either has no context or "
146 					"in some transit state, Addr = "
147 					QDF_MAC_ADDR_FMT,
148 					QDF_MAC_ADDR_REF(msg->bssId));
149 			return;
150 		}
151 
152 		stads->mlmStaContext.disassocReason =
153 			REASON_DISASSOC_DUE_TO_INACTIVITY;
154 		stads->mlmStaContext.cleanupTrigger =
155 			eLIM_LINK_MONITORING_DEAUTH;
156 
157 		/* Issue Deauth Indication to SME. */
158 		qdf_mem_copy((uint8_t *) &mlm_deauth_ind.peerMacAddr,
159 			     stads->staAddr, sizeof(tSirMacAddr));
160 		mlm_deauth_ind.reasonCode =
161 			(uint8_t) stads->mlmStaContext.disassocReason;
162 		mlm_deauth_ind.deauthTrigger =
163 			stads->mlmStaContext.cleanupTrigger;
164 
165 #ifdef FEATURE_WLAN_TDLS
166 		/* Delete all TDLS peers connected before leaving BSS */
167 		lim_delete_tdls_peers(mac_ctx, session_entry);
168 #endif
169 		if (LIM_IS_STA_ROLE(session_entry))
170 			lim_post_sme_message(mac_ctx, LIM_MLM_DEAUTH_IND,
171 				     (uint32_t *) &mlm_deauth_ind);
172 
173 		lim_send_sme_deauth_ind(mac_ctx, stads,	session_entry);
174 #ifdef FEATURE_WLAN_TDLS
175 	}
176 #endif
177 	}
178 }
179 
180 /**
181  * lim_delete_sta_context() - delete sta context.
182  *
183  * @mac_ctx: global mac_ctx context
184  * @lim_msg: lim message.
185  *
186  * This function handles the message from HAL: WMA_DELETE_STA_CONTEXT_IND.
187  * This function validates that the given station id exist, and if so,
188  * deletes the station by calling lim_trigger_sta_deletion.
189  *
190  * Return: none
191  */
lim_delete_sta_context(struct mac_context * mac_ctx,struct scheduler_msg * lim_msg)192 void lim_delete_sta_context(struct mac_context *mac_ctx,
193 			    struct scheduler_msg *lim_msg)
194 {
195 	tpDeleteStaContext msg = (tpDeleteStaContext) lim_msg->bodyptr;
196 	struct pe_session *session_entry;
197 	tpDphHashNode sta_ds;
198 	enum wlan_reason_code reason_code;
199 	struct reject_ap_info ap_info;
200 
201 	if (!msg) {
202 		pe_err("Invalid body pointer in message");
203 		return;
204 	}
205 	session_entry = pe_find_session_by_vdev_id(mac_ctx, msg->vdev_id);
206 	if (!session_entry) {
207 		pe_err("session not found for given sme session");
208 		qdf_mem_free(msg);
209 		return;
210 	}
211 
212 	switch (msg->reasonCode) {
213 	case HAL_DEL_STA_REASON_CODE_KEEP_ALIVE:
214 	case HAL_DEL_STA_REASON_CODE_SA_QUERY_TIMEOUT:
215 	case HAL_DEL_STA_REASON_CODE_XRETRY:
216 		if (LIM_IS_STA_ROLE(session_entry) && !msg->is_tdls) {
217 			if (!lim_is_sb_disconnect_allowed(session_entry)) {
218 				qdf_mem_free(msg);
219 				return;
220 			}
221 			sta_ds = dph_get_hash_entry(mac_ctx,
222 					DPH_STA_HASH_INDEX_PEER,
223 					&session_entry->dph.dphHashTable);
224 			if (!sta_ds) {
225 				pe_err("Dph entry not found");
226 				qdf_mem_free(msg);
227 				return;
228 			}
229 			lim_send_deauth_mgmt_frame(mac_ctx,
230 				REASON_DISASSOC_DUE_TO_INACTIVITY,
231 				msg->addr2, session_entry, false);
232 			if (msg->reasonCode ==
233 				HAL_DEL_STA_REASON_CODE_SA_QUERY_TIMEOUT)
234 				reason_code = REASON_SA_QUERY_TIMEOUT;
235 			else if (msg->reasonCode ==
236 				HAL_DEL_STA_REASON_CODE_XRETRY)
237 				reason_code = REASON_PEER_XRETRY_FAIL;
238 			else
239 				reason_code = REASON_PEER_INACTIVITY;
240 			lim_tear_down_link_with_ap(mac_ctx,
241 						   session_entry->peSessionId,
242 						   reason_code,
243 						   eLIM_LINK_MONITORING_DEAUTH);
244 			qdf_mem_zero(&ap_info, sizeof(struct reject_ap_info));
245 			qdf_mem_copy(&ap_info.bssid, msg->addr2,
246 				     QDF_MAC_ADDR_SIZE);
247 			ap_info.reject_ap_type = DRIVER_AVOID_TYPE;
248 			ap_info.reject_reason = REASON_STA_KICKOUT;
249 			ap_info.source = ADDED_BY_DRIVER;
250 			wlan_dlm_add_bssid_to_reject_list(mac_ctx->pdev,
251 							  &ap_info);
252 
253 			/* only break for STA role (non TDLS) */
254 			break;
255 		}
256 		lim_delete_sta_util(mac_ctx, msg, session_entry);
257 		break;
258 
259 	case HAL_DEL_STA_REASON_CODE_UNKNOWN_A2:
260 		pe_err("Deleting Unknown station:  "QDF_MAC_ADDR_FMT,
261 		       QDF_MAC_ADDR_REF(msg->addr2));
262 		lim_send_deauth_mgmt_frame(mac_ctx,
263 			REASON_CLASS3_FRAME_FROM_NON_ASSOC_STA,
264 			msg->addr2, session_entry, false);
265 		break;
266 
267 	case HAL_DEL_STA_REASON_CODE_BTM_DISASSOC_IMMINENT:
268 		if (!lim_is_sb_disconnect_allowed(session_entry)) {
269 			qdf_mem_free(msg);
270 			lim_msg->bodyptr = NULL;
271 			return;
272 		}
273 		lim_send_deauth_mgmt_frame(mac_ctx,
274 				REASON_DISASSOC_BSS_TRANSITION ,
275 				session_entry->bssId, session_entry, false);
276 		lim_tear_down_link_with_ap(mac_ctx, session_entry->peSessionId,
277 					   REASON_DISASSOC_BSS_TRANSITION ,
278 					   eLIM_LINK_MONITORING_DEAUTH);
279 		break;
280 
281 	default:
282 		pe_err("Unknown reason code");
283 		break;
284 	}
285 	qdf_mem_free(msg);
286 	lim_msg->bodyptr = NULL;
287 	return;
288 }
289 
290 /**
291  * lim_trigger_sta_deletion() -
292  *          This function is called to trigger STA context deletion.
293  *
294  * @param  mac_ctx   - Pointer to global MAC structure
295  * @param  sta_ds - Pointer to internal STA Datastructure
296  * @session_entry: PE session entry
297 
298  * @return None
299  */
300 void
lim_trigger_sta_deletion(struct mac_context * mac_ctx,tpDphHashNode sta_ds,struct pe_session * session_entry)301 lim_trigger_sta_deletion(struct mac_context *mac_ctx, tpDphHashNode sta_ds,
302 			 struct pe_session *session_entry)
303 {
304 	tLimMlmDisassocInd mlm_disassoc_ind;
305 
306 	if (!sta_ds) {
307 		pe_warn("Skip STA deletion (invalid STA)");
308 		return;
309 	}
310 
311 	if ((sta_ds->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_STA_RSP_STATE) ||
312 		(sta_ds->mlmStaContext.mlmState ==
313 			eLIM_MLM_WT_DEL_BSS_RSP_STATE) ||
314 		sta_ds->sta_deletion_in_progress) {
315 		/* Already in the process of deleting context for the peer */
316 		pe_debug("Deletion is in progress (%d) for peer:%pK in mlmState %d",
317 			sta_ds->sta_deletion_in_progress, sta_ds->staAddr,
318 			sta_ds->mlmStaContext.mlmState);
319 		return;
320 	}
321 	sta_ds->sta_deletion_in_progress = true;
322 
323 	sta_ds->mlmStaContext.disassocReason =
324 		REASON_DISASSOC_DUE_TO_INACTIVITY;
325 	sta_ds->mlmStaContext.cleanupTrigger = eLIM_LINK_MONITORING_DISASSOC;
326 	qdf_mem_copy(&mlm_disassoc_ind.peerMacAddr, sta_ds->staAddr,
327 		sizeof(tSirMacAddr));
328 	mlm_disassoc_ind.reasonCode =
329 		REASON_DISASSOC_DUE_TO_INACTIVITY;
330 	mlm_disassoc_ind.disassocTrigger = eLIM_LINK_MONITORING_DISASSOC;
331 
332 	/* Update PE session Id */
333 	mlm_disassoc_ind.sessionId = session_entry->peSessionId;
334 	lim_post_sme_message(mac_ctx, LIM_MLM_DISASSOC_IND,
335 			(uint32_t *) &mlm_disassoc_ind);
336 	if (mac_ctx->mlme_cfg->gen.fatal_event_trigger)
337 		cds_flush_logs(WLAN_LOG_TYPE_FATAL,
338 				WLAN_LOG_INDICATOR_HOST_DRIVER,
339 				WLAN_LOG_REASON_HB_FAILURE,
340 				false, false);
341 	/* Issue Disassoc Indication to SME */
342 	lim_send_sme_disassoc_ind(mac_ctx, sta_ds, session_entry);
343 } /*** end lim_trigger_st_adeletion() ***/
344 
345 static void
lim_connectivity_bmiss_disconn_event(tpDphHashNode sta,struct wlan_objmgr_psoc * psoc,enum wlan_reason_code reason_code,uint32_t vdev_id)346 lim_connectivity_bmiss_disconn_event(tpDphHashNode sta,
347 				     struct wlan_objmgr_psoc *psoc,
348 				     enum wlan_reason_code reason_code,
349 				     uint32_t vdev_id)
350 {
351 	if (!(reason_code == REASON_BEACON_MISSED))
352 		return;
353 
354 	/*
355 	 * Firmware sends final bmiss indication as part of roam scan stats
356 	 * event. Disconn log is sent as part of the final bmiss indication
357 	 * from  roam scan stats event with specific reason. But if RSO stop
358 	 * or RSO deinit happens after first bmiss due to concurrent interface
359 	 * connection, then firmware doesn't send the final bmiss indication
360 	 * to driver since roam scan will be disabled. But final bmiss
361 	 * heartbeat failure will be indicated as part of WMI_ROAM_EVENTID with
362 	 * reason as BMISS. So generate DISCONN log in this case from host based
363 	 * on RSO state and final bmiss HB failure teardown.
364 	 */
365 	if (!(MLME_IS_ROAM_STATE_STOPPED(psoc, vdev_id) ||
366 	      MLME_IS_ROAM_STATE_DEINIT(psoc, vdev_id)))
367 		return;
368 
369 	cm_roam_beacon_loss_disconnect_event(psoc,
370 					     *(struct qdf_mac_addr *)sta->staAddr,
371 					     vdev_id);
372 }
373 
374 void
lim_tear_down_link_with_ap(struct mac_context * mac,uint8_t sessionId,enum wlan_reason_code reasonCode,enum eLimDisassocTrigger trigger)375 lim_tear_down_link_with_ap(struct mac_context *mac, uint8_t sessionId,
376 			   enum wlan_reason_code reasonCode,
377 			   enum eLimDisassocTrigger trigger)
378 {
379 	tpDphHashNode sta = NULL;
380 	tLimMlmDeauthInd mlmDeauthInd;
381 
382 	/* tear down the following pe_session */
383 	struct pe_session *pe_session;
384 
385 	pe_session = pe_find_session_by_session_id(mac, sessionId);
386 	if (!pe_session) {
387 		pe_err("Session Does not exist for given sessionID");
388 		return;
389 	}
390 
391 	pe_info("Session %d Vdev %d reason code %d trigger %d",
392 		pe_session->peSessionId, pe_session->vdev_id, reasonCode,
393 		trigger);
394 
395 	/* Add the check here in case caller missed the check */
396 	if (!lim_is_sb_disconnect_allowed(pe_session))
397 		return;
398 
399 	/**
400 	 * Heart beat failed for upto threshold value
401 	 * and AP did not respond for Probe request.
402 	 * Trigger link tear down.
403 	 */
404 	pe_session->pmmOffloadInfo.bcnmiss = false;
405 
406 	/* Delete all TDLS peers connected before leaving BSS */
407 	lim_delete_tdls_peers(mac, pe_session);
408 
409 	/* Announce loss of link to Roaming algorithm */
410 	/* and cleanup by sending SME_DISASSOC_REQ to SME */
411 
412 	sta = dph_get_hash_entry(mac, DPH_STA_HASH_INDEX_PEER,
413 				 &pe_session->dph.dphHashTable);
414 	if (!sta) {
415 		pe_debug("vdev:%d no sta hash entry for peer:" QDF_MAC_ADDR_FMT,
416 			 pe_session->vdev_id,
417 			 QDF_MAC_ADDR_REF(pe_session->bssId));
418 		return;
419 	}
420 
421 	if ((sta->mlmStaContext.disassocReason ==
422 	    REASON_DEAUTH_NETWORK_LEAVING) ||
423 	    (sta->mlmStaContext.cleanupTrigger ==
424 	    eLIM_HOST_DEAUTH)) {
425 		pe_err("Host already issued deauth, do nothing");
426 		return;
427 	}
428 
429 	sta->mlmStaContext.disassocReason = reasonCode;
430 	sta->mlmStaContext.cleanupTrigger = trigger;
431 	/* / Issue Deauth Indication to SME. */
432 	qdf_mem_copy((uint8_t *) &mlmDeauthInd.peerMacAddr,
433 		     sta->staAddr, sizeof(tSirMacAddr));
434 
435 	/*
436 	 * if deauth_before_connection is enabled and reasoncode is
437 	 * Beacon Missed Store the MAC of AP in the flip flop
438 	 * buffer. This MAC will be used to send Deauth before
439 	 * connection, if we connect to same AP after HB failure.
440 	 */
441 	if (mac->mlme_cfg->sta.deauth_before_connection &&
442 	    reasonCode == REASON_BEACON_MISSED) {
443 		int apCount = mac->lim.gLimHeartBeatApMacIndex;
444 
445 		if (mac->lim.gLimHeartBeatApMacIndex)
446 			mac->lim.gLimHeartBeatApMacIndex = 0;
447 		else
448 			mac->lim.gLimHeartBeatApMacIndex = 1;
449 
450 		pe_debug("HB Failure on MAC "
451 			 QDF_MAC_ADDR_FMT" Store it on Index %d",
452 			 QDF_MAC_ADDR_REF(sta->staAddr), apCount);
453 
454 		sir_copy_mac_addr(mac->lim.gLimHeartBeatApMac[apCount],
455 				  sta->staAddr);
456 	}
457 
458 	mlmDeauthInd.reasonCode =
459 		(uint8_t) sta->mlmStaContext.disassocReason;
460 	mlmDeauthInd.deauthTrigger =
461 		sta->mlmStaContext.cleanupTrigger;
462 
463 	if (LIM_IS_STA_ROLE(pe_session)) {
464 		lim_connectivity_bmiss_disconn_event(sta, mac->psoc, reasonCode,
465 						     pe_session->vdev_id);
466 
467 		lim_post_sme_message(mac, LIM_MLM_DEAUTH_IND,
468 				     (uint32_t *)&mlmDeauthInd);
469 	}
470 
471 	if (mac->mlme_cfg->gen.fatal_event_trigger)
472 		cds_flush_logs(WLAN_LOG_TYPE_FATAL,
473 				WLAN_LOG_INDICATOR_HOST_DRIVER,
474 				WLAN_LOG_REASON_HB_FAILURE,
475 				false, false);
476 
477 	lim_send_sme_deauth_ind(mac, sta, pe_session);
478 
479 } /*** lim_tear_down_link_with_ap() ***/
480 
481 /**
482  * lim_handle_heart_beat_failure() - handle hear beat failure in STA
483  *
484  * @mac_ctx: global MAC context
485  * @session: PE session entry
486  *
487  * This function is called when heartbeat (beacon reception)
488  * fails on STA
489  *
490  * Return: None
491  */
492 
lim_handle_heart_beat_failure(struct mac_context * mac_ctx,struct pe_session * session)493 void lim_handle_heart_beat_failure(struct mac_context *mac_ctx,
494 				   struct pe_session *session)
495 {
496 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
497 	host_log_beacon_update_pkt_type *log_ptr = NULL;
498 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
499 
500 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
501 	WLAN_HOST_DIAG_LOG_ALLOC(log_ptr, host_log_beacon_update_pkt_type,
502 				 LOG_WLAN_BEACON_UPDATE_C);
503 	if (log_ptr)
504 		log_ptr->bcn_rx_cnt = session->LimRxedBeaconCntDuringHB;
505 	WLAN_HOST_DIAG_LOG_REPORT(log_ptr);
506 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
507 
508 	if (LIM_IS_STA_ROLE(session) &&
509 	    lim_is_sb_disconnect_allowed(session)) {
510 		if (!mac_ctx->sys.gSysEnableLinkMonitorMode) {
511 			goto hb_handler_fail;
512 		}
513 
514 		/* Ignore HB if channel switch is in progress */
515 		if (session->gLimSpecMgmt.dot11hChanSwState ==
516 		   eLIM_11H_CHANSW_RUNNING) {
517 			pe_debug("Ignore Heartbeat failure as Channel switch is in progress");
518 			session->pmmOffloadInfo.bcnmiss = false;
519 			goto hb_handler_fail;
520 		}
521 		/* Beacon frame not received within heartbeat timeout. */
522 		pe_warn("Heartbeat Failure");
523 		mac_ctx->lim.gLimHBfailureCntInLinkEstState++;
524 
525 		/*
526 		 * Before host received beacon miss, firmware has checked link
527 		 * by sending QoS NULL data, don't need host send probe req.
528 		 * Some IoT AP can send probe response, but can't send beacon
529 		 * sometimes, need disconnect too, or firmware will assert.
530 		 */
531 		lim_send_deauth_mgmt_frame(mac_ctx,
532 					   REASON_DISASSOC_DUE_TO_INACTIVITY,
533 					   session->bssId,
534 					   session, false);
535 		lim_tear_down_link_with_ap(mac_ctx,
536 					   session->peSessionId,
537 					   REASON_BEACON_MISSED,
538 					   eLIM_LINK_MONITORING_DEAUTH);
539 	} else {
540 		/**
541 		 * Heartbeat timer may have timed out
542 		 * while we're doing background scanning/learning
543 		 * or in states other than link-established state.
544 		 * Log error.
545 		 */
546 		pe_debug("received heartbeat timeout in state %X",
547 			session->limMlmState);
548 		lim_print_mlm_state(mac_ctx, LOG1, session->limMlmState);
549 		mac_ctx->lim.gLimHBfailureCntInOtherStates++;
550 	}
551 
552 hb_handler_fail:
553 	if (mac_ctx->sme.tx_queue_cb)
554 		mac_ctx->sme.tx_queue_cb(mac_ctx->hdd_handle,
555 					 session->smeSessionId,
556 					 WLAN_WAKE_ALL_NETIF_QUEUE,
557 					 WLAN_CONTROL_PATH);
558 }
559 
lim_rx_invalid_peer_process(struct mac_context * mac_ctx,struct scheduler_msg * lim_msg)560 void lim_rx_invalid_peer_process(struct mac_context *mac_ctx,
561 				 struct scheduler_msg *lim_msg)
562 {
563 	struct ol_rx_inv_peer_params *msg =
564 			(struct ol_rx_inv_peer_params *)lim_msg->bodyptr;
565 	struct pe_session *session_entry;
566 	uint16_t reason_code = REASON_CLASS3_FRAME_FROM_NON_ASSOC_STA;
567 	uint16_t aid;
568 	tpDphHashNode sta_ds;
569 
570 	if (!msg) {
571 		pe_err("Invalid body pointer in message");
572 		return;
573 	}
574 
575 	session_entry = pe_find_session_by_vdev_id(mac_ctx, msg->vdev_id);
576 	if (!session_entry) {
577 		pe_err_rl("session not found for given sme session");
578 		qdf_mem_free(msg);
579 		return;
580 	}
581 
582 	/* only if SAP mode */
583 	if (session_entry->bssType == eSIR_INFRA_AP_MODE) {
584 		sta_ds = dph_lookup_hash_entry(mac_ctx, msg->ta, &aid,
585 					       &session_entry->dph.dphHashTable);
586 		if (sta_ds && sta_ds->is_key_installed) {
587 			/*
588 			 * Skip deauth for an associated STA.
589 			 *
590 			 * The deauth sent for invalid peer indication will
591 			 * not cleanup the SM if this is an associated STA.
592 			 * Therefore, the deauth for associated STA creates
593 			 * stale entries even after STA gets disconnected.
594 			 */
595 			pe_err_rl("Received Invalid rx peer indication for an associated STA "
596 			       QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(msg->ta));
597 			qdf_mem_free(msg);
598 			lim_msg->bodyptr = NULL;
599 			return;
600 		}
601 		pe_debug("send deauth frame to non-assoc STA");
602 		lim_send_deauth_mgmt_frame(mac_ctx,
603 					   reason_code,
604 					   msg->ta,
605 					   session_entry,
606 					   false);
607 	}
608 
609 	qdf_mem_free(msg);
610 	lim_msg->bodyptr = NULL;
611 }
612 
lim_req_send_delba_ind_process(struct mac_context * mac_ctx,struct scheduler_msg * lim_msg)613 void lim_req_send_delba_ind_process(struct mac_context *mac_ctx,
614 				    struct scheduler_msg *lim_msg)
615 {
616 	struct lim_delba_req_info *req =
617 			(struct lim_delba_req_info *)lim_msg->bodyptr;
618 	QDF_STATUS status;
619 	void *dp_soc = cds_get_context(QDF_MODULE_ID_SOC);
620 
621 	if (!req) {
622 		pe_err("Invalid body pointer in message");
623 		return;
624 	}
625 
626 	status = lim_send_delba_action_frame(mac_ctx, req->vdev_id,
627 					     req->peer_macaddr,
628 					     req->tid, req->reason_code);
629 	if (status != QDF_STATUS_SUCCESS)
630 		cdp_delba_tx_completion(dp_soc, req->peer_macaddr,
631 					req->vdev_id, req->tid,
632 					WMI_MGMT_TX_COMP_TYPE_DISCARD);
633 	qdf_mem_free(req);
634 	lim_msg->bodyptr = NULL;
635 }
636