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