xref: /wlan-driver/qcacld-3.0/core/mac/src/pe/lim/lim_process_action_frame.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
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_process_action_frame.cc contains the code
22  * for processing Action Frame.
23  * Author:      Michael Lui
24  * Date:        05/23/03
25  * History:-
26  * Date           Modified by    Modification Information
27  * --------------------------------------------------------------------
28  *
29  */
30 #include "cds_api.h"
31 #include "wni_api.h"
32 #include "sir_api.h"
33 #include "ani_global.h"
34 #include "wni_cfg.h"
35 #include "sch_api.h"
36 #include "utils_api.h"
37 #include "lim_types.h"
38 #include "lim_utils.h"
39 #include "lim_assoc_utils.h"
40 #include "lim_security_utils.h"
41 #include "lim_ser_des_utils.h"
42 #include "lim_send_sme_rsp_messages.h"
43 #include "parser_api.h"
44 #include "lim_admit_control.h"
45 #include "wmm_apsd.h"
46 #include "lim_send_messages.h"
47 #include "rrm_api.h"
48 #include "lim_session_utils.h"
49 #include "wlan_policy_mgr_api.h"
50 #include "wma_types.h"
51 #include "wma.h"
52 #include <cdp_txrx_cmn.h>
53 #include <cdp_txrx_peer_ops.h>
54 #include "dot11f.h"
55 #include "wlan_p2p_cfg_api.h"
56 #include "son_api.h"
57 #include "wlan_t2lm_api.h"
58 #include "wlan_epcs_api.h"
59 #include <wlan_mlo_mgr_sta.h>
60 #include "wlan_mlo_mgr_public_structs.h"
61 #include "wlan_p2p_api.h"
62 
63 #define SA_QUERY_REQ_MIN_LEN \
64 (DOT11F_FF_CATEGORY_LEN + DOT11F_FF_ACTION_LEN + DOT11F_FF_TRANSACTIONID_LEN)
65 #define SA_QUERY_RESP_MIN_LEN \
66 (DOT11F_FF_CATEGORY_LEN + DOT11F_FF_ACTION_LEN + DOT11F_FF_TRANSACTIONID_LEN)
67 #define SA_QUERY_IE_OFFSET (4)
68 
69 #define MIN_OCI_IE_LEN 6
70 #define OCI_IE_OUI_SIZE 1
71 #define OCI_IE_OP_CLS_OFFSET 3
72 #define ELE_ID_EXT_LEN 1
73 
74 static last_processed_msg rrm_link_action_frm;
75 
76 /**-----------------------------------------------------------------
77    \fn     lim_stop_tx_and_switch_channel
78    \brief  Stops the transmission if channel switch mode is silent and
79    starts the channel switch timer.
80 
81    \param  mac
82    \return NONE
83    -----------------------------------------------------------------*/
lim_stop_tx_and_switch_channel(struct mac_context * mac,uint8_t sessionId)84 void lim_stop_tx_and_switch_channel(struct mac_context *mac, uint8_t sessionId)
85 {
86 	struct pe_session *pe_session;
87 	QDF_STATUS status;
88 
89 	pe_session = pe_find_session_by_session_id(mac, sessionId);
90 
91 	if (!pe_session) {
92 		pe_err("Session: %d not active", sessionId);
93 		return;
94 	}
95 
96 	if (pe_session->ftPEContext.pFTPreAuthReq) {
97 		pe_debug("Avoid Switch Channel req during pre auth");
98 		return;
99 	}
100 
101 	status = policy_mgr_check_and_set_hw_mode_for_channel_switch(mac->psoc,
102 				pe_session->smeSessionId,
103 				pe_session->gLimChannelSwitch.sw_target_freq,
104 				POLICY_MGR_UPDATE_REASON_CHANNEL_SWITCH_STA);
105 
106 	/*
107 	 * If status is QDF_STATUS_E_FAILURE, mean HW mode change was required
108 	 * but driver failed to set HW mode so ignore CSA for the channel.
109 	 * If status is QDF_STATUS_SUCCESS mean HW mode change was required
110 	 * and was successfully changed so the channel switch will continue after
111 	 * HW mode change completion.
112 	 * If status is QDF_STATUS_E_NOSUPPORT or QDF_STATUS_E_ALREADY, mean
113 	 * DBS is not supported or required HW mode is already set, so
114 	 * So contunue with CSA from here.
115 	 */
116 	if (status == QDF_STATUS_E_FAILURE) {
117 		pe_err("Failed to set required HW mode for channel %d freq %d, ignore CSA",
118 		       pe_session->gLimChannelSwitch.primaryChannel,
119 		       pe_session->gLimChannelSwitch.sw_target_freq);
120 		return;
121 	}
122 
123 	if (QDF_IS_STATUS_SUCCESS(status)) {
124 		pe_info("Channel change will continue after HW mode change");
125 		return;
126 	}
127 
128 	lim_process_channel_switch(mac, pe_session->smeSessionId);
129 
130 	return;
131 }
132 
133 /**
134  * lim_process_ext_channel_switch_action_frame()- Process ECSA Action
135  * Frames.
136  * @mac_ctx: pointer to global mac structure
137  * @rx_packet_info: rx packet meta information
138  * @session_entry: Session entry.
139  *
140  * This function is called when ECSA action frame is received.
141  *
142  * Return: void
143  */
144 static void
lim_process_ext_channel_switch_action_frame(struct mac_context * mac_ctx,uint8_t * rx_packet_info,struct pe_session * session_entry)145 lim_process_ext_channel_switch_action_frame(struct mac_context *mac_ctx,
146 		uint8_t *rx_packet_info, struct pe_session *session_entry)
147 {
148 
149 	tpSirMacMgmtHdr         hdr;
150 	uint8_t                 *body;
151 	tDot11fext_channel_switch_action_frame *ext_channel_switch_frame;
152 	uint32_t                frame_len;
153 	uint32_t                status;
154 	uint32_t                target_freq;
155 
156 	hdr = WMA_GET_RX_MAC_HEADER(rx_packet_info);
157 	body = WMA_GET_RX_MPDU_DATA(rx_packet_info);
158 	frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_packet_info);
159 
160 	pe_debug("Received EXT Channel switch action frame");
161 
162 	ext_channel_switch_frame =
163 		 qdf_mem_malloc(sizeof(*ext_channel_switch_frame));
164 	if (!ext_channel_switch_frame)
165 		return;
166 
167 	/* Unpack channel switch frame */
168 	status = dot11f_unpack_ext_channel_switch_action_frame(mac_ctx,
169 			body, frame_len, ext_channel_switch_frame, false);
170 
171 	if (DOT11F_FAILED(status)) {
172 		pe_err("Failed to parse CHANSW action frame (0x%08x, len %d):",
173 			status, frame_len);
174 		qdf_mem_free(ext_channel_switch_frame);
175 		return;
176 	} else if (DOT11F_WARNED(status)) {
177 		pe_debug("There were warnings while unpacking CHANSW Request (0x%08x, %d bytes):",
178 		  status, frame_len);
179 	}
180 
181 	if (!wlan_reg_is_6ghz_supported(mac_ctx->psoc) &&
182 	    (wlan_reg_is_6ghz_op_class(mac_ctx->pdev,
183 				       ext_channel_switch_frame->
184 				       ext_chan_switch_ann_action.op_class))) {
185 		pe_err("channel belongs to 6 ghz spectrum, abort");
186 		qdf_mem_free(ext_channel_switch_frame);
187 		return;
188 	}
189 
190 	target_freq =
191 		wlan_reg_chan_opclass_to_freq(ext_channel_switch_frame->ext_chan_switch_ann_action.new_channel,
192 					      ext_channel_switch_frame->ext_chan_switch_ann_action.op_class,
193 					      false);
194 
195 	/* Free ext_channel_switch_frame here as its no longer needed */
196 	qdf_mem_free(ext_channel_switch_frame);
197 	/*
198 	 * Now, validate if channel change is required for the passed
199 	 * channel and if is valid in the current regulatory domain,
200 	 * and no concurrent session is running.
201 	 */
202 	if (!(session_entry->curr_op_freq != target_freq &&
203 	      ((wlan_reg_get_channel_state_for_pwrmode(mac_ctx->pdev,
204 						       target_freq,
205 						       REG_CURRENT_PWR_MODE) == CHANNEL_STATE_ENABLE) ||
206 	       (wlan_reg_is_dfs_for_freq(mac_ctx->pdev, target_freq) &&
207 		!policy_mgr_concurrent_open_sessions_running(
208 			mac_ctx->psoc))))) {
209 		pe_err("Channel freq: %d is not valid", target_freq);
210 		return;
211 	}
212 
213 	if (session_entry->opmode == QDF_P2P_GO_MODE) {
214 
215 		struct sir_sme_ext_cng_chan_ind *ext_cng_chan_ind;
216 		struct scheduler_msg mmh_msg = {0};
217 
218 		ext_cng_chan_ind = qdf_mem_malloc(sizeof(*ext_cng_chan_ind));
219 		if (!ext_cng_chan_ind)
220 			return;
221 
222 		ext_cng_chan_ind->session_id =
223 					session_entry->smeSessionId;
224 
225 		/* No need to extract op mode as BW will be decided in
226 		 *  in SAP FSM depending on previous BW.
227 		 */
228 		ext_cng_chan_ind->new_chan_freq = target_freq;
229 
230 		mmh_msg.type = eWNI_SME_EXT_CHANGE_CHANNEL_IND;
231 		mmh_msg.bodyptr = ext_cng_chan_ind;
232 		mmh_msg.bodyval = 0;
233 		lim_sys_process_mmh_msg_api(mac_ctx, &mmh_msg);
234 	}
235 	return;
236 } /*** end lim_process_ext_channel_switch_action_frame() ***/
237 
238 /**
239  * __lim_process_operating_mode_action_frame() - To process op mode frames
240  * @mac_ctx: pointer to mac context
241  * @rx_pkt_info: pointer to received packet info
242  * @session: pointer to session
243  *
244  * This routine is called to process operating mode action frames
245  *
246  * Return: None
247  */
__lim_process_operating_mode_action_frame(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,struct pe_session * session)248 static void __lim_process_operating_mode_action_frame(struct mac_context *mac_ctx,
249 			uint8_t *rx_pkt_info, struct pe_session *session)
250 {
251 
252 	tpSirMacMgmtHdr mac_hdr;
253 	uint8_t *body_ptr;
254 	tDot11fOperatingMode *operating_mode_frm;
255 	uint32_t frame_len;
256 	uint32_t status;
257 	tpDphHashNode sta_ptr;
258 	uint16_t aid;
259 	enum phy_ch_width ch_bw = 0;
260 
261 	mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
262 	body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
263 	frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
264 
265 	pe_debug("Received Operating Mode action frame");
266 
267 	/*
268 	 * Ignore opmode change during channel change The opmode will be updated
269 	 * with the beacons on new channel once the AP move to new channel.
270 	 */
271 	if (session->ch_switch_in_progress) {
272 		pe_debug("Ignore opmode change as channel switch is in progress");
273 		return;
274 	}
275 	operating_mode_frm = qdf_mem_malloc(sizeof(*operating_mode_frm));
276 	if (!operating_mode_frm)
277 		return;
278 
279 	/* Unpack channel switch frame */
280 	status = dot11f_unpack_operating_mode(mac_ctx, body_ptr, frame_len,
281 			operating_mode_frm, false);
282 	if (DOT11F_FAILED(status)) {
283 		pe_err("Failed to unpack and parse (0x%08x, %d bytes)",
284 			status, frame_len);
285 		qdf_mem_free(operating_mode_frm);
286 		return;
287 	} else if (DOT11F_WARNED(status)) {
288 		pe_warn("warnings while unpacking (0x%08x, %d bytes):",
289 			status, frame_len);
290 	}
291 	sta_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid,
292 			&session->dph.dphHashTable);
293 
294 	if (!sta_ptr) {
295 		pe_err("Station context not found");
296 		goto end;
297 	}
298 
299 	lim_update_nss(mac_ctx, sta_ptr,
300 		       operating_mode_frm->OperatingMode.rxNSS, session);
301 
302 	if (lim_update_channel_width(mac_ctx, sta_ptr, session,
303 				   operating_mode_frm->OperatingMode.chanWidth,
304 				   &ch_bw))
305 		wlan_son_deliver_opmode(session->vdev,
306 					ch_bw,
307 					sta_ptr->vhtSupportedRxNss,
308 					mac_hdr->sa);
309 
310 end:
311 	qdf_mem_free(operating_mode_frm);
312 	return;
313 }
314 
315 /**
316  * __lim_process_gid_management_action_frame() - To process group-id mgmt frames
317  * @mac_ctx: Pointer to mac context
318  * @rx_pkt_info: Rx packet info
319  * @session: pointer to session
320  *
321  * This routine will be called to process group id management frames
322  *
323  * Return: none
324  */
325 static void
__lim_process_gid_management_action_frame(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,struct pe_session * session)326 __lim_process_gid_management_action_frame(struct mac_context *mac_ctx,
327 					  uint8_t *rx_pkt_info,
328 					  struct pe_session *session)
329 {
330 	uint8_t *body_ptr;
331 	uint16_t aid;
332 	uint32_t frame_len, status, membership = 0, usr_position = 0;
333 	uint32_t *mem_lower, *mem_upper, *mem_cur;
334 	tpSirMacMgmtHdr mac_hdr;
335 	tDot11fVHTGidManagementActionFrame *gid_mgmt_frame;
336 	tpDphHashNode sta_ptr;
337 	struct sDot11fFfVhtMembershipStatusArray *vht_member_status = NULL;
338 	struct sDot11fFfVhtUserPositionArray *vht_user_position = NULL;
339 
340 	mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
341 	body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
342 	frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
343 
344 	pe_debug("Received GID Management action frame");
345 	gid_mgmt_frame = qdf_mem_malloc(sizeof(*gid_mgmt_frame));
346 	if (!gid_mgmt_frame)
347 		return;
348 
349 	/* Unpack Gid Management Action frame */
350 	status = dot11f_unpack_vht_gid_management_action_frame(mac_ctx,
351 			body_ptr, frame_len, gid_mgmt_frame, false);
352 	if (DOT11F_FAILED(status)) {
353 		pe_err("Fail to parse an Grp id frame (0x%08x, %d bytes):",
354 			status, frame_len);
355 		qdf_mem_free(gid_mgmt_frame);
356 		return;
357 	} else if (DOT11F_WARNED(status)) {
358 		pe_warn("warnings while unpacking Grp id frm (0x%08x, %d bytes):",
359 		 status, frame_len);
360 	}
361 	sta_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid,
362 			&session->dph.dphHashTable);
363 	if (!sta_ptr) {
364 		pe_err("Failed to get STA entry from hash table");
365 		goto out;
366 	}
367 
368 	pe_debug(" MAC: %0x:%0x:%0x:%0x:%0x:%0x",
369 		mac_hdr->sa[0], mac_hdr->sa[1], mac_hdr->sa[2],
370 		mac_hdr->sa[3], mac_hdr->sa[4], mac_hdr->sa[5]);
371 	vht_member_status = &gid_mgmt_frame->VhtMembershipStatusArray;
372 	mem_lower =  (uint32_t *) vht_member_status->membershipStatusArray;
373 	mem_upper = (uint32_t *) &vht_member_status->membershipStatusArray[4];
374 
375 	if (*mem_lower && *mem_upper) {
376 		pe_err("rcved frame with mult group ID set");
377 		goto out;
378 	}
379 	if (*mem_lower) {
380 		mem_cur = mem_lower;
381 	} else if (*mem_upper) {
382 		mem_cur = mem_upper;
383 		membership += sizeof(uint32_t);
384 	} else {
385 		pe_err("rcved Gid frame with no group ID set");
386 		goto out;
387 	}
388 	while (!(*mem_cur & 1)) {
389 		*mem_cur >>= 1;
390 		++membership;
391 	}
392 	if (*mem_cur) {
393 		pe_err("rcved frame with mult group ID set");
394 		goto out;
395 	}
396 
397 	/*Just read the last two bits */
398 	vht_user_position = &gid_mgmt_frame->VhtUserPositionArray;
399 	usr_position = vht_user_position->userPositionArray[membership] & 0x3;
400 	lim_check_membership_user_position(mac_ctx, session, membership,
401 			usr_position);
402 out:
403 	qdf_mem_free(gid_mgmt_frame);
404 	return;
405 }
406 
407 static void
__lim_process_add_ts_req(struct mac_context * mac,uint8_t * pRxPacketInfo,struct pe_session * pe_session)408 __lim_process_add_ts_req(struct mac_context *mac, uint8_t *pRxPacketInfo,
409 			 struct pe_session *pe_session)
410 {
411 }
412 
413 /**
414  * lim_is_medium_time_valid() - To check whether AP sends ADD TS response for
415  * an AC with zero medium time and ACM is enabled
416  * @mac_ctx: Pointer to mac context
417  * @pe_session: pointer to session
418  * @addts: Add TS resp buffer
419  *
420  * Return: false if ADD TS response frame for an AC has 0 as medium time.
421  */
422 static bool
lim_is_medium_time_valid(struct mac_context * mac,struct pe_session * pe_session,tSirAddtsRspInfo addts)423 lim_is_medium_time_valid(struct mac_context *mac, struct pe_session *pe_session,
424 			 tSirAddtsRspInfo addts)
425 {
426 	struct mac_ts_info *ts_info = &addts.tspec.tsinfo;
427 	uint16_t user_priority = ts_info->traffic.userPrio;
428 	uint8_t ac = upToAc(user_priority);
429 	bool is_acm = false;
430 
431 	if (pe_session->wmm_params.present) {
432 		switch (ac) {
433 		case QCA_WLAN_AC_BE:
434 			if (pe_session->wmm_params.acbe_acm)
435 				is_acm = true;
436 			break;
437 		case QCA_WLAN_AC_BK:
438 			if (pe_session->wmm_params.acbk_acm)
439 				is_acm = true;
440 			break;
441 		case QCA_WLAN_AC_VI:
442 			if (pe_session->wmm_params.acvi_acm)
443 				is_acm = true;
444 			break;
445 		case QCA_WLAN_AC_VO:
446 			if (pe_session->wmm_params.acvo_acm)
447 				is_acm = true;
448 			break;
449 		default:
450 			pe_debug("Unknown AC:%d", ac);
451 			break;
452 		}
453 	}
454 	/*
455 	 * If AP sends ADD TS response for an AC with medium time as 0
456 	 * and acm disabled treat it as ADD TS failure.
457 	 */
458 	if (!addts.tspec.mediumTime && is_acm) {
459 		pe_debug("medium time 0 and ACM is mandatory. ADDTS failed");
460 		return false;
461 	}
462 
463 	return true;
464 }
465 
466 /**
467  * __lim_process_add_ts_rsp() - To process add ts response frame
468  * @mac_ctx: pointer to mac context
469  * @rx_pkt_info: Received packet info
470  * @session: pointer to session
471  *
472  * This routine is to handle add ts response frame
473  *
474  * Return: none
475  */
__lim_process_add_ts_rsp(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,struct pe_session * session)476 static void __lim_process_add_ts_rsp(struct mac_context *mac_ctx,
477 		uint8_t *rx_pkt_info, struct pe_session *session)
478 {
479 	tSirAddtsRspInfo addts;
480 	QDF_STATUS retval;
481 	tpSirMacMgmtHdr mac_hdr;
482 	tpDphHashNode sta_ptr;
483 	uint16_t aid;
484 	uint32_t frameLen;
485 	uint8_t *body_ptr;
486 	tpLimTspecInfo tspec_info;
487 	uint8_t ac;
488 	tpDphHashNode sta_ds_ptr = NULL;
489 	uint8_t rsp_reqd = 1;
490 	uint32_t cfg_len;
491 	tSirMacAddr peer_macaddr;
492 
493 	mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
494 	body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
495 	frameLen = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
496 
497 	pe_warn("Recv AddTs Response");
498 	if (LIM_IS_AP_ROLE(session)) {
499 		pe_warn("AddTsRsp recvd at AP: ignoring");
500 		return;
501 	}
502 
503 	sta_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid,
504 				&session->dph.dphHashTable);
505 	if (!sta_ptr) {
506 		pe_err("Station context not found - ignoring AddTsRsp");
507 		return;
508 	}
509 
510 	retval = sir_convert_addts_rsp2_struct(mac_ctx, body_ptr,
511 			frameLen, &addts);
512 	if (retval != QDF_STATUS_SUCCESS) {
513 		pe_err("AddTsRsp parsing failed %d", retval);
514 		return;
515 	}
516 	/*
517 	 * don't have to check for qos/wme capabilities since we wouldn't have
518 	 * this flag set otherwise
519 	 */
520 	if (!mac_ctx->lim.gLimAddtsSent) {
521 		/* we never sent an addts request! */
522 		pe_warn("rx AddTsRsp but no req was ever sent-ignoring");
523 		return;
524 	}
525 
526 	if (mac_ctx->lim.gLimAddtsReq.req.dialogToken != addts.dialogToken) {
527 		pe_warn("token mismatch got: %d exp: %d - ignoring",
528 			addts.dialogToken,
529 			mac_ctx->lim.gLimAddtsReq.req.dialogToken);
530 		return;
531 	}
532 
533 	/*
534 	 * for successful addts response, try to add the classifier.
535 	 * if this fails for any reason, we should send a delts request to the
536 	 * ap for now, its ok not to send a delts since we are going to add
537 	 * support for multiple tclas soon and until then we won't send any
538 	 * addts requests with multiple tclas elements anyway.
539 	 * In case of addClassifier failure, we just let the addts timer run out
540 	 */
541 	if (((addts.tspec.tsinfo.traffic.accessPolicy ==
542 		SIR_MAC_ACCESSPOLICY_HCCA) ||
543 		(addts.tspec.tsinfo.traffic.accessPolicy ==
544 			SIR_MAC_ACCESSPOLICY_BOTH)) &&
545 		(addts.status == STATUS_SUCCESS)) {
546 		/* add the classifier - this should always succeed */
547 		if (addts.numTclas > 1) {
548 			/* currently no support for multiple tclas elements */
549 			pe_err("Sta: %d Too many Tclas: %d 1 supported",
550 				aid, addts.numTclas);
551 			return;
552 		} else if (addts.numTclas == 1) {
553 			pe_debug("Response from STA: %d tsid: %d UP: %d OK!",
554 				aid, addts.tspec.tsinfo.traffic.tsid,
555 				addts.tspec.tsinfo.traffic.userPrio);
556 		}
557 	}
558 
559 	pe_debug("Recv AddTsRsp: tsid: %d UP: %d status: %d",
560 		addts.tspec.tsinfo.traffic.tsid,
561 		addts.tspec.tsinfo.traffic.userPrio, addts.status);
562 
563 	/*
564 	 * Change the status to failure and fallthrough to send response
565 	 * to SME to cleanup the flow.
566 	 */
567 	if (addts.tspec.tsinfo.traffic.direction != SIR_MAC_DIRECTION_DNLINK &&
568 	    !lim_is_medium_time_valid(mac_ctx, session, addts))
569 		addts.status = STATUS_UNSPECIFIED_FAILURE;
570 
571 	/* deactivate the response timer */
572 	lim_deactivate_and_change_timer(mac_ctx, eLIM_ADDTS_RSP_TIMER);
573 
574 	if (addts.status != STATUS_SUCCESS) {
575 		pe_debug("Recv AddTsRsp: tsid: %d UP: %d status: %d",
576 			addts.tspec.tsinfo.traffic.tsid,
577 			addts.tspec.tsinfo.traffic.userPrio, addts.status);
578 		lim_send_sme_addts_rsp(mac_ctx, true, addts.status, session,
579 				       addts.tspec, session->smeSessionId);
580 
581 		/* clear the addts flag */
582 		mac_ctx->lim.gLimAddtsSent = false;
583 
584 		return;
585 	}
586 #ifdef FEATURE_WLAN_ESE
587 	if (addts.tsmPresent) {
588 		pe_debug("TSM IE Present");
589 		session->eseContext.tsm.tid =
590 			addts.tspec.tsinfo.traffic.userPrio;
591 		qdf_mem_copy(&session->eseContext.tsm.tsmInfo,
592 			     &addts.tsmIE, sizeof(struct ese_tsm_ie));
593 		lim_send_sme_tsm_ie_ind(mac_ctx, session, addts.tsmIE.tsid,
594 					addts.tsmIE.state,
595 					addts.tsmIE.msmt_interval);
596 	}
597 #endif
598 	/*
599 	 * Since AddTS response was successful, check for the PSB flag
600 	 * and directional flag inside the TS Info field.
601 	 * An AC is trigger enabled AC if the PSB subfield is set to 1
602 	 * in the uplink direction.
603 	 * An AC is delivery enabled AC if the PSB subfield is set to 1
604 	 * in the downlink direction.
605 	 * An AC is trigger and delivery enabled AC if the PSB subfield
606 	 * is set to 1 in the bi-direction field.
607 	 */
608 	if (addts.tspec.tsinfo.traffic.psb == 1)
609 		lim_set_tspec_uapsd_mask_per_session(mac_ctx, session,
610 						     &addts.tspec.tsinfo,
611 						     SET_UAPSD_MASK);
612 	else
613 		lim_set_tspec_uapsd_mask_per_session(mac_ctx, session,
614 						     &addts.tspec.tsinfo,
615 						     CLEAR_UAPSD_MASK);
616 
617 	/*
618 	 * ADDTS success, so AC is now admitted. We shall now use the default
619 	 * EDCA parameters as advertised by AP and send the updated EDCA params
620 	 * to HAL.
621 	 */
622 	ac = upToAc(addts.tspec.tsinfo.traffic.userPrio);
623 	if (addts.tspec.tsinfo.traffic.direction ==
624 	    SIR_MAC_DIRECTION_UPLINK) {
625 		session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |=
626 			(1 << ac);
627 	} else if (addts.tspec.tsinfo.traffic.direction ==
628 		   SIR_MAC_DIRECTION_DNLINK) {
629 		session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |=
630 			(1 << ac);
631 	} else if (addts.tspec.tsinfo.traffic.direction ==
632 		   SIR_MAC_DIRECTION_BIDIR) {
633 		session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |=
634 			(1 << ac);
635 		session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |=
636 			(1 << ac);
637 	}
638 	lim_set_active_edca_params(mac_ctx, session->gLimEdcaParams,
639 				   session);
640 	sta_ds_ptr = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
641 				   &session->dph.dphHashTable);
642 	if (sta_ds_ptr)
643 		lim_send_edca_params(mac_ctx, session->gLimEdcaParamsActive,
644 				     session->vdev_id, false);
645 	else
646 		pe_err("Self entry missing in Hash Table");
647 	sir_copy_mac_addr(peer_macaddr, session->bssId);
648 	/* if schedule is not present then add TSPEC with svcInterval as 0. */
649 	if (!addts.schedulePresent)
650 		addts.schedule.svcInterval = 0;
651 	if (QDF_STATUS_SUCCESS !=
652 	    lim_tspec_add(mac_ctx, sta_ptr->staAddr, sta_ptr->assocId,
653 		&addts.tspec, addts.schedule.svcInterval, &tspec_info)) {
654 		pe_err("Adding entry in lim Tspec Table failed");
655 		lim_send_delts_req_action_frame(mac_ctx, peer_macaddr, rsp_reqd,
656 						&addts.tspec.tsinfo,
657 						&addts.tspec, session);
658 		mac_ctx->lim.gLimAddtsSent = false;
659 		return;
660 		/*
661 		 * Error handling. send the response with error status.
662 		 * need to send DelTS to tear down the TSPEC status.
663 		 */
664 	}
665 	if ((addts.tspec.tsinfo.traffic.accessPolicy !=
666 			SIR_MAC_ACCESSPOLICY_EDCA) ||
667 		((upToAc(addts.tspec.tsinfo.traffic.userPrio) < QCA_WLAN_AC_ALL))) {
668 #ifdef FEATURE_WLAN_ESE
669 		retval = lim_send_hal_msg_add_ts(mac_ctx,
670 				tspec_info->idx,
671 				addts.tspec, session->peSessionId,
672 				addts.tsmIE.msmt_interval);
673 #else
674 		retval = lim_send_hal_msg_add_ts(mac_ctx,
675 				tspec_info->idx,
676 				addts.tspec, session->peSessionId);
677 #endif
678 		if (QDF_STATUS_SUCCESS != retval) {
679 			lim_admit_control_delete_ts(mac_ctx, sta_ptr->assocId,
680 				&addts.tspec.tsinfo, NULL, &tspec_info->idx);
681 
682 			/* Send DELTS action frame to AP */
683 			cfg_len = sizeof(tSirMacAddr);
684 			lim_send_delts_req_action_frame(mac_ctx, peer_macaddr,
685 					rsp_reqd, &addts.tspec.tsinfo,
686 					&addts.tspec, session);
687 			lim_send_sme_addts_rsp(mac_ctx, true, retval,
688 					session, addts.tspec,
689 					session->smeSessionId);
690 			mac_ctx->lim.gLimAddtsSent = false;
691 			return;
692 		}
693 		pe_debug("AddTsRsp received successfully UP: %d TSID: %d",
694 			addts.tspec.tsinfo.traffic.userPrio,
695 			addts.tspec.tsinfo.traffic.tsid);
696 	} else {
697 		pe_debug("AddTsRsp received successfully UP: %d TSID: %d",
698 			addts.tspec.tsinfo.traffic.userPrio,
699 			addts.tspec.tsinfo.traffic.tsid);
700 		pe_debug("no ACM: Bypass sending WMA_ADD_TS_REQ to HAL");
701 		lim_send_sme_addts_rsp(mac_ctx, true, eSIR_SME_SUCCESS,
702 				       session, addts.tspec,
703 				       session->smeSessionId);
704 	}
705 	/* clear the addts flag */
706 	mac_ctx->lim.gLimAddtsSent = false;
707 	return;
708 }
709 
710 /**
711  * __lim_process_del_ts_req() - To process del ts response frame
712  * @mac_ctx: pointer to mac context
713  * @rx_pkt_info: Received packet info
714  * @session: pointer to session
715  *
716  * This routine is to handle del ts request frame
717  *
718  * Return: none
719  */
__lim_process_del_ts_req(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,struct pe_session * session)720 static void __lim_process_del_ts_req(struct mac_context *mac_ctx,
721 		uint8_t *rx_pkt_info, struct pe_session *session)
722 {
723 	QDF_STATUS retval;
724 	struct delts_req_info delts;
725 	tpSirMacMgmtHdr mac_hdr;
726 	tpDphHashNode sta_ptr;
727 	uint32_t frame_len;
728 	uint16_t aid;
729 	uint8_t *body_ptr;
730 	uint8_t ts_status;
731 	struct mac_ts_info *tsinfo;
732 	uint8_t tspec_idx;
733 	uint8_t ac;
734 	tpDphHashNode sta_ds_ptr = NULL;
735 
736 	mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
737 	body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
738 	frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
739 
740 	sta_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid,
741 				      &session->dph.dphHashTable);
742 	if (!sta_ptr) {
743 		pe_err("Station context not found - ignoring DelTs");
744 		return;
745 	}
746 	/* parse the delts request */
747 	retval = sir_convert_delts_req2_struct(mac_ctx, body_ptr,
748 			frame_len, &delts);
749 	if (retval != QDF_STATUS_SUCCESS) {
750 		pe_err("DelTs parsing failed %d", retval);
751 		return;
752 	}
753 
754 	if (delts.wmeTspecPresent) {
755 		if ((!session->limWmeEnabled) || (!sta_ptr->wmeEnabled)) {
756 			pe_warn("Ignore delts req: wme not enabled");
757 			return;
758 		}
759 		pe_debug("WME Delts received");
760 	} else if ((session->limQosEnabled) && sta_ptr->lleEnabled) {
761 		pe_debug("11e QoS Delts received");
762 	} else if ((session->limWsmEnabled) && sta_ptr->wsmEnabled) {
763 		pe_debug("WSM Delts received");
764 	} else {
765 		pe_warn("Ignoring delts request: qos not enabled/capable");
766 		return;
767 	}
768 
769 	tsinfo = delts.wmeTspecPresent ? &delts.tspec.tsinfo : &delts.tsinfo;
770 
771 	/* if no Admit Control, ignore the request */
772 	if (tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_EDCA) {
773 		if (upToAc(tsinfo->traffic.userPrio) >= QCA_WLAN_AC_ALL) {
774 			pe_warn("DelTs with UP: %d has no AC - ignoring req",
775 				tsinfo->traffic.userPrio);
776 			return;
777 		}
778 	}
779 
780 	if (!LIM_IS_AP_ROLE(session))
781 		lim_send_sme_delts_ind(mac_ctx, &delts, aid, session);
782 
783 	/* try to delete the TS */
784 	if (QDF_STATUS_SUCCESS !=
785 	    lim_admit_control_delete_ts(mac_ctx, sta_ptr->assocId, tsinfo,
786 				&ts_status, &tspec_idx)) {
787 		pe_warn("Unable to Delete TS");
788 		return;
789 	} else if (!((tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_HCCA)
790 			|| (tsinfo->traffic.accessPolicy ==
791 					SIR_MAC_ACCESSPOLICY_BOTH))){
792 		/* send message to HAL to delete TS */
793 		if (QDF_STATUS_SUCCESS != lim_send_hal_msg_del_ts(mac_ctx,
794 						tspec_idx,
795 						delts, session->peSessionId,
796 						session->bssId)) {
797 			pe_warn("DelTs with UP: %d failed ignoring request",
798 				tsinfo->traffic.userPrio);
799 			return;
800 		}
801 	}
802 	/*
803 	 * We successfully deleted the TSPEC. Update the dynamic UAPSD Mask.
804 	 * The AC for this TSPEC is no longer trigger enabled if this Tspec
805 	 * was set-up in uplink direction only.
806 	 * The AC for this TSPEC is no longer delivery enabled if this Tspec
807 	 * was set-up in downlink direction only.
808 	 * The AC for this TSPEC is no longer triiger enabled and delivery
809 	 * enabled if this Tspec was a bidirectional TSPEC.
810 	 */
811 	lim_set_tspec_uapsd_mask_per_session(mac_ctx, session,
812 					     tsinfo, CLEAR_UAPSD_MASK);
813 	/*
814 	 * We're deleting the TSPEC.
815 	 * The AC for this TSPEC is no longer admitted in uplink/downlink
816 	 * direction if this TSPEC was set-up in uplink/downlink direction only.
817 	 * The AC for this TSPEC is no longer admitted in both uplink and
818 	 * downlink directions if this TSPEC was a bi-directional TSPEC.
819 	 * If ACM is set for this AC and this AC is admitted only in downlink
820 	 * direction, PE needs to downgrade the EDCA parameter
821 	 * (for the AC for which TS is being deleted) to the
822 	 * next best AC for which ACM is not enabled, and send the
823 	 * updated values to HAL.
824 	 */
825 	ac = upToAc(tsinfo->traffic.userPrio);
826 	if (tsinfo->traffic.direction == SIR_MAC_DIRECTION_UPLINK) {
827 		session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &=
828 			~(1 << ac);
829 	} else if (tsinfo->traffic.direction ==
830 		   SIR_MAC_DIRECTION_DNLINK) {
831 		session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &=
832 			~(1 << ac);
833 	} else if (tsinfo->traffic.direction == SIR_MAC_DIRECTION_BIDIR) {
834 		session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &=
835 			~(1 << ac);
836 		session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &=
837 			~(1 << ac);
838 	}
839 	lim_set_active_edca_params(mac_ctx, session->gLimEdcaParams,
840 				   session);
841 	sta_ds_ptr = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
842 				   &session->dph.dphHashTable);
843 	if (sta_ds_ptr)
844 		lim_send_edca_params(mac_ctx, session->gLimEdcaParamsActive,
845 				     session->vdev_id, false);
846 	else
847 		pe_err("Self entry missing in Hash Table");
848 
849 	pe_debug("DeleteTS succeeded");
850 #ifdef FEATURE_WLAN_ESE
851 	lim_send_sme_tsm_ie_ind(mac_ctx, session, 0, 0, 0);
852 #endif
853 }
854 
855 /**
856  * __lim_process_qos_map_configure_frame() - to process QoS map configure frame
857  * @mac_ctx: pointer to mac context
858  * @rx_pkt_info: pointer to received packet info
859  * @session: pointer to session
860  *
861  * This routine will called to process qos map configure frame
862  *
863  * Return: none
864  */
__lim_process_qos_map_configure_frame(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,struct pe_session * session)865 static void __lim_process_qos_map_configure_frame(struct mac_context *mac_ctx,
866 			uint8_t *rx_pkt_info, struct pe_session *session)
867 {
868 	tpSirMacMgmtHdr mac_hdr;
869 	uint32_t frame_len;
870 	uint8_t *body_ptr;
871 	QDF_STATUS retval;
872 
873 	mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
874 	body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
875 	frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
876 	retval = sir_convert_qos_map_configure_frame2_struct(mac_ctx,
877 				body_ptr, frame_len, &session->QosMapSet);
878 	if (retval != QDF_STATUS_SUCCESS) {
879 		pe_err("QosMapConfigure frame parsing fail %d", retval);
880 		return;
881 	}
882 	lim_send_sme_mgmt_frame_ind(mac_ctx, mac_hdr->fc.subType,
883 				    (uint8_t *)mac_hdr,
884 				    frame_len + sizeof(tSirMacMgmtHdr), 0,
885 				    WMA_GET_RX_FREQ(rx_pkt_info),
886 				    WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info),
887 				    RXMGMT_FLAG_NONE);
888 }
889 
890 #ifdef ANI_SUPPORT_11H
891 static void
__lim_process_basic_meas_req(struct mac_context * mac,tpSirMacMeasReqActionFrame pMeasReqFrame,tSirMacAddr peerMacAddr,struct pe_session * pe_session)892 __lim_process_basic_meas_req(struct mac_context *mac,
893 			     tpSirMacMeasReqActionFrame pMeasReqFrame,
894 			     tSirMacAddr peerMacAddr, struct pe_session *pe_session)
895 {
896 	if (lim_send_meas_report_frame(mac, pMeasReqFrame,
897 				       peerMacAddr, pe_session) !=
898 					 QDF_STATUS_SUCCESS) {
899 		pe_err("fail to send Basic Meas report");
900 		return;
901 	}
902 }
903 static void
__lim_process_cca_meas_req(struct mac_context * mac,tpSirMacMeasReqActionFrame pMeasReqFrame,tSirMacAddr peerMacAddr,struct pe_session * pe_session)904 __lim_process_cca_meas_req(struct mac_context *mac,
905 			   tpSirMacMeasReqActionFrame pMeasReqFrame,
906 			   tSirMacAddr peerMacAddr, struct pe_session *pe_session)
907 {
908 	if (lim_send_meas_report_frame(mac, pMeasReqFrame,
909 				       peerMacAddr, pe_session) !=
910 					 QDF_STATUS_SUCCESS) {
911 		pe_err("fail to send CCA Meas report");
912 		return;
913 	}
914 }
915 static void
__lim_process_rpi_meas_req(struct mac_context * mac,tpSirMacMeasReqActionFrame pMeasReqFrame,tSirMacAddr peerMacAddr,struct pe_session * pe_session)916 __lim_process_rpi_meas_req(struct mac_context *mac,
917 			   tpSirMacMeasReqActionFrame pMeasReqFrame,
918 			   tSirMacAddr peerMacAddr, struct pe_session *pe_session)
919 {
920 	if (lim_send_meas_report_frame(mac, pMeasReqFrame,
921 				       peerMacAddr, pe_session) !=
922 					 QDF_STATUS_SUCCESS) {
923 		pe_err("fail to send RPI Meas report");
924 		return;
925 	}
926 }
927 static void
__lim_process_measurement_request_frame(struct mac_context * mac,uint8_t * pRxPacketInfo,struct pe_session * pe_session)928 __lim_process_measurement_request_frame(struct mac_context *mac,
929 					uint8_t *pRxPacketInfo,
930 					struct pe_session *pe_session)
931 {
932 	tpSirMacMgmtHdr pHdr;
933 	uint8_t *pBody;
934 	tpSirMacMeasReqActionFrame pMeasReqFrame;
935 	uint32_t frameLen;
936 
937 	pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
938 	pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
939 	frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
940 
941 	pMeasReqFrame = qdf_mem_malloc(sizeof(tSirMacMeasReqActionFrame));
942 	if (!pMeasReqFrame)
943 		return;
944 
945 	if (sir_convert_meas_req_frame2_struct(mac, pBody, pMeasReqFrame, frameLen)
946 	    != QDF_STATUS_SUCCESS) {
947 		pe_warn("Rcv invalid Measurement Request Action Frame");
948 		return;
949 	}
950 	switch (pMeasReqFrame->measReqIE.measType) {
951 	case SIR_MAC_BASIC_MEASUREMENT_TYPE:
952 		__lim_process_basic_meas_req(mac, pMeasReqFrame, pHdr->sa,
953 					     pe_session);
954 		break;
955 	case SIR_MAC_CCA_MEASUREMENT_TYPE:
956 		__lim_process_cca_meas_req(mac, pMeasReqFrame, pHdr->sa,
957 					   pe_session);
958 		break;
959 	case SIR_MAC_RPI_MEASUREMENT_TYPE:
960 		__lim_process_rpi_meas_req(mac, pMeasReqFrame, pHdr->sa,
961 					   pe_session);
962 		break;
963 	default:
964 		pe_warn("Unknown Measurement Type: %d",
965 			       pMeasReqFrame->measReqIE.measType);
966 		break;
967 	}
968 } /*** end limProcessMeasurementRequestFrame ***/
969 static void
__lim_process_tpc_request_frame(struct mac_context * mac,uint8_t * pRxPacketInfo,struct pe_session * pe_session)970 __lim_process_tpc_request_frame(struct mac_context *mac, uint8_t *pRxPacketInfo,
971 				struct pe_session *pe_session)
972 {
973 	tpSirMacMgmtHdr pHdr;
974 	uint8_t *pBody;
975 	tpSirMacTpcReqActionFrame pTpcReqFrame;
976 	uint32_t frameLen;
977 
978 	pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
979 	pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
980 	frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
981 	pe_debug("****LIM: Processing TPC Request from peer ****");
982 
983 	pTpcReqFrame = qdf_mem_malloc(sizeof(tSirMacTpcReqActionFrame));
984 	if (!pTpcReqFrame)
985 		return;
986 
987 	if (sir_convert_tpc_req_frame2_struct(mac, pBody, pTpcReqFrame, frameLen) !=
988 	    QDF_STATUS_SUCCESS) {
989 		pe_warn("Rcv invalid TPC Req Action Frame");
990 		return;
991 	}
992 	if (lim_send_tpc_report_frame(mac,
993 				      pTpcReqFrame,
994 				      pHdr->sa, pe_session) != QDF_STATUS_SUCCESS) {
995 		pe_err("fail to send TPC Report Frame");
996 		return;
997 	}
998 }
999 #endif
1000 
1001 static void
__lim_process_sm_power_save_update(struct mac_context * mac,uint8_t * pRxPacketInfo,struct pe_session * pe_session)1002 __lim_process_sm_power_save_update(struct mac_context *mac, uint8_t *pRxPacketInfo,
1003 				   struct pe_session *pe_session)
1004 {
1005 
1006 	tpSirMacMgmtHdr pHdr;
1007 	tDot11fSMPowerSave frmSMPower;
1008 	tSirMacHTMIMOPowerSaveState state;
1009 	tpDphHashNode pSta;
1010 	uint16_t aid;
1011 	uint32_t frameLen, nStatus;
1012 	uint8_t *pBody;
1013 
1014 	pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
1015 	pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
1016 	frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
1017 
1018 	pSta =
1019 		dph_lookup_hash_entry(mac, pHdr->sa, &aid,
1020 				      &pe_session->dph.dphHashTable);
1021 	if (!pSta) {
1022 		pe_err("STA context not found - ignoring UpdateSM PSave Mode from SA: "QDF_MAC_ADDR_FMT,
1023 		       QDF_MAC_ADDR_REF(pHdr->sa));
1024 		return;
1025 	}
1026 
1027 	/**Unpack the received frame */
1028 	nStatus = dot11f_unpack_sm_power_save(mac, pBody, frameLen,
1029 					      &frmSMPower, false);
1030 
1031 	if (DOT11F_FAILED(nStatus)) {
1032 		pe_err("Failed to unpack and parse a Update SM Power (0x%08x, %d bytes):",
1033 			nStatus, frameLen);
1034 		QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
1035 				   pBody, frameLen);
1036 		return;
1037 	} else if (DOT11F_WARNED(nStatus)) {
1038 		pe_debug("There were warnings while unpacking a SMPower Save update (0x%08x, %d bytes):",
1039 			nStatus, frameLen);
1040 	}
1041 
1042 	pe_debug("Received SM Power save Mode update Frame with PS_Enable: %d"
1043 		   "PS Mode: %d", frmSMPower.SMPowerModeSet.PowerSave_En,
1044 		frmSMPower.SMPowerModeSet.Mode);
1045 
1046 	/** Update in the DPH Table about the Update in the SM Power Save mode*/
1047 	if (frmSMPower.SMPowerModeSet.PowerSave_En
1048 	    && frmSMPower.SMPowerModeSet.Mode)
1049 		state = eSIR_HT_MIMO_PS_DYNAMIC;
1050 	else if ((frmSMPower.SMPowerModeSet.PowerSave_En)
1051 		 && (frmSMPower.SMPowerModeSet.Mode == 0))
1052 		state = eSIR_HT_MIMO_PS_STATIC;
1053 	else if ((frmSMPower.SMPowerModeSet.PowerSave_En == 0)
1054 		 && (frmSMPower.SMPowerModeSet.Mode == 0))
1055 		state = eSIR_HT_MIMO_PS_NO_LIMIT;
1056 	else {
1057 		pe_warn("Received SM Power save Mode update Frame with invalid mode");
1058 		return;
1059 	}
1060 
1061 	if (state == pSta->htMIMOPSState) {
1062 		pe_err("The PEER is already set in the same mode");
1063 		return;
1064 	}
1065 
1066 	/** Update in the HAL Station Table for the Update of the Protection Mode */
1067 	pSta->htMIMOPSState = state;
1068 	lim_post_sm_state_update(mac, pSta->htMIMOPSState,
1069 				 pSta->staAddr, pe_session->smeSessionId);
1070 	wlan_son_deliver_smps(pe_session->vdev,
1071 			      (eSIR_HT_MIMO_PS_STATIC == state) ? 1 : 0,
1072 			      pSta->staAddr);
1073 }
1074 
1075 
1076 static void
__lim_process_radio_measure_request(struct mac_context * mac,uint8_t * pRxPacketInfo,struct pe_session * pe_session)1077 __lim_process_radio_measure_request(struct mac_context *mac, uint8_t *pRxPacketInfo,
1078 				    struct pe_session *pe_session)
1079 {
1080 	tpSirMacMgmtHdr pHdr;
1081 	tDot11fRadioMeasurementRequest *frm;
1082 	uint32_t frameLen, nStatus;
1083 	uint8_t *pBody;
1084 	uint16_t curr_seq_num;
1085 
1086 	pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
1087 	pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
1088 	frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
1089 
1090 	if (!pe_session) {
1091 		return;
1092 	}
1093 
1094 	curr_seq_num = ((pHdr->seqControl.seqNumHi <<
1095 			 HIGH_SEQ_NUM_OFFSET) |
1096 			pHdr->seqControl.seqNumLo);
1097 	if (curr_seq_num == mac->rrm.rrmPEContext.prev_rrm_report_seq_num &&
1098 	    (mac->rrm.rrmPEContext.pCurrentReq[DEFAULT_RRM_IDX] ||
1099 	     mac->rrm.rrmPEContext.pCurrentReq[DEFAULT_RRM_IDX + 1])) {
1100 		pe_err("rrm report req frame, seq num: %d is already in progress, drop it",
1101 			curr_seq_num);
1102 		return;
1103 	}
1104 	/* Save seq no of currently processing rrm report req frame */
1105 	mac->rrm.rrmPEContext.prev_rrm_report_seq_num = curr_seq_num;
1106 
1107 	frm = qdf_mem_malloc(sizeof(*frm));
1108 	if (!frm)
1109 		return;
1110 
1111 	/**Unpack the received frame */
1112 	nStatus = dot11f_unpack_radio_measurement_request(mac, pBody,
1113 							  frameLen, frm, false);
1114 
1115 	if (DOT11F_FAILED(nStatus)) {
1116 		pe_err("Failed to unpack and parse a Radio Measure request (0x%08x, %d bytes):",
1117 			nStatus, frameLen);
1118 		QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
1119 				   pBody, frameLen);
1120 		goto err;
1121 	} else if (DOT11F_WARNED(nStatus)) {
1122 		pe_debug("Warnings while unpacking a Radio Measure request (0x%08x, %d bytes):",
1123 			 nStatus, frameLen);
1124 	}
1125 	/* Call rrm function to handle the request. */
1126 
1127 	pe_debug("vdev: %d Received rrm req from sa addr:"QDF_MAC_ADDR_FMT" bssId:"QDF_MAC_ADDR_FMT" session addr:"QDF_MAC_ADDR_FMT" session self addr:"QDF_MAC_ADDR_FMT"",
1128 		 pe_session->vdev_id,
1129 		 QDF_MAC_ADDR_REF(pHdr->sa),
1130 		 QDF_MAC_ADDR_REF(pHdr->bssId),
1131 		 QDF_MAC_ADDR_REF(pe_session->bssId),
1132 		 QDF_MAC_ADDR_REF(pe_session->self_mac_addr));
1133 
1134 	pe_debug("RX RRM - type %hu, sub type %hu, seq num[%d]",
1135 		 pHdr->fc.type, pHdr->fc.subType, curr_seq_num);
1136 
1137 	rrm_process_radio_measurement_request(mac, pe_session->bssId, frm,
1138 					      pe_session);
1139 err:
1140 	qdf_mem_free(frm);
1141 }
1142 
1143 static QDF_STATUS
__lim_process_link_measurement_req(struct mac_context * mac,uint8_t * pRxPacketInfo,struct pe_session * pe_session)1144 __lim_process_link_measurement_req(struct mac_context *mac, uint8_t *pRxPacketInfo,
1145 				   struct pe_session *pe_session)
1146 {
1147 	tpSirMacMgmtHdr pHdr;
1148 	tDot11fLinkMeasurementRequest frm;
1149 	uint32_t frameLen, nStatus;
1150 	uint8_t *pBody;
1151 
1152 	pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
1153 	pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
1154 	frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
1155 
1156 	if (!pe_session) {
1157 		return QDF_STATUS_E_FAILURE;
1158 	}
1159 
1160 	/**Unpack the received frame */
1161 	nStatus =
1162 		dot11f_unpack_link_measurement_request(mac, pBody, frameLen,
1163 						       &frm, false);
1164 
1165 	if (DOT11F_FAILED(nStatus)) {
1166 		pe_err("Failed to unpack and parse a Link Measure request (0x%08x, %d bytes):",
1167 			nStatus, frameLen);
1168 		QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
1169 				   pBody, frameLen);
1170 		return QDF_STATUS_E_FAILURE;
1171 	} else if (DOT11F_WARNED(nStatus)) {
1172 		pe_debug("There were warnings while unpacking a Link Measure request (0x%08x, %d bytes):",
1173 			nStatus, frameLen);
1174 	}
1175 
1176 	if (pe_session->sta_follows_sap_power) {
1177 		pe_debug("STA power has changed, reject the link measurement request");
1178 		return QDF_STATUS_E_FAILURE;
1179 	}
1180 	/* Call rrm function to handle the request. */
1181 	return rrm_process_link_measurement_request(mac, pRxPacketInfo, &frm,
1182 					     pe_session);
1183 
1184 }
1185 
1186 static void
__lim_process_neighbor_report(struct mac_context * mac,uint8_t * pRxPacketInfo,struct pe_session * pe_session)1187 __lim_process_neighbor_report(struct mac_context *mac, uint8_t *pRxPacketInfo,
1188 			      struct pe_session *pe_session)
1189 {
1190 	tpSirMacMgmtHdr pHdr;
1191 	tDot11fNeighborReportResponse *pFrm;
1192 	uint32_t frameLen, nStatus;
1193 	uint8_t *pBody;
1194 
1195 	pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
1196 	pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
1197 	frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
1198 
1199 	pFrm = qdf_mem_malloc(sizeof(tDot11fNeighborReportResponse));
1200 	if (!pFrm)
1201 		return;
1202 
1203 	if (!pe_session) {
1204 		qdf_mem_free(pFrm);
1205 		return;
1206 	}
1207 
1208 	/**Unpack the received frame */
1209 	nStatus =
1210 		dot11f_unpack_neighbor_report_response(mac, pBody,
1211 						       frameLen, pFrm, false);
1212 
1213 	if (DOT11F_FAILED(nStatus)) {
1214 		pe_err("Failed to unpack and parse a Neighbor report response (0x%08x, %d bytes):",
1215 			nStatus, frameLen);
1216 		QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
1217 				   pBody, frameLen);
1218 		qdf_mem_free(pFrm);
1219 		return;
1220 	} else if (DOT11F_WARNED(nStatus)) {
1221 		pe_debug("There were warnings while unpacking a Neighbor report response (0x%08x, %d bytes):",
1222 			nStatus, frameLen);
1223 	}
1224 
1225 	/* Call rrm function to handle the request. */
1226 	rrm_process_neighbor_report_response(mac, pFrm, pe_session);
1227 
1228 	qdf_mem_free(pFrm);
1229 }
1230 
1231 static bool
lim_check_oci_match(struct mac_context * mac,struct pe_session * pe_session,uint8_t * ie,uint8_t * peer,uint32_t ie_len)1232 lim_check_oci_match(struct mac_context *mac, struct pe_session *pe_session,
1233 		    uint8_t *ie, uint8_t *peer, uint32_t ie_len)
1234 {
1235 	const uint8_t *oci_ie, ext_id_param = WLAN_EXTN_ELEMID_OCI;
1236 	tDot11fIEoci self_oci, peer_oci = {0};
1237 	uint16_t peer_chan_width;
1238 	uint16_t local_peer_chan_width = 0;
1239 	uint8_t country_code[CDS_COUNTRY_CODE_LEN + 1];
1240 	uint32_t status = DOT11F_PARSE_SUCCESS;
1241 
1242 	if (!lim_is_self_and_peer_ocv_capable(mac, peer, pe_session))
1243 		return true;
1244 
1245 	if (ie_len < MIN_OCI_IE_LEN)
1246 		return false;
1247 
1248 	oci_ie = wlan_get_ext_ie_ptr_from_ext_id(&ext_id_param,
1249 						 OCI_IE_OUI_SIZE,
1250 						 ie, ie_len);
1251 	if (!oci_ie) {
1252 		pe_err("OCV not found OCI in SA Query frame!");
1253 		return false;
1254 	}
1255 
1256 	/* OCV enabled, check the OCI information:
1257 	 * Element ID           : 1 byte
1258 	 * Packet length        : 1 byte
1259 	 * Element ID extension : 1 byte
1260 	 * Operating class      : 1 byte
1261 	 * Primary channel      : 1 byte
1262 	 * Freq_seg_1_ch_num    : 1 byte
1263 	 */
1264 	status = dot11f_unpack_ie_oci(mac,
1265 				      (uint8_t *)&oci_ie[OCI_IE_OP_CLS_OFFSET],
1266 				      oci_ie[SIR_MAC_IE_LEN_OFFSET] -
1267 				      ELE_ID_EXT_LEN,
1268 				      &peer_oci, false);
1269 	if (!DOT11F_SUCCEEDED(status) || !peer_oci.present)
1270 		return false;
1271 
1272 	wlan_reg_read_current_country(mac->psoc, country_code);
1273 	peer_chan_width =
1274 	wlan_reg_dmn_get_chanwidth_from_opclass_auto(
1275 			country_code,
1276 			peer_oci.prim_ch_num,
1277 			peer_oci.op_class);
1278 
1279 	lim_fill_oci_params(mac, pe_session, &self_oci, peer,
1280 			    &local_peer_chan_width);
1281 	if ((self_oci.op_class != peer_oci.op_class &&
1282 	     local_peer_chan_width > peer_chan_width) ||
1283 	    self_oci.prim_ch_num != peer_oci.prim_ch_num ||
1284 	    self_oci.freq_seg_1_ch_num != peer_oci.freq_seg_1_ch_num) {
1285 		pe_err("OCI mismatch,self %d %d %d %d, peer %d %d %d %d",
1286 		       self_oci.op_class,
1287 		       self_oci.prim_ch_num,
1288 		       self_oci.freq_seg_1_ch_num,
1289 		       local_peer_chan_width,
1290 		       peer_oci.op_class,
1291 		       peer_oci.prim_ch_num,
1292 		       peer_oci.freq_seg_1_ch_num,
1293 		       peer_chan_width);
1294 		return false;
1295 	}
1296 
1297 	return true;
1298 }
1299 
1300 /**
1301  * limProcessSAQueryRequestActionFrame
1302  *
1303  ***FUNCTION:
1304  * This function is called by lim_process_action_frame() upon
1305  * SA query request Action frame reception.
1306  *
1307  ***LOGIC:
1308  *
1309  ***ASSUMPTIONS:
1310  *
1311  ***NOTE:
1312  *
1313  * @param  mac - Pointer to Global MAC structure
1314  * @param  *pRxPacketInfo - Handle to the Rx packet info
1315  * @param  pe_session - PE session entry
1316  *
1317  * @return None
1318  */
__lim_process_sa_query_request_action_frame(struct mac_context * mac,uint8_t * pRxPacketInfo,struct pe_session * pe_session)1319 static void __lim_process_sa_query_request_action_frame(struct mac_context *mac,
1320 							uint8_t *pRxPacketInfo,
1321 							struct pe_session *pe_session)
1322 {
1323 	tpSirMacMgmtHdr mac_header;
1324 	uint8_t *p_body;
1325 	uint32_t frame_len;
1326 	uint8_t transId[2];
1327 	tpDphHashNode sta_ds;
1328 	uint16_t aid;
1329 
1330 	/* Prima  --- Below Macro not available in prima
1331 	   pHdr = SIR_MAC_BD_TO_MPDUHEADER(pBd);
1332 	   pBody = SIR_MAC_BD_TO_MPDUDATA(pBd); */
1333 
1334 	mac_header = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
1335 	p_body = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
1336 	frame_len = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
1337 
1338 	if (frame_len < SA_QUERY_REQ_MIN_LEN) {
1339 		pe_err("Invalid frame length %d", frame_len);
1340 		return;
1341 	}
1342 	/* If this is an unprotected SA Query Request, then ignore it. */
1343 	if (mac_header->fc.wep == 0)
1344 		return;
1345 
1346 	/* 11w offload is enabled then firmware should not fwd this frame */
1347 	if (LIM_IS_STA_ROLE(pe_session) && mac->pmf_offload) {
1348 		pe_err("11w offload enabled, SA Query req isn't expected");
1349 		return;
1350 	}
1351 
1352 	/*Extract 11w trsansId from SA query request action frame
1353 	   In SA query response action frame we will send same transId
1354 	   In SA query request action frame:
1355 	   Category       : 1 byte
1356 	   Action         : 1 byte
1357 	   Transaction ID : 2 bytes */
1358 	qdf_mem_copy(&transId[0], &p_body[2], 2);
1359 
1360 	sta_ds = dph_lookup_hash_entry(mac, mac_header->sa, &aid,
1361 				       &pe_session->dph.dphHashTable);
1362 
1363 	if (!lim_check_oci_match(mac, pe_session,
1364 				 p_body + SA_QUERY_IE_OFFSET,
1365 				 mac_header->sa,
1366 				 frame_len - SA_QUERY_IE_OFFSET)) {
1367 		/*
1368 		 * In case of channel switch, last ocv frequency will be
1369 		 * different from current frquency.
1370 		 * If there is channel switch and OCI is invalid in sa_query,
1371 		 * deauth STA on new channel.
1372 		 */
1373 		if (sta_ds && sta_ds->ocv_enabled &&
1374 		    sta_ds->last_ocv_done_freq != pe_session->curr_op_freq)
1375 			lim_send_deauth_mgmt_frame(mac, REASON_OCI_MISMATCH,
1376 						   mac_header->sa, pe_session,
1377 						   false);
1378 		return;
1379 	}
1380 
1381 	/*
1382 	 * Update the last ocv done freq when OCI is valid.
1383 	 * To support above algo, if it is moved to the current freq.
1384 	 */
1385 	if (sta_ds && sta_ds->ocv_enabled)
1386 		sta_ds->last_ocv_done_freq = pe_session->curr_op_freq;
1387 
1388 	/* Send 11w SA query response action frame */
1389 	if (lim_send_sa_query_response_frame(mac,
1390 					     transId,
1391 					     mac_header->sa,
1392 					     pe_session) != QDF_STATUS_SUCCESS) {
1393 		pe_err("fail to send SA query response action frame");
1394 		return;
1395 	}
1396 }
1397 
1398 /**
1399  * __lim_process_sa_query_response_action_frame
1400  *
1401  ***FUNCTION:
1402  * This function is called by lim_process_action_frame() upon
1403  * SA query response Action frame reception.
1404  *
1405  ***LOGIC:
1406  *
1407  ***ASSUMPTIONS:
1408  *
1409  ***NOTE:
1410  *
1411  * @param  mac - Pointer to Global MAC structure
1412  * @param  *pRxPacketInfo - Handle to the Rx packet info
1413  * @param  pe_session - PE session entry
1414  * @return None
1415  */
__lim_process_sa_query_response_action_frame(struct mac_context * mac,uint8_t * pRxPacketInfo,struct pe_session * pe_session)1416 static void __lim_process_sa_query_response_action_frame(struct mac_context *mac,
1417 							 uint8_t *pRxPacketInfo,
1418 							 struct pe_session *pe_session)
1419 {
1420 	tpSirMacMgmtHdr m_hdr;
1421 	uint32_t frame_len;
1422 	uint8_t *p_body;
1423 	tpDphHashNode pSta;
1424 	uint16_t aid;
1425 	uint16_t transId;
1426 	uint8_t retryNum;
1427 
1428 	m_hdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
1429 	frame_len = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
1430 	p_body = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
1431 	pe_debug("SA Query Response received");
1432 
1433 	if (frame_len < SA_QUERY_RESP_MIN_LEN) {
1434 		pe_err("Invalid frame length %d", frame_len);
1435 		return;
1436 	}
1437 	/* When a station, supplicant handles SA Query Response.
1438 	 * Forward to SME to HDD to wpa_supplicant.
1439 	 */
1440 	if (LIM_IS_STA_ROLE(pe_session)) {
1441 		lim_send_sme_mgmt_frame_ind(mac, m_hdr->fc.subType,
1442 					    (uint8_t *)m_hdr,
1443 					    frame_len + sizeof(tSirMacMgmtHdr),
1444 					    0,
1445 					    WMA_GET_RX_FREQ(pRxPacketInfo),
1446 					    WMA_GET_RX_RSSI_NORMALIZED(
1447 					    pRxPacketInfo), RXMGMT_FLAG_NONE);
1448 		return;
1449 	}
1450 
1451 	/* If this is an unprotected SA Query Response, then ignore it. */
1452 	if (m_hdr->fc.wep == 0)
1453 		return;
1454 
1455 	pSta =
1456 		dph_lookup_hash_entry(mac, m_hdr->sa, &aid,
1457 				      &pe_session->dph.dphHashTable);
1458 	if (!pSta)
1459 		return;
1460 
1461 	pe_debug("SA Query Response source addr:  %0x:%0x:%0x:%0x:%0x:%0x",
1462 		 m_hdr->sa[0], m_hdr->sa[1], m_hdr->sa[2], m_hdr->sa[3],
1463 		 m_hdr->sa[4], m_hdr->sa[5]);
1464 	pe_debug("SA Query state for station: %d", pSta->pmfSaQueryState);
1465 
1466 	if (DPH_SA_QUERY_IN_PROGRESS != pSta->pmfSaQueryState)
1467 		return;
1468 
1469 	/* Extract 11w trsansId from SA query response action frame
1470 	   In SA query response action frame:
1471 	   Category       : 1 byte
1472 	   Action         : 1 byte
1473 	   Transaction ID : 2 bytes */
1474 	qdf_mem_copy(&transId, &p_body[2], 2);
1475 
1476 	/* If SA Query is in progress with the station and the station
1477 	   responds then the association request that triggered the SA
1478 	   query is from a rogue station, just go back to initial state. */
1479 	for (retryNum = 0; retryNum <= pSta->pmfSaQueryRetryCount; retryNum++)
1480 		if (transId == pSta->pmfSaQueryStartTransId + retryNum) {
1481 			if (!lim_check_oci_match(mac, pe_session,
1482 						 p_body + SA_QUERY_IE_OFFSET,
1483 						 m_hdr->sa,
1484 						 frame_len -
1485 						 SA_QUERY_IE_OFFSET))
1486 				return;
1487 			pe_debug("Found matching SA Query Request - transaction ID: %d",
1488 				transId);
1489 			tx_timer_deactivate(&pSta->pmfSaQueryTimer);
1490 			pSta->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS;
1491 			break;
1492 		}
1493 }
1494 
1495 /**
1496  * lim_drop_unprotected_action_frame
1497  *
1498  ***FUNCTION:
1499  * This function checks if an Action frame should be dropped since it is
1500  * a Robust Management Frame, it is unprotected, and it is received on a
1501  * connection where PMF is enabled.
1502  *
1503  ***LOGIC:
1504  *
1505  ***ASSUMPTIONS:
1506  *
1507  ***NOTE:
1508  *
1509  * @param  mac - Global MAC structure
1510  * @param  pe_session - PE session entry
1511  * @param  pHdr - Frame header
1512  * @param  category - Action frame category
1513  * @return true if frame should be dropped
1514  */
1515 
1516 static bool
lim_drop_unprotected_action_frame(struct mac_context * mac,struct pe_session * pe_session,tpSirMacMgmtHdr pHdr,uint8_t category)1517 lim_drop_unprotected_action_frame(struct mac_context *mac, struct pe_session *pe_session,
1518 				  tpSirMacMgmtHdr pHdr, uint8_t category)
1519 {
1520 	uint16_t aid;
1521 	tpDphHashNode sta;
1522 	bool rmfConnection = false;
1523 
1524 	sta = dph_lookup_hash_entry(mac, pHdr->sa, &aid,
1525 				    &pe_session->dph.dphHashTable);
1526 	if (sta && sta->rmfEnabled)
1527 		rmfConnection = true;
1528 
1529 	if (rmfConnection && (pHdr->fc.wep == 0)) {
1530 		pe_err("Dropping unprotected Action category: %d frame since RMF is enabled",
1531 			category);
1532 		return true;
1533 	}
1534 
1535 	return false;
1536 }
1537 
1538 /**
1539  * lim_process_addba_req() - process ADDBA Request
1540  * @mac_ctx: Pointer to Global MAC structure
1541  * @rx_pkt_info: A pointer to packet info structure
1542  * @session: PE session pointer
1543  *
1544  * This routine will be called to process ADDBA request action frame
1545  *
1546  * Return: None
1547  */
lim_process_addba_req(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,struct pe_session * session)1548 static void lim_process_addba_req(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
1549 				  struct pe_session *session)
1550 {
1551 	tpSirMacMgmtHdr mac_hdr;
1552 	uint8_t *body_ptr;
1553 	tDot11faddba_req *addba_req;
1554 	uint32_t frame_len, status;
1555 	QDF_STATUS qdf_status;
1556 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
1557 	tpDphHashNode sta_ds;
1558 	uint16_t aid, buff_size;
1559 	bool he_cap = false;
1560 	bool eht_cap = false;
1561 	uint8_t extd_buff_size = 0;
1562 
1563 	if (mlo_is_any_link_disconnecting(session->vdev)) {
1564 		pe_err("Ignore ADDBA, vdev is in not in conncted state");
1565 		return;
1566 	}
1567 
1568 	mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
1569 	body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
1570 	frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
1571 
1572 	QDF_TRACE_HEX_DUMP_DEBUG_RL(QDF_MODULE_ID_PE, body_ptr, frame_len);
1573 
1574 	addba_req = qdf_mem_malloc(sizeof(*addba_req));
1575 	if (!addba_req)
1576 		return;
1577 
1578 	/* Unpack ADDBA request frame */
1579 	status = dot11f_unpack_addba_req(mac_ctx, body_ptr, frame_len,
1580 					 addba_req, false);
1581 
1582 	if (DOT11F_FAILED(status)) {
1583 		pe_err("Failed to unpack and parse (0x%08x, %d bytes)",
1584 			status, frame_len);
1585 		goto error;
1586 	} else if (DOT11F_WARNED(status)) {
1587 		pe_warn("warning: unpack addba Req(0x%08x, %d bytes)",
1588 			status, frame_len);
1589 	}
1590 
1591 	sta_ds = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid,
1592 				       &session->dph.dphHashTable);
1593 	if (sta_ds &&
1594 	    (lim_is_session_he_capable(session) ||
1595 	     sta_ds->staType == STA_ENTRY_TDLS_PEER))
1596 		he_cap = lim_is_sta_he_capable(sta_ds);
1597 
1598 	if (sta_ds &&
1599 	    (lim_is_session_eht_capable(session) ||
1600 	     sta_ds->staType == STA_ENTRY_TDLS_PEER))
1601 		eht_cap = lim_is_sta_eht_capable(sta_ds);
1602 
1603 	if (sta_ds && sta_ds->staType == STA_ENTRY_NDI_PEER)
1604 		he_cap = lim_is_session_he_capable(session);
1605 
1606 	if (eht_cap)
1607 		buff_size = MAX_EHT_BA_BUFF_SIZE;
1608 	else if (he_cap)
1609 		buff_size = MAX_BA_BUFF_SIZE;
1610 	else
1611 		buff_size = SIR_MAC_BA_DEFAULT_BUFF_SIZE;
1612 
1613 	if (mac_ctx->usr_cfg_ba_buff_size)
1614 		buff_size = mac_ctx->usr_cfg_ba_buff_size;
1615 
1616 	if (addba_req->addba_extn_element.present)
1617 		extd_buff_size = addba_req->addba_extn_element.extd_buff_size;
1618 
1619 	if (addba_req->addba_param_set.buff_size)
1620 		buff_size = QDF_MIN(buff_size,
1621 				    addba_req->addba_param_set.buff_size);
1622 	else if (extd_buff_size)
1623 		/* limit the buff size */
1624 		buff_size = QDF_MIN(buff_size, MAX_EHT_BA_BUFF_SIZE);
1625 
1626 	pe_debug("token %d tid %d timeout %d buff_size in frame %d buf_size calculated %d ssn %d, extd buff size %d",
1627 		 addba_req->DialogToken.token, addba_req->addba_param_set.tid,
1628 		 addba_req->ba_timeout.timeout,
1629 		 addba_req->addba_param_set.buff_size, buff_size,
1630 		 addba_req->ba_start_seq_ctrl.ssn, extd_buff_size);
1631 
1632 	qdf_status = cdp_addba_requestprocess(
1633 					soc, mac_hdr->sa,
1634 					session->vdev_id,
1635 					addba_req->DialogToken.token,
1636 					addba_req->addba_param_set.tid,
1637 					addba_req->ba_timeout.timeout,
1638 					buff_size,
1639 					addba_req->ba_start_seq_ctrl.ssn);
1640 
1641 	if (QDF_STATUS_SUCCESS == qdf_status) {
1642 		qdf_status = lim_send_addba_response_frame(mac_ctx,
1643 			mac_hdr->sa,
1644 			addba_req->addba_param_set.tid,
1645 			session,
1646 			addba_req->addba_extn_element.present,
1647 			addba_req->addba_param_set.amsdu_supp,
1648 			mac_hdr->fc.wep, buff_size, mac_hdr->bssId);
1649 		if (qdf_status != QDF_STATUS_SUCCESS) {
1650 			pe_err("Failed to send addba response frame");
1651 			cdp_addba_resp_tx_completion(
1652 					soc, mac_hdr->sa, session->vdev_id,
1653 					addba_req->addba_param_set.tid,
1654 					WMI_MGMT_TX_COMP_TYPE_DISCARD);
1655 		}
1656 	} else {
1657 		pe_debug_rl("Failed to process addba request");
1658 	}
1659 
1660 error:
1661 	qdf_mem_free(addba_req);
1662 	return;
1663 }
1664 
1665 /**
1666  * lim_process_delba_req() - process DELBA Request
1667  * @mac_ctx: Pointer to Global MAC structure
1668  * @rx_pkt_info: A pointer to packet info structure
1669  * @session: PE session pointer
1670  *
1671  * This routine will be called to process ADDBA request action frame
1672  *
1673  * Return: None
1674  */
lim_process_delba_req(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,struct pe_session * session)1675 static void lim_process_delba_req(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
1676 				  struct pe_session *session)
1677 {
1678 	tpSirMacMgmtHdr mac_hdr;
1679 	uint8_t *body_ptr;
1680 	tDot11fdelba_req *delba_req;
1681 	uint32_t frame_len, status;
1682 	QDF_STATUS qdf_status;
1683 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
1684 
1685 	mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
1686 	body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
1687 	frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
1688 
1689 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
1690 			   body_ptr, frame_len);
1691 
1692 	delba_req = qdf_mem_malloc(sizeof(*delba_req));
1693 	if (!delba_req)
1694 		return;
1695 
1696 	/* Unpack DELBA request frame */
1697 	status = dot11f_unpack_delba_req(mac_ctx, body_ptr, frame_len,
1698 					 delba_req, false);
1699 
1700 	if (DOT11F_FAILED(status)) {
1701 		pe_err("Failed to unpack and parse (0x%08x, %d bytes)",
1702 			status, frame_len);
1703 		goto error;
1704 	} else if (DOT11F_WARNED(status)) {
1705 		pe_warn("warning: unpack addba Req(0x%08x, %d bytes)",
1706 			status, frame_len);
1707 	}
1708 
1709 	qdf_status = cdp_delba_process(soc, mac_hdr->sa, session->vdev_id,
1710 			delba_req->delba_param_set.tid, delba_req->Reason.code);
1711 
1712 	if (QDF_STATUS_SUCCESS != qdf_status)
1713 		pe_err_rl("Failed to process delba request");
1714 
1715 error:
1716 	qdf_mem_free(delba_req);
1717 	return;
1718 }
1719 
1720 /**
1721  * lim_process_action_frame() - to process action frames
1722  * @mac_ctx: Pointer to Global MAC structure
1723  * @rx_pkt_info: A pointer to packet info structure
1724  *
1725  * This function is called by limProcessMessageQueue() upon
1726  * Action frame reception.
1727  *
1728  * Return: none
1729  */
1730 
lim_process_action_frame(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,struct pe_session * session)1731 void lim_process_action_frame(struct mac_context *mac_ctx,
1732 		uint8_t *rx_pkt_info, struct pe_session *session)
1733 {
1734 	uint8_t *body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
1735 	tpSirMacActionFrameHdr action_hdr = (tpSirMacActionFrameHdr) body_ptr;
1736 	tpSirMacMgmtHdr mac_hdr_11w = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
1737 	tpSirMacMgmtHdr mac_hdr = NULL;
1738 	int8_t rssi;
1739 	uint32_t frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
1740 	tpSirMacVendorSpecificFrameHdr vendor_specific;
1741 	uint8_t dpp_oui[] = { 0x50, 0x6F, 0x9A, 0x1A };
1742 	tpSirMacVendorSpecificPublicActionFrameHdr pub_action;
1743 	enum wlan_t2lm_resp_frm_type status_code;
1744 	uint8_t token = 0;
1745 	struct wlan_objmgr_peer *peer = NULL;
1746 	QDF_STATUS status;
1747 
1748 	if (frame_len < sizeof(*action_hdr)) {
1749 		pe_debug("frame_len %d less than Action Frame Hdr size",
1750 			 frame_len);
1751 		return;
1752 	}
1753 
1754 	if (wlan_mgmt_is_rmf_mgmt_action_frame(action_hdr->category) &&
1755 	    lim_drop_unprotected_action_frame(mac_ctx, session,
1756 			mac_hdr_11w, action_hdr->category))
1757 		return;
1758 
1759 	switch (action_hdr->category) {
1760 	case ACTION_CATEGORY_QOS:
1761 		if ((session->limQosEnabled) ||
1762 		    (action_hdr->actionID == QOS_MAP_CONFIGURE)) {
1763 			switch (action_hdr->actionID) {
1764 			case QOS_ADD_TS_REQ:
1765 				__lim_process_add_ts_req(mac_ctx,
1766 						(uint8_t *) rx_pkt_info,
1767 						session);
1768 				break;
1769 
1770 			case QOS_ADD_TS_RSP:
1771 				__lim_process_add_ts_rsp(mac_ctx,
1772 						 (uint8_t *) rx_pkt_info,
1773 						 session);
1774 				break;
1775 
1776 			case QOS_DEL_TS_REQ:
1777 				__lim_process_del_ts_req(mac_ctx,
1778 						(uint8_t *) rx_pkt_info,
1779 						session);
1780 				break;
1781 
1782 			case QOS_MAP_CONFIGURE:
1783 				__lim_process_qos_map_configure_frame(mac_ctx,
1784 						(uint8_t *)rx_pkt_info,
1785 						session);
1786 				break;
1787 			default:
1788 				pe_warn("Qos action: %d not handled",
1789 					action_hdr->actionID);
1790 				break;
1791 			}
1792 			break;
1793 		}
1794 		break;
1795 
1796 	case ACTION_CATEGORY_SPECTRUM_MGMT:
1797 		switch (action_hdr->actionID) {
1798 #ifdef ANI_SUPPORT_11H
1799 		case ACTION_SPCT_MSR_REQ:
1800 			if (session->lim11hEnable)
1801 				__lim_process_measurement_request_frame(mac_ctx,
1802 							rx_pkt_info,
1803 							session);
1804 			break;
1805 		case ACTION_SPCT_TPC_REQ:
1806 			if ((LIM_IS_STA_ROLE(session) ||
1807 				LIM_IS_AP_ROLE(session)) &&
1808 				session->lim11hEnable)
1809 					__lim_process_tpc_request_frame(mac_ctx,
1810 						rx_pkt_info, session);
1811 			break;
1812 #endif
1813 		default:
1814 			pe_warn("Spectrum mgmt action id: %d not handled",
1815 				action_hdr->actionID);
1816 			break;
1817 		}
1818 		break;
1819 
1820 	case ACTION_CATEGORY_WMM:
1821 		if (!session->limWmeEnabled) {
1822 			pe_warn("WME mode disabled - dropping frame: %d",
1823 				action_hdr->actionID);
1824 			break;
1825 		}
1826 		switch (action_hdr->actionID) {
1827 		case QOS_ADD_TS_REQ:
1828 			__lim_process_add_ts_req(mac_ctx,
1829 				(uint8_t *) rx_pkt_info, session);
1830 			break;
1831 
1832 		case QOS_ADD_TS_RSP:
1833 			__lim_process_add_ts_rsp(mac_ctx,
1834 				(uint8_t *) rx_pkt_info, session);
1835 			break;
1836 
1837 		case QOS_DEL_TS_REQ:
1838 			__lim_process_del_ts_req(mac_ctx,
1839 				(uint8_t *) rx_pkt_info, session);
1840 			break;
1841 
1842 		case QOS_MAP_CONFIGURE:
1843 			__lim_process_qos_map_configure_frame(mac_ctx,
1844 				(uint8_t *)rx_pkt_info, session);
1845 			break;
1846 
1847 		default:
1848 			pe_warn("WME action: %d not handled",
1849 				action_hdr->actionID);
1850 			break;
1851 		}
1852 		break;
1853 
1854 	case ACTION_CATEGORY_HT:
1855 		/** Type of HT Action to be performed*/
1856 		switch (action_hdr->actionID) {
1857 		case HT_ACTION_SMPS:
1858 			if (LIM_IS_AP_ROLE(session))
1859 				__lim_process_sm_power_save_update(mac_ctx,
1860 						(uint8_t *)rx_pkt_info,
1861 						session);
1862 			break;
1863 		default:
1864 			pe_warn("Action ID: %d not handled in HT category",
1865 				action_hdr->actionID);
1866 			break;
1867 		}
1868 		break;
1869 
1870 	case ACTION_CATEGORY_WNM:
1871 		pe_debug("WNM Action category: %d action: %d",
1872 			action_hdr->category, action_hdr->actionID);
1873 		switch (action_hdr->actionID) {
1874 		case WNM_BSS_TM_QUERY:
1875 		case WNM_BSS_TM_REQUEST:
1876 		case WNM_BSS_TM_RESPONSE:
1877 			if (cfg_p2p_is_roam_config_disabled(mac_ctx->psoc) &&
1878 			    session && LIM_IS_STA_ROLE(session) &&
1879 			    (policy_mgr_mode_specific_connection_count(
1880 				mac_ctx->psoc, PM_P2P_CLIENT_MODE, NULL) ||
1881 			     policy_mgr_mode_specific_connection_count(
1882 				mac_ctx->psoc, PM_P2P_GO_MODE, NULL))) {
1883 				pe_debug("p2p session active drop BTM frame");
1884 				break;
1885 			}
1886 			fallthrough;
1887 		case WNM_NOTIF_REQUEST:
1888 		case WNM_NOTIF_RESPONSE:
1889 			rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info);
1890 			mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
1891 			/* Forward to the SME to HDD to wpa_supplicant */
1892 			lim_send_sme_mgmt_frame_ind(mac_ctx,
1893 					mac_hdr->fc.subType,
1894 					(uint8_t *) mac_hdr,
1895 					frame_len + sizeof(tSirMacMgmtHdr),
1896 					session->vdev_id,
1897 					WMA_GET_RX_FREQ(rx_pkt_info),
1898 					rssi, RXMGMT_FLAG_NONE);
1899 			break;
1900 		default:
1901 			pe_debug("Action ID: %d not handled in WNM category",
1902 				action_hdr->actionID);
1903 			break;
1904 		}
1905 		break;
1906 
1907 	case ACTION_CATEGORY_RRM:
1908 
1909 		if (mac_ctx->rrm.rrmPEContext.rrmEnable &&
1910 		    LIM_IS_AP_ROLE(session) &&
1911 		    action_hdr->actionID == RRM_RADIO_MEASURE_RPT) {
1912 			mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
1913 			wlan_son_deliver_rrm_rpt(session->vdev,
1914 				 mac_hdr->sa,
1915 				 body_ptr + sizeof(tSirMacActionFrameHdr),
1916 				 frame_len - sizeof(tSirMacActionFrameHdr));
1917 		}
1918 
1919 		/* Ignore RRM measurement request until DHCP is set */
1920 		if (mac_ctx->rrm.rrmPEContext.rrmEnable &&
1921 		    mac_ctx->roam.roamSession[session->smeSessionId].dhcp_done) {
1922 			switch (action_hdr->actionID) {
1923 			case RRM_RADIO_MEASURE_REQ:
1924 				__lim_process_radio_measure_request(mac_ctx,
1925 						(uint8_t *)rx_pkt_info,
1926 						session);
1927 				break;
1928 			case RRM_LINK_MEASUREMENT_REQ:
1929 				if (!lim_is_valid_frame(
1930 					&rrm_link_action_frm,
1931 					rx_pkt_info))
1932 					break;
1933 
1934 				if (__lim_process_link_measurement_req(
1935 						mac_ctx,
1936 						(uint8_t *)rx_pkt_info,
1937 						session) == QDF_STATUS_SUCCESS)
1938 					lim_update_last_processed_frame(
1939 							&rrm_link_action_frm,
1940 							rx_pkt_info);
1941 
1942 				break;
1943 			case RRM_NEIGHBOR_RPT:
1944 				__lim_process_neighbor_report(mac_ctx,
1945 						(uint8_t *)rx_pkt_info,
1946 						session);
1947 				break;
1948 			default:
1949 				pe_warn("Action ID: %d not handled in RRM",
1950 					action_hdr->actionID);
1951 				break;
1952 
1953 			}
1954 		} else if (LIM_IS_AP_ROLE(session)) {
1955 			switch (action_hdr->actionID) {
1956 			case RRM_NEIGHBOR_REQ:
1957 			case RRM_RADIO_MEASURE_RPT:
1958 				rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info);
1959 				mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
1960 				lim_send_sme_mgmt_frame_ind(mac_ctx,
1961 						mac_hdr->fc.subType,
1962 						(uint8_t *)mac_hdr,
1963 						frame_len + sizeof(tSirMacMgmtHdr),
1964 						session->smeSessionId,
1965 						WMA_GET_RX_FREQ(rx_pkt_info),
1966 						rssi, RXMGMT_FLAG_NONE);
1967 				break;
1968 			default:
1969 				pe_warn("Action ID: %d not handled in RRM",
1970 					action_hdr->actionID);
1971 				break;
1972 			}
1973 		} else {
1974 			/* Else we will just ignore the RRM messages. */
1975 			pe_debug("RRM frm ignored, it is disabled in cfg: %d or DHCP not completed: %d",
1976 			  mac_ctx->rrm.rrmPEContext.rrmEnable,
1977 			  mac_ctx->roam.roamSession[session->smeSessionId].dhcp_done);
1978 		}
1979 		break;
1980 
1981 	case ACTION_CATEGORY_VENDOR_SPECIFIC:
1982 	case ACTION_CATEGORY_VENDOR_SPECIFIC_PROTECTED:
1983 		vendor_specific = (tpSirMacVendorSpecificFrameHdr) action_hdr;
1984 		mac_hdr = NULL;
1985 
1986 		mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
1987 
1988 		if (frame_len < sizeof(*vendor_specific)) {
1989 			pe_debug("frame len %d less than Vendor Specific Hdr len",
1990 				 frame_len);
1991 			return;
1992 		}
1993 
1994 		/* Forward all vendor specific action frames. */
1995 		if (!qdf_mem_cmp(session->self_mac_addr,
1996 				 &mac_hdr->da[0], sizeof(tSirMacAddr))) {
1997 			pe_debug("Rcvd Vendor specific frame OUI: %x %x %x",
1998 				vendor_specific->Oui[0],
1999 				vendor_specific->Oui[1],
2000 				vendor_specific->Oui[2]);
2001 			/*
2002 			 * Forward to the SME to HDD to wpa_supplicant
2003 			 * type is ACTION
2004 			 */
2005 			lim_send_sme_mgmt_frame_ind(mac_ctx,
2006 				mac_hdr->fc.subType, (uint8_t *)mac_hdr,
2007 				frame_len + sizeof(tSirMacMgmtHdr),
2008 				session->vdev_id,
2009 				WMA_GET_RX_FREQ(rx_pkt_info),
2010 				WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info),
2011 				RXMGMT_FLAG_NONE);
2012 		} else {
2013 			pe_debug("Dropping the vendor specific action frame SelfSta address system role: %d",
2014 				 GET_LIM_SYSTEM_ROLE(session));
2015 		}
2016 	break;
2017 	case ACTION_CATEGORY_PUBLIC:
2018 		mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
2019 
2020 		switch (action_hdr->actionID) {
2021 		case PUB_ACTION_EXT_CHANNEL_SWITCH_ID:
2022 			lim_process_ext_channel_switch_action_frame(mac_ctx,
2023 							rx_pkt_info, session);
2024 			break;
2025 		case TDLS_DISCOVERY_RESPONSE:
2026 			/* do not forward the tdls discovery response frame,
2027 			 * it is handled by
2028 			 * tgt_mgmt_txrx_rx_frame_handler ->
2029 			 * tgt_tdls_mgmt_frame_rx_cb ->
2030 			 * tdls_process_rx_frame
2031 			 */
2032 			break;
2033 		case PUB_ACTION_VENDOR_SPECIFIC:
2034 			pub_action =
2035 				(tpSirMacVendorSpecificPublicActionFrameHdr)
2036 				action_hdr;
2037 			if (frame_len < sizeof(*pub_action)) {
2038 				pe_debug("Received vendor specific public action frame of invalid len %d",
2039 					 frame_len);
2040 				return;
2041 			}
2042 			/*
2043 			 * Check if it is a DPP public action frame and fall
2044 			 * thru, else drop the frame.
2045 			 */
2046 			if (qdf_mem_cmp(pub_action->Oui, dpp_oui, 4)) {
2047 				pe_debug("Unhandled public action frame (Vendor specific) OUI: %x %x %x %x",
2048 					pub_action->Oui[0], pub_action->Oui[1],
2049 					pub_action->Oui[2], pub_action->Oui[3]);
2050 				break;
2051 			}
2052 			/* send the frame to supplicant */
2053 			fallthrough;
2054 		case ACTION_CATEGORY_VENDOR_SPECIFIC:
2055 		case ACTION_CATEGORY_VENDOR_SPECIFIC_PROTECTED:
2056 		case PUB_ACTION_2040_BSS_COEXISTENCE:
2057 		case PUB_ACTION_GAS_INITIAL_REQUEST:
2058 			if (action_hdr->actionID ==
2059 				PUB_ACTION_GAS_INITIAL_REQUEST) {
2060 				wlan_son_anqp_frame(session->vdev,
2061 						    mac_hdr->fc.subType,
2062 						    (uint8_t *)mac_hdr,
2063 						    (uint16_t)(frame_len +
2064 						    sizeof(tSirMacMgmtHdr)),
2065 						    (void *)action_hdr,
2066 						    &mac_hdr->sa[0]);
2067 			}
2068 			fallthrough;
2069 		case PUB_ACTION_GAS_INITIAL_RESPONSE:
2070 		case PUB_ACTION_GAS_COMEBACK_REQUEST:
2071 		case PUB_ACTION_GAS_COMEBACK_RESPONSE:
2072 		default:
2073 			pe_debug("Public action frame: %d",
2074 				 action_hdr->actionID);
2075 			/*
2076 			 * Forward to the SME to HDD to wpa_supplicant
2077 			 * type is ACTION
2078 			 */
2079 			lim_send_sme_mgmt_frame_ind(mac_ctx,
2080 				mac_hdr->fc.subType, (uint8_t *)mac_hdr,
2081 				frame_len + sizeof(tSirMacMgmtHdr),
2082 				session->vdev_id,
2083 				WMA_GET_RX_FREQ(rx_pkt_info),
2084 				WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info),
2085 				RXMGMT_FLAG_NONE);
2086 			break;
2087 		}
2088 		break;
2089 
2090 	case ACTION_CATEGORY_SA_QUERY:
2091 		pe_debug("SA Query Action category: %d action: %d",
2092 			action_hdr->category, action_hdr->actionID);
2093 		switch (action_hdr->actionID) {
2094 		case SA_QUERY_REQUEST:
2095 			/**11w SA query request action frame received**/
2096 			/* Respond directly to the incoming request in LIM */
2097 			__lim_process_sa_query_request_action_frame(mac_ctx,
2098 						(uint8_t *)rx_pkt_info,
2099 						session);
2100 			break;
2101 		case SA_QUERY_RESPONSE:
2102 			/**11w SA query response action frame received**/
2103 			/* Handle based on the current SA Query state */
2104 			__lim_process_sa_query_response_action_frame(mac_ctx,
2105 						(uint8_t *)rx_pkt_info,
2106 						session);
2107 			break;
2108 		default:
2109 			break;
2110 		}
2111 		break;
2112 
2113 	case ACTION_CATEGORY_VHT:
2114 		if (!session->vhtCapability)
2115 			break;
2116 		switch (action_hdr->actionID) {
2117 		case VHT_ACTION_OPMODE_NOTIF:
2118 			__lim_process_operating_mode_action_frame(mac_ctx,
2119 					rx_pkt_info, session);
2120 			break;
2121 		case VHT_ACTION_GID_NOTIF:
2122 			/* Only if ini supports it */
2123 			if (session->enableVhtGid)
2124 				__lim_process_gid_management_action_frame(
2125 					mac_ctx, rx_pkt_info, session);
2126 			break;
2127 		default:
2128 			break;
2129 		}
2130 		break;
2131 	case ACTION_CATEGORY_RVS:
2132 	case ACTION_CATEGORY_FST: {
2133 		tpSirMacMgmtHdr     hdr;
2134 
2135 		hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
2136 
2137 		pe_debug("Received %s MGMT action frame",
2138 			 (action_hdr->category == ACTION_CATEGORY_FST) ?
2139 			"FST" : "RVS");
2140 
2141 		/* Forward to the SME to HDD */
2142 		lim_send_sme_mgmt_frame_ind(mac_ctx, hdr->fc.subType,
2143 					    (uint8_t *)hdr,
2144 					    frame_len + sizeof(tSirMacMgmtHdr),
2145 					    session->vdev_id,
2146 					    WMA_GET_RX_FREQ(rx_pkt_info),
2147 					    WMA_GET_RX_RSSI_NORMALIZED(
2148 					    rx_pkt_info), RXMGMT_FLAG_NONE);
2149 		break;
2150 	}
2151 	case ACTION_CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION:
2152 		pe_debug("Rcvd Protected Dual of Public Action: %d",
2153 			action_hdr->actionID);
2154 		switch (action_hdr->actionID) {
2155 		case PDPA_GAS_INIT_REQ:
2156 		case PDPA_GAS_INIT_RSP:
2157 		case PDPA_GAS_COMEBACK_REQ:
2158 		case PDPA_GAS_COMEBACK_RSP:
2159 			mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
2160 			rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info);
2161 			lim_send_sme_mgmt_frame_ind(mac_ctx,
2162 				mac_hdr->fc.subType, (uint8_t *) mac_hdr,
2163 				frame_len + sizeof(tSirMacMgmtHdr),
2164 				session->vdev_id,
2165 				WMA_GET_RX_FREQ(rx_pkt_info), rssi,
2166 				RXMGMT_FLAG_NONE);
2167 			break;
2168 		default:
2169 			pe_debug("Unhandled - Protected Dual Public Action");
2170 			break;
2171 		}
2172 		break;
2173 	case ACTION_CATEGORY_BACK:
2174 		pe_debug("Rcvd Block Ack for "QDF_MAC_ADDR_FMT"; action: %d",
2175 			  QDF_MAC_ADDR_REF(session->self_mac_addr),
2176 			  action_hdr->actionID);
2177 		switch (action_hdr->actionID) {
2178 		case ADDBA_REQUEST:
2179 			lim_process_addba_req(mac_ctx, rx_pkt_info, session);
2180 			break;
2181 		case DELBA:
2182 			lim_process_delba_req(mac_ctx, rx_pkt_info, session);
2183 			break;
2184 		default:
2185 			pe_err("Unhandle BA action frame");
2186 			break;
2187 		}
2188 		break;
2189 	case ACTION_CATEGORY_PROTECTED_EHT:
2190 		pe_debug("EHT T2LM/EPCS action category: %d action: %d",
2191 			 action_hdr->category, action_hdr->actionID);
2192 		mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
2193 		body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
2194 		frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
2195 		peer = wlan_objmgr_get_peer_by_mac(mac_ctx->psoc,
2196 						   mac_hdr->sa,
2197 						   WLAN_LEGACY_MAC_ID);
2198 		if (!peer) {
2199 			pe_err("Peer is null");
2200 			break;
2201 		}
2202 		switch (action_hdr->actionID) {
2203 		case EHT_T2LM_REQUEST:
2204 			status = wlan_t2lm_deliver_event(
2205 				session->vdev, peer,
2206 				WLAN_T2LM_EV_ACTION_FRAME_RX_REQ,
2207 				(void *)body_ptr, frame_len,
2208 				&token);
2209 			if (QDF_IS_STATUS_SUCCESS(status))
2210 				status_code = WLAN_T2LM_RESP_TYPE_SUCCESS;
2211 			else
2212 				status_code =
2213 				WLAN_T2LM_RESP_TYPE_DENIED_TID_TO_LINK_MAPPING;
2214 
2215 			if (status == QDF_STATUS_E_NOSUPPORT)
2216 				pe_err("STA does not support T2LM drop frame");
2217 			else if (lim_send_t2lm_action_rsp_frame(
2218 					mac_ctx, mac_hdr->sa, session, token,
2219 					status_code) != QDF_STATUS_SUCCESS) {
2220 				pe_err("T2LM action response frame not sent");
2221 			} else {
2222 				wlan_send_peer_level_tid_to_link_mapping(
2223 								session->vdev,
2224 								peer);
2225 				wlan_connectivity_t2lm_status_event(
2226 								session->vdev);
2227 			}
2228 			break;
2229 		case EHT_T2LM_RESPONSE:
2230 			wlan_t2lm_deliver_event(
2231 					session->vdev, peer,
2232 					WLAN_T2LM_EV_ACTION_FRAME_RX_RESP,
2233 					(void *)body_ptr, frame_len, &token);
2234 			break;
2235 		case EHT_T2LM_TEARDOWN:
2236 			wlan_t2lm_deliver_event(
2237 					session->vdev, peer,
2238 					WLAN_T2LM_EV_ACTION_FRAME_RX_TEARDOWN,
2239 					(void *)body_ptr, frame_len, NULL);
2240 			break;
2241 		case EHT_EPCS_REQUEST:
2242 			wlan_epcs_deliver_event(
2243 					session->vdev, peer,
2244 					WLAN_EPCS_EV_ACTION_FRAME_RX_REQ,
2245 					(void *)body_ptr, frame_len);
2246 			break;
2247 		case EHT_EPCS_RESPONSE:
2248 			wlan_epcs_deliver_event(
2249 					session->vdev, peer,
2250 					WLAN_EPCS_EV_ACTION_FRAME_RX_RESP,
2251 					(void *)body_ptr, frame_len);
2252 			break;
2253 		case EHT_EPCS_TEARDOWN:
2254 			wlan_epcs_deliver_event(
2255 					session->vdev, peer,
2256 					WLAN_EPCS_EV_ACTION_FRAME_RX_TEARDOWN,
2257 					(void *)body_ptr, frame_len);
2258 			break;
2259 		default:
2260 			pe_err("Unhandled T2LM/EPCS action frame");
2261 			break;
2262 		}
2263 		break;
2264 	default:
2265 		pe_warn_rl("Action category: %d not handled",
2266 			action_hdr->category);
2267 		break;
2268 	}
2269 
2270 	if (peer)
2271 		wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
2272 }
2273 
2274 /**
2275  * lim_process_action_frame_no_session
2276  *
2277  ***FUNCTION:
2278  * This function is called by limProcessMessageQueue() upon
2279  * Action frame reception and no session.
2280  * Currently only public action frames can be received from
2281  * a non-associated station.
2282  *
2283  ***LOGIC:
2284  *
2285  ***ASSUMPTIONS:
2286  *
2287  ***NOTE:
2288  *
2289  * @param  mac - Pointer to Global MAC structure
2290  * @param  *pBd - A pointer to Buffer descriptor + associated PDUs
2291  * @return None
2292  */
lim_process_action_frame_no_session(struct mac_context * mac,uint8_t * pBd)2293 void lim_process_action_frame_no_session(struct mac_context *mac, uint8_t *pBd)
2294 {
2295 	tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(pBd);
2296 	uint32_t frame_len = WMA_GET_RX_PAYLOAD_LEN(pBd);
2297 	uint8_t *pBody = WMA_GET_RX_MPDU_DATA(pBd);
2298 	tpSirMacActionFrameHdr action_hdr = (tpSirMacActionFrameHdr) pBody;
2299 	tpSirMacVendorSpecificPublicActionFrameHdr vendor_specific;
2300 
2301 	pe_debug("Received an action frame category: %d action_id: %d",
2302 		 action_hdr->category, (action_hdr->category ==
2303 		 ACTION_CATEGORY_PUBLIC || action_hdr->category ==
2304 		 ACTION_CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION) ?
2305 		 action_hdr->actionID : 255);
2306 
2307 	if (frame_len < sizeof(*action_hdr)) {
2308 		pe_debug("frame_len %d less than action frame header len",
2309 			 frame_len);
2310 		return;
2311 	}
2312 
2313 	switch (action_hdr->category) {
2314 	case ACTION_CATEGORY_PUBLIC:
2315 	case ACTION_CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION:
2316 		if (action_hdr->actionID == PUB_ACTION_VENDOR_SPECIFIC) {
2317 			vendor_specific =
2318 				(tpSirMacVendorSpecificPublicActionFrameHdr)
2319 				action_hdr;
2320 
2321 			if (frame_len < sizeof(*vendor_specific)) {
2322 				pe_debug("Received vendor specific public action frame of invalid len %d",
2323 					 frame_len);
2324 				return;
2325 			}
2326 
2327 			pe_debug("public action frame (Vendor specific) OUI: %x %x %x %x",
2328 				 vendor_specific->Oui[0],
2329 				 vendor_specific->Oui[1],
2330 				 vendor_specific->Oui[2],
2331 				 vendor_specific->Oui[3]);
2332 
2333 			/* Drop P2P frames as they are handled by P2P module */
2334 			if (wlan_p2p_is_action_frame_of_p2p_type(
2335 						(uint8_t *)mac_hdr,
2336 						WMA_GET_RX_MPDU_LEN(pBd))) {
2337 				pe_debug("Drop P2P public action frame as already handled in p2p module");
2338 				return;
2339 			}
2340 		}
2341 
2342 		/*
2343 		 * Forward all public action frame with no session to
2344 		 * wpa_supplicant
2345 		 */
2346 		lim_send_sme_mgmt_frame_ind(mac, mac_hdr->fc.subType,
2347 					    (uint8_t *)mac_hdr,
2348 					    frame_len + sizeof(tSirMacMgmtHdr),
2349 					    0, WMA_GET_RX_FREQ(pBd),
2350 					    WMA_GET_RX_RSSI_NORMALIZED(pBd),
2351 					    RXMGMT_FLAG_NONE);
2352 
2353 		break;
2354 	default:
2355 		pe_info_rl("Unhandled action frame without session: %x",
2356 			   action_hdr->category);
2357 		break;
2358 	}
2359 }
2360