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