1  /*
2   * Copyright (c) 2011-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  #include "cds_api.h"
21  #include "wni_cfg.h"
22  #include "ani_global.h"
23  #include "sir_api.h"
24  #include "sir_params.h"
25  #include "cfg_ucfg_api.h"
26  #include "sch_api.h"
27  #include "utils_api.h"
28  #include "lim_utils.h"
29  #include "lim_assoc_utils.h"
30  #include "lim_prop_exts_utils.h"
31  #include "lim_security_utils.h"
32  #include "lim_send_messages.h"
33  #include "lim_send_messages.h"
34  #include "lim_session_utils.h"
35  #include <lim_ft.h>
36  #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
37  #include "host_diag_core_log.h"
38  #endif
39  #include "wma_if.h"
40  #include "wma.h"
41  #include "wlan_reg_services_api.h"
42  #include "lim_process_fils.h"
43  #include "wlan_mlme_public_struct.h"
44  #include "../../core/src/vdev_mgr_ops.h"
45  #include "wlan_pmo_ucfg_api.h"
46  #include "wlan_cp_stats_utils_api.h"
47  #include "wlan_objmgr_vdev_obj.h"
48  #include <wlan_cm_api.h>
49  #include <lim_mlo.h>
50  #include "wlan_mlo_mgr_peer.h"
51  #include <son_api.h>
52  #include "wifi_pos_pasn_api.h"
53  #include "rrm_api.h"
54  #include "../../core/src/wlan_cp_stats_obj_mgr_handler.h"
55  
56  static void lim_process_mlm_auth_req(struct mac_context *, uint32_t *);
57  static void lim_process_mlm_assoc_req(struct mac_context *, uint32_t *);
58  static void lim_process_mlm_disassoc_req(struct mac_context *, uint32_t *);
59  
60  /* MLM Timeout event handler templates */
61  static void lim_process_auth_rsp_timeout(struct mac_context *, uint32_t);
62  static void lim_process_periodic_join_probe_req_timer(struct mac_context *);
63  static void lim_process_auth_retry_timer(struct mac_context *);
64  
lim_fill_status_code(uint8_t frame_type,enum tx_ack_status ack_status,enum wlan_status_code * proto_status_code)65  static void lim_fill_status_code(uint8_t frame_type,
66  				 enum tx_ack_status ack_status,
67  				 enum wlan_status_code *proto_status_code)
68  {
69  	if (frame_type == SIR_MAC_MGMT_AUTH) {
70  		switch (ack_status) {
71  		case LIM_TX_FAILED:
72  			*proto_status_code = STATUS_AUTH_TX_FAIL;
73  			break;
74  		case LIM_ACK_RCD_FAILURE:
75  		case LIM_ACK_NOT_RCD:
76  			*proto_status_code = STATUS_AUTH_NO_ACK_RECEIVED;
77  			break;
78  		case LIM_ACK_RCD_SUCCESS:
79  			*proto_status_code = STATUS_AUTH_NO_RESP_RECEIVED;
80  			break;
81  		default:
82  			*proto_status_code = STATUS_UNSPECIFIED_FAILURE;
83  		}
84  	} else if (frame_type == SIR_MAC_MGMT_ASSOC_RSP) {
85  		switch (ack_status) {
86  		case LIM_TX_FAILED:
87  			*proto_status_code = STATUS_ASSOC_TX_FAIL;
88  			break;
89  		case LIM_ACK_RCD_FAILURE:
90  		case LIM_ACK_NOT_RCD:
91  			*proto_status_code = STATUS_ASSOC_NO_ACK_RECEIVED;
92  			break;
93  		case LIM_ACK_RCD_SUCCESS:
94  			*proto_status_code = STATUS_ASSOC_NO_RESP_RECEIVED;
95  			break;
96  		default:
97  			*proto_status_code = STATUS_UNSPECIFIED_FAILURE;
98  		}
99  	}
100  }
101  
lim_process_rrm_sta_stats_rsp_timeout(struct mac_context * mac)102  void lim_process_rrm_sta_stats_rsp_timeout(struct mac_context *mac)
103  {
104  	struct pe_session *session;
105  	tSirMacRadioMeasureReport rrm_report;
106  	QDF_STATUS status;
107  	uint8_t index;
108  	tpRRMReq pcurrent_req = NULL;
109  	tRrmRetStatus rrm_status;
110  
111  	session = pe_find_session_by_session_id(mac,
112  		mac->lim.lim_timers.rrm_sta_stats_resp_timer.sessionId);
113  	if (!session) {
114  		pe_err("Session does not exist for given session id %d",
115  		       mac->lim.lim_timers.rrm_sta_stats_resp_timer.sessionId);
116  		rrm_cleanup(mac, mac->rrm.rrmPEContext.rrm_sta_stats.index);
117  		return;
118  	}
119  
120  	pe_warn("STA STATS RSP timeout vdev_id %d", session->vdev_id);
121  	index = mac->rrm.rrmPEContext.rrm_sta_stats.index;
122  	pcurrent_req = mac->rrm.rrmPEContext.pCurrentReq[index];
123  	if (!pcurrent_req) {
124  		pe_err("Current request is NULL for index %d", index);
125  		qdf_mem_zero(&mac->rrm.rrmPEContext.rrm_sta_stats,
126  			     sizeof(mac->rrm.rrmPEContext.rrm_sta_stats));
127  		return;
128  	}
129  
130  	if (!mac->rrm.rrmPEContext.rrm_sta_stats.rrm_sta_stats_res_count) {
131  		pe_err("response not received for previous req");
132  		rrm_status = eRRM_INCAPABLE;
133  		goto err;
134  	}
135  
136  	rrm_report = mac->rrm.rrmPEContext.rrm_sta_stats.rrm_report;
137  	switch (rrm_report.report.statistics_report.group_id) {
138  	/*
139  	 * For Counter stats and Mac stats some stats will be received
140  	 * via FW and some via DP. So, same handling is required for both
141  	 * cases.
142  	 */
143  	case STA_STAT_GROUP_ID_COUNTER_STATS:
144  	case STA_STAT_GROUP_ID_MAC_STATS:
145  		status = wlan_cp_stats_infra_cp_deregister_resp_cb(mac->psoc);
146  		if (QDF_IS_STATUS_ERROR(status))
147  			pe_err("failed to deregister callback %d", status);
148  
149  		status =
150  			rrm_send_sta_stats_req(
151  				mac, session,
152  				mac->rrm.rrmPEContext.rrm_sta_stats.peer);
153  		if (QDF_IS_STATUS_ERROR(status)) {
154  			pe_err("fail to send stats req");
155  			rrm_status = eRRM_FAILURE;
156  			goto err;
157  		}
158  		break;
159  	case STA_STAT_GROUP_ID_DELAY_STATS:
160  		/* TOdo: fetch from scan ie */
161  		break;
162  	}
163  	return;
164  err:
165  	rrm_process_rrm_sta_stats_request_failure(
166  		mac, session, mac->rrm.rrmPEContext.rrm_sta_stats.peer,
167  		rrm_status, mac->rrm.rrmPEContext.rrm_sta_stats.index);
168  	rrm_cleanup(mac, mac->rrm.rrmPEContext.rrm_sta_stats.index);
169  }
170  
lim_process_sae_auth_timeout(struct mac_context * mac_ctx)171  void lim_process_sae_auth_timeout(struct mac_context *mac_ctx)
172  {
173  	struct pe_session *session;
174  	enum wlan_status_code proto_status_code;
175  
176  	session = pe_find_session_by_session_id(mac_ctx,
177  			mac_ctx->lim.lim_timers.sae_auth_timer.sessionId);
178  	if (!session) {
179  		pe_err("Session does not exist for given session id");
180  		return;
181  	}
182  
183  	pe_warn("SAE auth timeout sessionid %d mlmstate %X SmeState %X",
184  		session->peSessionId, session->limMlmState,
185  		session->limSmeState);
186  
187  	switch (session->limMlmState) {
188  	case eLIM_MLM_WT_SAE_AUTH_STATE:
189  		lim_fill_status_code(SIR_MAC_MGMT_AUTH,
190  				     mac_ctx->auth_ack_status,
191  				     &proto_status_code);
192  		/*
193  		 * SAE authentication is not completed. Restore from
194  		 * auth state.
195  		 */
196  		if ((session->opmode == QDF_STA_MODE) ||
197  		    (session->opmode == QDF_P2P_CLIENT_MODE))
198  			lim_restore_from_auth_state(mac_ctx,
199  				eSIR_SME_AUTH_TIMEOUT_RESULT_CODE,
200  				proto_status_code, session);
201  		break;
202  	default:
203  		/* SAE authentication is timed out in unexpected state */
204  		pe_err("received unexpected SAE auth timeout in state %X",
205  			session->limMlmState);
206  		lim_print_mlm_state(mac_ctx, LOGE, session->limMlmState);
207  		break;
208  	}
209  }
210  
211  /**
212   * lim_process_mlm_req_messages() - process mlm request messages
213   * @mac_ctx: global MAC context
214   * @msg: mlm request message
215   *
216   * This function is called by lim_post_mlm_message(). This
217   * function handles MLM primitives invoked by SME.
218   * Depending on the message type, corresponding function will be
219   * called.
220   * ASSUMPTIONS:
221   * 1. Upon receiving Beacon in WT_JOIN_STATE, MLM module invokes
222   *    APIs exposed by Beacon Processing module for setting parameters
223   *    at MAC hardware.
224   * 2. If attempt to Reassociate with an AP fails, link with current
225   *    AP is restored back.
226   *
227   * Return: None
228   */
lim_process_mlm_req_messages(struct mac_context * mac_ctx,struct scheduler_msg * msg)229  void lim_process_mlm_req_messages(struct mac_context *mac_ctx,
230  				  struct scheduler_msg *msg)
231  {
232  	switch (msg->type) {
233  	case LIM_MLM_AUTH_REQ:
234  		lim_process_mlm_auth_req(mac_ctx, msg->bodyptr);
235  		break;
236  	case LIM_MLM_ASSOC_REQ:
237  		lim_process_mlm_assoc_req(mac_ctx, msg->bodyptr);
238  		break;
239  	case LIM_MLM_DISASSOC_REQ:
240  		lim_process_mlm_disassoc_req(mac_ctx, msg->bodyptr);
241  		break;
242  	case SIR_LIM_JOIN_FAIL_TIMEOUT:
243  		lim_process_join_failure_timeout(mac_ctx);
244  		break;
245  	case SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT:
246  		lim_process_periodic_join_probe_req_timer(mac_ctx);
247  		break;
248  	case SIR_LIM_AUTH_FAIL_TIMEOUT:
249  		lim_process_auth_failure_timeout(mac_ctx);
250  		break;
251  	case SIR_LIM_AUTH_RSP_TIMEOUT:
252  		lim_process_auth_rsp_timeout(mac_ctx, msg->bodyval);
253  		break;
254  	case SIR_LIM_ASSOC_FAIL_TIMEOUT:
255  		lim_process_assoc_failure_timeout(mac_ctx, msg->bodyval);
256  		break;
257  	case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT:
258  		lim_process_ft_preauth_rsp_timeout(mac_ctx);
259  		break;
260  	case SIR_LIM_DISASSOC_ACK_TIMEOUT:
261  		lim_process_disassoc_ack_timeout(mac_ctx);
262  		break;
263  	case SIR_LIM_AUTH_RETRY_TIMEOUT:
264  		lim_process_auth_retry_timer(mac_ctx);
265  		break;
266  	case SIR_LIM_AUTH_SAE_TIMEOUT:
267  		lim_process_sae_auth_timeout(mac_ctx);
268  		break;
269  	case SIR_LIM_RRM_STA_STATS_RSP_TIMEOUT:
270  		lim_process_rrm_sta_stats_rsp_timeout(mac_ctx);
271  		break;
272  	case LIM_MLM_TSPEC_REQ:
273  	default:
274  		break;
275  	} /* switch (msg->type) */
276  }
277  
update_rmfEnabled(struct bss_params * addbss_param,struct pe_session * session)278  static void update_rmfEnabled(struct bss_params *addbss_param,
279  			      struct pe_session *session)
280  {
281  	addbss_param->rmfEnabled = session->limRmfEnabled;
282  }
283  
284  /**
285   * lim_mlm_add_bss() - HAL interface for WMA_ADD_BSS_REQ
286   * @mac_ctx: global MAC context
287   * @mlm_start_req: MLM start request
288   * @session: PE session entry
289   *
290   * Package WMA_ADD_BSS_REQ to HAL, in order to start a BSS
291   *
292   * Return: eSIR_SME_SUCCESS on success, other error codes otherwise
293   */
294  tSirResultCodes
lim_mlm_add_bss(struct mac_context * mac_ctx,tLimMlmStartReq * mlm_start_req,struct pe_session * session)295  lim_mlm_add_bss(struct mac_context *mac_ctx,
296  		tLimMlmStartReq *mlm_start_req, struct pe_session *session)
297  {
298  	struct vdev_mlme_obj *mlme_obj;
299  	struct wlan_objmgr_vdev *vdev = session->vdev;
300  	uint8_t vdev_id = session->vdev_id;
301  	QDF_STATUS status = QDF_STATUS_SUCCESS;
302  	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
303  	struct bss_params *addbss_param = NULL;
304  
305  	if (!wma)
306  		return eSIR_SME_INVALID_PARAMETERS;
307  
308  	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev);
309  	if (!mlme_obj) {
310  		pe_err("vdev component object is NULL");
311  		return eSIR_SME_INVALID_PARAMETERS;
312  	}
313  
314  	qdf_mem_copy(mlme_obj->mgmt.generic.bssid, mlm_start_req->bssId,
315  		     QDF_MAC_ADDR_SIZE);
316  	if (lim_is_session_he_capable(session)) {
317  		lim_decide_he_op(mac_ctx, &mlme_obj->proto.he_ops_info.he_ops,
318  				 session);
319  		lim_update_usr_he_cap(mac_ctx, session);
320  	}
321  
322  #ifdef WLAN_FEATURE_11BE
323  	if (lim_is_session_eht_capable(session)) {
324  		lim_decide_eht_op(mac_ctx,
325  				  &mlme_obj->proto.eht_ops_info.eht_ops,
326  				  session);
327  		lim_update_usr_eht_cap(mac_ctx, session);
328  	}
329  #endif
330  
331  	/* Set a new state for MLME */
332  	session->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_STATE;
333  	MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session->peSessionId,
334  			 session->limMlmState));
335  
336  	status = lim_pre_vdev_start(mac_ctx, mlme_obj, session);
337  	if (QDF_IS_STATUS_ERROR(status))
338  		goto send_fail_resp;
339  
340  	 addbss_param = qdf_mem_malloc(sizeof(struct bss_params));
341  	if (!addbss_param)
342  		goto send_fail_resp;
343  
344  	addbss_param->vhtCapable = mlm_start_req->htCapable;
345  	addbss_param->htCapable = session->vhtCapability;
346  	addbss_param->ch_width = session->ch_width;
347  	update_rmfEnabled(addbss_param, session);
348  	addbss_param->staContext.fShortGI20Mhz =
349  		lim_get_ht_capability(mac_ctx, eHT_SHORT_GI_20MHZ, session);
350  	addbss_param->staContext.fShortGI40Mhz =
351  		lim_get_ht_capability(mac_ctx, eHT_SHORT_GI_40MHZ, session);
352  	status = wma_pre_vdev_start_setup(vdev_id, addbss_param);
353  	qdf_mem_free(addbss_param);
354  	if (QDF_IS_STATUS_ERROR(status))
355  		goto send_fail_resp;
356  
357  	if (session->wps_state == SAP_WPS_DISABLED)
358  		ucfg_pmo_disable_wakeup_event(wma->psoc, vdev_id,
359  					      WOW_PROBE_REQ_WPS_IE_EVENT);
360  	status = wma_vdev_pre_start(vdev_id, false);
361  	if (QDF_IS_STATUS_ERROR(status))
362  		goto peer_cleanup;
363  	status = vdev_mgr_start_send(mlme_obj, false);
364  	if (QDF_IS_STATUS_ERROR(status))
365  		goto peer_cleanup;
366  	wma_post_vdev_start_setup(vdev_id);
367  
368  	return eSIR_SME_SUCCESS;
369  
370  peer_cleanup:
371  	wma_remove_bss_peer_on_failure(wma, vdev_id);
372  send_fail_resp:
373  	wma_send_add_bss_resp(wma, vdev_id, QDF_STATUS_E_FAILURE);
374  
375  	return eSIR_SME_SUCCESS;
376  }
377  
lim_process_mlm_start_req(struct mac_context * mac_ctx,tLimMlmStartReq * mlm_start_req)378  void lim_process_mlm_start_req(struct mac_context *mac_ctx,
379  			       tLimMlmStartReq *mlm_start_req)
380  {
381  	tLimMlmStartCnf mlm_start_cnf;
382  	struct pe_session *session = NULL;
383  
384  	if (!mlm_start_req) {
385  		pe_err("Buffer is Pointing to NULL");
386  		return;
387  	}
388  
389  	session = pe_find_session_by_session_id(mac_ctx,
390  				mlm_start_req->sessionId);
391  	if (!session) {
392  		pe_err("Session Does not exist for given sessionID");
393  		mlm_start_cnf.resultCode = eSIR_SME_REFUSED;
394  		goto end;
395  	}
396  
397  	if (session->limMlmState != eLIM_MLM_IDLE_STATE) {
398  		/*
399  		 * Should not have received Start req in states other than idle.
400  		 * Return Start confirm with failure code.
401  		 */
402  		pe_err("received unexpected MLM_START_REQ in state %X",
403  			session->limMlmState);
404  		lim_print_mlm_state(mac_ctx, LOGE, session->limMlmState);
405  		mlm_start_cnf.resultCode =
406  				eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED;
407  		goto end;
408  	}
409  
410  	mlm_start_cnf.resultCode =
411  		lim_mlm_add_bss(mac_ctx, mlm_start_req, session);
412  
413  end:
414  	/* Update PE session Id */
415  	mlm_start_cnf.sessionId = mlm_start_req->sessionId;
416  
417  	/*
418  	 * Respond immediately to LIM, only if MLME has not been
419  	 * successfully able to send WMA_ADD_BSS_REQ to HAL.
420  	 * Else, LIM_MLM_START_CNF will be sent after receiving
421  	 * WMA_ADD_BSS_RSP from HAL
422  	 */
423  	if (eSIR_SME_SUCCESS != mlm_start_cnf.resultCode)
424  		lim_send_start_bss_confirm(mac_ctx, &mlm_start_cnf);
425  }
426  
427  #if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
428  void
lim_pasn_peer_del_all_resp_vdev_delete_resume(struct mac_context * mac,struct wlan_objmgr_vdev * vdev)429  lim_pasn_peer_del_all_resp_vdev_delete_resume(struct mac_context *mac,
430  					      struct wlan_objmgr_vdev *vdev)
431  {
432  	if (!mac) {
433  		pe_err("Mac ctx is NULL");
434  		return;
435  	}
436  
437  	/*
438  	 * If PASN peer delete all command to firmware timedout, then
439  	 * the PASN peers will not be cleaned up. So cleanup the
440  	 * objmgr peers from here and reset the peer delete all in
441  	 * progress flag.
442  	 */
443  	if (wifi_pos_get_pasn_peer_count(vdev))
444  		wifi_pos_cleanup_pasn_peers(mac->psoc, vdev);
445  
446  	wifi_pos_set_delete_all_peer_in_progress(vdev, false);
447  
448  	pe_debug("Resume vdev delete");
449  	if (mac->sme.sme_vdev_del_cb)
450  		mac->sme.sme_vdev_del_cb(MAC_HANDLE(mac), vdev);
451  }
452  #endif
453  
lim_send_peer_create_resp(struct mac_context * mac,uint8_t vdev_id,QDF_STATUS qdf_status,uint8_t * peer_mac)454  void lim_send_peer_create_resp(struct mac_context *mac, uint8_t vdev_id,
455  			       QDF_STATUS qdf_status, uint8_t *peer_mac)
456  {
457  	struct wlan_objmgr_vdev *vdev;
458  	QDF_STATUS status;
459  
460  	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc,
461  						    vdev_id,
462  						    WLAN_LEGACY_MAC_ID);
463  	if (!vdev)
464  		return;
465  	status = wlan_cm_bss_peer_create_rsp(vdev, qdf_status,
466  					     (struct qdf_mac_addr *)peer_mac);
467  
468  	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
469  }
470  
471  static void
lim_process_mlm_post_join_suspend_link(struct mac_context * mac_ctx,struct pe_session * session)472  lim_process_mlm_post_join_suspend_link(struct mac_context *mac_ctx,
473  				       struct pe_session *session)
474  {
475  	lim_deactivate_and_change_timer(mac_ctx, eLIM_JOIN_FAIL_TIMER);
476  
477  	/* assign appropriate sessionId to the timer object */
478  	mac_ctx->lim.lim_timers.gLimJoinFailureTimer.sessionId =
479  		session->peSessionId;
480  
481  	/*
482  	 * store the channel switch session_entry in the lim
483  	 * global variable
484  	 */
485  	session->channelChangeReasonCode = LIM_SWITCH_CHANNEL_JOIN;
486  	session->pLimMlmReassocRetryReq = NULL;
487  	lim_send_switch_chnl_params(mac_ctx, session);
488  }
489  
490  /**
491   * lim_process_mlm_join_req() - process mlm join request.
492   *
493   * @mac_ctx:    Pointer to Global MAC structure
494   * @mlm_join_req:        Pointer to the mlme join request
495   *
496   * This function is called to process MLM_JOIN_REQ message
497   * from SME. It does following:
498   * 1) Initialize LIM, HAL, DPH
499   * 2) Configure the BSS for which the JOIN REQ was received
500   *   a) Send WMA_ADD_BSS_REQ to HAL -
501   *   This will identify the BSS that we are interested in
502   *   --AND--
503   *   Add a STA entry for the AP (in a STA context)
504   *   b) Wait for WMA_ADD_BSS_RSP
505   *   c) Send WMA_ADD_STA_REQ to HAL
506   *   This will add the "local STA" entry to the STA table
507   * 3) Continue as before, i.e,
508   *   a) Send a PROBE REQ
509   *   b) Wait for PROBE RSP/BEACON containing the SSID that
510   *   we are interested in
511   *   c) Then start an AUTH seq
512   *   d) Followed by the ASSOC seq
513   *
514   * @Return: None
515   */
lim_process_mlm_join_req(struct mac_context * mac_ctx,tLimMlmJoinReq * mlm_join_req)516  void lim_process_mlm_join_req(struct mac_context *mac_ctx,
517  			      tLimMlmJoinReq *mlm_join_req)
518  {
519  	uint8_t sessionid;
520  	struct pe_session *session;
521  
522  	sessionid = mlm_join_req->sessionId;
523  
524  	session = pe_find_session_by_session_id(mac_ctx, sessionid);
525  	if (!session) {
526  		pe_err("SessionId:%d does not exist", sessionid);
527  		return;
528  	}
529  
530  	session->pLimMlmJoinReq = mlm_join_req;
531  	lim_process_mlm_post_join_suspend_link(mac_ctx, session);
532  }
533  
534  /**
535   * lim_is_auth_req_expected() - check if auth request is expected
536   *
537   * @mac_ctx: global MAC context
538   * @session: PE session entry
539   *
540   * This function is called by lim_process_mlm_auth_req to check
541   * if auth request is expected.
542   *
543   * Return: true if expected and false otherwise
544   */
lim_is_auth_req_expected(struct mac_context * mac_ctx,struct pe_session * session)545  static bool lim_is_auth_req_expected(struct mac_context *mac_ctx,
546  				     struct pe_session *session)
547  {
548  	bool flag = false;
549  
550  	/*
551  	 * Expect Auth request only when:
552  	 * 1. STA joined/associated with a BSS or
553  	 * 2. STA is going to authenticate with a unicast
554  	 * address and requested authentication algorithm is
555  	 * supported.
556  	 */
557  
558  	flag = (((LIM_IS_STA_ROLE(session) &&
559  		 ((session->limMlmState == eLIM_MLM_JOINED_STATE) ||
560  		  (session->limMlmState ==
561  					eLIM_MLM_LINK_ESTABLISHED_STATE)))) &&
562  		(!IEEE80211_IS_MULTICAST(
563  			mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr)) &&
564  		 lim_is_auth_algo_supported(mac_ctx,
565  			mac_ctx->lim.gpLimMlmAuthReq->authType, session));
566  
567  	return flag;
568  }
569  
570  /**
571   * lim_is_preauth_ctx_exists() - check if preauth context exists
572   * @mac_ctx:          global MAC context
573   * @session:          PE session entry
574   * @preauth_node_ptr: pointer to preauth node pointer
575   *
576   * This function is called by lim_process_mlm_auth_req to check
577   * if preauth context already exists
578   *
579   * Return: true if exists and false otherwise
580   */
lim_is_preauth_ctx_exists(struct mac_context * mac_ctx,struct pe_session * session,struct tLimPreAuthNode ** preauth_node_ptr)581  static bool lim_is_preauth_ctx_exists(struct mac_context *mac_ctx,
582  				      struct pe_session *session,
583  				      struct tLimPreAuthNode **preauth_node_ptr)
584  {
585  	bool fl = false;
586  	struct tLimPreAuthNode *preauth_node;
587  	tpDphHashNode stads;
588  	tSirMacAddr curr_bssid;
589  
590  	preauth_node = *preauth_node_ptr;
591  	sir_copy_mac_addr(curr_bssid, session->bssId);
592  	stads = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
593  				   &session->dph.dphHashTable);
594  	preauth_node = lim_search_pre_auth_list(mac_ctx,
595  				mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr);
596  
597  	fl = (((LIM_IS_STA_ROLE(session)) &&
598  	       (session->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) &&
599  	      ((stads) &&
600  	       (mac_ctx->lim.gpLimMlmAuthReq->authType ==
601  			stads->mlmStaContext.authType)) &&
602  	       (!qdf_mem_cmp(mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr,
603  			curr_bssid, sizeof(tSirMacAddr)))) ||
604  	      ((preauth_node) &&
605  	       (preauth_node->authType ==
606  			mac_ctx->lim.gpLimMlmAuthReq->authType)));
607  
608  	return fl;
609  }
610  
611  #ifdef WLAN_FEATURE_SAE
612  static inline
lim_get_sae_keymgmt_suite(uint32_t keymgmt)613  uint32_t lim_get_sae_keymgmt_suite(uint32_t keymgmt)
614  {
615  	/* Select the best SAE AKM suite supported */
616  	if (QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_FT_SAE_EXT_KEY))
617  		return WLAN_AKM_FT_SAE_EXT_KEY;
618  	else if (QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY))
619  		return WLAN_AKM_SAE_EXT_KEY;
620  	else if (QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_FT_SAE))
621  		return WLAN_AKM_FT_SAE;
622  	else if (QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_SAE))
623  		return WLAN_AKM_SAE;
624  
625  	pe_err("Invalid SAE Keymgmt suite %d", keymgmt);
626  	return WLAN_AKM_SAE;
627  }
628  
lim_trigger_auth_req_sae(struct mac_context * mac_ctx,struct pe_session * session,struct qdf_mac_addr * peer_bssid)629  QDF_STATUS lim_trigger_auth_req_sae(struct mac_context *mac_ctx,
630  				    struct pe_session *session,
631  				    struct qdf_mac_addr *peer_bssid)
632  {
633  	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
634  	struct sir_sae_info *sae_info;
635  	struct scheduler_msg msg = {0};
636  	uint32_t keymgmt;
637  
638  	sae_info = qdf_mem_malloc(sizeof(*sae_info));
639  	if (!sae_info)
640  		return QDF_STATUS_E_FAILURE;
641  
642  	sae_info->msg_type = eWNI_SME_TRIGGER_SAE;
643  	sae_info->msg_len = sizeof(*sae_info);
644  	sae_info->vdev_id = session->smeSessionId;
645  
646  	qdf_copy_macaddr(&sae_info->peer_mac_addr, peer_bssid);
647  	keymgmt = wlan_crypto_get_param(session->vdev,
648  					WLAN_CRYPTO_PARAM_KEY_MGMT);
649  	sae_info->akm = lim_get_sae_keymgmt_suite(keymgmt);
650  
651  	sae_info->ssid.length = session->ssId.length;
652  	qdf_mem_copy(sae_info->ssid.ssId,
653  		session->ssId.ssId,
654  		session->ssId.length);
655  
656  	pe_debug("vdev_id %d ssid " QDF_SSID_FMT " " QDF_MAC_ADDR_FMT "akm %d",
657  		 sae_info->vdev_id,
658  		 QDF_SSID_REF(sae_info->ssid.length, sae_info->ssid.ssId),
659  		 QDF_MAC_ADDR_REF(sae_info->peer_mac_addr.bytes),
660  		 sae_info->akm);
661  
662  	msg.type = eWNI_SME_TRIGGER_SAE;
663  	msg.bodyptr = sae_info;
664  	msg.bodyval = 0;
665  
666  	qdf_status = mac_ctx->lim.sme_msg_callback(mac_ctx, &msg);
667  	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
668  		pe_err("SAE failed for AUTH frame");
669  		qdf_mem_free(sae_info);
670  		return qdf_status;
671  	}
672  
673  	return qdf_status;
674  }
675  
676  /**
677   * lim_process_mlm_auth_req_sae() - Handle SAE authentication
678   * @mac_ctx: global MAC context
679   * @session: PE session entry
680   *
681   * This function is called by lim_process_mlm_auth_req to handle SAE
682   * authentication.
683   *
684   * Return: QDF_STATUS
685   */
lim_process_mlm_auth_req_sae(struct mac_context * mac_ctx,struct pe_session * session)686  static QDF_STATUS lim_process_mlm_auth_req_sae(struct mac_context *mac_ctx,
687  					       struct pe_session *session)
688  {
689  	QDF_STATUS qdf_status;
690  
691  	qdf_status = lim_trigger_auth_req_sae(
692  					mac_ctx, session,
693  					(struct qdf_mac_addr *)session->bssId);
694  	if (QDF_IS_STATUS_ERROR(qdf_status))
695  		return qdf_status;
696  
697  	session->limMlmState = eLIM_MLM_WT_SAE_AUTH_STATE;
698  
699  	MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session->peSessionId,
700  		       session->limMlmState));
701  
702  	mac_ctx->lim.lim_timers.sae_auth_timer.sessionId =
703  					session->peSessionId;
704  
705  	/* Activate SAE auth timer */
706  	MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE,
707  			 session->peSessionId, eLIM_AUTH_SAE_TIMER));
708  	if (tx_timer_activate(&mac_ctx->lim.lim_timers.sae_auth_timer)
709  		    != TX_SUCCESS) {
710  		pe_err("could not start Auth SAE timer");
711  	}
712  
713  	return qdf_status;
714  }
715  #else
lim_process_mlm_auth_req_sae(struct mac_context * mac_ctx,struct pe_session * session)716  static QDF_STATUS lim_process_mlm_auth_req_sae(struct mac_context *mac_ctx,
717  		struct pe_session *session)
718  {
719  	return QDF_STATUS_E_NOSUPPORT;
720  }
721  #endif
722  
723  
724  /**
725   * lim_process_mlm_auth_req() - process lim auth request
726   *
727   * @mac_ctx:   global MAC context
728   * @msg:       MLM auth request message
729   *
730   * This function is called to process MLM_AUTH_REQ message from SME
731   *
732   * @Return: None
733   */
lim_process_mlm_auth_req(struct mac_context * mac_ctx,uint32_t * msg)734  static void lim_process_mlm_auth_req(struct mac_context *mac_ctx, uint32_t *msg)
735  {
736  	uint32_t num_preauth_ctx;
737  	tSirMacAddr curr_bssid;
738  	tSirMacAuthFrameBody *auth_frame_body;
739  	tLimMlmAuthCnf mlm_auth_cnf;
740  	struct tLimPreAuthNode *preauth_node = NULL;
741  	uint8_t session_id;
742  	struct pe_session *session;
743  
744  	if (!msg) {
745  		pe_err("Buffer is Pointing to NULL");
746  		return;
747  	}
748  
749  	mac_ctx->lim.gpLimMlmAuthReq = (tLimMlmAuthReq *) msg;
750  	session_id = mac_ctx->lim.gpLimMlmAuthReq->sessionId;
751  	session = pe_find_session_by_session_id(mac_ctx, session_id);
752  	if (!session) {
753  		pe_err("SessionId:%d does not exist", session_id);
754  		qdf_mem_free(msg);
755  		mac_ctx->lim.gpLimMlmAuthReq = NULL;
756  		return;
757  	}
758  
759  	pe_debug("vdev %d Systemrole %d mlmstate %d from: " QDF_MAC_ADDR_FMT "with authtype %d",
760  		 session->vdev_id, GET_LIM_SYSTEM_ROLE(session),
761  		 session->limMlmState,
762  		 QDF_MAC_ADDR_REF(mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr),
763  		 mac_ctx->lim.gpLimMlmAuthReq->authType);
764  
765  	sir_copy_mac_addr(curr_bssid, session->bssId);
766  
767  	if (!lim_is_auth_req_expected(mac_ctx, session)) {
768  		/*
769  		 * Unexpected auth request.
770  		 * Return Auth confirm with Invalid parameters code.
771  		 */
772  		pe_err("Auth req not expected is_privacy_enabled %d is_auth_open_system %d auth type %d",
773  			mac_ctx->mlme_cfg->wep_params.is_privacy_enabled,
774  			mac_ctx->mlme_cfg->wep_params.is_auth_open_system,
775  			mac_ctx->lim.gpLimMlmAuthReq->authType);
776  		mlm_auth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
777  		goto end;
778  	}
779  
780  	/*
781  	 * This is a request for pre-authentication. Check if there exists
782  	 * context already for the requested peer OR
783  	 * if this request is for the AP we're currently associated with.
784  	 * If yes, return auth confirm immediately when
785  	 * requested auth type is same as the one used before.
786  	 */
787  	if (lim_is_preauth_ctx_exists(mac_ctx, session, &preauth_node)) {
788  		pe_debug("Already have pre-auth context with peer: "
789  		    QDF_MAC_ADDR_FMT,
790  		    QDF_MAC_ADDR_REF(mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr));
791  		mlm_auth_cnf.resultCode = (tSirResultCodes)STATUS_SUCCESS;
792  		goto end;
793  	} else {
794  		num_preauth_ctx = mac_ctx->mlme_cfg->lfr.max_num_pre_auth;
795  		if (mac_ctx->lim.gLimNumPreAuthContexts == num_preauth_ctx) {
796  			pe_warn("Number of pre-auth reached max limit");
797  			/* Return Auth confirm with reject code */
798  			mlm_auth_cnf.resultCode =
799  				eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED;
800  			goto end;
801  		}
802  	}
803  
804  	/* Delete pre-auth node if exists */
805  	if (preauth_node)
806  		lim_delete_pre_auth_node(mac_ctx,
807  			 mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr);
808  
809  	session->limPrevMlmState = session->limMlmState;
810  
811  	auth_frame_body = qdf_mem_malloc(sizeof(*auth_frame_body));
812  	if (!auth_frame_body) {
813  		pe_err("mem alloc failed for auth frame body");
814  		return;
815  	}
816  
817  	if ((mac_ctx->lim.gpLimMlmAuthReq->authType == eSIR_AUTH_TYPE_SAE) &&
818  	     !session->sae_pmk_cached) {
819  		if (lim_process_mlm_auth_req_sae(mac_ctx, session) !=
820  					QDF_STATUS_SUCCESS) {
821  			mlm_auth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
822  			qdf_mem_free(auth_frame_body);
823  			goto end;
824  		} else {
825  			pe_debug("lim_process_mlm_auth_req_sae is successful");
826  			auth_frame_body->authAlgoNumber = eSIR_AUTH_TYPE_SAE;
827  			auth_frame_body->authTransactionSeqNumber =
828  							SIR_MAC_AUTH_FRAME_1;
829  			auth_frame_body->authStatusCode = 0;
830  			host_log_wlan_auth_info(auth_frame_body->authAlgoNumber,
831  				auth_frame_body->authTransactionSeqNumber,
832  				auth_frame_body->authStatusCode);
833  
834  			qdf_mem_free(auth_frame_body);
835  			return;
836  		}
837  	} else
838  		session->limMlmState = eLIM_MLM_WT_AUTH_FRAME2_STATE;
839  
840  	MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session->peSessionId,
841  		       session->limMlmState));
842  
843  	/* Mark auth algo as open when auth type is SAE and PMK is cached */
844  	if ((mac_ctx->lim.gpLimMlmAuthReq->authType == eSIR_AUTH_TYPE_SAE) &&
845  	   session->sae_pmk_cached) {
846  		auth_frame_body->authAlgoNumber = eSIR_OPEN_SYSTEM;
847  	} else {
848  		auth_frame_body->authAlgoNumber =
849  		(uint8_t) mac_ctx->lim.gpLimMlmAuthReq->authType;
850  	}
851  
852  	/* Prepare & send Authentication frame */
853  	auth_frame_body->authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_1;
854  	auth_frame_body->authStatusCode = 0;
855  	host_log_wlan_auth_info(auth_frame_body->authAlgoNumber,
856  				auth_frame_body->authTransactionSeqNumber,
857  				auth_frame_body->authStatusCode);
858  	mac_ctx->auth_ack_status = LIM_ACK_NOT_RCD;
859  	lim_send_auth_mgmt_frame(mac_ctx,
860  		auth_frame_body, mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr,
861  		LIM_NO_WEP_IN_FC, session);
862  
863  	/* assign appropriate session_id to the timer object */
864  	mac_ctx->lim.lim_timers.gLimAuthFailureTimer.sessionId = session_id;
865  
866  	/* assign appropriate sessionId to the timer object */
867  	 mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer.sessionId =
868  								  session_id;
869  	 lim_deactivate_and_change_timer(mac_ctx, eLIM_AUTH_RETRY_TIMER);
870  	/* Activate Auth failure timer */
871  	MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE,
872  			 session->peSessionId, eLIM_AUTH_FAIL_TIMER));
873  	 lim_deactivate_and_change_timer(mac_ctx, eLIM_AUTH_FAIL_TIMER);
874  	if (tx_timer_activate(&mac_ctx->lim.lim_timers.gLimAuthFailureTimer)
875  	    != TX_SUCCESS) {
876  		pe_err("could not start Auth failure timer");
877  		/* Cleanup as if auth timer expired */
878  		lim_process_auth_failure_timeout(mac_ctx);
879  	} else {
880  		MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE,
881  			   session->peSessionId, eLIM_AUTH_RETRY_TIMER));
882  		/* Activate Auth Retry timer */
883  		if (tx_timer_activate
884  		    (&mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer)
885  							      != TX_SUCCESS)
886  			pe_err("could not activate Auth Retry timer");
887  	}
888  
889  	qdf_mem_free(auth_frame_body);
890  
891  	return;
892  end:
893  	qdf_mem_copy((uint8_t *) &mlm_auth_cnf.peerMacAddr,
894  		     (uint8_t *) &mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr,
895  		     sizeof(tSirMacAddr));
896  
897  	mlm_auth_cnf.authType = mac_ctx->lim.gpLimMlmAuthReq->authType;
898  	mlm_auth_cnf.sessionId = session_id;
899  
900  	qdf_mem_free(mac_ctx->lim.gpLimMlmAuthReq);
901  	mac_ctx->lim.gpLimMlmAuthReq = NULL;
902  	pe_debug("SessionId:%d LimPostSme LIM_MLM_AUTH_CNF",
903  		session_id);
904  	lim_post_sme_message(mac_ctx, LIM_MLM_AUTH_CNF,
905  			     (uint32_t *) &mlm_auth_cnf);
906  }
907  
lim_store_pmfcomeback_timerinfo(struct pe_session * session_entry)908  static void lim_store_pmfcomeback_timerinfo(struct pe_session *session_entry)
909  {
910  	if (session_entry->opmode != QDF_STA_MODE ||
911  	    !session_entry->limRmfEnabled)
912  		return;
913  	/*
914  	 * Store current MLM state in case ASSOC response returns with
915  	 * TRY_AGAIN_LATER return code.
916  	 */
917  	session_entry->pmf_retry_timer_info.lim_prev_mlm_state =
918  		session_entry->limPrevMlmState;
919  	session_entry->pmf_retry_timer_info.lim_mlm_state =
920  		session_entry->limMlmState;
921  }
922  
923  /**
924   * lim_process_mlm_assoc_req() - This function is called to process
925   * MLM_ASSOC_REQ message from SME
926   *
927   * @mac_ctx:       Pointer to Global MAC structure
928   * @msg_buf:       A pointer to the MLM message buffer
929   *
930   * This function is called to process MLM_ASSOC_REQ message from SME
931   *
932   * @Return None
933   */
934  
lim_process_mlm_assoc_req(struct mac_context * mac_ctx,uint32_t * msg_buf)935  static void lim_process_mlm_assoc_req(struct mac_context *mac_ctx, uint32_t *msg_buf)
936  {
937  	tSirMacAddr curr_bssId;
938  	tLimMlmAssocReq *mlm_assoc_req;
939  	tLimMlmAssocCnf mlm_assoc_cnf;
940  	struct pe_session *session_entry;
941  
942  	if (!msg_buf) {
943  		pe_err("Buffer is Pointing to NULL");
944  		return;
945  	}
946  
947  	mlm_assoc_req = (tLimMlmAssocReq *) msg_buf;
948  	session_entry = pe_find_session_by_session_id(mac_ctx,
949  						      mlm_assoc_req->sessionId);
950  	if (!session_entry) {
951  		pe_err("SessionId:%d Session Does not exist",
952  			mlm_assoc_req->sessionId);
953  		qdf_mem_free(mlm_assoc_req);
954  		return;
955  	}
956  
957  	sir_copy_mac_addr(curr_bssId, session_entry->bssId);
958  
959  	if (!(!LIM_IS_AP_ROLE(session_entry) &&
960  		(session_entry->limMlmState == eLIM_MLM_AUTHENTICATED_STATE ||
961  		 session_entry->limMlmState == eLIM_MLM_JOINED_STATE) &&
962  		(!qdf_mem_cmp(mlm_assoc_req->peerMacAddr,
963  		 curr_bssId, sizeof(tSirMacAddr))))) {
964  		/*
965  		 * Received Association request either in invalid state
966  		 * or to a peer MAC entity whose address is different
967  		 * from one that STA is currently joined with or on AP.
968  		 * Return Assoc confirm with Invalid parameters code.
969  		 */
970  		pe_warn("received unexpected MLM_ASSOC_CNF in state %X for role=%d, MAC addr= "
971  			   QDF_MAC_ADDR_FMT, session_entry->limMlmState,
972  			GET_LIM_SYSTEM_ROLE(session_entry),
973  			QDF_MAC_ADDR_REF(mlm_assoc_req->peerMacAddr));
974  		lim_print_mlm_state(mac_ctx, LOGW, session_entry->limMlmState);
975  		mlm_assoc_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
976  		mlm_assoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
977  		goto end;
978  	}
979  
980  	/* map the session entry pointer to the AssocFailureTimer */
981  	mac_ctx->lim.lim_timers.gLimAssocFailureTimer.sessionId =
982  		mlm_assoc_req->sessionId;
983  	lim_store_pmfcomeback_timerinfo(session_entry);
984  	session_entry->limPrevMlmState = session_entry->limMlmState;
985  	session_entry->limMlmState = eLIM_MLM_WT_ASSOC_RSP_STATE;
986  	MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
987  			 session_entry->peSessionId,
988  			 session_entry->limMlmState));
989  	pe_debug("vdev %d Sending Assoc_Req Frame, timeout %d msec",
990  		 session_entry->vdev_id,
991  		 (int)mac_ctx->lim.lim_timers.gLimAssocFailureTimer.initScheduleTimeInMsecs);
992  
993  	/* Prepare and send Association request frame */
994  	lim_send_assoc_req_mgmt_frame(mac_ctx, mlm_assoc_req, session_entry);
995  
996  	/* Start association failure timer */
997  	MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE,
998  			 session_entry->peSessionId, eLIM_ASSOC_FAIL_TIMER));
999  	if (tx_timer_activate(&mac_ctx->lim.lim_timers.gLimAssocFailureTimer)
1000  	    != TX_SUCCESS) {
1001  		pe_warn("SessionId:%d couldn't start Assoc failure timer",
1002  			session_entry->peSessionId);
1003  		/* Cleanup as if assoc timer expired */
1004  		lim_process_assoc_failure_timeout(mac_ctx, LIM_ASSOC);
1005  	}
1006  
1007  	return;
1008  end:
1009  	/* Update PE session Id */
1010  	mlm_assoc_cnf.sessionId = mlm_assoc_req->sessionId;
1011  	/* Free up buffer allocated for assoc_req */
1012  	qdf_mem_free(mlm_assoc_req);
1013  	lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF,
1014  			     (uint32_t *) &mlm_assoc_cnf);
1015  }
1016  
1017  /**
1018   * lim_process_mlm_disassoc_req_ntf() - process disassoc request notification
1019   *
1020   * @mac_ctx:        global MAC context
1021   * @suspend_status: suspend status
1022   * @msg:            mlm message buffer
1023   *
1024   * This function is used to process MLM disassoc notification
1025   *
1026   * Return: None
1027   */
1028  static void
lim_process_mlm_disassoc_req_ntf(struct mac_context * mac_ctx,QDF_STATUS suspend_status,uint32_t * msg)1029  lim_process_mlm_disassoc_req_ntf(struct mac_context *mac_ctx,
1030  				 QDF_STATUS suspend_status, uint32_t *msg)
1031  {
1032  	uint16_t aid;
1033  	struct qdf_mac_addr curr_bssid;
1034  	tpDphHashNode stads;
1035  	tLimMlmDisassocReq *mlm_disassocreq;
1036  	tLimMlmDisassocCnf mlm_disassoccnf;
1037  	struct pe_session *session;
1038  	extern bool send_disassoc_frame;
1039  	tLimMlmStates mlm_state;
1040  	struct disassoc_rsp *sme_disassoc_rsp;
1041  
1042  	if (QDF_STATUS_SUCCESS != suspend_status)
1043  		pe_err("Suspend Status is not success %X",
1044  			suspend_status);
1045  
1046  	mlm_disassocreq = (tLimMlmDisassocReq *) msg;
1047  
1048  	session = pe_find_session_by_session_id(mac_ctx,
1049  				mlm_disassocreq->sessionId);
1050  	if (!session) {
1051  		pe_err("session does not exist for given sessionId %d",
1052  			mlm_disassocreq->sessionId);
1053  		mlm_disassoccnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
1054  		goto end;
1055  	}
1056  
1057  	qdf_mem_copy(curr_bssid.bytes, session->bssId, QDF_MAC_ADDR_SIZE);
1058  
1059  	switch (GET_LIM_SYSTEM_ROLE(session)) {
1060  	case eLIM_STA_ROLE:
1061  		if (!qdf_is_macaddr_equal(&mlm_disassocreq->peer_macaddr,
1062  				     &curr_bssid)) {
1063  			pe_warn("received MLM_DISASSOC_REQ with invalid BSS: "QDF_MAC_ADDR_FMT,
1064  				QDF_MAC_ADDR_REF(
1065  				mlm_disassocreq->peer_macaddr.bytes));
1066  
1067  			/*
1068  			 * Disassociation response due to host triggered
1069  			 * disassociation
1070  			 */
1071  			sme_disassoc_rsp =
1072  				qdf_mem_malloc(sizeof(*sme_disassoc_rsp));
1073  			if (!sme_disassoc_rsp) {
1074  				qdf_mem_free(mlm_disassocreq);
1075  				return;
1076  			}
1077  
1078  			pe_debug("send disassoc rsp with ret code %d for "QDF_MAC_ADDR_FMT,
1079  				 eSIR_SME_DEAUTH_STATUS,
1080  				 QDF_MAC_ADDR_REF(
1081  					mlm_disassocreq->peer_macaddr.bytes));
1082  
1083  			sme_disassoc_rsp->messageType = eWNI_SME_DISASSOC_RSP;
1084  			sme_disassoc_rsp->length = sizeof(*sme_disassoc_rsp);
1085  			sme_disassoc_rsp->sessionId =
1086  					mlm_disassocreq->sessionId;
1087  			sme_disassoc_rsp->status_code = eSIR_SME_DEAUTH_STATUS;
1088  
1089  			qdf_copy_macaddr(&sme_disassoc_rsp->peer_macaddr,
1090  					 &mlm_disassocreq->peer_macaddr);
1091  			msg = (uint32_t *)sme_disassoc_rsp;
1092  
1093  			lim_send_sme_disassoc_deauth_ntf(mac_ctx,
1094  					QDF_STATUS_SUCCESS, msg);
1095  			qdf_mem_free(mlm_disassocreq);
1096  			return;
1097  
1098  		}
1099  		break;
1100  	default:
1101  		break;
1102  	} /* end switch (GET_LIM_SYSTEM_ROLE(session)) */
1103  
1104  	/*
1105  	 * Check if there exists a context for the peer entity
1106  	 * to be disassociated with.
1107  	 */
1108  	stads = dph_lookup_hash_entry(mac_ctx,
1109  				      mlm_disassocreq->peer_macaddr.bytes,
1110  				      &aid, &session->dph.dphHashTable);
1111  	if (stads)
1112  		mlm_state = stads->mlmStaContext.mlmState;
1113  
1114  	if ((!stads) ||
1115  	    (stads &&
1116  	     ((mlm_state != eLIM_MLM_LINK_ESTABLISHED_STATE) &&
1117  	      (mlm_state != eLIM_MLM_WT_ASSOC_CNF_STATE) &&
1118  	      (mlm_state != eLIM_MLM_ASSOCIATED_STATE)))) {
1119  		/*
1120  		 * Received LIM_MLM_DISASSOC_REQ for STA that does not
1121  		 * have context or in some transit state.
1122  		 */
1123  		pe_warn("Invalid MLM_DISASSOC_REQ, Addr= " QDF_MAC_ADDR_FMT,
1124  			QDF_MAC_ADDR_REF(mlm_disassocreq->peer_macaddr.bytes));
1125  		if (stads)
1126  			pe_err("Sta MlmState: %d", stads->mlmStaContext.mlmState);
1127  
1128  		/* Prepare and Send LIM_MLM_DISASSOC_CNF */
1129  		mlm_disassoccnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
1130  		goto end;
1131  	}
1132  
1133  	stads->mlmStaContext.disassocReason = mlm_disassocreq->reasonCode;
1134  	stads->mlmStaContext.cleanupTrigger = mlm_disassocreq->disassocTrigger;
1135  
1136  	/*
1137  	 * Set state to mlm State to eLIM_MLM_WT_DEL_STA_RSP_STATE
1138  	 * This is to address the issue of race condition between
1139  	 * disconnect request from the HDD and deauth from AP
1140  	 */
1141  
1142  	stads->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE;
1143  
1144  	/* Send Disassociate frame to peer entity */
1145  	if (send_disassoc_frame && (mlm_disassocreq->reasonCode !=
1146  	    REASON_AUTHORIZED_ACCESS_LIMIT_REACHED)) {
1147  		if (mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq) {
1148  			pe_err("pMlmDisassocReq is not NULL, freeing");
1149  			qdf_mem_free(mac_ctx->lim.limDisassocDeauthCnfReq.
1150  				     pMlmDisassocReq);
1151  		}
1152  		mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq =
1153  			mlm_disassocreq;
1154  		/*
1155  		 * Set state to mlm State to eLIM_MLM_WT_DEL_STA_RSP_STATE
1156  		 * This is to address the issue of race condition between
1157  		 * disconnect request from the HDD and deauth from AP
1158  		 */
1159  		stads->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE;
1160  
1161  		lim_send_disassoc_mgmt_frame(mac_ctx,
1162  			mlm_disassocreq->reasonCode,
1163  			mlm_disassocreq->peer_macaddr.bytes, session, true);
1164  		/*
1165  		 * Abort Tx so that data frames won't be sent to the AP
1166  		 * after sending Disassoc.
1167  		 */
1168  		if (LIM_IS_STA_ROLE(session))
1169  			wma_tx_abort(session->smeSessionId);
1170  	} else {
1171  		lim_mlo_notify_peer_disconn(session, stads);
1172  		/* Disassoc frame is not sent OTA */
1173  		send_disassoc_frame = 1;
1174  		/* Receive path cleanup with dummy packet */
1175  		if (QDF_STATUS_SUCCESS !=
1176  		    lim_cleanup_rx_path(mac_ctx, stads, session, true)) {
1177  			mlm_disassoccnf.resultCode =
1178  				eSIR_SME_RESOURCES_UNAVAILABLE;
1179  			goto end;
1180  		}
1181  		/* Free up buffer allocated for mlmDisassocReq */
1182  		qdf_mem_free(mlm_disassocreq);
1183  	}
1184  
1185  	return;
1186  
1187  end:
1188  	qdf_mem_copy((uint8_t *) &mlm_disassoccnf.peerMacAddr,
1189  		     (uint8_t *) mlm_disassocreq->peer_macaddr.bytes,
1190  		     QDF_MAC_ADDR_SIZE);
1191  	mlm_disassoccnf.aid = mlm_disassocreq->aid;
1192  	mlm_disassoccnf.disassocTrigger = mlm_disassocreq->disassocTrigger;
1193  
1194  	/* Update PE session ID */
1195  	mlm_disassoccnf.sessionId = mlm_disassocreq->sessionId;
1196  
1197  	/* Free up buffer allocated for mlmDisassocReq */
1198  	qdf_mem_free(mlm_disassocreq);
1199  
1200  	lim_post_sme_message(mac_ctx, LIM_MLM_DISASSOC_CNF,
1201  			     (uint32_t *) &mlm_disassoccnf);
1202  }
1203  
1204  /**
1205   * lim_check_disassoc_deauth_ack_pending() - check if deauth is pending
1206   *
1207   * @mac_ctx - global MAC context
1208   * @sta_mac - station MAC
1209   *
1210   * This function checks if diassociation or deauthentication is pending for
1211   * given station MAC address.
1212   *
1213   * Return: true if pending and false otherwise.
1214   */
lim_check_disassoc_deauth_ack_pending(struct mac_context * mac_ctx,uint8_t * sta_mac)1215  bool lim_check_disassoc_deauth_ack_pending(struct mac_context *mac_ctx,
1216  					   uint8_t *sta_mac)
1217  {
1218  	tLimMlmDisassocReq *disassoc_req;
1219  	tLimMlmDeauthReq *deauth_req;
1220  
1221  	disassoc_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq;
1222  	deauth_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq;
1223  	if ((disassoc_req && (!qdf_mem_cmp((uint8_t *) sta_mac,
1224  			      (uint8_t *) &disassoc_req->peer_macaddr.bytes,
1225  			       QDF_MAC_ADDR_SIZE))) ||
1226  	    (deauth_req && (!qdf_mem_cmp((uint8_t *) sta_mac,
1227  			      (uint8_t *) &deauth_req->peer_macaddr.bytes,
1228  			       QDF_MAC_ADDR_SIZE)))) {
1229  		pe_debug("Disassoc/Deauth ack pending");
1230  		return true;
1231  	} else {
1232  		pe_debug("Disassoc/Deauth Ack not pending");
1233  		return false;
1234  	}
1235  }
1236  
1237  /*
1238   * lim_clean_up_disassoc_deauth_req() - cleans up pending disassoc or deauth req
1239   *
1240   * @mac_ctx:        mac_ctx
1241   * @sta_mac:        sta mac address
1242   * @clean_rx_path:  flag to indicate whether to cleanup rx path or not
1243   *
1244   * This function cleans up pending disassoc or deauth req
1245   *
1246   * Return: void
1247   */
lim_clean_up_disassoc_deauth_req(struct mac_context * mac_ctx,uint8_t * sta_mac,bool clean_rx_path)1248  void lim_clean_up_disassoc_deauth_req(struct mac_context *mac_ctx,
1249  				      uint8_t *sta_mac, bool clean_rx_path)
1250  {
1251  	tLimMlmDisassocReq *mlm_disassoc_req;
1252  	tLimMlmDeauthReq *mlm_deauth_req;
1253  
1254  	mlm_disassoc_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq;
1255  	if (mlm_disassoc_req &&
1256  	    (!qdf_mem_cmp((uint8_t *) sta_mac,
1257  			     (uint8_t *) &mlm_disassoc_req->peer_macaddr.bytes,
1258  			     QDF_MAC_ADDR_SIZE))) {
1259  		if (clean_rx_path) {
1260  			lim_process_disassoc_ack_timeout(mac_ctx);
1261  		} else {
1262  			if (tx_timer_running(
1263  			    &mac_ctx->lim.lim_timers.gLimDisassocAckTimer)) {
1264  				lim_deactivate_and_change_timer(mac_ctx,
1265  						eLIM_DISASSOC_ACK_TIMER);
1266  			}
1267  			qdf_mem_free(mlm_disassoc_req);
1268  			mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq =
1269  				NULL;
1270  		}
1271  	}
1272  
1273  	mlm_deauth_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq;
1274  	if (mlm_deauth_req &&
1275  	    (!qdf_mem_cmp((uint8_t *) sta_mac,
1276  			     (uint8_t *) &mlm_deauth_req->peer_macaddr.bytes,
1277  			     QDF_MAC_ADDR_SIZE))) {
1278  		if (clean_rx_path) {
1279  			lim_process_deauth_ack_timeout(mac_ctx,
1280  						       mlm_deauth_req->sessionId);
1281  		} else {
1282  			if (tx_timer_running(
1283  				&mac_ctx->lim.lim_timers.gLimDeauthAckTimer)) {
1284  				lim_deactivate_and_change_timer(mac_ctx,
1285  						eLIM_DEAUTH_ACK_TIMER);
1286  			}
1287  			qdf_mem_free(mlm_deauth_req);
1288  			mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq =
1289  				NULL;
1290  		}
1291  	}
1292  }
1293  
1294  /*
1295   * lim_process_disassoc_ack_timeout() - wrapper function around
1296   * lim_send_disassoc_cnf
1297   *
1298   * @mac_ctx:        mac_ctx
1299   *
1300   * wrapper function around lim_send_disassoc_cnf
1301   *
1302   * Return: void
1303   */
lim_process_disassoc_ack_timeout(struct mac_context * mac_ctx)1304  void lim_process_disassoc_ack_timeout(struct mac_context *mac_ctx)
1305  {
1306  	lim_send_disassoc_cnf(mac_ctx);
1307  }
1308  
1309  /**
1310   * lim_process_mlm_disassoc_req() - This function is called to process
1311   * MLM_DISASSOC_REQ message from SME
1312   *
1313   * @mac_ctx:      Pointer to Global MAC structure
1314   * @msg_buf:      A pointer to the MLM message buffer
1315   *
1316   * This function is called to process MLM_DISASSOC_REQ message from SME
1317   *
1318   * @Return: None
1319   */
1320  static void
lim_process_mlm_disassoc_req(struct mac_context * mac_ctx,uint32_t * msg_buf)1321  lim_process_mlm_disassoc_req(struct mac_context *mac_ctx, uint32_t *msg_buf)
1322  {
1323  	tLimMlmDisassocReq *mlm_disassoc_req;
1324  
1325  	if (!msg_buf) {
1326  		pe_err("Buffer is Pointing to NULL");
1327  		return;
1328  	}
1329  
1330  	mlm_disassoc_req = (tLimMlmDisassocReq *) msg_buf;
1331  	lim_process_mlm_disassoc_req_ntf(mac_ctx, QDF_STATUS_SUCCESS,
1332  					 (uint32_t *) msg_buf);
1333  }
1334  
1335  /**
1336   * lim_process_mlm_deauth_req_ntf() - This function is process mlm deauth req
1337   * notification
1338   *
1339   * @mac_ctx:         Pointer to Global MAC structure
1340   * @suspend_status:  suspend status
1341   * @msg_buf:         A pointer to the MLM message buffer
1342   *
1343   * This function is process mlm deauth req notification
1344   *
1345   * @Return: None
1346   */
1347  static void
lim_process_mlm_deauth_req_ntf(struct mac_context * mac_ctx,QDF_STATUS suspend_status,uint32_t * msg_buf)1348  lim_process_mlm_deauth_req_ntf(struct mac_context *mac_ctx,
1349  			       QDF_STATUS suspend_status, uint32_t *msg_buf)
1350  {
1351  	uint16_t aid, i;
1352  	tSirMacAddr curr_bssId;
1353  	tpDphHashNode sta_ds;
1354  	struct tLimPreAuthNode *auth_node;
1355  	tLimMlmDeauthReq *mlm_deauth_req;
1356  	tLimMlmDeauthCnf mlm_deauth_cnf;
1357  	struct pe_session *session;
1358  	struct deauth_rsp *sme_deauth_rsp;
1359  
1360  	if (QDF_STATUS_SUCCESS != suspend_status)
1361  		pe_err("Suspend Status is not success %X",
1362  			suspend_status);
1363  
1364  	mlm_deauth_req = (tLimMlmDeauthReq *) msg_buf;
1365  	session = pe_find_session_by_session_id(mac_ctx,
1366  				mlm_deauth_req->sessionId);
1367  	if (!session) {
1368  		pe_err("session does not exist for given sessionId %d",
1369  			mlm_deauth_req->sessionId);
1370  		qdf_mem_free(mlm_deauth_req);
1371  		return;
1372  	}
1373  	sir_copy_mac_addr(curr_bssId, session->bssId);
1374  
1375  	switch (GET_LIM_SYSTEM_ROLE(session)) {
1376  	case eLIM_STA_ROLE:
1377  		switch (session->limMlmState) {
1378  		case eLIM_MLM_IDLE_STATE:
1379  			/*
1380  			 * Attempting to Deauthenticate with a pre-authenticated
1381  			 * peer. Deauthetiate with peer if there exists a
1382  			 * pre-auth context below.
1383  			 */
1384  			break;
1385  		case eLIM_MLM_AUTHENTICATED_STATE:
1386  		case eLIM_MLM_WT_ASSOC_RSP_STATE:
1387  		case eLIM_MLM_LINK_ESTABLISHED_STATE:
1388  			if (qdf_mem_cmp(mlm_deauth_req->peer_macaddr.bytes,
1389  					curr_bssId, QDF_MAC_ADDR_SIZE)) {
1390  				pe_err("received MLM_DEAUTH_REQ with invalid BSS id "
1391  					   "Peer MAC: "QDF_MAC_ADDR_FMT
1392  					   " CFG BSSID Addr : "QDF_MAC_ADDR_FMT,
1393  					QDF_MAC_ADDR_REF(
1394  						mlm_deauth_req->peer_macaddr.bytes),
1395  					QDF_MAC_ADDR_REF(curr_bssId));
1396  				/*
1397  				 * Deauthentication response to host triggered
1398  				 * deauthentication
1399  				 */
1400  				sme_deauth_rsp =
1401  				    qdf_mem_malloc(sizeof(*sme_deauth_rsp));
1402  				if (!sme_deauth_rsp) {
1403  					qdf_mem_free(mlm_deauth_req);
1404  					return;
1405  				}
1406  
1407  				sme_deauth_rsp->messageType =
1408  						eWNI_SME_DEAUTH_RSP;
1409  				sme_deauth_rsp->length =
1410  						sizeof(*sme_deauth_rsp);
1411  				sme_deauth_rsp->status_code =
1412  						eSIR_SME_DEAUTH_STATUS;
1413  				sme_deauth_rsp->sessionId =
1414  						session->vdev_id;
1415  
1416  				qdf_mem_copy(sme_deauth_rsp->peer_macaddr.bytes,
1417  					     mlm_deauth_req->peer_macaddr.bytes,
1418  					     QDF_MAC_ADDR_SIZE);
1419  
1420  				msg_buf = (uint32_t *)sme_deauth_rsp;
1421  
1422  				lim_send_sme_disassoc_deauth_ntf(mac_ctx,
1423  						QDF_STATUS_SUCCESS, msg_buf);
1424  				qdf_mem_free(mlm_deauth_req);
1425  				return;
1426  			}
1427  
1428  			if ((session->limMlmState ==
1429  			     eLIM_MLM_AUTHENTICATED_STATE) ||
1430  			    (session->limMlmState ==
1431  			     eLIM_MLM_WT_ASSOC_RSP_STATE)) {
1432  				/* Send deauth frame to peer entity */
1433  				lim_send_deauth_mgmt_frame(mac_ctx,
1434  					mlm_deauth_req->reasonCode,
1435  					mlm_deauth_req->peer_macaddr.bytes,
1436  					session, false);
1437  				/* Prepare and Send LIM_MLM_DEAUTH_CNF */
1438  				mlm_deauth_cnf.resultCode = eSIR_SME_SUCCESS;
1439  				session->limMlmState = eLIM_MLM_IDLE_STATE;
1440  				MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
1441  						 session->peSessionId,
1442  						 session->limMlmState));
1443  				goto end;
1444  			}
1445  			break;
1446  		default:
1447  			pe_warn("received MLM_DEAUTH_REQ with in state %d for peer "
1448  				   QDF_MAC_ADDR_FMT,
1449  				session->limMlmState,
1450  				QDF_MAC_ADDR_REF(
1451  					mlm_deauth_req->peer_macaddr.bytes));
1452  			lim_print_mlm_state(mac_ctx, LOGW,
1453  					    session->limMlmState);
1454  			/* Prepare and Send LIM_MLM_DEAUTH_CNF */
1455  			mlm_deauth_cnf.resultCode =
1456  				eSIR_SME_STA_NOT_AUTHENTICATED;
1457  
1458  			goto end;
1459  		}
1460  		break;
1461  	default:
1462  		break;
1463  	} /* end switch (GET_LIM_SYSTEM_ROLE(session)) */
1464  
1465  	/*
1466  	 * Check if there exists a context for the peer entity
1467  	 * to be deauthenticated with.
1468  	 */
1469  	sta_ds = dph_lookup_hash_entry(mac_ctx,
1470  				       mlm_deauth_req->peer_macaddr.bytes,
1471  				       &aid,
1472  				       &session->dph.dphHashTable);
1473  
1474  	if (!sta_ds && (!mac_ctx->mlme_cfg->sap_cfg.is_sap_bcast_deauth_enabled
1475  	    || (mac_ctx->mlme_cfg->sap_cfg.is_sap_bcast_deauth_enabled &&
1476  	    !qdf_is_macaddr_broadcast(&mlm_deauth_req->peer_macaddr)))) {
1477  		/* Check if there exists pre-auth context for this STA */
1478  		auth_node = lim_search_pre_auth_list(mac_ctx, mlm_deauth_req->
1479  						     peer_macaddr.bytes);
1480  		if (!auth_node) {
1481  			/*
1482  			 * Received DEAUTH REQ for a STA that is neither
1483  			 * Associated nor Pre-authenticated. Log error,
1484  			 * Prepare and Send LIM_MLM_DEAUTH_CNF
1485  			 */
1486  			pe_warn("rcvd MLM_DEAUTH_REQ in mlme state %d STA does not have context, Addr="QDF_MAC_ADDR_FMT,
1487  				session->limMlmState,
1488  				QDF_MAC_ADDR_REF(
1489  					mlm_deauth_req->peer_macaddr.bytes));
1490  			mlm_deauth_cnf.resultCode =
1491  				eSIR_SME_STA_NOT_AUTHENTICATED;
1492  		} else {
1493  			mlm_deauth_cnf.resultCode = eSIR_SME_SUCCESS;
1494  			/* Delete STA from pre-auth STA list */
1495  			lim_delete_pre_auth_node(mac_ctx,
1496  						 mlm_deauth_req->
1497  						 peer_macaddr.bytes);
1498  			/*Send Deauthentication frame to peer entity*/
1499  			lim_send_deauth_mgmt_frame(mac_ctx,
1500  						   mlm_deauth_req->reasonCode,
1501  						   mlm_deauth_req->
1502  						   peer_macaddr.bytes,
1503  						   session, false);
1504  		}
1505  		goto end;
1506  	} else if (sta_ds && (sta_ds->mlmStaContext.mlmState !=
1507  		   eLIM_MLM_LINK_ESTABLISHED_STATE) &&
1508  		   (sta_ds->mlmStaContext.mlmState !=
1509  		   eLIM_MLM_WT_ASSOC_CNF_STATE)) {
1510  		/*
1511  		 * received MLM_DEAUTH_REQ for STA that either has no
1512  		 * context or in some transit state
1513  		 */
1514  		pe_warn("Invalid MLM_DEAUTH_REQ, Addr=" QDF_MAC_ADDR_FMT,
1515  			QDF_MAC_ADDR_REF(mlm_deauth_req->
1516  			peer_macaddr.bytes));
1517  		/* Prepare and Send LIM_MLM_DEAUTH_CNF */
1518  		mlm_deauth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
1519  		goto end;
1520  	} else if (sta_ds) {
1521  		/* sta_ds->mlmStaContext.rxPurgeReq     = 1; */
1522  		sta_ds->mlmStaContext.disassocReason =
1523  						mlm_deauth_req->reasonCode;
1524  		sta_ds->mlmStaContext.cleanupTrigger =
1525  						mlm_deauth_req->deauthTrigger;
1526  
1527  		/*
1528  		 * Set state to mlm State to eLIM_MLM_WT_DEL_STA_RSP_STATE
1529  		 * This is to address the issue of race condition between
1530  		 * disconnect request from the HDD and disassoc from
1531  		 * inactivity timer. This will make sure that we will not
1532  		 * process disassoc if deauth is in progress for the station
1533  		 * and thus mlmStaContext.cleanupTrigger will not be
1534  		 * overwritten.
1535  		 */
1536  		sta_ds->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE;
1537  	} else if (mac_ctx->mlme_cfg->sap_cfg.is_sap_bcast_deauth_enabled &&
1538  		   qdf_is_macaddr_broadcast(&mlm_deauth_req->peer_macaddr)) {
1539  		for (i = 0; i < session->dph.dphHashTable.size; i++) {
1540  			sta_ds = dph_get_hash_entry(mac_ctx, i,
1541  						   &session->dph.dphHashTable);
1542  			if (!sta_ds)
1543  				continue;
1544  
1545  			sta_ds->mlmStaContext.disassocReason =
1546  					mlm_deauth_req->reasonCode;
1547  			sta_ds->mlmStaContext.cleanupTrigger =
1548  						mlm_deauth_req->deauthTrigger;
1549  			sta_ds->mlmStaContext.mlmState =
1550  						eLIM_MLM_WT_DEL_STA_RSP_STATE;
1551  		}
1552  	}
1553  
1554  	if (mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq) {
1555  		pe_err("pMlmDeauthReq is not NULL, freeing");
1556  		qdf_mem_free(mac_ctx->lim.limDisassocDeauthCnfReq.
1557  			     pMlmDeauthReq);
1558  	}
1559  	mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = mlm_deauth_req;
1560  
1561  	/* Send Deauthentication frame to peer entity */
1562  	if (mlm_deauth_req->reasonCode != REASON_DISASSOC_DUE_TO_INACTIVITY ||
1563  	    wlan_son_peer_is_kickout_allow(session->vdev, sta_ds->staAddr)) {
1564  		lim_send_deauth_mgmt_frame(mac_ctx, mlm_deauth_req->reasonCode,
1565  					   mlm_deauth_req->peer_macaddr.bytes,
1566  					   session, true);
1567  	} else {
1568  		pe_err("peer " QDF_MAC_ADDR_FMT " is in band steering, do not send deauth frame",
1569  		       QDF_MAC_ADDR_REF(mlm_deauth_req->peer_macaddr.bytes));
1570  		mlm_deauth_cnf.resultCode = eSIR_SME_SUCCESS;
1571  		goto end;
1572  	}
1573  
1574  	return;
1575  end:
1576  	qdf_copy_macaddr(&mlm_deauth_cnf.peer_macaddr,
1577  			 &mlm_deauth_req->peer_macaddr);
1578  	mlm_deauth_cnf.deauthTrigger = mlm_deauth_req->deauthTrigger;
1579  	mlm_deauth_cnf.aid = mlm_deauth_req->aid;
1580  	mlm_deauth_cnf.sessionId = mlm_deauth_req->sessionId;
1581  
1582  	/* Free up buffer allocated for mlmDeauthReq */
1583  	qdf_mem_free(mlm_deauth_req);
1584  	lim_post_sme_message(mac_ctx,
1585  			     LIM_MLM_DEAUTH_CNF, (uint32_t *) &mlm_deauth_cnf);
1586  }
1587  
1588  /*
1589   * lim_process_deauth_ack_timeout() - wrapper function around
1590   * lim_send_deauth_cnf
1591   *
1592   * @pMacGlobal:     mac_ctx
1593   * @vdev_id:        vdev id
1594   *
1595   * wrapper function around lim_send_deauth_cnf
1596   *
1597   * Return: void
1598   */
lim_process_deauth_ack_timeout(void * pMacGlobal,uint32_t vdev_id)1599  void lim_process_deauth_ack_timeout(void *pMacGlobal, uint32_t vdev_id)
1600  {
1601  	struct mac_context *mac_ctx = (struct mac_context *)pMacGlobal;
1602  
1603  	pe_debug("Deauth Ack timeout for vdev id %d", vdev_id);
1604  	lim_send_deauth_cnf(mac_ctx, vdev_id);
1605  }
1606  
1607  /*
1608   * lim_process_mlm_deauth_req() - This function is called to process
1609   * MLM_DEAUTH_REQ message from SME
1610   *
1611   * @mac_ctx:      Pointer to Global MAC structure
1612   * @msg_buf:      A pointer to the MLM message buffer
1613   *
1614   * This function is called to process MLM_DEAUTH_REQ message from SME
1615   *
1616   * @Return: None
1617   */
lim_process_mlm_deauth_req(struct mac_context * mac_ctx,uint32_t * msg_buf)1618  void lim_process_mlm_deauth_req(struct mac_context *mac_ctx, uint32_t *msg_buf)
1619  {
1620  	tLimMlmDeauthReq *mlm_deauth_req;
1621  	struct pe_session *session;
1622  
1623  	if (!msg_buf) {
1624  		pe_err("Buffer is Pointing to NULL");
1625  		return;
1626  	}
1627  
1628  	mlm_deauth_req = (tLimMlmDeauthReq *) msg_buf;
1629  	session = pe_find_session_by_session_id(mac_ctx,
1630  				mlm_deauth_req->sessionId);
1631  	if (!session) {
1632  		pe_err("session does not exist for given sessionId %d",
1633  			mlm_deauth_req->sessionId);
1634  		qdf_mem_free(mlm_deauth_req);
1635  		return;
1636  	}
1637  	lim_process_mlm_deauth_req_ntf(mac_ctx, QDF_STATUS_SUCCESS,
1638  				       (uint32_t *) msg_buf);
1639  }
1640  
lim_process_join_failure_timeout(struct mac_context * mac_ctx)1641  void lim_process_join_failure_timeout(struct mac_context *mac_ctx)
1642  {
1643  	tLimMlmJoinCnf mlm_join_cnf;
1644  	uint32_t len;
1645  #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
1646  	host_log_rssi_pkt_type *rssi_log = NULL;
1647  #endif
1648  	struct pe_session *session;
1649  
1650  	session = pe_find_session_by_session_id(mac_ctx,
1651  			mac_ctx->lim.lim_timers.gLimJoinFailureTimer.sessionId);
1652  	if (!session) {
1653  		pe_err("Session Does not exist for given sessionID");
1654  		return;
1655  	}
1656  #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
1657  	WLAN_HOST_DIAG_LOG_ALLOC(rssi_log,
1658  				host_log_rssi_pkt_type, LOG_WLAN_RSSI_UPDATE_C);
1659  	if (rssi_log)
1660  		rssi_log->rssi = session->rssi;
1661  	WLAN_HOST_DIAG_LOG_REPORT(rssi_log);
1662  #endif
1663  	session->join_probe_cnt = 0;
1664  
1665  	if (session->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE) {
1666  		len = sizeof(tSirMacAddr);
1667  		/* Change timer for future activations */
1668  		lim_deactivate_and_change_timer(mac_ctx, eLIM_JOIN_FAIL_TIMER);
1669  		/* Change Periodic probe req timer for future activation */
1670  		lim_deactivate_and_change_timer(mac_ctx,
1671  					eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER);
1672  		/* Issue MLM join confirm with timeout reason code */
1673  		pe_err("Join Failure Timeout, In eLIM_MLM_WT_JOIN_BEACON_STATE session:%d "
1674  			   QDF_MAC_ADDR_FMT,
1675  			session->peSessionId,
1676  			QDF_MAC_ADDR_REF(session->bssId));
1677  
1678  		mlm_join_cnf.resultCode = eSIR_SME_JOIN_TIMEOUT_RESULT_CODE;
1679  		mlm_join_cnf.protStatusCode = STATUS_NO_NETWORK_FOUND;
1680  		session->limMlmState = eLIM_MLM_IDLE_STATE;
1681  		MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
1682  				 session->peSessionId, session->limMlmState));
1683  		/* Update PE session Id */
1684  		mlm_join_cnf.sessionId = session->peSessionId;
1685  		/* Freeup buffer allocated to join request */
1686  		if (session->pLimMlmJoinReq) {
1687  			qdf_mem_free(session->pLimMlmJoinReq);
1688  			session->pLimMlmJoinReq = NULL;
1689  		}
1690  		lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF,
1691  				     (uint32_t *) &mlm_join_cnf);
1692  		return;
1693  	} else {
1694  		pe_warn("received unexpected JOIN failure timeout in state %X",
1695  			session->limMlmState);
1696  		lim_print_mlm_state(mac_ctx, LOGW, session->limMlmState);
1697  	}
1698  }
1699  
1700  /**
1701   * lim_process_periodic_join_probe_req_timer() - This function is called to
1702   * process periodic probe request send during joining process.
1703   *
1704   * @mac_ctx:      Pointer to Global MAC structure
1705   *
1706   * This function is called to process periodic probe request send during
1707   * joining process.
1708   *
1709   * @Return None
1710   */
lim_process_periodic_join_probe_req_timer(struct mac_context * mac_ctx)1711  static void lim_process_periodic_join_probe_req_timer(struct mac_context *mac_ctx)
1712  {
1713  	struct pe_session *session;
1714  	tSirMacSSid ssid;
1715  	tSirMacAddr bssid;
1716  	tSirMacAddr bcast_mac = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
1717  
1718  	session = pe_find_session_by_session_id(mac_ctx,
1719  	      mac_ctx->lim.lim_timers.gLimPeriodicJoinProbeReqTimer.sessionId);
1720  	if (!session) {
1721  		pe_err("session does not exist for given SessionId: %d",
1722  			mac_ctx->lim.lim_timers.gLimPeriodicJoinProbeReqTimer.
1723  			sessionId);
1724  		return;
1725  	}
1726  
1727  	if ((true ==
1728  	    tx_timer_running(&mac_ctx->lim.lim_timers.gLimJoinFailureTimer))
1729  		&& (session->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE)) {
1730  		qdf_mem_copy(ssid.ssId, session->ssId.ssId,
1731  			     session->ssId.length);
1732  		ssid.length = session->ssId.length;
1733  		sir_copy_mac_addr(bssid,
1734  				  session->pLimMlmJoinReq->bssDescription.bssId);
1735  
1736  		/*
1737  		 * Some APs broadcasting hidden SSID doesn't respond to unicast
1738  		 * probe requests, however those APs respond to broadcast probe
1739  		 * requests. Therefore for hidden ssid connections, after 3
1740  		 * unicast probe requests, try the pending probes with broadcast
1741  		 * mac.
1742  		 */
1743  		if (session->ssidHidden && session->join_probe_cnt > 2)
1744  			sir_copy_mac_addr(bssid, bcast_mac);
1745  
1746  		lim_send_probe_req_mgmt_frame(mac_ctx, &ssid, bssid,
1747  					      session->curr_op_freq,
1748  			session->self_mac_addr, session->dot11mode,
1749  			&session->lim_join_req->addIEScan.length,
1750  			session->lim_join_req->addIEScan.addIEdata);
1751  		lim_deactivate_and_change_timer(mac_ctx,
1752  				eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER);
1753  		/* Activate Join Periodic Probe Req timer */
1754  		if (tx_timer_activate(
1755  		    &mac_ctx->lim.lim_timers.gLimPeriodicJoinProbeReqTimer) !=
1756  		    TX_SUCCESS) {
1757  			pe_warn("could not activate Periodic Join req failure timer");
1758  			return;
1759  		}
1760  		session->join_probe_cnt++;
1761  	}
1762  }
1763  
lim_send_pre_auth_failure(uint8_t vdev_id,tSirMacAddr bssid)1764  static void lim_send_pre_auth_failure(uint8_t vdev_id, tSirMacAddr bssid)
1765  {
1766  	struct scheduler_msg sch_msg = {0};
1767  	struct wmi_roam_auth_status_params *params;
1768  	QDF_STATUS status = QDF_STATUS_SUCCESS;
1769  
1770  	params = qdf_mem_malloc(sizeof(*params));
1771  	if (!params)
1772  		return;
1773  
1774  	params->vdev_id = vdev_id;
1775  	params->preauth_status = STATUS_UNSPECIFIED_FAILURE;
1776  	qdf_mem_copy(params->bssid.bytes, bssid, QDF_MAC_ADDR_SIZE);
1777  	qdf_mem_zero(params->pmkid, PMKID_LEN);
1778  
1779  	sch_msg.type = WMA_ROAM_PRE_AUTH_STATUS;
1780  	sch_msg.bodyptr = params;
1781  	pe_debug("Sending pre auth failure for mac_addr " QDF_MAC_ADDR_FMT,
1782  		 QDF_MAC_ADDR_REF(params->bssid.bytes));
1783  
1784  	status = scheduler_post_message(QDF_MODULE_ID_PE,
1785  					QDF_MODULE_ID_WMA,
1786  					QDF_MODULE_ID_WMA,
1787  					&sch_msg);
1788  	if (QDF_IS_STATUS_ERROR(status)) {
1789  		pe_err("Sending preauth status failed");
1790  		qdf_mem_free(params);
1791  	}
1792  }
1793  
lim_handle_sae_auth_timeout(struct mac_context * mac_ctx,struct pe_session * session_entry)1794  static void lim_handle_sae_auth_timeout(struct mac_context *mac_ctx,
1795  					struct pe_session *session_entry)
1796  {
1797  	struct sae_auth_retry *sae_retry;
1798  	tpSirMacMgmtHdr mac_hdr;
1799  
1800  	sae_retry = mlme_get_sae_auth_retry(session_entry->vdev);
1801  	if (!(sae_retry && sae_retry->sae_auth.ptr)) {
1802  		pe_debug("sae auth frame is not buffered vdev id %d",
1803  			 session_entry->vdev_id);
1804  		return;
1805  	}
1806  
1807  	if (!sae_retry->sae_auth_max_retry) {
1808  		if (!wlan_cm_is_vdev_connecting(session_entry->vdev)) {
1809  			mac_hdr = (tpSirMacMgmtHdr)sae_retry->sae_auth.ptr;
1810  			lim_send_pre_auth_failure(session_entry->vdev_id,
1811  						  mac_hdr->bssId);
1812  		}
1813  		goto free_and_deactivate_timer;
1814  	}
1815  
1816  	pe_debug("Retry sae auth for seq num %d vdev id %d",
1817  		 mac_ctx->mgmtSeqNum, session_entry->vdev_id);
1818  	lim_send_frame(mac_ctx, session_entry->vdev_id, sae_retry->sae_auth.ptr,
1819  		       sae_retry->sae_auth.len);
1820  	sae_retry->sae_auth_max_retry--;
1821  
1822  	if (TX_SUCCESS != tx_timer_activate(
1823  	    &mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer))
1824  		goto free_and_deactivate_timer;
1825  	return;
1826  
1827  free_and_deactivate_timer:
1828  	lim_sae_auth_cleanup_retry(mac_ctx, session_entry->vdev_id);
1829  }
1830  
1831  /**
1832   * lim_process_auth_retry_timer()- function to Retry Auth when auth timeout
1833   * occurs
1834   * @mac_ctx:pointer to global mac
1835   *
1836   * Return: void
1837   */
lim_process_auth_retry_timer(struct mac_context * mac_ctx)1838  static void lim_process_auth_retry_timer(struct mac_context *mac_ctx)
1839  {
1840  	struct pe_session *session_entry;
1841  	tAniAuthType auth_type;
1842  	tLimTimers *lim_timers = &mac_ctx->lim.lim_timers;
1843  	uint16_t pe_session_id =
1844  		lim_timers->g_lim_periodic_auth_retry_timer.sessionId;
1845  
1846  	session_entry = pe_find_session_by_session_id(mac_ctx, pe_session_id);
1847  	if (!session_entry) {
1848  		pe_err("session does not exist for pe_session_id: %d",
1849  		       pe_session_id);
1850  		return;
1851  	}
1852  
1853  	/** For WPA3 SAE gLimAuthFailureTimer is not running hence
1854  	 *  we don't enter in below "if" block in case of wpa3 sae
1855  	 */
1856  	if (tx_timer_running(&mac_ctx->lim.lim_timers.gLimAuthFailureTimer) &&
1857  	    (session_entry->limMlmState == eLIM_MLM_WT_AUTH_FRAME2_STATE) &&
1858  	     (LIM_ACK_RCD_SUCCESS != mac_ctx->auth_ack_status)) {
1859  		/*
1860  		 * Send the auth retry only in case we have received ack failure
1861  		 * else just restart the retry timer.
1862  		 */
1863  		if (((mac_ctx->auth_ack_status == LIM_ACK_RCD_FAILURE) ||
1864  		     (mac_ctx->auth_ack_status == LIM_TX_FAILED)) &&
1865  		      mac_ctx->lim.gpLimMlmAuthReq) {
1866  			tSirMacAuthFrameBody *auth_frame;
1867  
1868  			auth_type = mac_ctx->lim.gpLimMlmAuthReq->authType;
1869  
1870  			auth_frame = qdf_mem_malloc(sizeof(*auth_frame));
1871  			if (!auth_frame) {
1872  				pe_err("malloc failed for auth_frame");
1873  				return;
1874  			}
1875  
1876  			/* Prepare & send Authentication frame */
1877  			if (session_entry->sae_pmk_cached &&
1878  			    auth_type == eSIR_AUTH_TYPE_SAE)
1879  				auth_frame->authAlgoNumber = eSIR_OPEN_SYSTEM;
1880  			else
1881  				auth_frame->authAlgoNumber = (uint8_t)auth_type;
1882  
1883  			auth_frame->authTransactionSeqNumber =
1884  						SIR_MAC_AUTH_FRAME_1;
1885  			auth_frame->authStatusCode = 0;
1886  			pe_debug("Retry Auth");
1887  			lim_increase_fils_sequence_number(session_entry);
1888  			lim_send_auth_mgmt_frame(mac_ctx, auth_frame,
1889  				mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr,
1890  				LIM_NO_WEP_IN_FC, session_entry);
1891  
1892  			qdf_mem_free(auth_frame);
1893  		}
1894  
1895  		lim_deactivate_and_change_timer(mac_ctx, eLIM_AUTH_RETRY_TIMER);
1896  
1897  		/* Activate Auth Retry timer */
1898  		if (tx_timer_activate
1899  		     (&mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer)
1900  			 != TX_SUCCESS)
1901  			pe_err("could not activate Auth Retry failure timer");
1902  
1903  		return;
1904  	}
1905  
1906  	/* Auth retry time out for wpa3 sae */
1907  	lim_handle_sae_auth_timeout(mac_ctx, session_entry);
1908  } /*** lim_process_auth_retry_timer() ***/
1909  
lim_process_auth_failure_timeout(struct mac_context * mac_ctx)1910  void lim_process_auth_failure_timeout(struct mac_context *mac_ctx)
1911  {
1912  	/* fetch the pe_session based on the sessionId */
1913  	struct pe_session *session;
1914  	uint32_t val;
1915  	enum wlan_status_code proto_status_code;
1916  #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
1917  	host_log_rssi_pkt_type *rssi_log = NULL;
1918  #endif
1919  
1920  	session = pe_find_session_by_session_id(mac_ctx,
1921  			mac_ctx->lim.lim_timers.gLimAuthFailureTimer.sessionId);
1922  	if (!session) {
1923  		pe_err("Session Does not exist for given sessionID");
1924  		return;
1925  	}
1926  
1927  	pe_warn("received AUTH failure timeout in sessionid %d "
1928  		   "limMlmstate %X limSmeState %X",
1929  		session->peSessionId, session->limMlmState,
1930  		session->limSmeState);
1931  #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
1932  	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_AUTH_TIMEOUT, session,
1933  				0, AUTH_FAILURE_TIMEOUT);
1934  
1935  	WLAN_HOST_DIAG_LOG_ALLOC(rssi_log, host_log_rssi_pkt_type,
1936  				 LOG_WLAN_RSSI_UPDATE_C);
1937  	if (rssi_log)
1938  		rssi_log->rssi = session->rssi;
1939  	WLAN_HOST_DIAG_LOG_REPORT(rssi_log);
1940  #endif
1941  
1942  	switch (session->limMlmState) {
1943  	case eLIM_MLM_WT_AUTH_FRAME2_STATE:
1944  	case eLIM_MLM_WT_AUTH_FRAME4_STATE:
1945  		/*
1946  		 * Requesting STA did not receive next auth frame before Auth
1947  		 * Failure timeout. Issue MLM auth confirm with timeout reason
1948  		 * code. Restore default failure timeout
1949  		 */
1950  		if (QDF_P2P_CLIENT_MODE == session->opmode &&
1951  		    session->defaultAuthFailureTimeout) {
1952  			if (cfg_in_range(CFG_AUTH_FAILURE_TIMEOUT,
1953  					 session->defaultAuthFailureTimeout)) {
1954  				val = session->defaultAuthFailureTimeout;
1955  			} else {
1956  				val = cfg_default(CFG_AUTH_FAILURE_TIMEOUT);
1957  				session->defaultAuthFailureTimeout = val;
1958  			}
1959  			mac_ctx->mlme_cfg->timeouts.auth_failure_timeout = val;
1960  		}
1961  		lim_fill_status_code(SIR_MAC_MGMT_AUTH,
1962  				     mac_ctx->auth_ack_status,
1963  				     &proto_status_code);
1964  		lim_restore_from_auth_state(mac_ctx,
1965  				eSIR_SME_AUTH_TIMEOUT_RESULT_CODE,
1966  				proto_status_code, session);
1967  		mac_ctx->auth_ack_status = LIM_ACK_NOT_RCD;
1968  		break;
1969  	default:
1970  		/*
1971  		 * Auth failure timer should not have timed out
1972  		 * in states other than wt_auth_frame2/4
1973  		 */
1974  		pe_err("received unexpected AUTH failure timeout in state %X",
1975  			session->limMlmState);
1976  		lim_print_mlm_state(mac_ctx, LOGE, session->limMlmState);
1977  		break;
1978  	}
1979  }
1980  
1981  /**
1982   * lim_process_auth_rsp_timeout() - This function is called to process Min
1983   * Channel Timeout during channel scan.
1984   *
1985   * @mac_ctx:      Pointer to Global MAC structure
1986   *
1987   * This function is called to process Min Channel Timeout during channel scan.
1988   *
1989   * @Return: None
1990   */
1991  static void
lim_process_auth_rsp_timeout(struct mac_context * mac_ctx,uint32_t auth_idx)1992  lim_process_auth_rsp_timeout(struct mac_context *mac_ctx, uint32_t auth_idx)
1993  {
1994  	struct tLimPreAuthNode *auth_node;
1995  	struct pe_session *session;
1996  	uint8_t session_id;
1997  
1998  	auth_node = lim_get_pre_auth_node_from_index(mac_ctx,
1999  				&mac_ctx->lim.gLimPreAuthTimerTable, auth_idx);
2000  	if (!auth_node) {
2001  		pe_warn("Invalid auth node");
2002  		return;
2003  	}
2004  
2005  	session = pe_find_session_by_bssid(mac_ctx, auth_node->peerMacAddr,
2006  					   &session_id);
2007  	if (!session) {
2008  		pe_warn("session does not exist for given BSSID");
2009  		return;
2010  	}
2011  
2012  #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
2013  		lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_AUTH_TIMEOUT,
2014  				session, 0, AUTH_RESPONSE_TIMEOUT);
2015  #endif
2016  
2017  	if (LIM_IS_AP_ROLE(session)) {
2018  		if (auth_node->mlmState != eLIM_MLM_WT_AUTH_FRAME3_STATE) {
2019  			pe_err("received AUTH rsp timeout in unexpected "
2020  				   "state for MAC address: " QDF_MAC_ADDR_FMT,
2021  				QDF_MAC_ADDR_REF(auth_node->peerMacAddr));
2022  		} else {
2023  			auth_node->mlmState = eLIM_MLM_AUTH_RSP_TIMEOUT_STATE;
2024  			auth_node->fTimerStarted = 0;
2025  			pe_debug("AUTH rsp timedout for MAC address "
2026  				   QDF_MAC_ADDR_FMT,
2027  				QDF_MAC_ADDR_REF(auth_node->peerMacAddr));
2028  			/* Change timer to reactivate it in future */
2029  			lim_deactivate_and_change_per_sta_id_timer(mac_ctx,
2030  				eLIM_AUTH_RSP_TIMER, auth_node->authNodeIdx);
2031  			lim_delete_pre_auth_node(mac_ctx,
2032  						 auth_node->peerMacAddr);
2033  		}
2034  	}
2035  }
2036  
lim_process_assoc_failure_timeout(struct mac_context * mac_ctx,uint32_t msg_type)2037  void lim_process_assoc_failure_timeout(struct mac_context *mac_ctx,
2038  				       uint32_t msg_type)
2039  {
2040  
2041  	tLimMlmAssocCnf mlm_assoc_cnf;
2042  	struct pe_session *session;
2043  	enum wlan_status_code proto_status_code;
2044  #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
2045  	host_log_rssi_pkt_type *rssi_log = NULL;
2046  #endif
2047  	/*
2048  	 * to fetch the lim/mlm state based on the session_id, use the
2049  	 * below pe_session
2050  	 */
2051  	uint8_t session_id;
2052  
2053  	if (msg_type == LIM_ASSOC)
2054  		session_id =
2055  		    mac_ctx->lim.lim_timers.gLimAssocFailureTimer.sessionId;
2056  	else
2057  		session_id =
2058  		    mac_ctx->lim.lim_timers.gLimReassocFailureTimer.sessionId;
2059  
2060  	session = pe_find_session_by_session_id(mac_ctx, session_id);
2061  	if (!session) {
2062  		pe_err("Session Does not exist for given sessionID");
2063  		return;
2064  	}
2065  #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
2066  	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_ASSOC_TIMEOUT,
2067  				session, 0, 0);
2068  
2069  	WLAN_HOST_DIAG_LOG_ALLOC(rssi_log,
2070  				 host_log_rssi_pkt_type,
2071  				 LOG_WLAN_RSSI_UPDATE_C);
2072  	if (rssi_log)
2073  		rssi_log->rssi = session->rssi;
2074  	WLAN_HOST_DIAG_LOG_REPORT(rssi_log);
2075  #endif
2076  
2077  	pe_debug("Re/Association Response not received before timeout");
2078  
2079  	/*
2080  	 * Send Deauth to handle the scenareo where association timeout happened
2081  	 * when device has missed the assoc resp sent by peer.
2082  	 * By sending deauth try to clear the session created on peer device.
2083  	 */
2084  	if (msg_type == LIM_ASSOC &&
2085  	    mlme_get_reconn_after_assoc_timeout_flag(mac_ctx->psoc,
2086  						     session->vdev_id)) {
2087  		pe_debug("vdev: %d skip sending deauth on channel freq %d to BSSID: "
2088  			QDF_MAC_ADDR_FMT, session->vdev_id,
2089  			session->curr_op_freq,
2090  			QDF_MAC_ADDR_REF(session->bssId));
2091  	} else {
2092  		pe_debug("vdev: %d try sending deauth on channel freq %d to BSSID: "
2093  			QDF_MAC_ADDR_FMT, session->vdev_id,
2094  			session->curr_op_freq,
2095  			QDF_MAC_ADDR_REF(session->bssId));
2096  		lim_send_deauth_mgmt_frame(mac_ctx,
2097  					   REASON_UNSPEC_FAILURE,
2098  					   session->bssId, session, false);
2099  	}
2100  	if ((LIM_IS_AP_ROLE(session)) ||
2101  	    ((session->limMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE) &&
2102  	    (session->limMlmState != eLIM_MLM_WT_REASSOC_RSP_STATE) &&
2103  	    (session->limMlmState != eLIM_MLM_WT_FT_REASSOC_RSP_STATE))) {
2104  		/*
2105  		 * Re/Assoc failure timer should not have timedout on AP
2106  		 * or in a state other than wt_re/assoc_response.
2107  		 */
2108  		pe_warn("received unexpected REASSOC failure timeout in state %X for role %d",
2109  			session->limMlmState,
2110  			GET_LIM_SYSTEM_ROLE(session));
2111  		lim_print_mlm_state(mac_ctx, LOGW, session->limMlmState);
2112  		return;
2113  	}
2114  
2115  	if ((msg_type == LIM_ASSOC) || ((msg_type == LIM_REASSOC)
2116  	     && (session->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE))) {
2117  		pe_err("(Re)Assoc Failure Timeout occurred");
2118  		session->limMlmState = eLIM_MLM_IDLE_STATE;
2119  		MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
2120  			session->peSessionId, session->limMlmState));
2121  		/* Change timer for future activations */
2122  		lim_deactivate_and_change_timer(mac_ctx, eLIM_ASSOC_FAIL_TIMER);
2123  		lim_stop_pmfcomeback_timer(session);
2124  		/*
2125  		 * Free up buffer allocated for JoinReq held by
2126  		 * MLM state machine
2127  		 */
2128  		if (session->pLimMlmJoinReq) {
2129  			qdf_mem_free(session->pLimMlmJoinReq);
2130  			session->pLimMlmJoinReq = NULL;
2131  		}
2132  		/* To remove the preauth node in case of fail to associate */
2133  		if (lim_search_pre_auth_list(mac_ctx, session->bssId)) {
2134  			pe_debug("delete pre auth node for "QDF_MAC_ADDR_FMT,
2135  				QDF_MAC_ADDR_REF(session->bssId));
2136  			lim_delete_pre_auth_node(mac_ctx,
2137  						 session->bssId);
2138  		}
2139  		lim_fill_status_code(SIR_MAC_MGMT_ASSOC_RSP,
2140  				     mac_ctx->assoc_ack_status,
2141  				     &proto_status_code);
2142  
2143  		mlm_assoc_cnf.resultCode = eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE;
2144  		mlm_assoc_cnf.protStatusCode = proto_status_code;
2145  		/* Update PE session Id */
2146  		mlm_assoc_cnf.sessionId = session->peSessionId;
2147  		if (msg_type == LIM_ASSOC) {
2148  			lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF,
2149  					     (uint32_t *) &mlm_assoc_cnf);
2150  		} else {
2151  			/*
2152  			 * Will come here only in case of 11r, Ese FT
2153  			 * when reassoc rsp is not received and we
2154  			 * receive a reassoc - timesout
2155  			 */
2156  			mlm_assoc_cnf.resultCode =
2157  				eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE;
2158  			lim_post_sme_message(mac_ctx, LIM_MLM_REASSOC_CNF,
2159  					     (uint32_t *) &mlm_assoc_cnf);
2160  		}
2161  	} else {
2162  		/*
2163  		 * Restore pre-reassoc req state.
2164  		 * Set BSSID to currently associated AP address.
2165  		 */
2166  		session->limMlmState = session->limPrevMlmState;
2167  		MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
2168  				 session->peSessionId, session->limMlmState));
2169  		lim_restore_pre_reassoc_state(mac_ctx,
2170  				eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE,
2171  				STATUS_UNSPECIFIED_FAILURE, session);
2172  	}
2173  }
2174