xref: /wlan-dirver/qcacld-3.0/core/mac/src/pe/lim/lim_send_management_frames.c (revision e41e8755738c61945e20243db946b67646275f7c)
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 /**
21  * DOC: lim_send_management_frames.c
22  *
23  * WLAN Host Device Driver file for preparing and sending 802.11 Management
24  * frames
25  */
26 
27 #include "sir_api.h"
28 #include "ani_global.h"
29 #include "sir_mac_prot_def.h"
30 #include "utils_api.h"
31 #include "lim_types.h"
32 #include "lim_utils.h"
33 #include "lim_security_utils.h"
34 #include "lim_prop_exts_utils.h"
35 #include "dot11f.h"
36 #include "sch_api.h"
37 #include "lim_send_messages.h"
38 #include "lim_assoc_utils.h"
39 #include "lim_ft.h"
40 #include "wni_cfg.h"
41 
42 #include "lim_ft_defs.h"
43 #include "lim_session.h"
44 #include "qdf_types.h"
45 #include "qdf_trace.h"
46 #include "cds_utils.h"
47 #include "sme_trace.h"
48 #include "rrm_api.h"
49 #include "qdf_crypto.h"
50 #include "parser_api.h"
51 
52 #include "wma_types.h"
53 #include <cdp_txrx_cmn.h>
54 #include <cdp_txrx_peer_ops.h>
55 #include "lim_process_fils.h"
56 #include "wlan_utility.h"
57 #include <wlan_mlme_api.h>
58 #include <wlan_mlme_main.h>
59 #include "wlan_crypto_global_api.h"
60 #include "wlan_connectivity_logging.h"
61 #include "lim_mlo.h"
62 #include "wlan_mlo_mgr_sta.h"
63 #include "wlan_t2lm_api.h"
64 #include "wlan_connectivity_logging.h"
65 
66 /**
67  *
68  * \brief This function is called to add the sequence number to the
69  * management frames
70  *
71  * \param  mac Pointer to Global MAC structure
72  *
73  * \param  pMacHdr Pointer to MAC management header
74  *
75  * The pMacHdr argument points to the MAC management header. The
76  * sequence number stored in the mac structure will be incremented
77  * and updated to the MAC management header. The start sequence
78  * number is WLAN_HOST_SEQ_NUM_MIN and the end value is
79  * WLAN_HOST_SEQ_NUM_MAX. After reaching the MAX value, the sequence
80  * number will roll over.
81  *
82  */
83 static void lim_add_mgmt_seq_num(struct mac_context *mac, tpSirMacMgmtHdr pMacHdr)
84 {
85 	if (mac->mgmtSeqNum >= WLAN_HOST_SEQ_NUM_MAX) {
86 		mac->mgmtSeqNum = WLAN_HOST_SEQ_NUM_MIN - 1;
87 	}
88 
89 	mac->mgmtSeqNum++;
90 
91 	pMacHdr->seqControl.seqNumLo = (mac->mgmtSeqNum & LOW_SEQ_NUM_MASK);
92 	pMacHdr->seqControl.seqNumHi =
93 		((mac->mgmtSeqNum & HIGH_SEQ_NUM_MASK) >> HIGH_SEQ_NUM_OFFSET);
94 	pMacHdr->seqControl.fragNum = 0;
95 }
96 
97 /**
98  * lim_populate_mac_header() - Fill in 802.11 header of frame
99  *
100  * @mac_ctx: Pointer to Global MAC structure
101  * @buf: Pointer to the frame buffer that needs to be populate
102  * @type: 802.11 Type of the frame
103  * @sub_type: 802.11 Subtype of the frame
104  * @peer_addr: dst address
105  * @self_mac_addr: local mac address
106  *
107  * This function is called by various LIM modules to prepare the
108  * 802.11 frame MAC header
109  *
110  * The buf argument points to the beginning of the frame buffer to
111  * which - a) The 802.11 MAC header is set b) Following this MAC header
112  * will be the MGMT frame payload The payload itself is populated by the
113  * caller API
114  *
115  * Return: None
116  */
117 
118 void lim_populate_mac_header(struct mac_context *mac_ctx, uint8_t *buf,
119 		uint8_t type, uint8_t sub_type, tSirMacAddr peer_addr,
120 		tSirMacAddr self_mac_addr)
121 {
122 	tpSirMacMgmtHdr mac_hdr;
123 
124 	/* Prepare MAC management header */
125 	mac_hdr = (tpSirMacMgmtHdr) (buf);
126 
127 	/* Prepare FC */
128 	mac_hdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION;
129 	mac_hdr->fc.type = type;
130 	mac_hdr->fc.subType = sub_type;
131 
132 	/* Prepare Address 1 */
133 	qdf_mem_copy((uint8_t *) mac_hdr->da,
134 		     (uint8_t *) peer_addr, sizeof(tSirMacAddr));
135 
136 	/* Prepare Address 2 */
137 	sir_copy_mac_addr(mac_hdr->sa, self_mac_addr);
138 
139 	/* Prepare Address 3 */
140 	qdf_mem_copy((uint8_t *) mac_hdr->bssId,
141 		     (uint8_t *) peer_addr, sizeof(tSirMacAddr));
142 
143 	/* Prepare sequence number */
144 	lim_add_mgmt_seq_num(mac_ctx, mac_hdr);
145 	pe_debug("seqNumLo=%d, seqNumHi=%d, mgmtSeqNum=%d, fragNum=%d",
146 		 mac_hdr->seqControl.seqNumLo, mac_hdr->seqControl.seqNumHi,
147 		 mac_ctx->mgmtSeqNum, mac_hdr->seqControl.fragNum);
148 }
149 
150 /**
151  * lim_send_probe_req_mgmt_frame() - send probe request management frame
152  * @mac_ctx: Pointer to Global MAC structure
153  * @ssid: SSID to be sent in Probe Request frame
154  * @bssid: BSSID to be sent in Probe Request frame
155  * @chan_freq: Channel frequency on which the Probe Request is going out
156  * @self_macaddr: self MAC address
157  * @dot11mode: self dotllmode
158  * @additional_ielen: if non-zero, include additional_ie in the Probe Request
159  *                   frame
160  * @additional_ie: if additional_ielen is non zero, include this field in the
161  *                Probe Request frame
162  *
163  * This function is called by various LIM modules to send Probe Request frame
164  * during active scan/learn phase.
165  * Probe request is sent out in the following scenarios:
166  * --heartbeat failure:  session needed
167  * --join req:           session needed
168  * --foreground scan:    no session
169  * --background scan:    no session
170  * --sch_beacon_processing:  to get EDCA parameters:  session needed
171  *
172  * Return: QDF_STATUS (QDF_STATUS_SUCCESS on success and error codes otherwise)
173  */
174 QDF_STATUS
175 lim_send_probe_req_mgmt_frame(struct mac_context *mac_ctx,
176 			      tSirMacSSid *ssid,
177 			      tSirMacAddr bssid,
178 			      qdf_freq_t chan_freq,
179 			      tSirMacAddr self_macaddr,
180 			      uint32_t dot11mode,
181 			      uint16_t *additional_ielen,
182 			      uint8_t *additional_ie)
183 {
184 	tDot11fProbeRequest *pr;
185 	uint32_t status, bytes, payload;
186 	uint8_t *frame;
187 	void *packet;
188 	QDF_STATUS qdf_status;
189 	struct pe_session *pesession;
190 	uint8_t sessionid;
191 	const uint8_t *p2pie = NULL;
192 	uint8_t txflag = 0;
193 	uint8_t vdev_id = 0;
194 	bool is_vht_enabled = false;
195 	uint8_t txPower;
196 	uint16_t addn_ielen = 0;
197 	bool extracted_ext_cap_flag = false;
198 	tDot11fIEExtCap extracted_ext_cap;
199 	QDF_STATUS sir_status;
200 	const uint8_t *qcn_ie = NULL;
201 	uint8_t channel;
202 	uint8_t *eht_cap_ie = NULL, eht_cap_ie_len = 0;
203 	bool is_band_2g;
204 	uint16_t ie_buf_size;
205 	uint16_t mlo_ie_len = 0;
206 
207 	if (additional_ielen)
208 		addn_ielen = *additional_ielen;
209 
210 	channel = wlan_reg_freq_to_chan(mac_ctx->pdev, chan_freq);
211 	/*
212 	 * The probe req should not send 11ac capabilities if band is
213 	 * 2.4GHz, unless gEnableVhtFor24GHzBand is enabled in INI. So
214 	 * if gEnableVhtFor24GHzBand is false and dot11mode is 11ac
215 	 * set it to 11n.
216 	 */
217 	if (wlan_reg_is_24ghz_ch_freq(chan_freq) &&
218 	    !mac_ctx->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band &&
219 	    (MLME_DOT11_MODE_11AC == dot11mode ||
220 	     MLME_DOT11_MODE_11AC_ONLY == dot11mode))
221 		dot11mode = MLME_DOT11_MODE_11N;
222 	/*
223 	 * session context may or may not be present, when probe request needs
224 	 * to be sent out. Following cases exist:
225 	 * --heartbeat failure:  session needed
226 	 * --join req:           session needed
227 	 * --foreground scan:    no session
228 	 * --background scan:    no session
229 	 * --sch_beacon_processing:  to get EDCA parameters:  session needed
230 	 * If session context does not exist, some IEs will be populated from
231 	 * CFGs, e.g. Supported and Extended rate set IEs
232 	 */
233 	pesession = pe_find_session_by_bssid(mac_ctx, bssid, &sessionid);
234 
235 	if (pesession)
236 		vdev_id = pesession->vdev_id;
237 
238 	pr = qdf_mem_malloc(sizeof(*pr));
239 	if (!pr) {
240 		pe_err("memory alloc failed for probe request");
241 		return QDF_STATUS_E_NOMEM;
242 	}
243 
244 	/* The scheme here is to fill out a 'tDot11fProbeRequest' structure */
245 	/* and then hand it off to 'dot11f_pack_probe_request' (for */
246 	/* serialization). */
247 
248 	/* & delegating to assorted helpers: */
249 	populate_dot11f_ssid(mac_ctx, ssid, &pr->SSID);
250 
251 	if (addn_ielen && additional_ie)
252 		p2pie = limGetP2pIEPtr(mac_ctx, additional_ie, addn_ielen);
253 
254 	/*
255 	 * Don't include 11b rate if it is a P2P search or probe request is
256 	 * sent by P2P Client
257 	 */
258 	if ((MLME_DOT11_MODE_11B != dot11mode) && (p2pie) &&
259 	    ((pesession) && (QDF_P2P_CLIENT_MODE == pesession->opmode))) {
260 		/*
261 		 * In the below API pass channel number > 14, do that it fills
262 		 * only 11a rates in supported rates
263 		 */
264 		populate_dot11f_supp_rates(mac_ctx, 15, &pr->SuppRates,
265 					   pesession);
266 	} else {
267 		populate_dot11f_supp_rates(mac_ctx, channel,
268 					   &pr->SuppRates, pesession);
269 
270 		if (MLME_DOT11_MODE_11B != dot11mode) {
271 			populate_dot11f_ext_supp_rates1(mac_ctx, channel,
272 							&pr->ExtSuppRates);
273 		}
274 	}
275 
276 	/*
277 	 * Table 7-14 in IEEE Std. 802.11k-2008 says
278 	 * DS params "can" be present in RRM is disabled and "is" present if
279 	 * RRM is enabled. It should be ok even if we add it into probe req when
280 	 * RRM is not enabled.
281 	 */
282 	populate_dot11f_ds_params(mac_ctx, &pr->DSParams,
283 				  chan_freq);
284 	/* Call RRM module to get the tx power for management used. */
285 	txPower = (uint8_t) rrm_get_mgmt_tx_power(mac_ctx, pesession);
286 	populate_dot11f_wfatpc(mac_ctx, &pr->WFATPC, txPower, 0);
287 
288 	if (pesession) {
289 		/* Include HT Capability IE */
290 		if (pesession->htCapability &&
291 		    !(WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_freq)))
292 			populate_dot11f_ht_caps(mac_ctx, pesession,
293 						&pr->HTCaps);
294 	} else {                /* !pesession */
295 		if (IS_DOT11_MODE_HT(dot11mode) &&
296 		    !(WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_freq)))
297 			populate_dot11f_ht_caps(mac_ctx, NULL, &pr->HTCaps);
298 	}
299 
300 	/*
301 	 * Set channelbonding information as "disabled" when tuned to a
302 	 * 2.4 GHz channel
303 	 */
304 	if (wlan_reg_is_24ghz_ch_freq(chan_freq)) {
305 		if (mac_ctx->roam.configParam.channelBondingMode24GHz
306 		    == PHY_SINGLE_CHANNEL_CENTERED) {
307 			pr->HTCaps.supportedChannelWidthSet =
308 				eHT_CHANNEL_WIDTH_20MHZ;
309 			pr->HTCaps.shortGI40MHz = 0;
310 		} else {
311 			pr->HTCaps.supportedChannelWidthSet =
312 				eHT_CHANNEL_WIDTH_40MHZ;
313 		}
314 	}
315 	if (pesession) {
316 		/* Include VHT Capability IE */
317 		if (pesession->vhtCapability &&
318 		    !(WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_freq))) {
319 			populate_dot11f_vht_caps(mac_ctx, pesession,
320 						 &pr->VHTCaps);
321 			is_vht_enabled = true;
322 		}
323 	} else {
324 		if (IS_DOT11_MODE_VHT(dot11mode) &&
325 		    !(WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_freq))) {
326 			populate_dot11f_vht_caps(mac_ctx, pesession,
327 						 &pr->VHTCaps);
328 			is_vht_enabled = true;
329 		}
330 	}
331 	if (pesession)
332 		populate_dot11f_ext_cap(mac_ctx, is_vht_enabled, &pr->ExtCap,
333 					pesession);
334 
335 	if (IS_DOT11_MODE_HE(dot11mode) && pesession)
336 		lim_update_session_he_capable(mac_ctx, pesession);
337 
338 	populate_dot11f_he_caps(mac_ctx, pesession, &pr->he_cap);
339 	populate_dot11f_he_6ghz_cap(mac_ctx, pesession,
340 				    &pr->he_6ghz_band_cap);
341 
342 	if (IS_DOT11_MODE_EHT(dot11mode) && pesession &&
343 			pesession->lim_join_req) {
344 		lim_update_session_eht_capable(mac_ctx, pesession);
345 		mlo_ie_len = lim_send_probe_req_frame_mlo(mac_ctx, pesession);
346 	}
347 
348 	populate_dot11f_eht_caps(mac_ctx, pesession, &pr->eht_cap);
349 
350 	if (addn_ielen && additional_ie) {
351 		qdf_mem_zero((uint8_t *)&extracted_ext_cap,
352 			sizeof(tDot11fIEExtCap));
353 		sir_status = lim_strip_extcap_update_struct(mac_ctx,
354 					additional_ie,
355 					&addn_ielen,
356 					&extracted_ext_cap);
357 		if (QDF_STATUS_SUCCESS != sir_status) {
358 			pe_debug("Unable to Stripoff ExtCap IE from Probe Req");
359 		} else {
360 			struct s_ext_cap *p_ext_cap =
361 				(struct s_ext_cap *)
362 					extracted_ext_cap.bytes;
363 			if (p_ext_cap->interworking_service)
364 				p_ext_cap->qos_map = 1;
365 			extracted_ext_cap.num_bytes =
366 				lim_compute_ext_cap_ie_length
367 					(&extracted_ext_cap);
368 			extracted_ext_cap_flag =
369 				(extracted_ext_cap.num_bytes > 0);
370 			if (additional_ielen)
371 				*additional_ielen = addn_ielen;
372 		}
373 		qcn_ie = wlan_get_vendor_ie_ptr_from_oui(SIR_MAC_QCN_OUI_TYPE,
374 				SIR_MAC_QCN_OUI_TYPE_SIZE,
375 				additional_ie, addn_ielen);
376 	}
377 
378 	/* Add qcn_ie only if qcn ie is not present in additional_ie */
379 	if (pesession) {
380 		if (!qcn_ie)
381 			populate_dot11f_qcn_ie(mac_ctx, pesession,
382 					       &pr->qcn_ie,
383 					       QCN_IE_ATTR_ID_ALL);
384 		else
385 			populate_dot11f_qcn_ie(mac_ctx, pesession,
386 					       &pr->qcn_ie,
387 					       QCN_IE_ATTR_ID_VHT_MCS11);
388 	}
389 
390 	/*
391 	 * Extcap IE now support variable length, merge Extcap IE from addn_ie
392 	 * may change the frame size. Therefore, MUST merge ExtCap IE before
393 	 * dot11f get packed payload size.
394 	 */
395 	if (extracted_ext_cap_flag)
396 		lim_merge_extcap_struct(&pr->ExtCap, &extracted_ext_cap, true);
397 
398 
399 	/* That's it-- now we pack it.  First, how much space are we going to */
400 	status = dot11f_get_packed_probe_request_size(mac_ctx, pr, &payload);
401 	if (DOT11F_FAILED(status)) {
402 		pe_err("Failed to calculate the packed size for a Probe Request (0x%08x)",
403 			status);
404 		/* We'll fall back on the worst case scenario: */
405 		payload = sizeof(tDot11fProbeRequest);
406 	} else if (DOT11F_WARNED(status)) {
407 		pe_warn("There were warnings while calculating the packed size for a Probe Request (0x%08x)",
408 			status);
409 	}
410 
411 	bytes = payload + sizeof(tSirMacMgmtHdr) + addn_ielen + mlo_ie_len;
412 
413 	/* Ok-- try to allocate some memory: */
414 	qdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame,
415 				      (void **)&packet);
416 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
417 		pe_err("Failed to allocate %d bytes for a Probe Request", bytes);
418 		qdf_mem_free(pr);
419 		return QDF_STATUS_E_NOMEM;
420 	}
421 	/* Paranoia: */
422 	qdf_mem_zero(frame, bytes);
423 
424 	/* Next, we fill out the buffer descriptor: */
425 	lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME,
426 		SIR_MAC_MGMT_PROBE_REQ, bssid, self_macaddr);
427 
428 	/* That done, pack the Probe Request: */
429 	status = dot11f_pack_probe_request(mac_ctx, pr, frame +
430 					    sizeof(tSirMacMgmtHdr),
431 					    payload, &payload);
432 	if (DOT11F_FAILED(status)) {
433 		pe_err("Failed to pack a Probe Request (0x%08x)", status);
434 		cds_packet_free((void *)packet);
435 		return QDF_STATUS_E_FAILURE;    /* allocated! */
436 	} else if (DOT11F_WARNED(status)) {
437 		pe_warn("There were warnings while packing a Probe Request (0x%08x)", status);
438 	}
439 
440 	/* Strip EHT capabilities IE */
441 	if (lim_is_session_eht_capable(pesession)) {
442 		ie_buf_size = payload;
443 
444 		eht_cap_ie = qdf_mem_malloc(WLAN_MAX_IE_LEN + 2);
445 		if (!eht_cap_ie) {
446 			pe_err("malloc failed for eht_cap_ie");
447 			goto skip_eht_ie_update;
448 		}
449 
450 		qdf_status = lim_strip_eht_cap_ie(mac_ctx, frame +
451 						  sizeof(tSirMacMgmtHdr),
452 						  &ie_buf_size, eht_cap_ie);
453 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
454 			pe_err("Failed to strip EHT cap IE");
455 			qdf_mem_free(eht_cap_ie);
456 			goto skip_eht_ie_update;
457 		}
458 
459 		is_band_2g =
460 			WLAN_REG_IS_24GHZ_CH_FREQ(pesession->curr_op_freq);
461 
462 		lim_ieee80211_pack_ehtcap(eht_cap_ie, pr->eht_cap, pr->he_cap,
463 					  is_band_2g);
464 		eht_cap_ie_len = eht_cap_ie[1] + 2;
465 
466 		/* Copy the EHT IE to the end of the frame */
467 		qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) +
468 			     ie_buf_size,
469 			     eht_cap_ie, eht_cap_ie_len);
470 		qdf_mem_free(eht_cap_ie);
471 		payload = ie_buf_size +  eht_cap_ie_len;
472 	}
473 skip_eht_ie_update:
474 	qdf_mem_free(pr);
475 
476 	/* Append any AddIE if present. */
477 	if (addn_ielen) {
478 		qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
479 			     additional_ie, addn_ielen);
480 		payload += addn_ielen;
481 	}
482 
483 	if (mlo_ie_len) {
484 		qdf_status = lim_fill_complete_mlo_ie(pesession, mlo_ie_len,
485 				      frame + sizeof(tSirMacMgmtHdr) + payload);
486 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
487 			pe_debug("assemble ml ie error, status %d", qdf_status);
488 			mlo_ie_len = 0;
489 		}
490 
491 		payload += mlo_ie_len;
492 	}
493 
494 	pe_nofl_debug("Probe req TX: vdev %d seq num %d to " QDF_MAC_ADDR_FMT " len %d",
495 		      vdev_id, mac_ctx->mgmtSeqNum,
496 		      QDF_MAC_ADDR_REF(bssid),
497 		      (int)sizeof(tSirMacMgmtHdr) + payload);
498 	qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, frame,
499 			   sizeof(tSirMacMgmtHdr) + payload);
500 
501 	/* If this probe request is sent during P2P Search State, then we need
502 	 * to send it at OFDM rate.
503 	 */
504 	if ((REG_BAND_5G == lim_get_rf_band(chan_freq)) ||
505 		/*
506 		 * For unicast probe req mgmt from Join function we don't set
507 		 * above variables. So we need to add one more check whether it
508 		 * is opmode is P2P_CLIENT or not
509 		 */
510 	    ((pesession) && (QDF_P2P_CLIENT_MODE == pesession->opmode)))
511 		txflag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
512 
513 	qdf_status =
514 		wma_tx_frame(mac_ctx, packet,
515 			   (uint16_t) sizeof(tSirMacMgmtHdr) + payload,
516 			   TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
517 			   lim_tx_complete, frame, txflag, vdev_id,
518 			   0, RATEID_DEFAULT, 0);
519 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
520 		pe_err("could not send Probe Request frame!");
521 		/* Pkt will be freed up by the callback */
522 		return QDF_STATUS_E_FAILURE;
523 	}
524 
525 	return QDF_STATUS_SUCCESS;
526 } /* End lim_send_probe_req_mgmt_frame. */
527 
528 static QDF_STATUS lim_get_addn_ie_for_probe_resp(struct mac_context *mac,
529 					     uint8_t *addIE, uint16_t *addnIELen,
530 					     uint8_t probeReqP2pIe)
531 {
532 	/* If Probe request doesn't have P2P IE, then take out P2P IE
533 	   from additional IE */
534 	if (!probeReqP2pIe) {
535 		uint8_t *tempbuf = NULL;
536 		uint16_t tempLen = 0;
537 		int left = *addnIELen;
538 		uint8_t *ptr = addIE;
539 		uint8_t elem_id, elem_len;
540 
541 		if (!addIE) {
542 			pe_err("NULL addIE pointer");
543 			return QDF_STATUS_E_FAILURE;
544 		}
545 
546 		tempbuf = qdf_mem_malloc(left);
547 		if (!tempbuf)
548 			return QDF_STATUS_E_NOMEM;
549 
550 		while (left >= 2) {
551 			elem_id = ptr[0];
552 			elem_len = ptr[1];
553 			left -= 2;
554 			if (elem_len > left) {
555 				pe_err("Invalid IEs eid: %d elem_len: %d left: %d",
556 					elem_id, elem_len, left);
557 				qdf_mem_free(tempbuf);
558 				return QDF_STATUS_E_FAILURE;
559 			}
560 			if (!((WLAN_ELEMID_VENDOR == elem_id) &&
561 			      (memcmp
562 				       (&ptr[2], SIR_MAC_P2P_OUI,
563 				       SIR_MAC_P2P_OUI_SIZE) == 0))) {
564 				qdf_mem_copy(tempbuf + tempLen, &ptr[0],
565 					     elem_len + 2);
566 				tempLen += (elem_len + 2);
567 			}
568 			left -= elem_len;
569 			ptr += (elem_len + 2);
570 		}
571 		qdf_mem_copy(addIE, tempbuf, tempLen);
572 		*addnIELen = tempLen;
573 		qdf_mem_free(tempbuf);
574 	}
575 	return QDF_STATUS_SUCCESS;
576 }
577 
578 /**
579  * lim_add_additional_ie() - Add additional IE to management frame
580  * @frame:          pointer to frame
581  * @frame_offset:   current offset of frame
582  * @add_ie:         pointer to additional ie
583  * @add_ie_len:     length of additional ie
584  * @p2p_ie:         pointer to p2p ie
585  * @noa_ie:         pointer to noa ie, this is separate p2p ie
586  * @noa_ie_len:     length of noa ie
587  * @noa_stream:     pointer to noa stream, this is noa attribute only
588  * @noa_stream_len: length of noa stream
589  *
590  * This function adds additional IE to management frame.
591  *
592  * Return: None
593  */
594 static void lim_add_additional_ie(uint8_t *frame, uint32_t frame_offset,
595 				  uint8_t *add_ie, uint32_t add_ie_len,
596 				  uint8_t *p2p_ie, uint8_t *noa_ie,
597 				  uint32_t noa_ie_len, uint8_t *noa_stream,
598 				  uint32_t noa_stream_len) {
599 	uint16_t p2p_ie_offset;
600 
601 	if (!add_ie_len || !add_ie) {
602 		pe_debug("no valid additional ie");
603 		return;
604 	}
605 
606 	if (!noa_stream_len) {
607 		qdf_mem_copy(frame + frame_offset, &add_ie[0], add_ie_len);
608 		return;
609 	}
610 
611 	if (noa_ie_len > (SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN)) {
612 		pe_err("Not able to insert NoA, len=%d", noa_ie_len);
613 		return;
614 	} else if (noa_ie_len > 0) {
615 		pe_debug("new p2p ie for noa attr");
616 		qdf_mem_copy(frame + frame_offset, &add_ie[0], add_ie_len);
617 		frame_offset += add_ie_len;
618 		qdf_mem_copy(frame + frame_offset, &noa_ie[0], noa_ie_len);
619 	} else {
620 		if (!p2p_ie || (p2p_ie < add_ie) ||
621 		    (p2p_ie > (add_ie + add_ie_len))) {
622 			pe_err("invalid p2p ie");
623 			return;
624 		}
625 		p2p_ie_offset = p2p_ie - add_ie + p2p_ie[1] + 2;
626 		if (p2p_ie_offset > add_ie_len) {
627 			pe_err("Invalid p2p ie");
628 			return;
629 		}
630 		pe_debug("insert noa attr to existed p2p ie");
631 		p2p_ie[1] = p2p_ie[1] + noa_stream_len;
632 		qdf_mem_copy(frame + frame_offset, &add_ie[0], p2p_ie_offset);
633 		frame_offset += p2p_ie_offset;
634 		qdf_mem_copy(frame + frame_offset, &noa_stream[0],
635 			     noa_stream_len);
636 		if (p2p_ie_offset < add_ie_len) {
637 			frame_offset += noa_stream_len;
638 			qdf_mem_copy(frame + frame_offset,
639 				     &add_ie[p2p_ie_offset],
640 				     add_ie_len - p2p_ie_offset);
641 		}
642 	}
643 }
644 
645 void
646 lim_send_probe_rsp_mgmt_frame(struct mac_context *mac_ctx,
647 			      tSirMacAddr peer_macaddr,
648 			      tpAniSSID ssid,
649 			      struct pe_session *pe_session,
650 			      uint8_t preq_p2pie)
651 {
652 	tDot11fProbeResponse *frm;
653 	QDF_STATUS sir_status;
654 	uint32_t cfg, payload, bytes = 0, status;
655 	tpSirMacMgmtHdr mac_hdr;
656 	uint8_t *frame;
657 	void *packet = NULL;
658 	QDF_STATUS qdf_status;
659 	uint32_t addn_ie_present = false;
660 
661 	uint16_t addn_ie_len = 0;
662 	bool wps_ap = 0;
663 	uint8_t tx_flag = 0;
664 	uint8_t *add_ie = NULL;
665 	uint8_t *p2p_ie = NULL;
666 	uint8_t noalen = 0;
667 	uint8_t total_noalen = 0;
668 	uint8_t noa_stream[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN];
669 	uint8_t noa_ie[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN];
670 	uint8_t vdev_id = 0;
671 	bool is_vht_enabled = false;
672 	tDot11fIEExtCap extracted_ext_cap = {0};
673 	bool extracted_ext_cap_flag = false;
674 	uint16_t mlo_ie_len = 0;
675 
676 	/* We don't answer requests in this case*/
677 	if (ANI_DRIVER_TYPE(mac_ctx) == QDF_DRIVER_TYPE_MFG)
678 		return;
679 
680 	if (!pe_session)
681 		return;
682 
683 	/*
684 	 * In case when cac timer is running for this SAP session then
685 	 * avoid sending probe rsp out. It is violation of dfs specification.
686 	 */
687 	if (((pe_session->opmode == QDF_SAP_MODE) ||
688 	    (pe_session->opmode == QDF_P2P_GO_MODE)) &&
689 	    (true == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)) {
690 		pe_info("CAC timer is running, probe response dropped");
691 		return;
692 	}
693 	if (wlan_vdev_is_up(pe_session->vdev) != QDF_STATUS_SUCCESS)
694 		return;
695 
696 	vdev_id = pe_session->vdev_id;
697 	frm = qdf_mem_malloc(sizeof(tDot11fProbeResponse));
698 	if (!frm)
699 		return;
700 	/*
701 	 * Fill out 'frm', after which we'll just hand the struct off to
702 	 * 'dot11f_pack_probe_response'.
703 	 */
704 	qdf_mem_zero((uint8_t *) frm, sizeof(tDot11fProbeResponse));
705 
706 	/*
707 	 * Timestamp to be updated by TFP, below.
708 	 *
709 	 * Beacon Interval:
710 	 */
711 	if (LIM_IS_AP_ROLE(pe_session)) {
712 		frm->BeaconInterval.interval =
713 			mac_ctx->sch.beacon_interval;
714 	} else {
715 		cfg = mac_ctx->mlme_cfg->sap_cfg.beacon_interval;
716 		frm->BeaconInterval.interval = (uint16_t) cfg;
717 	}
718 
719 	populate_dot11f_capabilities(mac_ctx, &frm->Capabilities, pe_session);
720 	populate_dot11f_ssid(mac_ctx, (tSirMacSSid *) ssid, &frm->SSID);
721 	populate_dot11f_supp_rates(mac_ctx, POPULATE_DOT11F_RATES_OPERATIONAL,
722 		&frm->SuppRates, pe_session);
723 	populate_dot11f_tpc_report(mac_ctx, &frm->TPCReport, pe_session);
724 
725 	populate_dot11f_ds_params(
726 		mac_ctx, &frm->DSParams,
727 		pe_session->curr_op_freq);
728 
729 	if (LIM_IS_AP_ROLE(pe_session)) {
730 		if (pe_session->wps_state != SAP_WPS_DISABLED)
731 			populate_dot11f_probe_res_wpsi_es(mac_ctx,
732 				&frm->WscProbeRes,
733 				pe_session);
734 	} else {
735 		wps_ap = mac_ctx->mlme_cfg->wps_params.enable_wps &
736 					    WNI_CFG_WPS_ENABLE_AP;
737 		if (wps_ap)
738 			populate_dot11f_wsc_in_probe_res(mac_ctx,
739 				&frm->WscProbeRes);
740 
741 		if (mac_ctx->lim.wscIeInfo.probeRespWscEnrollmentState ==
742 		    eLIM_WSC_ENROLL_BEGIN) {
743 			populate_dot11f_wsc_registrar_info_in_probe_res(mac_ctx,
744 				&frm->WscProbeRes);
745 			mac_ctx->lim.wscIeInfo.probeRespWscEnrollmentState =
746 				eLIM_WSC_ENROLL_IN_PROGRESS;
747 		}
748 
749 		if (mac_ctx->lim.wscIeInfo.wscEnrollmentState ==
750 		    eLIM_WSC_ENROLL_END) {
751 			de_populate_dot11f_wsc_registrar_info_in_probe_res(
752 				mac_ctx, &frm->WscProbeRes);
753 			mac_ctx->lim.wscIeInfo.probeRespWscEnrollmentState =
754 				eLIM_WSC_ENROLL_NOOP;
755 		}
756 	}
757 
758 	populate_dot11f_country(mac_ctx, &frm->Country, pe_session);
759 	populate_dot11f_edca_param_set(mac_ctx, &frm->EDCAParamSet, pe_session);
760 
761 	if (pe_session->dot11mode != MLME_DOT11_MODE_11B)
762 		populate_dot11f_erp_info(mac_ctx, &frm->ERPInfo, pe_session);
763 
764 	populate_dot11f_ext_supp_rates(mac_ctx,
765 		POPULATE_DOT11F_RATES_OPERATIONAL,
766 		&frm->ExtSuppRates, pe_session);
767 
768 	/* Populate HT IEs, when operating in 11n */
769 	if (pe_session->htCapability) {
770 		populate_dot11f_ht_caps(mac_ctx, pe_session, &frm->HTCaps);
771 		populate_dot11f_ht_info(mac_ctx, &frm->HTInfo, pe_session);
772 	}
773 	if (pe_session->vhtCapability) {
774 		pe_debug("Populate VHT IE in Probe Response");
775 		populate_dot11f_vht_caps(mac_ctx, pe_session, &frm->VHTCaps);
776 		populate_dot11f_vht_operation(mac_ctx, pe_session,
777 			&frm->VHTOperation);
778 		populate_dot11f_tx_power_env(mac_ctx,
779 					     &frm->transmit_power_env[0],
780 					     pe_session->ch_width,
781 					     pe_session->curr_op_freq,
782 					     &frm->num_transmit_power_env, false);
783 		/*
784 		 * we do not support multi users yet.
785 		 * populate_dot11f_vht_ext_bss_load( mac_ctx,
786 		 *         &frm.VHTExtBssLoad );
787 		 */
788 		is_vht_enabled = true;
789 	}
790 
791 	if (wlan_reg_is_6ghz_chan_freq(pe_session->curr_op_freq)) {
792 		populate_dot11f_tx_power_env(mac_ctx,
793 					     &frm->transmit_power_env[0],
794 					     pe_session->ch_width,
795 					     pe_session->curr_op_freq,
796 					     &frm->num_transmit_power_env,
797 					     false);
798 	}
799 
800 	if (lim_is_session_he_capable(pe_session)) {
801 		pe_debug("Populate HE IEs");
802 		populate_dot11f_he_caps(mac_ctx, pe_session,
803 					&frm->he_cap);
804 		populate_dot11f_he_operation(mac_ctx, pe_session,
805 					     &frm->he_op);
806 		populate_dot11f_sr_info(mac_ctx, pe_session,
807 					&frm->spatial_reuse);
808 		populate_dot11f_he_6ghz_cap(mac_ctx, pe_session,
809 					    &frm->he_6ghz_band_cap);
810 	}
811 
812 	if (wlan_vdev_mlme_is_mlo_ap(pe_session->vdev)) {
813 		mlo_ie_len = lim_send_bcn_frame_mlo(mac_ctx, pe_session);
814 		populate_dot11f_mlo_rnr(mac_ctx, pe_session,
815 					&frm->reduced_neighbor_report);
816 	}
817 	if (lim_is_session_eht_capable(pe_session)) {
818 		pe_debug("Populate EHT IEs");
819 		populate_dot11f_eht_caps(mac_ctx, pe_session, &frm->eht_cap);
820 		populate_dot11f_eht_operation(mac_ctx, pe_session,
821 					      &frm->eht_op);
822 	}
823 
824 	populate_dot11f_ext_cap(mac_ctx, is_vht_enabled, &frm->ExtCap,
825 		pe_session);
826 
827 	if (pe_session->pLimStartBssReq) {
828 		populate_dot11f_wpa(mac_ctx,
829 			&(pe_session->pLimStartBssReq->rsnIE),
830 			&frm->WPA);
831 		populate_dot11f_rsn_opaque(mac_ctx,
832 			&(pe_session->pLimStartBssReq->rsnIE),
833 			&frm->RSNOpaque);
834 	}
835 
836 	populate_dot11f_wmm(mac_ctx, &frm->WMMInfoAp, &frm->WMMParams,
837 		&frm->WMMCaps, pe_session);
838 
839 #if defined(FEATURE_WLAN_WAPI)
840 	if (pe_session->pLimStartBssReq)
841 		populate_dot11f_wapi(mac_ctx,
842 			&(pe_session->pLimStartBssReq->rsnIE),
843 			&frm->WAPI);
844 #endif /* defined(FEATURE_WLAN_WAPI) */
845 
846 	/*
847 	 * Only use CFG for non-listen mode. This CFG is not working for
848 	 * concurrency. In listening mode, probe rsp IEs is passed in
849 	 * the message from SME to PE.
850 	 */
851 	addn_ie_present =
852 		(pe_session->add_ie_params.probeRespDataLen != 0);
853 
854 	if (addn_ie_present) {
855 
856 		add_ie = qdf_mem_malloc(
857 				pe_session->add_ie_params.probeRespDataLen);
858 		if (!add_ie)
859 			goto err_ret;
860 
861 		qdf_mem_copy(add_ie,
862 			     pe_session->add_ie_params.probeRespData_buff,
863 			     pe_session->add_ie_params.probeRespDataLen);
864 		addn_ie_len = pe_session->add_ie_params.probeRespDataLen;
865 
866 		if (QDF_STATUS_SUCCESS != lim_get_addn_ie_for_probe_resp(mac_ctx,
867 					add_ie, &addn_ie_len, preq_p2pie)) {
868 			pe_err("Unable to get addn_ie");
869 			goto err_ret;
870 		}
871 
872 		sir_status = lim_strip_extcap_update_struct(mac_ctx,
873 					add_ie, &addn_ie_len,
874 					&extracted_ext_cap);
875 		if (QDF_STATUS_SUCCESS != sir_status) {
876 			pe_debug("Unable to strip off ExtCap IE");
877 		} else {
878 			extracted_ext_cap_flag = true;
879 		}
880 
881 		bytes = bytes + addn_ie_len;
882 
883 		if (preq_p2pie)
884 			p2p_ie = (uint8_t *)limGetP2pIEPtr(mac_ctx, &add_ie[0],
885 							   addn_ie_len);
886 
887 		if (p2p_ie) {
888 			/* get NoA attribute stream P2P IE */
889 			noalen = lim_get_noa_attr_stream(mac_ctx,
890 					noa_stream, pe_session);
891 			if (noalen) {
892 				if ((p2p_ie[1] + noalen) >
893 				    WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) {
894 					total_noalen = lim_build_p2p_ie(
895 								mac_ctx,
896 								&noa_ie[0],
897 								&noa_stream[0],
898 								noalen);
899 					bytes = bytes + total_noalen;
900 				} else {
901 					bytes = bytes + noalen;
902 				}
903 			}
904 		}
905 	}
906 
907 	/*
908 	 * Extcap IE now support variable length, merge Extcap IE from addn_ie
909 	 * may change the frame size. Therefore, MUST merge ExtCap IE before
910 	 * dot11f get packed payload size.
911 	 */
912 	if (extracted_ext_cap_flag)
913 		lim_merge_extcap_struct(&frm->ExtCap, &extracted_ext_cap,
914 					true);
915 	populate_dot11f_bcn_prot_extcaps(mac_ctx, pe_session, &frm->ExtCap);
916 
917 	status = dot11f_get_packed_probe_response_size(mac_ctx, frm, &payload);
918 	if (DOT11F_FAILED(status)) {
919 		pe_err("Probe Response size error (0x%08x)",
920 			status);
921 		/* We'll fall back on the worst case scenario: */
922 		payload = sizeof(tDot11fProbeResponse);
923 	} else if (DOT11F_WARNED(status)) {
924 		pe_warn("Probe Response size warning (0x%08x)",
925 			status);
926 	}
927 
928 	bytes += payload + sizeof(tSirMacMgmtHdr) + mlo_ie_len;
929 
930 	qdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame,
931 				      (void **)&packet);
932 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
933 		pe_err("Probe Response allocation failed");
934 		goto err_ret;
935 	}
936 	/* Paranoia: */
937 	qdf_mem_zero(frame, bytes);
938 
939 	/* Next, we fill out the buffer descriptor: */
940 	lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME,
941 		SIR_MAC_MGMT_PROBE_RSP, peer_macaddr,
942 		pe_session->self_mac_addr);
943 
944 	mac_hdr = (tpSirMacMgmtHdr) frame;
945 
946 	sir_copy_mac_addr(mac_hdr->bssId, pe_session->bssId);
947 
948 	/* That done, pack the Probe Response: */
949 	status =
950 		dot11f_pack_probe_response(mac_ctx, frm,
951 			frame + sizeof(tSirMacMgmtHdr),
952 			payload, &payload);
953 	if (DOT11F_FAILED(status)) {
954 		pe_err("Probe Response pack failure (0x%08x)",
955 			status);
956 			goto err_ret;
957 	} else if (DOT11F_WARNED(status)) {
958 		pe_warn("Probe Response pack warning (0x%08x)", status);
959 	}
960 
961 	if (mlo_ie_len) {
962 		qdf_status = lim_fill_complete_mlo_ie(pe_session, mlo_ie_len,
963 				    frame + sizeof(tSirMacMgmtHdr) + payload);
964 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
965 			pe_debug("assemble ml ie error");
966 			mlo_ie_len = 0;
967 		}
968 		payload += mlo_ie_len;
969 	}
970 
971 	pe_debug("Sending Probe Response frame to: "QDF_MAC_ADDR_FMT,
972 		 QDF_MAC_ADDR_REF(peer_macaddr));
973 
974 	lim_add_additional_ie(frame, sizeof(tSirMacMgmtHdr) + payload, add_ie,
975 			      addn_ie_len, p2p_ie, noa_ie, total_noalen,
976 			      noa_stream, noalen);
977 
978 	if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) ||
979 	    pe_session->opmode == QDF_P2P_CLIENT_MODE ||
980 	    pe_session->opmode == QDF_P2P_GO_MODE)
981 		tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
982 
983 	/* Queue Probe Response frame in high priority WQ */
984 	qdf_status = wma_tx_frame(mac_ctx, packet,
985 				  (uint16_t)bytes,
986 				  TXRX_FRM_802_11_MGMT,
987 				  ANI_TXDIR_TODS,
988 				  7, lim_tx_complete, frame, tx_flag,
989 				  vdev_id, 0, RATEID_DEFAULT, 0);
990 
991 	/* Pkt will be freed up by the callback */
992 	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
993 		pe_err("Could not send Probe Response");
994 
995 	if (add_ie)
996 		qdf_mem_free(add_ie);
997 
998 	qdf_mem_free(frm);
999 	return;
1000 
1001 err_ret:
1002 	if (add_ie)
1003 		qdf_mem_free(add_ie);
1004 	if (frm)
1005 		qdf_mem_free(frm);
1006 	if (packet)
1007 		cds_packet_free((void *)packet);
1008 	return;
1009 
1010 } /* End lim_send_probe_rsp_mgmt_frame. */
1011 
1012 void
1013 lim_send_addts_req_action_frame(struct mac_context *mac,
1014 				tSirMacAddr peerMacAddr,
1015 				tSirAddtsReqInfo *pAddTS, struct pe_session *pe_session)
1016 {
1017 	uint16_t i;
1018 	uint8_t *pFrame;
1019 	tDot11fAddTSRequest AddTSReq;
1020 	tDot11fWMMAddTSRequest WMMAddTSReq;
1021 	uint32_t nPayload, nBytes, nStatus;
1022 	tpSirMacMgmtHdr pMacHdr;
1023 	void *pPacket;
1024 #ifdef FEATURE_WLAN_ESE
1025 	uint32_t phyMode;
1026 #endif
1027 	QDF_STATUS qdf_status;
1028 	uint8_t txFlag = 0;
1029 	uint8_t smeSessionId = 0;
1030 
1031 	if (!pe_session) {
1032 		return;
1033 	}
1034 
1035 	smeSessionId = pe_session->smeSessionId;
1036 
1037 	if (!pAddTS->wmeTspecPresent) {
1038 		qdf_mem_zero((uint8_t *) &AddTSReq, sizeof(AddTSReq));
1039 
1040 		AddTSReq.Action.action = QOS_ADD_TS_REQ;
1041 		AddTSReq.DialogToken.token = pAddTS->dialogToken;
1042 		AddTSReq.Category.category = ACTION_CATEGORY_QOS;
1043 		if (pAddTS->lleTspecPresent) {
1044 			populate_dot11f_tspec(&pAddTS->tspec, &AddTSReq.TSPEC);
1045 		} else {
1046 			populate_dot11f_wmmtspec(&pAddTS->tspec,
1047 						 &AddTSReq.WMMTSPEC);
1048 		}
1049 
1050 		if (pAddTS->lleTspecPresent) {
1051 			AddTSReq.num_WMMTCLAS = 0;
1052 			AddTSReq.num_TCLAS = pAddTS->numTclas;
1053 			for (i = 0; i < pAddTS->numTclas; ++i) {
1054 				populate_dot11f_tclas(mac, &pAddTS->tclasInfo[i],
1055 						      &AddTSReq.TCLAS[i]);
1056 			}
1057 		} else {
1058 			AddTSReq.num_TCLAS = 0;
1059 			AddTSReq.num_WMMTCLAS = pAddTS->numTclas;
1060 			for (i = 0; i < pAddTS->numTclas; ++i) {
1061 				populate_dot11f_wmmtclas(mac,
1062 							 &pAddTS->tclasInfo[i],
1063 							 &AddTSReq.WMMTCLAS[i]);
1064 			}
1065 		}
1066 
1067 		if (pAddTS->tclasProcPresent) {
1068 			if (pAddTS->lleTspecPresent) {
1069 				AddTSReq.TCLASSPROC.processing =
1070 					pAddTS->tclasProc;
1071 				AddTSReq.TCLASSPROC.present = 1;
1072 			} else {
1073 				AddTSReq.WMMTCLASPROC.version = 1;
1074 				AddTSReq.WMMTCLASPROC.processing =
1075 					pAddTS->tclasProc;
1076 				AddTSReq.WMMTCLASPROC.present = 1;
1077 			}
1078 		}
1079 
1080 		nStatus =
1081 			dot11f_get_packed_add_ts_request_size(mac, &AddTSReq, &nPayload);
1082 		if (DOT11F_FAILED(nStatus)) {
1083 			pe_err("Failed to calculate the packed size for an Add TS Request (0x%08x)",
1084 				nStatus);
1085 			/* We'll fall back on the worst case scenario: */
1086 			nPayload = sizeof(tDot11fAddTSRequest);
1087 		} else if (DOT11F_WARNED(nStatus)) {
1088 			pe_warn("There were warnings while calculating the packed size for an Add TS Request (0x%08x)",
1089 				nStatus);
1090 		}
1091 	} else {
1092 		qdf_mem_zero((uint8_t *) &WMMAddTSReq, sizeof(WMMAddTSReq));
1093 
1094 		WMMAddTSReq.Action.action = QOS_ADD_TS_REQ;
1095 		WMMAddTSReq.DialogToken.token = pAddTS->dialogToken;
1096 		WMMAddTSReq.Category.category = ACTION_CATEGORY_WMM;
1097 
1098 		/* WMM spec 2.2.10 - status code is only filled in for ADDTS response */
1099 		WMMAddTSReq.StatusCode.statusCode = 0;
1100 
1101 		populate_dot11f_wmmtspec(&pAddTS->tspec, &WMMAddTSReq.WMMTSPEC);
1102 #ifdef FEATURE_WLAN_ESE
1103 		lim_get_phy_mode(mac, &phyMode, pe_session);
1104 
1105 		if (phyMode == WNI_CFG_PHY_MODE_11G
1106 		    || phyMode == WNI_CFG_PHY_MODE_11A) {
1107 			pAddTS->tsrsIE.rates[0] = TSRS_11AG_RATE_6MBPS;
1108 		} else {
1109 			pAddTS->tsrsIE.rates[0] = TSRS_11B_RATE_5_5MBPS;
1110 		}
1111 		populate_dot11_tsrsie(mac, &pAddTS->tsrsIE,
1112 				      &WMMAddTSReq.ESETrafStrmRateSet,
1113 				      sizeof(uint8_t));
1114 #endif
1115 		/* fillWmeTspecIE */
1116 
1117 		nStatus =
1118 			dot11f_get_packed_wmm_add_ts_request_size(mac, &WMMAddTSReq,
1119 								  &nPayload);
1120 		if (DOT11F_FAILED(nStatus)) {
1121 			pe_err("Failed to calculate the packed size for a WMM Add TS Request (0x%08x)",
1122 				nStatus);
1123 			/* We'll fall back on the worst case scenario: */
1124 			nPayload = sizeof(tDot11fAddTSRequest);
1125 		} else if (DOT11F_WARNED(nStatus)) {
1126 			pe_warn("There were warnings while calculating the packed size for a WMM Add TS Request (0x%08x)",
1127 				nStatus);
1128 		}
1129 	}
1130 
1131 	nBytes = nPayload + sizeof(tSirMacMgmtHdr);
1132 
1133 	qdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
1134 				      (void **)&pPacket);
1135 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1136 		pe_err("Failed to allocate %d bytes for an Add TS Request",
1137 			nBytes);
1138 		return;
1139 	}
1140 	/* Paranoia: */
1141 	qdf_mem_zero(pFrame, nBytes);
1142 
1143 	/* Next, we fill out the buffer descriptor: */
1144 	lim_populate_mac_header(mac, pFrame, SIR_MAC_MGMT_FRAME,
1145 		SIR_MAC_MGMT_ACTION, peerMacAddr, pe_session->self_mac_addr);
1146 	pMacHdr = (tpSirMacMgmtHdr) pFrame;
1147 
1148 	sir_copy_mac_addr(pMacHdr->bssId, pe_session->bssId);
1149 
1150 	lim_set_protected_bit(mac, pe_session, peerMacAddr, pMacHdr);
1151 
1152 	/* That done, pack the struct: */
1153 	if (!pAddTS->wmeTspecPresent) {
1154 		nStatus = dot11f_pack_add_ts_request(mac, &AddTSReq,
1155 						     pFrame +
1156 						     sizeof(tSirMacMgmtHdr),
1157 						     nPayload, &nPayload);
1158 		if (DOT11F_FAILED(nStatus)) {
1159 			pe_err("Failed to pack an Add TS Request "
1160 				"(0x%08x)", nStatus);
1161 			cds_packet_free((void *)pPacket);
1162 			return; /* allocated! */
1163 		} else if (DOT11F_WARNED(nStatus)) {
1164 			pe_warn("There were warnings while packing an Add TS Request (0x%08x)",
1165 				nStatus);
1166 		}
1167 	} else {
1168 		nStatus = dot11f_pack_wmm_add_ts_request(mac, &WMMAddTSReq,
1169 							 pFrame +
1170 							 sizeof(tSirMacMgmtHdr),
1171 							 nPayload, &nPayload);
1172 		if (DOT11F_FAILED(nStatus)) {
1173 			pe_err("Failed to pack a WMM Add TS Request (0x%08x)",
1174 				nStatus);
1175 			cds_packet_free((void *)pPacket);
1176 			return; /* allocated! */
1177 		} else if (DOT11F_WARNED(nStatus)) {
1178 			pe_warn("There were warnings while packing a WMM Add TS Request (0x%08x)",
1179 				nStatus);
1180 		}
1181 	}
1182 
1183 	pe_debug("Sending an Add TS Request frame to "QDF_MAC_ADDR_FMT,
1184 		 QDF_MAC_ADDR_REF(peerMacAddr));
1185 
1186 	if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) ||
1187 	    pe_session->opmode == QDF_P2P_CLIENT_MODE ||
1188 	    pe_session->opmode == QDF_P2P_GO_MODE)
1189 		txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
1190 
1191 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
1192 			 pe_session->peSessionId, pMacHdr->fc.subType));
1193 	lim_diag_mgmt_tx_event_report(mac, pMacHdr,
1194 				      pe_session, QDF_STATUS_SUCCESS,
1195 				      QDF_STATUS_SUCCESS);
1196 
1197 	/* Queue Addts Response frame in high priority WQ */
1198 	qdf_status = wma_tx_frame(mac, pPacket, (uint16_t) nBytes,
1199 				TXRX_FRM_802_11_MGMT,
1200 				ANI_TXDIR_TODS,
1201 				7, lim_tx_complete, pFrame, txFlag,
1202 				smeSessionId, 0, RATEID_DEFAULT, 0);
1203 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
1204 			 pe_session->peSessionId, qdf_status));
1205 
1206 	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
1207 		pe_err("Could not send an Add TS Request (%X",
1208 			qdf_status);
1209 } /* End lim_send_addts_req_action_frame. */
1210 
1211 #ifdef WLAN_FEATURE_MSCS
1212 /**
1213  * lim_mscs_req_tx_complete_cnf()- Confirmation for mscs req sent over the air
1214  * @context: pointer to global mac
1215  * @buf: buffer
1216  * @tx_complete : Sent status
1217  * @params; tx completion params
1218  *
1219  * Return: This returns QDF_STATUS
1220  */
1221 
1222 static QDF_STATUS lim_mscs_req_tx_complete_cnf(void *context, qdf_nbuf_t buf,
1223 					       uint32_t tx_complete,
1224 					       void *params)
1225 {
1226 	uint16_t mscs_ack_status;
1227 	uint16_t reason_code;
1228 
1229 	pe_debug("mscs req TX: %s (%d)",
1230 		 (tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK) ?
1231 		      "success" : "fail", tx_complete);
1232 
1233 	if (tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK) {
1234 		mscs_ack_status = ACKED;
1235 		reason_code = QDF_STATUS_SUCCESS;
1236 	} else {
1237 		mscs_ack_status = NOT_ACKED;
1238 		reason_code = QDF_STATUS_E_FAILURE;
1239 	}
1240 	if (buf)
1241 		qdf_nbuf_free(buf);
1242 
1243 	return QDF_STATUS_SUCCESS;
1244 }
1245 
1246 void lim_send_mscs_req_action_frame(struct mac_context *mac,
1247 				    struct qdf_mac_addr peer_mac,
1248 				    struct mscs_req_info *mscs_req,
1249 				    struct pe_session *pe_session)
1250 {
1251 	uint8_t *frame;
1252 	tDot11fmscs_request_action_frame mscs_req_frame;
1253 	uint32_t payload, bytes;
1254 	tpSirMacMgmtHdr peer_mac_hdr;
1255 	void *packet;
1256 	QDF_STATUS qdf_status;
1257 	tpSirMacMgmtHdr mac_hdr;
1258 
1259 	qdf_mem_zero(&mscs_req_frame, sizeof(mscs_req_frame));
1260 
1261 	mscs_req_frame.Action.action = MCSC_REQ;
1262 	mscs_req_frame.DialogToken.token = mscs_req->dialog_token;
1263 	mscs_req_frame.Category.category = ACTION_CATEGORY_RVS;
1264 	populate_dot11f_mscs_dec_element(mscs_req, &mscs_req_frame);
1265 	bytes = dot11f_get_packed_mscs_request_action_frameSize(mac,
1266 					&mscs_req_frame, &payload);
1267 	if (DOT11F_FAILED(bytes)) {
1268 		pe_err("Failed to calculate the packed size for an MSCS Request (0x%08x)",
1269 		       bytes);
1270 		/* We'll fall back on the worst case scenario: */
1271 		payload = sizeof(tDot11fmscs_request_action_frame);
1272 	} else if (DOT11F_WARNED(bytes)) {
1273 		pe_warn("There were warnings while calculating the packed size for MSCS Request (0x%08x)",
1274 			bytes);
1275 	}
1276 
1277 	bytes = payload + sizeof(struct qdf_mac_addr);
1278 
1279 	qdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame,
1280 				      (void **)&packet);
1281 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1282 		pe_err("Failed to allocate %d bytes for an mscs request",
1283 		       bytes);
1284 		return;
1285 	}
1286 	/* Paranoia: */
1287 	qdf_mem_zero(frame, bytes);
1288 
1289 	lim_populate_mac_header(mac, frame, SIR_MAC_MGMT_FRAME,
1290 				SIR_MAC_MGMT_ACTION,
1291 				peer_mac.bytes, pe_session->self_mac_addr);
1292 	peer_mac_hdr = (tpSirMacMgmtHdr) frame;
1293 
1294 	qdf_mem_copy(peer_mac.bytes, pe_session->bssId, QDF_MAC_ADDR_SIZE);
1295 
1296 	lim_set_protected_bit(mac, pe_session, peer_mac.bytes, peer_mac_hdr);
1297 
1298 	bytes = dot11f_pack_mscs_request_action_frame(mac, &mscs_req_frame,
1299 						      frame +
1300 						      sizeof(tSirMacMgmtHdr),
1301 						      payload, &payload);
1302 	if (DOT11F_FAILED(bytes)) {
1303 		pe_err("Failed to pack an mscs Request " "(0x%08x)", bytes);
1304 		cds_packet_free((void *)packet);
1305 			return; /* allocated! */
1306 	} else if (DOT11F_WARNED(bytes)) {
1307 			pe_warn("There were warnings while packing an mscs Request (0x%08x)",
1308 				bytes);
1309 	}
1310 
1311 	mac_hdr = (tpSirMacMgmtHdr) frame;
1312 
1313 	pe_debug("mscs req TX: vdev id: %d to "QDF_MAC_ADDR_FMT" seq num[%d], frame subtype:%d ",
1314 		 mscs_req->vdev_id, QDF_MAC_ADDR_REF(peer_mac.bytes),
1315 		 mac->mgmtSeqNum, mac_hdr->fc.subType);
1316 
1317 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
1318 			   frame,
1319 			   (uint16_t)(sizeof(tSirMacMgmtHdr) + payload));
1320 	qdf_status =
1321 		wma_tx_frameWithTxComplete(mac, packet,
1322 			   (uint16_t) (sizeof(tSirMacMgmtHdr) + payload),
1323 			   TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
1324 			   lim_tx_complete, frame, lim_mscs_req_tx_complete_cnf,
1325 			   HAL_USE_PEER_STA_REQUESTED_MASK,
1326 			   pe_session->vdev_id, false, 0, RATEID_DEFAULT, 0, 0);
1327 	if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
1328 		mlme_set_is_mscs_req_sent(pe_session->vdev, true);
1329 	} else {
1330 		pe_err("Could not send an mscs Request (%X)", qdf_status);
1331 	}
1332 
1333 	/* Pkt will be freed up by the callback */
1334 } /* End lim_send_mscs_req_action_frame */
1335 #endif
1336 
1337 /**
1338  * lim_assoc_rsp_tx_complete() - Confirmation for assoc rsp OTA
1339  * @context: pointer to global mac
1340  * @buf: buffer which is nothing but entire assoc rsp frame
1341  * @tx_complete : Sent status
1342  * @params; tx completion params
1343  *
1344  * Return: This returns QDF_STATUS
1345  */
1346 static QDF_STATUS lim_assoc_rsp_tx_complete(
1347 					void *context,
1348 					qdf_nbuf_t buf,
1349 					uint32_t tx_complete,
1350 					void *params)
1351 {
1352 	struct mac_context *mac_ctx = (struct mac_context *)context;
1353 	tSirMacMgmtHdr *mac_hdr;
1354 	struct pe_session *session_entry;
1355 	uint8_t session_id;
1356 	tpLimMlmAssocInd lim_assoc_ind;
1357 	tpDphHashNode sta_ds;
1358 	uint16_t aid;
1359 	uint8_t *data;
1360 	struct assoc_ind *sme_assoc_ind;
1361 	struct scheduler_msg msg;
1362 	tpSirAssocReq assoc_req;
1363 
1364 	if (!buf) {
1365 		pe_err("Assoc rsp frame buffer is NULL");
1366 		goto null_buf;
1367 	}
1368 
1369 	data = qdf_nbuf_data(buf);
1370 
1371 	if (!data) {
1372 		pe_err("Assoc rsp frame is NULL");
1373 		goto end;
1374 	}
1375 
1376 	mac_hdr = (tSirMacMgmtHdr *)data;
1377 
1378 	session_entry = pe_find_session_by_bssid(
1379 				mac_ctx, mac_hdr->sa,
1380 				&session_id);
1381 	if (!session_entry) {
1382 		pe_err("session entry is NULL");
1383 		goto end;
1384 	}
1385 
1386 	sta_ds = dph_lookup_hash_entry(mac_ctx,
1387 				       (uint8_t *)mac_hdr->da, &aid,
1388 				       &session_entry->dph.dphHashTable);
1389 	if (!sta_ds) {
1390 		pe_err("sta_ds is NULL");
1391 		goto end;
1392 	}
1393 
1394 	/* Get a copy of the already parsed Assoc Request */
1395 	assoc_req =
1396 		(tpSirAssocReq)session_entry->parsedAssocReq[sta_ds->assocId];
1397 
1398 	if (!assoc_req) {
1399 		pe_err("assoc req for assoc_id:%d is NULL", sta_ds->assocId);
1400 		goto end;
1401 	}
1402 
1403 	if (tx_complete != WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK) {
1404 		lim_send_disassoc_mgmt_frame(mac_ctx,
1405 					     REASON_DISASSOC_DUE_TO_INACTIVITY,
1406 					     sta_ds->staAddr,
1407 					     session_entry, false);
1408 		lim_trigger_sta_deletion(mac_ctx, sta_ds, session_entry);
1409 		goto free_buffers;
1410 	}
1411 
1412 	if (lim_is_mlo_conn(session_entry, sta_ds) &&
1413 	    QDF_IS_STATUS_ERROR(lim_mlo_assoc_ind_upper_layer(
1414 				mac_ctx, session_entry,
1415 				&assoc_req->mlo_info))) {
1416 		pe_err("partner link indicate upper layer error");
1417 		goto free_assoc_req;
1418 	}
1419 	lim_assoc_ind = qdf_mem_malloc(sizeof(tLimMlmAssocInd));
1420 	if (!lim_assoc_ind)
1421 		goto free_assoc_req;
1422 
1423 	if (!lim_fill_lim_assoc_ind_params(lim_assoc_ind, mac_ctx,
1424 					   sta_ds, session_entry)) {
1425 		pe_err("lim assoc ind fill error");
1426 		goto lim_assoc_ind;
1427 	}
1428 
1429 	sme_assoc_ind = qdf_mem_malloc(sizeof(struct assoc_ind));
1430 	if (!sme_assoc_ind)
1431 		goto lim_assoc_ind;
1432 
1433 	sme_assoc_ind->messageType = eWNI_SME_ASSOC_IND_UPPER_LAYER;
1434 	lim_fill_sme_assoc_ind_params(
1435 				mac_ctx, lim_assoc_ind,
1436 				sme_assoc_ind,
1437 				session_entry, true);
1438 
1439 	qdf_mem_zero(&msg, sizeof(struct scheduler_msg));
1440 	msg.type = eWNI_SME_ASSOC_IND_UPPER_LAYER;
1441 	msg.bodyptr = sme_assoc_ind;
1442 	msg.bodyval = 0;
1443 	sme_assoc_ind->reassocReq = sta_ds->mlmStaContext.subType;
1444 	sme_assoc_ind->timingMeasCap = sta_ds->timingMeasCap;
1445 	MTRACE(mac_trace_msg_tx(mac_ctx, session_entry->peSessionId, msg.type));
1446 	lim_sys_process_mmh_msg_api(mac_ctx, &msg);
1447 
1448 	qdf_mem_free(lim_assoc_ind);
1449 
1450 free_buffers:
1451 	lim_free_assoc_req_frm_buf(assoc_req);
1452 	qdf_mem_free(session_entry->parsedAssocReq[sta_ds->assocId]);
1453 	session_entry->parsedAssocReq[sta_ds->assocId] = NULL;
1454 	qdf_nbuf_free(buf);
1455 
1456 	return QDF_STATUS_SUCCESS;
1457 
1458 lim_assoc_ind:
1459 	qdf_mem_free(lim_assoc_ind);
1460 free_assoc_req:
1461 	lim_free_assoc_req_frm_buf(assoc_req);
1462 	qdf_mem_free(session_entry->parsedAssocReq[sta_ds->assocId]);
1463 	session_entry->parsedAssocReq[sta_ds->assocId] = NULL;
1464 end:
1465 	qdf_nbuf_free(buf);
1466 null_buf:
1467 	return QDF_STATUS_E_FAILURE;
1468 }
1469 
1470 #ifdef WLAN_FEATURE_11BE
1471 QDF_STATUS lim_strip_eht_cap_ie(struct mac_context *mac_ctx,
1472 				uint8_t *frame_ies,
1473 				uint16_t *ie_buf_size,
1474 				uint8_t *eht_cap_ie)
1475 {
1476 	return lim_strip_ie(mac_ctx, frame_ies,	ie_buf_size,
1477 			    WLAN_ELEMID_EXTN_ELEM, ONE_BYTE,
1478 			    EHT_CAP_OUI_TYPE, EHT_CAP_OUI_SIZE,
1479 			    eht_cap_ie,	WLAN_MAX_IE_LEN);
1480 }
1481 
1482 QDF_STATUS lim_strip_eht_op_ie(struct mac_context *mac_ctx,
1483 			       uint8_t *frame_ies,
1484 			       uint16_t *ie_buf_size,
1485 			       uint8_t *eht_op_ie)
1486 {
1487 	return lim_strip_ie(mac_ctx, frame_ies, ie_buf_size,
1488 			    WLAN_ELEMID_EXTN_ELEM, ONE_BYTE,
1489 			    EHT_OP_OUI_TYPE, EHT_OP_OUI_SIZE,
1490 			    eht_op_ie, WLAN_MAX_IE_LEN);
1491 }
1492 #endif
1493 
1494 void
1495 lim_send_assoc_rsp_mgmt_frame(struct mac_context *mac_ctx,
1496 			      uint16_t status_code, uint16_t aid,
1497 			      tSirMacAddr peer_addr,
1498 			      uint8_t subtype, tpDphHashNode sta,
1499 			      struct pe_session *pe_session,
1500 			      bool tx_complete)
1501 {
1502 	static tDot11fAssocResponse frm;
1503 	uint8_t *frame;
1504 	tpSirMacMgmtHdr mac_hdr;
1505 	QDF_STATUS sir_status;
1506 	uint8_t lle_mode = 0, addts;
1507 	tHalBitVal qos_mode, wme_mode;
1508 	uint32_t payload, bytes = 0, status;
1509 	void *packet;
1510 	QDF_STATUS qdf_status;
1511 	tUpdateBeaconParams beacon_params;
1512 	uint8_t tx_flag = 0;
1513 	uint32_t addn_ie_len = 0;
1514 	uint8_t *add_ie;
1515 	tpSirAssocReq assoc_req = NULL;
1516 	uint8_t sme_session = 0;
1517 	bool is_vht = false;
1518 	uint16_t stripoff_len = 0;
1519 	tDot11fIEExtCap extracted_ext_cap;
1520 	bool extracted_flag = false;
1521 	uint8_t retry_int;
1522 	uint16_t max_retries;
1523 	uint8_t *eht_op_ie = NULL, eht_op_ie_len = 0;
1524 	uint8_t *eht_cap_ie = NULL, eht_cap_ie_len = 0;
1525 	bool is_band_2g;
1526 	uint16_t ie_buf_size;
1527 	uint16_t mlo_ie_len = 0;
1528 	struct element_info ie;
1529 
1530 	if (!pe_session) {
1531 		pe_err("pe_session is NULL");
1532 		return;
1533 	}
1534 	if (sta && lim_is_mlo_conn(pe_session, sta) &&
1535 	    !lim_is_mlo_recv_assoc(sta)) {
1536 		pe_err("Do not send assoc rsp in mlo partner peer "
1537 		       QDF_MAC_ADDR_FMT,
1538 		       QDF_MAC_ADDR_REF(sta->staAddr));
1539 		return;
1540 	}
1541 
1542 	sme_session = pe_session->smeSessionId;
1543 
1544 	qdf_mem_zero((uint8_t *) &frm, sizeof(frm));
1545 
1546 	limGetQosMode(pe_session, &qos_mode);
1547 	limGetWmeMode(pe_session, &wme_mode);
1548 
1549 	/*
1550 	 * An Add TS IE is added only if the AP supports it and
1551 	 * the requesting STA sent a traffic spec.
1552 	 */
1553 	addts = (qos_mode && sta && sta->qos.addtsPresent) ? 1 : 0;
1554 
1555 	frm.Status.status = status_code;
1556 
1557 	frm.AID.associd = aid | LIM_AID_MASK;
1558 
1559 	if (!sta) {
1560 		populate_dot11f_supp_rates(mac_ctx,
1561 			POPULATE_DOT11F_RATES_OPERATIONAL,
1562 			&frm.SuppRates, pe_session);
1563 		populate_dot11f_ext_supp_rates(mac_ctx,
1564 			POPULATE_DOT11F_RATES_OPERATIONAL,
1565 			&frm.ExtSuppRates, pe_session);
1566 	} else {
1567 		populate_dot11f_assoc_rsp_rates(mac_ctx, &frm.SuppRates,
1568 			&frm.ExtSuppRates,
1569 			sta->supportedRates.llbRates,
1570 			sta->supportedRates.llaRates);
1571 	}
1572 
1573 	if (LIM_IS_AP_ROLE(pe_session) && sta &&
1574 	    QDF_STATUS_SUCCESS == status_code) {
1575 		assoc_req = (tpSirAssocReq)
1576 			pe_session->parsedAssocReq[sta->assocId];
1577 		/*
1578 		 * populate P2P IE in AssocRsp when assoc_req from the peer
1579 		 * includes P2P IE
1580 		 */
1581 		if (assoc_req && assoc_req->addIEPresent)
1582 			populate_dot11_assoc_res_p2p_ie(mac_ctx,
1583 				&frm.P2PAssocRes,
1584 				assoc_req);
1585 	}
1586 
1587 	if (sta) {
1588 		if (eHAL_SET == qos_mode) {
1589 			if (sta->lleEnabled) {
1590 				lle_mode = 1;
1591 				populate_dot11f_edca_param_set(mac_ctx,
1592 					&frm.EDCAParamSet, pe_session);
1593 			}
1594 		}
1595 
1596 		if ((!lle_mode) && (eHAL_SET == wme_mode) && sta->wmeEnabled) {
1597 			populate_dot11f_wmm_params(mac_ctx, &frm.WMMParams,
1598 				pe_session);
1599 
1600 			if (sta->wsmEnabled)
1601 				populate_dot11f_wmm_caps(&frm.WMMCaps);
1602 		}
1603 
1604 		if (sta->mlmStaContext.htCapability &&
1605 		    pe_session->htCapability) {
1606 			populate_dot11f_ht_caps(mac_ctx, pe_session,
1607 				&frm.HTCaps);
1608 			/*
1609 			 * Check the STA capability and
1610 			 * update the HTCaps accordingly
1611 			 */
1612 			frm.HTCaps.supportedChannelWidthSet = (
1613 				sta->htSupportedChannelWidthSet <
1614 				     pe_session->htSupportedChannelWidthSet) ?
1615 				      sta->htSupportedChannelWidthSet :
1616 				       pe_session->htSupportedChannelWidthSet;
1617 			if (!frm.HTCaps.supportedChannelWidthSet)
1618 				frm.HTCaps.shortGI40MHz = 0;
1619 
1620 			populate_dot11f_ht_info(mac_ctx, &frm.HTInfo,
1621 						pe_session);
1622 		}
1623 
1624 		if (sta->mlmStaContext.vhtCapability &&
1625 		    pe_session->vhtCapability) {
1626 			populate_dot11f_vht_caps(mac_ctx, pe_session,
1627 				&frm.VHTCaps);
1628 			populate_dot11f_vht_operation(mac_ctx, pe_session,
1629 					&frm.VHTOperation);
1630 			is_vht = true;
1631 		} else if (sta->mlmStaContext.force_1x1 &&
1632 			   frm.HTCaps.present) {
1633 			/*
1634 			 * WAR: In P2P GO mode, if the P2P client device
1635 			 * is only HT capable and not VHT capable, but the P2P
1636 			 * GO device is VHT capable and advertises 2x2 NSS with
1637 			 * HT capability client device, which results in IOT
1638 			 * issues.
1639 			 * When GO is operating in DBS mode, GO beacons
1640 			 * advertise 2x2 capability but include OMN IE to
1641 			 * indicate current operating mode of 1x1. But here
1642 			 * peer device is only HT capable and will not
1643 			 * understand OMN IE.
1644 			 */
1645 			frm.HTInfo.basicMCSSet[1] = 0;
1646 			frm.HTCaps.supportedMCSSet[1] = 0;
1647 		}
1648 
1649 		if (pe_session->vhtCapability &&
1650 		    pe_session->vendor_vht_sap &&
1651 		    (assoc_req) &&
1652 		    assoc_req->vendor_vht_ie.VHTCaps.present) {
1653 			frm.vendor_vht_ie.present = 1;
1654 			frm.vendor_vht_ie.sub_type =
1655 				pe_session->vendor_specific_vht_ie_sub_type;
1656 			frm.vendor_vht_ie.VHTCaps.present = 1;
1657 			populate_dot11f_vht_caps(mac_ctx, pe_session,
1658 				&frm.vendor_vht_ie.VHTCaps);
1659 			populate_dot11f_vht_operation(mac_ctx, pe_session,
1660 					&frm.vendor_vht_ie.VHTOperation);
1661 			is_vht = true;
1662 		}
1663 		populate_dot11f_ext_cap(mac_ctx, is_vht, &frm.ExtCap,
1664 			pe_session);
1665 
1666 		populate_dot11f_qcn_ie(mac_ctx, pe_session, &frm.qcn_ie,
1667 				       QCN_IE_ATTR_ID_ALL);
1668 
1669 		if (lim_is_sta_he_capable(sta) &&
1670 		    lim_is_session_he_capable(pe_session)) {
1671 			populate_dot11f_he_caps(mac_ctx, pe_session,
1672 						&frm.he_cap);
1673 			populate_dot11f_sr_info(mac_ctx, pe_session,
1674 						&frm.spatial_reuse);
1675 			populate_dot11f_he_operation(mac_ctx, pe_session,
1676 						     &frm.he_op);
1677 			populate_dot11f_he_6ghz_cap(mac_ctx, pe_session,
1678 						    &frm.he_6ghz_band_cap);
1679 		}
1680 
1681 		if (lim_is_sta_eht_capable(sta) &&
1682 		    lim_is_session_eht_capable(pe_session)) {
1683 			populate_dot11f_eht_caps(mac_ctx, pe_session,
1684 						 &frm.eht_cap);
1685 			populate_dot11f_eht_operation(mac_ctx, pe_session,
1686 						      &frm.eht_op);
1687 		}
1688 
1689 		if (status_code == STATUS_ASSOC_REJECTED_TEMPORARILY) {
1690 			max_retries =
1691 			mac_ctx->mlme_cfg->gen.pmf_sa_query_max_retries;
1692 			retry_int =
1693 			mac_ctx->mlme_cfg->gen.pmf_sa_query_retry_interval;
1694 			populate_dot11f_timeout_interval(mac_ctx,
1695 							 &frm.TimeoutInterval,
1696 						SIR_MAC_TI_TYPE_ASSOC_COMEBACK,
1697 						(max_retries -
1698 						sta->pmfSaQueryRetryCount)
1699 						* retry_int);
1700 		}
1701 
1702 		if (LIM_IS_AP_ROLE(pe_session)  && sta->non_ecsa_capable)
1703 			pe_session->lim_non_ecsa_cap_num++;
1704 	}
1705 
1706 	qdf_mem_zero((uint8_t *) &beacon_params, sizeof(beacon_params));
1707 
1708 	if (LIM_IS_AP_ROLE(pe_session) &&
1709 	    (pe_session->gLimProtectionControl !=
1710 	     MLME_FORCE_POLICY_PROTECTION_DISABLE))
1711 		lim_decide_ap_protection(mac_ctx, peer_addr, &beacon_params,
1712 					 pe_session);
1713 
1714 	lim_update_short_preamble(mac_ctx, peer_addr, &beacon_params,
1715 		pe_session);
1716 	lim_update_short_slot_time(mac_ctx, peer_addr, &beacon_params,
1717 		pe_session);
1718 
1719 	/*
1720 	 * Populate Do11capabilities after updating session with
1721 	 * Assos req details
1722 	 */
1723 	populate_dot11f_capabilities(mac_ctx, &frm.Capabilities, pe_session);
1724 
1725 	beacon_params.bss_idx = pe_session->vdev_id;
1726 
1727 	/* Send message to HAL about beacon parameter change. */
1728 	if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)
1729 	    && beacon_params.paramChangeBitmap) {
1730 		sch_set_fixed_beacon_fields(mac_ctx, pe_session);
1731 		lim_send_beacon_params(mac_ctx, &beacon_params, pe_session);
1732 	}
1733 
1734 	lim_obss_send_detection_cfg(mac_ctx, pe_session, false);
1735 
1736 	add_ie = qdf_mem_malloc(WNI_CFG_ASSOC_RSP_ADDNIE_DATA_LEN);
1737 	if (!add_ie) {
1738 		pe_err("memory alloc failed for add_ie");
1739 		return;
1740 	}
1741 
1742 	if (assoc_req) {
1743 		addn_ie_len = pe_session->add_ie_params.assocRespDataLen;
1744 
1745 		/* Nonzero length indicates Assoc rsp IE available */
1746 		if (addn_ie_len > 0 &&
1747 		    addn_ie_len <= WNI_CFG_ASSOC_RSP_ADDNIE_DATA_LEN &&
1748 		    (bytes + addn_ie_len) <= SIR_MAX_PACKET_SIZE) {
1749 			qdf_mem_copy(add_ie,
1750 				pe_session->add_ie_params.assocRespData_buff,
1751 				pe_session->add_ie_params.assocRespDataLen);
1752 
1753 			qdf_mem_zero((uint8_t *) &extracted_ext_cap,
1754 				    sizeof(extracted_ext_cap));
1755 
1756 			stripoff_len = addn_ie_len;
1757 			sir_status =
1758 				lim_strip_extcap_update_struct
1759 					(mac_ctx, &add_ie[0], &stripoff_len,
1760 					&extracted_ext_cap);
1761 			if (QDF_STATUS_SUCCESS != sir_status) {
1762 				pe_debug("strip off extcap IE failed");
1763 			} else {
1764 				addn_ie_len = stripoff_len;
1765 				extracted_flag = true;
1766 			}
1767 			bytes = bytes + addn_ie_len;
1768 		}
1769 	}
1770 
1771 	/*
1772 	 * Extcap IE now support variable length, merge Extcap IE from addn_ie
1773 	 * may change the frame size. Therefore, MUST merge ExtCap IE before
1774 	 * dot11f get packed payload size.
1775 	 */
1776 	if (extracted_flag)
1777 		lim_merge_extcap_struct(&(frm.ExtCap), &extracted_ext_cap,
1778 					true);
1779 	populate_dot11f_bcn_prot_extcaps(mac_ctx, pe_session, &(frm.ExtCap));
1780 	if (sta && lim_is_sta_eht_capable(sta) &&
1781 	    lim_is_mlo_conn(pe_session, sta) &&
1782 	    lim_is_session_eht_capable(pe_session) &&
1783 	    wlan_vdev_mlme_is_mlo_ap(pe_session->vdev) &&
1784 	    (status_code != STATUS_ASSOC_REJECTED_TEMPORARILY)) {
1785 		pe_debug("Populate mlo IEs");
1786 		mlo_ie_len = lim_send_assoc_rsp_mgmt_frame_mlo(mac_ctx,
1787 							       pe_session,
1788 							       sta, &frm);
1789 	}
1790 
1791 	/* Allocate a buffer for this frame: */
1792 	status = dot11f_get_packed_assoc_response_size(mac_ctx, &frm, &payload);
1793 	if (DOT11F_FAILED(status)) {
1794 		pe_err("get Association Response size failure (0x%08x)",
1795 			status);
1796 		goto error;
1797 	} else if (DOT11F_WARNED(status)) {
1798 		pe_warn("get Association Response size warning (0x%08x)",
1799 			status);
1800 	}
1801 
1802 	bytes += sizeof(tSirMacMgmtHdr) + payload + mlo_ie_len;
1803 
1804 	if (sta) {
1805 		bytes += sta->mlmStaContext.owe_ie_len;
1806 		bytes += sta->mlmStaContext.ft_ie_len;
1807 	}
1808 	qdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame,
1809 				      (void **)&packet);
1810 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1811 		pe_err("cds_packet_alloc failed");
1812 		goto error;
1813 	}
1814 	/* Paranoia: */
1815 	qdf_mem_zero(frame, bytes);
1816 
1817 	/* Next, we fill out the buffer descriptor: */
1818 	lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME,
1819 		(LIM_ASSOC == subtype) ?
1820 			SIR_MAC_MGMT_ASSOC_RSP : SIR_MAC_MGMT_REASSOC_RSP,
1821 			peer_addr,
1822 			pe_session->self_mac_addr);
1823 	mac_hdr = (tpSirMacMgmtHdr) frame;
1824 
1825 	sir_copy_mac_addr(mac_hdr->bssId, pe_session->bssId);
1826 
1827 	status = dot11f_pack_assoc_response(mac_ctx, &frm,
1828 					     frame + sizeof(tSirMacMgmtHdr),
1829 					     payload, &payload);
1830 	if (DOT11F_FAILED(status)) {
1831 		pe_err("Association Response pack failure(0x%08x)",
1832 			status);
1833 		cds_packet_free((void *)packet);
1834 		goto error;
1835 	} else if (DOT11F_WARNED(status)) {
1836 		pe_warn("Association Response pack warning (0x%08x)",
1837 			status);
1838 	}
1839 
1840 	/* Strip EHT operation and EHT capabilities IEs */
1841 	if (lim_is_session_eht_capable(pe_session)) {
1842 		ie_buf_size = payload - WLAN_ASSOC_RSP_IES_OFFSET;
1843 		eht_op_ie = qdf_mem_malloc(WLAN_MAX_IE_LEN + 2);
1844 		if (!eht_op_ie) {
1845 			pe_err("malloc failed for eht_op_ie");
1846 			cds_packet_free((void *)packet);
1847 			goto error;
1848 		}
1849 
1850 		qdf_status = lim_strip_eht_op_ie(mac_ctx, frame +
1851 						 sizeof(tSirMacMgmtHdr) +
1852 						 WLAN_ASSOC_RSP_IES_OFFSET,
1853 						 &ie_buf_size, eht_op_ie);
1854 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
1855 			pe_err("Failed to strip EHT op IE");
1856 			qdf_mem_free(eht_cap_ie);
1857 			cds_packet_free((void *)packet);
1858 			cds_packet_free((void *)packet);
1859 		}
1860 
1861 		lim_ieee80211_pack_ehtop(eht_op_ie, frm.eht_op,
1862 					 frm.VHTOperation,
1863 					 frm.he_op,
1864 					 frm.HTInfo);
1865 		eht_op_ie_len = eht_op_ie[1] + 2;
1866 
1867 		/* Copy the EHT operation IE to the end of the frame */
1868 		qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) +
1869 			     WLAN_ASSOC_RSP_IES_OFFSET + ie_buf_size,
1870 			     eht_op_ie, eht_op_ie_len);
1871 		qdf_mem_free(eht_op_ie);
1872 		bytes = bytes - payload;
1873 		payload = ie_buf_size + WLAN_ASSOC_RSP_IES_OFFSET +
1874 			  eht_op_ie_len;
1875 		bytes = bytes + payload;
1876 
1877 		ie_buf_size = payload - WLAN_ASSOC_RSP_IES_OFFSET;
1878 		eht_cap_ie = qdf_mem_malloc(WLAN_MAX_IE_LEN + 2);
1879 		if (!eht_cap_ie) {
1880 			pe_err("malloc failed for eht_cap_ie");
1881 			cds_packet_free((void *)packet);
1882 			goto error;
1883 		}
1884 
1885 		qdf_status = lim_strip_eht_cap_ie(mac_ctx, frame +
1886 						  sizeof(tSirMacMgmtHdr) +
1887 						  WLAN_ASSOC_RSP_IES_OFFSET,
1888 						  &ie_buf_size, eht_cap_ie);
1889 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
1890 			pe_err("Failed to strip EHT cap IE");
1891 			qdf_mem_free(eht_cap_ie);
1892 			cds_packet_free((void *)packet);
1893 			goto error;
1894 		}
1895 
1896 		is_band_2g =
1897 			WLAN_REG_IS_24GHZ_CH_FREQ(pe_session->curr_op_freq);
1898 		lim_ieee80211_pack_ehtcap(eht_cap_ie, frm.eht_cap, frm.he_cap,
1899 					  is_band_2g);
1900 
1901 		eht_cap_ie_len = eht_cap_ie[1] + 2;
1902 
1903 		/* Copy the EHT capability IE to the end of the frame */
1904 		qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) +
1905 			     WLAN_ASSOC_RSP_IES_OFFSET + ie_buf_size,
1906 			     eht_cap_ie, eht_cap_ie_len);
1907 		qdf_mem_free(eht_cap_ie);
1908 		bytes = bytes - payload;
1909 		payload = ie_buf_size + WLAN_ASSOC_RSP_IES_OFFSET +
1910 			  eht_cap_ie_len;
1911 		bytes = bytes + payload;
1912 	}
1913 
1914 	if (addn_ie_len && addn_ie_len <= WNI_CFG_ASSOC_RSP_ADDNIE_DATA_LEN) {
1915 		qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
1916 			     &add_ie[0], addn_ie_len);
1917 		payload += addn_ie_len;
1918 	}
1919 
1920 	if (sta && sta->mlmStaContext.owe_ie_len) {
1921 		qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
1922 			     sta->mlmStaContext.owe_ie,
1923 			     sta->mlmStaContext.owe_ie_len);
1924 		payload += sta->mlmStaContext.owe_ie_len;
1925 	}
1926 
1927 	if (sta && sta->mlmStaContext.ft_ie_len) {
1928 		qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
1929 			     sta->mlmStaContext.ft_ie,
1930 			     sta->mlmStaContext.ft_ie_len);
1931 		payload += sta->mlmStaContext.ft_ie_len;
1932 	}
1933 
1934 	if (sta && mlo_ie_len) {
1935 		qdf_status = lim_fill_complete_mlo_ie(pe_session, mlo_ie_len,
1936 				      frame + sizeof(tSirMacMgmtHdr) + payload);
1937 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
1938 			pe_debug("assemble ml ie error");
1939 			mlo_ie_len = 0;
1940 		}
1941 		payload += mlo_ie_len;
1942 	}
1943 
1944 	pe_nofl_debug("Assoc rsp TX: vdev %d subtype %d to "QDF_MAC_ADDR_FMT" seq num %d status %d aid %d addn_ie_len %d ht %d vht %d vendor vht %d he %d eht %d",
1945 		      pe_session->vdev_id, subtype,
1946 		      QDF_MAC_ADDR_REF(mac_hdr->da),
1947 		      mac_ctx->mgmtSeqNum, status_code, aid, addn_ie_len,
1948 		      frm.HTCaps.present, frm.VHTCaps.present,
1949 		      frm.vendor_vht_ie.present, frm.he_cap.present,
1950 		      frm.eht_cap.present);
1951 
1952 	if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) ||
1953 	    pe_session->opmode == QDF_P2P_CLIENT_MODE ||
1954 	    pe_session->opmode == QDF_P2P_GO_MODE)
1955 		tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
1956 
1957 	ie.ptr = frame + sizeof(tSirMacMgmtHdr) + WLAN_ASSOC_RSP_IES_OFFSET;
1958 	ie.len = payload - WLAN_ASSOC_RSP_IES_OFFSET;
1959 
1960 	mlme_set_peer_assoc_rsp_ie(mac_ctx->psoc, peer_addr, &ie);
1961 
1962 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
1963 			 pe_session->peSessionId, mac_hdr->fc.subType));
1964 	lim_diag_mgmt_tx_event_report(mac_ctx, mac_hdr,
1965 				      pe_session, QDF_STATUS_SUCCESS, status_code);
1966 	/* Queue Association Response frame in high priority WQ */
1967 	if (tx_complete)
1968 		qdf_status = wma_tx_frameWithTxComplete(
1969 				mac_ctx, packet, (uint16_t)bytes,
1970 				TXRX_FRM_802_11_MGMT,
1971 				ANI_TXDIR_TODS,
1972 				7, lim_tx_complete, frame,
1973 				lim_assoc_rsp_tx_complete, tx_flag,
1974 				sme_session, false, 0, RATEID_DEFAULT, 0, 0);
1975 	else
1976 		qdf_status = wma_tx_frame(
1977 				mac_ctx, packet, (uint16_t)bytes,
1978 				TXRX_FRM_802_11_MGMT,
1979 				ANI_TXDIR_TODS,
1980 				7, lim_tx_complete, frame, tx_flag,
1981 				sme_session, 0, RATEID_DEFAULT, 0);
1982 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
1983 			 pe_session->peSessionId, qdf_status));
1984 
1985 	/* Pkt will be freed up by the callback */
1986 	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
1987 		pe_err("Could not Send Re/AssocRsp, retCode=%X",
1988 			qdf_status);
1989 
1990 	/*
1991 	 * update the ANI peer station count.
1992 	 * FIXME_PROTECTION : take care of different type of station
1993 	 * counter inside this function.
1994 	 */
1995 	lim_util_count_sta_add(mac_ctx, sta, pe_session);
1996 
1997 error:
1998 	qdf_mem_free(add_ie);
1999 }
2000 
2001 void
2002 lim_send_delts_req_action_frame(struct mac_context *mac,
2003 				tSirMacAddr peer,
2004 				uint8_t wmmTspecPresent,
2005 				struct mac_ts_info *pTsinfo,
2006 				struct mac_tspec_ie *pTspecIe,
2007 				struct pe_session *pe_session)
2008 {
2009 	uint8_t *pFrame;
2010 	tpSirMacMgmtHdr pMacHdr;
2011 	tDot11fDelTS DelTS;
2012 	tDot11fWMMDelTS WMMDelTS;
2013 	uint32_t nBytes, nPayload, nStatus;
2014 	void *pPacket;
2015 	QDF_STATUS qdf_status;
2016 	uint8_t txFlag = 0;
2017 	uint8_t smeSessionId = 0;
2018 
2019 	if (!pe_session)
2020 		return;
2021 
2022 	smeSessionId = pe_session->smeSessionId;
2023 
2024 	if (!wmmTspecPresent) {
2025 		qdf_mem_zero((uint8_t *) &DelTS, sizeof(DelTS));
2026 
2027 		DelTS.Category.category = ACTION_CATEGORY_QOS;
2028 		DelTS.Action.action = QOS_DEL_TS_REQ;
2029 		populate_dot11f_ts_info(pTsinfo, &DelTS.TSInfo);
2030 
2031 		nStatus = dot11f_get_packed_del_ts_size(mac, &DelTS, &nPayload);
2032 		if (DOT11F_FAILED(nStatus)) {
2033 			pe_err("Failed to calculate the packed size for a Del TS (0x%08x)",
2034 			       nStatus);
2035 			/* We'll fall back on the worst case scenario: */
2036 			nPayload = sizeof(tDot11fDelTS);
2037 		} else if (DOT11F_WARNED(nStatus)) {
2038 			pe_warn("There were warnings while calculating the packed size for a Del TS (0x%08x)",
2039 				nStatus);
2040 		}
2041 	} else {
2042 		qdf_mem_zero((uint8_t *) &WMMDelTS, sizeof(WMMDelTS));
2043 
2044 		WMMDelTS.Category.category = ACTION_CATEGORY_WMM;
2045 		WMMDelTS.Action.action = QOS_DEL_TS_REQ;
2046 		WMMDelTS.DialogToken.token = 0;
2047 		WMMDelTS.StatusCode.statusCode = 0;
2048 		populate_dot11f_wmmtspec(pTspecIe, &WMMDelTS.WMMTSPEC);
2049 		nStatus =
2050 			dot11f_get_packed_wmm_del_ts_size(mac, &WMMDelTS, &nPayload);
2051 		if (DOT11F_FAILED(nStatus)) {
2052 			pe_err("Failed to calculate the packed size for a WMM Del TS (0x%08x)",
2053 			       nStatus);
2054 			/* We'll fall back on the worst case scenario: */
2055 			nPayload = sizeof(tDot11fDelTS);
2056 		} else if (DOT11F_WARNED(nStatus)) {
2057 			pe_warn("There were warnings while calculating the packed size for a WMM Del TS (0x%08x)",
2058 				nStatus);
2059 		}
2060 	}
2061 
2062 	nBytes = nPayload + sizeof(tSirMacMgmtHdr);
2063 
2064 	qdf_status =
2065 		cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
2066 				 (void **)&pPacket);
2067 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2068 		pe_err("Failed to allocate %d bytes for an Add TS Response",
2069 			nBytes);
2070 		return;
2071 	}
2072 	/* Paranoia: */
2073 	qdf_mem_zero(pFrame, nBytes);
2074 
2075 	/* Next, we fill out the buffer descriptor: */
2076 	lim_populate_mac_header(mac, pFrame, SIR_MAC_MGMT_FRAME,
2077 		SIR_MAC_MGMT_ACTION, peer, pe_session->self_mac_addr);
2078 	pMacHdr = (tpSirMacMgmtHdr) pFrame;
2079 
2080 	sir_copy_mac_addr(pMacHdr->bssId, pe_session->bssId);
2081 
2082 	lim_set_protected_bit(mac, pe_session, peer, pMacHdr);
2083 
2084 	/* That done, pack the struct: */
2085 	if (!wmmTspecPresent) {
2086 		nStatus = dot11f_pack_del_ts(mac, &DelTS,
2087 					     pFrame + sizeof(tSirMacMgmtHdr),
2088 					     nPayload, &nPayload);
2089 		if (DOT11F_FAILED(nStatus)) {
2090 			pe_err("Failed to pack a Del TS frame (0x%08x)",
2091 				nStatus);
2092 			cds_packet_free((void *)pPacket);
2093 			return; /* allocated! */
2094 		} else if (DOT11F_WARNED(nStatus)) {
2095 			pe_warn("There were warnings while packing a Del TS frame (0x%08x)",
2096 				nStatus);
2097 		}
2098 	} else {
2099 		nStatus = dot11f_pack_wmm_del_ts(mac, &WMMDelTS,
2100 						 pFrame + sizeof(tSirMacMgmtHdr),
2101 						 nPayload, &nPayload);
2102 		if (DOT11F_FAILED(nStatus)) {
2103 			pe_err("Failed to pack a WMM Del TS frame (0x%08x)",
2104 				nStatus);
2105 			cds_packet_free((void *)pPacket);
2106 			return; /* allocated! */
2107 		} else if (DOT11F_WARNED(nStatus)) {
2108 			pe_warn("There were warnings while packing a WMM Del TS frame (0x%08x)",
2109 				nStatus);
2110 		}
2111 	}
2112 
2113 	pe_debug("Sending DELTS REQ (size %d) to "QDF_MAC_ADDR_FMT, nBytes,
2114 		 QDF_MAC_ADDR_REF(pMacHdr->da));
2115 
2116 	if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) ||
2117 	    pe_session->opmode == QDF_P2P_CLIENT_MODE ||
2118 	    pe_session->opmode == QDF_P2P_GO_MODE)
2119 		txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
2120 
2121 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
2122 			 pe_session->peSessionId, pMacHdr->fc.subType));
2123 	lim_diag_mgmt_tx_event_report(mac, pMacHdr,
2124 				      pe_session, QDF_STATUS_SUCCESS,
2125 				      QDF_STATUS_SUCCESS);
2126 	qdf_status = wma_tx_frame(mac, pPacket, (uint16_t) nBytes,
2127 				TXRX_FRM_802_11_MGMT,
2128 				ANI_TXDIR_TODS,
2129 				7, lim_tx_complete, pFrame, txFlag,
2130 				smeSessionId, 0, RATEID_DEFAULT, 0);
2131 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
2132 			 pe_session->peSessionId, qdf_status));
2133 	/* Pkt will be freed up by the callback */
2134 	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
2135 		pe_err("Failed to send Del TS (%X)!", qdf_status);
2136 
2137 } /* End lim_send_delts_req_action_frame. */
2138 
2139 #define SAE_AUTH_SEQ_NUM_OFFSET         2
2140 #define SAE_AUTH_STATUS_CODE_OFFSET     4
2141 #define SAE_AUTH_MESSAGE_TYPE_OFFSET    6
2142 #define SAE_FRAME_LENGTH \
2143 	(sizeof(struct wlan_frame_hdr) + SAE_AUTH_MESSAGE_TYPE_OFFSET)
2144 
2145 /**
2146  * wlan_send_tx_complete_event() - Fill mgmt params
2147  * @mac: Pointer to mac context
2148  * @buf: skb buffer
2149  * @params: Pointer to wmi_mgmt_params
2150  * @tx_complete: Sent status
2151  * @tag: wlan main tag
2152  *
2153  * Function is used to send connectivity log event for mgmt ack status
2154  *
2155  * Return None
2156  */
2157 
2158 static void wlan_send_tx_complete_event(struct mac_context *mac, qdf_nbuf_t buf,
2159 					struct wmi_mgmt_params *params,
2160 					uint8_t tx_complete,
2161 					enum wlan_main_tag tag)
2162 {
2163 	struct pe_session *pe_session = NULL;
2164 	struct wlan_frame_hdr *mac_hdr;
2165 	enum qdf_dp_tx_rx_status qdf_tx_complete;
2166 	uint8_t *frm_body;
2167 	uint16_t reason_code = 0;
2168 
2169 	pe_session = pe_find_session_by_vdev_id(mac, params->vdev_id);
2170 	if (pe_session && pe_session->opmode == QDF_STA_MODE) {
2171 		if (qdf_nbuf_len(buf) < sizeof(struct wlan_frame_hdr) + 2)
2172 			return;
2173 
2174 		mac_hdr = (struct wlan_frame_hdr *)qdf_nbuf_data(buf);
2175 		frm_body = (uint8_t *)mac_hdr + sizeof(struct wlan_frame_hdr);
2176 
2177 		if (tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK)
2178 			qdf_tx_complete = QDF_TX_RX_STATUS_OK;
2179 		else if (tx_complete  == WMI_MGMT_TX_COMP_TYPE_DISCARD)
2180 			qdf_tx_complete = QDF_TX_RX_STATUS_FW_DISCARD;
2181 		else
2182 			qdf_tx_complete = QDF_TX_RX_STATUS_NO_ACK;
2183 
2184 		if (tag == WLAN_AUTH_REQ) {
2185 			uint16_t algo = 0, type = 0, seq = 0, status = 0;
2186 
2187 			if (qdf_nbuf_len(buf) < SAE_FRAME_LENGTH)
2188 				return;
2189 
2190 			algo = *(uint16_t *)frm_body;
2191 			seq = *(uint16_t *)(frm_body + SAE_AUTH_SEQ_NUM_OFFSET);
2192 			status =
2193 			*(uint16_t *)(frm_body + SAE_AUTH_STATUS_CODE_OFFSET);
2194 
2195 			if (algo == eSIR_AUTH_TYPE_SAE)
2196 				type = seq;
2197 
2198 			wlan_connectivity_mgmt_event(
2199 					mac->psoc,
2200 					mac_hdr, params->vdev_id, status,
2201 					qdf_tx_complete, mac->lim.bss_rssi,
2202 					algo, type, seq, 0, WLAN_AUTH_REQ);
2203 			return;
2204 		}
2205 
2206 		if (tag == WLAN_DEAUTH_TX || tag == WLAN_DISASSOC_TX)
2207 			reason_code = pe_session->deauth_disassoc_rc;
2208 
2209 		wlan_connectivity_mgmt_event(
2210 					mac->psoc,
2211 					mac_hdr, params->vdev_id, reason_code,
2212 					qdf_tx_complete, mac->lim.bss_rssi,
2213 					0, 0, 0, 0, tag);
2214 	}
2215 }
2216 
2217 /**
2218  * lim_assoc_tx_complete_cnf()- Confirmation for assoc sent over the air
2219  * @context: pointer to global mac
2220  * @buf: buffer
2221  * @tx_complete: Sent status
2222  * @params: tx completion params
2223  *
2224  * Return: This returns QDF_STATUS
2225  */
2226 
2227 static QDF_STATUS lim_assoc_tx_complete_cnf(void *context,
2228 					   qdf_nbuf_t buf,
2229 					   uint32_t tx_complete,
2230 					   void *params)
2231 {
2232 	uint16_t assoc_ack_status;
2233 	uint16_t reason_code;
2234 	struct mac_context *mac_ctx = (struct mac_context *)context;
2235 
2236 	pe_nofl_rl_info("Assoc req TX: %s (%d)",
2237 			(tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK) ?
2238 			"success" : "fail", tx_complete);
2239 
2240 	if (params)
2241 		wlan_send_tx_complete_event(context, buf, params, tx_complete,
2242 					    WLAN_ASSOC_REQ);
2243 
2244 	if (tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK) {
2245 		assoc_ack_status = ACKED;
2246 		reason_code = QDF_STATUS_SUCCESS;
2247 		mac_ctx->assoc_ack_status = LIM_ACK_RCD_SUCCESS;
2248 	} else if (tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_NO_ACK) {
2249 		assoc_ack_status = NOT_ACKED;
2250 		reason_code = QDF_STATUS_E_FAILURE;
2251 		mac_ctx->assoc_ack_status = LIM_ACK_RCD_FAILURE;
2252 	} else {
2253 		assoc_ack_status = SENT_FAIL;
2254 		reason_code = QDF_STATUS_E_FAILURE;
2255 		mac_ctx->assoc_ack_status = LIM_TX_FAILED;
2256 	}
2257 
2258 	if (buf)
2259 		qdf_nbuf_free(buf);
2260 
2261 	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_ASSOC_ACK_EVENT,
2262 			NULL, assoc_ack_status, reason_code);
2263 	return QDF_STATUS_SUCCESS;
2264 }
2265 
2266 #ifdef WLAN_ADAPTIVE_11R
2267 /**
2268  * lim_fill_adaptive_11r_ie() - Populate the Vendor specific adaptive 11r
2269  * IE to association request frame
2270  * @pe_session: pointer to PE session
2271  * @ie_buf: buffer to which Adaptive 11r IE will be copied
2272  * @ie_len: length of the Adaptive 11r Vendor specific IE
2273  *
2274  * Return QDF_STATUS
2275  */
2276 static QDF_STATUS lim_fill_adaptive_11r_ie(struct pe_session *pe_session,
2277 					   uint8_t **ie_buf, uint8_t *ie_len)
2278 {
2279 	uint8_t *buf = NULL, *adaptive_11r_ie = NULL;
2280 
2281 	if (!pe_session->is_adaptive_11r_connection)
2282 		return QDF_STATUS_SUCCESS;
2283 
2284 	/*
2285 	 * Vendor specific Adaptive 11r IE to be advertised in Assoc
2286 	 * req:
2287 	 * Type     0xDD
2288 	 * Length   0x0B
2289 	 * OUI      0x00 0x00 0x0F
2290 	 * Type     0x22
2291 	 * subtype  0x00
2292 	 * Version  0x01
2293 	 * Length   0x04
2294 	 * Data     0x00 00 00 01(0th bit is 1 means adaptive 11r is
2295 	 * supported)
2296 	 */
2297 	adaptive_11r_ie = qdf_mem_malloc(ADAPTIVE_11R_STA_IE_LEN + 2);
2298 	if (!adaptive_11r_ie)
2299 		return QDF_STATUS_E_FAILURE;
2300 
2301 	/* Fill the Vendor IE Type (0xDD) */
2302 	buf = adaptive_11r_ie;
2303 	*buf = WLAN_ELEMID_VENDOR;
2304 	buf++;
2305 
2306 	/* Fill the Vendor IE length (0x0B) */
2307 	*buf = ADAPTIVE_11R_STA_IE_LEN;
2308 	buf++;
2309 
2310 	/*
2311 	 * Fill the Adaptive 11r Vendor specific OUI(0x00 0x00 0x0F 0x22)
2312 	 */
2313 	qdf_mem_copy(buf, ADAPTIVE_11R_STA_OUI, ADAPTIVE_11R_OUI_LEN);
2314 	buf += ADAPTIVE_11R_OUI_LEN;
2315 
2316 	/* Fill Adaptive 11r Vendor specific Subtype (0x00) */
2317 	*buf = ADAPTIVE_11R_OUI_SUBTYPE;
2318 	buf++;
2319 
2320 	/* Fill Adaptive 11r Version (0x01) */
2321 	*buf = ADAPTIVE_11R_OUI_VERSION;
2322 	buf++;
2323 
2324 	/* Fill Adaptive 11r IE Data length (0x04) */
2325 	*buf = ADAPTIVE_11R_DATA_LEN;
2326 	buf++;
2327 
2328 	/* Fill Adaptive 11r IE Data (0x00 0x00 0x00 0x01) */
2329 	qdf_mem_copy(buf, ADAPTIVE_11R_OUI_DATA, ADAPTIVE_11R_DATA_LEN);
2330 
2331 	*ie_len = ADAPTIVE_11R_STA_IE_LEN + 2;
2332 	*ie_buf = adaptive_11r_ie;
2333 
2334 	return QDF_STATUS_SUCCESS;
2335 }
2336 
2337 #else
2338 static inline
2339 QDF_STATUS lim_fill_adaptive_11r_ie(struct pe_session *pe_session,
2340 				    uint8_t **ie_buf, uint8_t *ie_len)
2341 {
2342 	return QDF_STATUS_SUCCESS;
2343 }
2344 #endif
2345 
2346 /**
2347  * lim_send_assoc_req_mgmt_frame() - Send association request
2348  * @mac_ctx: Handle to MAC context
2349  * @mlm_assoc_req: Association request information
2350  * @pe_session: PE session information
2351  *
2352  * Builds and transmits association request frame to AP.
2353  *
2354  * Return: Void
2355  */
2356 void
2357 lim_send_assoc_req_mgmt_frame(struct mac_context *mac_ctx,
2358 			      tLimMlmAssocReq *mlm_assoc_req,
2359 			      struct pe_session *pe_session)
2360 {
2361 	int ret;
2362 	tDot11fAssocRequest *frm;
2363 	uint16_t caps;
2364 	uint8_t *frame, *rsnx_ie = NULL;
2365 	QDF_STATUS sir_status;
2366 	tLimMlmAssocCnf assoc_cnf;
2367 	uint32_t bytes = 0, payload, status;
2368 	uint8_t qos_enabled, wme_enabled, wsm_enabled;
2369 	void *packet;
2370 	QDF_STATUS qdf_status;
2371 	uint16_t add_ie_len, current_len = 0, vendor_ie_len = 0;
2372 	uint8_t *add_ie = NULL, *mscs_ext_ie = NULL;
2373 	const uint8_t *wps_ie = NULL;
2374 	uint8_t power_caps = false;
2375 	uint8_t tx_flag = 0;
2376 	uint8_t vdev_id = 0;
2377 	bool vht_enabled = false;
2378 	tDot11fIEExtCap extr_ext_cap;
2379 	bool extr_ext_flag = true, is_open_auth = false;
2380 	tpSirMacMgmtHdr mac_hdr;
2381 	uint32_t ie_offset = 0;
2382 	uint8_t *p_ext_cap = NULL;
2383 	tDot11fIEExtCap bcn_ext_cap;
2384 	uint8_t *bcn_ie = NULL;
2385 	uint32_t bcn_ie_len = 0;
2386 	uint32_t aes_block_size_len = 0;
2387 	enum rateid min_rid = RATEID_DEFAULT;
2388 	uint8_t *mbo_ie = NULL, *adaptive_11r_ie = NULL, *vendor_ies = NULL;
2389 	uint8_t mbo_ie_len = 0, adaptive_11r_ie_len = 0, rsnx_ie_len = 0;
2390 	uint8_t mscs_ext_ie_len = 0;
2391 	uint8_t *eht_cap_ie = NULL, eht_cap_ie_len = 0;
2392 	bool bss_mfp_capable, frag_ie_present = false;
2393 	int8_t peer_rssi = 0;
2394 	bool is_band_2g;
2395 	uint16_t ie_buf_size;
2396 	uint16_t mlo_ie_len, fils_hlp_ie_len = 0;
2397 	uint8_t *fils_hlp_ie = NULL;
2398 	struct cm_roam_values_copy mdie_cfg = {0};
2399 
2400 	if (!pe_session) {
2401 		pe_err("pe_session is NULL");
2402 		qdf_mem_free(mlm_assoc_req);
2403 		return;
2404 	}
2405 
2406 	vdev_id = pe_session->vdev_id;
2407 
2408 	/* check this early to avoid unnecessary operation */
2409 	if (!pe_session->lim_join_req) {
2410 		pe_err("pe_session->lim_join_req is NULL");
2411 		qdf_mem_free(mlm_assoc_req);
2412 		return;
2413 	}
2414 	add_ie_len = pe_session->lim_join_req->addIEAssoc.length;
2415 	if (add_ie_len) {
2416 		add_ie = qdf_mem_malloc(add_ie_len);
2417 		if (!add_ie) {
2418 			qdf_mem_free(mlm_assoc_req);
2419 			return;
2420 		}
2421 		/*
2422 		 * copy the additional ie to local, as this func modify
2423 		 * the IE, these IE will be required in assoc/re-assoc
2424 		 * retry. So do not modify the original IE.
2425 		 */
2426 		qdf_mem_copy(add_ie, pe_session->lim_join_req->addIEAssoc.addIEdata,
2427 			     add_ie_len);
2428 
2429 	}
2430 
2431 	frm = qdf_mem_malloc(sizeof(tDot11fAssocRequest));
2432 	if (!frm) {
2433 		qdf_mem_free(mlm_assoc_req);
2434 		qdf_mem_free(add_ie);
2435 		return;
2436 	}
2437 	qdf_mem_zero((uint8_t *) frm, sizeof(tDot11fAssocRequest));
2438 
2439 	if (add_ie_len && pe_session->is_ext_caps_present) {
2440 		qdf_mem_zero((uint8_t *) &extr_ext_cap,
2441 				sizeof(tDot11fIEExtCap));
2442 		sir_status = lim_strip_extcap_update_struct(mac_ctx,
2443 					add_ie, &add_ie_len, &extr_ext_cap);
2444 		if (QDF_STATUS_SUCCESS != sir_status) {
2445 			extr_ext_flag = false;
2446 			pe_debug("Unable to Stripoff ExtCap IE from Assoc Req");
2447 		} else {
2448 			struct s_ext_cap *p_ext_cap = (struct s_ext_cap *)
2449 							extr_ext_cap.bytes;
2450 
2451 			if (p_ext_cap->interworking_service)
2452 				p_ext_cap->qos_map = 1;
2453 			extr_ext_cap.num_bytes =
2454 				lim_compute_ext_cap_ie_length(&extr_ext_cap);
2455 			extr_ext_flag = (extr_ext_cap.num_bytes > 0);
2456 		}
2457 	} else {
2458 		extr_ext_flag = false;
2459 	}
2460 
2461 	caps = mlm_assoc_req->capabilityInfo;
2462 #if defined(FEATURE_WLAN_WAPI)
2463 	/*
2464 	 * According to WAPI standard:
2465 	 * 7.3.1.4 Capability Information field
2466 	 * In WAPI, non-AP STAs within an ESS set the Privacy subfield to 0
2467 	 * in transmitted Association or Reassociation management frames.
2468 	 * APs ignore the Privacy subfield within received Association and
2469 	 * Reassociation management frames.
2470 	 */
2471 	if (pe_session->encryptType == eSIR_ED_WPI)
2472 		((tSirMacCapabilityInfo *) &caps)->privacy = 0;
2473 #endif
2474 	swap_bit_field16(caps, (uint16_t *) &frm->Capabilities);
2475 
2476 	frm->ListenInterval.interval = mlm_assoc_req->listenInterval;
2477 
2478 	populate_dot11f_ssid2(pe_session, &frm->SSID);
2479 	populate_dot11f_supp_rates(mac_ctx, POPULATE_DOT11F_RATES_OPERATIONAL,
2480 		&frm->SuppRates, pe_session);
2481 
2482 	qos_enabled = (pe_session->limQosEnabled) &&
2483 		      SIR_MAC_GET_QOS(pe_session->limCurrentBssCaps);
2484 
2485 	wme_enabled = (pe_session->limWmeEnabled) &&
2486 		      LIM_BSS_CAPS_GET(WME, pe_session->limCurrentBssQosCaps);
2487 
2488 	/* We prefer .11e asociations: */
2489 	if (qos_enabled)
2490 		wme_enabled = false;
2491 
2492 	wsm_enabled = (pe_session->limWsmEnabled) && wme_enabled &&
2493 		      LIM_BSS_CAPS_GET(WSM, pe_session->limCurrentBssQosCaps);
2494 
2495 	if (pe_session->lim11hEnable &&
2496 	    pe_session->spectrumMgtEnabled == true) {
2497 		power_caps = true;
2498 
2499 		populate_dot11f_power_caps(mac_ctx, &frm->PowerCaps,
2500 			LIM_ASSOC, pe_session);
2501 		populate_dot11f_supp_channels(mac_ctx, &frm->SuppChannels,
2502 			LIM_ASSOC, pe_session);
2503 
2504 	}
2505 	if (mac_ctx->rrm.rrmPEContext.rrmEnable &&
2506 	    SIR_MAC_GET_RRM(pe_session->limCurrentBssCaps)) {
2507 		if (power_caps == false) {
2508 			power_caps = true;
2509 			populate_dot11f_power_caps(mac_ctx, &frm->PowerCaps,
2510 				LIM_ASSOC, pe_session);
2511 		}
2512 	}
2513 	if (qos_enabled)
2514 		populate_dot11f_qos_caps_station(mac_ctx, pe_session,
2515 						&frm->QOSCapsStation);
2516 
2517 	populate_dot11f_ext_supp_rates(mac_ctx,
2518 		POPULATE_DOT11F_RATES_OPERATIONAL, &frm->ExtSuppRates,
2519 		pe_session);
2520 
2521 	if (mac_ctx->rrm.rrmPEContext.rrmEnable &&
2522 	    SIR_MAC_GET_RRM(pe_session->limCurrentBssCaps))
2523 		populate_dot11f_rrm_ie(mac_ctx, &frm->RRMEnabledCap,
2524 			pe_session);
2525 
2526 	/*
2527 	 * The join request *should* contain zero or one of the WPA and RSN
2528 	 * IEs.  The payload send along with the request is a
2529 	 * 'struct join_req'; the IE portion is held inside a 'tSirRSNie':
2530 	 *     typedef struct sSirRSNie
2531 	 *     {
2532 	 *         uint16_t       length;
2533 	 *         uint8_t        rsnIEdata[WLAN_MAX_IE_LEN+2];
2534 	 *     } tSirRSNie, *tpSirRSNie;
2535 	 * So, we should be able to make the following two calls harmlessly,
2536 	 * since they do nothing if they don't find the given IE in the
2537 	 * bytestream with which they're provided.
2538 	 * The net effect of this will be to faithfully transmit whatever
2539 	 * security IE is in the join request.
2540 	 * However, if we're associating for the purpose of WPS
2541 	 * enrollment, and we've been configured to indicate that by
2542 	 * eliding the WPA or RSN IE, we just skip this:
2543 	 */
2544 	if (add_ie_len && add_ie)
2545 		wps_ie = limGetWscIEPtr(mac_ctx, add_ie, add_ie_len);
2546 
2547 	if (!wps_ie) {
2548 		populate_dot11f_rsn_opaque(mac_ctx,
2549 					   &pe_session->lim_join_req->rsnIE,
2550 					   &frm->RSNOpaque);
2551 		populate_dot11f_wpa_opaque(mac_ctx,
2552 					   &pe_session->lim_join_req->rsnIE,
2553 					   &frm->WPAOpaque);
2554 #if defined(FEATURE_WLAN_WAPI)
2555 		populate_dot11f_wapi_opaque(mac_ctx,
2556 			&(pe_session->lim_join_req->rsnIE),
2557 			&frm->WAPIOpaque);
2558 #endif /* defined(FEATURE_WLAN_WAPI) */
2559 	}
2560 	/* include WME EDCA IE as well */
2561 	if (wme_enabled) {
2562 		populate_dot11f_wmm_info_station_per_session(mac_ctx,
2563 			pe_session, &frm->WMMInfoStation);
2564 
2565 		if (wsm_enabled)
2566 			populate_dot11f_wmm_caps(&frm->WMMCaps);
2567 	}
2568 
2569 	/*
2570 	 * Populate HT IEs, when operating in 11n and
2571 	 * when AP is also operating in 11n mode
2572 	 */
2573 	if (pe_session->htCapability &&
2574 	    mac_ctx->lim.htCapabilityPresentInBeacon)
2575 		populate_dot11f_ht_caps(mac_ctx, pe_session, &frm->HTCaps);
2576 	else if (pe_session->he_with_wep_tkip)
2577 		populate_dot11f_ht_caps(mac_ctx, NULL, &frm->HTCaps);
2578 
2579 	if (pe_session->vhtCapability &&
2580 	    pe_session->vhtCapabilityPresentInBeacon) {
2581 		populate_dot11f_vht_caps(mac_ctx, pe_session, &frm->VHTCaps);
2582 		vht_enabled = true;
2583 		if (pe_session->gLimOperatingMode.present &&
2584 		    pe_session->ap_ch_width == CH_WIDTH_20MHZ &&
2585 		    frm->VHTCaps.present &&
2586 		    !IS_DOT11_MODE_HE(pe_session->dot11mode)) {
2587 			populate_dot11f_operating_mode(mac_ctx,
2588 					&frm->OperatingMode, pe_session);
2589 		}
2590 	} else if (pe_session->he_with_wep_tkip) {
2591 		populate_dot11f_vht_caps(mac_ctx, NULL, &frm->VHTCaps);
2592 	}
2593 
2594 	if (!vht_enabled && pe_session->is_vendor_specific_vhtcaps) {
2595 		frm->vendor_vht_ie.present = 1;
2596 		frm->vendor_vht_ie.sub_type =
2597 			pe_session->vendor_specific_vht_ie_sub_type;
2598 		frm->vendor_vht_ie.VHTCaps.present = 1;
2599 		if (!mac_ctx->mlme_cfg->vht_caps.vht_cap_info.vendor_vhtie &&
2600 		    pe_session->vht_config.su_beam_formee) {
2601 			pe_debug("Disable SU beamformee for vendor IE");
2602 			pe_session->vht_config.su_beam_formee = 0;
2603 		}
2604 		populate_dot11f_vht_caps(mac_ctx, pe_session,
2605 				&frm->vendor_vht_ie.VHTCaps);
2606 		vht_enabled = true;
2607 	}
2608 	if (pe_session->is_ext_caps_present)
2609 		populate_dot11f_ext_cap(mac_ctx, vht_enabled,
2610 				&frm->ExtCap, pe_session);
2611 
2612 	populate_dot11f_qcn_ie(mac_ctx, pe_session,
2613 			       &frm->qcn_ie, QCN_IE_ATTR_ID_ALL);
2614 
2615 	populate_dot11f_bss_max_idle(mac_ctx, pe_session,
2616 				     &frm->bss_max_idle_period);
2617 
2618 	if (IS_DOT11_MODE_HE(pe_session->dot11mode))
2619 		lim_update_session_he_capable(mac_ctx, pe_session);
2620 
2621 	if (lim_is_session_he_capable(pe_session)) {
2622 		populate_dot11f_he_caps(mac_ctx, pe_session,
2623 					&frm->he_cap);
2624 		populate_dot11f_he_6ghz_cap(mac_ctx, pe_session,
2625 					    &frm->he_6ghz_band_cap);
2626 	} else if (pe_session->he_with_wep_tkip) {
2627 		populate_dot11f_he_caps(mac_ctx, NULL, &frm->he_cap);
2628 		populate_dot11f_he_6ghz_cap(mac_ctx, pe_session,
2629 					    &frm->he_6ghz_band_cap);
2630 	}
2631 
2632 	if (add_ie_len && lim_is_session_eht_capable(pe_session)) {
2633 		populate_dot11f_eht_caps(mac_ctx, pe_session, &frm->eht_cap);
2634 		lim_strip_mlo_ie(mac_ctx, add_ie, &add_ie_len);
2635 	}
2636 
2637 	mlo_ie_len = lim_fill_assoc_req_mlo_ie(mac_ctx, pe_session, frm);
2638 
2639 	/**
2640 	 * In case of ML connection, if ML IE length is 0 then return failure.
2641 	 */
2642 	if (mlo_is_mld_sta(pe_session->vdev) && !mlo_ie_len) {
2643 		pe_err("Failed to add ML IE for vdev:%d", pe_session->vdev_id);
2644 		goto end;
2645 	}
2646 
2647 	if (pe_session->is11Rconnection) {
2648 		struct bss_description *bssdescr;
2649 
2650 		bssdescr = &pe_session->lim_join_req->bssDescription;
2651 		pe_debug("mdie = %02x %02x %02x",
2652 			(unsigned int) bssdescr->mdie[0],
2653 			(unsigned int) bssdescr->mdie[1],
2654 			(unsigned int) bssdescr->mdie[2]);
2655 		populate_mdie(mac_ctx, &frm->MobilityDomain,
2656 			pe_session->lim_join_req->bssDescription.mdie);
2657 		if (bssdescr->mdiePresent) {
2658 			mdie_cfg.bool_value = true;
2659 			mdie_cfg.uint_value =
2660 				(bssdescr->mdie[1] << 8) | (bssdescr->mdie[0]);
2661 		} else {
2662 			mdie_cfg.bool_value = false;
2663 			mdie_cfg.uint_value = 0;
2664 		}
2665 
2666 		wlan_cm_roam_cfg_set_value(mac_ctx->psoc, vdev_id,
2667 					   MOBILITY_DOMAIN, &mdie_cfg);
2668 
2669 		/*
2670 		 * IEEE80211-ai [13.2.4 FT initial mobility domain association
2671 		 * over FILS in an RSN]
2672 		 * Populate FT IE in association request. This FT IE should be
2673 		 * same as the FT IE received in auth response frame during the
2674 		 * FT-FILS authentication.
2675 		 */
2676 		if (lim_is_fils_connection(pe_session))
2677 			populate_fils_ft_info(mac_ctx, &frm->FTInfo,
2678 					      pe_session);
2679 	}
2680 
2681 #ifdef FEATURE_WLAN_ESE
2682 	/*
2683 	 * ESE Version IE will be included in association request
2684 	 * when ESE is enabled on DUT through ini and it is also
2685 	 * advertised by the peer AP to which we are trying to
2686 	 * associate to.
2687 	 */
2688 	if (pe_session->is_ese_version_ie_present &&
2689 		mac_ctx->mlme_cfg->lfr.ese_enabled)
2690 		populate_dot11f_ese_version(&frm->ESEVersion);
2691 	/* For ESE Associations fill the ESE IEs */
2692 	if (wlan_cm_get_ese_assoc(mac_ctx->pdev, pe_session->vdev_id)) {
2693 #ifndef FEATURE_DISABLE_RM
2694 		populate_dot11f_ese_rad_mgmt_cap(&frm->ESERadMgmtCap);
2695 #endif
2696 	}
2697 #endif
2698 
2699 	/*
2700 	 * Extcap IE now support variable length, merge Extcap IE from addn_ie
2701 	 * may change the frame size. Therefore, MUST merge ExtCap IE before
2702 	 * dot11f get packed payload size.
2703 	 */
2704 	if (extr_ext_flag)
2705 		lim_merge_extcap_struct(&frm->ExtCap, &extr_ext_cap, true);
2706 
2707 	/* Clear the bits in EXTCAP IE if AP not advertise it in beacon */
2708 	if (frm->ExtCap.present && pe_session->is_ext_caps_present) {
2709 		ie_offset = DOT11F_FF_TIMESTAMP_LEN +
2710 				DOT11F_FF_BEACONINTERVAL_LEN +
2711 				DOT11F_FF_CAPABILITIES_LEN;
2712 
2713 		qdf_mem_zero((uint8_t *)&bcn_ext_cap, sizeof(tDot11fIEExtCap));
2714 		if (pe_session->beacon && (pe_session->bcnLen >
2715 		    (ie_offset + sizeof(struct wlan_frame_hdr)))) {
2716 			bcn_ie = pe_session->beacon + ie_offset +
2717 						sizeof(struct wlan_frame_hdr);
2718 			bcn_ie_len = pe_session->bcnLen - ie_offset -
2719 						sizeof(struct wlan_frame_hdr);
2720 			p_ext_cap = (uint8_t *)wlan_get_ie_ptr_from_eid(
2721 							DOT11F_EID_EXTCAP,
2722 							bcn_ie, bcn_ie_len);
2723 			lim_update_extcap_struct(mac_ctx, p_ext_cap,
2724 							&bcn_ext_cap);
2725 			lim_merge_extcap_struct(&frm->ExtCap, &bcn_ext_cap,
2726 							false);
2727 		}
2728 
2729 		populate_dot11f_btm_extended_caps(mac_ctx, pe_session,
2730 						  &frm->ExtCap);
2731 		/*
2732 		 * TWT extended capabilities should be populated after the
2733 		 * intersection of beacon caps and self caps is done because
2734 		 * the bits for TWT are unique to STA and AP and cannot be
2735 		 * intersected.
2736 		 */
2737 		populate_dot11f_twt_extended_caps(mac_ctx, pe_session,
2738 						  &frm->ExtCap);
2739 	} else {
2740 		wlan_cm_set_assoc_btm_cap(pe_session->vdev, false);
2741 	}
2742 
2743 	if (QDF_STATUS_SUCCESS != lim_strip_supp_op_class_update_struct(mac_ctx,
2744 			add_ie, &add_ie_len, &frm->SuppOperatingClasses))
2745 		pe_debug("Unable to Stripoff supp op classes IE from Assoc Req");
2746 
2747 	if (lim_is_fils_connection(pe_session)) {
2748 		populate_dot11f_fils_params(mac_ctx, frm, pe_session);
2749 		aes_block_size_len = AES_BLOCK_SIZE;
2750 		if (add_ie_len && wlan_get_ie_ptr_from_eid(WLAN_ELEMID_FRAGMENT,
2751 							   add_ie, add_ie_len))
2752 			frag_ie_present = true;
2753 	}
2754 
2755 	/* Strip and append HLP container IE only if it is fragmented */
2756 	if (frag_ie_present && add_ie_len &&
2757 	    wlan_get_ext_ie_ptr_from_ext_id(SIR_FILS_HLP_OUI_TYPE,
2758 					    SIR_FILS_HLP_OUI_LEN, add_ie,
2759 					    add_ie_len)) {
2760 		fils_hlp_ie = qdf_mem_malloc(SIR_FILS_HLP_IE_LEN);
2761 		if (!fils_hlp_ie)
2762 			goto end;
2763 
2764 		qdf_status =
2765 			lim_strip_ie(mac_ctx, add_ie, &add_ie_len,
2766 				     WLAN_ELEMID_EXTN_ELEM, ONE_BYTE,
2767 				     SIR_FILS_HLP_OUI_TYPE,
2768 				     SIR_FILS_HLP_OUI_LEN, fils_hlp_ie,
2769 				     SIR_FILS_HLP_IE_LEN - 2);
2770 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
2771 			pe_err("Failed to strip FILS HLP container IE");
2772 			goto end;
2773 		}
2774 		fils_hlp_ie_len = fils_hlp_ie[1] + 2;
2775 
2776 		current_len = add_ie_len;
2777 		qdf_status =
2778 			lim_strip_ie(mac_ctx, add_ie, &add_ie_len,
2779 				     WLAN_ELEMID_FRAGMENT, ONE_BYTE,
2780 				     NULL, 0, &fils_hlp_ie[fils_hlp_ie_len],
2781 				     SIR_FILS_HLP_IE_LEN - fils_hlp_ie_len - 2);
2782 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
2783 			pe_err("Failed to strip fragment IE of HLP container IE");
2784 			goto end;
2785 		}
2786 		fils_hlp_ie_len += current_len - add_ie_len;
2787 	}
2788 
2789 	/* RSNX IE for SAE PWE derivation based on H2E */
2790 	if (add_ie_len &&
2791 	    wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSNXE, add_ie, add_ie_len)) {
2792 		rsnx_ie = qdf_mem_malloc(WLAN_MAX_IE_LEN + 2);
2793 		if (!rsnx_ie)
2794 			goto end;
2795 
2796 		qdf_status = lim_strip_ie(mac_ctx, add_ie, &add_ie_len,
2797 					  WLAN_ELEMID_RSNXE, ONE_BYTE,
2798 					  NULL, 0, rsnx_ie, WLAN_MAX_IE_LEN);
2799 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
2800 			pe_err("Failed to strip Vendor IEs");
2801 			goto end;
2802 		}
2803 		rsnx_ie_len = rsnx_ie[1] + 2;
2804 	}
2805 	/* MSCS ext ie */
2806 	if (add_ie_len &&
2807 	    wlan_get_ext_ie_ptr_from_ext_id(MSCS_OUI_TYPE, MSCS_OUI_SIZE,
2808 					    add_ie, add_ie_len)) {
2809 		mscs_ext_ie = qdf_mem_malloc(WLAN_MAX_IE_LEN + 2);
2810 		if (!mscs_ext_ie)
2811 			goto end;
2812 
2813 		qdf_status = lim_strip_ie(mac_ctx, add_ie, &add_ie_len,
2814 					  WLAN_ELEMID_EXTN_ELEM, ONE_BYTE,
2815 					  MSCS_OUI_TYPE, MSCS_OUI_SIZE,
2816 					  mscs_ext_ie, WLAN_MAX_IE_LEN);
2817 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
2818 			pe_err("Failed to strip MSCS ext IE");
2819 			goto end;
2820 		}
2821 		mscs_ext_ie_len = mscs_ext_ie[1] + 2;
2822 	}
2823 
2824 	/*
2825 	 * MBO IE needs to be appendded at the end of the assoc request
2826 	 * frame and is not parsed and unpacked by the frame parser
2827 	 * as the supplicant can send multiple TLVs with same Attribute
2828 	 * in the MBO IE and the frame parser does not support multiple
2829 	 * TLVs with same attribute in a single IE.
2830 	 * Strip off the MBO IE from add_ie and append it at the end.
2831 	 */
2832 	if (add_ie_len &&
2833 	    wlan_get_vendor_ie_ptr_from_oui(SIR_MAC_MBO_OUI,
2834 					    SIR_MAC_MBO_OUI_SIZE, add_ie,
2835 					    add_ie_len)) {
2836 		mbo_ie = qdf_mem_malloc(DOT11F_IE_MBO_IE_MAX_LEN + 2);
2837 		if (!mbo_ie)
2838 			goto end;
2839 
2840 		qdf_status = lim_strip_ie(mac_ctx, add_ie, &add_ie_len,
2841 					  WLAN_ELEMID_VENDOR, ONE_BYTE,
2842 					  SIR_MAC_MBO_OUI,
2843 					  SIR_MAC_MBO_OUI_SIZE,
2844 					  mbo_ie, DOT11F_IE_MBO_IE_MAX_LEN);
2845 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
2846 			pe_err("Failed to strip MBO IE");
2847 			goto end;
2848 		}
2849 
2850 		/* Include the EID and length fields */
2851 		mbo_ie_len = mbo_ie[1] + 2;
2852 
2853 		if (pe_session->connected_akm == ANI_AKM_TYPE_NONE)
2854 			is_open_auth = true;
2855 
2856 		if (!is_open_auth) {
2857 			bss_mfp_capable =
2858 				lim_get_vdev_rmf_capable(mac_ctx, pe_session);
2859 			if (!bss_mfp_capable) {
2860 				pe_debug("Peer doesn't support PMF, Don't add MBO IE");
2861 				qdf_mem_free(mbo_ie);
2862 				mbo_ie = NULL;
2863 				mbo_ie_len = 0;
2864 			}
2865 		}
2866 	}
2867 
2868 	/*
2869 	 * Strip rest of the vendor IEs and append to the assoc request frame.
2870 	 * Append the IEs just before MBO IEs as MBO IEs have to be at the
2871 	 * end of the frame.
2872 	 */
2873 	if (add_ie_len &&
2874 	    wlan_get_ie_ptr_from_eid(WLAN_ELEMID_VENDOR, add_ie, add_ie_len)) {
2875 		vendor_ies = qdf_mem_malloc(MAX_VENDOR_IES_LEN + 2);
2876 		if (vendor_ies) {
2877 			current_len = add_ie_len;
2878 			qdf_status = lim_strip_ie(mac_ctx, add_ie, &add_ie_len,
2879 						  WLAN_ELEMID_VENDOR, ONE_BYTE,
2880 						  NULL,
2881 						  0,
2882 						  vendor_ies,
2883 						  MAX_VENDOR_IES_LEN);
2884 			if (QDF_IS_STATUS_ERROR(qdf_status)) {
2885 				pe_err("Failed to strip Vendor IEs");
2886 				goto end;
2887 			}
2888 
2889 			vendor_ie_len = current_len - add_ie_len;
2890 		}
2891 	}
2892 
2893 	qdf_status = lim_fill_adaptive_11r_ie(pe_session, &adaptive_11r_ie,
2894 					      &adaptive_11r_ie_len);
2895 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
2896 		pe_err("Failed to fill adaptive 11r IE");
2897 		goto end;
2898 	}
2899 
2900 	/*
2901 	 * Do unpack to populate the add_ie buffer to frm structure
2902 	 * before packing the frm structure. In this way, the IE ordering
2903 	 * which the latest 802.11 spec mandates is maintained.
2904 	 */
2905 	if (add_ie_len) {
2906 		ret = dot11f_unpack_assoc_request(mac_ctx, add_ie,
2907 					    add_ie_len, frm, true);
2908 		if (DOT11F_FAILED(ret)) {
2909 			pe_err("unpack failed, ret: 0x%x", ret);
2910 			goto end;
2911 		}
2912 	}
2913 
2914 	status = dot11f_get_packed_assoc_request_size(mac_ctx, frm, &payload);
2915 	if (DOT11F_FAILED(status)) {
2916 		pe_err("Association Request packet size failure(0x%08x)",
2917 			status);
2918 		/* We'll fall back on the worst case scenario: */
2919 		payload = sizeof(tDot11fAssocRequest);
2920 	} else if (DOT11F_WARNED(status)) {
2921 		pe_warn("Association request packet size warning (0x%08x)",
2922 			status);
2923 	}
2924 
2925 	bytes = payload + sizeof(tSirMacMgmtHdr) + aes_block_size_len +
2926 		rsnx_ie_len + mbo_ie_len + adaptive_11r_ie_len +
2927 		mscs_ext_ie_len + vendor_ie_len + mlo_ie_len + fils_hlp_ie_len;
2928 
2929 
2930 	qdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame,
2931 				(void **)&packet);
2932 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2933 		pe_err("Failed to allocate %d bytes", bytes);
2934 
2935 		pe_session->limMlmState = pe_session->limPrevMlmState;
2936 		MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_MLM_STATE,
2937 				 pe_session->peSessionId,
2938 				 pe_session->limMlmState));
2939 
2940 		/* Update PE session id */
2941 		assoc_cnf.sessionId = pe_session->peSessionId;
2942 
2943 		assoc_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
2944 
2945 		lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF,
2946 			(uint32_t *) &assoc_cnf);
2947 
2948 		goto end;
2949 	}
2950 	/* Paranoia: */
2951 	qdf_mem_zero(frame, bytes);
2952 
2953 	/* Next, we fill out the buffer descriptor: */
2954 	lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME,
2955 		SIR_MAC_MGMT_ASSOC_REQ, pe_session->bssId,
2956 		pe_session->self_mac_addr);
2957 	/* That done, pack the Assoc Request: */
2958 	status = dot11f_pack_assoc_request(mac_ctx, frm,
2959 			frame + sizeof(tSirMacMgmtHdr), payload, &payload);
2960 	if (DOT11F_FAILED(status)) {
2961 		pe_err("Assoc request pack failure (0x%08x)", status);
2962 		cds_packet_free((void *)packet);
2963 		goto end;
2964 	} else if (DOT11F_WARNED(status)) {
2965 		pe_warn("Assoc request pack warning (0x%08x)", status);
2966 	}
2967 
2968 	if (fils_hlp_ie && fils_hlp_ie_len) {
2969 		qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
2970 			     fils_hlp_ie, fils_hlp_ie_len);
2971 		payload = payload + fils_hlp_ie_len;
2972 	}
2973 
2974 	/* Strip EHT capabilities IE */
2975 	if (lim_is_session_eht_capable(pe_session)) {
2976 		ie_buf_size = payload - WLAN_ASSOC_REQ_IES_OFFSET;
2977 
2978 		eht_cap_ie = qdf_mem_malloc(WLAN_MAX_IE_LEN + 2);
2979 		if (!eht_cap_ie) {
2980 			pe_err("malloc failed for eht_cap_ie");
2981 			cds_packet_free((void *)packet);
2982 			goto end;
2983 		}
2984 
2985 		qdf_status = lim_strip_eht_cap_ie(mac_ctx, frame +
2986 						  sizeof(tSirMacMgmtHdr) +
2987 						  WLAN_ASSOC_REQ_IES_OFFSET,
2988 						  &ie_buf_size, eht_cap_ie);
2989 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
2990 			pe_err("Failed to strip EHT cap IE");
2991 			qdf_mem_free(eht_cap_ie);
2992 			cds_packet_free((void *)packet);
2993 			goto end;
2994 		}
2995 
2996 		is_band_2g =
2997 			WLAN_REG_IS_24GHZ_CH_FREQ(pe_session->curr_op_freq);
2998 
2999 		lim_ieee80211_pack_ehtcap(eht_cap_ie, frm->eht_cap, frm->he_cap,
3000 					  is_band_2g);
3001 		eht_cap_ie_len = eht_cap_ie[1] + 2;
3002 
3003 		/* Copy the EHT IE to the end of the frame */
3004 		qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) +
3005 			     WLAN_ASSOC_REQ_IES_OFFSET + ie_buf_size,
3006 			     eht_cap_ie, eht_cap_ie_len);
3007 		qdf_mem_free(eht_cap_ie);
3008 		payload = ie_buf_size + WLAN_ASSOC_REQ_IES_OFFSET +
3009 			  eht_cap_ie_len;
3010 	}
3011 
3012 	if (rsnx_ie && rsnx_ie_len) {
3013 		qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
3014 			     rsnx_ie, rsnx_ie_len);
3015 		payload = payload + rsnx_ie_len;
3016 	}
3017 
3018 	if (mscs_ext_ie && mscs_ext_ie_len) {
3019 		qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
3020 			     mscs_ext_ie, mscs_ext_ie_len);
3021 		payload = payload + mscs_ext_ie_len;
3022 	}
3023 
3024 	/* Copy the vendor IEs to the end of the frame */
3025 	qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
3026 		     vendor_ies, vendor_ie_len);
3027 	payload = payload + vendor_ie_len;
3028 
3029 	/* Copy the MBO IE to the end of the frame */
3030 	qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
3031 		     mbo_ie, mbo_ie_len);
3032 	payload = payload + mbo_ie_len;
3033 
3034 	/*
3035 	 * Copy the Vendor specific Adaptive 11r IE to end of the
3036 	 * assoc request frame
3037 	 */
3038 	qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
3039 		     adaptive_11r_ie, adaptive_11r_ie_len);
3040 	payload = payload + adaptive_11r_ie_len;
3041 
3042 	if (mlo_ie_len) {
3043 		qdf_status = lim_fill_complete_mlo_ie(pe_session, mlo_ie_len,
3044 				      frame + sizeof(tSirMacMgmtHdr) + payload);
3045 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
3046 			pe_debug("assemble ml ie error");
3047 			mlo_ie_len = 0;
3048 		}
3049 		payload = payload + mlo_ie_len;
3050 	}
3051 
3052 	if (pe_session->assoc_req) {
3053 		qdf_mem_free(pe_session->assoc_req);
3054 		pe_session->assoc_req = NULL;
3055 		pe_session->assocReqLen = 0;
3056 	}
3057 
3058 	if (lim_is_fils_connection(pe_session)) {
3059 		qdf_status = aead_encrypt_assoc_req(mac_ctx, pe_session,
3060 						    frame, &payload);
3061 		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
3062 			cds_packet_free((void *)packet);
3063 			goto end;
3064 		}
3065 	}
3066 
3067 	pe_session->assoc_req = qdf_mem_malloc(payload);
3068 	if (pe_session->assoc_req) {
3069 		/*
3070 		 * Store the Assoc request. This is sent to csr/hdd in
3071 		 * join cnf response.
3072 		 */
3073 		qdf_mem_copy(pe_session->assoc_req,
3074 			     frame + sizeof(tSirMacMgmtHdr), payload);
3075 		pe_session->assocReqLen = payload;
3076 	}
3077 
3078 	if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) ||
3079 	    pe_session->opmode == QDF_P2P_CLIENT_MODE ||
3080 	    pe_session->opmode == QDF_P2P_GO_MODE)
3081 		tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
3082 
3083 	if (pe_session->opmode == QDF_P2P_CLIENT_MODE ||
3084 	    pe_session->opmode == QDF_STA_MODE)
3085 		tx_flag |= HAL_USE_PEER_STA_REQUESTED_MASK;
3086 
3087 	mac_hdr = (tpSirMacMgmtHdr) frame;
3088 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
3089 			 pe_session->peSessionId, mac_hdr->fc.subType));
3090 
3091 	pe_debug("extr_ext_flag %d mbo ie len %d is open auth %d stripped vendor len %d he with tkip %d ht %d vht %d opmode %d vendor vht %d he %d eht %d",
3092 		 extr_ext_flag, mbo_ie_len, is_open_auth, current_len,
3093 		 pe_session->he_with_wep_tkip,
3094 		 frm->HTCaps.present, frm->VHTCaps.present,
3095 		 frm->OperatingMode.present, frm->vendor_vht_ie.present,
3096 		 frm->he_cap.present, frm->eht_cap.present);
3097 	pe_nofl_info("Assoc req TX: vdev %d to "QDF_MAC_ADDR_FMT" seq num %d",
3098 		     pe_session->vdev_id, QDF_MAC_ADDR_REF(pe_session->bssId),
3099 		     mac_ctx->mgmtSeqNum);
3100 
3101 	min_rid = lim_get_min_session_txrate(pe_session, NULL);
3102 	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_ASSOC_START_EVENT,
3103 			      pe_session, QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS);
3104 	lim_diag_mgmt_tx_event_report(mac_ctx, mac_hdr,
3105 				      pe_session, QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS);
3106 	peer_rssi = mac_ctx->lim.bss_rssi;
3107 
3108 	qdf_status =
3109 		wma_tx_frameWithTxComplete(mac_ctx, packet,
3110 			   (uint16_t) (sizeof(tSirMacMgmtHdr) + payload),
3111 			   TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
3112 			   lim_tx_complete, frame, lim_assoc_tx_complete_cnf,
3113 			   tx_flag, vdev_id, false, 0,
3114 			   min_rid, peer_rssi, 0);
3115 	MTRACE(qdf_trace
3116 		       (QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
3117 		       pe_session->peSessionId, qdf_status));
3118 
3119 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
3120 		pe_err("Failed to send Association Request (%X)!",
3121 			qdf_status);
3122 		mac_ctx->assoc_ack_status = LIM_TX_FAILED;
3123 		lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_ASSOC_ACK_EVENT,
3124 				pe_session, SENT_FAIL, QDF_STATUS_E_FAILURE);
3125 		/* Pkt will be freed up by the callback */
3126 	}
3127 
3128 end:
3129 	qdf_mem_free(fils_hlp_ie);
3130 	qdf_mem_free(rsnx_ie);
3131 	qdf_mem_free(vendor_ies);
3132 	qdf_mem_free(mbo_ie);
3133 	qdf_mem_free(mscs_ext_ie);
3134 
3135 	/* Free up buffer allocated for mlm_assoc_req */
3136 	qdf_mem_free(adaptive_11r_ie);
3137 	qdf_mem_free(mlm_assoc_req);
3138 	qdf_mem_free(add_ie);
3139 	mlm_assoc_req = NULL;
3140 	qdf_mem_free(frm);
3141 	return;
3142 }
3143 
3144 /**
3145  * lim_get_addba_rsp_ptr() - Search the pointer to addba response
3146  * @ie: the pointer to entire frame
3147  * @ie_len: length of ie
3148  *
3149  * Host reserved 8 bytes for CCMP header trailer and initialize them
3150  * as 0 when rmf enabled & key installed and tx addba rsp frame. So,
3151  * search the pointer to addba response and then unpack the frame.
3152  *
3153  * Return: the pointer to addba response
3154  */
3155 static uint8_t *
3156 lim_get_addba_rsp_ptr(uint8_t *ie, uint32_t ie_len)
3157 {
3158 	uint32_t left = ie_len;
3159 	uint8_t *ptr = ie;
3160 	uint8_t category, action;
3161 	uint32_t addba_rsp_len = sizeof(tDot11faddba_rsp);
3162 
3163 	while (left >= addba_rsp_len) {
3164 		category  = ptr[0];
3165 		action = ptr[1];
3166 
3167 		if (category == ACTION_CATEGORY_BACK &&
3168 		    action == ADDBA_RESPONSE)
3169 			return ptr;
3170 
3171 		left--;
3172 		ptr++;
3173 	}
3174 
3175 	return NULL;
3176 }
3177 
3178 /**
3179  * lim_addba_rsp_tx_complete_cnf() - Confirmation for add BA response OTA
3180  * @context: pointer to global mac
3181  * @buf: buffer which is nothing but entire ADD BA frame
3182  * @tx_complete: Sent status
3183  * @params: tx completion params
3184  *
3185  * Return: This returns QDF_STATUS
3186  */
3187 static QDF_STATUS lim_addba_rsp_tx_complete_cnf(void *context,
3188 						qdf_nbuf_t buf,
3189 						uint32_t tx_complete,
3190 						void *params)
3191 {
3192 	struct mac_context *mac_ctx = (struct mac_context *)context;
3193 	tSirMacMgmtHdr *mac_hdr;
3194 	tDot11faddba_rsp rsp = {0};
3195 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3196 	uint32_t rsp_len;
3197 	QDF_STATUS status;
3198 	uint8_t *data;
3199 	uint8_t *addba_rsp_ptr;
3200 	uint32_t data_len;
3201 	struct wmi_mgmt_params *mgmt_params = (struct wmi_mgmt_params *)params;
3202 
3203 	if (tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK)
3204 		pe_debug("Add ba response successfully sent");
3205 	else
3206 		pe_debug("Fail to send add ba response");
3207 
3208 	if (!buf) {
3209 		pe_err("Addba response frame buffer is NULL");
3210 		return QDF_STATUS_E_FAILURE;
3211 	}
3212 
3213 	data = qdf_nbuf_data(buf);
3214 
3215 	if (!data) {
3216 		pe_err("Addba response frame is NULL");
3217 		return QDF_STATUS_E_FAILURE;
3218 	}
3219 
3220 	data_len = (uint32_t)qdf_nbuf_get_data_len(buf);
3221 	if (data_len < (sizeof(*mac_hdr) + sizeof(rsp))) {
3222 		pe_err("Invalid data len %d", data_len);
3223 		return QDF_STATUS_E_FAILURE;
3224 	}
3225 
3226 	addba_rsp_ptr = lim_get_addba_rsp_ptr(
3227 				data + sizeof(*mac_hdr),
3228 				data_len - sizeof(*mac_hdr));
3229 	if (!addba_rsp_ptr) {
3230 		pe_debug("null addba_rsp_ptr");
3231 		qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
3232 				   (void *)data, data_len);
3233 		addba_rsp_ptr = (uint8_t *)data + sizeof(*mac_hdr);
3234 	}
3235 	mac_hdr = (tSirMacMgmtHdr *)data;
3236 	rsp_len = sizeof(rsp);
3237 	status = dot11f_unpack_addba_rsp(mac_ctx, addba_rsp_ptr,
3238 					 rsp_len, &rsp, false);
3239 
3240 	if (DOT11F_FAILED(status)) {
3241 		pe_err("Failed to unpack and parse (0x%08x, %d bytes)",
3242 			status, rsp_len);
3243 		goto error;
3244 	}
3245 
3246 	cdp_addba_resp_tx_completion(soc, mac_hdr->da, mgmt_params->vdev_id,
3247 				     rsp.addba_param_set.tid, tx_complete);
3248 error:
3249 	if (buf)
3250 		qdf_nbuf_free(buf);
3251 
3252 	return QDF_STATUS_SUCCESS;
3253 }
3254 
3255 #define SAE_AUTH_ALGO_LEN 2
3256 #define SAE_AUTH_ALGO_OFFSET 0
3257 static bool lim_is_ack_for_sae_auth(qdf_nbuf_t buf)
3258 {
3259 	tpSirMacMgmtHdr mac_hdr;
3260 	uint16_t *sae_auth, min_len;
3261 
3262 	if (!buf) {
3263 		pe_debug("buf is NULL");
3264 		return false;
3265 	}
3266 
3267 	min_len = sizeof(tSirMacMgmtHdr) + SAE_AUTH_ALGO_LEN;
3268 	if (qdf_nbuf_len(buf) < min_len) {
3269 		pe_debug("buf_len %d less than min_len %d",
3270 			 (uint32_t)qdf_nbuf_len(buf), min_len);
3271 		return false;
3272 	}
3273 
3274 	mac_hdr = (tpSirMacMgmtHdr)(qdf_nbuf_data(buf));
3275 	if (mac_hdr->fc.subType == SIR_MAC_MGMT_AUTH) {
3276 		sae_auth = (uint16_t *)((uint8_t *)mac_hdr +
3277 					sizeof(tSirMacMgmtHdr));
3278 		if (sae_auth[SAE_AUTH_ALGO_OFFSET] ==
3279 		    eSIR_AUTH_TYPE_SAE)
3280 			return true;
3281 	}
3282 
3283 	return false;
3284 }
3285 
3286 /**
3287  * lim_auth_tx_complete_cnf()- Confirmation for auth sent over the air
3288  * @context: pointer to global mac
3289  * @buf: buffer
3290  * @tx_complete : Sent status
3291  * @params: tx completion params
3292  *
3293  * Return: This returns QDF_STATUS
3294  */
3295 static QDF_STATUS lim_auth_tx_complete_cnf(void *context,
3296 					   qdf_nbuf_t buf,
3297 					   uint32_t tx_complete,
3298 					   void *params)
3299 {
3300 	struct mac_context *mac_ctx = (struct mac_context *)context;
3301 	uint16_t auth_ack_status;
3302 	uint16_t reason_code;
3303 	bool sae_auth_acked;
3304 
3305 	if (params)
3306 		wlan_send_tx_complete_event(context, buf, params, tx_complete,
3307 					    WLAN_AUTH_REQ);
3308 
3309 	pe_nofl_rl_info("Auth TX: %s (%d)",
3310 			(tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK) ?
3311 			"success" : "fail", tx_complete);
3312 	if (tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK) {
3313 		mac_ctx->auth_ack_status = LIM_ACK_RCD_SUCCESS;
3314 		auth_ack_status = ACKED;
3315 		reason_code = QDF_STATUS_SUCCESS;
3316 		sae_auth_acked = lim_is_ack_for_sae_auth(buf);
3317 		/*
3318 		 * 'Change' timer for future activations only if ack
3319 		 * received is not for WPA SAE auth frames.
3320 		 */
3321 		if (!sae_auth_acked)
3322 			lim_deactivate_and_change_timer(mac_ctx,
3323 							eLIM_AUTH_RETRY_TIMER);
3324 	} else if (tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_NO_ACK) {
3325 		mac_ctx->auth_ack_status = LIM_ACK_RCD_FAILURE;
3326 		auth_ack_status = NOT_ACKED;
3327 		reason_code = QDF_STATUS_E_FAILURE;
3328 	} else {
3329 		mac_ctx->auth_ack_status = LIM_TX_FAILED;
3330 		auth_ack_status = SENT_FAIL;
3331 		reason_code = QDF_STATUS_E_FAILURE;
3332 	}
3333 
3334 	if (buf)
3335 		qdf_nbuf_free(buf);
3336 
3337 	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_AUTH_ACK_EVENT,
3338 				NULL, auth_ack_status, reason_code);
3339 
3340 	return QDF_STATUS_SUCCESS;
3341 }
3342 
3343 #ifdef WLAN_FEATURE_11BE_MLO
3344 static uint32_t lim_calculate_auth_mlo_ie_len(struct mac_context *mac_ctx,
3345 					      struct pe_session *session,
3346 					      tSirMacAddr peer_addr)
3347 {
3348 	struct wlan_mlo_ie *mlo_ie;
3349 	uint32_t mlo_ie_len = 0;
3350 	struct tLimPreAuthNode *auth_node;
3351 
3352 	mlo_ie = &session->mlo_ie;
3353 	if (wlan_vdev_mlme_is_mlo_vdev(session->vdev)) {
3354 		qdf_mem_zero(mlo_ie, sizeof(*mlo_ie));
3355 
3356 		pe_debug("Auth TX sys role: %d", GET_LIM_SYSTEM_ROLE(session));
3357 		if (LIM_IS_STA_ROLE(session)) {
3358 			populate_dot11f_auth_mlo_ie(mac_ctx, session, mlo_ie);
3359 			mlo_ie_len = lim_caculate_mlo_ie_length(mlo_ie);
3360 		} else if (LIM_IS_AP_ROLE(session)) {
3361 			auth_node = lim_search_pre_auth_list(mac_ctx, peer_addr);
3362 			if (!auth_node) {
3363 				pe_err("no pre-auth ctx with peer addr");
3364 				return 0;
3365 			}
3366 
3367 			/*
3368 			 * Populate MLO IE in Auth response frame if
3369 			 * is_mlo_ie_present flag is set. It is set when peer
3370 			 * is MLO AP
3371 			 */
3372 			if (auth_node && auth_node->is_mlo_ie_present) {
3373 				populate_dot11f_auth_mlo_ie(mac_ctx, session,
3374 							   mlo_ie);
3375 				mlo_ie_len = lim_caculate_mlo_ie_length(mlo_ie);
3376 			}
3377 		}
3378 	}
3379 
3380 	return mlo_ie_len;
3381 }
3382 
3383 #else
3384 static inline
3385 uint32_t lim_calculate_auth_mlo_ie_len(struct mac_context *mac_ctx,
3386 				       struct pe_session *session,
3387 				       tSirMacAddr peer_addr)
3388 {
3389 	return 0;
3390 }
3391 #endif
3392 
3393 /**
3394  * lim_send_auth_mgmt_frame() - Send an Authentication frame
3395  * @mac_ctx: Pointer to Global MAC structure
3396  * @auth_frame: Pointer to Authentication frame structure
3397  * @peer_addr: MAC address of destination peer
3398  * @wep_challenge_len: wep challenge length
3399  * @session: PE session information
3400  *
3401  * This function is called by lim_process_mlm_messages(). Authentication frame
3402  * is formatted and sent when this function is called.
3403  *
3404  * Return: void
3405  */
3406 void
3407 lim_send_auth_mgmt_frame(struct mac_context *mac_ctx,
3408 			 tpSirMacAuthFrameBody auth_frame,
3409 			 tSirMacAddr peer_addr,
3410 			 uint8_t wep_challenge_len,
3411 			 struct pe_session *session)
3412 {
3413 	uint8_t *frame, *body;
3414 	uint32_t frame_len = 0, body_len = 0;
3415 	tpSirMacMgmtHdr mac_hdr;
3416 	void *packet;
3417 	QDF_STATUS qdf_status, status;
3418 	uint8_t tx_flag = 0;
3419 	uint8_t vdev_id = 0;
3420 	uint16_t ft_ies_length = 0;
3421 	bool challenge_req = false;
3422 	enum rateid min_rid = RATEID_DEFAULT;
3423 	uint16_t ch_freq_tx_frame = 0;
3424 	int8_t peer_rssi = 0;
3425 	uint8_t *mlo_ie_buf = NULL;
3426 	uint32_t mlo_ie_len = 0;
3427 
3428 	if (!session) {
3429 		pe_err("Error: psession Entry is NULL");
3430 		return;
3431 	}
3432 
3433 	vdev_id = session->vdev_id;
3434 
3435 	if (wep_challenge_len) {
3436 		/*
3437 		 * Auth frame3 to be sent with encrypted framebody
3438 		 *
3439 		 * Allocate buffer for Authenticaton frame of size
3440 		 * equal to management frame header length plus 2 bytes
3441 		 * each for auth algorithm number, transaction number,
3442 		 * status code, 128 bytes for challenge text and
3443 		 * 4 bytes each for IV & ICV.
3444 		 */
3445 		body_len = wep_challenge_len + LIM_ENCR_AUTH_INFO_LEN;
3446 		frame_len = sizeof(tSirMacMgmtHdr) + body_len;
3447 
3448 		goto alloc_packet;
3449 	}
3450 
3451 	switch (auth_frame->authTransactionSeqNumber) {
3452 	case SIR_MAC_AUTH_FRAME_1:
3453 		/*
3454 		 * Allocate buffer for Authenticaton frame of size
3455 		 * equal to management frame header length plus 2 bytes
3456 		 * each for auth algorithm number, transaction number
3457 		 * and status code.
3458 		 */
3459 
3460 		body_len = SIR_MAC_AUTH_FRAME_INFO_LEN;
3461 		frame_len = sizeof(tSirMacMgmtHdr) + body_len;
3462 
3463 		status = lim_create_fils_auth_data(mac_ctx, auth_frame,
3464 						   session, &frame_len);
3465 		if (QDF_IS_STATUS_ERROR(status))
3466 			return;
3467 
3468 		if (auth_frame->authAlgoNumber == eSIR_FT_AUTH) {
3469 			if (session->ftPEContext.pFTPreAuthReq &&
3470 			    0 != session->ftPEContext.pFTPreAuthReq->
3471 				ft_ies_length) {
3472 				ft_ies_length = session->ftPEContext.
3473 					pFTPreAuthReq->ft_ies_length;
3474 				frame_len += ft_ies_length;
3475 				pe_debug("Auth frame, FTIES length added=%d",
3476 					ft_ies_length);
3477 			} else {
3478 				pe_debug("Auth frame, Does not contain FTIES!");
3479 				frame_len += (2 + SIR_MDIE_SIZE);
3480 			}
3481 		}
3482 
3483 		/* include MDIE in FILS authentication frame */
3484 		if (session->lim_join_req &&
3485 		    session->is11Rconnection &&
3486 		    auth_frame->authAlgoNumber == SIR_FILS_SK_WITHOUT_PFS &&
3487 		    session->lim_join_req->bssDescription.mdiePresent)
3488 			frame_len += (2 + SIR_MDIE_SIZE);
3489 		break;
3490 
3491 	case SIR_MAC_AUTH_FRAME_2:
3492 		if ((auth_frame->authAlgoNumber == eSIR_OPEN_SYSTEM) ||
3493 		    ((auth_frame->authAlgoNumber == eSIR_SHARED_KEY) &&
3494 			(auth_frame->authStatusCode != STATUS_SUCCESS))) {
3495 			/*
3496 			 * Allocate buffer for Authenticaton frame of size
3497 			 * equal to management frame header length plus
3498 			 * 2 bytes each for auth algorithm number,
3499 			 * transaction number and status code.
3500 			 */
3501 
3502 			body_len = SIR_MAC_AUTH_FRAME_INFO_LEN;
3503 			frame_len = sizeof(tSirMacMgmtHdr) + body_len;
3504 		} else {
3505 			/*
3506 			 * Shared Key algorithm with challenge text
3507 			 * to be sent.
3508 			 *
3509 			 * Allocate buffer for Authenticaton frame of size
3510 			 * equal to management frame header length plus
3511 			 * 2 bytes each for auth algorithm number,
3512 			 * transaction number, status code and 128 bytes
3513 			 * for challenge text.
3514 			 */
3515 
3516 			challenge_req = true;
3517 			body_len = SIR_MAC_AUTH_FRAME_INFO_LEN +
3518 				   SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH +
3519 				   SIR_MAC_CHALLENGE_ID_LEN;
3520 			frame_len = sizeof(tSirMacMgmtHdr) + body_len;
3521 		}
3522 		break;
3523 
3524 	case SIR_MAC_AUTH_FRAME_3:
3525 		/*
3526 		 * Auth frame3 to be sent without encrypted framebody
3527 		 *
3528 		 * Allocate buffer for Authenticaton frame of size equal
3529 		 * to management frame header length plus 2 bytes each
3530 		 * for auth algorithm number, transaction number and
3531 		 * status code.
3532 		 */
3533 
3534 		body_len = SIR_MAC_AUTH_FRAME_INFO_LEN;
3535 		frame_len = sizeof(tSirMacMgmtHdr) + body_len;
3536 		break;
3537 
3538 	case SIR_MAC_AUTH_FRAME_4:
3539 		/*
3540 		 * Allocate buffer for Authenticaton frame of size equal
3541 		 * to management frame header length plus 2 bytes each
3542 		 * for auth algorithm number, transaction number and
3543 		 * status code.
3544 		 */
3545 
3546 		body_len = SIR_MAC_AUTH_FRAME_INFO_LEN;
3547 		frame_len = sizeof(tSirMacMgmtHdr) + body_len;
3548 
3549 		break;
3550 	default:
3551 		pe_err("Invalid auth transaction seq num");
3552 		return;
3553 	} /* switch (auth_frame->authTransactionSeqNumber) */
3554 
3555 	mlo_ie_len = lim_calculate_auth_mlo_ie_len(mac_ctx, session, peer_addr);
3556 
3557 	if (mlo_ie_len) {
3558 		mlo_ie_buf = qdf_mem_malloc(mlo_ie_len);
3559 		if (mlo_ie_buf) {
3560 			qdf_status = lim_fill_complete_mlo_ie(session,
3561 							      mlo_ie_len,
3562 							      mlo_ie_buf);
3563 			if (QDF_IS_STATUS_ERROR(qdf_status)) {
3564 				mlo_ie_len = 0;
3565 				qdf_mem_free(mlo_ie_buf);
3566 			}
3567 
3568 			frame_len += mlo_ie_len;
3569 		}
3570 	}
3571 alloc_packet:
3572 	qdf_status = cds_packet_alloc((uint16_t) frame_len, (void **)&frame,
3573 				 (void **)&packet);
3574 
3575 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
3576 		pe_err("call to bufAlloc failed for AUTH frame");
3577 		return;
3578 	}
3579 
3580 	qdf_mem_zero(frame, frame_len);
3581 
3582 	/* Prepare BD */
3583 	lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME,
3584 		SIR_MAC_MGMT_AUTH, peer_addr, session->self_mac_addr);
3585 	mac_hdr = (tpSirMacMgmtHdr) frame;
3586 	if (wep_challenge_len)
3587 		mac_hdr->fc.wep = LIM_WEP_IN_FC;
3588 	else
3589 		mac_hdr->fc.wep = LIM_NO_WEP_IN_FC;
3590 
3591 	/* Prepare BSSId */
3592 	if (LIM_IS_AP_ROLE(session))
3593 		qdf_mem_copy((uint8_t *) mac_hdr->bssId,
3594 			     (uint8_t *) session->bssId,
3595 			     sizeof(tSirMacAddr));
3596 
3597 	/* Prepare Authentication frame body */
3598 	body = frame + sizeof(tSirMacMgmtHdr);
3599 
3600 	if (wep_challenge_len) {
3601 		qdf_mem_copy(body, (uint8_t *) auth_frame, body_len);
3602 	} else {
3603 		*((uint16_t *) (body)) =
3604 			sir_swap_u16if_needed(auth_frame->authAlgoNumber);
3605 		body += sizeof(uint16_t);
3606 		body_len -= sizeof(uint16_t);
3607 
3608 		*((uint16_t *) (body)) =
3609 			sir_swap_u16if_needed(
3610 				auth_frame->authTransactionSeqNumber);
3611 		body += sizeof(uint16_t);
3612 		body_len -= sizeof(uint16_t);
3613 
3614 		*((uint16_t *) (body)) =
3615 			sir_swap_u16if_needed(auth_frame->authStatusCode);
3616 		body += sizeof(uint16_t);
3617 		body_len -= sizeof(uint16_t);
3618 
3619 		if (challenge_req) {
3620 			if (body_len < SIR_MAC_AUTH_CHALLENGE_BODY_LEN) {
3621 				/* copy challenge IE id, len, challenge text */
3622 				*body = auth_frame->type;
3623 				body++;
3624 				body_len -= sizeof(uint8_t);
3625 				*body = auth_frame->length;
3626 				body++;
3627 				body_len -= sizeof(uint8_t);
3628 				qdf_mem_copy(body, auth_frame->challengeText,
3629 					     body_len);
3630 				pe_err("Incomplete challenge info: length: %d, expected: %d",
3631 				       body_len,
3632 				       SIR_MAC_AUTH_CHALLENGE_BODY_LEN);
3633 				body += body_len;
3634 				body_len = 0;
3635 			} else {
3636 				/* copy challenge IE id, len, challenge text */
3637 				*body = auth_frame->type;
3638 				body++;
3639 				*body = auth_frame->length;
3640 				body++;
3641 				qdf_mem_copy(body, auth_frame->challengeText,
3642 					     SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH);
3643 				body += SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH;
3644 				body_len -= SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH +
3645 					    SIR_MAC_CHALLENGE_ID_LEN;
3646 			}
3647 		}
3648 
3649 		if ((auth_frame->authAlgoNumber == eSIR_FT_AUTH) &&
3650 		    (auth_frame->authTransactionSeqNumber ==
3651 		     SIR_MAC_AUTH_FRAME_1) &&
3652 		     (session->ftPEContext.pFTPreAuthReq)) {
3653 
3654 			if (ft_ies_length > 0) {
3655 				qdf_mem_copy(body,
3656 					session->ftPEContext.
3657 						pFTPreAuthReq->ft_ies,
3658 					ft_ies_length);
3659 				pe_debug("Auth1 Frame FTIE is: ");
3660 				QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE,
3661 						   QDF_TRACE_LEVEL_DEBUG,
3662 						   (uint8_t *) body,
3663 						   ft_ies_length);
3664 			} else if (session->ftPEContext.
3665 					pFTPreAuthReq->pbssDescription) {
3666 				/* MDID attr is 54 */
3667 				*body = WLAN_ELEMID_MOBILITY_DOMAIN;
3668 				body++;
3669 				*body = SIR_MDIE_SIZE;
3670 				body++;
3671 				qdf_mem_copy(body,
3672 					&session->ftPEContext.pFTPreAuthReq->
3673 						pbssDescription->mdie[0],
3674 					SIR_MDIE_SIZE);
3675 			}
3676 		} else if ((auth_frame->authAlgoNumber ==
3677 					SIR_FILS_SK_WITHOUT_PFS) &&
3678 			   (auth_frame->authTransactionSeqNumber ==
3679 						SIR_MAC_AUTH_FRAME_1)) {
3680 			pe_debug("FILS: appending fils Auth data");
3681 			lim_add_fils_data_to_auth_frame(session, body);
3682 		}
3683 	}
3684 
3685 	if (mlo_ie_len && mlo_ie_buf) {
3686 		qdf_mem_copy(body, mlo_ie_buf, mlo_ie_len);
3687 		qdf_mem_free(mlo_ie_buf);
3688 	}
3689 
3690 	pe_nofl_info("Auth TX: vdev %d seq %d seq num %d status %d WEP %d to " QDF_MAC_ADDR_FMT,
3691 		     vdev_id, auth_frame->authTransactionSeqNumber,
3692 		     mac_ctx->mgmtSeqNum, auth_frame->authStatusCode,
3693 		     mac_hdr->fc.wep, QDF_MAC_ADDR_REF(mac_hdr->da));
3694 
3695 	if ((session->ftPEContext.pFTPreAuthReq) &&
3696 	    (!wlan_reg_is_24ghz_ch_freq(
3697 	     session->ftPEContext.pFTPreAuthReq->pre_auth_channel_freq)))
3698 		tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
3699 	else if (!wlan_reg_is_24ghz_ch_freq(session->curr_op_freq) ||
3700 		 session->opmode == QDF_P2P_CLIENT_MODE ||
3701 		 session->opmode == QDF_P2P_GO_MODE)
3702 		tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
3703 
3704 	if (session->opmode == QDF_P2P_CLIENT_MODE ||
3705 	    session->opmode == QDF_STA_MODE)
3706 		tx_flag |= HAL_USE_PEER_STA_REQUESTED_MASK;
3707 
3708 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
3709 			 session->peSessionId, mac_hdr->fc.subType));
3710 
3711 	if (mac_ctx->auth_ack_status != LIM_ACK_RCD_FAILURE &&
3712 	    mac_ctx->auth_ack_status != LIM_TX_FAILED)
3713 		mac_ctx->auth_ack_status = LIM_ACK_NOT_RCD;
3714 	min_rid = lim_get_min_session_txrate(session, NULL);
3715 	peer_rssi = mac_ctx->lim.bss_rssi;
3716 	lim_diag_mgmt_tx_event_report(mac_ctx, mac_hdr,
3717 				      session, QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS);
3718 
3719 	if (session->ftPEContext.pFTPreAuthReq)
3720 		ch_freq_tx_frame = session->ftPEContext.
3721 				pFTPreAuthReq->pre_auth_channel_freq;
3722 
3723 	qdf_status = wma_tx_frameWithTxComplete(mac_ctx, packet,
3724 				 (uint16_t)frame_len,
3725 				 TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS,
3726 				 7, lim_tx_complete, frame,
3727 				 lim_auth_tx_complete_cnf,
3728 				 tx_flag, vdev_id, false,
3729 				 ch_freq_tx_frame, min_rid, peer_rssi, 0);
3730 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
3731 		session->peSessionId, qdf_status));
3732 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
3733 		pe_err("*** Could not send Auth frame, retCode=%X ***",
3734 			qdf_status);
3735 		mac_ctx->auth_ack_status = LIM_TX_FAILED;
3736 		lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_AUTH_ACK_EVENT,
3737 				session, SENT_FAIL, QDF_STATUS_E_FAILURE);
3738 	/* Pkt will be freed up by the callback */
3739 	}
3740 	return;
3741 }
3742 
3743 static
3744 void lim_delete_deauth_all_pending_sta(struct mac_context *mac_ctx,
3745 				       struct pe_session *session)
3746 {
3747 	int i = 0;
3748 	tpDphHashNode sta_ds = NULL;
3749 
3750 	if (!session)
3751 		return;
3752 
3753 	for (i = 0; i < session->dph.dphHashTable.size; i++) {
3754 		sta_ds = dph_get_hash_entry(mac_ctx, i,
3755 					    &session->dph.dphHashTable);
3756 		/*
3757 		 * In case of multiple STA kickout on SAP interface,
3758 		 * DeauthAckTimer would be started only for the first
3759 		 * deauth queued. So, the ack timeout would not be
3760 		 * fired for other deauth frames. Therefore as part of
3761 		 * of this timer expiry(of first queued deauth), trigger
3762 		 * sta deletion for all the peers with deauth in progress.
3763 		 *
3764 		 * Do not trigger deletion if sta_deletion is already in
3765 		 * progress.
3766 		 */
3767 
3768 		if (!sta_ds || !sta_ds->valid ||
3769 		    sta_ds->sta_deletion_in_progress ||
3770 		    !sta_ds->is_disassoc_deauth_in_progress)
3771 			continue;
3772 
3773 		sta_ds->is_disassoc_deauth_in_progress = 0;
3774 		lim_trigger_sta_deletion(mac_ctx, sta_ds, session);
3775 	}
3776 }
3777 
3778 QDF_STATUS lim_send_deauth_cnf(struct mac_context *mac_ctx, uint8_t vdev_id)
3779 {
3780 	uint16_t aid;
3781 	tpDphHashNode sta_ds;
3782 	tLimMlmDeauthReq *deauth_req;
3783 	tLimMlmDeauthCnf deauth_cnf;
3784 	struct pe_session *session_entry;
3785 	QDF_STATUS qdf_status;
3786 	uint32_t i;
3787 
3788 	deauth_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq;
3789 	if (deauth_req) {
3790 		if (tx_timer_running(
3791 			&mac_ctx->lim.lim_timers.gLimDeauthAckTimer))
3792 			lim_deactivate_and_change_timer(mac_ctx,
3793 							eLIM_DEAUTH_ACK_TIMER);
3794 
3795 		session_entry = pe_find_session_by_session_id(mac_ctx,
3796 					deauth_req->sessionId);
3797 		if (!session_entry) {
3798 			pe_err("session does not exist for given sessionId");
3799 			deauth_cnf.resultCode =
3800 				eSIR_SME_INVALID_PARAMETERS;
3801 			goto end;
3802 		}
3803 		if (qdf_is_macaddr_broadcast(&deauth_req->peer_macaddr) &&
3804 		    mac_ctx->mlme_cfg->sap_cfg.is_sap_bcast_deauth_enabled) {
3805 			if (wlan_vdev_mlme_is_mlo_ap(session_entry->vdev)) {
3806 				for (i = 1;
3807 				     i < session_entry->dph.dphHashTable.size;
3808 				     i++) {
3809 					sta_ds = dph_get_hash_entry(
3810 					    mac_ctx, i,
3811 					    &session_entry->dph.dphHashTable);
3812 					if (!sta_ds)
3813 						continue;
3814 					if (lim_is_mlo_conn(session_entry,
3815 							    sta_ds))
3816 						lim_mlo_notify_peer_disconn(
3817 								session_entry,
3818 								sta_ds);
3819 				}
3820 			}
3821 			qdf_status = lim_del_sta_all(mac_ctx, session_entry);
3822 			qdf_mem_free(deauth_req);
3823 			mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq =
3824 									 NULL;
3825 			return qdf_status;
3826 		}
3827 
3828 		sta_ds =
3829 			dph_lookup_hash_entry(mac_ctx,
3830 					      deauth_req->peer_macaddr.bytes,
3831 					      &aid,
3832 					      &session_entry->
3833 					      dph.dphHashTable);
3834 		if (!sta_ds) {
3835 			deauth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
3836 			goto end;
3837 		}
3838 
3839 		lim_mlo_notify_peer_disconn(session_entry, sta_ds);
3840 
3841 		/* / Receive path cleanup with dummy packet */
3842 		lim_ft_cleanup_pre_auth_info(mac_ctx, session_entry);
3843 		lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry, true);
3844 		if ((session_entry->limSystemRole == eLIM_STA_ROLE) &&
3845 		    (
3846 #ifdef FEATURE_WLAN_ESE
3847 		    (wlan_cm_get_ese_assoc(mac_ctx->pdev,
3848 					   session_entry->vdev_id)) ||
3849 #endif
3850 		    (cm_is_fast_roam_enabled(mac_ctx->psoc)) ||
3851 		    (session_entry->is11Rconnection))) {
3852 			pe_debug("FT Preauth (%pK,%d) Deauth rc %d src = %d",
3853 				 session_entry,
3854 				 session_entry->peSessionId,
3855 				 deauth_req->reasonCode,
3856 				 deauth_req->deauthTrigger);
3857 			lim_ft_cleanup(mac_ctx, session_entry);
3858 		} else {
3859 #ifdef FEATURE_WLAN_ESE
3860 			pe_debug("No FT Preauth Session Cleanup in role %d"
3861 				 " isESE %d"
3862 				 " isLFR %d"
3863 				 " is11r %d, Deauth reason %d Trigger = %d",
3864 				 session_entry->limSystemRole,
3865 				 mac_ctx->mlme_cfg->lfr.ese_enabled,
3866 				 cm_is_fast_roam_enabled(mac_ctx->psoc),
3867 				 session_entry->is11Rconnection,
3868 				 deauth_req->reasonCode,
3869 				 deauth_req->deauthTrigger);
3870 #else
3871 			pe_debug("No FT Preauth Session Cleanup in role %d"
3872 				 " isLFR %d"
3873 				 " is11r %d, Deauth reason %d Trigger = %d",
3874 				 session_entry->limSystemRole,
3875 				 cm_is_fast_roam_enabled(mac_ctx->psoc),
3876 				 session_entry->is11Rconnection,
3877 				 deauth_req->reasonCode,
3878 				 deauth_req->deauthTrigger);
3879 #endif
3880 		}
3881 		/* Free up buffer allocated for mlmDeauthReq */
3882 		qdf_mem_free(deauth_req);
3883 		mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = NULL;
3884 	} else  {
3885 		session_entry =  pe_find_session_by_vdev_id(mac_ctx, vdev_id);
3886 		if (!session_entry || (session_entry->opmode != QDF_SAP_MODE &&
3887 				       session_entry->opmode !=QDF_P2P_GO_MODE))
3888 			return QDF_STATUS_SUCCESS;
3889 		/*
3890 		 * If deauth request is not present, then the deauth could
3891 		 * be from the SB STA kickout queued in SAP context.
3892 		 * Cleanup all the STA which has is_disassoc_deauth_in_progress
3893 		 */
3894 		lim_delete_deauth_all_pending_sta(mac_ctx, session_entry);
3895 	}
3896 	return QDF_STATUS_SUCCESS;
3897 end:
3898 	qdf_copy_macaddr(&deauth_cnf.peer_macaddr,
3899 			 &deauth_req->peer_macaddr);
3900 	deauth_cnf.deauthTrigger = deauth_req->deauthTrigger;
3901 	deauth_cnf.aid = deauth_req->aid;
3902 	deauth_cnf.sessionId = deauth_req->sessionId;
3903 
3904 	/* Free up buffer allocated */
3905 	/* for mlmDeauthReq */
3906 	qdf_mem_free(deauth_req);
3907 	mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = NULL;
3908 
3909 	lim_post_sme_message(mac_ctx,
3910 			     LIM_MLM_DEAUTH_CNF, (uint32_t *) &deauth_cnf);
3911 	return QDF_STATUS_SUCCESS;
3912 }
3913 
3914 /**
3915  * lim_send_disassoc_cnf() - Send disassoc confirmation to SME
3916  *
3917  * @mac_ctx: Handle to MAC context
3918  *
3919  * Sends disassoc confirmation to SME. Removes disassoc request stored
3920  * in lim.
3921  *
3922  * Return: QDF_STATUS_SUCCESS
3923  */
3924 
3925 QDF_STATUS lim_send_disassoc_cnf(struct mac_context *mac_ctx)
3926 {
3927 	uint16_t aid;
3928 	tpDphHashNode sta_ds;
3929 	tLimMlmDisassocCnf disassoc_cnf;
3930 	struct pe_session *pe_session;
3931 	tLimMlmDisassocReq *disassoc_req;
3932 
3933 	disassoc_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq;
3934 	if (disassoc_req) {
3935 		if (tx_timer_running(
3936 			&mac_ctx->lim.lim_timers.gLimDisassocAckTimer))
3937 			lim_deactivate_and_change_timer(mac_ctx,
3938 				eLIM_DISASSOC_ACK_TIMER);
3939 
3940 		pe_session = pe_find_session_by_session_id(
3941 					mac_ctx, disassoc_req->sessionId);
3942 		if (!pe_session) {
3943 			pe_err("No session for given sessionId");
3944 			disassoc_cnf.resultCode =
3945 				eSIR_SME_INVALID_PARAMETERS;
3946 			goto end;
3947 		}
3948 
3949 		sta_ds = dph_lookup_hash_entry(mac_ctx,
3950 				disassoc_req->peer_macaddr.bytes, &aid,
3951 				&pe_session->dph.dphHashTable);
3952 		if (!sta_ds) {
3953 			pe_err("StaDs Null");
3954 			disassoc_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
3955 			goto end;
3956 		}
3957 
3958 		lim_mlo_notify_peer_disconn(pe_session, sta_ds);
3959 
3960 		/* Receive path cleanup with dummy packet */
3961 		if (QDF_STATUS_SUCCESS !=
3962 		    lim_cleanup_rx_path(mac_ctx, sta_ds, pe_session, true)) {
3963 			disassoc_cnf.resultCode =
3964 				eSIR_SME_RESOURCES_UNAVAILABLE;
3965 			pe_err("cleanup_rx_path error");
3966 			goto end;
3967 		}
3968 		if (LIM_IS_STA_ROLE(pe_session) &&
3969 		    (disassoc_req->reasonCode !=
3970 		     REASON_AUTHORIZED_ACCESS_LIMIT_REACHED)) {
3971 			pe_debug("FT Preauth Session (%pK %d) Clean up",
3972 				 pe_session, pe_session->peSessionId);
3973 
3974 			/* Delete FT session if there exists one */
3975 			lim_ft_cleanup_pre_auth_info(mac_ctx, pe_session);
3976 		}
3977 		/* Free up buffer allocated for mlmDisassocReq */
3978 		qdf_mem_free(disassoc_req);
3979 		mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq = NULL;
3980 		return QDF_STATUS_SUCCESS;
3981 	} else {
3982 		return QDF_STATUS_SUCCESS;
3983 	}
3984 end:
3985 	qdf_mem_copy((uint8_t *) &disassoc_cnf.peerMacAddr,
3986 		     (uint8_t *) disassoc_req->peer_macaddr.bytes,
3987 		     QDF_MAC_ADDR_SIZE);
3988 	disassoc_cnf.aid = disassoc_req->aid;
3989 	disassoc_cnf.disassocTrigger = disassoc_req->disassocTrigger;
3990 
3991 	/* Update PE session ID */
3992 	disassoc_cnf.sessionId = disassoc_req->sessionId;
3993 
3994 	if (disassoc_req) {
3995 		/* / Free up buffer allocated for mlmDisassocReq */
3996 		qdf_mem_free(disassoc_req);
3997 		mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq = NULL;
3998 	}
3999 
4000 	lim_post_sme_message(mac_ctx, LIM_MLM_DISASSOC_CNF,
4001 		(uint32_t *) &disassoc_cnf);
4002 	return QDF_STATUS_SUCCESS;
4003 }
4004 
4005 QDF_STATUS lim_disassoc_tx_complete_cnf(void *context,
4006 					uint32_t tx_success,
4007 					void *params)
4008 {
4009 	struct mac_context *max_ctx = (struct mac_context *)context;
4010 
4011 	pe_debug("tx_success: %d", tx_success);
4012 
4013 	return lim_send_disassoc_cnf(max_ctx);
4014 }
4015 
4016 static QDF_STATUS lim_disassoc_tx_complete_cnf_handler(void *context,
4017 						       qdf_nbuf_t buf,
4018 						       uint32_t tx_success,
4019 						       void *params)
4020 {
4021 	struct mac_context *max_ctx = (struct mac_context *)context;
4022 	QDF_STATUS status_code;
4023 	struct scheduler_msg msg = {0};
4024 
4025 	if (params)
4026 		wlan_send_tx_complete_event(context, buf, params, tx_success,
4027 					    WLAN_DISASSOC_TX);
4028 
4029 	pe_debug("tx_success: %d", tx_success);
4030 
4031 	if (buf)
4032 		qdf_nbuf_free(buf);
4033 	msg.type = (uint16_t) WMA_DISASSOC_TX_COMP;
4034 	msg.bodyptr = params;
4035 	msg.bodyval = tx_success;
4036 
4037 	status_code = lim_post_msg_high_priority(max_ctx, &msg);
4038 	if (status_code != QDF_STATUS_SUCCESS)
4039 		pe_err("posting message: %X to LIM failed, reason: %d",
4040 		       msg.type, status_code);
4041 	return status_code;
4042 }
4043 
4044 QDF_STATUS lim_deauth_tx_complete_cnf(void *context,
4045 				      uint32_t tx_success,
4046 				      void *params)
4047 {
4048 	struct mac_context *mac_ctx = (struct mac_context *)context;
4049 	struct wmi_mgmt_params *mgmt_params =
4050 				(struct wmi_mgmt_params *)params;
4051 	uint8_t vdev_id = WLAN_INVALID_VDEV_ID;
4052 
4053 	pe_debug("tx_success: %d", tx_success);
4054 	if (mgmt_params)
4055 		vdev_id = mgmt_params->vdev_id;
4056 	qdf_mem_free(params);
4057 
4058 	return lim_send_deauth_cnf(mac_ctx, vdev_id);
4059 }
4060 
4061 static QDF_STATUS lim_ap_delete_sta_upon_deauth_tx(struct mac_context *mac_ctx,
4062 						   struct pe_session *session,
4063 						   tSirMacAddr peer)
4064 {
4065 	tpDphHashNode stads;
4066 	uint16_t aid;
4067 
4068 	if (!session || (session->opmode != QDF_SAP_MODE &&
4069 			 session->opmode != QDF_P2P_GO_MODE))
4070 		return QDF_STATUS_E_FAILURE;
4071 
4072 	stads = dph_lookup_hash_entry(mac_ctx, peer, &aid,
4073 				      &session->dph.dphHashTable);
4074 
4075 	if (!stads || !stads->ocv_enabled ||
4076 	    stads->last_ocv_done_freq == session->curr_op_freq)
4077 		return QDF_STATUS_E_FAILURE;
4078 
4079 	/*
4080 	 * Proceed with sta deletion only if
4081 	 * is_disassoc_deauth_in_progress is set. If unset,
4082 	 * sta deletion will be handled by the deauth ack
4083 	 * timeout handler.
4084 	 */
4085 	if (!stads->is_disassoc_deauth_in_progress ||
4086 	    stads->sta_deletion_in_progress)
4087 		return QDF_STATUS_SUCCESS;
4088 
4089 	lim_trigger_sta_deletion(mac_ctx, stads, session);
4090 	return QDF_STATUS_SUCCESS;
4091 }
4092 
4093 static QDF_STATUS lim_deauth_tx_complete_cnf_handler(void *context,
4094 						     qdf_nbuf_t buf,
4095 						     uint32_t tx_success,
4096 						     void *params)
4097 {
4098 	struct mac_context *mac_ctx = (struct mac_context *)context;
4099 	QDF_STATUS status_code = QDF_STATUS_E_FAILURE;
4100 	struct scheduler_msg msg = {0};
4101 	tLimMlmDeauthReq *deauth_req;
4102 	struct pe_session *session = NULL;
4103 	tSirMacMgmtHdr *mac_hdr = NULL;
4104 	uint8_t vdev_id = WLAN_INVALID_VDEV_ID;
4105 	struct wmi_mgmt_params *mgmt_params =
4106 			(struct wmi_mgmt_params *)params;
4107 	struct wmi_mgmt_params *msg_params = NULL;
4108 
4109 	if (params)
4110 		wlan_send_tx_complete_event(context, buf, params, tx_success,
4111 					    WLAN_DEAUTH_TX);
4112 
4113 	deauth_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq;
4114 
4115 	pe_debug("tx_complete = %s tx_success = %d",
4116 		(tx_success == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK) ?
4117 		 "success" : "fail", tx_success);
4118 
4119 	if (buf && (qdf_nbuf_len(buf) > sizeof(struct wlan_frame_hdr) + 2))
4120 		mac_hdr = (tSirMacMgmtHdr *)qdf_nbuf_data(buf);
4121 
4122 	if (!deauth_req && mac_hdr) {
4123 		if (mgmt_params)
4124 			vdev_id = mgmt_params->vdev_id;
4125 		session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
4126 		status_code = lim_ap_delete_sta_upon_deauth_tx(mac_ctx, session,
4127 							       (uint8_t *)mac_hdr->da);
4128 	}
4129 
4130 	if (buf)
4131 		qdf_nbuf_free(buf);
4132 
4133 	/* Cleanup has been handled for SAP/GO context, return */
4134 	if (QDF_IS_STATUS_SUCCESS(status_code))
4135 		return QDF_STATUS_SUCCESS;
4136 
4137 	if (deauth_req)
4138 		session = pe_find_session_by_session_id(mac_ctx,
4139 				deauth_req->sessionId);
4140 	if (tx_success != WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK && session &&
4141 	    session->deauth_retry.retry_cnt) {
4142 		if (tx_timer_running(
4143 			&mac_ctx->lim.lim_timers.gLimDeauthAckTimer))
4144 			lim_deactivate_and_change_timer(mac_ctx,
4145 							eLIM_DEAUTH_ACK_TIMER);
4146 		lim_send_deauth_mgmt_frame(mac_ctx,
4147 				session->deauth_retry.reason_code,
4148 				session->deauth_retry.peer_macaddr.bytes,
4149 				session, true);
4150 		session->deauth_retry.retry_cnt--;
4151 		return QDF_STATUS_SUCCESS;
4152 	}
4153 
4154 	msg_params = qdf_mem_malloc(sizeof(struct wmi_mgmt_params));
4155 	if (!msg_params) {
4156 		pe_err("malloc failed");
4157 		return QDF_STATUS_E_NOMEM;
4158 	}
4159 
4160 	qdf_mem_copy(msg_params, mgmt_params, sizeof(struct wmi_mgmt_params));
4161 
4162 	msg.type = (uint16_t) WMA_DEAUTH_TX_COMP;
4163 	msg.bodyptr = msg_params;
4164 	msg.bodyval = tx_success;
4165 
4166 	status_code = lim_post_msg_high_priority(mac_ctx, &msg);
4167 	if (status_code != QDF_STATUS_SUCCESS) {
4168 		qdf_mem_free(msg_params);
4169 		pe_err("posting message: %X to LIM failed, reason: %d",
4170 		       msg.type, status_code);
4171 	}
4172 
4173 	return status_code;
4174 }
4175 
4176 /**
4177  * lim_append_ies_to_frame() - Append IEs to the frame
4178  *
4179  * @frame: Pointer to the frame buffer that needs to be populated
4180  * @frame_len: Pointer for current frame length
4181  * @ie: pointer for disconnect IEs
4182  *
4183  * This function is called by lim_send_disassoc_mgmt_frame and
4184  * lim_send_deauth_mgmt_frame APIs as part of disconnection.
4185  * Append IEs and update frame length.
4186  *
4187  * Return: None
4188  */
4189 static void
4190 lim_append_ies_to_frame(uint8_t *frame, uint32_t *frame_len,
4191 			struct element_info *ie)
4192 {
4193 	if (!ie || !ie->len || !ie->ptr)
4194 		return;
4195 	qdf_mem_copy(frame, ie->ptr, ie->len);
4196 	*frame_len += ie->len;
4197 	pe_debug("Appended IEs len: %u", ie->len);
4198 }
4199 
4200 /**
4201  * \brief This function is called to send Disassociate frame.
4202  *
4203  *
4204  * \param mac Pointer to Global MAC structure
4205  *
4206  * \param nReason Indicates the reason that need to be sent in
4207  * Disassociation frame
4208  *
4209  * \param peerMacAddr MAC address of the STA to which Disassociation frame is
4210  * sent
4211  *
4212  *
4213  */
4214 
4215 void
4216 lim_send_disassoc_mgmt_frame(struct mac_context *mac,
4217 			     uint16_t nReason,
4218 			     tSirMacAddr peer,
4219 			     struct pe_session *pe_session, bool waitForAck)
4220 {
4221 	tDot11fDisassociation frm;
4222 	uint8_t *pFrame;
4223 	tpSirMacMgmtHdr pMacHdr;
4224 	uint32_t nBytes, nPayload, nStatus;
4225 	void *pPacket;
4226 	QDF_STATUS qdf_status;
4227 	uint8_t txFlag = 0;
4228 	uint32_t val = 0;
4229 	uint8_t smeSessionId = 0;
4230 	struct element_info *discon_ie;
4231 
4232 	if (!pe_session) {
4233 		return;
4234 	}
4235 
4236 	/*
4237 	 * In case when cac timer is running for this SAP session then
4238 	 * avoid sending disassoc out. It is violation of dfs specification.
4239 	 */
4240 	if (((pe_session->opmode == QDF_SAP_MODE) ||
4241 	     (pe_session->opmode == QDF_P2P_GO_MODE)) &&
4242 	    (true == mac->sap.SapDfsInfo.is_dfs_cac_timer_running)) {
4243 		pe_info("CAC timer is running, drop disassoc from going out");
4244 		if (waitForAck)
4245 			lim_send_disassoc_cnf(mac);
4246 		return;
4247 	} else if (lim_is_ml_peer_state_disconn(mac, pe_session, peer)) {
4248 		/**
4249 		 * Check if disassoc is already sent on link vdev and ML peer
4250 		 * state is moved to ML_PEER_DISCONN_INITIATED. In which case,
4251 		 * do not send disassoc on assoc vdev, issue disassoc only if
4252 		 * this check fails.
4253 		 */
4254 		pe_debug("disassoc tx not required for vdev id %d",
4255 			 pe_session->vdev_id);
4256 		lim_send_disassoc_cnf(mac);
4257 		return;
4258 	}
4259 	smeSessionId = pe_session->smeSessionId;
4260 
4261 	qdf_mem_zero((uint8_t *) &frm, sizeof(frm));
4262 
4263 	frm.Reason.code = nReason;
4264 
4265 	nStatus = dot11f_get_packed_disassociation_size(mac, &frm, &nPayload);
4266 	if (DOT11F_FAILED(nStatus)) {
4267 		pe_err("Failed to calculate the packed size for a Disassociation (0x%08x)",
4268 			nStatus);
4269 		/* We'll fall back on the worst case scenario: */
4270 		nPayload = sizeof(tDot11fDisassociation);
4271 	} else if (DOT11F_WARNED(nStatus)) {
4272 		pe_warn("There were warnings while calculating the packed size for a Disassociation (0x%08x)",
4273 			nStatus);
4274 	}
4275 
4276 	nBytes = nPayload + sizeof(tSirMacMgmtHdr);
4277 
4278 	discon_ie = mlme_get_self_disconnect_ies(pe_session->vdev);
4279 	if (discon_ie && discon_ie->len)
4280 		nBytes += discon_ie->len;
4281 
4282 	qdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
4283 				      (void **)&pPacket);
4284 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
4285 		pe_err("Failed to allocate %d bytes for a Disassociation",
4286 			nBytes);
4287 		if (waitForAck)
4288 			lim_send_disassoc_cnf(mac);
4289 		return;
4290 	}
4291 	/* Paranoia: */
4292 	qdf_mem_zero(pFrame, nBytes);
4293 
4294 	/* Next, we fill out the buffer descriptor: */
4295 	lim_populate_mac_header(mac, pFrame, SIR_MAC_MGMT_FRAME,
4296 		SIR_MAC_MGMT_DISASSOC, peer, pe_session->self_mac_addr);
4297 	pMacHdr = (tpSirMacMgmtHdr) pFrame;
4298 
4299 	/* Prepare the BSSID */
4300 	sir_copy_mac_addr(pMacHdr->bssId, pe_session->bssId);
4301 
4302 	if (mac->is_usr_cfg_pmf_wep != PMF_WEP_DISABLE)
4303 		lim_set_protected_bit(mac, pe_session, peer, pMacHdr);
4304 	else
4305 		pe_debug("Skip WEP bit setting per usr cfg");
4306 
4307 	if (mac->is_usr_cfg_pmf_wep == PMF_INCORRECT_KEY)
4308 		txFlag |= HAL_USE_INCORRECT_KEY_PMF;
4309 
4310 	nStatus = dot11f_pack_disassociation(mac, &frm, pFrame +
4311 					     sizeof(tSirMacMgmtHdr),
4312 					     nPayload, &nPayload);
4313 	if (DOT11F_FAILED(nStatus)) {
4314 		pe_err("Failed to pack a Disassociation (0x%08x)",
4315 			nStatus);
4316 		cds_packet_free((void *)pPacket);
4317 		if (waitForAck)
4318 			lim_send_disassoc_cnf(mac);
4319 		return;
4320 	} else if (DOT11F_WARNED(nStatus)) {
4321 		pe_warn("There were warnings while packing a Disassociation (0x%08x)",
4322 			nStatus);
4323 	}
4324 
4325 	/* Copy disconnect IEs to the end of the frame */
4326 	lim_append_ies_to_frame(pFrame + sizeof(tSirMacMgmtHdr) + nPayload,
4327 				&nPayload, discon_ie);
4328 	mlme_free_self_disconnect_ies(pe_session->vdev);
4329 
4330 	pe_nofl_info("Disassoc TX: vdev %d seq %d reason %u and waitForAck %d to " QDF_MAC_ADDR_FMT " From " QDF_MAC_ADDR_FMT,
4331 		     pe_session->vdev_id, mac->mgmtSeqNum, nReason, waitForAck,
4332 		     QDF_MAC_ADDR_REF(pMacHdr->da),
4333 		     QDF_MAC_ADDR_REF(pe_session->self_mac_addr));
4334 
4335 	if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) ||
4336 	    pe_session->opmode == QDF_P2P_CLIENT_MODE ||
4337 	    pe_session->opmode == QDF_P2P_GO_MODE)
4338 		txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
4339 
4340 	txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK;
4341 
4342 	pe_session->deauth_disassoc_rc = nReason;
4343 	if (waitForAck) {
4344 		MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
4345 				 pe_session->peSessionId,
4346 				 pMacHdr->fc.subType));
4347 		lim_diag_mgmt_tx_event_report(mac, pMacHdr,
4348 					      pe_session, QDF_STATUS_SUCCESS,
4349 					      QDF_STATUS_SUCCESS);
4350 
4351 		/* Queue Disassociation frame in high priority WQ */
4352 		/* get the duration from the request */
4353 		qdf_status =
4354 			wma_tx_frameWithTxComplete(mac, pPacket, (uint16_t) nBytes,
4355 					 TXRX_FRM_802_11_MGMT,
4356 					 ANI_TXDIR_TODS, 7, lim_tx_complete,
4357 					 pFrame, lim_disassoc_tx_complete_cnf_handler,
4358 					 txFlag, smeSessionId, false, 0,
4359 					 RATEID_DEFAULT, 0, 0);
4360 		MTRACE(qdf_trace
4361 			       (QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
4362 			       pe_session->peSessionId, qdf_status));
4363 
4364 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
4365 			pe_err("Failed to send disassoc frame");
4366 			lim_send_disassoc_cnf(mac);
4367 			return;
4368 		}
4369 
4370 		val = SYS_MS_TO_TICKS(LIM_DISASSOC_DEAUTH_ACK_TIMEOUT);
4371 
4372 		if (tx_timer_change
4373 			    (&mac->lim.lim_timers.gLimDisassocAckTimer, val, 0)
4374 		    != TX_SUCCESS) {
4375 			pe_err("Unable to change Disassoc ack Timer val");
4376 			return;
4377 		} else if (TX_SUCCESS !=
4378 			   tx_timer_activate(&mac->lim.lim_timers.
4379 					     gLimDisassocAckTimer)) {
4380 			pe_err("Unable to activate Disassoc ack Timer");
4381 			lim_deactivate_and_change_timer(mac,
4382 							eLIM_DISASSOC_ACK_TIMER);
4383 			return;
4384 		}
4385 	} else {
4386 		MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
4387 				 pe_session->peSessionId,
4388 				 pMacHdr->fc.subType));
4389 		lim_diag_mgmt_tx_event_report(mac, pMacHdr,
4390 					      pe_session,
4391 					      QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS);
4392 		wlan_connectivity_mgmt_event(mac->psoc,
4393 					     (struct wlan_frame_hdr *)pMacHdr,
4394 					     pe_session->vdev_id, nReason,
4395 					     QDF_TX_RX_STATUS_OK,
4396 					     mac->lim.bss_rssi, 0, 0, 0, 0,
4397 					     WLAN_DISASSOC_TX);
4398 
4399 		/* Queue Disassociation frame in high priority WQ */
4400 		qdf_status = wma_tx_frame(mac, pPacket, (uint16_t) nBytes,
4401 					TXRX_FRM_802_11_MGMT,
4402 					ANI_TXDIR_TODS,
4403 					7,
4404 					lim_tx_complete, pFrame, txFlag,
4405 					smeSessionId, 0, RATEID_DEFAULT, 0);
4406 		MTRACE(qdf_trace
4407 			       (QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
4408 			       pe_session->peSessionId, qdf_status));
4409 		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
4410 			pe_err("Failed to send Disassociation (%X)!",
4411 				qdf_status);
4412 			/* Pkt will be freed up by the callback */
4413 		}
4414 	}
4415 } /* End lim_send_disassoc_mgmt_frame. */
4416 
4417 /**
4418  * \brief This function is called to send a Deauthenticate frame
4419  *
4420  *
4421  * \param mac Pointer to global MAC structure
4422  *
4423  * \param nReason Indicates the reason that need to be sent in the
4424  * Deauthenticate frame
4425  *
4426  * \param peer address of the STA to which the frame is to be sent
4427  *
4428  *
4429  */
4430 
4431 void
4432 lim_send_deauth_mgmt_frame(struct mac_context *mac,
4433 			   uint16_t nReason,
4434 			   tSirMacAddr peer,
4435 			   struct pe_session *pe_session, bool waitForAck)
4436 {
4437 	tDot11fDeAuth frm;
4438 	uint8_t *pFrame;
4439 	tpSirMacMgmtHdr pMacHdr;
4440 	uint32_t nBytes, nPayload, nStatus;
4441 	void *pPacket;
4442 	QDF_STATUS qdf_status;
4443 	uint8_t txFlag = 0;
4444 	uint32_t val = 0;
4445 #ifdef FEATURE_WLAN_TDLS
4446 	uint16_t aid;
4447 	tpDphHashNode sta;
4448 #endif
4449 	uint8_t smeSessionId = 0;
4450 	struct element_info *discon_ie;
4451 	bool drop_deauth = false;
4452 
4453 	if (!pe_session) {
4454 		return;
4455 	}
4456 
4457 	/*
4458 	 * Avoid sending deauth frame out when
4459 	 * 1. CAC timer is running for this SAP session,
4460 	 *    It is avoid violation of dfs specification.
4461 	 * 2. Silent deauth is requested for a particular peer
4462 	 */
4463 	if ((pe_session->opmode == QDF_SAP_MODE) ||
4464 	    (pe_session->opmode == QDF_P2P_GO_MODE)) {
4465 		if (mac->sap.SapDfsInfo.is_dfs_cac_timer_running) {
4466 			pe_info("CAC timer is running, drop the deauth from going out");
4467 			drop_deauth = true;
4468 		}
4469 		if (nReason == REASON_HOST_TRIGGERED_SILENT_DEAUTH) {
4470 			pe_info("Silent deauth, remove the peer");
4471 			drop_deauth = true;
4472 		}
4473 		if (drop_deauth) {
4474 			if (waitForAck)
4475 				lim_send_deauth_cnf(mac, pe_session->vdev_id);
4476 			return;
4477 		}
4478 	} else if (lim_is_ml_peer_state_disconn(mac, pe_session, peer)) {
4479 		/**
4480 		 * Check if deauth is already sent on link vdev and ML peer
4481 		 * state is moved to ML_PEER_DISCONN_INITIATED. In which case,
4482 		 * do not send deauth on assoc vdev as well. Issue deauth only
4483 		 * if this check fails.
4484 		 */
4485 		pe_debug("Deauth tx not required for vdev id %d",
4486 			 pe_session->vdev_id);
4487 		lim_send_deauth_cnf(mac, pe_session->vdev_id);
4488 		return;
4489 	}
4490 	smeSessionId = pe_session->smeSessionId;
4491 
4492 	qdf_mem_zero((uint8_t *) &frm, sizeof(frm));
4493 
4494 	frm.Reason.code = nReason;
4495 
4496 	nStatus = dot11f_get_packed_de_auth_size(mac, &frm, &nPayload);
4497 	if (DOT11F_FAILED(nStatus)) {
4498 		pe_err("Failed to calculate the packed size for a De-Authentication (0x%08x)",
4499 			nStatus);
4500 		/* We'll fall back on the worst case scenario: */
4501 		nPayload = sizeof(tDot11fDeAuth);
4502 	} else if (DOT11F_WARNED(nStatus)) {
4503 		pe_warn("There were warnings while calculating the packed size for a De-Authentication (0x%08x)",
4504 			nStatus);
4505 	}
4506 
4507 	nBytes = nPayload + sizeof(tSirMacMgmtHdr);
4508 	discon_ie = mlme_get_self_disconnect_ies(pe_session->vdev);
4509 	if (discon_ie && discon_ie->len)
4510 		nBytes += discon_ie->len;
4511 
4512 	qdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
4513 				      (void **)&pPacket);
4514 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
4515 		pe_err("Failed to allocate %d bytes for a De-Authentication",
4516 			nBytes);
4517 		if (waitForAck)
4518 			lim_send_deauth_cnf(mac, pe_session->vdev_id);
4519 		return;
4520 	}
4521 	/* Paranoia: */
4522 	qdf_mem_zero(pFrame, nBytes);
4523 
4524 	/* Next, we fill out the buffer descriptor: */
4525 	lim_populate_mac_header(mac, pFrame, SIR_MAC_MGMT_FRAME,
4526 		SIR_MAC_MGMT_DEAUTH, peer, pe_session->self_mac_addr);
4527 	pMacHdr = (tpSirMacMgmtHdr) pFrame;
4528 
4529 	/* Prepare the BSSID */
4530 	sir_copy_mac_addr(pMacHdr->bssId, pe_session->bssId);
4531 
4532 	lim_set_protected_bit(mac, pe_session, peer, pMacHdr);
4533 
4534 	nStatus = dot11f_pack_de_auth(mac, &frm, pFrame +
4535 				      sizeof(tSirMacMgmtHdr), nPayload, &nPayload);
4536 	if (DOT11F_FAILED(nStatus)) {
4537 		pe_err("Failed to pack a DeAuthentication (0x%08x)",
4538 			nStatus);
4539 		cds_packet_free((void *)pPacket);
4540 		if (waitForAck)
4541 			lim_send_deauth_cnf(mac, pe_session->vdev_id);
4542 		return;
4543 	} else if (DOT11F_WARNED(nStatus)) {
4544 		pe_warn("There were warnings while packing a De-Authentication (0x%08x)",
4545 			nStatus);
4546 	}
4547 
4548 	/* Copy disconnect IEs to the end of the frame */
4549 	lim_append_ies_to_frame(pFrame + sizeof(tSirMacMgmtHdr) + nPayload,
4550 				&nPayload, discon_ie);
4551 	mlme_free_self_disconnect_ies(pe_session->vdev);
4552 
4553 	pe_nofl_rl_info("Deauth TX: vdev %d seq_num %d reason %u waitForAck %d to " QDF_MAC_ADDR_FMT " from " QDF_MAC_ADDR_FMT,
4554 			pe_session->vdev_id, mac->mgmtSeqNum, nReason, waitForAck,
4555 			QDF_MAC_ADDR_REF(pMacHdr->da),
4556 			QDF_MAC_ADDR_REF(pe_session->self_mac_addr));
4557 
4558 	if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) ||
4559 	    pe_session->opmode == QDF_P2P_CLIENT_MODE ||
4560 	    pe_session->opmode == QDF_P2P_GO_MODE)
4561 		txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
4562 
4563 	txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK;
4564 #ifdef FEATURE_WLAN_TDLS
4565 	sta =
4566 		dph_lookup_hash_entry(mac, peer, &aid,
4567 				      &pe_session->dph.dphHashTable);
4568 #endif
4569 
4570 	pe_session->deauth_disassoc_rc = nReason;
4571 	if (waitForAck) {
4572 		MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
4573 				 pe_session->peSessionId,
4574 				 pMacHdr->fc.subType));
4575 		lim_diag_mgmt_tx_event_report(mac, pMacHdr,
4576 					      pe_session,
4577 					      QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS);
4578 		if (pe_session->opmode == QDF_STA_MODE &&
4579 		    mac->mlme_cfg->sta.deauth_retry_cnt &&
4580 		    !pe_session->deauth_retry.retry_cnt) {
4581 			pe_session->deauth_retry.retry_cnt =
4582 				mac->mlme_cfg->sta.deauth_retry_cnt;
4583 			pe_session->deauth_retry.reason_code = nReason;
4584 			qdf_mem_copy(pe_session->deauth_retry.peer_macaddr.bytes,
4585 					 peer, QDF_MAC_ADDR_SIZE);
4586 		}
4587 
4588 		/* Queue Disassociation frame in high priority WQ */
4589 		qdf_status =
4590 			wma_tx_frameWithTxComplete(mac, pPacket, (uint16_t) nBytes,
4591 					 TXRX_FRM_802_11_MGMT,
4592 					 ANI_TXDIR_TODS, 7, lim_tx_complete,
4593 					 pFrame, lim_deauth_tx_complete_cnf_handler,
4594 					 txFlag, smeSessionId, false, 0,
4595 					 RATEID_DEFAULT, 0, 0);
4596 		MTRACE(qdf_trace
4597 			       (QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
4598 			       pe_session->peSessionId, qdf_status));
4599 		/* Pkt will be freed up by the callback lim_tx_complete */
4600 		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
4601 			pe_err("Failed to send De-Authentication (%X)!",
4602 				qdf_status);
4603 
4604 			/* Call lim_process_deauth_ack_timeout which will send
4605 			 * DeauthCnf for this frame
4606 			 */
4607 			lim_process_deauth_ack_timeout(mac,
4608 						       pe_session->peSessionId);
4609 			return;
4610 		}
4611 
4612 		val = SYS_MS_TO_TICKS(LIM_DISASSOC_DEAUTH_ACK_TIMEOUT);
4613 		if (tx_timer_change_context(
4614 				&mac->lim.lim_timers.gLimDeauthAckTimer,
4615 				pe_session->vdev_id) != TX_SUCCESS) {
4616 			pe_err("Unable to update the vdev id in the Deauth ack timer");
4617 			return;
4618 		} else if (tx_timer_change
4619 			    (&mac->lim.lim_timers.gLimDeauthAckTimer, val, 0)
4620 		    != TX_SUCCESS) {
4621 			pe_err("Unable to change Deauth ack Timer val");
4622 			return;
4623 		} else if (TX_SUCCESS !=
4624 			   tx_timer_activate(&mac->lim.lim_timers.
4625 					     gLimDeauthAckTimer)) {
4626 			pe_err("Unable to activate Deauth ack Timer");
4627 			lim_deactivate_and_change_timer(mac,
4628 							eLIM_DEAUTH_ACK_TIMER);
4629 			return;
4630 		}
4631 	} else {
4632 		MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
4633 				 pe_session->peSessionId,
4634 				 pMacHdr->fc.subType));
4635 #ifdef FEATURE_WLAN_TDLS
4636 		if ((sta)
4637 		    && (STA_ENTRY_TDLS_PEER == sta->staType)) {
4638 			/* Queue Disassociation frame in high priority WQ */
4639 			lim_diag_mgmt_tx_event_report(mac, pMacHdr,
4640 						      pe_session,
4641 						      QDF_STATUS_SUCCESS,
4642 						      QDF_STATUS_SUCCESS);
4643 			qdf_status =
4644 				wma_tx_frame(mac, pPacket, (uint16_t) nBytes,
4645 					   TXRX_FRM_802_11_MGMT, ANI_TXDIR_IBSS,
4646 					   7, lim_tx_complete, pFrame, txFlag,
4647 					   smeSessionId, 0, RATEID_DEFAULT, 0);
4648 		} else {
4649 #endif
4650 		lim_diag_mgmt_tx_event_report(mac, pMacHdr,
4651 					      pe_session,
4652 					      QDF_STATUS_SUCCESS,
4653 					      QDF_STATUS_SUCCESS);
4654 
4655 		wlan_connectivity_mgmt_event(mac->psoc,
4656 					     (struct wlan_frame_hdr *)pMacHdr,
4657 					     pe_session->vdev_id, nReason,
4658 					     QDF_TX_RX_STATUS_OK,
4659 					     mac->lim.bss_rssi, 0, 0, 0, 0,
4660 					     WLAN_DEAUTH_TX);
4661 
4662 		/* Queue Disassociation frame in high priority WQ */
4663 		qdf_status =
4664 			wma_tx_frame(mac, pPacket, (uint16_t) nBytes,
4665 				   TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS,
4666 				   7, lim_tx_complete, pFrame, txFlag,
4667 				   smeSessionId, 0, RATEID_DEFAULT, 0);
4668 #ifdef FEATURE_WLAN_TDLS
4669 	}
4670 #endif
4671 		MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
4672 				 pe_session->peSessionId, qdf_status));
4673 		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
4674 			pe_err("Failed to send De-Authentication (%X)!",
4675 				qdf_status);
4676 			/* Pkt will be freed up by the callback */
4677 		}
4678 	}
4679 
4680 } /* End lim_send_deauth_mgmt_frame. */
4681 
4682 #ifdef ANI_SUPPORT_11H
4683 /**
4684  * \brief Send a Measurement Report Action frame
4685  *
4686  *
4687  * \param mac Pointer to the global MAC structure
4688  *
4689  * \param pMeasReqFrame Address of a tSirMacMeasReqActionFrame
4690  *
4691  * \return QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE else
4692  *
4693  *
4694  */
4695 
4696 QDF_STATUS
4697 lim_send_meas_report_frame(struct mac_context *mac,
4698 			   tpSirMacMeasReqActionFrame pMeasReqFrame,
4699 			   tSirMacAddr peer, struct pe_session *pe_session)
4700 {
4701 	tDot11fMeasurementReport frm;
4702 	uint8_t *pFrame;
4703 	QDF_STATUS nSirStatus;
4704 	tpSirMacMgmtHdr pMacHdr;
4705 	uint32_t nBytes, nPayload, nStatus;
4706 	void *pPacket;
4707 	QDF_STATUS qdf_status;
4708 
4709 	qdf_mem_zero((uint8_t *) &frm, sizeof(frm));
4710 
4711 	frm.Category.category = ACTION_CATEGORY_SPECTRUM_MGMT;
4712 	frm.Action.action = ACTION_SPCT_MSR_RPRT;
4713 	frm.DialogToken.token = pMeasReqFrame->actionHeader.dialogToken;
4714 
4715 	switch (pMeasReqFrame->measReqIE.measType) {
4716 	case SIR_MAC_BASIC_MEASUREMENT_TYPE:
4717 		nSirStatus =
4718 			populate_dot11f_measurement_report0(mac, pMeasReqFrame,
4719 							    &frm.MeasurementReport);
4720 		break;
4721 	case SIR_MAC_CCA_MEASUREMENT_TYPE:
4722 		nSirStatus =
4723 			populate_dot11f_measurement_report1(mac, pMeasReqFrame,
4724 							    &frm.MeasurementReport);
4725 		break;
4726 	case SIR_MAC_RPI_MEASUREMENT_TYPE:
4727 		nSirStatus =
4728 			populate_dot11f_measurement_report2(mac, pMeasReqFrame,
4729 							    &frm.MeasurementReport);
4730 		break;
4731 	default:
4732 		pe_err("Unknown measurement type %d in limSendMeasReportFrame",
4733 			pMeasReqFrame->measReqIE.measType);
4734 		return QDF_STATUS_E_FAILURE;
4735 	}
4736 
4737 	if (QDF_STATUS_SUCCESS != nSirStatus)
4738 		return QDF_STATUS_E_FAILURE;
4739 
4740 	nStatus = dot11f_get_packed_measurement_report_size(mac, &frm, &nPayload);
4741 	if (DOT11F_FAILED(nStatus)) {
4742 		pe_err("Failed to calculate the packed size for a Measurement Report (0x%08x)",
4743 			nStatus);
4744 		/* We'll fall back on the worst case scenario: */
4745 		nPayload = sizeof(tDot11fMeasurementReport);
4746 	} else if (DOT11F_WARNED(nStatus)) {
4747 		pe_warn("There were warnings while calculating the packed size for a Measurement Report (0x%08x)",
4748 			nStatus);
4749 	}
4750 
4751 	nBytes = nPayload + sizeof(tSirMacMgmtHdr);
4752 
4753 	qdf_status =
4754 		cds_packet_alloc(mac->hdd_handle, TXRX_FRM_802_11_MGMT,
4755 				 (uint16_t) nBytes, (void **)&pFrame,
4756 				 (void **)&pPacket);
4757 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
4758 		pe_err("Failed to allocate %d bytes for a De-Authentication",
4759 		       nBytes);
4760 		return QDF_STATUS_E_FAILURE;
4761 	}
4762 	/* Paranoia: */
4763 	qdf_mem_zero(pFrame, nBytes);
4764 
4765 	/* Next, we fill out the buffer descriptor: */
4766 	lim_populate_mac_header(mac, pFrame, SIR_MAC_MGMT_FRAME,
4767 		SIR_MAC_MGMT_ACTION, peer);
4768 	pMacHdr = (tpSirMacMgmtHdr) pFrame;
4769 
4770 	qdf_mem_copy(pMacHdr->bssId, pe_session->bssId, sizeof(tSirMacAddr));
4771 
4772 	lim_set_protected_bit(mac, pe_session, peer, pMacHdr);
4773 
4774 	nStatus = dot11f_pack_measurement_report(mac, &frm, pFrame +
4775 						 sizeof(tSirMacMgmtHdr),
4776 						 nPayload, &nPayload);
4777 	if (DOT11F_FAILED(nStatus)) {
4778 		pe_err("Failed to pack a Measurement Report (0x%08x)",
4779 			nStatus);
4780 		cds_packet_free(mac->hdd_handle, TXRX_FRM_802_11_MGMT,
4781 				(void *)pFrame, (void *)pPacket);
4782 		return QDF_STATUS_E_FAILURE;    /* allocated! */
4783 	} else if (DOT11F_WARNED(nStatus)) {
4784 		pe_warn("There were warnings while packing a Measurement Report (0x%08x)",
4785 			nStatus);
4786 	}
4787 
4788 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
4789 			 ((pe_session) ? pe_session->
4790 			  peSessionId : NO_SESSION), pMacHdr->fc.subType));
4791 	qdf_status =
4792 		wma_tx_frame(mac, pPacket, (uint16_t) nBytes,
4793 			   TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
4794 			   lim_tx_complete, pFrame, 0, 0, RATEID_DEFAULT, 0);
4795 	MTRACE(qdf_trace
4796 		       (QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
4797 		       ((pe_session) ? pe_session->peSessionId : NO_SESSION),
4798 		       qdf_status));
4799 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
4800 		pe_err("Failed to send a Measurement Report (%X)!",
4801 			qdf_status);
4802 		/* Pkt will be freed up by the callback */
4803 		return QDF_STATUS_E_FAILURE;    /* just allocated... */
4804 	}
4805 
4806 	return QDF_STATUS_SUCCESS;
4807 
4808 } /* End lim_send_meas_report_frame. */
4809 
4810 /**
4811  * \brief Send a TPC Report Action frame
4812  *
4813  *
4814  * \param mac Pointer to the global MAC datastructure
4815  *
4816  * \param pTpcReqFrame Pointer to the received TPC Request
4817  *
4818  * \return QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE else
4819  *
4820  *
4821  */
4822 
4823 QDF_STATUS
4824 lim_send_tpc_report_frame(struct mac_context *mac,
4825 			  tpSirMacTpcReqActionFrame pTpcReqFrame,
4826 			  tSirMacAddr peer, struct pe_session *pe_session)
4827 {
4828 	tDot11fTPCReport frm;
4829 	uint8_t *pFrame;
4830 	tpSirMacMgmtHdr pMacHdr;
4831 	uint32_t nBytes, nPayload, nStatus;
4832 	void *pPacket;
4833 	QDF_STATUS qdf_status;
4834 	struct vdev_mlme_obj *mlme_obj;
4835 
4836 	qdf_mem_zero((uint8_t *) &frm, sizeof(frm));
4837 
4838 	frm.Category.category = ACTION_CATEGORY_SPECTRUM_MGMT;
4839 	frm.Action.action = ACTION_SPCT_TPC_RPRT;
4840 	frm.DialogToken.token = pTpcReqFrame->actionHeader.dialogToken;
4841 
4842 	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev);
4843 	if (mlme_obj)
4844 		frm.TPCReport.tx_power = mlme_obj->mgmt.generic.tx_pwrlimit;
4845 
4846 	frm.TPCReport.link_margin = 0;
4847 	frm.TPCReport.present = 1;
4848 
4849 	nStatus = dot11f_get_packed_tpc_report_size(mac, &frm, &nPayload);
4850 	if (DOT11F_FAILED(nStatus)) {
4851 		pe_err("Failed to calculate the packed size for a TPC Report (0x%08x)", nStatus);
4852 		/* We'll fall back on the worst case scenario: */
4853 		nPayload = sizeof(tDot11fTPCReport);
4854 	} else if (DOT11F_WARNED(nStatus)) {
4855 		pe_warn("There were warnings while calculating the packed size for a TPC Report (0x%08x)",
4856 			nStatus);
4857 	}
4858 
4859 	nBytes = nPayload + sizeof(tSirMacMgmtHdr);
4860 
4861 	qdf_status =
4862 		cds_packet_alloc(mac->hdd_handle, TXRX_FRM_802_11_MGMT,
4863 				 (uint16_t) nBytes, (void **)&pFrame,
4864 				 (void **)&pPacket);
4865 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
4866 		pe_err("Failed to allocate %d bytes for a TPC"
4867 			" Report", nBytes);
4868 		return QDF_STATUS_E_FAILURE;
4869 	}
4870 	/* Paranoia: */
4871 	qdf_mem_zero(pFrame, nBytes);
4872 
4873 	/* Next, we fill out the buffer descriptor: */
4874 	lim_populate_mac_header(mac, pFrame, SIR_MAC_MGMT_FRAME,
4875 		SIR_MAC_MGMT_ACTION, peer);
4876 
4877 	pMacHdr = (tpSirMacMgmtHdr) pFrame;
4878 
4879 	qdf_mem_copy(pMacHdr->bssId, pe_session->bssId, sizeof(tSirMacAddr));
4880 
4881 	lim_set_protected_bit(mac, pe_session, peer, pMacHdr);
4882 
4883 	nStatus = dot11f_pack_tpc_report(mac, &frm, pFrame +
4884 					 sizeof(tSirMacMgmtHdr),
4885 					 nPayload, &nPayload);
4886 	if (DOT11F_FAILED(nStatus)) {
4887 		pe_err("Failed to pack a TPC Report (0x%08x)",
4888 			nStatus);
4889 		cds_packet_free(mac->hdd_handle, TXRX_FRM_802_11_MGMT,
4890 				(void *)pFrame, (void *)pPacket);
4891 		return QDF_STATUS_E_FAILURE;    /* allocated! */
4892 	} else if (DOT11F_WARNED(nStatus)) {
4893 		pe_warn("There were warnings while packing a TPC Report (0x%08x)",
4894 			nStatus);
4895 
4896 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
4897 			 ((pe_session) ? pe_session->
4898 			  peSessionId : NO_SESSION), pMacHdr->fc.subType));
4899 	qdf_status =
4900 		wma_tx_frame(mac, pPacket, (uint16_t) nBytes,
4901 			   TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
4902 			   lim_tx_complete, pFrame, 0, 0, RATEID_DEFAULT, 0);
4903 	MTRACE(qdf_trace
4904 		(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
4905 		((pe_session) ? pe_session->peSessionId : NO_SESSION),
4906 		qdf_status));
4907 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
4908 		pe_err("Failed to send a TPC Report (%X)!",
4909 			qdf_status);
4910 		/* Pkt will be freed up by the callback */
4911 		return QDF_STATUS_E_FAILURE;    /* just allocated... */
4912 	}
4913 
4914 	return QDF_STATUS_SUCCESS;
4915 
4916 } /* End lim_send_tpc_report_frame. */
4917 #endif /* ANI_SUPPORT_11H */
4918 
4919 /**
4920  * \brief Send a Channel Switch Announcement
4921  *
4922  *
4923  * \param mac Pointer to the global MAC datastructure
4924  *
4925  * \param peer MAC address to which this frame will be sent
4926  *
4927  * \param nMode
4928  *
4929  * \param nNewChannel
4930  *
4931  * \param nCount
4932  *
4933  * \return QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE else
4934  *
4935  *
4936  */
4937 
4938 QDF_STATUS
4939 lim_send_channel_switch_mgmt_frame(struct mac_context *mac,
4940 				   tSirMacAddr peer,
4941 				   uint8_t nMode,
4942 				   uint8_t nNewChannel,
4943 				   uint8_t nCount, struct pe_session *pe_session)
4944 {
4945 	tDot11fChannelSwitch frm;
4946 	uint8_t *pFrame;
4947 	tpSirMacMgmtHdr pMacHdr;
4948 	uint32_t nBytes, nPayload, nStatus;     /* , nCfg; */
4949 	void *pPacket;
4950 	QDF_STATUS qdf_status;
4951 	uint8_t txFlag = 0;
4952 
4953 	uint8_t smeSessionId = 0;
4954 
4955 	if (!pe_session) {
4956 		pe_err("Session entry is NULL!!!");
4957 		return QDF_STATUS_E_FAILURE;
4958 	}
4959 	smeSessionId = pe_session->smeSessionId;
4960 
4961 	qdf_mem_zero((uint8_t *) &frm, sizeof(frm));
4962 
4963 	frm.Category.category = ACTION_CATEGORY_SPECTRUM_MGMT;
4964 	frm.Action.action = ACTION_SPCT_CHL_SWITCH;
4965 	frm.ChanSwitchAnn.switchMode = nMode;
4966 	frm.ChanSwitchAnn.newChannel = nNewChannel;
4967 	frm.ChanSwitchAnn.switchCount = nCount;
4968 	frm.ChanSwitchAnn.present = 1;
4969 
4970 	nStatus = dot11f_get_packed_channel_switch_size(mac, &frm, &nPayload);
4971 	if (DOT11F_FAILED(nStatus)) {
4972 		pe_err("Failed to calculate the packed size for a Channel Switch (0x%08x)",
4973 			nStatus);
4974 		/* We'll fall back on the worst case scenario: */
4975 		nPayload = sizeof(tDot11fChannelSwitch);
4976 	} else if (DOT11F_WARNED(nStatus)) {
4977 		pe_warn("There were warnings while calculating the packed size for a Channel Switch (0x%08x)",
4978 			nStatus);
4979 	}
4980 
4981 	nBytes = nPayload + sizeof(tSirMacMgmtHdr);
4982 
4983 	qdf_status =
4984 		cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
4985 				 (void **)&pPacket);
4986 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
4987 		pe_err("Failed to allocate %d bytes for a TPC Report", nBytes);
4988 		return QDF_STATUS_E_FAILURE;
4989 	}
4990 	/* Paranoia: */
4991 	qdf_mem_zero(pFrame, nBytes);
4992 
4993 	/* Next, we fill out the buffer descriptor: */
4994 	lim_populate_mac_header(mac, pFrame, SIR_MAC_MGMT_FRAME,
4995 		SIR_MAC_MGMT_ACTION, peer,
4996 		pe_session->self_mac_addr);
4997 	pMacHdr = (tpSirMacMgmtHdr) pFrame;
4998 	qdf_mem_copy((uint8_t *) pMacHdr->bssId,
4999 		     (uint8_t *) pe_session->bssId, sizeof(tSirMacAddr));
5000 
5001 	lim_set_protected_bit(mac, pe_session, peer, pMacHdr);
5002 
5003 	nStatus = dot11f_pack_channel_switch(mac, &frm, pFrame +
5004 					     sizeof(tSirMacMgmtHdr),
5005 					     nPayload, &nPayload);
5006 	if (DOT11F_FAILED(nStatus)) {
5007 		pe_err("Failed to pack a Channel Switch (0x%08x)",
5008 			nStatus);
5009 		cds_packet_free((void *)pPacket);
5010 		return QDF_STATUS_E_FAILURE;    /* allocated! */
5011 	} else if (DOT11F_WARNED(nStatus)) {
5012 		pe_warn("There were warnings while packing a Channel Switch (0x%08x)",
5013 			nStatus);
5014 	}
5015 
5016 	if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) ||
5017 	    pe_session->opmode == QDF_P2P_CLIENT_MODE ||
5018 	    pe_session->opmode == QDF_P2P_GO_MODE)
5019 		txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
5020 
5021 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
5022 			 pe_session->peSessionId, pMacHdr->fc.subType));
5023 	qdf_status = wma_tx_frame(mac, pPacket, (uint16_t) nBytes,
5024 				TXRX_FRM_802_11_MGMT,
5025 				ANI_TXDIR_TODS,
5026 				7, lim_tx_complete, pFrame, txFlag,
5027 				smeSessionId, 0, RATEID_DEFAULT, 0);
5028 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
5029 			 pe_session->peSessionId, qdf_status));
5030 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
5031 		pe_err("Failed to send a Channel Switch (%X)!",
5032 			qdf_status);
5033 		/* Pkt will be freed up by the callback */
5034 		return QDF_STATUS_E_FAILURE;
5035 	}
5036 
5037 	return QDF_STATUS_SUCCESS;
5038 
5039 } /* End lim_send_channel_switch_mgmt_frame. */
5040 
5041 /**
5042  * lim_send_extended_chan_switch_action_frame()- function to send ECSA
5043  * action frame over the air .
5044  * @mac_ctx: pointer to global mac structure
5045  * @peer: Destination mac.
5046  * @mode: channel switch mode
5047  * @new_op_class: new op class
5048  * @new_channel: new channel to switch
5049  * @count: channel switch count
5050  *
5051  * This function is called to send ECSA frame.
5052  *
5053  * Return: success if frame is sent else return failure
5054  */
5055 
5056 QDF_STATUS
5057 lim_send_extended_chan_switch_action_frame(struct mac_context *mac_ctx,
5058 		tSirMacAddr peer, uint8_t mode, uint8_t new_op_class,
5059 		uint8_t new_channel, uint8_t count, struct pe_session *session_entry)
5060 {
5061 	tDot11fext_channel_switch_action_frame frm;
5062 	uint8_t                  *frame;
5063 	tpSirMacMgmtHdr          mac_hdr;
5064 	uint32_t                 num_bytes, n_payload, status;
5065 	void                     *packet;
5066 	QDF_STATUS               qdf_status;
5067 	uint8_t                  txFlag = 0;
5068 	uint8_t                  vdev_id = 0;
5069 	uint8_t                  ch_spacing;
5070 	tLimWiderBWChannelSwitchInfo *wide_bw_ie;
5071 	uint8_t reg_cc[REG_ALPHA2_LEN + 1];
5072 
5073 	if (!session_entry) {
5074 		pe_err("Session entry is NULL!!!");
5075 		return QDF_STATUS_E_FAILURE;
5076 	}
5077 
5078 	vdev_id = session_entry->smeSessionId;
5079 
5080 	qdf_mem_zero(&frm, sizeof(frm));
5081 
5082 	frm.Category.category     = ACTION_CATEGORY_PUBLIC;
5083 	frm.Action.action         = PUB_ACTION_EXT_CHANNEL_SWITCH_ID;
5084 
5085 	frm.ext_chan_switch_ann_action.switch_mode = mode;
5086 	frm.ext_chan_switch_ann_action.op_class = new_op_class;
5087 	frm.ext_chan_switch_ann_action.new_channel = new_channel;
5088 	frm.ext_chan_switch_ann_action.switch_count = count;
5089 
5090 	wlan_reg_read_current_country(mac_ctx->psoc, reg_cc);
5091 	ch_spacing = wlan_reg_dmn_get_chanwidth_from_opclass(
5092 			reg_cc, new_channel, new_op_class);
5093 
5094 	if ((ch_spacing == 80) || (ch_spacing == 160)) {
5095 		wide_bw_ie = &session_entry->gLimWiderBWChannelSwitch;
5096 		frm.WiderBWChanSwitchAnn.newChanWidth =
5097 			wide_bw_ie->newChanWidth;
5098 		frm.WiderBWChanSwitchAnn.newCenterChanFreq0 =
5099 			wide_bw_ie->newCenterChanFreq0;
5100 		frm.WiderBWChanSwitchAnn.newCenterChanFreq1 =
5101 			wide_bw_ie->newCenterChanFreq1;
5102 		frm.WiderBWChanSwitchAnn.present = 1;
5103 		pe_debug("wrapper: width:%d f0:%d f1:%d",
5104 			 frm.WiderBWChanSwitchAnn.newChanWidth,
5105 			 frm.WiderBWChanSwitchAnn.newCenterChanFreq0,
5106 			 frm.WiderBWChanSwitchAnn.newCenterChanFreq1);
5107 	}
5108 
5109 	if (lim_is_session_eht_capable(session_entry))
5110 		populate_dot11f_bw_ind_element(mac_ctx, session_entry,
5111 					       &frm.bw_ind_element);
5112 
5113 	status = dot11f_get_packed_ext_channel_switch_action_frame_size(mac_ctx,
5114 							    &frm, &n_payload);
5115 	if (DOT11F_FAILED(status)) {
5116 		pe_err("Failed to get packed size for Channel Switch 0x%08x",
5117 				 status);
5118 		/* We'll fall back on the worst case scenario*/
5119 		n_payload = sizeof(tDot11fext_channel_switch_action_frame);
5120 	} else if (DOT11F_WARNED(status)) {
5121 		pe_warn("There were warnings while calculating the packed size for a Ext Channel Switch (0x%08x)",
5122 		 status);
5123 	}
5124 
5125 	num_bytes = n_payload + sizeof(tSirMacMgmtHdr);
5126 
5127 	qdf_status = cds_packet_alloc((uint16_t)num_bytes,
5128 				(void **) &frame, (void **) &packet);
5129 
5130 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
5131 		pe_err("Failed to allocate %d bytes for a Ext Channel Switch",
5132 								 num_bytes);
5133 		return QDF_STATUS_E_FAILURE;
5134 	}
5135 
5136 	/* Paranoia*/
5137 	qdf_mem_zero(frame, num_bytes);
5138 
5139 	/* Next, we fill out the buffer descriptor */
5140 	lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME,
5141 		SIR_MAC_MGMT_ACTION, peer, session_entry->self_mac_addr);
5142 	mac_hdr = (tpSirMacMgmtHdr) frame;
5143 	qdf_mem_copy((uint8_t *) mac_hdr->bssId,
5144 				   (uint8_t *) session_entry->bssId,
5145 				   sizeof(tSirMacAddr));
5146 
5147 	lim_set_protected_bit(mac_ctx, session_entry, peer, mac_hdr);
5148 
5149 	status = dot11f_pack_ext_channel_switch_action_frame(mac_ctx, &frm,
5150 		frame + sizeof(tSirMacMgmtHdr), n_payload, &n_payload);
5151 	if (DOT11F_FAILED(status)) {
5152 		pe_err("Failed to pack a Channel Switch 0x%08x", status);
5153 		cds_packet_free((void *)packet);
5154 		return QDF_STATUS_E_FAILURE;
5155 	} else if (DOT11F_WARNED(status)) {
5156 		pe_warn("There were warnings while packing a Channel Switch 0x%08x",
5157 		 status);
5158 	}
5159 
5160 	if (!wlan_reg_is_24ghz_ch_freq(session_entry->curr_op_freq) ||
5161 	    session_entry->opmode == QDF_P2P_CLIENT_MODE ||
5162 	    session_entry->opmode == QDF_P2P_GO_MODE)
5163 		txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
5164 
5165 	pe_debug("ECSA frame to :"QDF_MAC_ADDR_FMT" count %d mode %d chan %d op class %d",
5166 		 QDF_MAC_ADDR_REF(mac_hdr->da),
5167 		 frm.ext_chan_switch_ann_action.switch_count,
5168 		 frm.ext_chan_switch_ann_action.switch_mode,
5169 		 frm.ext_chan_switch_ann_action.new_channel,
5170 		 frm.ext_chan_switch_ann_action.op_class);
5171 
5172 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
5173 			session_entry->peSessionId, mac_hdr->fc.subType));
5174 	qdf_status = wma_tx_frame(mac_ctx, packet, (uint16_t) num_bytes,
5175 						 TXRX_FRM_802_11_MGMT,
5176 						 ANI_TXDIR_TODS,
5177 						 7,
5178 						 lim_tx_complete, frame,
5179 						 txFlag, vdev_id, 0,
5180 						 RATEID_DEFAULT, 0);
5181 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
5182 			session_entry->peSessionId, qdf_status));
5183 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
5184 		pe_err("Failed to send a Ext Channel Switch %X!",
5185 							 qdf_status);
5186 		/* Pkt will be freed up by the callback */
5187 		return QDF_STATUS_E_FAILURE;
5188 	}
5189 	return QDF_STATUS_SUCCESS;
5190 } /* End lim_send_extended_chan_switch_action_frame */
5191 
5192 
5193 /**
5194  * lim_oper_chan_change_confirm_tx_complete_cnf()- Confirmation for oper_chan_change_confirm
5195  * sent over the air
5196  *
5197  * @context: pointer to global mac
5198  * @buf: buffer
5199  * @tx_complete : Sent status
5200  * @params: tx completion params
5201  *
5202  * Return: This returns QDF_STATUS
5203  */
5204 
5205 static QDF_STATUS lim_oper_chan_change_confirm_tx_complete_cnf(
5206 			void *context,
5207 			qdf_nbuf_t buf,
5208 			uint32_t tx_complete,
5209 			void *params)
5210 {
5211 	pe_debug("tx_complete: %d", tx_complete);
5212 	if (buf)
5213 		qdf_nbuf_free(buf);
5214 	return QDF_STATUS_SUCCESS;
5215 }
5216 
5217 /**
5218  * lim_p2p_oper_chan_change_confirm_action_frame()- function to send
5219  * p2p oper chan change confirm action frame
5220  * @mac_ctx: pointer to global mac structure
5221  * @peer: Destination mac.
5222  * @session_entry: session entry
5223  *
5224  * This function is called to send p2p oper chan change confirm action frame.
5225  *
5226  * Return: success if frame is sent else return failure
5227  */
5228 
5229 QDF_STATUS
5230 lim_p2p_oper_chan_change_confirm_action_frame(struct mac_context *mac_ctx,
5231 		tSirMacAddr peer, struct pe_session *session_entry)
5232 {
5233 	tDot11fp2p_oper_chan_change_confirm frm;
5234 	uint8_t                  *frame;
5235 	tpSirMacMgmtHdr          mac_hdr;
5236 	uint32_t                 num_bytes, n_payload, status;
5237 	void                     *packet;
5238 	QDF_STATUS               qdf_status;
5239 	uint8_t                  tx_flag = 0;
5240 	uint8_t                  vdev_id = 0;
5241 
5242 	if (!session_entry) {
5243 		pe_err("Session entry is NULL!!!");
5244 		return QDF_STATUS_E_FAILURE;
5245 	}
5246 
5247 	vdev_id = session_entry->smeSessionId;
5248 
5249 	qdf_mem_zero(&frm, sizeof(frm));
5250 
5251 	frm.Category.category     = ACTION_CATEGORY_VENDOR_SPECIFIC;
5252 
5253 	qdf_mem_copy(frm.p2p_action_oui.oui_data,
5254 		SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE);
5255 	frm.p2p_action_subtype.subtype = 0x04;
5256 	frm.DialogToken.token = 0x0;
5257 
5258 	if (session_entry->htCapability) {
5259 		pe_debug("Populate HT Caps in Assoc Request");
5260 		populate_dot11f_ht_caps(mac_ctx, session_entry, &frm.HTCaps);
5261 	}
5262 
5263 	if (session_entry->vhtCapability) {
5264 		pe_debug("Populate VHT Caps in Assoc Request");
5265 		populate_dot11f_vht_caps(mac_ctx, session_entry, &frm.VHTCaps);
5266 		populate_dot11f_operating_mode(mac_ctx,
5267 					&frm.OperatingMode, session_entry);
5268 	}
5269 
5270 	status = dot11f_get_packed_p2p_oper_chan_change_confirmSize(mac_ctx,
5271 							    &frm, &n_payload);
5272 	if (DOT11F_FAILED(status)) {
5273 		pe_err("Failed to get packed size 0x%08x", status);
5274 		/* We'll fall back on the worst case scenario*/
5275 		n_payload = sizeof(tDot11fp2p_oper_chan_change_confirm);
5276 	} else if (DOT11F_WARNED(status)) {
5277 		pe_warn("There were warnings while calculating the packed size (0x%08x)",
5278 			status);
5279 	}
5280 
5281 	num_bytes = n_payload + sizeof(tSirMacMgmtHdr);
5282 
5283 	qdf_status = cds_packet_alloc((uint16_t)num_bytes,
5284 				(void **) &frame, (void **) &packet);
5285 
5286 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
5287 		pe_err("Failed to allocate %d bytes", num_bytes);
5288 		return QDF_STATUS_E_FAILURE;
5289 	}
5290 
5291 	qdf_mem_zero(frame, num_bytes);
5292 
5293 	/* Next, fill out the buffer descriptor */
5294 	lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME,
5295 		SIR_MAC_MGMT_ACTION, peer, session_entry->self_mac_addr);
5296 	mac_hdr = (tpSirMacMgmtHdr) frame;
5297 	qdf_mem_copy((uint8_t *) mac_hdr->bssId,
5298 				   (uint8_t *) session_entry->bssId,
5299 				   sizeof(tSirMacAddr));
5300 
5301 	status = dot11f_pack_p2p_oper_chan_change_confirm(mac_ctx, &frm,
5302 		frame + sizeof(tSirMacMgmtHdr), n_payload, &n_payload);
5303 	if (DOT11F_FAILED(status)) {
5304 		pe_err("Failed to pack 0x%08x", status);
5305 		cds_packet_free((void *)packet);
5306 		return QDF_STATUS_E_FAILURE;
5307 	} else if (DOT11F_WARNED(status)) {
5308 		pe_warn("There were warnings while packing 0x%08x",
5309 		 status);
5310 	}
5311 
5312 	if (!wlan_reg_is_24ghz_ch_freq(session_entry->curr_op_freq) ||
5313 	    session_entry->opmode == QDF_P2P_CLIENT_MODE ||
5314 	    session_entry->opmode == QDF_P2P_GO_MODE) {
5315 		tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
5316 	}
5317 	pe_debug("Send frame on channel freq %d to mac "
5318 		QDF_MAC_ADDR_FMT, session_entry->curr_op_freq,
5319 		QDF_MAC_ADDR_REF(peer));
5320 
5321 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
5322 			session_entry->peSessionId, mac_hdr->fc.subType));
5323 
5324 	qdf_status = wma_tx_frameWithTxComplete(mac_ctx, packet,
5325 			(uint16_t)num_bytes,
5326 			TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS,
5327 			7, lim_tx_complete, frame,
5328 			lim_oper_chan_change_confirm_tx_complete_cnf,
5329 			tx_flag, vdev_id, false, 0, RATEID_DEFAULT, 0, 0);
5330 
5331 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
5332 			session_entry->peSessionId, qdf_status));
5333 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
5334 		pe_err("Failed to send status %X!", qdf_status);
5335 		/* Pkt will be freed up by the callback */
5336 		return QDF_STATUS_E_FAILURE;
5337 	}
5338 		return QDF_STATUS_SUCCESS;
5339 }
5340 
5341 
5342 /**
5343  * \brief Send a Neighbor Report Request Action frame
5344  *
5345  *
5346  * \param mac Pointer to the global MAC structure
5347  *
5348  * \param pNeighborReq Address of a tSirMacNeighborReportReq
5349  *
5350  * \param peer mac address of peer station.
5351  *
5352  * \param pe_session address of session entry.
5353  *
5354  * \return QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE else
5355  *
5356  *
5357  */
5358 
5359 QDF_STATUS
5360 lim_send_neighbor_report_request_frame(struct mac_context *mac,
5361 				       tpSirMacNeighborReportReq pNeighborReq,
5362 				       tSirMacAddr peer, struct pe_session *pe_session)
5363 {
5364 	QDF_STATUS status_code = QDF_STATUS_SUCCESS;
5365 	tDot11fNeighborReportRequest frm;
5366 	uint8_t *pFrame;
5367 	tpSirMacMgmtHdr pMacHdr;
5368 	uint32_t nBytes, nPayload, nStatus;
5369 	void *pPacket;
5370 	QDF_STATUS qdf_status;
5371 	uint8_t txFlag = 0;
5372 	uint8_t smeSessionId = 0;
5373 
5374 	if (!pe_session) {
5375 		pe_err("(!psession) in Request to send Neighbor Report request action frame");
5376 		return QDF_STATUS_E_FAILURE;
5377 	}
5378 	smeSessionId = pe_session->smeSessionId;
5379 	qdf_mem_zero((uint8_t *) &frm, sizeof(frm));
5380 
5381 	frm.Category.category = ACTION_CATEGORY_RRM;
5382 	frm.Action.action = RRM_NEIGHBOR_REQ;
5383 	frm.DialogToken.token = pNeighborReq->dialogToken;
5384 
5385 	if (pNeighborReq->ssid_present) {
5386 		populate_dot11f_ssid(mac, &pNeighborReq->ssid, &frm.SSID);
5387 	}
5388 
5389 	nStatus =
5390 		dot11f_get_packed_neighbor_report_request_size(mac, &frm, &nPayload);
5391 	if (DOT11F_FAILED(nStatus)) {
5392 		pe_err("Failed to calculate the packed size for a Neighbor Report Request(0x%08x)",
5393 			nStatus);
5394 		/* We'll fall back on the worst case scenario: */
5395 		nPayload = sizeof(tDot11fNeighborReportRequest);
5396 	} else if (DOT11F_WARNED(nStatus)) {
5397 		pe_warn("There were warnings while calculating the packed size for a Neighbor Report Request(0x%08x)",
5398 			nStatus);
5399 	}
5400 
5401 	nBytes = nPayload + sizeof(tSirMacMgmtHdr);
5402 
5403 	qdf_status =
5404 		cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
5405 				 (void **)&pPacket);
5406 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
5407 		pe_err("Failed to allocate %d bytes for a Neighbor "
5408 			   "Report Request", nBytes);
5409 		return QDF_STATUS_E_FAILURE;
5410 	}
5411 	/* Paranoia: */
5412 	qdf_mem_zero(pFrame, nBytes);
5413 
5414 	/* Copy necessary info to BD */
5415 	lim_populate_mac_header(mac, pFrame, SIR_MAC_MGMT_FRAME,
5416 		SIR_MAC_MGMT_ACTION, peer, pe_session->self_mac_addr);
5417 
5418 	/* Update A3 with the BSSID */
5419 	pMacHdr = (tpSirMacMgmtHdr) pFrame;
5420 
5421 	sir_copy_mac_addr(pMacHdr->bssId, pe_session->bssId);
5422 
5423 	lim_set_protected_bit(mac, pe_session, peer, pMacHdr);
5424 
5425 	/* Now, we're ready to "pack" the frames */
5426 	nStatus = dot11f_pack_neighbor_report_request(mac,
5427 						      &frm,
5428 						      pFrame +
5429 						      sizeof(tSirMacMgmtHdr),
5430 						      nPayload, &nPayload);
5431 
5432 	if (DOT11F_FAILED(nStatus)) {
5433 		pe_err("Failed to pack an Neighbor Report Request (0x%08x)",
5434 			nStatus);
5435 
5436 		/* FIXME - Need to convert to QDF_STATUS */
5437 		status_code = QDF_STATUS_E_FAILURE;
5438 		goto returnAfterError;
5439 	} else if (DOT11F_WARNED(nStatus)) {
5440 		pe_warn("There were warnings while packing Neighbor Report Request (0x%08x)",
5441 			nStatus);
5442 	}
5443 
5444 	pe_debug("Sending a Neighbor Report Request to "QDF_MAC_ADDR_FMT,
5445 		 QDF_MAC_ADDR_REF(peer));
5446 
5447 	if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) ||
5448 	    pe_session->opmode == QDF_P2P_CLIENT_MODE ||
5449 	    pe_session->opmode == QDF_P2P_GO_MODE)
5450 		txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
5451 
5452 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
5453 			 pe_session->peSessionId, pMacHdr->fc.subType));
5454 	qdf_status = wma_tx_frame(mac,
5455 				pPacket,
5456 				(uint16_t) nBytes,
5457 				TXRX_FRM_802_11_MGMT,
5458 				ANI_TXDIR_TODS,
5459 				7, lim_tx_complete, pFrame, txFlag,
5460 				smeSessionId, 0, RATEID_DEFAULT, 0);
5461 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
5462 			 pe_session->peSessionId, qdf_status));
5463 	if (QDF_STATUS_SUCCESS != qdf_status) {
5464 		pe_err("wma_tx_frame FAILED! Status [%d]", qdf_status);
5465 		status_code = QDF_STATUS_E_FAILURE;
5466 		/* Pkt will be freed up by the callback */
5467 		return status_code;
5468 	} else
5469 		return QDF_STATUS_SUCCESS;
5470 
5471 returnAfterError:
5472 	cds_packet_free((void *)pPacket);
5473 
5474 	return status_code;
5475 } /* End lim_send_neighbor_report_request_frame. */
5476 
5477 QDF_STATUS
5478 lim_send_link_report_action_frame(struct mac_context *mac,
5479 				  tpSirMacLinkReport pLinkReport,
5480 				  tSirMacAddr peer, struct pe_session *pe_session)
5481 {
5482 	QDF_STATUS status_code = QDF_STATUS_SUCCESS;
5483 	tDot11fLinkMeasurementReport frm;
5484 	uint8_t *pFrame;
5485 	tpSirMacMgmtHdr pMacHdr;
5486 	uint32_t nBytes, nPayload, nStatus;
5487 	void *pPacket;
5488 	QDF_STATUS qdf_status;
5489 	uint8_t txFlag = 0;
5490 	uint8_t vdev_id = 0;
5491 
5492 	if (!pe_session) {
5493 		pe_err("RRM: Send link report: NULL PE session");
5494 		return QDF_STATUS_E_FAILURE;
5495 	}
5496 
5497 	vdev_id = pe_session->vdev_id;
5498 	qdf_mem_zero((uint8_t *) &frm, sizeof(frm));
5499 
5500 	frm.Category.category = ACTION_CATEGORY_RRM;
5501 	frm.Action.action = RRM_LINK_MEASUREMENT_RPT;
5502 	frm.DialogToken.token = pLinkReport->dialogToken;
5503 
5504 	/* IEEE Std. 802.11 7.3.2.18. for the report element. */
5505 	/* Even though TPC report an IE, it is represented using fixed fields since it is positioned */
5506 	/* in the middle of other fixed fields in the link report frame(IEEE Std. 802.11k section7.4.6.4 */
5507 	/* and frame parser always expects IEs to come after all fixed fields. It is easier to handle */
5508 	/* such case this way than changing the frame parser. */
5509 	frm.TPCEleID.TPCId = WLAN_ELEMID_TPCREP;
5510 	frm.TPCEleLen.TPCLen = 2;
5511 	frm.TxPower.txPower = pLinkReport->txPower;
5512 	frm.LinkMargin.linkMargin = 0;
5513 
5514 	frm.RxAntennaId.antennaId = pLinkReport->rxAntenna;
5515 	frm.TxAntennaId.antennaId = pLinkReport->txAntenna;
5516 	frm.RCPI.rcpi = pLinkReport->rcpi;
5517 	frm.RSNI.rsni = pLinkReport->rsni;
5518 
5519 	nStatus =
5520 		dot11f_get_packed_link_measurement_report_size(mac, &frm, &nPayload);
5521 	if (DOT11F_FAILED(nStatus)) {
5522 		pe_err("Failed to calculate the packed size for a Link Report (0x%08x)", nStatus);
5523 		/* We'll fall back on the worst case scenario: */
5524 		nPayload = sizeof(tDot11fLinkMeasurementReport);
5525 	} else if (DOT11F_WARNED(nStatus)) {
5526 		pe_warn("There were warnings while calculating the packed size for a Link Report (0x%08x)",
5527 			nStatus);
5528 	}
5529 
5530 	nBytes = nPayload + sizeof(tSirMacMgmtHdr);
5531 
5532 	qdf_status =
5533 		cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
5534 				 (void **)&pPacket);
5535 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
5536 		pe_err("Failed to allocate %d bytes for a Link "
5537 			"Report", nBytes);
5538 		return QDF_STATUS_E_FAILURE;
5539 	}
5540 	/* Paranoia: */
5541 	qdf_mem_zero(pFrame, nBytes);
5542 
5543 	/* Copy necessary info to BD */
5544 	lim_populate_mac_header(mac, pFrame, SIR_MAC_MGMT_FRAME,
5545 		SIR_MAC_MGMT_ACTION, peer, pe_session->self_mac_addr);
5546 
5547 	/* Update A3 with the BSSID */
5548 	pMacHdr = (tpSirMacMgmtHdr) pFrame;
5549 
5550 	sir_copy_mac_addr(pMacHdr->bssId, pe_session->bssId);
5551 
5552 	lim_set_protected_bit(mac, pe_session, peer, pMacHdr);
5553 
5554 	/* Now, we're ready to "pack" the frames */
5555 	nStatus = dot11f_pack_link_measurement_report(mac,
5556 						      &frm,
5557 						      pFrame +
5558 						      sizeof(tSirMacMgmtHdr),
5559 						      nPayload, &nPayload);
5560 
5561 	if (DOT11F_FAILED(nStatus)) {
5562 		pe_err("Failed to pack an Link Report (0x%08x)", nStatus);
5563 
5564 		/* FIXME - Need to convert to QDF_STATUS */
5565 		status_code = QDF_STATUS_E_FAILURE;
5566 		goto returnAfterError;
5567 	} else if (DOT11F_WARNED(nStatus)) {
5568 		pe_warn("There were warnings while packing Link Report (0x%08x)",
5569 			nStatus);
5570 	}
5571 
5572 	pe_warn_rl("RRM: Sending Link Report to "QDF_MAC_ADDR_FMT" on vdev[%d]",
5573 		   QDF_MAC_ADDR_REF(peer), vdev_id);
5574 
5575 	if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) ||
5576 	    pe_session->opmode == QDF_P2P_CLIENT_MODE ||
5577 	    pe_session->opmode == QDF_P2P_GO_MODE)
5578 		txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
5579 
5580 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
5581 			 pe_session->peSessionId, pMacHdr->fc.subType));
5582 	qdf_status = wma_tx_frame(mac,
5583 				pPacket,
5584 				(uint16_t) nBytes,
5585 				TXRX_FRM_802_11_MGMT,
5586 				ANI_TXDIR_TODS,
5587 				7, lim_tx_complete, pFrame, txFlag,
5588 				vdev_id, 0, RATEID_DEFAULT, 0);
5589 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
5590 			 pe_session->peSessionId, qdf_status));
5591 	if (QDF_STATUS_SUCCESS != qdf_status) {
5592 		pe_err_rl("wma_tx_frame FAILED! Status [%d]", qdf_status);
5593 		status_code = QDF_STATUS_E_FAILURE;
5594 		/* Pkt will be freed up by the callback */
5595 		return status_code;
5596 	} else
5597 		return QDF_STATUS_SUCCESS;
5598 
5599 returnAfterError:
5600 	cds_packet_free((void *)pPacket);
5601 
5602 	return status_code;
5603 } /* End lim_send_link_report_action_frame. */
5604 
5605 #ifdef CONNECTIVITY_DIAG_EVENT
5606 /**
5607  * lim_beacon_report_response_event() - Send Beacon Report Response log
5608  * event
5609  * @token: Dialog token
5610  * @num_rpt: Number of Report element
5611  * @pe_session: pe session pointer
5612  */
5613 static void
5614 lim_beacon_report_response_event(uint8_t token, uint8_t num_rpt,
5615 				 struct pe_session *pe_session)
5616 {
5617 	WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct wlan_diag_bcn_rpt);
5618 
5619 	qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event));
5620 
5621 	wlan_diag_event.diag_cmn.vdev_id = wlan_vdev_get_id(pe_session->vdev);
5622 	wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us();
5623 	wlan_diag_event.diag_cmn.ktime_us =  qdf_ktime_to_us(qdf_ktime_get());
5624 
5625 	wlan_diag_event.version = DIAG_BCN_RPT_VERSION_2;
5626 	wlan_diag_event.subtype = WLAN_CONN_DIAG_BCN_RPT_RESP_EVENT;
5627 	wlan_diag_event.meas_token = token;
5628 	wlan_diag_event.num_rpt = num_rpt;
5629 
5630 	if (mlo_is_mld_sta(pe_session->vdev))
5631 		wlan_diag_event.band =
5632 			wlan_convert_freq_to_diag_band(pe_session->curr_op_freq);
5633 
5634 	WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_BCN_RPT);
5635 }
5636 #else
5637 static void
5638 lim_beacon_report_response_event(uint8_t token, uint8_t num_rpt,
5639 				 struct pe_session *pe_session)
5640 {
5641 }
5642 #endif
5643 
5644 QDF_STATUS
5645 lim_send_radio_measure_report_action_frame(struct mac_context *mac,
5646 				uint8_t dialog_token,
5647 				uint8_t num_report,
5648 				bool is_last_frame,
5649 				tpSirMacRadioMeasureReport pRRMReport,
5650 				tSirMacAddr peer,
5651 				struct pe_session *pe_session)
5652 {
5653 	QDF_STATUS status_code = QDF_STATUS_SUCCESS;
5654 	uint8_t *pFrame;
5655 	tpSirMacMgmtHdr pMacHdr;
5656 	uint32_t nBytes, nPayload, nStatus;
5657 	void *pPacket;
5658 	QDF_STATUS qdf_status;
5659 	uint8_t i;
5660 	uint8_t txFlag = 0;
5661 	uint8_t smeSessionId = 0;
5662 	bool is_last_report = false;
5663 
5664 	/* Malloc size of (tDot11fIEMeasurementReport) * (num_report - 1)
5665 	 * as memory for one Dot11fIEMeasurementReport is already calculated.
5666 	 */
5667 	tDot11fRadioMeasurementReport *frm =
5668 		qdf_mem_malloc(sizeof(tDot11fRadioMeasurementReport) +
5669 		(sizeof(tDot11fIEMeasurementReport) * (num_report - 1)));
5670 	if (!frm)
5671 		return QDF_STATUS_E_NOMEM;
5672 
5673 	if (!pe_session) {
5674 		pe_err("session not found");
5675 		qdf_mem_free(frm);
5676 		return QDF_STATUS_E_FAILURE;
5677 	}
5678 
5679 	smeSessionId = pe_session->smeSessionId;
5680 
5681 	frm->Category.category = ACTION_CATEGORY_RRM;
5682 	frm->Action.action = RRM_RADIO_MEASURE_RPT;
5683 	frm->DialogToken.token = dialog_token;
5684 
5685 	frm->num_MeasurementReport = num_report;
5686 
5687 	for (i = 0; i < frm->num_MeasurementReport; i++) {
5688 		frm->MeasurementReport[i].type = pRRMReport[i].type;
5689 		frm->MeasurementReport[i].token = pRRMReport[i].token;
5690 		frm->MeasurementReport[i].late = 0;     /* IEEE 802.11k section 7.3.22. (always zero in rrm) */
5691 		switch (pRRMReport[i].type) {
5692 		case SIR_MAC_RRM_BEACON_TYPE:
5693 			/*
5694 			 * Last beacon report indication needs to be set to 1
5695 			 * only for the last report in the last frame
5696 			 */
5697 			if (is_last_frame &&
5698 			    (i == (frm->num_MeasurementReport - 1)))
5699 				is_last_report = true;
5700 
5701 			populate_dot11f_beacon_report(mac,
5702 						     &frm->MeasurementReport[i],
5703 						     &pRRMReport[i].report.
5704 						     beaconReport,
5705 						     is_last_report);
5706 			frm->MeasurementReport[i].incapable =
5707 				pRRMReport[i].incapable;
5708 			frm->MeasurementReport[i].refused =
5709 				pRRMReport[i].refused;
5710 			frm->MeasurementReport[i].present = 1;
5711 			break;
5712 		case SIR_MAC_RRM_CHANNEL_LOAD_TYPE:
5713 			populate_dot11f_chan_load_report(mac,
5714 				&frm->MeasurementReport[i],
5715 				&pRRMReport[i].report.channel_load_report);
5716 			frm->MeasurementReport[i].incapable =
5717 				pRRMReport[i].incapable;
5718 			frm->MeasurementReport[i].refused =
5719 				pRRMReport[i].refused;
5720 			frm->MeasurementReport[i].present = 1;
5721 			break;
5722 		case SIR_MAC_RRM_STA_STATISTICS_TYPE:
5723 			populate_dot11f_rrm_sta_stats_report(
5724 				mac, &frm->MeasurementReport[i],
5725 				&pRRMReport[i].report.statistics_report);
5726 			frm->MeasurementReport[i].incapable =
5727 				pRRMReport[i].incapable;
5728 			frm->MeasurementReport[i].refused =
5729 				pRRMReport[i].refused;
5730 			frm->MeasurementReport[i].present = 1;
5731 			break;
5732 		default:
5733 			frm->MeasurementReport[i].incapable =
5734 				pRRMReport[i].incapable;
5735 			frm->MeasurementReport[i].refused =
5736 				pRRMReport[i].refused;
5737 			frm->MeasurementReport[i].present = 1;
5738 			break;
5739 		}
5740 	}
5741 
5742 
5743 	nStatus =
5744 		dot11f_get_packed_radio_measurement_report_size(mac, frm, &nPayload);
5745 	if (DOT11F_FAILED(nStatus)) {
5746 		pe_nofl_err("TX: [802.11 RRM] Failed to get packed size for RM Report (0x%08x)",
5747 		       nStatus);
5748 		/* We'll fall back on the worst case scenario: */
5749 		nPayload = sizeof(tDot11fLinkMeasurementReport);
5750 		qdf_mem_free(frm);
5751 		return QDF_STATUS_E_FAILURE;
5752 	} else if (DOT11F_WARNED(nStatus)) {
5753 		pe_warn("Warnings while calculating the size for Radio Measure Report (0x%08x)",
5754 			nStatus);
5755 	}
5756 
5757 	nBytes = nPayload + sizeof(tSirMacMgmtHdr);
5758 
5759 	qdf_status =
5760 		cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
5761 				 (void **)&pPacket);
5762 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
5763 		pe_nofl_err("TX: [802.11 RRM] Allocation of %d bytes failed for RM"
5764 			   "Report", nBytes);
5765 		qdf_mem_free(frm);
5766 		return QDF_STATUS_E_FAILURE;
5767 	}
5768 	/* Paranoia: */
5769 	qdf_mem_zero(pFrame, nBytes);
5770 
5771 	/* Copy necessary info to BD */
5772 	lim_populate_mac_header(mac, pFrame, SIR_MAC_MGMT_FRAME,
5773 		SIR_MAC_MGMT_ACTION, peer, pe_session->self_mac_addr);
5774 
5775 	/* Update A3 with the BSSID */
5776 	pMacHdr = (tpSirMacMgmtHdr) pFrame;
5777 
5778 	sir_copy_mac_addr(pMacHdr->bssId, pe_session->bssId);
5779 
5780 	lim_set_protected_bit(mac, pe_session, peer, pMacHdr);
5781 
5782 	/* Now, we're ready to "pack" the frames */
5783 	nStatus = dot11f_pack_radio_measurement_report(mac,
5784 						       frm,
5785 						       pFrame +
5786 						       sizeof(tSirMacMgmtHdr),
5787 						       nPayload, &nPayload);
5788 
5789 	if (DOT11F_FAILED(nStatus)) {
5790 		pe_nofl_err("Failed to pack an Radio Measure Report (0x%08x)",
5791 			nStatus);
5792 
5793 		/* FIXME - Need to convert to QDF_STATUS */
5794 		status_code = QDF_STATUS_E_FAILURE;
5795 		goto returnAfterError;
5796 	} else if (DOT11F_WARNED(nStatus)) {
5797 		pe_warn("Warnings while packing Radio Measure Report (0x%08x)",
5798 			nStatus);
5799 	}
5800 
5801 	if (frm->MeasurementReport[0].type == SIR_MAC_RRM_BEACON_TYPE) {
5802 		lim_beacon_report_response_event(frm->MeasurementReport[0].token,
5803 						 num_report,
5804 						 pe_session);
5805 	}
5806 
5807 	pe_nofl_rl_info("TX: type:%d seq_no:%d dialog_token:%d no. of APs:%d is_last_rpt:%d num_report:%d peer:"QDF_MAC_ADDR_FMT,
5808 			frm->MeasurementReport[0].type,
5809 			(pMacHdr->seqControl.seqNumHi << HIGH_SEQ_NUM_OFFSET |
5810 			pMacHdr->seqControl.seqNumLo),
5811 			dialog_token, frm->num_MeasurementReport,
5812 			is_last_report, num_report, QDF_MAC_ADDR_REF(peer));
5813 
5814 	if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) ||
5815 	    pe_session->opmode == QDF_P2P_CLIENT_MODE ||
5816 	    pe_session->opmode == QDF_P2P_GO_MODE)
5817 		txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
5818 
5819 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
5820 			 pe_session->peSessionId, pMacHdr->fc.subType));
5821 	qdf_status = wma_tx_frame(mac, pPacket, (uint16_t)nBytes,
5822 				  TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS,
5823 				  7, lim_tx_complete, pFrame, txFlag,
5824 				  smeSessionId, 0, RATEID_DEFAULT, 0);
5825 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
5826 			 pe_session->peSessionId, qdf_status));
5827 	if (QDF_STATUS_SUCCESS != qdf_status) {
5828 		pe_nofl_rl_err("TX: [802.11 RRM] Send FAILED! err_status [%d]",
5829 			       qdf_status);
5830 		status_code = QDF_STATUS_E_FAILURE;
5831 		/* Pkt will be freed up by the callback */
5832 	}
5833 
5834 	qdf_mem_free(frm);
5835 	return status_code;
5836 
5837 returnAfterError:
5838 	qdf_mem_free(frm);
5839 	cds_packet_free((void *)pPacket);
5840 	return status_code;
5841 }
5842 
5843 bool
5844 lim_is_self_and_peer_ocv_capable(struct mac_context *mac,
5845 				 uint8_t *peer,
5846 				 struct pe_session *pe_session)
5847 {
5848 	uint16_t self_rsn_cap, aid;
5849 	tpDphHashNode sta_ds;
5850 
5851 	self_rsn_cap = wlan_crypto_get_param(pe_session->vdev,
5852 					     WLAN_CRYPTO_PARAM_RSN_CAP);
5853 	if (!(self_rsn_cap & WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED))
5854 		return false;
5855 
5856 	sta_ds = dph_lookup_hash_entry(mac, peer, &aid,
5857 				       &pe_session->dph.dphHashTable);
5858 
5859 	if (sta_ds && sta_ds->ocv_enabled)
5860 		return true;
5861 
5862 	return false;
5863 }
5864 
5865 void
5866 lim_fill_oci_params(struct mac_context *mac, struct pe_session *session,
5867 		    tDot11fIEoci *oci, uint8_t *peer, uint16_t *tx_chan_width)
5868 {
5869 	tpDphHashNode sta_ds;
5870 	uint16_t aid;
5871 	uint8_t ch_offset;
5872 	uint8_t prim_ch_num = wlan_reg_freq_to_chan(mac->pdev,
5873 						    session->curr_op_freq);
5874 	if (session->ch_width == CH_WIDTH_80MHZ) {
5875 		ch_offset = BW80;
5876 	} else {
5877 		switch (session->htSecondaryChannelOffset) {
5878 		case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
5879 			ch_offset = BW40_HIGH_PRIMARY;
5880 			break;
5881 		case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
5882 			ch_offset = BW40_LOW_PRIMARY;
5883 			break;
5884 		default:
5885 			ch_offset = BW20;
5886 			break;
5887 		}
5888 	}
5889 	oci->op_class = lim_op_class_from_bandwidth(mac,
5890 						    session->curr_op_freq,
5891 						    session->ch_width,
5892 						    ch_offset);
5893 	oci->prim_ch_num = prim_ch_num;
5894 	oci->freq_seg_1_ch_num = session->ch_center_freq_seg1;
5895 	oci->present = 1;
5896 	if (tx_chan_width)
5897 		*tx_chan_width = ch_width_in_mhz(session->ch_width);
5898 	if (LIM_IS_STA_ROLE(session))
5899 		return;
5900 
5901 	if (!peer || !tx_chan_width)
5902 		return;
5903 
5904 	sta_ds = dph_lookup_hash_entry(mac, peer, &aid,
5905 				       &session->dph.dphHashTable);
5906 	if (!sta_ds) {
5907 		pe_nofl_debug("no find sta ds "QDF_MAC_ADDR_FMT,
5908 			      QDF_MAC_ADDR_REF(peer));
5909 		return;
5910 	}
5911 	if (WLAN_REG_IS_24GHZ_CH_FREQ(session->curr_op_freq)) {
5912 		if (*tx_chan_width > 20 &&
5913 		    !sta_ds->htSupportedChannelWidthSet) {
5914 			*tx_chan_width = 20;
5915 			pe_nofl_debug("peer no support ht40 in 2g, %d :"QDF_MAC_ADDR_FMT,
5916 				      sta_ds->ch_width,
5917 				      QDF_MAC_ADDR_REF(peer));
5918 		}
5919 	}
5920 }
5921 
5922 /**
5923  * \brief Send SA query request action frame to peer
5924  *
5925  * \sa lim_send_sa_query_request_frame
5926  *
5927  *
5928  * \param mac    The global struct mac_context *object
5929  *
5930  * \param transId Transaction identifier
5931  *
5932  * \param peer    The Mac address of the station to which this action frame is addressed
5933  *
5934  * \param pe_session The PE session entry
5935  *
5936  * \return QDF_STATUS_SUCCESS if setup completes successfully
5937  *         QDF_STATUS_E_FAILURE is some problem is encountered
5938  */
5939 
5940 QDF_STATUS lim_send_sa_query_request_frame(struct mac_context *mac, uint8_t *transId,
5941 					      tSirMacAddr peer,
5942 					      struct pe_session *pe_session)
5943 {
5944 
5945 	tDot11fSaQueryReq frm;  /* SA query request action frame */
5946 	uint8_t *pFrame;
5947 	QDF_STATUS nSirStatus;
5948 	tpSirMacMgmtHdr pMacHdr;
5949 	uint32_t nBytes, nPayload, nStatus;
5950 	void *pPacket;
5951 	QDF_STATUS qdf_status;
5952 	uint8_t txFlag = 0;
5953 	uint8_t smeSessionId = 0;
5954 
5955 	qdf_mem_zero((uint8_t *) &frm, sizeof(frm));
5956 	frm.Category.category = ACTION_CATEGORY_SA_QUERY;
5957 	/* 11w action  field is :
5958 	   action: 0 --> SA Query Request action frame
5959 	   action: 1 --> SA Query Response action frame */
5960 	frm.Action.action = SA_QUERY_REQUEST;
5961 	/* 11w SA Query Request transId */
5962 	qdf_mem_copy(&frm.TransactionId.transId[0], &transId[0], 2);
5963 
5964 	if (lim_is_self_and_peer_ocv_capable(mac, peer, pe_session))
5965 		lim_fill_oci_params(mac, pe_session, &frm.oci, NULL, NULL);
5966 
5967 	nStatus = dot11f_get_packed_sa_query_req_size(mac, &frm, &nPayload);
5968 	if (DOT11F_FAILED(nStatus)) {
5969 		pe_err("Failed to calculate the packed size for an SA Query Request (0x%08x)",
5970 			nStatus);
5971 		/* We'll fall back on the worst case scenario: */
5972 		nPayload = sizeof(tDot11fSaQueryReq);
5973 	} else if (DOT11F_WARNED(nStatus)) {
5974 		pe_warn("There were warnings while calculating the packed size for an SA Query Request (0x%08x)",
5975 			nStatus);
5976 	}
5977 
5978 	nBytes = nPayload + sizeof(tSirMacMgmtHdr);
5979 	qdf_status =
5980 		cds_packet_alloc(nBytes, (void **)&pFrame, (void **)&pPacket);
5981 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
5982 		pe_err("Failed to allocate %d bytes for a SA Query Request "
5983 			   "action frame", nBytes);
5984 		return QDF_STATUS_E_FAILURE;
5985 	}
5986 	/* Paranoia: */
5987 	qdf_mem_zero(pFrame, nBytes);
5988 
5989 	/* Copy necessary info to BD */
5990 	lim_populate_mac_header(mac, pFrame, SIR_MAC_MGMT_FRAME,
5991 		SIR_MAC_MGMT_ACTION, peer, pe_session->self_mac_addr);
5992 
5993 	/* Update A3 with the BSSID */
5994 	pMacHdr = (tpSirMacMgmtHdr) pFrame;
5995 
5996 	sir_copy_mac_addr(pMacHdr->bssId, pe_session->bssId);
5997 
5998 	/* Since this is a SA Query Request, set the "protect" (aka WEP) bit */
5999 	/* in the FC */
6000 	lim_set_protected_bit(mac, pe_session, peer, pMacHdr);
6001 
6002 	/* Pack 11w SA Query Request frame */
6003 	nStatus = dot11f_pack_sa_query_req(mac,
6004 					   &frm,
6005 					   pFrame + sizeof(tSirMacMgmtHdr),
6006 					   nPayload, &nPayload);
6007 
6008 	if (DOT11F_FAILED(nStatus)) {
6009 		pe_err("Failed to pack an SA Query Request (0x%08x)",
6010 			nStatus);
6011 		/* FIXME - Need to convert to QDF_STATUS */
6012 		nSirStatus = QDF_STATUS_E_FAILURE;
6013 		goto returnAfterError;
6014 	} else if (DOT11F_WARNED(nStatus)) {
6015 		pe_warn("There were warnings while packing SA Query Request (0x%08x)",
6016 			nStatus);
6017 	}
6018 
6019 	pe_debug("Sending an SA Query Request from "QDF_MAC_ADDR_FMT" to "QDF_MAC_ADDR_FMT,
6020 		 QDF_MAC_ADDR_REF(pe_session->self_mac_addr),
6021 		 QDF_MAC_ADDR_REF(peer));
6022 
6023 	if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) ||
6024 	    pe_session->opmode == QDF_P2P_CLIENT_MODE ||
6025 	    pe_session->opmode == QDF_P2P_GO_MODE)
6026 		txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
6027 
6028 	smeSessionId = pe_session->smeSessionId;
6029 
6030 	qdf_status = wma_tx_frame(mac,
6031 				pPacket,
6032 				(uint16_t) nBytes,
6033 				TXRX_FRM_802_11_MGMT,
6034 				ANI_TXDIR_TODS,
6035 				7, lim_tx_complete, pFrame, txFlag,
6036 				smeSessionId, 0, RATEID_DEFAULT, 0);
6037 	if (QDF_STATUS_SUCCESS != qdf_status) {
6038 		pe_err("wma_tx_frame FAILED! Status [%d]", qdf_status);
6039 		nSirStatus = QDF_STATUS_E_FAILURE;
6040 		/* Pkt will be freed up by the callback */
6041 		return nSirStatus;
6042 	} else {
6043 		return QDF_STATUS_SUCCESS;
6044 	}
6045 
6046 returnAfterError:
6047 	cds_packet_free((void *)pPacket);
6048 
6049 	return nSirStatus;
6050 } /* End lim_send_sa_query_request_frame */
6051 
6052 /**
6053  * lim_send_sa_query_response_frame() - Send SA query response action frame to
6054  * peer
6055  * @mac: The global struct mac_context *object
6056  * @transId: Transaction identifier received in SA query request action frame
6057  * @peer:    The Mac address of the AP to which this action frame is addressed
6058  * @pe_session: The PE session entry
6059  *
6060  * Return: QDF_STATUS_SUCCESS if setup completes successfully
6061  *         QDF_STATUS_E_FAILURE is some problem is encountered
6062  */
6063 QDF_STATUS lim_send_sa_query_response_frame(struct mac_context *mac,
6064 					    uint8_t *transId, tSirMacAddr peer,
6065 					    struct pe_session *pe_session)
6066 {
6067 
6068 	tDot11fSaQueryRsp frm;  /* SA query response action frame */
6069 	uint8_t *pFrame;
6070 	QDF_STATUS nSirStatus;
6071 	tpSirMacMgmtHdr pMacHdr;
6072 	uint32_t nBytes, nPayload, nStatus;
6073 	void *pPacket;
6074 	QDF_STATUS qdf_status;
6075 	uint8_t txFlag = 0;
6076 	uint8_t smeSessionId = 0;
6077 
6078 	smeSessionId = pe_session->smeSessionId;
6079 
6080 	qdf_mem_zero((uint8_t *) &frm, sizeof(frm));
6081 	frm.Category.category = ACTION_CATEGORY_SA_QUERY;
6082 	/*11w action  field is :
6083 	   action: 0 --> SA query request action frame
6084 	   action: 1 --> SA query response action frame */
6085 	frm.Action.action = SA_QUERY_RESPONSE;
6086 	/*11w SA query response transId is same as
6087 	   SA query request transId */
6088 	qdf_mem_copy(&frm.TransactionId.transId[0], &transId[0], 2);
6089 	if (lim_is_self_and_peer_ocv_capable(mac, peer, pe_session))
6090 		lim_fill_oci_params(mac, pe_session, &frm.oci, NULL, NULL);
6091 
6092 	nStatus = dot11f_get_packed_sa_query_rsp_size(mac, &frm, &nPayload);
6093 	if (DOT11F_FAILED(nStatus)) {
6094 		pe_err("Failed to calculate the packed size for a SA Query Response (0x%08x)",
6095 			nStatus);
6096 		/* We'll fall back on the worst case scenario: */
6097 		nPayload = sizeof(tDot11fSaQueryRsp);
6098 	} else if (DOT11F_WARNED(nStatus)) {
6099 		pe_warn("There were warnings while calculating the packed size for an SA Query Response (0x%08x)",
6100 			nStatus);
6101 	}
6102 	nBytes = nPayload + sizeof(tSirMacMgmtHdr);
6103 	qdf_status =
6104 		cds_packet_alloc(nBytes, (void **)&pFrame, (void **)&pPacket);
6105 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
6106 		pe_err("Failed to allocate %d bytes for a SA query response"
6107 			   " action frame", nBytes);
6108 		return QDF_STATUS_E_FAILURE;
6109 	}
6110 	/* Paranoia: */
6111 	qdf_mem_zero(pFrame, nBytes);
6112 
6113 	/* Copy necessary info to BD */
6114 	lim_populate_mac_header(mac, pFrame, SIR_MAC_MGMT_FRAME,
6115 		SIR_MAC_MGMT_ACTION, peer, pe_session->self_mac_addr);
6116 
6117 	/* Update A3 with the BSSID */
6118 	pMacHdr = (tpSirMacMgmtHdr) pFrame;
6119 
6120 	sir_copy_mac_addr(pMacHdr->bssId, pe_session->bssId);
6121 
6122 	/* Since this is a SA Query Response, set the "protect" (aka WEP) bit */
6123 	/* in the FC */
6124 	lim_set_protected_bit(mac, pe_session, peer, pMacHdr);
6125 
6126 	/* Pack 11w SA query response frame */
6127 	nStatus = dot11f_pack_sa_query_rsp(mac,
6128 					   &frm,
6129 					   pFrame + sizeof(tSirMacMgmtHdr),
6130 					   nPayload, &nPayload);
6131 
6132 	if (DOT11F_FAILED(nStatus)) {
6133 		pe_err("Failed to pack an SA Query Response (0x%08x)",
6134 			nStatus);
6135 		/* FIXME - Need to convert to QDF_STATUS */
6136 		nSirStatus = QDF_STATUS_E_FAILURE;
6137 		goto returnAfterError;
6138 	} else if (DOT11F_WARNED(nStatus)) {
6139 		pe_warn("There were warnings while packing SA Query Response (0x%08x)",
6140 			nStatus);
6141 	}
6142 
6143 	pe_debug("Sending SA Query Response to "QDF_MAC_ADDR_FMT" op_class %d prim_ch_num %d freq_seg_1_ch_num %d oci_present %d",
6144 		 QDF_MAC_ADDR_REF(peer), frm.oci.op_class,
6145 		 frm.oci.prim_ch_num, frm.oci.freq_seg_1_ch_num,
6146 		 frm.oci.present);
6147 
6148 	if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) ||
6149 	    pe_session->opmode == QDF_P2P_CLIENT_MODE ||
6150 	    pe_session->opmode == QDF_P2P_GO_MODE)
6151 		txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
6152 
6153 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
6154 			 pe_session->peSessionId, pMacHdr->fc.subType));
6155 	qdf_status = wma_tx_frame(mac,
6156 				pPacket,
6157 				(uint16_t) nBytes,
6158 				TXRX_FRM_802_11_MGMT,
6159 				ANI_TXDIR_TODS,
6160 				7, lim_tx_complete, pFrame, txFlag,
6161 				smeSessionId, 0, RATEID_DEFAULT, 0);
6162 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
6163 			 pe_session->peSessionId, qdf_status));
6164 	if (QDF_STATUS_SUCCESS != qdf_status) {
6165 		pe_err("wma_tx_frame FAILED! Status [%d]", qdf_status);
6166 		nSirStatus = QDF_STATUS_E_FAILURE;
6167 		/* Pkt will be freed up by the callback */
6168 		return nSirStatus;
6169 	} else {
6170 		return QDF_STATUS_SUCCESS;
6171 	}
6172 
6173 returnAfterError:
6174 	cds_packet_free((void *)pPacket);
6175 	return nSirStatus;
6176 } /* End lim_send_sa_query_response_frame */
6177 
6178 #if defined(CONFIG_LITHIUM) || defined(CONFIG_BERYLLIUM)
6179 #ifdef WLAN_FEATURE_11AX
6180 #define IS_PE_SESSION_HE_MODE(_session) ((_session)->he_capable)
6181 #else
6182 #define IS_PE_SESSION_HE_MODE(_session) false
6183 #endif /* WLAN_FEATURE_11AX */
6184 #else
6185 #define IS_PE_SESSION_HE_MODE(_session) false
6186 #endif
6187 
6188 #ifdef FEATURE_WLAN_TDLS
6189 static bool lim_tdls_peer_support_he(tpDphHashNode sta_ds)
6190 {
6191 	bool peer_he_cap = false;
6192 
6193 	if (sta_ds) {
6194 		peer_he_cap = lim_is_sta_he_capable(sta_ds);
6195 		if (sta_ds->staType == STA_ENTRY_TDLS_PEER && peer_he_cap)
6196 			return true;
6197 		else
6198 			return false;
6199 	} else {
6200 		return false;
6201 	}
6202 }
6203 #else
6204 static inline
6205 bool lim_tdls_peer_support_he(tpDphHashNode sta_ds)
6206 {
6207 	return false;
6208 }
6209 #endif
6210 
6211 #ifdef WLAN_FEATURE_11BE_MLO
6212 static
6213 void lim_prepare_tdls_with_mlo(struct pe_session *session,
6214 			       tSirMacAddr peer_mac, tSirMacAddr self_mac,
6215 			       uint16_t *action)
6216 {
6217 	uint8_t *mld_addr;
6218 
6219 	if (!sir_compare_mac_addr(session->bssId, peer_mac) &&
6220 	    wlan_mlo_get_tdls_link_vdev(session->vdev)) {
6221 		mld_addr = wlan_vdev_mlme_get_mldaddr(session->vdev);
6222 		sir_copy_mac_addr(self_mac, mld_addr);
6223 		*action = ACTION_CATEGORY_BACK << 8 | ADDBA_RESPONSE;
6224 	} else {
6225 		sir_copy_mac_addr(self_mac, session->self_mac_addr);
6226 		*action = 0;
6227 	}
6228 }
6229 #else
6230 static
6231 void lim_prepare_tdls_with_mlo(struct pe_session *session,
6232 			       tSirMacAddr peer_mac, tSirMacAddr self_mac,
6233 			       uint16_t *action)
6234 {
6235 	sir_copy_mac_addr(self_mac, session->self_mac_addr);
6236 	*action = 0;
6237 }
6238 #endif
6239 
6240 QDF_STATUS lim_send_addba_response_frame(struct mac_context *mac_ctx,
6241 					 tSirMacAddr peer_mac, uint16_t tid,
6242 					 struct pe_session *session,
6243 					 uint8_t addba_extn_present,
6244 					 uint8_t amsdu_support, uint8_t is_wep,
6245 					 uint16_t calc_buff_size,
6246 					 tSirMacAddr bssid)
6247 {
6248 
6249 	tDot11faddba_rsp frm;
6250 	uint8_t *frame_ptr;
6251 	tpSirMacMgmtHdr mgmt_hdr;
6252 	uint32_t num_bytes, payload_size, status;
6253 	void *pkt_ptr = NULL;
6254 	QDF_STATUS qdf_status;
6255 	uint8_t tx_flag = 0;
6256 	uint8_t vdev_id = 0;
6257 	uint16_t buff_size, status_code, batimeout;
6258 	uint16_t frm_buff_size = 0;
6259 	uint8_t dialog_token;
6260 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
6261 	uint8_t he_frag = 0;
6262 	tpDphHashNode sta_ds = NULL;
6263 	uint16_t aid;
6264 	bool he_cap = false;
6265 	bool eht_cap = false;
6266 	struct wlan_mlme_qos *qos_aggr;
6267 	tSirMacAddr self_mac;
6268 	uint16_t action;
6269 
6270 	vdev_id = session->vdev_id;
6271 
6272 	cdp_addba_responsesetup(soc, peer_mac, vdev_id, tid,
6273 				&dialog_token, &status_code, &buff_size,
6274 				&batimeout);
6275 
6276 	qos_aggr = &mac_ctx->mlme_cfg->qos_mlme_params;
6277 	qdf_mem_zero((uint8_t *) &frm, sizeof(frm));
6278 	frm.Category.category = ACTION_CATEGORY_BACK;
6279 	frm.Action.action = ADDBA_RESPONSE;
6280 
6281 	frm.DialogToken.token = dialog_token;
6282 	frm.Status.status = status_code;
6283 
6284 	sta_ds = dph_lookup_hash_entry(mac_ctx, peer_mac, &aid,
6285 				       &session->dph.dphHashTable);
6286 
6287 	if (sta_ds && lim_is_session_he_capable(session))
6288 		he_cap = lim_is_sta_he_capable(sta_ds);
6289 
6290 	if (sta_ds && lim_is_session_eht_capable(session))
6291 		eht_cap = lim_is_sta_eht_capable(sta_ds);
6292 
6293 	if ((LIM_IS_STA_ROLE(session) && qos_aggr->rx_aggregation_size == 1 &&
6294 	    !mac_ctx->usr_cfg_ba_buff_size) || mac_ctx->reject_addba_req) {
6295 		frm.Status.status = STATUS_REQUEST_DECLINED;
6296 		pe_err("refused addba req for rx_aggregation_size: %d mac_ctx->reject_addba_req: %d",
6297 		       qos_aggr->rx_aggregation_size, mac_ctx->reject_addba_req);
6298 	} else if (LIM_IS_STA_ROLE(session) && !mac_ctx->usr_cfg_ba_buff_size) {
6299 		frm_buff_size =
6300 			QDF_MIN(qos_aggr->rx_aggregation_size, calc_buff_size);
6301 		pe_debug("rx_aggregation_size %d, calc_buff_size %d",
6302 			 qos_aggr->rx_aggregation_size, calc_buff_size);
6303 
6304 		if (eht_cap) {
6305 			if (frm_buff_size > MAX_EHT_BA_BUFF_SIZE)
6306 				frm_buff_size = MAX_EHT_BA_BUFF_SIZE;
6307 		} else {
6308 			if (frm_buff_size > MAX_BA_BUFF_SIZE)
6309 				frm_buff_size = MAX_BA_BUFF_SIZE;
6310 		}
6311 	} else {
6312 		if (sta_ds && sta_ds->staType == STA_ENTRY_NDI_PEER)
6313 			frm_buff_size = calc_buff_size;
6314 		else if (eht_cap)
6315 			frm_buff_size = MAX_EHT_BA_BUFF_SIZE;
6316 		else if (he_cap)
6317 			frm_buff_size = MAX_BA_BUFF_SIZE;
6318 		else
6319 			frm_buff_size = SIR_MAC_BA_DEFAULT_BUFF_SIZE;
6320 
6321 		if (mac_ctx->usr_cfg_ba_buff_size)
6322 			frm_buff_size = mac_ctx->usr_cfg_ba_buff_size;
6323 
6324 		if (eht_cap) {
6325 			if (frm_buff_size > MAX_EHT_BA_BUFF_SIZE)
6326 				frm_buff_size = MAX_EHT_BA_BUFF_SIZE;
6327 		} else {
6328 			if (frm_buff_size > MAX_BA_BUFF_SIZE)
6329 				frm_buff_size = MAX_BA_BUFF_SIZE;
6330 		}
6331 
6332 		if (frm_buff_size > SIR_MAC_BA_DEFAULT_BUFF_SIZE) {
6333 			if (session->active_ba_64_session) {
6334 				frm_buff_size = SIR_MAC_BA_DEFAULT_BUFF_SIZE;
6335 			}
6336 		} else if (!session->active_ba_64_session) {
6337 			session->active_ba_64_session = true;
6338 		}
6339 		if (buff_size && frm_buff_size > buff_size) {
6340 			pe_debug("buff size: %d larger than peer's capability: %d",
6341 				 frm_buff_size, buff_size);
6342 			frm_buff_size = buff_size;
6343 		}
6344 	}
6345 
6346 	/* In case where AP advertizes BA window size which is different
6347 	 * than our max supported BA window size.
6348 	 */
6349 	cdp_tid_update_ba_win_size(soc, peer_mac, vdev_id, tid, frm_buff_size);
6350 
6351 	frm.addba_param_set.tid = tid;
6352 	frm.addba_param_set.buff_size = frm_buff_size % MAX_EHT_BA_BUFF_SIZE;
6353 
6354 	/* Enable RX AMSDU only in HE mode if supported */
6355 	if (mac_ctx->is_usr_cfg_amsdu_enabled &&
6356 	    ((IS_PE_SESSION_HE_MODE(session) &&
6357 	      WLAN_REG_IS_24GHZ_CH_FREQ(session->curr_op_freq)) ||
6358 	     !WLAN_REG_IS_24GHZ_CH_FREQ(session->curr_op_freq) ||
6359 	     lim_tdls_peer_support_he(sta_ds)))
6360 		frm.addba_param_set.amsdu_supp = amsdu_support;
6361 	else
6362 		frm.addba_param_set.amsdu_supp = 0;
6363 
6364 	frm.addba_param_set.policy = SIR_MAC_BA_POLICY_IMMEDIATE;
6365 	frm.ba_timeout.timeout = batimeout;
6366 	if (addba_extn_present) {
6367 		frm.addba_extn_element.present = 1;
6368 		frm.addba_extn_element.no_fragmentation = 1;
6369 		frm.addba_extn_element.extd_buff_size =
6370 					frm_buff_size / MAX_EHT_BA_BUFF_SIZE;
6371 		if (lim_is_session_he_capable(session)) {
6372 			he_frag = lim_get_session_he_frag_cap(session);
6373 			if (he_frag != 0) {
6374 				frm.addba_extn_element.no_fragmentation = 0;
6375 				frm.addba_extn_element.he_frag_operation =
6376 					he_frag;
6377 			}
6378 		}
6379 	}
6380 
6381 	/*
6382 	 * for TDLS MLO case, it needs to use MLD mac address for TA and
6383 	 * set action code to send out from specific vdev in fw.
6384 	 */
6385 	lim_prepare_tdls_with_mlo(session, peer_mac, self_mac, &action);
6386 	pe_debug("Sending a ADDBA Response from "QDF_MAC_ADDR_FMT" to "QDF_MAC_ADDR_FMT,
6387 		 QDF_MAC_ADDR_REF(self_mac),
6388 		 QDF_MAC_ADDR_REF(peer_mac));
6389 	pe_debug("tid %d dialog_token %d status %d buff_size %d amsdu_supp %d",
6390 		 tid, frm.DialogToken.token, frm.Status.status,
6391 		 frm.addba_param_set.buff_size,
6392 		 frm.addba_param_set.amsdu_supp);
6393 	pe_debug("addba_extn %d he_capable %d no_frag %d he_frag %d, exted buff size %d",
6394 		 addba_extn_present,
6395 		 lim_is_session_he_capable(session),
6396 		 frm.addba_extn_element.no_fragmentation,
6397 		 frm.addba_extn_element.he_frag_operation,
6398 		 frm.addba_extn_element.extd_buff_size);
6399 
6400 	status = dot11f_get_packed_addba_rsp_size(mac_ctx, &frm, &payload_size);
6401 	if (DOT11F_FAILED(status)) {
6402 		pe_err("Failed to calculate the packed size for a ADDBA Response (0x%08x).",
6403 			status);
6404 		/* We'll fall back on the worst case scenario: */
6405 		payload_size = sizeof(tDot11faddba_rsp);
6406 	} else if (DOT11F_WARNED(status)) {
6407 		pe_warn("There were warnings while calculating the packed size for a ADDBA Response (0x%08x).", status);
6408 	}
6409 
6410 	num_bytes = payload_size + sizeof(*mgmt_hdr);
6411 	qdf_status = cds_packet_alloc(num_bytes, (void **)&frame_ptr,
6412 				      (void **)&pkt_ptr);
6413 	if (!QDF_IS_STATUS_SUCCESS(qdf_status) || (!pkt_ptr)) {
6414 		pe_err("Failed to allocate %d bytes for a ADDBA response action frame",
6415 			num_bytes);
6416 		return QDF_STATUS_E_FAILURE;
6417 	}
6418 	qdf_mem_zero(frame_ptr, num_bytes);
6419 
6420 	lim_populate_mac_header(mac_ctx, frame_ptr, SIR_MAC_MGMT_FRAME,
6421 		SIR_MAC_MGMT_ACTION, peer_mac, self_mac);
6422 
6423 	/* Update A3 with the BSSID */
6424 	mgmt_hdr = (tpSirMacMgmtHdr) frame_ptr;
6425 
6426 	sir_copy_mac_addr(mgmt_hdr->bssId, bssid);
6427 
6428 	/* ADDBA Response is a robust mgmt action frame,
6429 	 * set the "protect" (aka WEP) bit in the FC
6430 	 */
6431 	lim_set_protected_bit(mac_ctx, session, peer_mac, mgmt_hdr);
6432 
6433 	if (is_wep && sta_ds && sta_ds->staType == STA_ENTRY_NDI_PEER) {
6434 		mgmt_hdr->fc.wep = 1;
6435 		tx_flag |= HAL_USE_PMF;
6436 	}
6437 
6438 	status = dot11f_pack_addba_rsp(mac_ctx, &frm,
6439 			frame_ptr + sizeof(tSirMacMgmtHdr), payload_size,
6440 			&payload_size);
6441 
6442 	if (DOT11F_FAILED(status)) {
6443 		pe_err("Failed to pack a ADDBA Response (0x%08x)",
6444 			status);
6445 		qdf_status = QDF_STATUS_E_FAILURE;
6446 		goto error_addba_rsp;
6447 	} else if (DOT11F_WARNED(status)) {
6448 		pe_warn("There were warnings while packing ADDBA Response (0x%08x)",
6449 			status);
6450 	}
6451 
6452 
6453 	if (!wlan_reg_is_24ghz_ch_freq(session->curr_op_freq) ||
6454 	    session->opmode == QDF_P2P_CLIENT_MODE ||
6455 	    session->opmode == QDF_P2P_GO_MODE)
6456 		tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
6457 
6458 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
6459 			 session->peSessionId, mgmt_hdr->fc.subType));
6460 	qdf_status = wma_tx_frameWithTxComplete(mac_ctx, pkt_ptr,
6461 						(uint16_t)num_bytes,
6462 						TXRX_FRM_802_11_MGMT,
6463 						ANI_TXDIR_TODS, 7,
6464 						NULL, frame_ptr,
6465 						lim_addba_rsp_tx_complete_cnf,
6466 						tx_flag, vdev_id,
6467 						false, 0, RATEID_DEFAULT, 0,
6468 						action);
6469 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
6470 			 session->peSessionId, qdf_status));
6471 	if (QDF_STATUS_SUCCESS != qdf_status) {
6472 		pe_err("wma_tx_frame FAILED! Status [%d]",
6473 			qdf_status);
6474 		return QDF_STATUS_E_FAILURE;
6475 	} else {
6476 		return QDF_STATUS_SUCCESS;
6477 	}
6478 
6479 error_addba_rsp:
6480 	cds_packet_free((void *)pkt_ptr);
6481 	return qdf_status;
6482 }
6483 
6484 #ifdef WLAN_FEATURE_11BE_MLO
6485 QDF_STATUS
6486 lim_send_epcs_update_edca_params(struct wlan_objmgr_vdev *vdev,
6487 				 tSirMacEdcaParamRecord *edca, bool mu_edca)
6488 {
6489 	struct mac_context *mac_ctx;
6490 
6491 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
6492 	if (!mac_ctx)
6493 		return QDF_STATUS_E_INVAL;
6494 
6495 	return lim_send_edca_params(mac_ctx, edca,
6496 				    wlan_vdev_get_id(vdev), mu_edca);
6497 }
6498 
6499 QDF_STATUS
6500 lim_send_epcs_restore_edca_params(struct wlan_objmgr_vdev *vdev)
6501 {
6502 	struct mac_context *mac_ctx;
6503 	struct pe_session *session;
6504 
6505 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
6506 	if (!mac_ctx)
6507 		return QDF_STATUS_E_INVAL;
6508 
6509 	session = pe_find_session_by_vdev_id(mac_ctx, wlan_vdev_get_id(vdev));
6510 	if (!session)
6511 		return QDF_STATUS_E_INVAL;
6512 
6513 	lim_send_edca_params(mac_ctx, session->gLimEdcaParamsActive,
6514 			     session->vdev_id, false);
6515 
6516 	if (mac_ctx->usr_cfg_mu_edca_params)
6517 		lim_send_edca_params(mac_ctx, mac_ctx->usr_mu_edca_params,
6518 				     session->vdev_id, true);
6519 	else if (session->mu_edca_present)
6520 		lim_send_edca_params(mac_ctx, session->ap_mu_edca_params,
6521 				     session->vdev_id, true);
6522 
6523 	return QDF_STATUS_SUCCESS;
6524 }
6525 
6526 QDF_STATUS
6527 lim_send_epcs_action_rsp_frame(struct wlan_objmgr_vdev *vdev,
6528 			       uint8_t *peer_mac,
6529 			       struct wlan_action_frame_args *args)
6530 {
6531 	struct mac_context *mac_ctx;
6532 	struct pe_session *session;
6533 	tDot11fepcs_neg_rsp frm;
6534 	uint8_t *frame_ptr;
6535 	tpSirMacMgmtHdr mgmt_hdr;
6536 	uint32_t num_bytes, payload_size, status;
6537 	void *pkt_ptr = NULL;
6538 	uint8_t vdev_id = 0;
6539 	uint8_t tx_flag = 0;
6540 	QDF_STATUS qdf_status;
6541 
6542 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
6543 	if (!mac_ctx)
6544 		return QDF_STATUS_E_INVAL;
6545 
6546 	session = pe_find_session_by_vdev_id(mac_ctx, wlan_vdev_get_id(vdev));
6547 	if (!session)
6548 		return QDF_STATUS_E_INVAL;
6549 
6550 	frm.Category.category = args->category;
6551 	frm.Action.action = args->action;
6552 	frm.DialogToken.token = args->arg1;
6553 	frm.Status.status = args->arg2;
6554 
6555 	pe_debug("Sending a EPCS negotiation Response from " QDF_MAC_ADDR_FMT " to " QDF_MAC_ADDR_FMT,
6556 		 QDF_MAC_ADDR_REF(session->self_mac_addr),
6557 		 QDF_MAC_ADDR_REF(peer_mac));
6558 	pe_debug("Dialog token %d status %d", frm.DialogToken.token,
6559 		 frm.Status.status);
6560 
6561 	status = dot11f_get_packed_epcs_neg_rspSize(mac_ctx, &frm,
6562 						    &payload_size);
6563 	if (DOT11F_FAILED(status)) {
6564 		pe_err("Failed to calculate packed size for a EPCS negotiation Response (0x%08x).",
6565 		       status);
6566 		/* We'll fall back on the worst case scenario: */
6567 		payload_size = sizeof(tDot11fepcs_neg_rsp);
6568 	} else if (DOT11F_WARNED(status)) {
6569 		pe_warn("There were warnings while calculating packed size for a EPCS negotiation Response (0x%08x).",
6570 			status);
6571 	}
6572 
6573 	num_bytes = payload_size + sizeof(*mgmt_hdr);
6574 	qdf_status = cds_packet_alloc(num_bytes, (void **)&frame_ptr,
6575 				      (void **)&pkt_ptr);
6576 	if (!QDF_IS_STATUS_SUCCESS(qdf_status) || !pkt_ptr) {
6577 		pe_err("Failed to allocate %d bytes for a EPCS rsp action frm",
6578 		       num_bytes);
6579 		return QDF_STATUS_E_FAILURE;
6580 	}
6581 
6582 	lim_populate_mac_header(mac_ctx, frame_ptr, SIR_MAC_MGMT_FRAME,
6583 				SIR_MAC_MGMT_ACTION, peer_mac,
6584 				session->self_mac_addr);
6585 
6586 	/* Update A3 with the BSSID */
6587 	mgmt_hdr = (tpSirMacMgmtHdr)frame_ptr;
6588 	sir_copy_mac_addr(mgmt_hdr->bssId, session->bssId);
6589 
6590 	lim_set_protected_bit(mac_ctx, session, peer_mac, mgmt_hdr);
6591 
6592 	status = dot11f_pack_epcs_neg_rsp(mac_ctx, &frm,
6593 					  frame_ptr + sizeof(tSirMacMgmtHdr),
6594 					  payload_size, &payload_size);
6595 
6596 	if (DOT11F_FAILED(status)) {
6597 		pe_err("Failed to pack a EPCS negotiation response (0x%08x)",
6598 		       status);
6599 		qdf_status = QDF_STATUS_E_FAILURE;
6600 		goto error_epcs_rsp;
6601 	} else if (DOT11F_WARNED(status)) {
6602 		pe_warn("There were warnings while packing EPCS rsp (0x%08x)",
6603 			status);
6604 	}
6605 
6606 	if (!wlan_reg_is_24ghz_ch_freq(session->curr_op_freq) ||
6607 	    session->opmode == QDF_P2P_CLIENT_MODE ||
6608 	    session->opmode == QDF_P2P_GO_MODE)
6609 		tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
6610 
6611 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
6612 			 session->peSessionId, mgmt_hdr->fc.subType));
6613 
6614 	vdev_id = session->vdev_id;
6615 	qdf_status = wma_tx_frame(mac_ctx, pkt_ptr, (uint16_t)num_bytes,
6616 				  TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
6617 				  lim_tx_complete, frame_ptr, tx_flag,
6618 				  vdev_id, 0, RATEID_DEFAULT, 0);
6619 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
6620 			 session->peSessionId, qdf_status));
6621 	if (QDF_STATUS_SUCCESS != qdf_status) {
6622 		pe_err("wma_tx_frame FAILED! Status [%d]", qdf_status);
6623 		return QDF_STATUS_E_FAILURE;
6624 	} else {
6625 		return QDF_STATUS_SUCCESS;
6626 	}
6627 
6628 error_epcs_rsp:
6629 	cds_packet_free((void *)pkt_ptr);
6630 	return qdf_status;
6631 }
6632 
6633 QDF_STATUS
6634 lim_send_epcs_action_req_frame(struct wlan_objmgr_vdev *vdev,
6635 			       uint8_t *peer_mac,
6636 			       struct wlan_action_frame_args *args)
6637 {
6638 	tDot11fepcs_neg_req frm;
6639 	struct mac_context *mac_ctx;
6640 	struct pe_session *session;
6641 	uint8_t *frame_ptr;
6642 	tpSirMacMgmtHdr mgmt_hdr;
6643 	uint32_t num_bytes, payload_size, status;
6644 	void *pkt_ptr = NULL;
6645 	QDF_STATUS qdf_status;
6646 	uint8_t vdev_id = 0;
6647 	uint8_t tx_flag = 0;
6648 
6649 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
6650 	if (!mac_ctx)
6651 		return QDF_STATUS_E_INVAL;
6652 
6653 	if (!vdev)
6654 		return QDF_STATUS_E_NULL_VALUE;
6655 
6656 	vdev_id = wlan_vdev_get_id(vdev);
6657 
6658 	session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
6659 	if (!session) {
6660 		pe_debug("session not found for given vdev_id %d ", vdev_id);
6661 		return QDF_STATUS_E_INVAL;
6662 	}
6663 
6664 	frm.Category.category = args->category;
6665 	frm.Action.action = args->action;
6666 	frm.DialogToken.token = args->arg1;
6667 
6668 	pe_debug("Sending a EPCS negotiation Request from " QDF_MAC_ADDR_FMT " to " QDF_MAC_ADDR_FMT,
6669 		 QDF_MAC_ADDR_REF(session->self_mac_addr),
6670 		 QDF_MAC_ADDR_REF(peer_mac));
6671 	pe_debug("Dialog token %d", frm.DialogToken.token);
6672 
6673 	status = dot11f_get_packed_epcs_neg_reqSize(mac_ctx, &frm,
6674 						    &payload_size);
6675 	if (DOT11F_FAILED(status)) {
6676 		pe_err("Failed to calculate packed size for a EPCS negotiation Request (0x%08x).",
6677 		       status);
6678 		/* We'll fall back on the worst case scenario: */
6679 		payload_size = sizeof(tDot11fepcs_neg_req);
6680 	} else if (DOT11F_WARNED(status)) {
6681 		pe_warn("There were warnings while calculating packed size for a EPCS negotiation Request (0x%08x).",
6682 			status);
6683 	}
6684 
6685 	num_bytes = payload_size + sizeof(*mgmt_hdr);
6686 	qdf_status = cds_packet_alloc(num_bytes, (void **)&frame_ptr,
6687 				      (void **)&pkt_ptr);
6688 	if (!QDF_IS_STATUS_SUCCESS(qdf_status) || (!pkt_ptr)) {
6689 		pe_err("Failed to allocate %d bytes for a EPCS req action frm",
6690 		       num_bytes);
6691 		return QDF_STATUS_E_FAILURE;
6692 	}
6693 
6694 	lim_populate_mac_header(mac_ctx, frame_ptr, SIR_MAC_MGMT_FRAME,
6695 				SIR_MAC_MGMT_ACTION, peer_mac,
6696 				session->self_mac_addr);
6697 
6698 	/* Update A3 with the BSSID */
6699 	mgmt_hdr = (tpSirMacMgmtHdr)frame_ptr;
6700 	sir_copy_mac_addr(mgmt_hdr->bssId, session->bssId);
6701 	lim_set_protected_bit(mac_ctx, session, peer_mac, mgmt_hdr);
6702 
6703 	status = dot11f_pack_epcs_neg_req(mac_ctx, &frm,
6704 					  frame_ptr + sizeof(tSirMacMgmtHdr),
6705 					  payload_size, &payload_size);
6706 
6707 	if (DOT11F_FAILED(status)) {
6708 		pe_err("Failed to pack a EPCS negotiation request (0x%08x)",
6709 		       status);
6710 		qdf_status = QDF_STATUS_E_FAILURE;
6711 		goto error_epcs_req;
6712 	} else if (DOT11F_WARNED(status)) {
6713 		pe_warn("There were warnings while packing EPCS req (0x%08x)",
6714 			status);
6715 	}
6716 
6717 	pe_debug("Dump EPCS TX req action frame");
6718 	qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, frame_ptr,
6719 			   num_bytes);
6720 
6721 	if (!wlan_reg_is_24ghz_ch_freq(session->curr_op_freq) ||
6722 	    session->opmode == QDF_P2P_CLIENT_MODE ||
6723 	    session->opmode == QDF_P2P_GO_MODE)
6724 		tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
6725 
6726 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
6727 			 session->peSessionId, mgmt_hdr->fc.subType));
6728 	qdf_status = wma_tx_frame(mac_ctx, pkt_ptr, (uint16_t)num_bytes,
6729 				  TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
6730 				  lim_tx_complete, frame_ptr, tx_flag,
6731 				  vdev_id, 0, RATEID_DEFAULT, 0);
6732 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
6733 			 session->peSessionId, qdf_status));
6734 	if (qdf_status != QDF_STATUS_SUCCESS) {
6735 		pe_err("wma_tx_frame FAILED! Status [%d]", qdf_status);
6736 		return QDF_STATUS_E_FAILURE;
6737 	} else {
6738 		return QDF_STATUS_SUCCESS;
6739 	}
6740 
6741 error_epcs_req:
6742 	cds_packet_free((void *)pkt_ptr);
6743 	return qdf_status;
6744 }
6745 
6746 QDF_STATUS
6747 lim_send_epcs_action_teardown_frame(struct wlan_objmgr_vdev *vdev,
6748 				    uint8_t *peer_mac,
6749 				    struct wlan_action_frame_args *args)
6750 {
6751 	tDot11fepcs_teardown frm;
6752 	struct mac_context *mac_ctx;
6753 	struct pe_session *session;
6754 	uint8_t *frame_ptr;
6755 	tpSirMacMgmtHdr mgmt_hdr;
6756 	uint32_t num_bytes, payload_size, status;
6757 	void *pkt_ptr = NULL;
6758 	QDF_STATUS qdf_status;
6759 	uint8_t vdev_id = 0;
6760 	uint8_t tx_flag = 0;
6761 
6762 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
6763 	if (!mac_ctx)
6764 		return QDF_STATUS_E_INVAL;
6765 
6766 	if (!vdev)
6767 		return QDF_STATUS_E_NULL_VALUE;
6768 
6769 	vdev_id = wlan_vdev_get_id(vdev);
6770 
6771 	session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
6772 	if (!session) {
6773 		pe_err("session not found for given vdev_id %d", vdev_id);
6774 		return QDF_STATUS_E_INVAL;
6775 	}
6776 
6777 	frm.Category.category = args->category;
6778 	frm.Action.action = args->action;
6779 
6780 	pe_debug("Sending a EPCS tear down from " QDF_MAC_ADDR_FMT " to " QDF_MAC_ADDR_FMT,
6781 		 QDF_MAC_ADDR_REF(session->self_mac_addr),
6782 		 QDF_MAC_ADDR_REF(peer_mac));
6783 
6784 	status = dot11f_get_packed_epcs_teardownSize(mac_ctx, &frm,
6785 						     &payload_size);
6786 	if (DOT11F_FAILED(status)) {
6787 		pe_err("Failed to calculate packed size for a EPCS tear down (0x%08x).",
6788 		       status);
6789 		/* We'll fall back on the worst case scenario: */
6790 		payload_size = sizeof(tDot11fepcs_teardown);
6791 	} else if (DOT11F_WARNED(status)) {
6792 		pe_warn("There were warnings while calculating packed size for a EPCS tear down (0x%08x).",
6793 			status);
6794 	}
6795 
6796 	num_bytes = payload_size + sizeof(*mgmt_hdr);
6797 	qdf_status = cds_packet_alloc(num_bytes, (void **)&frame_ptr,
6798 				      (void **)&pkt_ptr);
6799 	if (!QDF_IS_STATUS_SUCCESS(qdf_status) || (!pkt_ptr)) {
6800 		pe_err("Failed to allocate %d bytes for a EPCS req action frm",
6801 		       num_bytes);
6802 		return QDF_STATUS_E_FAILURE;
6803 	}
6804 	qdf_mem_zero(frame_ptr, num_bytes);
6805 
6806 	lim_populate_mac_header(mac_ctx, frame_ptr, SIR_MAC_MGMT_FRAME,
6807 				SIR_MAC_MGMT_ACTION, peer_mac,
6808 				session->self_mac_addr);
6809 
6810 	/* Update A3 with the BSSID */
6811 	mgmt_hdr = (tpSirMacMgmtHdr)frame_ptr;
6812 	sir_copy_mac_addr(mgmt_hdr->bssId, session->bssId);
6813 	lim_set_protected_bit(mac_ctx, session, peer_mac, mgmt_hdr);
6814 
6815 	status = dot11f_pack_epcs_teardown(mac_ctx, &frm,
6816 					   frame_ptr + sizeof(tSirMacMgmtHdr),
6817 					   payload_size, &payload_size);
6818 	if (DOT11F_FAILED(status)) {
6819 		pe_err("Failed to pack a EPCS tear down (0x%08x)",
6820 		       status);
6821 		qdf_status = QDF_STATUS_E_FAILURE;
6822 		goto error_epcs_td;
6823 	} else if (DOT11F_WARNED(status)) {
6824 		pe_warn("There were warnings while packing EPCS tear down(0x%08x)",
6825 			status);
6826 	}
6827 
6828 	pe_debug("Dump EPCS TX tear down action frame");
6829 	qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, frame_ptr,
6830 			   num_bytes);
6831 
6832 	if (!wlan_reg_is_24ghz_ch_freq(session->curr_op_freq) ||
6833 	    session->opmode == QDF_P2P_CLIENT_MODE ||
6834 	    session->opmode == QDF_P2P_GO_MODE)
6835 		tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
6836 
6837 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
6838 			 session->peSessionId, mgmt_hdr->fc.subType));
6839 	qdf_status = wma_tx_frame(mac_ctx, pkt_ptr, (uint16_t)num_bytes,
6840 				  TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
6841 				  lim_tx_complete, frame_ptr, tx_flag,
6842 				  vdev_id, 0, RATEID_DEFAULT, 0);
6843 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
6844 			 session->peSessionId, qdf_status));
6845 	if (qdf_status != QDF_STATUS_SUCCESS) {
6846 		pe_err("wma_tx_frame FAILED! Status [%d]", qdf_status);
6847 		return QDF_STATUS_E_FAILURE;
6848 	} else {
6849 		return QDF_STATUS_SUCCESS;
6850 	}
6851 
6852 error_epcs_td:
6853 	cds_packet_free((void *)pkt_ptr);
6854 	return qdf_status;
6855 }
6856 
6857 static QDF_STATUS
6858 lim_mgmt_t2lm_rsp_tx_complete(void *context, qdf_nbuf_t buf,
6859 			      uint32_t tx_status, void *params)
6860 {
6861 	struct mac_context *mac_ctx = (struct mac_context *)context;
6862 	struct pe_session *pe_session;
6863 	struct wlan_frame_hdr *mac_hdr;
6864 	struct wmi_mgmt_params *mgmt_params;
6865 	tDot11ft2lm_neg_rsp rsp = {0};
6866 	enum qdf_dp_tx_rx_status qdf_tx_complete;
6867 	uint32_t extract_status;
6868 	uint8_t *frame_ptr;
6869 	uint8_t ff_offset;
6870 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6871 
6872 	if (!params) {
6873 		status = QDF_STATUS_E_FAILURE;
6874 		goto out;
6875 	}
6876 
6877 	frame_ptr = qdf_nbuf_data(buf);
6878 	mac_hdr = (struct wlan_frame_hdr *)frame_ptr;
6879 
6880 	ff_offset = sizeof(*mac_hdr);
6881 	if (wlan_crypto_is_data_protected(frame_ptr))
6882 		ff_offset += IEEE80211_CCMP_MICLEN;
6883 
6884 	if (qdf_nbuf_len(buf) < (ff_offset + sizeof(rsp))) {
6885 		status = QDF_STATUS_E_FAILURE;
6886 		goto out;
6887 	}
6888 
6889 	mgmt_params = params;
6890 	pe_session = pe_find_session_by_vdev_id(mac_ctx, mgmt_params->vdev_id);
6891 	if (!pe_session || pe_session->opmode != QDF_STA_MODE) {
6892 		status = QDF_STATUS_E_FAILURE;
6893 		goto out;
6894 	}
6895 
6896 	if (tx_status == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK)
6897 		qdf_tx_complete = QDF_TX_RX_STATUS_OK;
6898 	else if (tx_status  == WMI_MGMT_TX_COMP_TYPE_DISCARD)
6899 		qdf_tx_complete = QDF_TX_RX_STATUS_FW_DISCARD;
6900 	else
6901 		qdf_tx_complete = QDF_TX_RX_STATUS_NO_ACK;
6902 
6903 	extract_status =
6904 		dot11f_unpack_t2lm_neg_rsp(mac_ctx,
6905 					   frame_ptr + ff_offset,
6906 					   sizeof(rsp), &rsp, false);
6907 	if (DOT11F_FAILED(extract_status)) {
6908 		pe_err("Failed to unpack T2LM negotiation response (0x%08x)",
6909 		       extract_status);
6910 		status = QDF_STATUS_E_FAILURE;
6911 		goto out;
6912 	}
6913 
6914 	wlan_connectivity_t2lm_req_resp_event(pe_session->vdev,
6915 					      rsp.DialogToken.token,
6916 					      rsp.Status.status,
6917 					      qdf_tx_complete,
6918 					      (qdf_freq_t)mgmt_params->chanfreq,
6919 					      false,
6920 					      WLAN_CONN_DIAG_MLO_T2LM_REQ_EVENT);
6921 out:
6922 	qdf_nbuf_free(buf);
6923 
6924 	return status;
6925 }
6926 
6927 static QDF_STATUS
6928 lim_mgmt_t2lm_req_tx_complete(void *context, qdf_nbuf_t buf,
6929 			      uint32_t tx_status, void *params)
6930 {
6931 	struct mac_context *mac_ctx = (struct mac_context *)context;
6932 	struct pe_session *pe_session;
6933 	struct wlan_frame_hdr *mac_hdr;
6934 	struct wmi_mgmt_params *mgmt_params;
6935 	tDot11ft2lm_neg_req req = {0};
6936 	enum qdf_dp_tx_rx_status qdf_tx_complete;
6937 	uint32_t extract_status;
6938 	uint8_t *frame_ptr;
6939 	uint8_t ff_offset;
6940 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6941 
6942 	if (!params) {
6943 		status = QDF_STATUS_E_FAILURE;
6944 		goto out;
6945 	}
6946 
6947 	frame_ptr = qdf_nbuf_data(buf);
6948 	mac_hdr = (struct wlan_frame_hdr *)frame_ptr;
6949 
6950 	ff_offset = sizeof(*mac_hdr);
6951 	if (wlan_crypto_is_data_protected(frame_ptr))
6952 		ff_offset += IEEE80211_CCMP_MICLEN;
6953 
6954 	if (qdf_nbuf_len(buf) < (ff_offset + sizeof(struct action_frm_hdr))) {
6955 		status = QDF_STATUS_E_FAILURE;
6956 		goto out;
6957 	}
6958 
6959 	mgmt_params = params;
6960 	pe_session = pe_find_session_by_vdev_id(mac_ctx, mgmt_params->vdev_id);
6961 	if (!pe_session || pe_session->opmode != QDF_STA_MODE) {
6962 		status = QDF_STATUS_E_FAILURE;
6963 		goto out;
6964 	}
6965 
6966 	if (tx_status == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK)
6967 		qdf_tx_complete = QDF_TX_RX_STATUS_OK;
6968 	else if (tx_status  == WMI_MGMT_TX_COMP_TYPE_DISCARD)
6969 		qdf_tx_complete = QDF_TX_RX_STATUS_FW_DISCARD;
6970 	else
6971 		qdf_tx_complete = QDF_TX_RX_STATUS_NO_ACK;
6972 
6973 	extract_status =
6974 		dot11f_unpack_t2lm_neg_req(mac_ctx,
6975 					   frame_ptr + ff_offset,
6976 					   sizeof(req), &req, false);
6977 	if (DOT11F_FAILED(extract_status)) {
6978 		pe_err("Failed to unpack T2LM negotiation request (0x%08x)",
6979 		       extract_status);
6980 		status = QDF_STATUS_E_FAILURE;
6981 		goto out;
6982 	}
6983 
6984 	wlan_connectivity_t2lm_req_resp_event(pe_session->vdev,
6985 					      req.DialogToken.token,
6986 					      false,
6987 					      qdf_tx_complete,
6988 					      (qdf_freq_t)mgmt_params->chanfreq,
6989 					      false,
6990 					      WLAN_CONN_DIAG_MLO_T2LM_REQ_EVENT);
6991 out:
6992 	qdf_nbuf_free(buf);
6993 
6994 	return status;
6995 }
6996 
6997 QDF_STATUS
6998 lim_send_t2lm_action_rsp_frame(struct mac_context *mac_ctx,
6999 			       tSirMacAddr peer_mac,
7000 			       struct pe_session *session, uint8_t token,
7001 			       enum wlan_t2lm_resp_frm_type status_code)
7002 {
7003 	tDot11ft2lm_neg_rsp frm;
7004 	uint8_t session_id = 0;
7005 	uint8_t *frame_ptr;
7006 	tpSirMacMgmtHdr mgmt_hdr;
7007 	uint32_t num_bytes, payload_size, dot11f_status;
7008 	void *pkt_ptr = NULL;
7009 	QDF_STATUS status;
7010 	uint8_t vdev_id = 0;
7011 	uint8_t tx_flag = 0;
7012 
7013 	session_id = session->smeSessionId;
7014 	vdev_id = session->vdev_id;
7015 
7016 	qdf_mem_zero((uint8_t *)&frm, sizeof(frm));
7017 	frm.Category.category = ACTION_CATEGORY_PROTECTED_EHT;
7018 	frm.Action.action = EHT_T2LM_RESPONSE;
7019 
7020 	frm.DialogToken.token = token;
7021 	frm.Status.status = status_code;
7022 
7023 	pe_debug("Sending a T2LM negotiation Response from " QDF_MAC_ADDR_FMT " to " QDF_MAC_ADDR_FMT,
7024 		 QDF_MAC_ADDR_REF(session->self_mac_addr),
7025 		 QDF_MAC_ADDR_REF(peer_mac));
7026 	pe_debug("Dialog token %d status %d", frm.DialogToken.token,
7027 		 frm.Status.status);
7028 
7029 	dot11f_status = dot11f_get_packed_t2lm_neg_rspSize(mac_ctx, &frm,
7030 							   &payload_size);
7031 	if (DOT11F_FAILED(dot11f_status)) {
7032 		pe_err("Failed to calculate packed size for a T2LM negotiation Response (0x%08x).",
7033 		       dot11f_status);
7034 		/* We'll fall back on the worst case scenario: */
7035 		payload_size = sizeof(tDot11ft2lm_neg_rsp);
7036 	} else if (DOT11F_WARNED(dot11f_status)) {
7037 		pe_warn("There were warnings while calculating packed size for a T2LM negotiation Response (0x%08x).",
7038 			dot11f_status);
7039 	}
7040 
7041 	num_bytes = payload_size + sizeof(*mgmt_hdr);
7042 	status = cds_packet_alloc(num_bytes, (void **)&frame_ptr,
7043 				  (void **)&pkt_ptr);
7044 	if (!QDF_IS_STATUS_SUCCESS(status) || !pkt_ptr) {
7045 		pe_err("Failed to allocate %d bytes for a T2LM rsp action frm",
7046 		       num_bytes);
7047 		return QDF_STATUS_E_FAILURE;
7048 	}
7049 	qdf_mem_zero(frame_ptr, num_bytes);
7050 
7051 	lim_populate_mac_header(mac_ctx, frame_ptr, SIR_MAC_MGMT_FRAME,
7052 				SIR_MAC_MGMT_ACTION, peer_mac,
7053 				session->self_mac_addr);
7054 
7055 	/* Update A3 with the BSSID */
7056 	mgmt_hdr = (tpSirMacMgmtHdr)frame_ptr;
7057 	sir_copy_mac_addr(mgmt_hdr->bssId, session->bssId);
7058 
7059 	lim_set_protected_bit(mac_ctx, session, peer_mac, mgmt_hdr);
7060 
7061 	status = dot11f_pack_t2lm_neg_rsp(mac_ctx, &frm,
7062 					  frame_ptr + sizeof(tSirMacMgmtHdr),
7063 					  payload_size, &payload_size);
7064 
7065 	if (DOT11F_FAILED(status)) {
7066 		pe_err("Failed to pack a T2LM negotiation response (0x%08x)",
7067 		       status);
7068 		status = QDF_STATUS_E_FAILURE;
7069 		goto error_t2lm_rsp;
7070 	} else if (DOT11F_WARNED(status)) {
7071 		pe_warn("There were warnings while packing T2LM rsp (0x%08x)",
7072 			status);
7073 	}
7074 
7075 	if (!wlan_reg_is_24ghz_ch_freq(session->curr_op_freq) ||
7076 	    session->opmode == QDF_P2P_CLIENT_MODE ||
7077 	    session->opmode == QDF_P2P_GO_MODE)
7078 		tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
7079 
7080 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
7081 			 session->peSessionId, mgmt_hdr->fc.subType));
7082 	status = wma_tx_frameWithTxComplete(
7083 			mac_ctx, pkt_ptr, (uint16_t)num_bytes,
7084 			TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
7085 			lim_tx_complete, frame_ptr,
7086 			lim_mgmt_t2lm_rsp_tx_complete,
7087 			tx_flag, vdev_id, 0, session->curr_op_freq,
7088 			RATEID_DEFAULT, 0, 0);
7089 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
7090 			 session->peSessionId, status));
7091 	if (QDF_IS_STATUS_ERROR(status))
7092 		pe_err("wma_tx_frame FAILED! Status [%d]", status);
7093 
7094 	return status;
7095 
7096 error_t2lm_rsp:
7097 	cds_packet_free((void *)pkt_ptr);
7098 	return status;
7099 }
7100 
7101 QDF_STATUS
7102 lim_send_t2lm_action_req_frame(struct wlan_objmgr_vdev *vdev,
7103 			       uint8_t *peer_mac,
7104 			       struct wlan_action_frame_args *args,
7105 			       struct wlan_t2lm_onging_negotiation_info *t2lm_neg,
7106 			       uint8_t token)
7107 {
7108 	tDot11ft2lm_neg_req frm;
7109 	struct mac_context *mac_ctx;
7110 	struct pe_session *session;
7111 	uint8_t session_id = 0;
7112 	uint8_t *frame_ptr;
7113 	tpSirMacMgmtHdr mgmt_hdr;
7114 	uint32_t num_bytes, payload_size, status;
7115 	void *pkt_ptr = NULL;
7116 	QDF_STATUS qdf_status;
7117 	uint8_t vdev_id = 0;
7118 	uint8_t tx_flag = 0;
7119 	struct wlan_ie_tid_to_link_mapping *t2lm_ie;
7120 	struct wlan_ie_tid_to_link_mapping *ie_buf;
7121 	uint8_t *t2lm_frame;
7122 
7123 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
7124 	if (!mac_ctx)
7125 		return QDF_STATUS_E_INVAL;
7126 
7127 	if (!vdev)
7128 		return QDF_STATUS_E_NULL_VALUE;
7129 
7130 	vdev_id = wlan_vdev_get_id(vdev);
7131 
7132 	session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
7133 	if (!session) {
7134 		pe_err("session not found for given vdev_id %d", vdev_id);
7135 		return QDF_STATUS_E_INVAL;
7136 	}
7137 	session_id = session->smeSessionId;
7138 
7139 	qdf_mem_zero((uint8_t *)&frm, sizeof(frm));
7140 
7141 	ie_buf = qdf_mem_malloc(sizeof(uint8_t) * T2LM_IE_ACTION_FRAME_MAX_LEN);
7142 
7143 	if (!ie_buf) {
7144 		pe_err("Malloc failed");
7145 		return QDF_STATUS_E_NULL_VALUE;
7146 	}
7147 
7148 	t2lm_ie = (struct wlan_ie_tid_to_link_mapping *)&frm.t2lm_ie[0].data;
7149 	t2lm_frame = wlan_mlo_add_t2lm_ie((uint8_t *)ie_buf,
7150 					  t2lm_neg,
7151 					  vdev);
7152 	if (!t2lm_frame) {
7153 		pe_debug("Failed to populate T2LM IE");
7154 		qdf_mem_free(ie_buf);
7155 		return QDF_STATUS_E_FAILURE;
7156 	}
7157 
7158 	frm.t2lm_ie[0].num_data = ie_buf->elem_len - 1;
7159 
7160 	pe_debug("Dump T2LM IE buff len %d", ie_buf->elem_len);
7161 	qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, ie_buf,
7162 			   ie_buf->elem_len +  sizeof(struct ie_header));
7163 
7164 	qdf_mem_copy(&frm.t2lm_ie[0].data, ie_buf->data,
7165 		     frm.t2lm_ie[0].num_data);
7166 
7167 	qdf_mem_free(ie_buf);
7168 
7169 	frm.Category.category = args->category;
7170 	frm.Action.action = args->action;
7171 	frm.DialogToken.token = args->arg1;
7172 	frm.num_t2lm_ie = 1;
7173 	frm.t2lm_ie[0].present = 1;
7174 
7175 	pe_debug("Sending a T2LM negotiation Request from " QDF_MAC_ADDR_FMT " to " QDF_MAC_ADDR_FMT,
7176 		 QDF_MAC_ADDR_REF(session->self_mac_addr),
7177 		 QDF_MAC_ADDR_REF(peer_mac));
7178 	pe_debug("Dialog token %d", frm.DialogToken.token);
7179 
7180 	status = dot11f_get_packed_t2lm_neg_reqSize(mac_ctx, &frm,
7181 						    &payload_size);
7182 	if (DOT11F_FAILED(status)) {
7183 		pe_err("Failed to calculate packed size for a T2LM negotiation Request (0x%08x).",
7184 		       status);
7185 		/* We'll fall back on the worst case scenario: */
7186 		payload_size = sizeof(tDot11ft2lm_neg_req);
7187 	} else if (DOT11F_WARNED(status)) {
7188 		pe_warn("There were warnings while calculating packed size for a T2LM negotiation Request (0x%08x).",
7189 			status);
7190 	}
7191 
7192 	num_bytes = payload_size + sizeof(*mgmt_hdr);
7193 	qdf_status = cds_packet_alloc(num_bytes, (void **)&frame_ptr,
7194 				      (void **)&pkt_ptr);
7195 	if (!QDF_IS_STATUS_SUCCESS(qdf_status) || (!pkt_ptr)) {
7196 		pe_err("Failed to allocate %d bytes for a T2LM req action frm",
7197 		       num_bytes);
7198 		return QDF_STATUS_E_FAILURE;
7199 	}
7200 	qdf_mem_zero(frame_ptr, num_bytes);
7201 
7202 	lim_populate_mac_header(mac_ctx, frame_ptr, SIR_MAC_MGMT_FRAME,
7203 				SIR_MAC_MGMT_ACTION, peer_mac,
7204 				session->self_mac_addr);
7205 
7206 	/* Update A3 with the BSSID */
7207 	mgmt_hdr = (tpSirMacMgmtHdr)frame_ptr;
7208 	sir_copy_mac_addr(mgmt_hdr->bssId, session->bssId);
7209 	lim_set_protected_bit(mac_ctx, session, peer_mac, mgmt_hdr);
7210 
7211 	status = dot11f_pack_t2lm_neg_req(mac_ctx, &frm,
7212 					  frame_ptr + sizeof(tSirMacMgmtHdr),
7213 					  payload_size, &payload_size);
7214 
7215 	if (DOT11F_FAILED(status)) {
7216 		pe_err("Failed to pack a T2LM negotiation request (0x%08x)",
7217 		       status);
7218 		qdf_status = QDF_STATUS_E_FAILURE;
7219 		goto error_t2lm_req;
7220 	} else if (DOT11F_WARNED(status)) {
7221 		pe_warn("There were warnings while packing T2LM req (0x%08x)",
7222 			status);
7223 	}
7224 
7225 	pe_debug("Dump T2LM TX req action frame");
7226 	qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, frame_ptr,
7227 			   num_bytes);
7228 
7229 	if (!wlan_reg_is_24ghz_ch_freq(session->curr_op_freq) ||
7230 	    session->opmode == QDF_P2P_CLIENT_MODE ||
7231 	    session->opmode == QDF_P2P_GO_MODE)
7232 		tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
7233 
7234 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
7235 			 session->peSessionId, mgmt_hdr->fc.subType));
7236 	qdf_status = wma_tx_frameWithTxComplete(
7237 			mac_ctx, pkt_ptr, (uint16_t)num_bytes,
7238 			 TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
7239 			 lim_tx_complete, frame_ptr,
7240 			 lim_mgmt_t2lm_req_tx_complete, tx_flag,
7241 			 vdev_id, 0, session->curr_op_freq,
7242 			 RATEID_DEFAULT, 0, 0);
7243 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
7244 			 session->peSessionId, qdf_status));
7245 	if (qdf_status != QDF_STATUS_SUCCESS) {
7246 		pe_err("wma_tx_frame FAILED! Status [%d]", qdf_status);
7247 		return QDF_STATUS_E_FAILURE;
7248 	} else {
7249 		return QDF_STATUS_SUCCESS;
7250 	}
7251 
7252 error_t2lm_req:
7253 	cds_packet_free((void *)pkt_ptr);
7254 	return qdf_status;
7255 }
7256 #endif
7257 
7258 /**
7259  * lim_delba_tx_complete_cnf() - Confirmation for Delba OTA
7260  * @context: pointer to global mac
7261  * @buf: netbuf of Del BA frame
7262  * @tx_complete: Sent status
7263  * @params: tx completion params
7264  *
7265  * Return: This returns QDF_STATUS
7266  */
7267 static QDF_STATUS lim_delba_tx_complete_cnf(void *context, qdf_nbuf_t buf,
7268 					    uint32_t tx_complete, void *params)
7269 {
7270 	struct mac_context *mac_ctx = (struct mac_context *)context;
7271 	tSirMacMgmtHdr *mac_hdr;
7272 	struct sDot11fdelba_req frm;
7273 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
7274 	uint32_t frame_len;
7275 	QDF_STATUS status;
7276 	uint8_t *data;
7277 	struct wmi_mgmt_params *mgmt_params = (struct wmi_mgmt_params *)params;
7278 
7279 	if (!mgmt_params || !mac_ctx || !buf || !soc) {
7280 		pe_err("delba tx cnf invalid parameters");
7281 		goto error;
7282 	}
7283 	data = qdf_nbuf_data(buf);
7284 	if (!data) {
7285 		pe_err("Delba frame is NULL");
7286 		goto error;
7287 	}
7288 
7289 	mac_hdr = (tSirMacMgmtHdr *)data;
7290 	qdf_mem_zero((void *)&frm, sizeof(struct sDot11fdelba_req));
7291 	frame_len = sizeof(frm);
7292 	status = dot11f_unpack_delba_req(mac_ctx, (uint8_t *)data +
7293 					 sizeof(*mac_hdr), frame_len,
7294 					 &frm, false);
7295 	if (DOT11F_FAILED(status)) {
7296 		pe_err("Failed to unpack and parse delba (0x%08x, %d bytes)",
7297 		       status, frame_len);
7298 		goto error;
7299 	}
7300 	pe_debug("delba ota done vdev %d "QDF_MAC_ADDR_FMT" tid %d desc_id %d status %d",
7301 		 mgmt_params->vdev_id,
7302 		 QDF_MAC_ADDR_REF(mac_hdr->da), frm.delba_param_set.tid,
7303 		 mgmt_params->desc_id, tx_complete);
7304 	cdp_delba_tx_completion(soc, mac_hdr->da, mgmt_params->vdev_id,
7305 				frm.delba_param_set.tid, tx_complete);
7306 
7307 error:
7308 	if (buf)
7309 		qdf_nbuf_free(buf);
7310 
7311 	return QDF_STATUS_SUCCESS;
7312 }
7313 
7314 QDF_STATUS lim_send_delba_action_frame(struct mac_context *mac_ctx,
7315 				       uint8_t vdev_id, uint8_t *peer_macaddr,
7316 				       uint8_t tid, uint8_t reason_code)
7317 {
7318 	struct pe_session *session;
7319 	struct sDot11fdelba_req frm;
7320 	QDF_STATUS qdf_status;
7321 	tpSirMacMgmtHdr mgmt_hdr;
7322 	uint32_t num_bytes, payload_size = 0;
7323 	uint32_t status;
7324 	void *pkt_ptr = NULL;
7325 	uint8_t *frame_ptr;
7326 	uint8_t tx_flag = 0;
7327 
7328 	session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
7329 	if (!session) {
7330 		pe_debug("delba invalid vdev id %d ", vdev_id);
7331 		return QDF_STATUS_E_INVAL;
7332 	}
7333 	pe_debug("send delba vdev %d "QDF_MAC_ADDR_FMT" tid %d reason %d", vdev_id,
7334 		 QDF_MAC_ADDR_REF(peer_macaddr), tid, reason_code);
7335 	qdf_mem_zero((uint8_t *)&frm, sizeof(frm));
7336 	frm.Category.category = ACTION_CATEGORY_BACK;
7337 	frm.Action.action = DELBA;
7338 	frm.delba_param_set.initiator = 0;
7339 	frm.delba_param_set.tid = tid;
7340 	frm.Reason.code = reason_code;
7341 
7342 	status = dot11f_get_packed_delba_req_size(mac_ctx, &frm, &payload_size);
7343 	if (DOT11F_FAILED(status)) {
7344 		pe_err("Failed to calculate the packed size for a DELBA(0x%08x).",
7345 		       status);
7346 		/* We'll fall back on the worst case scenario: */
7347 		payload_size = sizeof(struct sDot11fdelba_req);
7348 	} else if (DOT11F_WARNED(status)) {
7349 		pe_warn("Warnings in calculating the packed size for a DELBA (0x%08x).",
7350 			status);
7351 	}
7352 	num_bytes = payload_size + sizeof(*mgmt_hdr);
7353 	qdf_status = cds_packet_alloc(num_bytes, (void **)&frame_ptr,
7354 				      (void **)&pkt_ptr);
7355 	if (!QDF_IS_STATUS_SUCCESS(qdf_status) || !pkt_ptr) {
7356 		pe_err("Failed to allocate %d bytes for a DELBA",
7357 		       num_bytes);
7358 		return QDF_STATUS_E_FAILURE;
7359 	}
7360 	qdf_mem_zero(frame_ptr, num_bytes);
7361 
7362 	lim_populate_mac_header(mac_ctx, frame_ptr, SIR_MAC_MGMT_FRAME,
7363 				SIR_MAC_MGMT_ACTION, peer_macaddr,
7364 				session->self_mac_addr);
7365 
7366 	/* Update A3 with the BSSID */
7367 	mgmt_hdr = (tpSirMacMgmtHdr)frame_ptr;
7368 	sir_copy_mac_addr(mgmt_hdr->bssId, session->bssId);
7369 
7370 	/* DEL is a robust mgmt action frame,
7371 	 * set the "protect" (aka WEP) bit in the FC
7372 	 */
7373 	lim_set_protected_bit(mac_ctx, session, peer_macaddr, mgmt_hdr);
7374 
7375 	status = dot11f_pack_delba_req(mac_ctx, &frm,
7376 				       frame_ptr + sizeof(tSirMacMgmtHdr),
7377 				       payload_size, &payload_size);
7378 	if (DOT11F_FAILED(status)) {
7379 		pe_err("Failed to pack a DELBA (0x%08x)",
7380 		       status);
7381 		qdf_status = QDF_STATUS_E_FAILURE;
7382 		goto error_delba;
7383 	} else if (DOT11F_WARNED(status)) {
7384 		pe_warn("There were warnings while packing DELBA (0x%08x)",
7385 			status);
7386 	}
7387 	if (wlan_reg_is_5ghz_ch_freq(session->curr_op_freq) ||
7388 	    wlan_reg_is_6ghz_chan_freq(session->curr_op_freq) ||
7389 	    session->opmode == QDF_P2P_CLIENT_MODE ||
7390 	    session->opmode == QDF_P2P_GO_MODE)
7391 		tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
7392 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
7393 			 session->peSessionId, mgmt_hdr->fc.subType));
7394 	qdf_status = wma_tx_frameWithTxComplete(mac_ctx, pkt_ptr,
7395 						(uint16_t)num_bytes,
7396 						TXRX_FRM_802_11_MGMT,
7397 						ANI_TXDIR_TODS, 7,
7398 						NULL, frame_ptr,
7399 						lim_delba_tx_complete_cnf,
7400 						tx_flag, vdev_id,
7401 						false, 0, RATEID_DEFAULT, 0, 0);
7402 	if (qdf_status != QDF_STATUS_SUCCESS) {
7403 		pe_err("delba wma_tx_frame FAILED! Status [%d]", qdf_status);
7404 		return qdf_status;
7405 	} else {
7406 		return QDF_STATUS_SUCCESS;
7407 	}
7408 
7409 error_delba:
7410 	if (pkt_ptr)
7411 		cds_packet_free((void *)pkt_ptr);
7412 
7413 	return qdf_status;
7414 }
7415 
7416 #define MAC_AUTH_FRAME_STATUS_CODE_OFFSET 4
7417 
7418 /**
7419  * lim_tx_mgmt_frame() - Transmits Auth mgmt frame
7420  * @mac_ctx Pointer to Global MAC structure
7421  * @vdev_id: vdev id
7422  * @msg_len: Received message length
7423  * @packet: Packet to be transmitted
7424  * @frame: Received frame
7425  *
7426  * Return: None
7427  */
7428 static void lim_tx_mgmt_frame(struct mac_context *mac_ctx, uint8_t vdev_id,
7429 			      uint32_t msg_len, void *packet, uint8_t *frame)
7430 {
7431 	tpSirMacFrameCtl fc = (tpSirMacFrameCtl)frame;
7432 	QDF_STATUS qdf_status;
7433 	struct pe_session *session = NULL;
7434 	uint16_t auth_ack_status;
7435 	enum rateid min_rid = RATEID_DEFAULT;
7436 	enum QDF_OPMODE opmode;
7437 	uint16_t session_id;
7438 	qdf_freq_t channel_freq = 0;
7439 	qdf_freq_t *pre_auth_freq = NULL;
7440 
7441 	opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, vdev_id);
7442 	if (opmode != QDF_NAN_DISC_MODE) {
7443 		session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
7444 		if (!session) {
7445 			cds_packet_free((void *)packet);
7446 			pe_err("session not found for given vdev_id %d",
7447 			       vdev_id);
7448 			return;
7449 		}
7450 		session_id = session->peSessionId;
7451 	} else {
7452 		session_id = vdev_id;
7453 	}
7454 
7455 	qdf_mtrace(QDF_MODULE_ID_PE, QDF_MODULE_ID_WMA, TRACE_CODE_TX_MGMT,
7456 		   session_id, 0);
7457 
7458 	if (opmode != QDF_NAN_DISC_MODE) {
7459 		if (fc->subType == SIR_MAC_MGMT_AUTH) {
7460 			tpSirFTPreAuthReq pre_auth_req;
7461 			uint16_t auth_algo = *(uint16_t *)(frame +
7462 						sizeof(tSirMacMgmtHdr));
7463 
7464 			if (auth_algo == eSIR_AUTH_TYPE_SAE) {
7465 				if (session->ftPEContext.pFTPreAuthReq) {
7466 					pre_auth_req =
7467 					     session->ftPEContext.pFTPreAuthReq;
7468 					channel_freq =
7469 					    pre_auth_req->pre_auth_channel_freq;
7470 				}
7471 				pre_auth_freq = &channel_freq;
7472 			}
7473 			pe_debug("TX SAE pre-auth frame on freq %d",
7474 				 channel_freq);
7475 		}
7476 		min_rid = lim_get_min_session_txrate(session, pre_auth_freq);
7477 	}
7478 
7479 	qdf_status = wma_tx_frameWithTxComplete(mac_ctx, packet,
7480 					 (uint16_t)msg_len,
7481 					 TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS,
7482 					 7, lim_tx_complete, frame,
7483 					 lim_auth_tx_complete_cnf,
7484 					 0, vdev_id, false, channel_freq,
7485 					 min_rid, 0, 0);
7486 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
7487 		session_id, qdf_status));
7488 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7489 		pe_err("*** Could not send Auth frame (subType: %d), retCode=%X ***",
7490 			fc->subType, qdf_status);
7491 		mac_ctx->auth_ack_status = LIM_TX_FAILED;
7492 		auth_ack_status = SENT_FAIL;
7493 		lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_AUTH_ACK_EVENT,
7494 				session, auth_ack_status, QDF_STATUS_E_FAILURE);
7495 		/* Pkt will be freed up by the callback */
7496 	}
7497 }
7498 
7499 static void
7500 lim_handle_sae_auth_retry(struct mac_context *mac_ctx, uint8_t vdev_id,
7501 			  uint8_t *frame, uint32_t frame_len)
7502 {
7503 	struct pe_session *session;
7504 	struct sae_auth_retry *sae_retry;
7505 	uint8_t retry_count = 0;
7506 	uint32_t val = 0;
7507 
7508 	session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
7509 	if (!session) {
7510 		pe_err("session not found for given vdev_id %d",
7511 		       vdev_id);
7512 		return;
7513 	}
7514 	if ((session->opmode != QDF_STA_MODE) &&
7515 	    (session->opmode != QDF_P2P_CLIENT_MODE))
7516 		return;
7517 
7518 	if (session->limMlmState == eLIM_MLM_WT_SAE_AUTH_STATE)
7519 		wlan_mlme_get_sae_auth_retry_count(mac_ctx->psoc, &retry_count);
7520 	else
7521 		wlan_mlme_get_sae_roam_auth_retry_count(mac_ctx->psoc,
7522 							&retry_count);
7523 	if (!retry_count) {
7524 		pe_debug("vdev %d: SAE Auth retry disabled", vdev_id);
7525 		return;
7526 	}
7527 
7528 	sae_retry = mlme_get_sae_auth_retry(session->vdev);
7529 	if (!sae_retry) {
7530 		pe_err("sae retry pointer is NULL for vdev_id %d",
7531 		       vdev_id);
7532 		return;
7533 	}
7534 
7535 	if (sae_retry->sae_auth.ptr)
7536 		lim_sae_auth_cleanup_retry(mac_ctx, vdev_id);
7537 
7538 	sae_retry->sae_auth.ptr = qdf_mem_malloc(frame_len);
7539 	if (!sae_retry->sae_auth.ptr)
7540 		return;
7541 
7542 	pe_debug("SAE auth frame queued vdev_id %d seq_num %d",
7543 		 vdev_id, mac_ctx->mgmtSeqNum + 1);
7544 	qdf_mem_copy(sae_retry->sae_auth.ptr, frame, frame_len);
7545 	mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer.sessionId =
7546 					session->peSessionId;
7547 	sae_retry->sae_auth.len = frame_len;
7548 	sae_retry->sae_auth_max_retry = retry_count;
7549 
7550 	val = mac_ctx->mlme_cfg->timeouts.sae_auth_failure_timeout;
7551 
7552 	tx_timer_change(
7553 		&mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer,
7554 		SYS_MS_TO_TICKS(val), 0);
7555 	/* Activate Auth Retry timer */
7556 	if (tx_timer_activate(
7557 	    &mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer) !=
7558 	    TX_SUCCESS) {
7559 		pe_err("failed to start periodic auth retry timer");
7560 		lim_sae_auth_cleanup_retry(mac_ctx, vdev_id);
7561 	}
7562 }
7563 
7564 #ifdef WLAN_FEATURE_11BE_MLO
7565 static QDF_STATUS lim_update_mld_to_link_address(struct mac_context *mac_ctx,
7566 						 struct wlan_objmgr_vdev *vdev,
7567 						 tpSirMacMgmtHdr mac_hdr)
7568 {
7569 	struct qdf_mac_addr *self_link_addr;
7570 	struct tLimPreAuthNode *pre_auth_node;
7571 	struct qdf_mac_addr peer_link_addr;
7572 	struct wlan_objmgr_peer *bss_peer = NULL;
7573 	struct qdf_mac_addr *peer_roaming_link_addr;
7574 	enum QDF_OPMODE opmode;
7575 	uint8_t *peer_mld_addr = NULL;
7576 	QDF_STATUS status;
7577 
7578 	if (!wlan_cm_is_sae_auth_addr_conversion_required(vdev))
7579 		return QDF_STATUS_SUCCESS;
7580 
7581 	opmode = wlan_vdev_mlme_get_opmode(vdev);
7582 	self_link_addr = (struct qdf_mac_addr *)
7583 				wlan_vdev_mlme_get_linkaddr(vdev);
7584 
7585 	switch (opmode) {
7586 	case QDF_SAP_MODE:
7587 		pre_auth_node =
7588 			lim_search_pre_auth_list_by_mld_addr(mac_ctx,
7589 							     mac_hdr->da);
7590 		if (!pre_auth_node) {
7591 			/**
7592 			 * Using MLD address, if pre_auth_node is not present then
7593 			 * check for peer mac address due to legacy connection.
7594 			 */
7595 			pre_auth_node = lim_search_pre_auth_list(mac_ctx,
7596 								 mac_hdr->da);
7597 			if (!pre_auth_node) {
7598 				pe_err("pre_auth not found by MLD: "QDF_MAC_ADDR_FMT,
7599 				       QDF_MAC_ADDR_REF(mac_hdr->da));
7600 				return QDF_STATUS_E_INVAL;
7601 			} else {
7602 				return QDF_STATUS_SUCCESS;
7603 			}
7604 		}
7605 
7606 		qdf_mem_copy(mac_hdr->da, pre_auth_node->peerMacAddr,
7607 			     QDF_MAC_ADDR_SIZE);
7608 		qdf_mem_copy(mac_hdr->bssId, self_link_addr->bytes,
7609 			     QDF_MAC_ADDR_SIZE);
7610 		break;
7611 	case QDF_STA_MODE:
7612 		if (!wlan_cm_is_vdev_roaming(vdev)) {
7613 			status = wlan_vdev_get_bss_peer_mac(vdev,
7614 							    &peer_link_addr);
7615 			if (QDF_IS_STATUS_ERROR(status))
7616 				return status;
7617 			bss_peer = wlan_objmgr_vdev_try_get_bsspeer(
7618 						vdev, WLAN_MLME_OBJMGR_ID);
7619 			if (bss_peer) {
7620 				peer_mld_addr =
7621 					wlan_peer_mlme_get_mldaddr(bss_peer);
7622 				wlan_objmgr_peer_release_ref(
7623 						bss_peer, WLAN_MLME_OBJMGR_ID);
7624 			}
7625 		} else {
7626 			peer_roaming_link_addr =
7627 				wlan_cm_roaming_get_peer_link_addr(vdev);
7628 			if (!peer_roaming_link_addr)
7629 				return QDF_STATUS_E_FAILURE;
7630 			peer_link_addr = *peer_roaming_link_addr;
7631 			peer_mld_addr = (uint8_t *)
7632 					wlan_cm_roaming_get_peer_mld_addr(vdev);
7633 		}
7634 		if (!peer_mld_addr)
7635 			return QDF_STATUS_SUCCESS;
7636 
7637 		pe_debug("dest address"QDF_MAC_ADDR_FMT"mld addr"QDF_MAC_ADDR_FMT,
7638 			 QDF_MAC_ADDR_REF(mac_hdr->da),
7639 			 QDF_MAC_ADDR_REF(peer_mld_addr));
7640 		if (!qdf_mem_cmp(mac_hdr->da, peer_mld_addr, QDF_MAC_ADDR_SIZE))
7641 			qdf_mem_copy(mac_hdr->da, peer_link_addr.bytes,
7642 				     QDF_MAC_ADDR_SIZE);
7643 
7644 		qdf_mem_copy(mac_hdr->bssId, peer_link_addr.bytes,
7645 			     QDF_MAC_ADDR_SIZE);
7646 		break;
7647 	default:
7648 		return QDF_STATUS_SUCCESS;
7649 	}
7650 
7651 	qdf_mem_copy(mac_hdr->sa, self_link_addr->bytes, QDF_MAC_ADDR_SIZE);
7652 
7653 	return QDF_STATUS_SUCCESS;
7654 }
7655 #else
7656 static QDF_STATUS lim_update_mld_to_link_address(struct mac_context *mac_ctx,
7657 						 struct wlan_objmgr_vdev *vdev,
7658 						 tpSirMacMgmtHdr mac_hdr)
7659 {
7660 	return QDF_STATUS_SUCCESS;
7661 }
7662 #endif
7663 
7664 void lim_send_frame(struct mac_context *mac_ctx, uint8_t vdev_id, uint8_t *buf,
7665 		    uint16_t buf_len)
7666 {
7667 	QDF_STATUS qdf_status;
7668 	uint8_t *frame;
7669 	void *packet;
7670 	tpSirMacFrameCtl fc = (tpSirMacFrameCtl)buf;
7671 	tpSirMacMgmtHdr mac_hdr = (tpSirMacMgmtHdr)buf;
7672 	struct wlan_objmgr_vdev *vdev;
7673 	QDF_STATUS status;
7674 
7675 	pe_debug("sending fc->type: %d fc->subType: %d", fc->type, fc->subType);
7676 
7677 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, vdev_id,
7678 						    WLAN_LEGACY_MAC_ID);
7679 	if (!vdev)
7680 		return;
7681 
7682 	/* Case:
7683 	 * 1. In case of SAP, userspace will send MLD addresses in 2nd and 4th
7684 	 *    SAE auth frames. Driver needs to convert it into link address.
7685 	 * 2. In case of STA, userspace will send MLD addresses in 1st and 3rd
7686 	 *    SAE auth frames. Driver needs to convert it into link address.
7687 	 */
7688 	status = lim_update_mld_to_link_address(mac_ctx, vdev, mac_hdr);
7689 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
7690 
7691 	if (QDF_IS_STATUS_ERROR(status)) {
7692 		pe_err("SAE address conversion failure with status:%d", status);
7693 		return;
7694 	}
7695 
7696 	lim_add_mgmt_seq_num(mac_ctx, mac_hdr);
7697 	qdf_status = cds_packet_alloc(buf_len, (void **)&frame,
7698 				      (void **)&packet);
7699 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7700 		pe_err("call to bufAlloc failed for AUTH frame");
7701 		return;
7702 	}
7703 
7704 	qdf_mem_copy(frame, buf, buf_len);
7705 	lim_tx_mgmt_frame(mac_ctx, vdev_id, buf_len, packet, frame);
7706 }
7707 
7708 void lim_send_mgmt_frame_tx(struct mac_context *mac_ctx,
7709 			    struct scheduler_msg *msg)
7710 {
7711 	struct sir_mgmt_msg *mb_msg = (struct sir_mgmt_msg *)msg->bodyptr;
7712 	uint32_t msg_len;
7713 	tpSirMacFrameCtl fc = (tpSirMacFrameCtl)mb_msg->data;
7714 	uint8_t vdev_id;
7715 	uint16_t auth_algo;
7716 
7717 	msg_len = mb_msg->msg_len - sizeof(*mb_msg);
7718 	vdev_id = mb_msg->vdev_id;
7719 
7720 	if (fc->subType == SIR_MAC_MGMT_AUTH) {
7721 		auth_algo = *(uint16_t *)(mb_msg->data +
7722 					sizeof(tSirMacMgmtHdr));
7723 		if (auth_algo == eSIR_AUTH_TYPE_SAE)
7724 			lim_handle_sae_auth_retry(mac_ctx, vdev_id,
7725 						  mb_msg->data, msg_len);
7726 		if (auth_algo == eSIR_FT_AUTH) {
7727 			struct tLimPreAuthNode *sta_pre_auth_ctx;
7728 
7729 			sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx,
7730 				((tpSirMacMgmtHdr)(mb_msg->data))->da);
7731 			pe_debug("FT Auth TX to " QDF_MAC_ADDR_FMT,
7732 				 QDF_MAC_ADDR_REF(((tpSirMacMgmtHdr)(mb_msg->data))->da));
7733 			if (sta_pre_auth_ctx) {
7734 				pe_debug("STA is AUTHENTICATED_STATE");
7735 				sta_pre_auth_ctx->mlmState =
7736 					eLIM_MLM_AUTHENTICATED_STATE;
7737 			}
7738 		}
7739 	}
7740 	mac_ctx->auth_ack_status = LIM_ACK_NOT_RCD;
7741 	lim_send_frame(mac_ctx, vdev_id, mb_msg->data, msg_len);
7742 }
7743