xref: /wlan-dirver/qcacld-3.0/core/mac/src/pe/lim/lim_process_tdls.c (revision 019b2fff7f27950fdf4acf3ed3d33ab750d67ede)
1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*===========================================================================
21  * lim_process_tdls.c
22  * OVERVIEW:
23  *
24  * DEPENDENCIES:
25  *
26  * Are listed for each API below.
27  * ===========================================================================*/
28 
29 /*===========================================================================
30 
31  *                      EDIT HISTORY FOR FILE
32 
33  *  This section contains comments describing changes made to the module.
34  *  Notice that changes are listed in reverse chronological order.
35 
36  *  $Header$$DateTime$$Author$
37 
38  *  when        who     what, where, why
39  *  ----------    ---    ------------------------------------------------------
40  *  05/05/2010   Ashwani    Initial Creation, added TDLS action frame
41  *  functionality,TDLS message exchange with SME..etc..
42 
43    ===========================================================================*/
44 
45 /**
46  * \file lim_process_tdls.c
47  *
48  * \brief Code for preparing,processing and sending 802.11z action frames
49  *
50  */
51 
52 #ifdef FEATURE_WLAN_TDLS
53 
54 #include "sir_api.h"
55 #include "ani_global.h"
56 #include "sir_mac_prot_def.h"
57 #include "utils_api.h"
58 #include "lim_types.h"
59 #include "lim_utils.h"
60 #include "lim_security_utils.h"
61 #include "dot11f.h"
62 #include "sch_api.h"
63 #include "lim_send_messages.h"
64 #include "utils_parser.h"
65 #include "lim_assoc_utils.h"
66 #include "lim_prop_exts_utils.h"
67 #include "dph_hash_table.h"
68 #include "wma_types.h"
69 #include "cds_regdomain.h"
70 #include "cds_utils.h"
71 #include "wlan_mlo_mgr_sta.h"
72 #include "wlan_reg_services_api.h"
73 #include "wlan_tdls_tgt_api.h"
74 #include "wlan_mlme_public_struct.h"
75 #include "wlan_mlme_api.h"
76 #include "wlan_tdls_public_structs.h"
77 #include "wlan_cfg80211_tdls.h"
78 #include "wlan_tdls_api.h"
79 #include "lim_mlo.h"
80 
81 /* define NO_PAD_TDLS_MIN_8023_SIZE to NOT padding: See CR#447630
82    There was IOT issue with cisco 1252 open mode, where it pads
83    discovery req/teardown frame with some junk value up to min size.
84    To avoid this issue, we pad QCOM_VENDOR_IE.
85    If there is other IOT issue because of this bandage, define NO_PAD...
86  */
87 #ifndef NO_PAD_TDLS_MIN_8023_SIZE
88 #define MIN_IEEE_8023_SIZE              46
89 #define MIN_VENDOR_SPECIFIC_IE_SIZE     5
90 #endif
91 
92 /*
93  * TDLS data frames will go out/come in as non-qos data.
94  * so, eth_890d_header will be aligned access..
95  */
96 static const uint8_t eth_890d_header[] = {
97 	0xaa, 0xaa, 0x03, 0x00,
98 	0x00, 0x00, 0x89, 0x0d,
99 };
100 
101 #define ETH_ADDR_LEN 6 /* bytes */
102 
103 struct tdls_ethernet_hdr {
104 	uint8_t dest_addr[ETH_ADDR_LEN];
105 	uint8_t src_addr[ETH_ADDR_LEN];
106 } qdf_packed;
107 
108 #define eth_890d_hdr_len 2 /* bytes */
109 
110 static const uint8_t eth_890d_tdls_discvory_frm_hdr[] = {
111 	0x89, 0x0d, 0x02, 0x0c, 0x0a,
112 };
113 
114 #define TDLS_ETHR_HDR_LEN (sizeof(struct tdls_ethernet_hdr))
115 
116 /*
117  * type of links used in TDLS
118  */
119 enum tdlsLinks {
120 	TDLS_LINK_AP,
121 	TDLS_LINK_DIRECT
122 } e_tdls_link;
123 
124 enum tdlsReqType {
125 	TDLS_INITIATOR,
126 	TDLS_RESPONDER
127 } e_tdls_req_type;
128 
129 typedef enum tdlsLinkSetupStatus {
130 	TDLS_SETUP_STATUS_SUCCESS = 0,
131 	TDLS_SETUP_STATUS_FAILURE = 37
132 } etdlsLinkSetupStatus;
133 
134 /* These maps to Kernel TDLS peer capability
135  * flags and should get changed as and when necessary
136  */
137 enum tdls_peer_capability {
138 	TDLS_PEER_HT_CAP = 0,
139 	TDLS_PEER_VHT_CAP = 1,
140 	TDLS_PEER_WMM_CAP = 2,
141 	TDLS_PEER_HE_CAP = 3
142 } e_tdls_peer_capability;
143 
144 #define LINK_IDEN_ADDR_OFFSET(x) (&(x)->LinkIdentifier)
145 
146 /* TODO, Move this parameters to configuration */
147 #define PEER_PSM_SUPPORT          (0)
148 #define TDLS_SUPPORT              (1)
149 #define TDLS_PROHIBITED           (0)
150 #define TDLS_CH_SWITCH_PROHIBITED (1)
151 /** @brief Set bit manipulation macro */
152 #define SET_BIT(value, mask)       ((value) |= (1 << (mask)))
153 /** @brief Clear bit manipulation macro */
154 #define CLEAR_BIT(value, mask)     ((value) &= ~(1 << (mask)))
155 /** @brief Check bit manipulation macro */
156 #define CHECK_BIT(value, mask)    ((value) & (1 << (mask)))
157 
158 #define SET_PEER_AID_BITMAP(peer_bitmap, aid) \
159 	do { \
160 	if ((aid) < (sizeof(uint32_t) << 3)) \
161 		SET_BIT(peer_bitmap[0], (aid));	\
162 	else if ((aid) < (sizeof(uint32_t) << 4)) \
163 		SET_BIT(peer_bitmap[1], ((aid) - (sizeof(uint32_t) << 3)));\
164 	} while (0);
165 
166 #define CLEAR_PEER_AID_BITMAP(peer_bitmap, aid)	\
167 	do { \
168 	if ((aid) < (sizeof(uint32_t) << 3)) \
169 		CLEAR_BIT(peer_bitmap[0], (aid)); \
170 	else if ((aid) < (sizeof(uint32_t) << 4)) \
171 		CLEAR_BIT(peer_bitmap[1], ((aid) - (sizeof(uint32_t) << 3)));\
172 	} while (0);
173 
174 #define IS_QOS_ENABLED(pe_session) ((((pe_session)->limQosEnabled) && \
175 					SIR_MAC_GET_QOS((pe_session)->limCurrentBssCaps)) ||	\
176 				       (((pe_session)->limWmeEnabled) && \
177 					LIM_BSS_CAPS_GET(WME, (pe_session)->limCurrentBssQosCaps)))
178 
179 #define TID_AC_VI                  4
180 #define TID_AC_BK                  1
181 
182 static const uint8_t *lim_trace_tdls_action_string(uint8_t tdlsActionCode)
183 {
184 	switch (tdlsActionCode) {
185 		CASE_RETURN_STRING(TDLS_SETUP_REQUEST);
186 		CASE_RETURN_STRING(TDLS_SETUP_RESPONSE);
187 		CASE_RETURN_STRING(TDLS_SETUP_CONFIRM);
188 		CASE_RETURN_STRING(TDLS_TEARDOWN);
189 		CASE_RETURN_STRING(TDLS_PEER_TRAFFIC_INDICATION);
190 		CASE_RETURN_STRING(TDLS_CHANNEL_SWITCH_REQUEST);
191 		CASE_RETURN_STRING(TDLS_CHANNEL_SWITCH_RESPONSE);
192 		CASE_RETURN_STRING(TDLS_PEER_TRAFFIC_RESPONSE);
193 		CASE_RETURN_STRING(TDLS_DISCOVERY_REQUEST);
194 		CASE_RETURN_STRING(TDLS_DISCOVERY_RESPONSE);
195 	}
196 	return (const uint8_t *)"UNKNOWN";
197 }
198 
199 /*
200  * initialize TDLS setup list and related data structures.
201  */
202 void lim_init_tdls_data(struct mac_context *mac, struct pe_session *pe_session)
203 {
204 	lim_init_peer_idxpool(mac, pe_session);
205 
206 	return;
207 }
208 
209 static bool
210 is_duplicate_chan(uint8_t *arr, uint8_t index, uint8_t ch_id)
211 {
212 	int i;
213 
214 	for (i = 0; i < index; i++) {
215 		if (arr[i] == ch_id)
216 			return true;
217 	}
218 	return false;
219 }
220 
221 static void populate_dot11f_tdls_offchannel_params(
222 				struct mac_context *mac,
223 				struct pe_session *pe_session,
224 				tDot11fIESuppChannels *suppChannels,
225 				tDot11fIESuppOperatingClasses *suppOperClasses)
226 {
227 	uint32_t numChans = CFG_VALID_CHANNEL_LIST_LEN;
228 	uint8_t validChan[CFG_VALID_CHANNEL_LIST_LEN];
229 	uint8_t i, count_opclss = 1;
230 	uint8_t valid_count = 0;
231 	uint8_t chanOffset;
232 	uint8_t op_class;
233 	uint8_t numClasses;
234 	uint8_t classes[REG_MAX_SUPP_OPER_CLASSES];
235 	uint32_t band;
236 	uint8_t nss_2g;
237 	uint8_t nss_5g;
238 	qdf_freq_t ch_freq;
239 	bool is_vlp_country;
240 	uint8_t ap_cc[REG_ALPHA2_LEN + 1];
241 	uint8_t reg_cc[REG_ALPHA2_LEN + 1];
242 
243 	numChans = mac->mlme_cfg->reg.valid_channel_list_num;
244 
245 	if (wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq))
246 		band = BAND_2G;
247 	else
248 		band = BAND_5G;
249 
250 	nss_5g = QDF_MIN(mac->vdev_type_nss_5g.tdls,
251 			 mac->user_configured_nss);
252 	nss_2g = QDF_MIN(mac->vdev_type_nss_2g.tdls,
253 			 mac->user_configured_nss);
254 
255 	wlan_cm_get_country_code(mac->pdev, pe_session->vdev_id, ap_cc);
256 	wlan_reg_read_current_country(mac->psoc, reg_cc);
257 	is_vlp_country = wlan_reg_ctry_support_vlp(ap_cc) &&
258 			 wlan_reg_ctry_support_vlp(reg_cc);
259 
260 	/* validating the channel list for DFS and 2G channels */
261 	for (i = 0; i < numChans; i++) {
262 		ch_freq = mac->mlme_cfg->reg.valid_channel_freq_list[i];
263 
264 		validChan[i] = wlan_reg_freq_to_chan(mac->pdev,
265 						     mac->mlme_cfg->reg.valid_channel_freq_list[i]);
266 
267 		if (is_duplicate_chan(validChan, i, validChan[i]))
268 			continue;
269 
270 		if ((band == BAND_5G) &&
271 		    (NSS_2x2_MODE == nss_5g) &&
272 		    (NSS_1x1_MODE == nss_2g) &&
273 		    (wlan_reg_is_dfs_for_freq(mac->pdev, ch_freq))) {
274 			pe_debug("skipping channel: %d, nss_5g: %d, nss_2g: %d",
275 				validChan[i], nss_5g, nss_2g);
276 			continue;
277 		} else {
278 			if (wlan_reg_is_dsrc_freq(ch_freq)) {
279 				pe_debug("skipping freq: %d from the valid freq list",
280 					 ch_freq);
281 				continue;
282 			}
283 		}
284 
285 		if (wlan_reg_is_6ghz_chan_freq(ch_freq) &&
286 		    !(is_vlp_country &&
287 		      wlan_reg_is_6ghz_psc_chan_freq(ch_freq))) {
288 			pe_debug("skipping is_vlp_country %d or non-psc channel %d",
289 				 is_vlp_country, ch_freq);
290 			continue;
291 		}
292 
293 		if (valid_count >= ARRAY_SIZE(suppChannels->bands))
294 			break;
295 
296 		suppChannels->bands[valid_count][0] = validChan[i];
297 		suppChannels->bands[valid_count][1] = 1;
298 		valid_count++;
299 	}
300 
301 	suppChannels->num_bands = valid_count;
302 	suppChannels->present = 1;
303 
304 	/* find channel offset and get op class for current operating channel */
305 	switch (pe_session->htSecondaryChannelOffset) {
306 	case PHY_SINGLE_CHANNEL_CENTERED:
307 		chanOffset = BW20;
308 		break;
309 
310 	case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
311 		chanOffset = BW40_LOW_PRIMARY;
312 		break;
313 
314 	case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
315 		chanOffset = BW40_HIGH_PRIMARY;
316 		break;
317 
318 	default:
319 		chanOffset = BWALL;
320 		break;
321 	}
322 
323 	op_class = wlan_reg_dmn_get_opclass_from_channel(
324 		reg_cc,
325 		wlan_reg_freq_to_chan(mac->pdev, pe_session->curr_op_freq),
326 		chanOffset);
327 
328 	suppOperClasses->present = 1;
329 	suppOperClasses->classes[0] = op_class;
330 
331 	wlan_reg_dmn_get_curr_opclasses(&numClasses, &classes[0]);
332 
333 	for (i = 0; i < numClasses; i++) {
334 		if (wlan_reg_is_6ghz_op_class(mac->pdev, classes[i]) &&
335 		    !is_vlp_country)
336 			continue;
337 
338 		suppOperClasses->classes[count_opclss] = classes[i];
339 		count_opclss++;
340 	}
341 
342 	pe_debug("countryCodeCurrent: %s, curr_op_freq: %d, htSecondaryChannelOffset: %d, chanOffset: %d op class: %d num_supportd_chan %d total opclasses %d num_supportd_opclass %d",
343 		 reg_cc,
344 		 pe_session->curr_op_freq,
345 		 pe_session->htSecondaryChannelOffset,
346 		 chanOffset, op_class, valid_count, numClasses,
347 		 count_opclss);
348 
349 	/* add one for present operating class, added in the beginning */
350 	suppOperClasses->num_classes = count_opclss;
351 
352 	return;
353 }
354 
355 #ifdef WLAN_FEATURE_11BE_MLO
356 /**
357  * lim_tdls_copy_self_mac() - copy mac address
358  * @session: pe session
359  * @init_sta_addr: the pointer to save the address
360  *
361  * For MLD device, it needs to copy mld mac address.
362  *
363  * Return: void
364  */
365 static void lim_tdls_copy_self_mac(struct pe_session *session,
366 				   uint8_t *init_sta_addr)
367 {
368 	struct wlan_mlo_dev_context *mlo_dev_ctx;
369 
370 	if (wlan_vdev_mlme_is_mlo_vdev(session->vdev)) {
371 		mlo_dev_ctx = session->vdev->mlo_dev_ctx;
372 		if (!mlo_dev_ctx) {
373 			pe_debug("mlo_dev_ctx is NULL");
374 			return;
375 		}
376 
377 		qdf_mem_copy((uint8_t *)init_sta_addr,
378 			     mlo_dev_ctx->mld_addr.bytes, QDF_MAC_ADDR_SIZE);
379 	} else {
380 		qdf_mem_copy((uint8_t *)init_sta_addr,
381 			     session->self_mac_addr, QDF_MAC_ADDR_SIZE);
382 	}
383 }
384 #else
385 static void lim_tdls_copy_self_mac(struct pe_session *session,
386 				   uint8_t *init_sta_addr)
387 {
388 	qdf_mem_copy((uint8_t *)init_sta_addr,
389 		     session->self_mac_addr, QDF_MAC_ADDR_SIZE);
390 }
391 #endif
392 
393 /*
394  * FUNCTION: Populate Link Identifier element IE
395  *
396  */
397 
398 static void populate_dot11f_link_iden(struct mac_context *mac,
399 				      struct pe_session *pe_session,
400 				      tDot11fIELinkIdentifier *linkIden,
401 				      struct qdf_mac_addr peer_mac,
402 				      uint8_t reqType)
403 {
404 	uint8_t *initaddr = NULL;
405 	uint8_t *respaddr = NULL;
406 
407 	(reqType == TDLS_INITIATOR) ? ((initaddr = linkIden->InitStaAddr),
408 				       (respaddr = linkIden->RespStaAddr))
409 	: ((respaddr = linkIden->InitStaAddr),
410 	   (initaddr = linkIden->RespStaAddr));
411 	qdf_mem_copy((uint8_t *)linkIden->bssid,
412 		     (uint8_t *)pe_session->bssId, QDF_MAC_ADDR_SIZE);
413 
414 	lim_tdls_copy_self_mac(pe_session, initaddr);
415 
416 	qdf_mem_copy((uint8_t *)respaddr, (uint8_t *)peer_mac.bytes,
417 		     QDF_MAC_ADDR_SIZE);
418 
419 	linkIden->present = 1;
420 	return;
421 
422 }
423 
424 static void populate_dot11f_tdls_ext_capability(struct mac_context *mac,
425 						struct pe_session *pe_session,
426 						tDot11fIEExtCap *extCapability)
427 {
428 	struct s_ext_cap *p_ext_cap = (struct s_ext_cap *)extCapability->bytes;
429 
430 	p_ext_cap->tdls_peer_psm_supp = PEER_PSM_SUPPORT;
431 	p_ext_cap->tdls_peer_uapsd_buffer_sta = mac->lim.gLimTDLSBufStaEnabled;
432 
433 	/*
434 	 * Set TDLS channel switching bits only if offchannel is enabled
435 	 * and TDLS Channel Switching is not prohibited by AP in ExtCap
436 	 * IE in assoc/re-assoc response.
437 	 */
438 	if ((1 == mac->lim.gLimTDLSOffChannelEnabled) &&
439 	    (!mlme_get_tdls_chan_switch_prohibited(pe_session->vdev))) {
440 		p_ext_cap->tdls_channel_switching = 1;
441 		p_ext_cap->tdls_chan_swit_prohibited = 0;
442 	} else {
443 	    p_ext_cap->tdls_channel_switching = 0;
444 	    p_ext_cap->tdls_chan_swit_prohibited = TDLS_CH_SWITCH_PROHIBITED;
445 	}
446 	p_ext_cap->tdls_support = TDLS_SUPPORT;
447 	p_ext_cap->tdls_prohibited = TDLS_PROHIBITED;
448 	/*
449 	 * For supporting wider bandwidth set tdls_wider_bw set as 1
450 	 */
451 	if (wlan_cfg80211_tdls_is_fw_wideband_capable(pe_session->vdev) &&
452 	    (mac->lim.gLimTDLSOffChannelEnabled ||
453 	     !wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq)))
454 		p_ext_cap->tdls_wider_bw = 1;
455 
456 	extCapability->present = 1;
457 	extCapability->num_bytes = lim_compute_ext_cap_ie_length(extCapability);
458 
459 	return;
460 }
461 
462 /*
463  * prepare TDLS frame header, it includes
464  * |             |              |                |
465  * |802.11 header|RFC1042 header|TDLS_PYLOAD_TYPE|PAYLOAD
466  * |             |              |                |
467  */
468 static uint32_t lim_prepare_tdls_frame_header(struct mac_context *mac, uint8_t *pFrame,
469 					      tDot11fIELinkIdentifier *link_iden,
470 					      uint8_t tdlsLinkType, uint8_t reqType,
471 					      uint8_t tid,
472 					      struct pe_session *pe_session)
473 {
474 	tpSirMacDataHdr3a pMacHdr;
475 	uint32_t header_offset = 0;
476 	uint8_t *addr1 = NULL;
477 	uint8_t *addr3 = NULL;
478 	uint8_t toDs = (tdlsLinkType == TDLS_LINK_AP)
479 		       ? ANI_TXDIR_TODS : ANI_TXDIR_IBSS;
480 	uint8_t *peerMac = (reqType == TDLS_INITIATOR)
481 			   ? link_iden->RespStaAddr : link_iden->InitStaAddr;
482 	uint8_t *staMac = (reqType == TDLS_INITIATOR)
483 			  ? link_iden->InitStaAddr : link_iden->RespStaAddr;
484 	tpDphHashNode sta_ds;
485 	uint16_t aid = 0;
486 	uint8_t qos_mode = 0;
487 
488 	pMacHdr = (tpSirMacDataHdr3a) (pFrame);
489 
490 	/*
491 	 * if TDLS frame goes through the AP link, it follows normal address
492 	 * pattern, if TDLS frame goes through the direct link, then
493 	 * A1--> Peer STA addr, A2-->Self STA address, A3--> BSSID
494 	 */
495 	(tdlsLinkType == TDLS_LINK_AP) ? ((addr1 = (link_iden->bssid)),
496 					  (addr3 = (peerMac)))
497 	: ((addr1 = (peerMac)), (addr3 = (link_iden->bssid)));
498 	/*
499 	 * prepare 802.11 header
500 	 */
501 	pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION;
502 	pMacHdr->fc.type = SIR_MAC_DATA_FRAME;
503 
504 	sta_ds = dph_lookup_hash_entry(mac, peerMac, &aid,
505 					&pe_session->dph.dphHashTable);
506 	if (sta_ds)
507 		qos_mode = sta_ds->qosMode;
508 
509 	pMacHdr->fc.subType =
510 		((IS_QOS_ENABLED(pe_session) &&
511 		(tdlsLinkType == TDLS_LINK_AP)) ||
512 		((tdlsLinkType == TDLS_LINK_DIRECT) && qos_mode))
513 		? SIR_MAC_DATA_QOS_DATA : SIR_MAC_DATA_DATA;
514 
515 	/*
516 	 * TL is not setting up below fields, so we are doing it here
517 	 */
518 	pMacHdr->fc.toDS = toDs;
519 	pMacHdr->fc.powerMgmt = 0;
520 	pMacHdr->fc.wep = (pe_session->encryptType == eSIR_ED_NONE) ? 0 : 1;
521 
522 	qdf_mem_copy((uint8_t *) pMacHdr->addr1,
523 		     (uint8_t *) addr1, sizeof(tSirMacAddr));
524 	qdf_mem_copy((uint8_t *) pMacHdr->addr2,
525 		     (uint8_t *) staMac, sizeof(tSirMacAddr));
526 
527 	qdf_mem_copy((uint8_t *) pMacHdr->addr3,
528 		     (uint8_t *) (addr3), sizeof(tSirMacAddr));
529 
530 	pe_debug("Preparing TDLS frame header to %s A1:"
531 		   QDF_MAC_ADDR_FMT", A2:"QDF_MAC_ADDR_FMT", A3:"
532 		   QDF_MAC_ADDR_FMT,
533 		(tdlsLinkType == TDLS_LINK_AP) ? "AP" : "DIRECT",
534 		QDF_MAC_ADDR_REF(pMacHdr->addr1),
535 		QDF_MAC_ADDR_REF(pMacHdr->addr2),
536 		QDF_MAC_ADDR_REF(pMacHdr->addr3));
537 
538 	if (pMacHdr->fc.subType == SIR_MAC_DATA_QOS_DATA) {
539 		pMacHdr->qosControl.tid = tid;
540 		header_offset += sizeof(tSirMacDataHdr3a);
541 	} else
542 		header_offset += sizeof(tSirMacMgmtHdr);
543 
544 	/*
545 	 * Now form RFC1042 header
546 	 */
547 	qdf_mem_copy((uint8_t *) (pFrame + header_offset),
548 		     (uint8_t *) eth_890d_header, sizeof(eth_890d_header));
549 
550 	header_offset += sizeof(eth_890d_header);
551 
552 	/* add payload type as TDLS */
553 	*(pFrame + header_offset) = PAYLOAD_TYPE_TDLS;
554 	header_offset += PAYLOAD_TYPE_TDLS_SIZE;
555 
556 	return header_offset;
557 }
558 
559 /**
560  * lim_mgmt_tdls_tx_complete - callback to indicate Tx completion
561  * @context: pointer to mac structure
562  * @buf: buffer
563  * @tx_complete: indicates tx success/failure
564  * @params: tx completion params
565  *
566  * Function will be invoked on receiving tx completion indication
567  *
568  * Return: success: eHAL_STATUS_SUCCESS failure: eHAL_STATUS_FAILURE
569  */
570 static QDF_STATUS lim_mgmt_tdls_tx_complete(void *context, qdf_nbuf_t buf,
571 					    uint32_t tx_complete, void *params)
572 {
573 	struct mac_context *mac_ctx = (struct mac_context *)context;
574 	struct tdls_ethernet_hdr *ethernet_hdr;
575 	tpSirMacActionFrameHdr action_hdr;
576 	bool is_tdls_discvory_frm = false;
577 
578 
579 	if (NO_SESSION != mac_ctx->lim.tdls_frm_session_id) {
580 		if (buf &&
581 		    (qdf_nbuf_len(buf) >= (TDLS_ETHR_HDR_LEN +
582 					  eth_890d_hdr_len +
583 					  PAYLOAD_TYPE_TDLS_SIZE +
584 					  sizeof(*action_hdr)))) {
585 			ethernet_hdr =
586 				(struct tdls_ethernet_hdr *)qdf_nbuf_data(buf);
587 			is_tdls_discvory_frm =
588 				!qdf_mem_cmp(((uint8_t *)qdf_nbuf_data(buf) +
589 				TDLS_ETHR_HDR_LEN),
590 				eth_890d_tdls_discvory_frm_hdr,
591 				sizeof(eth_890d_tdls_discvory_frm_hdr));
592 
593 			if (is_tdls_discvory_frm &&
594 			    tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK)
595 				wlan_tdls_increment_discovery_attempts(
596 					mac_ctx->psoc,
597 					mac_ctx->lim.tdls_frm_session_id,
598 					ethernet_hdr->dest_addr);
599 		}
600 
601 		lim_send_sme_mgmt_tx_completion(mac_ctx,
602 				mac_ctx->lim.tdls_frm_session_id,
603 				tx_complete);
604 		mac_ctx->lim.tdls_frm_session_id = NO_SESSION;
605 	}
606 
607 	pe_debug("tdls_frm_session_id: %x tx_complete: %x is_discovery:%d",
608 		 mac_ctx->lim.tdls_frm_session_id, tx_complete,
609 		 is_tdls_discvory_frm);
610 
611 	if (buf)
612 		qdf_nbuf_free(buf);
613 
614 	return QDF_STATUS_SUCCESS;
615 }
616 
617 #ifdef WLAN_FEATURE_11BE_MLO
618 /**
619  * lim_get_assoc_link_vdev_id() - get vdev id
620  * @session: pe session
621  *
622  * Since fw only uses assoc link vdev to transmit data packets,
623  * it needs to fetch the right vdev id when transfer tdls management
624  * frame for partner link.
625  *
626  * Return: vdev id
627  */
628 static uint8_t lim_get_assoc_link_vdev_id(struct pe_session *session)
629 {
630 	struct wlan_objmgr_vdev *assoc_vdev;
631 
632 	if (wlan_vdev_mlme_is_mlo_vdev(session->vdev)) {
633 		assoc_vdev = wlan_mlo_get_assoc_link_vdev(session->vdev);
634 		if (assoc_vdev)
635 			return wlan_vdev_get_id(assoc_vdev);
636 	}
637 
638 	return session->smeSessionId;
639 }
640 #else
641 static uint8_t lim_get_assoc_link_vdev_id(struct pe_session *session)
642 {
643 	return session->smeSessionId;
644 }
645 #endif
646 
647 /*
648  * This function can be used for bacst or unicast discovery request
649  * We are not differentiating it here, it will all depend on peer MAC address,
650  */
651 static QDF_STATUS lim_send_tdls_dis_req_frame(struct mac_context *mac,
652 					      struct qdf_mac_addr peer_mac,
653 					      uint8_t dialog,
654 					      struct pe_session *pe_session,
655 					      enum wifi_traffic_ac ac)
656 {
657 	tDot11fTDLSDisReq *tdls_dis_req;
658 	uint32_t status = 0;
659 	uint32_t nPayload = 0;
660 	uint32_t size = 0;
661 	uint32_t nBytes = 0;
662 	uint32_t header_offset = 0;
663 	uint8_t *pFrame;
664 	void *pPacket;
665 	uint8_t vdev_id;
666 	QDF_STATUS qdf_status;
667 #ifndef NO_PAD_TDLS_MIN_8023_SIZE
668 	uint32_t padLen = 0;
669 #endif
670 	uint8_t smeSessionId = 0;
671 	uint16_t mlo_ie_len = 0;
672 
673 	if (!pe_session) {
674 		pe_err("pe_session is NULL");
675 		return QDF_STATUS_E_FAILURE;
676 	}
677 
678 	tdls_dis_req = qdf_mem_malloc(sizeof(*tdls_dis_req));
679 	if (!tdls_dis_req) {
680 		pe_err("memory allocation failed for DisReq");
681 		return QDF_STATUS_E_NOMEM;
682 	}
683 
684 	smeSessionId = pe_session->smeSessionId;
685 	/*
686 	 * The scheme here is to fill out a 'tDot11fProbeRequest' structure
687 	 * and then hand it off to 'dot11f_pack_probe_request' (for
688 	 * serialization).
689 	 */
690 
691 	/*
692 	 * setup Fixed fields,
693 	 */
694 	tdls_dis_req->Category.category = ACTION_CATEGORY_TDLS;
695 	tdls_dis_req->Action.action = TDLS_DISCOVERY_REQUEST;
696 	tdls_dis_req->DialogToken.token = dialog;
697 
698 	size = sizeof(tSirMacAddr);
699 
700 	populate_dot11f_link_iden(mac, pe_session,
701 				  &tdls_dis_req->LinkIdentifier,
702 				  peer_mac, TDLS_INITIATOR);
703 
704 	if (wlan_vdev_mlme_is_mlo_vdev(pe_session->vdev))
705 		mlo_ie_len = lim_send_tdls_mgmt_frame_mlo(mac, pe_session);
706 
707 	/*
708 	 * now we pack it.  First, how much space are we going to need?
709 	 */
710 	status = dot11f_get_packed_tdls_dis_req_size(mac, tdls_dis_req,
711 						     &nPayload);
712 	if (DOT11F_FAILED(status)) {
713 		pe_err("Failed to calculate the packed size for a discovery Request (0x%08x)",
714 			status);
715 		/* We'll fall back on the worst case scenario: */
716 		nPayload = sizeof(tDot11fTDLSDisReq);
717 	} else if (DOT11F_WARNED(status)) {
718 		pe_warn("There were warnings while calculating the packed size for a discovery Request (0x%08x)",
719 			status);
720 	}
721 
722 	/*
723 	 * This frame is going out from PE as data frames with special ethertype
724 	 * 89-0d.
725 	 * 8 bytes of RFC 1042 header
726 	 */
727 
728 	nBytes = nPayload + ((IS_QOS_ENABLED(pe_session))
729 			     ? sizeof(tSirMacDataHdr3a) :
730 			     sizeof(tSirMacMgmtHdr))
731 		 + sizeof(eth_890d_header)
732 		 + PAYLOAD_TYPE_TDLS_SIZE
733 		 + mlo_ie_len;
734 
735 #ifndef NO_PAD_TDLS_MIN_8023_SIZE
736 	/* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64)
737 	   Hence AP itself padding some bytes, which caused teardown packet is dropped at
738 	   receiver side. To avoid such IOT issue, we added some extra bytes to meet data frame size >= 64
739 	 */
740 	if (nPayload + PAYLOAD_TYPE_TDLS_SIZE < MIN_IEEE_8023_SIZE) {
741 		padLen =
742 			MIN_IEEE_8023_SIZE - (nPayload + PAYLOAD_TYPE_TDLS_SIZE);
743 
744 		/* if padLen is less than minimum vendorSpecific (5), pad up to 5 */
745 		if (padLen < MIN_VENDOR_SPECIFIC_IE_SIZE)
746 			padLen = MIN_VENDOR_SPECIFIC_IE_SIZE;
747 
748 		nBytes += padLen;
749 	}
750 #endif
751 
752 	/* Ok-- try to allocate memory from MGMT PKT pool */
753 
754 	qdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
755 				      (void **)&pPacket);
756 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
757 		pe_err("Failed to allocate: %d bytes for a TDLS Discovery Request",
758 			nBytes);
759 		qdf_mem_free(tdls_dis_req);
760 		return QDF_STATUS_E_NOMEM;
761 	}
762 
763 	/* zero out the memory */
764 	qdf_mem_zero(pFrame, nBytes);
765 
766 	/*
767 	 * IE formation, memory allocation is completed, Now form TDLS discovery
768 	 * request frame
769 	 */
770 
771 	/* fill out the buffer descriptor */
772 
773 	header_offset = lim_prepare_tdls_frame_header(mac, pFrame,
774 			      &tdls_dis_req->LinkIdentifier, TDLS_LINK_AP,
775 			      TDLS_INITIATOR,
776 			      (ac == WIFI_AC_VI) ? TID_AC_VI : TID_AC_BK,
777 			      pe_session);
778 
779 	status = dot11f_pack_tdls_dis_req(mac, tdls_dis_req, pFrame
780 					  + header_offset, nPayload, &nPayload);
781 
782 	if (DOT11F_FAILED(status)) {
783 		pe_err("Failed to pack a TDLS discovery req (0x%08x)",
784 			status);
785 		cds_packet_free((void *)pPacket);
786 		qdf_mem_free(tdls_dis_req);
787 		return QDF_STATUS_E_FAILURE;
788 	} else if (DOT11F_WARNED(status)) {
789 		pe_warn("There were warnings while packing TDLS Discovery Request (0x%08x)",
790 			status);
791 	}
792 
793 	if (mlo_ie_len) {
794 		qdf_status = lim_fill_complete_mlo_ie(pe_session, mlo_ie_len,
795 						      pFrame + header_offset +
796 						      nPayload);
797 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
798 			pe_debug("assemble ml ie error");
799 			mlo_ie_len = 0;
800 		}
801 
802 		nPayload += mlo_ie_len;
803 	}
804 
805 	lim_cp_stats_cstats_log_disc_req_evt(tdls_dis_req, pe_session);
806 
807 	qdf_mem_free(tdls_dis_req);
808 
809 #ifndef NO_PAD_TDLS_MIN_8023_SIZE
810 	if (padLen != 0) {
811 		/* QCOM VENDOR OUI = { 0x00, 0xA0, 0xC6, type = 0x0000 }; */
812 		uint8_t *padVendorSpecific = pFrame + header_offset + nPayload;
813 		/* make QCOM_VENDOR_OUI, and type = 0x0000, and all the payload to be zero */
814 		padVendorSpecific[0] = 221;
815 		padVendorSpecific[1] = padLen - 2;
816 		padVendorSpecific[2] = 0x00;
817 		padVendorSpecific[3] = 0xA0;
818 		padVendorSpecific[4] = 0xC6;
819 
820 		pe_debug("Padding Vendor Specific Ie Len: %d", padLen);
821 
822 		/* padding zero if more than 5 bytes are required */
823 		if (padLen > MIN_VENDOR_SPECIFIC_IE_SIZE)
824 			qdf_mem_zero(pFrame + header_offset + nPayload +
825 				    MIN_VENDOR_SPECIFIC_IE_SIZE,
826 				    padLen - MIN_VENDOR_SPECIFIC_IE_SIZE);
827 	}
828 #endif
829 
830 	pe_debug("[TDLS] action: %d (%s) -AP-> OTA peer="QDF_MAC_ADDR_FMT,
831 		TDLS_DISCOVERY_REQUEST,
832 		lim_trace_tdls_action_string(TDLS_DISCOVERY_REQUEST),
833 		QDF_MAC_ADDR_REF(peer_mac.bytes));
834 
835 	mac->lim.tdls_frm_session_id = pe_session->smeSessionId;
836 	vdev_id = lim_get_assoc_link_vdev_id(pe_session);
837 
838 	lim_diag_mgmt_tx_event_report(mac, (tpSirMacMgmtHdr) pFrame,
839 				      pe_session, QDF_STATUS_SUCCESS,
840 				      QDF_STATUS_SUCCESS);
841 	qdf_status = wma_tx_frameWithTxComplete(mac, pPacket,
842 					(uint16_t) nBytes,
843 					TXRX_FRM_802_11_DATA,
844 					ANI_TXDIR_TODS,
845 					TID_AC_VI,
846 					lim_tx_complete, pFrame,
847 					lim_mgmt_tdls_tx_complete,
848 					HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME |
849 					HAL_USE_PEER_STA_REQUESTED_MASK,
850 					vdev_id, false, 0,
851 					RATEID_DEFAULT, 0, 0);
852 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
853 		mac->lim.tdls_frm_session_id = NO_SESSION;
854 		pe_err("could not send TDLS Discovery Request frame");
855 		return QDF_STATUS_E_FAILURE;
856 	}
857 
858 	return QDF_STATUS_SUCCESS;
859 
860 }
861 
862 /*
863  * This static function is consistent with any kind of TDLS management
864  * frames we are sending. Currently it is being used by lim_send_tdls_dis_rsp_frame,
865  * lim_send_tdls_link_setup_req_frame and lim_send_tdls_setup_rsp_frame
866  */
867 static void populate_dot11f_tdls_ht_vht_cap(struct mac_context *mac,
868 					    uint32_t selfDot11Mode,
869 					    tDot11fIEHTCaps *htCap,
870 					    tDot11fIEVHTCaps *vhtCap,
871 					    struct pe_session *pe_session)
872 {
873 	uint8_t nss;
874 	qdf_size_t val_len;
875 	struct mlme_vht_capabilities_info *vht_cap_info;
876 	bool is_wideband;
877 
878 	is_wideband =
879 		wlan_cfg80211_tdls_is_fw_wideband_capable(pe_session->vdev);
880 
881 	vht_cap_info = &mac->mlme_cfg->vht_caps.vht_cap_info;
882 
883 	if (wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq))
884 		nss = mac->vdev_type_nss_2g.tdls;
885 	else
886 		nss = mac->vdev_type_nss_5g.tdls;
887 
888 	nss = QDF_MIN(nss, mac->user_configured_nss);
889 	if (IS_DOT11_MODE_HT(selfDot11Mode) &&
890 	    !lim_is_he_6ghz_band(pe_session)) {
891 		/* Include HT Capability IE */
892 		populate_dot11f_ht_caps(mac, pe_session, htCap);
893 		val_len = SIZE_OF_SUPPORTED_MCS_SET;
894 		wlan_mlme_get_cfg_str(&htCap->supportedMCSSet[0],
895 				      &mac->mlme_cfg->rates.supported_mcs_set,
896 				      &val_len);
897 		if (WLAN_REG_IS_5GHZ_CH_FREQ(pe_session->curr_op_freq) &&
898 		    !wlan_reg_is_dfs_for_freq(mac->pdev,
899 					      pe_session->curr_op_freq) &&
900 		    is_wideband)
901 			htCap->supportedChannelWidthSet = 1;
902 		else
903 			if (pe_session->ch_width == CH_WIDTH_20MHZ)
904 				htCap->supportedChannelWidthSet = 0;
905 
906 		if (NSS_1x1_MODE == nss)
907 			htCap->supportedMCSSet[1] = 0;
908 		/*
909 		 * Advertise ht capability and max supported channel bandwidth
910 		 * when populating HT IE in TDLS Setup Request/Setup Response/
911 		 * Setup Confirmation frames.
912 		 * 11.21.6.2 Setting up a 40 MHz direct link: A 40 MHz
913 		 * off-channel direct link may be started if both TDLS peer STAs
914 		 * indicated 40 MHz support in the Supported Channel Width Set
915 		 * field of the HT Capabilities element (which is included in
916 		 * the TDLS Setup Request frame and the TDLS Setup Response
917 		 * frame). Switching to a 40 MHz off-channel direct link is
918 		 * achieved by including the following information in the TDLS
919 		 * Channel Switch Request
920 		 * 11.21.1 General: The channel width of the TDLS direct link on
921 		 * the base channel shall not exceed the channel width of the
922 		 * BSS to which the TDLS peer STAs are associated.
923 		 * Select supportedChannelWidthSet based on channel bonding
924 		 * settings for each band
925 		 */
926 	} else {
927 		htCap->present = 0;
928 	}
929 	pe_debug("HT present: %hu, Chan Width: %hu",
930 		htCap->present, htCap->supportedChannelWidthSet);
931 
932 	if ((WLAN_REG_IS_24GHZ_CH_FREQ(pe_session->curr_op_freq) &&
933 	     vht_cap_info->b24ghz_band) ||
934 	    WLAN_REG_IS_5GHZ_CH_FREQ(pe_session->curr_op_freq)) {
935 		if (IS_DOT11_MODE_VHT(selfDot11Mode) &&
936 		    IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) {
937 			/*
938 			 * Include VHT Capability IE
939 			 *
940 			 * VHT supportedChannelWidthSet should be set such as
941 			 * 1. Set to 0 if AP does not support either
942 			 *    160 or 80+80 MHz. With 0, it means 20/40/80 Mhz.
943 			 *    Since for TDLS wideband we need to restrict the BW
944 			 *    to 80 MHz for AP supporting BW less than 80 Mhz.
945 			 *    So, set it to 0 for such cases so that TDLS STA
946 			 *    can connect with 80 MHz width.
947 			 * 2. Set to 1 if AP supports 160 MHz, thus TDLS STA can
948 			 *    connect with 160 MHz BW
949 			 * 3. Set to 2 if AP supports 160 MHz and
950 			 *    80+80 MHz. Not possible in case of 5 GHz
951 			 *
952 			 *   The value 3 is reserved
953 			 */
954 			populate_dot11f_vht_caps(mac, pe_session, vhtCap);
955 			vhtCap->suBeamformeeCap = 0;
956 			vhtCap->suBeamFormerCap = 0;
957 			vhtCap->muBeamformeeCap = 0;
958 			vhtCap->muBeamformerCap = 0;
959 
960 			vhtCap->rxMCSMap = vht_cap_info->rx_mcs_map;
961 
962 			vhtCap->rxHighSupDataRate =
963 				vht_cap_info->rx_supp_data_rate;
964 			vhtCap->txMCSMap = vht_cap_info->tx_mcs_map;
965 			vhtCap->txSupDataRate = vht_cap_info->tx_supp_data_rate;
966 			if (nss == NSS_1x1_MODE) {
967 				vhtCap->txMCSMap |= DISABLE_NSS2_MCS;
968 				vhtCap->rxMCSMap |= DISABLE_NSS2_MCS;
969 				vhtCap->txSupDataRate =
970 					VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
971 				vhtCap->rxHighSupDataRate =
972 					VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
973 			}
974 		} else {
975 			vhtCap->present = 0;
976 		}
977 	} else {
978 		/* Vht Disable from ini in 2.4 GHz */
979 		vhtCap->present = 0;
980 	}
981 	pe_debug("VHT present: %hu, Chan Width: %u",
982 		 vhtCap->present, vhtCap->supportedChannelWidthSet);
983 }
984 
985 #ifdef WLAN_FEATURE_11AX
986 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
987 static void
988 lim_tdls_populate_dot11f_6hgz_he_caps(struct mac_context *mac,
989 				      struct tdls_add_sta_req *add_sta_req,
990 				      tDot11fIEhe_6ghz_band_cap *pDot11f)
991 {
992 	union {
993 		struct hecap_6ghz he_6ghz_cap;
994 		struct he_6ghz_capability_info dot11f;
995 	} peer_cfg;
996 
997 	if (!add_sta_req->he_6ghz_cap.a_mpdu_params &&
998 	    !add_sta_req->he_6ghz_cap.info) {
999 		tdls_debug("6Ghz HE capabilities not present");
1000 		return;
1001 	}
1002 
1003 	qdf_mem_copy(&peer_cfg.he_6ghz_cap,
1004 		     &add_sta_req->he_6ghz_cap,
1005 		     sizeof(add_sta_req->he_6ghz_cap));
1006 
1007 	pDot11f->present = 1;
1008 	pDot11f->min_mpdu_start_spacing =
1009 				peer_cfg.dot11f.min_mpdu_start_spacing;
1010 	pDot11f->max_ampdu_len_exp = peer_cfg.dot11f.max_ampdu_len_exp;
1011 	pDot11f->max_mpdu_len = peer_cfg.dot11f.max_mpdu_len;
1012 	pDot11f->sm_pow_save = peer_cfg.dot11f.sm_pow_save;
1013 	pDot11f->rd_responder = peer_cfg.dot11f.rd_responder;
1014 	pDot11f->rx_ant_pattern_consistency =
1015 				peer_cfg.dot11f.rx_ant_pattern_consistency;
1016 	pDot11f->tx_ant_pattern_consistency =
1017 				peer_cfg.dot11f.tx_ant_pattern_consistency;
1018 
1019 	lim_log_he_6g_cap(mac, pDot11f);
1020 }
1021 
1022 static void lim_populate_tdls_setup_6g_cap(struct mac_context *mac,
1023 					   tDot11fIEhe_6ghz_band_cap *hecap_6g,
1024 					   struct pe_session *session)
1025 {
1026 	if (hecap_6g)
1027 		populate_dot11f_he_6ghz_cap(mac, session, hecap_6g);
1028 }
1029 
1030 #else
1031 static void
1032 lim_tdls_populate_dot11f_6hgz_he_caps(struct mac_context *mac,
1033 				      struct tdls_add_sta_req *add_sta_req,
1034 				      tDot11fIEhe_6ghz_band_cap *pDot11f)
1035 {
1036 }
1037 
1038 static void lim_populate_tdls_setup_6g_cap(struct mac_context *mac,
1039 					   tDot11fIEhe_6ghz_band_cap *hecap_6g,
1040 					   struct pe_session *session)
1041 {
1042 }
1043 #endif
1044 
1045 static void lim_fill_session_he_width(struct pe_session *session,
1046 				      tDot11fIEhe_cap *heCap)
1047 {
1048 	/*
1049 	 * For TDLS, the bw is filled using mlme_cfg so max supported bw
1050 	 * will be set, so here reset he bw as per session bw.
1051 	 */
1052 	if (session->ch_width == CH_WIDTH_20MHZ) {
1053 		goto bw_20;
1054 	} else if (session->ch_width == CH_WIDTH_40MHZ) {
1055 		heCap->chan_width_0 = 1;
1056 		goto bw_40;
1057 	} else if (session->ch_width == CH_WIDTH_80MHZ) {
1058 		heCap->chan_width_1 = 1;
1059 		goto bw_80;
1060 	} else if (session->ch_width == CH_WIDTH_160MHZ) {
1061 		heCap->chan_width_2 = 1;
1062 		goto bw_160;
1063 	} else if (session->ch_width == CH_WIDTH_80P80MHZ) {
1064 		heCap->chan_width_3 = 1;
1065 		return;
1066 	}
1067 
1068 bw_20:
1069 	heCap->chan_width_0 = 0;
1070 bw_40:
1071 	heCap->chan_width_1 = 0;
1072 bw_80:
1073 	heCap->chan_width_2 = 0;
1074 bw_160:
1075 	heCap->chan_width_3 = 0;
1076 }
1077 
1078 static void lim_tdls_set_he_chan_width(struct mac_context *mac,
1079 				       tDot11fIEhe_cap *heCap,
1080 				       struct pe_session *session,
1081 				       bool wideband_sta)
1082 {
1083 	if (!wideband_sta ||
1084 	    wlan_reg_is_24ghz_ch_freq(session->curr_op_freq)) {
1085 		lim_fill_session_he_width(session, heCap);
1086 		return;
1087 	}
1088 
1089 	if (wlan_reg_is_5ghz_ch_freq(session->curr_op_freq)) {
1090 		if (wlan_reg_is_dfs_for_freq(mac->pdev,
1091 					     session->curr_op_freq)) {
1092 			lim_fill_session_he_width(session, heCap);
1093 			return;
1094 		}
1095 	/*
1096 	 * Right now, no support for ch_width 160 Mhz or 80P80 Mhz in 5 Ghz
1097 	 * Also, restricting bw to 80 Mhz in case ap on 5 ghz is operating in
1098 	 * less than 80 Mhz bw.
1099 	 */
1100 		if (session->ch_width <= CH_WIDTH_80MHZ)
1101 			heCap->chan_width_2 = 0;
1102 		heCap->chan_width_3 = 0;
1103 		heCap->chan_width_4 = 0;
1104 		heCap->chan_width_5 = 0;
1105 		heCap->chan_width_6 = 0;
1106 	}
1107 }
1108 
1109 static void lim_tdls_populate_ppe_caps(struct mac_context *mac,
1110 				       struct pe_session *session,
1111 				       tDot11fIEhe_cap *he_cap)
1112 {
1113 	uint8_t *ppet;
1114 
1115 	/*
1116 	 * No Need to populate if ppet is not present
1117 	 */
1118 	if (!he_cap->ppet_present)
1119 		return;
1120 
1121 	if (!wlan_reg_is_24ghz_ch_freq(session->curr_op_freq))
1122 		ppet = mac->mlme_cfg->he_caps.he_ppet_5g;
1123 	else
1124 		ppet = mac->mlme_cfg->he_caps.he_ppet_2g;
1125 
1126 	he_cap->ppet.ppe_threshold.num_ppe_th = lim_truncate_ppet(ppet,
1127 							      MLME_HE_PPET_LEN);
1128 
1129 	/*
1130 	 * If num_ppe_th calculated above is zero and ppet_present is set then
1131 	 * atleast one byte should be sent with zero data otherwise framework
1132 	 * will fail add_sta on the peer end.
1133 	 */
1134 	if (he_cap->ppet.ppe_threshold.num_ppe_th)
1135 		qdf_mem_copy(he_cap->ppet.ppe_threshold.ppe_th, ppet,
1136 			     MLME_HE_PPET_LEN);
1137 	else
1138 		he_cap->ppet.ppe_threshold.num_ppe_th = 1;
1139 }
1140 
1141 static void populate_dot11f_set_tdls_he_cap(struct mac_context *mac,
1142 					    uint32_t selfDot11Mode,
1143 					    tDot11fIEhe_cap *heCap,
1144 					    tDot11fIEhe_6ghz_band_cap *hecap_6g,
1145 					    struct pe_session *session)
1146 {
1147 	if (IS_DOT11_MODE_HE(selfDot11Mode)) {
1148 		populate_dot11f_he_caps(mac, NULL, heCap);
1149 		lim_tdls_set_he_chan_width(mac, heCap, session,
1150 		      wlan_cfg80211_tdls_is_fw_wideband_capable(session->vdev));
1151 		lim_tdls_populate_ppe_caps(mac, session, heCap);
1152 		lim_log_he_cap(mac, heCap);
1153 		lim_populate_tdls_setup_6g_cap(mac, hecap_6g, session);
1154 	} else {
1155 		pe_debug("Not populating he cap as SelfDot11Mode not HE %d",
1156 			 selfDot11Mode);
1157 	}
1158 }
1159 
1160 static void lim_tdls_fill_dis_rsp_he_cap(struct mac_context *mac,
1161 					 uint32_t selfDot11Mode,
1162 					 tDot11fTDLSDisRsp *tdls_dis_rsp,
1163 					 struct pe_session *pe_session)
1164 {
1165 	populate_dot11f_set_tdls_he_cap(mac, selfDot11Mode,
1166 					&tdls_dis_rsp->he_cap,
1167 					NULL,
1168 					pe_session);
1169 }
1170 
1171 static void lim_tdls_fill_setup_req_he_cap(struct mac_context *mac,
1172 					   uint32_t selfDot11Mode,
1173 					   tDot11fTDLSSetupReq *tdls_setup_req,
1174 					   struct pe_session *pe_session)
1175 {
1176 	populate_dot11f_set_tdls_he_cap(mac, selfDot11Mode,
1177 					&tdls_setup_req->he_cap,
1178 					&tdls_setup_req->he_6ghz_band_cap,
1179 					pe_session);
1180 }
1181 
1182 static void lim_tdls_fill_setup_rsp_he_cap(struct mac_context *mac,
1183 					   uint32_t selfDot11Mode,
1184 					   tDot11fTDLSSetupRsp *tdls_setup_rsp,
1185 					   struct pe_session *pe_session)
1186 {
1187 	populate_dot11f_set_tdls_he_cap(mac, selfDot11Mode,
1188 					&tdls_setup_rsp->he_cap,
1189 					&tdls_setup_rsp->he_6ghz_band_cap,
1190 					pe_session);
1191 }
1192 
1193 static void lim_tdls_populate_he_operations(struct mac_context *mac,
1194 					    struct pe_session *pe_session,
1195 					    tDot11fIEhe_op *he_op)
1196 {
1197 	struct wlan_mlme_he_caps *he_cap_info;
1198 	uint16_t mcs_set = 0;
1199 
1200 	he_cap_info = &mac->mlme_cfg->he_caps;
1201 	he_op->co_located_bss = 0;
1202 	he_op->bss_color = pe_session->he_bss_color_change.new_color;
1203 	if (!he_op->bss_color)
1204 		he_op->bss_col_disabled = 1;
1205 
1206 	mcs_set = (uint16_t)he_cap_info->he_ops_basic_mcs_nss;
1207 	if (pe_session->nss == NSS_1x1_MODE)
1208 		mcs_set |= 0xFFFC;
1209 	else
1210 		mcs_set |= 0xFFF0;
1211 
1212 	*((uint16_t *)he_op->basic_mcs_nss) = mcs_set;
1213 	populate_dot11f_he_operation(mac,
1214 				     pe_session,
1215 				     he_op);
1216 }
1217 
1218 static void lim_tdls_fill_setup_cnf_he_op(struct mac_context *mac,
1219 					  uint32_t peer_capability,
1220 					  tDot11fTDLSSetupCnf *tdls_setup_cnf,
1221 					  struct pe_session *pe_session)
1222 {
1223 	if (CHECK_BIT(peer_capability, TDLS_PEER_HE_CAP))
1224 		lim_tdls_populate_he_operations(mac,
1225 						pe_session,
1226 						&tdls_setup_cnf->he_op);
1227 }
1228 
1229 static void lim_tdls_fill_he_wideband_offchannel_mcs(struct mac_context *mac_ctx,
1230 						     tpDphHashNode stads,
1231 						     uint8_t nss,
1232 						     struct pe_session *session)
1233 {
1234 	struct supported_rates *rates = &stads->supportedRates;
1235 	tDot11fIEhe_cap *peer_he_caps = &stads->he_config;
1236 	struct tdls_vdev_priv_obj *tdls_obj = NULL;
1237 	struct tdls_peer *tdls_peer_candidate = NULL;
1238 	struct tdls_peer *curr_peer_candidate = NULL;
1239 	qdf_list_t *head;
1240 	qdf_list_node_t *p_node;
1241 	int i = 0;
1242 	uint16_t rx_he_mcs_map_160 = 0xfffa;
1243 	uint16_t tx_he_mcs_map_160 = 0xfffa;
1244 	QDF_STATUS status;
1245 
1246 	tdls_obj = wlan_vdev_get_tdls_vdev_obj(session->vdev);
1247 	if (!tdls_obj) {
1248 		pe_debug("failed to ger tdls priv object");
1249 		return;
1250 	}
1251 
1252 	for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
1253 		head = &tdls_obj->peer_list[i];
1254 		status = qdf_list_peek_front(head, &p_node);
1255 		while (QDF_IS_STATUS_SUCCESS(status)) {
1256 			curr_peer_candidate = qdf_container_of(p_node,
1257 							       struct tdls_peer,
1258 							       node);
1259 			if (!qdf_mem_cmp(&curr_peer_candidate->peer_mac.bytes,
1260 					&stads->staAddr, QDF_MAC_ADDR_SIZE)) {
1261 				tdls_peer_candidate = curr_peer_candidate;
1262 				break;
1263 			}
1264 			status = qdf_list_peek_next(head, p_node, &p_node);
1265 		}
1266 	}
1267 
1268 	if (!tdls_peer_candidate) {
1269 		pe_debug("failed to ger tdls peer object");
1270 		return;
1271 	}
1272 
1273 	if (stads->ch_width == CH_WIDTH_160MHZ) {
1274 		lim_populate_he_mcs_per_bw(
1275 			mac_ctx, &rates->rx_he_mcs_map_160,
1276 			&rates->tx_he_mcs_map_160,
1277 			*((uint16_t *)peer_he_caps->rx_he_mcs_map_160),
1278 			*((uint16_t *)peer_he_caps->tx_he_mcs_map_160),
1279 			nss,
1280 			*((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap.
1281 				rx_he_mcs_map_160),
1282 			*((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap.
1283 					tx_he_mcs_map_160));
1284 	} else if (tdls_peer_candidate->pref_off_chan_width &
1285 	     (1 << BW_160_OFFSET_BIT)) {
1286 		lim_populate_he_mcs_per_bw(
1287 			mac_ctx, &rates->rx_he_mcs_map_160,
1288 			&rates->tx_he_mcs_map_160,
1289 			rx_he_mcs_map_160,
1290 			tx_he_mcs_map_160,
1291 			nss,
1292 			*((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap.
1293 				rx_he_mcs_map_160),
1294 			*((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap.
1295 					tx_he_mcs_map_160));
1296 	} else {
1297 		rates->tx_he_mcs_map_160 = HE_MCS_ALL_DISABLED;
1298 		rates->rx_he_mcs_map_160 = HE_MCS_ALL_DISABLED;
1299 	}
1300 	if (stads->ch_width == CH_WIDTH_80P80MHZ) {
1301 		lim_populate_he_mcs_per_bw(
1302 			mac_ctx, &rates->rx_he_mcs_map_80_80,
1303 			&rates->tx_he_mcs_map_80_80,
1304 			*((uint16_t *)peer_he_caps->rx_he_mcs_map_80_80),
1305 			*((uint16_t *)peer_he_caps->tx_he_mcs_map_80_80), nss,
1306 			*((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap.
1307 					rx_he_mcs_map_80_80),
1308 			*((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap.
1309 					tx_he_mcs_map_80_80));
1310 	} else {
1311 		rates->tx_he_mcs_map_80_80 = HE_MCS_ALL_DISABLED;
1312 		rates->rx_he_mcs_map_80_80 = HE_MCS_ALL_DISABLED;
1313 	}
1314 }
1315 
1316 static void lim_tdls_populate_he_matching_rate_set(struct mac_context *mac_ctx,
1317 						   tpDphHashNode stads,
1318 						   uint8_t nss,
1319 						   struct pe_session *session)
1320 {
1321 	lim_populate_he_mcs_set(mac_ctx, &stads->supportedRates,
1322 				&stads->he_config, session, nss);
1323 
1324 	lim_tdls_fill_he_wideband_offchannel_mcs(mac_ctx, stads, nss, session);
1325 }
1326 
1327 static QDF_STATUS
1328 lim_tdls_populate_dot11f_he_caps(struct mac_context *mac,
1329 				 struct tdls_add_sta_req *add_sta_req,
1330 				 tDot11fIEhe_cap *pDot11f)
1331 {
1332 	uint32_t chan_width;
1333 	union {
1334 		struct hecap nCfgValue;
1335 		struct he_capability_info he_cap;
1336 	} uHECapInfo;
1337 
1338 	if (add_sta_req->he_cap_len < MIN_TDLS_HE_CAP_LEN) {
1339 		pe_debug("He_capability invalid");
1340 		return QDF_STATUS_E_INVAL;
1341 	}
1342 
1343 	qdf_mem_copy(&uHECapInfo.nCfgValue, &add_sta_req->he_cap,
1344 		     sizeof(uHECapInfo.nCfgValue));
1345 
1346 	pDot11f->present = 1;
1347 	pDot11f->htc_he = uHECapInfo.he_cap.htc_he;
1348 	pDot11f->twt_request = uHECapInfo.he_cap.twt_request;
1349 	pDot11f->twt_responder = uHECapInfo.he_cap.twt_responder;
1350 	pDot11f->fragmentation = uHECapInfo.he_cap.fragmentation;
1351 	pDot11f->max_num_frag_msdu_amsdu_exp =
1352 		uHECapInfo.he_cap.max_num_frag_msdu_amsdu_exp;
1353 	pDot11f->min_frag_size = uHECapInfo.he_cap.min_frag_size;
1354 	pDot11f->trigger_frm_mac_pad = uHECapInfo.he_cap.trigger_frm_mac_pad;
1355 	pDot11f->multi_tid_aggr_rx_supp =
1356 		uHECapInfo.he_cap.multi_tid_aggr_rx_supp;
1357 	pDot11f->he_link_adaptation = uHECapInfo.he_cap.he_link_adaptation;
1358 	pDot11f->all_ack = uHECapInfo.he_cap.all_ack;
1359 	pDot11f->trigd_rsp_sched = uHECapInfo.he_cap.trigd_rsp_sched;
1360 	pDot11f->a_bsr = uHECapInfo.he_cap.a_bsr;
1361 	pDot11f->broadcast_twt = uHECapInfo.he_cap.broadcast_twt;
1362 	pDot11f->ba_32bit_bitmap = uHECapInfo.he_cap.ba_32bit_bitmap;
1363 	pDot11f->mu_cascade = uHECapInfo.he_cap.mu_cascade;
1364 	pDot11f->ack_enabled_multitid = uHECapInfo.he_cap.ack_enabled_multitid;
1365 	pDot11f->omi_a_ctrl = uHECapInfo.he_cap.omi_a_ctrl;
1366 	pDot11f->ofdma_ra = uHECapInfo.he_cap.ofdma_ra;
1367 	pDot11f->max_ampdu_len_exp_ext =
1368 		uHECapInfo.he_cap.max_ampdu_len_exp_ext;
1369 	pDot11f->amsdu_frag = uHECapInfo.he_cap.amsdu_frag;
1370 	pDot11f->flex_twt_sched = uHECapInfo.he_cap.flex_twt_sched;
1371 	pDot11f->rx_ctrl_frame = uHECapInfo.he_cap.rx_ctrl_frame;
1372 
1373 	pDot11f->bsrp_ampdu_aggr = uHECapInfo.he_cap.bsrp_ampdu_aggr;
1374 	pDot11f->qtp = uHECapInfo.he_cap.qtp;
1375 	pDot11f->a_bqr = uHECapInfo.he_cap.a_bqr;
1376 	pDot11f->spatial_reuse_param_rspder =
1377 		uHECapInfo.he_cap.spatial_reuse_param_rspder;
1378 	pDot11f->ops_supp = uHECapInfo.he_cap.ops_supp;
1379 	pDot11f->ndp_feedback_supp = uHECapInfo.he_cap.ndp_feedback_supp;
1380 	pDot11f->amsdu_in_ampdu = uHECapInfo.he_cap.amsdu_in_ampdu;
1381 
1382 	chan_width = uHECapInfo.he_cap.chan_width;
1383 	pDot11f->chan_width_0 = HE_CH_WIDTH_GET_BIT(chan_width, 0);
1384 	pDot11f->chan_width_1 = HE_CH_WIDTH_GET_BIT(chan_width, 1);
1385 	pDot11f->chan_width_2 = HE_CH_WIDTH_GET_BIT(chan_width, 2);
1386 	pDot11f->chan_width_3 = HE_CH_WIDTH_GET_BIT(chan_width, 3);
1387 	pDot11f->chan_width_4 = HE_CH_WIDTH_GET_BIT(chan_width, 4);
1388 	pDot11f->chan_width_5 = HE_CH_WIDTH_GET_BIT(chan_width, 5);
1389 	pDot11f->chan_width_6 = HE_CH_WIDTH_GET_BIT(chan_width, 6);
1390 
1391 	pDot11f->rx_pream_puncturing = uHECapInfo.he_cap.rx_pream_puncturing;
1392 	pDot11f->device_class = uHECapInfo.he_cap.device_class;
1393 	pDot11f->ldpc_coding = uHECapInfo.he_cap.ldpc_coding;
1394 	pDot11f->he_1x_ltf_800_gi_ppdu =
1395 		uHECapInfo.he_cap.he_1x_ltf_800_gi_ppdu;
1396 	pDot11f->midamble_tx_rx_max_nsts =
1397 		uHECapInfo.he_cap.midamble_tx_rx_max_nsts;
1398 	pDot11f->he_4x_ltf_3200_gi_ndp =
1399 		uHECapInfo.he_cap.he_4x_ltf_3200_gi_ndp;
1400 	pDot11f->tb_ppdu_tx_stbc_lt_80mhz =
1401 		uHECapInfo.he_cap.tb_ppdu_tx_stbc_lt_80mhz;
1402 	pDot11f->rx_stbc_lt_80mhz = uHECapInfo.he_cap.rx_stbc_lt_80mhz;
1403 	pDot11f->tb_ppdu_tx_stbc_gt_80mhz =
1404 		uHECapInfo.he_cap.tb_ppdu_tx_stbc_gt_80mhz;
1405 	pDot11f->rx_stbc_gt_80mhz = uHECapInfo.he_cap.rx_stbc_gt_80mhz;
1406 	pDot11f->doppler = uHECapInfo.he_cap.doppler;
1407 	pDot11f->ul_mu = uHECapInfo.he_cap.ul_mu;
1408 	pDot11f->dcm_enc_tx = uHECapInfo.he_cap.dcm_enc_tx;
1409 	pDot11f->dcm_enc_rx = uHECapInfo.he_cap.dcm_enc_rx;
1410 	pDot11f->ul_he_mu = uHECapInfo.he_cap.ul_he_mu;
1411 	pDot11f->su_beamformer = uHECapInfo.he_cap.su_beamformer;
1412 
1413 	pDot11f->su_beamformee = uHECapInfo.he_cap.su_beamformee;
1414 	pDot11f->mu_beamformer = uHECapInfo.he_cap.mu_beamformer;
1415 	pDot11f->bfee_sts_lt_80 = uHECapInfo.he_cap.bfee_sts_lt_80;
1416 	pDot11f->bfee_sts_gt_80 = uHECapInfo.he_cap.bfee_sts_gt_80;
1417 	pDot11f->num_sounding_lt_80 = uHECapInfo.he_cap.num_sounding_lt_80;
1418 	pDot11f->num_sounding_gt_80 = uHECapInfo.he_cap.num_sounding_gt_80;
1419 	pDot11f->su_feedback_tone16 = uHECapInfo.he_cap.su_feedback_tone16;
1420 	pDot11f->mu_feedback_tone16 = uHECapInfo.he_cap.mu_feedback_tone16;
1421 	pDot11f->codebook_su = uHECapInfo.he_cap.codebook_su;
1422 	pDot11f->codebook_mu = uHECapInfo.he_cap.codebook_mu;
1423 	pDot11f->beamforming_feedback = uHECapInfo.he_cap.beamforming_feedback;
1424 	pDot11f->he_er_su_ppdu = uHECapInfo.he_cap.he_er_su_ppdu;
1425 	pDot11f->dl_mu_mimo_part_bw = uHECapInfo.he_cap.dl_mu_mimo_part_bw;
1426 	pDot11f->ppet_present = uHECapInfo.he_cap.ppet_present;
1427 	pDot11f->srp = uHECapInfo.he_cap.srp;
1428 	pDot11f->power_boost = uHECapInfo.he_cap.power_boost;
1429 
1430 	pDot11f->he_ltf_800_gi_4x = uHECapInfo.he_cap.he_ltf_800_gi_4x;
1431 	pDot11f->max_nc = uHECapInfo.he_cap.max_nc;
1432 	pDot11f->er_he_ltf_800_gi_4x = uHECapInfo.he_cap.er_he_ltf_800_gi_4x;
1433 	pDot11f->he_ppdu_20_in_40Mhz_2G =
1434 				uHECapInfo.he_cap.he_ppdu_20_in_40Mhz_2G;
1435 	pDot11f->he_ppdu_20_in_160_80p80Mhz =
1436 				uHECapInfo.he_cap.he_ppdu_20_in_160_80p80Mhz;
1437 	pDot11f->he_ppdu_80_in_160_80p80Mhz =
1438 				uHECapInfo.he_cap.he_ppdu_80_in_160_80p80Mhz;
1439 	pDot11f->er_1x_he_ltf_gi =
1440 				uHECapInfo.he_cap.er_1x_he_ltf_gi;
1441 	pDot11f->midamble_tx_rx_1x_he_ltf =
1442 				uHECapInfo.he_cap.midamble_tx_rx_1x_he_ltf;
1443 	pDot11f->reserved2 = uHECapInfo.he_cap.reserved2;
1444 
1445 	pDot11f->rx_he_mcs_map_lt_80 = uHECapInfo.he_cap.rx_he_mcs_map_lt_80;
1446 	pDot11f->tx_he_mcs_map_lt_80 = uHECapInfo.he_cap.tx_he_mcs_map_lt_80;
1447 	if (pDot11f->chan_width_2) {
1448 		*((uint16_t *)pDot11f->rx_he_mcs_map_160) =
1449 			uHECapInfo.he_cap.rx_he_mcs_map_160;
1450 		*((uint16_t *)pDot11f->tx_he_mcs_map_160) =
1451 			uHECapInfo.he_cap.tx_he_mcs_map_160;
1452 	}
1453 	if (pDot11f->chan_width_3) {
1454 		*((uint16_t *)pDot11f->rx_he_mcs_map_80_80) =
1455 			uHECapInfo.he_cap.rx_he_mcs_map_80_80;
1456 		*((uint16_t *)pDot11f->tx_he_mcs_map_80_80) =
1457 			uHECapInfo.he_cap.tx_he_mcs_map_80_80;
1458 	}
1459 
1460 	return QDF_STATUS_SUCCESS;
1461 }
1462 
1463 static void lim_tdls_check_and_force_he_ldpc_cap(struct pe_session *pe_session,
1464 						 tDphHashNode *sta)
1465 {
1466 	if (pe_session && sta->he_config.present)
1467 		lim_check_and_force_he_ldpc_cap(pe_session, &sta->he_config);
1468 }
1469 
1470 static enum phy_ch_width lim_tdls_get_he_ch_width(struct pe_session *pe_session,
1471 						  tDot11fIEhe_cap *he_cap)
1472 {
1473 	enum phy_ch_width ch_width = CH_WIDTH_20MHZ;
1474 
1475 	if (wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) &&
1476 	    he_cap->chan_width_0)
1477 		return CH_WIDTH_40MHZ;
1478 
1479 	if (he_cap->chan_width_3)
1480 		ch_width = CH_WIDTH_80P80MHZ;
1481 	else if (he_cap->chan_width_2)
1482 		ch_width = CH_WIDTH_160MHZ;
1483 	else if (he_cap->chan_width_1)
1484 		ch_width = CH_WIDTH_80MHZ;
1485 
1486 	return ch_width;
1487 }
1488 
1489 static void lim_tdls_update_node_he_caps(struct mac_context *mac,
1490 					 struct tdls_add_sta_req *add_sta_req,
1491 					 tDphHashNode *sta,
1492 					 struct pe_session *pe_session,
1493 					 bool wide_band_peer)
1494 {
1495 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1496 
1497 	pe_debug("Populating HE IEs");
1498 	status = lim_tdls_populate_dot11f_he_caps(mac, add_sta_req,
1499 						  &sta->he_config);
1500 
1501 	if (status != QDF_STATUS_SUCCESS)
1502 		return;
1503 
1504 	if (!sta->he_config.present)
1505 		return;
1506 
1507 	sta->mlmStaContext.he_capable = 1;
1508 	lim_tdls_set_he_chan_width(mac, &sta->he_config, pe_session,
1509 				   wide_band_peer);
1510 	lim_log_he_cap(mac, &sta->he_config);
1511 	if (lim_is_he_6ghz_band(pe_session)) {
1512 		lim_tdls_populate_dot11f_6hgz_he_caps(mac, add_sta_req,
1513 						      &sta->he_6g_band_cap);
1514 		/*
1515 		 * In 6Ghz, vht and ht ie may not present, peer channel width
1516 		 * is populated while extracting HT and VHT cap itself. So,
1517 		 * incase of 6ghz fill the chan_width.
1518 		 */
1519 		lim_update_stads_he_6ghz_op(pe_session, sta);
1520 	}
1521 	sta->ch_width = lim_tdls_get_he_ch_width(pe_session,
1522 						 &sta->he_config);
1523 	pe_debug("sta->ch_width %d", sta->ch_width);
1524 }
1525 
1526 #else
1527 static void lim_tdls_fill_dis_rsp_he_cap(struct mac_context *mac,
1528 					 uint32_t selfDot11Mode,
1529 					 tDot11fTDLSDisRsp *tdls_dis_rsp,
1530 					 struct pe_session *pe_session)
1531 {
1532 }
1533 
1534 static void lim_tdls_fill_setup_req_he_cap(struct mac_context *mac,
1535 					   uint32_t selfDot11Mode,
1536 					   tDot11fTDLSSetupReq *tdls_setup_req,
1537 					   struct pe_session *pe_session)
1538 {
1539 }
1540 
1541 static void lim_tdls_fill_setup_rsp_he_cap(struct mac_context *mac,
1542 					   uint32_t selfDot11Mode,
1543 					   tDot11fTDLSSetupRsp *tdls_setup_rsp,
1544 					   struct pe_session *pe_session)
1545 {
1546 }
1547 
1548 static void lim_tdls_fill_setup_cnf_he_op(struct mac_context *mac,
1549 					  uint32_t peer_capability,
1550 					  tDot11fTDLSSetupCnf *tdls_setup_cnf,
1551 					  struct pe_session *pe_session)
1552 {
1553 }
1554 
1555 static void lim_tdls_populate_he_matching_rate_set(struct mac_context *mac_ctx,
1556 						   tpDphHashNode stads,
1557 						   uint8_t nss,
1558 						   struct pe_session *session)
1559 {
1560 }
1561 
1562 static void lim_tdls_update_node_he_caps(struct mac_context *mac,
1563 					 struct tdls_add_sta_req *add_sta_req,
1564 					 tDphHashNode *sta,
1565 					 struct pe_session *pe_session,
1566 					 bool wide_band_peer)
1567 {
1568 }
1569 
1570 static void lim_tdls_check_and_force_he_ldpc_cap(struct pe_session *pe_session,
1571 						 tDphHashNode *sta)
1572 {
1573 }
1574 
1575 #endif
1576 
1577 #ifdef WLAN_FEATURE_11BE
1578 static uint8_t *
1579 lim_ieee80211_pack_ehtcap_tdls(struct mac_context *mac,
1580 			       struct pe_session *pe_session, uint8_t *len)
1581 {
1582 	tDot11fIEhe_cap he_cap;
1583 	uint8_t *eht_cap_ie;
1584 	bool is_band_2g;
1585 	uint32_t self_mode;
1586 
1587 	if (!pe_session || !len)
1588 		return NULL;
1589 
1590 	eht_cap_ie = qdf_mem_malloc(WLAN_MAX_IE_LEN + 2);
1591 	if (!eht_cap_ie) {
1592 		pe_err("malloc failed for eht_cap_ie");
1593 		*len = 0;
1594 		return NULL;
1595 	}
1596 
1597 	is_band_2g = WLAN_REG_IS_24GHZ_CH_FREQ(pe_session->curr_op_freq);
1598 	self_mode = mac->mlme_cfg->dot11_mode.dot11_mode;
1599 	populate_dot11f_set_tdls_he_cap(mac, self_mode, &he_cap,
1600 					NULL, pe_session);
1601 
1602 	lim_ieee80211_pack_ehtcap(eht_cap_ie, pe_session->eht_config,
1603 				  he_cap, is_band_2g);
1604 
1605 	*len = eht_cap_ie[1] + 2;
1606 	return eht_cap_ie;
1607 }
1608 #else
1609 static uint8_t *
1610 lim_ieee80211_pack_ehtcap_tdls(struct mac_context *mac,
1611 			       struct pe_session *pe_session, uint8_t *len)
1612 {
1613 	if (!mac || !pe_session || !len)
1614 		return NULL;
1615 
1616 	*len = 0;
1617 	return NULL;
1618 }
1619 #endif
1620 
1621 /*
1622  * Send TDLS discovery response frame on direct link.
1623  */
1624 static QDF_STATUS lim_send_tdls_dis_rsp_frame(struct mac_context *mac,
1625 					      struct qdf_mac_addr peer_mac,
1626 					      uint8_t dialog,
1627 					      struct pe_session *pe_session,
1628 					      uint8_t *addIe,
1629 					      uint16_t addIeLen)
1630 {
1631 	tDot11fTDLSDisRsp *tdls_dis_rsp;
1632 	uint16_t caps = 0;
1633 	uint32_t status = 0;
1634 	uint32_t nPayload = 0;
1635 	uint32_t nBytes = 0;
1636 	uint8_t *pFrame;
1637 	void *pPacket;
1638 	QDF_STATUS qdf_status;
1639 	uint32_t selfDot11Mode;
1640 	uint8_t  selfaddr[QDF_MAC_ADDR_SIZE];
1641 /*  Placeholder to support different channel bonding mode of TDLS than AP. */
1642 /*  Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP */
1643 /*  To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE */
1644 /*  As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) */
1645 /*  uint32_t tdlsChannelBondingMode; */
1646 	uint8_t smeSessionId = 0;
1647 	uint16_t mlo_ie_len = 0;
1648 	uint8_t *eht_cap_ie = NULL, eht_cap_ie_len = 0;
1649 	uint16_t action;
1650 
1651 	if (!pe_session) {
1652 		pe_err("pe_session is NULL");
1653 		return QDF_STATUS_E_FAILURE;
1654 	}
1655 
1656 	tdls_dis_rsp = qdf_mem_malloc(sizeof(*tdls_dis_rsp));
1657 	if (!tdls_dis_rsp) {
1658 		pe_err("memory allocation failed for DisRsp");
1659 		return QDF_STATUS_E_NOMEM;
1660 	}
1661 
1662 	smeSessionId = pe_session->smeSessionId;
1663 
1664 	/*
1665 	 * The scheme here is to fill out a 'tDot11fProbeRequest' structure
1666 	 * and then hand it off to 'dot11f_pack_probe_request' (for
1667 	 * serialization).
1668 	 */
1669 
1670 	/*
1671 	 * setup Fixed fields,
1672 	 */
1673 	tdls_dis_rsp->Category.category = ACTION_CATEGORY_PUBLIC;
1674 	tdls_dis_rsp->Action.action = TDLS_DISCOVERY_RESPONSE;
1675 	tdls_dis_rsp->DialogToken.token = dialog;
1676 
1677 	populate_dot11f_link_iden(mac, pe_session,
1678 				  LINK_IDEN_ADDR_OFFSET(tdls_dis_rsp),
1679 				  peer_mac, TDLS_RESPONDER);
1680 
1681 	if (lim_get_capability_info(mac, &caps, pe_session) !=
1682 	    QDF_STATUS_SUCCESS) {
1683 		/*
1684 		 * Could not get Capabilities value
1685 		 * from CFG. Log error.
1686 		 */
1687 		pe_err("could not retrieve Capabilities value");
1688 	}
1689 	swap_bit_field16(caps, (uint16_t *)&tdls_dis_rsp->Capabilities);
1690 
1691 	/* populate supported rate and ext supported rate IE */
1692 	if (QDF_STATUS_E_FAILURE == populate_dot11f_rates_tdls(mac,
1693 					&tdls_dis_rsp->SuppRates,
1694 					&tdls_dis_rsp->ExtSuppRates,
1695 					wlan_reg_freq_to_chan(
1696 					mac->pdev, pe_session->curr_op_freq)))
1697 		pe_err("could not populate supported data rates");
1698 
1699 	/* populate extended capability IE */
1700 	populate_dot11f_tdls_ext_capability(mac,
1701 					    pe_session,
1702 					    &tdls_dis_rsp->ExtCap);
1703 
1704 	selfDot11Mode = mac->mlme_cfg->dot11_mode.dot11_mode;
1705 
1706 	/* Populate HT/VHT Capabilities */
1707 	populate_dot11f_tdls_ht_vht_cap(mac, selfDot11Mode,
1708 					&tdls_dis_rsp->HTCaps,
1709 					&tdls_dis_rsp->VHTCaps,
1710 					pe_session);
1711 
1712 	lim_tdls_fill_dis_rsp_he_cap(mac, selfDot11Mode, tdls_dis_rsp,
1713 				     pe_session);
1714 
1715 	if (wlan_vdev_mlme_is_mlo_vdev(pe_session->vdev))
1716 		mlo_ie_len = lim_send_tdls_mgmt_frame_mlo(mac, pe_session);
1717 
1718 	if (lim_is_session_eht_capable(pe_session)) {
1719 		eht_cap_ie = lim_ieee80211_pack_ehtcap_tdls(mac, pe_session,
1720 							    &eht_cap_ie_len);
1721 		if (!eht_cap_ie) {
1722 			pe_err("malloc failed for eht_cap_ie");
1723 			qdf_mem_free(tdls_dis_rsp);
1724 			return QDF_STATUS_E_FAILURE;
1725 		}
1726 	}
1727 
1728 	/* Populate TDLS offchannel param only if offchannel is enabled
1729 	 * and TDLS Channel Switching is not prohibited by AP in ExtCap
1730 	 * IE in assoc/re-assoc response.
1731 	 */
1732 	if ((1 == mac->lim.gLimTDLSOffChannelEnabled) &&
1733 	    (!mlme_get_tdls_chan_switch_prohibited(pe_session->vdev))) {
1734 		populate_dot11f_tdls_offchannel_params(mac, pe_session,
1735 					&tdls_dis_rsp->SuppChannels,
1736 					&tdls_dis_rsp->SuppOperatingClasses);
1737 		if (mac->mlme_cfg->gen.band_capability != BIT(REG_BAND_2G)) {
1738 			tdls_dis_rsp->ht2040_bss_coexistence.present = 1;
1739 			tdls_dis_rsp->ht2040_bss_coexistence.info_request = 1;
1740 		}
1741 	} else {
1742 		pe_debug("TDLS offchan not enabled, or channel switch prohibited by AP, gLimTDLSOffChannelEnabled: %d tdls_chan_swit_prohibited: %d",
1743 			mac->lim.gLimTDLSOffChannelEnabled,
1744 			mlme_get_tdls_chan_switch_prohibited(pe_session->vdev));
1745 	}
1746 	/*
1747 	 * now we pack it.  First, how much space are we going to need?
1748 	 */
1749 	status = dot11f_get_packed_tdls_dis_rsp_size(mac, tdls_dis_rsp,
1750 						     &nPayload);
1751 	if (DOT11F_FAILED(status)) {
1752 		pe_err("Failed to calculate the packed size for a Discovery Response (0x%08x)",
1753 			status);
1754 		/* We'll fall back on the worst case scenario: */
1755 		nPayload = sizeof(tDot11fProbeRequest);
1756 	} else if (DOT11F_WARNED(status)) {
1757 		pe_warn("There were warnings while calculating the packed size for a Discovery Response (0x%08x)",
1758 			status);
1759 	}
1760 
1761 	/*
1762 	 * This frame is going out from PE as data frames with special ethertype
1763 	 * 89-0d.
1764 	 * 8 bytes of RFC 1042 header
1765 	 */
1766 
1767 	nBytes = nPayload + sizeof(tSirMacMgmtHdr) + addIeLen +
1768 		 eht_cap_ie_len + mlo_ie_len;
1769 
1770 	/* Ok-- try to allocate memory from MGMT PKT pool */
1771 	qdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
1772 				(void **)&pPacket);
1773 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1774 		pe_err("Failed to allocate %d bytes for a TDLS Discovery Request",
1775 			nBytes);
1776 		qdf_mem_free(eht_cap_ie);
1777 		qdf_mem_free(tdls_dis_rsp);
1778 		return QDF_STATUS_E_NOMEM;
1779 	}
1780 
1781 	/* zero out the memory */
1782 	qdf_mem_zero(pFrame, nBytes);
1783 
1784 	/*
1785 	 * IE formation, memory allocation is completed, Now form TDLS discovery
1786 	 * response frame
1787 	 */
1788 
1789 	/* Make public Action Frame */
1790 	lim_tdls_copy_self_mac(pe_session, selfaddr);
1791 	lim_populate_mac_header(mac, pFrame, SIR_MAC_MGMT_FRAME,
1792 				SIR_MAC_MGMT_ACTION, peer_mac.bytes,
1793 				selfaddr);
1794 
1795 	{
1796 		tpSirMacMgmtHdr pMacHdr;
1797 
1798 		pMacHdr = (tpSirMacMgmtHdr) pFrame;
1799 		pMacHdr->fc.toDS = ANI_TXDIR_IBSS;
1800 		pMacHdr->fc.powerMgmt = 0;
1801 		sir_copy_mac_addr(pMacHdr->bssId, pe_session->bssId);
1802 	}
1803 
1804 	status = dot11f_pack_tdls_dis_rsp(mac, tdls_dis_rsp, pFrame +
1805 					  sizeof(tSirMacMgmtHdr),
1806 					  nPayload, &nPayload);
1807 	if (DOT11F_FAILED(status)) {
1808 		pe_err("Failed to pack a TDLS discovery response (0x%08x)",
1809 			status);
1810 		cds_packet_free((void *)pPacket);
1811 		qdf_mem_free(eht_cap_ie);
1812 		qdf_mem_free(tdls_dis_rsp);
1813 		return QDF_STATUS_E_FAILURE;
1814 	} else if (DOT11F_WARNED(status)) {
1815 		pe_warn("There were warnings while packing TDLS Discovery Response (0x%08x)",
1816 			status);
1817 	}
1818 
1819 	if (eht_cap_ie_len) {
1820 		/* Copy the EHT IE to the end of the frame */
1821 		qdf_mem_copy(pFrame + sizeof(tSirMacMgmtHdr) + nPayload,
1822 			     eht_cap_ie, eht_cap_ie_len);
1823 		qdf_mem_free(eht_cap_ie);
1824 
1825 		nPayload += eht_cap_ie_len;
1826 	}
1827 
1828 	if (mlo_ie_len) {
1829 		qdf_status = lim_fill_complete_mlo_ie(pe_session, mlo_ie_len,
1830 						      pFrame +
1831 						      sizeof(tSirMacMgmtHdr) +
1832 						      nPayload);
1833 
1834 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
1835 			pe_debug("assemble ml ie error");
1836 			mlo_ie_len = 0;
1837 		}
1838 
1839 		nPayload += mlo_ie_len;
1840 	}
1841 
1842 	lim_cp_stats_cstats_log_disc_resp_evt(tdls_dis_rsp, pe_session);
1843 
1844 	qdf_mem_free(tdls_dis_rsp);
1845 
1846 	if (0 != addIeLen) {
1847 		pe_debug("Copy Additional Ie Len: %d", addIeLen);
1848 		qdf_mem_copy(pFrame + sizeof(tSirMacMgmtHdr) + nPayload, addIe,
1849 			     addIeLen);
1850 	}
1851 	pe_debug("[TDLS] action: %d (%s) -DIRECT-> OTA peer="QDF_MAC_ADDR_FMT,
1852 		TDLS_DISCOVERY_RESPONSE,
1853 		lim_trace_tdls_action_string(TDLS_DISCOVERY_RESPONSE),
1854 		QDF_MAC_ADDR_REF(peer_mac.bytes));
1855 
1856 	mac->lim.tdls_frm_session_id = pe_session->smeSessionId;
1857 	lim_diag_mgmt_tx_event_report(mac, (tpSirMacMgmtHdr) pFrame,
1858 				      pe_session, QDF_STATUS_SUCCESS,
1859 				      QDF_STATUS_SUCCESS);
1860 	/*
1861 	 * Transmit Discovery response and watch if this is delivered to
1862 	 * peer STA.
1863 	 */
1864 	/* In CLD 2.0, pass Discovery Response as mgmt frame so that
1865 	 * wma does not do header conversion to 802.3 before calling tx/rx
1866 	 * routine and subsequenly target also sends frame as is OTA
1867 	 */
1868 	action = ACTION_CATEGORY_PUBLIC << 8 | TDLS_DISCOVERY_RESPONSE;
1869 	qdf_status = wma_tx_frameWithTxComplete(mac, pPacket, (uint16_t) nBytes,
1870 					      TXRX_FRM_802_11_MGMT,
1871 					      ANI_TXDIR_IBSS,
1872 					      0,
1873 					      lim_tx_complete, pFrame,
1874 					      lim_mgmt_tdls_tx_complete,
1875 					      HAL_USE_SELF_STA_REQUESTED_MASK,
1876 					      smeSessionId, false, 0,
1877 					      RATEID_DEFAULT, 0,
1878 					      action);
1879 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1880 		mac->lim.tdls_frm_session_id = NO_SESSION;
1881 		pe_err("could not send TDLS Discovery Response frame!");
1882 		return QDF_STATUS_E_FAILURE;
1883 	}
1884 
1885 	return QDF_STATUS_SUCCESS;
1886 }
1887 
1888 /*
1889  * This static function is currently used by lim_send_tdls_link_setup_req_frame and
1890  * lim_send_tdls_setup_rsp_frame to populate the AID if device is 11ac capable.
1891  */
1892 static void populate_dotf_tdls_vht_aid(struct mac_context *mac, uint32_t selfDot11Mode,
1893 				       struct qdf_mac_addr peerMac,
1894 				       tDot11fIEAID *Aid,
1895 				       struct pe_session *pe_session)
1896 {
1897 	if (((wlan_reg_freq_to_chan(mac->pdev, pe_session->curr_op_freq) <=
1898 		SIR_11B_CHANNEL_END) &&
1899 	     mac->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band) ||
1900 	    (wlan_reg_freq_to_chan(mac->pdev, pe_session->curr_op_freq) >=
1901 		SIR_11B_CHANNEL_END)) {
1902 		if (IS_DOT11_MODE_VHT(selfDot11Mode) &&
1903 		    IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) {
1904 
1905 			uint16_t aid;
1906 			tpDphHashNode sta;
1907 
1908 			sta =
1909 				dph_lookup_hash_entry(mac, peerMac.bytes, &aid,
1910 						      &pe_session->dph.
1911 						      dphHashTable);
1912 			if (sta) {
1913 				Aid->present = 1;
1914 				Aid->assocId = aid | LIM_AID_MASK;      /* set bit 14 and 15 1's */
1915 			} else {
1916 				Aid->present = 0;
1917 				pe_err("sta is NULL for "
1918 					   QDF_MAC_ADDR_FMT,
1919 					QDF_MAC_ADDR_REF(peerMac.bytes));
1920 			}
1921 		}
1922 	} else {
1923 		Aid->present = 0;
1924 		pe_warn("Vht not enable from ini for 2.4GHz");
1925 	}
1926 }
1927 
1928 #ifdef CONFIG_HL_SUPPORT
1929 
1930 /**
1931  * wma_tx_frame_with_tx_complete_send() - Send tx frames on Direct link or AP link
1932  *				       depend on reason code
1933  * @mac: pointer to MAC Sirius parameter structure
1934  * @pPacket: pointer to mgmt packet
1935  * @nBytes: number of bytes to send
1936  * @tid:tid value for AC
1937  * @pFrame: pointer to tdls frame
1938  * @smeSessionId:session id
1939  * @flag: tdls flag
1940  *
1941  * Send TDLS Teardown frame on Direct link or AP link, depends on reason code.
1942  *
1943  * Return: None
1944  */
1945 static inline QDF_STATUS
1946 wma_tx_frame_with_tx_complete_send(struct mac_context *mac, void *pPacket,
1947 				uint16_t nBytes,
1948 				uint8_t tid,
1949 				uint8_t *pFrame,
1950 				uint8_t smeSessionId, bool flag)
1951 {
1952 	return wma_tx_frameWithTxComplete(mac, pPacket,
1953 					  (uint16_t) nBytes,
1954 					  TXRX_FRM_802_11_DATA,
1955 					  ANI_TXDIR_TODS,
1956 					  tid,
1957 					  lim_tx_complete, pFrame,
1958 					  lim_mgmt_tdls_tx_complete,
1959 					  HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME
1960 					  | HAL_USE_PEER_STA_REQUESTED_MASK,
1961 					  smeSessionId, flag, 0,
1962 					  RATEID_DEFAULT, 0, 0);
1963 }
1964 #else
1965 
1966 static inline QDF_STATUS
1967 wma_tx_frame_with_tx_complete_send(struct mac_context *mac, void *pPacket,
1968 				uint16_t nBytes,
1969 				uint8_t tid,
1970 				uint8_t *pFrame,
1971 				uint8_t smeSessionId, bool flag)
1972 {
1973 	return wma_tx_frameWithTxComplete(mac, pPacket,
1974 					  (uint16_t) nBytes,
1975 					  TXRX_FRM_802_11_DATA,
1976 					  ANI_TXDIR_TODS,
1977 					  tid,
1978 					  lim_tx_complete, pFrame,
1979 					  lim_mgmt_tdls_tx_complete,
1980 					  HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME
1981 					  | HAL_USE_PEER_STA_REQUESTED_MASK,
1982 					  smeSessionId, false, 0,
1983 					  RATEID_DEFAULT, 0, 0);
1984 }
1985 #endif
1986 
1987 static
1988 bool lim_is_wide_band_set(uint8_t *ext_capability)
1989 {
1990 	struct s_ext_cap *p_ext_cap = (struct s_ext_cap *)ext_capability;
1991 
1992 	if (!p_ext_cap)
1993 		return false;
1994 
1995 	pe_debug("p_ext_cap->tdls_wider_bw %d", p_ext_cap->tdls_wider_bw);
1996 	return p_ext_cap->tdls_wider_bw;
1997 }
1998 
1999 /*
2000  * TDLS setup Request frame on AP link
2001  */
2002 static
2003 QDF_STATUS lim_send_tdls_link_setup_req_frame(struct mac_context *mac,
2004 					      struct qdf_mac_addr peer_mac,
2005 					      uint8_t dialog,
2006 					      struct pe_session *pe_session,
2007 					      uint8_t *addIe,
2008 					      uint16_t addIeLen,
2009 					      enum wifi_traffic_ac ac)
2010 {
2011 	tDot11fTDLSSetupReq *tdls_setup_req;
2012 	uint16_t caps = 0;
2013 	uint32_t status = 0;
2014 	uint32_t payload = 0;
2015 	uint32_t nbytes = 0;
2016 	uint32_t header_offset = 0;
2017 	uint8_t vdev_id;
2018 	uint8_t *frame;
2019 	void *packet;
2020 	QDF_STATUS qdf_status;
2021 	uint32_t selfDot11Mode;
2022 	uint8_t smeSessionId = 0;
2023 	uint8_t sp_length = 0;
2024 	uint16_t mlo_ie_len = 0;
2025 	uint8_t *eht_cap_ie = NULL, eht_cap_ie_len = 0;
2026 
2027 /*  Placeholder to support different channel bonding mode of TDLS than AP. */
2028 /*  Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP */
2029 /*  To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE */
2030 /*  As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) */
2031 /*  uint32_t tdlsChannelBondingMode; */
2032 
2033 	if (!pe_session) {
2034 		pe_err("pe_session is NULL");
2035 		return QDF_STATUS_E_FAILURE;
2036 	}
2037 
2038 	tdls_setup_req = qdf_mem_malloc(sizeof(*tdls_setup_req));
2039 	if (!tdls_setup_req) {
2040 		pe_err("memory allocation failed for SetupReq");
2041 		return QDF_STATUS_E_NOMEM;
2042 	}
2043 
2044 	/*
2045 	 * The scheme here is to fill out a 'tDot11fProbeRequest' structure
2046 	 * and then hand it off to 'dot11f_pack_probe_request' (for
2047 	 * serialization).
2048 	 */
2049 	smeSessionId = pe_session->smeSessionId;
2050 
2051 	tdls_setup_req->Category.category = ACTION_CATEGORY_TDLS;
2052 	tdls_setup_req->Action.action = TDLS_SETUP_REQUEST;
2053 	tdls_setup_req->DialogToken.token = dialog;
2054 
2055 	populate_dot11f_link_iden(mac, pe_session,
2056 				  &tdls_setup_req->LinkIdentifier, peer_mac,
2057 				  TDLS_INITIATOR);
2058 
2059 	if (lim_get_capability_info(mac, &caps, pe_session) !=
2060 	    QDF_STATUS_SUCCESS) {
2061 		/*
2062 		 * Could not get Capabilities value
2063 		 * from CFG. Log error.
2064 		 */
2065 		pe_err("could not retrieve Capabilities value");
2066 	}
2067 	swap_bit_field16(caps, (uint16_t *)&tdls_setup_req->Capabilities);
2068 
2069 	/* populate supported rate and ext supported rate IE */
2070 	if (QDF_STATUS_E_FAILURE == populate_dot11f_rates_tdls(mac,
2071 					&tdls_setup_req->SuppRates,
2072 					&tdls_setup_req->ExtSuppRates,
2073 					wlan_reg_freq_to_chan(
2074 					mac->pdev, pe_session->curr_op_freq)))
2075 		pe_err("could not populate supported data rates");
2076 
2077 	/* Populate extended capability IE */
2078 	populate_dot11f_tdls_ext_capability(mac,
2079 					    pe_session,
2080 					    &tdls_setup_req->ExtCap);
2081 
2082 	if (1 == mac->lim.gLimTDLSWmmMode) {
2083 
2084 		pe_debug("populate WMM IE in Setup Request Frame");
2085 		sp_length = mac->mlme_cfg->wmm_params.max_sp_length;
2086 		/* include WMM IE */
2087 		tdls_setup_req->WMMInfoStation.version = SIR_MAC_OUI_VERSION_1;
2088 		tdls_setup_req->WMMInfoStation.acvo_uapsd =
2089 			(mac->lim.gLimTDLSUapsdMask & 0x01);
2090 		tdls_setup_req->WMMInfoStation.acvi_uapsd =
2091 			((mac->lim.gLimTDLSUapsdMask & 0x02) >> 1);
2092 		tdls_setup_req->WMMInfoStation.acbk_uapsd =
2093 			((mac->lim.gLimTDLSUapsdMask & 0x04) >> 2);
2094 		tdls_setup_req->WMMInfoStation.acbe_uapsd =
2095 			((mac->lim.gLimTDLSUapsdMask & 0x08) >> 3);
2096 		tdls_setup_req->WMMInfoStation.max_sp_length = sp_length;
2097 		tdls_setup_req->WMMInfoStation.present = 1;
2098 	} else {
2099 		/*
2100 		 * TODO: we need to see if we have to support conditions where
2101 		 * we have EDCA parameter info element is needed a) if we need
2102 		 * different QOS parameters for off channel operations or QOS
2103 		 * is not supported on AP link and we wanted to QOS on direct
2104 		 * link.
2105 		 */
2106 
2107 		/* Populate QOS info, needed for Peer U-APSD session */
2108 
2109 		/*
2110 		 * TODO: Now hardcoded, since populate_dot11f_qos_caps_station()
2111 		 * depends on AP's capability, and TDLS doesn't want to depend
2112 		 * on AP's capability
2113 		 */
2114 
2115 		pe_debug("populate QOS IE in Setup Request Frame");
2116 		tdls_setup_req->QOSCapsStation.present = 1;
2117 		tdls_setup_req->QOSCapsStation.max_sp_length = 0;
2118 		tdls_setup_req->QOSCapsStation.qack = 0;
2119 		tdls_setup_req->QOSCapsStation.acbe_uapsd =
2120 			((mac->lim.gLimTDLSUapsdMask & 0x08) >> 3);
2121 		tdls_setup_req->QOSCapsStation.acbk_uapsd =
2122 			((mac->lim.gLimTDLSUapsdMask & 0x04) >> 2);
2123 		tdls_setup_req->QOSCapsStation.acvi_uapsd =
2124 			((mac->lim.gLimTDLSUapsdMask & 0x02) >> 1);
2125 		tdls_setup_req->QOSCapsStation.acvo_uapsd =
2126 			(mac->lim.gLimTDLSUapsdMask & 0x01);
2127 	}
2128 
2129 	/*
2130 	 * we will always try to init TDLS link with 11n capabilities
2131 	 * let TDLS setup response to come, and we will set our caps based
2132 	 * of peer caps
2133 	 */
2134 
2135 	selfDot11Mode =  mac->mlme_cfg->dot11_mode.dot11_mode;
2136 
2137 	/* Populate HT/VHT Capabilities */
2138 
2139 	populate_dot11f_tdls_ht_vht_cap(mac, selfDot11Mode,
2140 					&tdls_setup_req->HTCaps,
2141 					&tdls_setup_req->VHTCaps,
2142 					pe_session);
2143 	lim_tdls_fill_setup_req_he_cap(mac, selfDot11Mode, tdls_setup_req,
2144 				       pe_session);
2145 	/* Populate AID */
2146 	populate_dotf_tdls_vht_aid(mac, selfDot11Mode, peer_mac,
2147 				   &tdls_setup_req->AID, pe_session);
2148 
2149 	if (wlan_vdev_mlme_is_mlo_vdev(pe_session->vdev))
2150 		mlo_ie_len = lim_send_tdls_mgmt_frame_mlo(mac, pe_session);
2151 
2152 	if (lim_is_session_eht_capable(pe_session)) {
2153 		eht_cap_ie = lim_ieee80211_pack_ehtcap_tdls(mac, pe_session,
2154 							    &eht_cap_ie_len);
2155 		if (!eht_cap_ie) {
2156 			pe_err("malloc failed for eht_cap_ie");
2157 			qdf_mem_free(tdls_setup_req);
2158 			return QDF_STATUS_E_FAILURE;
2159 		}
2160 	}
2161 
2162 	/* Populate TDLS offchannel param only if offchannel is enabled
2163 	 * and TDLS Channel Switching is not prohibited by AP in ExtCap
2164 	 * IE in assoc/re-assoc response.
2165 	 */
2166 	if ((1 == mac->lim.gLimTDLSOffChannelEnabled) &&
2167 	    (!mlme_get_tdls_chan_switch_prohibited(pe_session->vdev))) {
2168 		populate_dot11f_tdls_offchannel_params(mac, pe_session,
2169 					&tdls_setup_req->SuppChannels,
2170 					&tdls_setup_req->SuppOperatingClasses);
2171 		if (mac->mlme_cfg->gen.band_capability != BIT(REG_BAND_2G)) {
2172 			tdls_setup_req->ht2040_bss_coexistence.present = 1;
2173 			tdls_setup_req->ht2040_bss_coexistence.info_request = 1;
2174 		}
2175 	} else {
2176 		pe_debug("TDLS offchan not enabled, or channel switch prohibited by AP, gLimTDLSOffChannelEnabled: %d tdls_chan_swit_prohibited: %d",
2177 			mac->lim.gLimTDLSOffChannelEnabled,
2178 			mlme_get_tdls_chan_switch_prohibited(pe_session->vdev));
2179 	}
2180 	/*
2181 	 * now we pack it.  First, how much space are we going to need?
2182 	 */
2183 	status = dot11f_get_packed_tdls_setup_req_size(mac, tdls_setup_req,
2184 						       &payload);
2185 	if (DOT11F_FAILED(status)) {
2186 		pe_err("Failed to calculate the packed size for a Setup Request (0x%08x)",
2187 			status);
2188 		/* We'll fall back on the worst case scenario: */
2189 		payload = sizeof(tDot11fProbeRequest);
2190 	} else if (DOT11F_WARNED(status)) {
2191 		pe_warn("There were warnings while calculating the packed size for a Setup Request (0x%08x)",
2192 			status);
2193 	}
2194 
2195 	/*
2196 	 * This frame is going out from PE as data frames with special ethertype
2197 	 * 89-0d.
2198 	 * 8 bytes of RFC 1042 header
2199 	 */
2200 
2201 	nbytes = payload + ((IS_QOS_ENABLED(pe_session))
2202 			     ? sizeof(tSirMacDataHdr3a) :
2203 			     sizeof(tSirMacMgmtHdr))
2204 		 + sizeof(eth_890d_header)
2205 		 + PAYLOAD_TYPE_TDLS_SIZE + addIeLen + eht_cap_ie_len
2206 		 + mlo_ie_len;
2207 
2208 	/* Ok-- try to allocate memory from MGMT PKT pool */
2209 	qdf_status = cds_packet_alloc((uint16_t)nbytes, (void **)&frame,
2210 				      (void **)&packet);
2211 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2212 		pe_err("Failed to allocate %d bytes for a TDLS Setup Request",
2213 			nbytes);
2214 		qdf_mem_free(eht_cap_ie);
2215 		qdf_mem_free(tdls_setup_req);
2216 		return QDF_STATUS_E_NOMEM;
2217 	}
2218 
2219 	/* zero out the memory */
2220 	qdf_mem_zero(frame, nbytes);
2221 
2222 	/*
2223 	 * IE formation, memory allocation is completed, Now form TDLS discovery
2224 	 * request frame
2225 	 */
2226 
2227 	/* fill out the buffer descriptor */
2228 
2229 	header_offset = lim_prepare_tdls_frame_header(mac, frame,
2230 				&tdls_setup_req->LinkIdentifier,
2231 				TDLS_LINK_AP, TDLS_INITIATOR,
2232 				(ac == WIFI_AC_VI) ? TID_AC_VI : TID_AC_BK,
2233 				pe_session);
2234 
2235 	pe_debug("SupportedChnlWidth: %x rxMCSMap: %x rxMCSMap: %x txSupDataRate: %x",
2236 		tdls_setup_req->VHTCaps.supportedChannelWidthSet,
2237 		tdls_setup_req->VHTCaps.rxMCSMap,
2238 		tdls_setup_req->VHTCaps.txMCSMap,
2239 		tdls_setup_req->VHTCaps.txSupDataRate);
2240 
2241 	status = dot11f_pack_tdls_setup_req(mac, tdls_setup_req,
2242 					    frame + header_offset,
2243 					    payload, &payload);
2244 
2245 	if (DOT11F_FAILED(status)) {
2246 		pe_err("Failed to pack a TDLS Setup request (0x%08x)",
2247 			status);
2248 		cds_packet_free((void *)packet);
2249 		qdf_mem_free(eht_cap_ie);
2250 		qdf_mem_free(tdls_setup_req);
2251 		return QDF_STATUS_E_FAILURE;
2252 	} else if (DOT11F_WARNED(status)) {
2253 		pe_warn("There were warnings while packing TDLS Setup Request (0x%08x)",
2254 			status);
2255 	}
2256 
2257 	lim_cp_stats_cstats_log_setup_req_evt(tdls_setup_req, pe_session);
2258 
2259 	qdf_mem_free(tdls_setup_req);
2260 
2261 	/* Copy the additional IE. */
2262 	/* TODO : addIe is added at the end of the frame. This means it doesn't */
2263 	/* follow the order. This should be ok, but we should consider changing this */
2264 	/* if there is any IOT issue. */
2265 	if (addIeLen != 0) {
2266 		pe_debug("Copy Additional Ie Len = %d", addIeLen);
2267 		qdf_mem_copy(frame + header_offset + payload, addIe,
2268 			     addIeLen);
2269 		payload += addIeLen;
2270 	}
2271 
2272 	if (eht_cap_ie_len) {
2273 		/* Copy the EHT IE to the end of the frame */
2274 		qdf_mem_copy(frame + header_offset + payload,
2275 			     eht_cap_ie, eht_cap_ie_len);
2276 		qdf_mem_free(eht_cap_ie);
2277 
2278 		payload += eht_cap_ie_len;
2279 	}
2280 
2281 	if (mlo_ie_len) {
2282 		qdf_status = lim_fill_complete_mlo_ie(pe_session, mlo_ie_len,
2283 						      frame + header_offset +
2284 						      payload);
2285 
2286 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
2287 			pe_debug("assemble ml ie error");
2288 			mlo_ie_len = 0;
2289 		}
2290 
2291 		payload += mlo_ie_len;
2292 	}
2293 
2294 	pe_debug("[TDLS] action: %d (%s) -AP-> OTA peer="QDF_MAC_ADDR_FMT,
2295 		TDLS_SETUP_REQUEST,
2296 		lim_trace_tdls_action_string(TDLS_SETUP_REQUEST),
2297 		QDF_MAC_ADDR_REF(peer_mac.bytes));
2298 
2299 	mac->lim.tdls_frm_session_id = pe_session->smeSessionId;
2300 
2301 	vdev_id = lim_get_assoc_link_vdev_id(pe_session);
2302 
2303 	lim_diag_mgmt_tx_event_report(mac, (tpSirMacMgmtHdr) frame,
2304 				      pe_session, QDF_STATUS_SUCCESS,
2305 				      QDF_STATUS_SUCCESS);
2306 
2307 	qdf_status = wma_tx_frame_with_tx_complete_send(mac, packet,
2308 							(uint16_t)nbytes,
2309 							TID_AC_VI,
2310 							frame,
2311 							vdev_id, true);
2312 
2313 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2314 		mac->lim.tdls_frm_session_id = NO_SESSION;
2315 		pe_err("could not send TDLS Setup Request frame!");
2316 		return QDF_STATUS_E_FAILURE;
2317 	}
2318 
2319 	return QDF_STATUS_SUCCESS;
2320 
2321 }
2322 
2323 /*
2324  * Send TDLS Teardown frame on Direct link or AP link, depends on reason code.
2325  */
2326 static
2327 QDF_STATUS lim_send_tdls_teardown_frame(struct mac_context *mac,
2328 					struct qdf_mac_addr peer_mac,
2329 					uint16_t reason,
2330 					uint8_t responder,
2331 					struct pe_session *pe_session,
2332 					uint8_t *addIe, uint16_t addIeLen,
2333 					enum wifi_traffic_ac ac)
2334 {
2335 	tDot11fTDLSTeardown *teardown;
2336 	uint32_t status = 0;
2337 	uint32_t payload = 0;
2338 	uint32_t nbytes = 0;
2339 	uint32_t header_offset = 0;
2340 	uint8_t *frame;
2341 	void *packet;
2342 	uint8_t vdev_id;
2343 	QDF_STATUS qdf_status;
2344 #ifndef NO_PAD_TDLS_MIN_8023_SIZE
2345 	uint32_t padlen = 0;
2346 #endif
2347 	uint8_t smeSessionId = 0;
2348 	tpDphHashNode sta_ds;
2349 	uint16_t aid = 0;
2350 	uint8_t qos_mode = 0;
2351 	uint8_t tdls_link_type;
2352 
2353 	if (!pe_session) {
2354 		pe_err("pe_session is NULL");
2355 		return QDF_STATUS_E_FAILURE;
2356 	}
2357 
2358 	teardown = qdf_mem_malloc(sizeof(*teardown));
2359 	if (!teardown) {
2360 		pe_err("memory allocation failed for teardown");
2361 		return QDF_STATUS_E_NOMEM;
2362 	}
2363 
2364 	smeSessionId = pe_session->smeSessionId;
2365 	/*
2366 	 * The scheme here is to fill out a 'tDot11fProbeRequest' structure
2367 	 * and then hand it off to 'dot11f_pack_probe_request' (for
2368 	 * serialization).
2369 	 */
2370 	teardown->Category.category = ACTION_CATEGORY_TDLS;
2371 	teardown->Action.action = TDLS_TEARDOWN;
2372 	teardown->Reason.code = reason;
2373 
2374 	populate_dot11f_link_iden(mac, pe_session,
2375 				  LINK_IDEN_ADDR_OFFSET(teardown),
2376 				  peer_mac,
2377 				  (responder ==
2378 				   true) ? TDLS_RESPONDER : TDLS_INITIATOR);
2379 
2380 	/*
2381 	 * now we pack it.  First, how much space are we going to need?
2382 	 */
2383 	status = dot11f_get_packed_tdls_teardown_size(mac, teardown, &payload);
2384 	if (DOT11F_FAILED(status)) {
2385 		pe_err("Failed to calculate the packed size for a discovery Request (0x%08x)",
2386 			status);
2387 		/* We'll fall back on the worst case scenario: */
2388 		payload = sizeof(tDot11fProbeRequest);
2389 	} else if (DOT11F_WARNED(status)) {
2390 		pe_warn("There were warnings while calculating the packed size for a discovery Request (0x%08x)",
2391 			status);
2392 	}
2393 
2394 	/*
2395 	 * This frame is going out from PE as data frames with special ethertype
2396 	 * 89-0d.
2397 	 * 8 bytes of RFC 1042 header
2398 	 */
2399 	sta_ds = dph_lookup_hash_entry(mac, pe_session->bssId, &aid,
2400 					&pe_session->dph.dphHashTable);
2401 	if (sta_ds)
2402 		qos_mode = sta_ds->qosMode;
2403 
2404 	if (reason == REASON_TDLS_PEER_UNREACHABLE)
2405 		tdls_link_type = TDLS_LINK_AP;
2406 	else
2407 		tdls_link_type = TDLS_LINK_DIRECT;
2408 
2409 	nbytes = payload + sizeof(eth_890d_header) + PAYLOAD_TYPE_TDLS_SIZE;
2410 	nbytes += addIeLen;
2411 
2412 	if ((IS_QOS_ENABLED(pe_session) && tdls_link_type == TDLS_LINK_AP) ||
2413 	    (tdls_link_type == TDLS_LINK_DIRECT && qos_mode))
2414 		nbytes += sizeof(tSirMacDataHdr3a);
2415 	else
2416 		nbytes += sizeof(tSirMacMgmtHdr);
2417 
2418 #ifndef NO_PAD_TDLS_MIN_8023_SIZE
2419 	/* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64)
2420 	   Hence AP itself padding some bytes, which caused teardown packet is dropped at
2421 	   receiver side. To avoid such IOT issue, we added some extra bytes to meet data frame size >= 64
2422 	 */
2423 	if (payload + PAYLOAD_TYPE_TDLS_SIZE < MIN_IEEE_8023_SIZE) {
2424 		padlen =
2425 			MIN_IEEE_8023_SIZE - (payload + PAYLOAD_TYPE_TDLS_SIZE);
2426 
2427 		/*
2428 		 * if padlen is less than minimum vendorSpecific (5),
2429 		 * pad up to 5
2430 		 */
2431 		if (padlen < MIN_VENDOR_SPECIFIC_IE_SIZE)
2432 			padlen = MIN_VENDOR_SPECIFIC_IE_SIZE;
2433 
2434 		nbytes += padlen;
2435 	}
2436 #endif
2437 
2438 	/* Ok-- try to allocate memory from MGMT PKT pool */
2439 	qdf_status = cds_packet_alloc((uint16_t)nbytes, (void **)&frame,
2440 				      (void **)&packet);
2441 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2442 		pe_err("Failed to allocate %d bytes for a TDLS Teardown Frame.",
2443 			nbytes);
2444 		qdf_mem_free(teardown);
2445 		return QDF_STATUS_E_NOMEM;
2446 	}
2447 
2448 	/* zero out the memory */
2449 	qdf_mem_zero(frame, nbytes);
2450 
2451 	/*
2452 	 * IE formation, memory allocation is completed, Now form TDLS discovery
2453 	 * request frame
2454 	 */
2455 
2456 	/* fill out the buffer descriptor */
2457 	pe_debug("Reason of TDLS Teardown: %d", reason);
2458 	header_offset = lim_prepare_tdls_frame_header(mac, frame,
2459 			LINK_IDEN_ADDR_OFFSET(teardown),
2460 			(reason == REASON_TDLS_PEER_UNREACHABLE) ?
2461 			TDLS_LINK_AP : TDLS_LINK_DIRECT,
2462 			(responder == true) ? TDLS_RESPONDER : TDLS_INITIATOR,
2463 			(ac == WIFI_AC_VI) ? TID_AC_VI : TID_AC_BK,
2464 			pe_session);
2465 
2466 	status = dot11f_pack_tdls_teardown(mac, teardown, frame
2467 					   + header_offset, payload, &payload);
2468 
2469 	if (DOT11F_FAILED(status)) {
2470 		pe_err("Failed to pack a TDLS Teardown frame (0x%08x)",
2471 			status);
2472 		cds_packet_free((void *)packet);
2473 		qdf_mem_free(teardown);
2474 		return QDF_STATUS_E_FAILURE;
2475 	} else if (DOT11F_WARNED(status)) {
2476 		pe_warn("There were warnings while packing TDLS Teardown frame (0x%08x)",
2477 			status);
2478 	}
2479 
2480 	lim_cp_stats_cstats_log_tear_down_evt(teardown, pe_session);
2481 
2482 	qdf_mem_free(teardown);
2483 
2484 	if (addIeLen != 0) {
2485 		pe_debug("Copy Additional Ie Len = %d", addIeLen);
2486 		qdf_mem_copy(frame + header_offset + payload, addIe,
2487 			     addIeLen);
2488 	}
2489 #ifndef NO_PAD_TDLS_MIN_8023_SIZE
2490 	if (padlen != 0) {
2491 		/* QCOM VENDOR OUI = { 0x00, 0xA0, 0xC6, type = 0x0000 }; */
2492 		uint8_t *padVendorSpecific =
2493 			frame + header_offset + payload + addIeLen;
2494 		/* make QCOM_VENDOR_OUI, and type = 0x0000, and all the payload to be zero */
2495 		padVendorSpecific[0] = 221;
2496 		padVendorSpecific[1] = padlen - 2;
2497 		padVendorSpecific[2] = 0x00;
2498 		padVendorSpecific[3] = 0xA0;
2499 		padVendorSpecific[4] = 0xC6;
2500 
2501 		pe_debug("Padding Vendor Specific Ie Len = %d", padlen);
2502 
2503 		/* padding zero if more than 5 bytes are required */
2504 		if (padlen > MIN_VENDOR_SPECIFIC_IE_SIZE)
2505 			qdf_mem_zero(frame + header_offset + payload +
2506 				    addIeLen + MIN_VENDOR_SPECIFIC_IE_SIZE,
2507 				    padlen - MIN_VENDOR_SPECIFIC_IE_SIZE);
2508 	}
2509 #endif
2510 	pe_debug("[TDLS] vdev:%d action: %d (%s) -%s-> OTA peer="QDF_MAC_ADDR_FMT,
2511 		 pe_session->vdev_id, TDLS_TEARDOWN,
2512 		 lim_trace_tdls_action_string(TDLS_TEARDOWN),
2513 		 ((reason == REASON_TDLS_PEER_UNREACHABLE) ? "AP" : "DIRECT"),
2514 		 QDF_MAC_ADDR_REF(peer_mac.bytes));
2515 
2516 	mac->lim.tdls_frm_session_id = pe_session->smeSessionId;
2517 
2518 	vdev_id = lim_get_assoc_link_vdev_id(pe_session);
2519 
2520 	lim_diag_mgmt_tx_event_report(mac, (tpSirMacMgmtHdr)frame,
2521 				      pe_session, QDF_STATUS_SUCCESS,
2522 				      QDF_STATUS_SUCCESS);
2523 
2524 	qdf_status = wma_tx_frame_with_tx_complete_send(mac, packet,
2525 					(uint16_t)nbytes,
2526 					TID_AC_VI, frame, vdev_id,
2527 					(reason == REASON_TDLS_PEER_UNREACHABLE)
2528 					? true : false);
2529 
2530 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2531 		mac->lim.tdls_frm_session_id = NO_SESSION;
2532 		pe_err("could not send TDLS Teardown frame");
2533 		return QDF_STATUS_E_FAILURE;
2534 
2535 	}
2536 
2537 	return QDF_STATUS_SUCCESS;
2538 }
2539 
2540 /*
2541  * Send Setup RSP frame on AP link.
2542  */
2543 static QDF_STATUS
2544 lim_send_tdls_setup_rsp_frame(struct mac_context *mac,
2545 			      struct qdf_mac_addr peer_mac,
2546 			      uint8_t dialog,
2547 			      struct pe_session *pe_session,
2548 			      etdlsLinkSetupStatus setupStatus,
2549 			      uint8_t *addIe, uint16_t addIeLen,
2550 			      enum wifi_traffic_ac ac)
2551 {
2552 	tDot11fTDLSSetupRsp *setup_rsp;
2553 	uint32_t status = 0;
2554 	uint16_t caps = 0;
2555 	uint32_t nPayload = 0;
2556 	uint32_t header_offset = 0;
2557 	uint32_t nBytes = 0;
2558 	uint8_t *pFrame;
2559 	void *pPacket;
2560 	QDF_STATUS qdf_status;
2561 	uint32_t selfDot11Mode;
2562 	uint8_t max_sp_length = 0;
2563 	uint8_t vdev_id;
2564 /*  Placeholder to support different channel bonding mode of TDLS than AP. */
2565 /*  Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP */
2566 /*  To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE */
2567 /*  As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) */
2568 /*  uint32_t tdlsChannelBondingMode; */
2569 	uint8_t smeSessionId = 0;
2570 	uint16_t mlo_ie_len = 0;
2571 	uint8_t *eht_cap_ie = NULL, eht_cap_ie_len = 0;
2572 
2573 	if (!pe_session) {
2574 		pe_err("pe_session is NULL");
2575 		return QDF_STATUS_E_FAILURE;
2576 	}
2577 
2578 	setup_rsp = qdf_mem_malloc(sizeof(*setup_rsp));
2579 	if (!setup_rsp) {
2580 		pe_err("memory allocation failed for SetupRsp");
2581 		return QDF_STATUS_E_NOMEM;
2582 	}
2583 
2584 	smeSessionId = pe_session->smeSessionId;
2585 
2586 	/*
2587 	 * The scheme here is to fill out a 'tDot11fProbeRequest' structure
2588 	 * and then hand it off to 'dot11f_pack_probe_request' (for
2589 	 * serialization).
2590 	 */
2591 
2592 	/*
2593 	 * setup Fixed fields,
2594 	 */
2595 	setup_rsp->Category.category = ACTION_CATEGORY_TDLS;
2596 	setup_rsp->Action.action = TDLS_SETUP_RESPONSE;
2597 	setup_rsp->DialogToken.token = dialog;
2598 
2599 	populate_dot11f_link_iden(mac, pe_session,
2600 				  LINK_IDEN_ADDR_OFFSET(setup_rsp), peer_mac,
2601 				  TDLS_RESPONDER);
2602 
2603 	if (lim_get_capability_info(mac, &caps, pe_session) !=
2604 	    QDF_STATUS_SUCCESS) {
2605 		/*
2606 		 * Could not get Capabilities value
2607 		 * from CFG. Log error.
2608 		 */
2609 		pe_err("could not retrieve Capabilities value");
2610 	}
2611 	swap_bit_field16(caps, (uint16_t *)&setup_rsp->Capabilities);
2612 
2613 	if (QDF_STATUS_E_FAILURE == populate_dot11f_rates_tdls(mac,
2614 					&setup_rsp->SuppRates,
2615 					&setup_rsp->ExtSuppRates,
2616 					wlan_reg_freq_to_chan(
2617 					mac->pdev, pe_session->curr_op_freq)))
2618 		pe_err("could not populate supported data rates");
2619 
2620 	/* Populate extended capability IE */
2621 	populate_dot11f_tdls_ext_capability(mac,
2622 					    pe_session,
2623 					    &setup_rsp->ExtCap);
2624 
2625 	if (1 == mac->lim.gLimTDLSWmmMode) {
2626 
2627 		pe_debug("populate WMM IE in Setup Response frame");
2628 		max_sp_length = mac->mlme_cfg->wmm_params.max_sp_length;
2629 		/* include WMM IE */
2630 		setup_rsp->WMMInfoStation.version = SIR_MAC_OUI_VERSION_1;
2631 		setup_rsp->WMMInfoStation.acvo_uapsd =
2632 			(mac->lim.gLimTDLSUapsdMask & 0x01);
2633 		setup_rsp->WMMInfoStation.acvi_uapsd =
2634 			((mac->lim.gLimTDLSUapsdMask & 0x02) >> 1);
2635 		setup_rsp->WMMInfoStation.acbk_uapsd =
2636 			((mac->lim.gLimTDLSUapsdMask & 0x04) >> 2);
2637 		setup_rsp->WMMInfoStation.acbe_uapsd =
2638 			((mac->lim.gLimTDLSUapsdMask & 0x08) >> 3);
2639 		setup_rsp->WMMInfoStation.max_sp_length = max_sp_length;
2640 		setup_rsp->WMMInfoStation.present = 1;
2641 	} else {
2642 		/*
2643 		 * TODO: we need to see if we have to support conditions where
2644 		 * we have EDCA parameter info element is needed a) if we need
2645 		 * different QOS parameters for off channel operations or QOS
2646 		 * is not supported on AP link and we wanted to QOS on direct
2647 		 * link.
2648 		 */
2649 		/* Populate QOS info, needed for Peer U-APSD session */
2650 		/*
2651 		 * TODO: Now hardcoded, because
2652 		 * populate_dot11f_qos_caps_station() depends on AP's
2653 		 * capability, and TDLS doesn't want to depend on AP's
2654 		 * capability
2655 		 */
2656 		pe_debug("populate QOS IE in Setup Response frame");
2657 		setup_rsp->QOSCapsStation.present = 1;
2658 		setup_rsp->QOSCapsStation.max_sp_length = 0;
2659 		setup_rsp->QOSCapsStation.qack = 0;
2660 		setup_rsp->QOSCapsStation.acbe_uapsd =
2661 			((mac->lim.gLimTDLSUapsdMask & 0x08) >> 3);
2662 		setup_rsp->QOSCapsStation.acbk_uapsd =
2663 			((mac->lim.gLimTDLSUapsdMask & 0x04) >> 2);
2664 		setup_rsp->QOSCapsStation.acvi_uapsd =
2665 			((mac->lim.gLimTDLSUapsdMask & 0x02) >> 1);
2666 		setup_rsp->QOSCapsStation.acvo_uapsd =
2667 			(mac->lim.gLimTDLSUapsdMask & 0x01);
2668 	}
2669 
2670 	selfDot11Mode = mac->mlme_cfg->dot11_mode.dot11_mode;
2671 
2672 	/* Populate HT/VHT Capabilities */
2673 	populate_dot11f_tdls_ht_vht_cap(mac, selfDot11Mode, &setup_rsp->HTCaps,
2674 					&setup_rsp->VHTCaps, pe_session);
2675 
2676 	lim_tdls_fill_setup_rsp_he_cap(mac, selfDot11Mode, setup_rsp,
2677 				       pe_session);
2678 	/* Populate AID */
2679 	populate_dotf_tdls_vht_aid(mac, selfDot11Mode, peer_mac,
2680 				   &setup_rsp->AID, pe_session);
2681 
2682 	if (wlan_vdev_mlme_is_mlo_vdev(pe_session->vdev))
2683 		mlo_ie_len = lim_send_tdls_mgmt_frame_mlo(mac, pe_session);
2684 
2685 	if (lim_is_session_eht_capable(pe_session)) {
2686 		eht_cap_ie = lim_ieee80211_pack_ehtcap_tdls(mac, pe_session,
2687 							    &eht_cap_ie_len);
2688 		if (!eht_cap_ie) {
2689 			pe_err("malloc failed for eht_cap_ie");
2690 			qdf_mem_free(setup_rsp);
2691 			return QDF_STATUS_E_FAILURE;
2692 		}
2693 	}
2694 
2695 	/* Populate TDLS offchannel param only if offchannel is enabled
2696 	 * and TDLS Channel Switching is not prohibited by AP in ExtCap
2697 	 * IE in assoc/re-assoc response.
2698 	 */
2699 	if ((1 == mac->lim.gLimTDLSOffChannelEnabled) &&
2700 	    (!mlme_get_tdls_chan_switch_prohibited(pe_session->vdev))) {
2701 		populate_dot11f_tdls_offchannel_params(mac, pe_session,
2702 						    &setup_rsp->SuppChannels,
2703 						    &setup_rsp->
2704 						    SuppOperatingClasses);
2705 		if (mac->mlme_cfg->gen.band_capability != BIT(REG_BAND_2G)) {
2706 			setup_rsp->ht2040_bss_coexistence.present = 1;
2707 			setup_rsp->ht2040_bss_coexistence.info_request = 1;
2708 		}
2709 	} else {
2710 		pe_debug("TDLS offchan not enabled, or channel switch prohibited by AP, gLimTDLSOffChannelEnabled: %d tdls_chan_swit_prohibited: %d",
2711 			mac->lim.gLimTDLSOffChannelEnabled,
2712 			mlme_get_tdls_chan_switch_prohibited(pe_session->vdev));
2713 	}
2714 	setup_rsp->Status.status = setupStatus;
2715 	/*
2716 	 * now we pack it.  First, how much space are we going to need?
2717 	 */
2718 	status = dot11f_get_packed_tdls_setup_rsp_size(mac, setup_rsp,
2719 						       &nPayload);
2720 	if (DOT11F_FAILED(status)) {
2721 		pe_err("Failed to calculate the packed size for a Setup Response (0x%08x)",
2722 			status);
2723 		/* We'll fall back on the worst case scenario: */
2724 		nPayload = sizeof(tDot11fProbeRequest);
2725 	} else if (DOT11F_WARNED(status)) {
2726 		pe_warn("There were warnings while calculating the packed size for Setup Response (0x%08x)",
2727 			status);
2728 	}
2729 
2730 	/*
2731 	 * This frame is going out from PE as data frames with special ethertype
2732 	 * 89-0d.
2733 	 * 8 bytes of RFC 1042 header
2734 	 */
2735 
2736 	nBytes = nPayload + ((IS_QOS_ENABLED(pe_session))
2737 			     ? sizeof(tSirMacDataHdr3a) :
2738 			     sizeof(tSirMacMgmtHdr))
2739 		 + sizeof(eth_890d_header)
2740 		 + PAYLOAD_TYPE_TDLS_SIZE + addIeLen + eht_cap_ie_len
2741 		 + mlo_ie_len;
2742 
2743 	/* Ok-- try to allocate memory from MGMT PKT pool */
2744 	qdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
2745 				      (void **)&pPacket);
2746 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2747 		pe_err("Failed to allocate %d bytes for a TDLS Setup Response",
2748 			nBytes);
2749 		qdf_mem_free(eht_cap_ie);
2750 		qdf_mem_free(setup_rsp);
2751 		return QDF_STATUS_E_NOMEM;
2752 	}
2753 
2754 	/* zero out the memory */
2755 	qdf_mem_zero(pFrame, nBytes);
2756 
2757 	/*
2758 	 * IE formation, memory allocation is completed, Now form TDLS discovery
2759 	 * request frame
2760 	 */
2761 
2762 	/* fill out the buffer descriptor */
2763 
2764 	header_offset = lim_prepare_tdls_frame_header(mac, pFrame,
2765 			LINK_IDEN_ADDR_OFFSET(setup_rsp), TDLS_LINK_AP,
2766 			TDLS_RESPONDER,
2767 			(ac == WIFI_AC_VI) ? TID_AC_VI : TID_AC_BK,
2768 			pe_session);
2769 
2770 	pe_debug("SupportedChnlWidth: %x rxMCSMap: %x rxMCSMap: %x txSupDataRate: %x",
2771 		 setup_rsp->VHTCaps.supportedChannelWidthSet,
2772 		 setup_rsp->VHTCaps.rxMCSMap, setup_rsp->VHTCaps.txMCSMap,
2773 		 setup_rsp->VHTCaps.txSupDataRate);
2774 	status = dot11f_pack_tdls_setup_rsp(mac, setup_rsp,
2775 					    pFrame + header_offset,
2776 					    nPayload, &nPayload);
2777 
2778 	if (DOT11F_FAILED(status)) {
2779 		pe_err("Failed to pack a TDLS Setup Response (0x%08x)",
2780 			status);
2781 		cds_packet_free((void *)pPacket);
2782 		qdf_mem_free(eht_cap_ie);
2783 		qdf_mem_free(setup_rsp);
2784 		return QDF_STATUS_E_FAILURE;
2785 	} else if (DOT11F_WARNED(status)) {
2786 		pe_warn("There were warnings while packing TDLS Setup Response (0x%08x)",
2787 			status);
2788 	}
2789 
2790 	lim_cp_stats_cstats_log_setup_resp_evt(setup_rsp, pe_session);
2791 
2792 	qdf_mem_free(setup_rsp);
2793 
2794 	/* Copy the additional IE. */
2795 	/* TODO : addIe is added at the end of the frame. This means it doesn't */
2796 	/* follow the order. This should be ok, but we should consider changing this */
2797 	/* if there is any IOT issue. */
2798 	if (addIeLen != 0) {
2799 		qdf_mem_copy(pFrame + header_offset + nPayload, addIe,
2800 			     addIeLen);
2801 		nPayload += addIeLen;
2802 	}
2803 
2804 	if (eht_cap_ie_len) {
2805 		/* Copy the EHT IE to the end of the frame */
2806 		qdf_mem_copy(pFrame + header_offset + nPayload,
2807 			     eht_cap_ie, eht_cap_ie_len);
2808 		qdf_mem_free(eht_cap_ie);
2809 
2810 		nPayload += eht_cap_ie_len;
2811 	}
2812 
2813 	if (mlo_ie_len) {
2814 		qdf_status = lim_fill_complete_mlo_ie(pe_session, mlo_ie_len,
2815 						      pFrame + header_offset +
2816 						      nPayload);
2817 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
2818 			pe_debug("assemble ml ie error");
2819 			mlo_ie_len = 0;
2820 		}
2821 
2822 		nPayload += mlo_ie_len;
2823 	}
2824 
2825 	pe_debug("[TDLS] vdev:%d action: %d (%s) -AP-> OTA peer="QDF_MAC_ADDR_FMT,
2826 		 pe_session->vdev_id, TDLS_SETUP_RESPONSE,
2827 		 lim_trace_tdls_action_string(TDLS_SETUP_RESPONSE),
2828 		 QDF_MAC_ADDR_REF(peer_mac.bytes));
2829 
2830 	mac->lim.tdls_frm_session_id = pe_session->smeSessionId;
2831 	vdev_id = lim_get_assoc_link_vdev_id(pe_session);
2832 	lim_diag_mgmt_tx_event_report(mac, (tpSirMacMgmtHdr) pFrame,
2833 				      pe_session, QDF_STATUS_SUCCESS,
2834 				      QDF_STATUS_SUCCESS);
2835 
2836 	qdf_status = wma_tx_frame_with_tx_complete_send(mac, pPacket,
2837 						     (uint16_t) nBytes,
2838 						     TID_AC_VI,
2839 						     pFrame,
2840 						     vdev_id, true);
2841 
2842 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2843 		mac->lim.tdls_frm_session_id = NO_SESSION;
2844 		pe_err("could not send TDLS Dis Request frame!");
2845 		return QDF_STATUS_E_FAILURE;
2846 	}
2847 
2848 	return QDF_STATUS_SUCCESS;
2849 }
2850 
2851 /*
2852  * Send TDLS setup CNF frame on AP link
2853  */
2854 static
2855 QDF_STATUS lim_send_tdls_link_setup_cnf_frame(struct mac_context *mac,
2856 					      struct qdf_mac_addr peer_mac,
2857 					      uint8_t dialog,
2858 					      uint32_t peerCapability,
2859 					      struct pe_session *pe_session,
2860 					      uint8_t *addIe,
2861 					      uint16_t addIeLen,
2862 					      enum wifi_traffic_ac ac)
2863 {
2864 	tDot11fTDLSSetupCnf *setup_cnf;
2865 	uint32_t status = 0;
2866 	uint32_t nPayload = 0;
2867 	uint32_t nBytes = 0;
2868 	uint32_t header_offset = 0;
2869 	uint8_t *pFrame;
2870 	void *pPacket;
2871 	QDF_STATUS qdf_status;
2872 	uint8_t vdev_id;
2873 #ifndef NO_PAD_TDLS_MIN_8023_SIZE
2874 	uint32_t padLen = 0;
2875 #endif
2876 	uint8_t smeSessionId = 0;
2877 	uint16_t mlo_ie_len = 0;
2878 	uint8_t *eht_cap_ie = NULL, eht_cap_ie_len = 0;
2879 
2880 	if (!pe_session) {
2881 		pe_err("pe_session is NULL");
2882 		return QDF_STATUS_E_FAILURE;
2883 	}
2884 
2885 	setup_cnf = qdf_mem_malloc(sizeof(*setup_cnf));
2886 	if (!setup_cnf) {
2887 		pe_err("memory allocation failed for SetupCnf");
2888 		return QDF_STATUS_E_NOMEM;
2889 	}
2890 
2891 	/*
2892 	 * The scheme here is to fill out a 'tDot11fProbeRequest' structure
2893 	 * and then hand it off to 'dot11f_pack_probe_request' (for
2894 	 * serialization).  We start by zero-initializing the structure:
2895 	 */
2896 	smeSessionId = pe_session->smeSessionId;
2897 
2898 	/*
2899 	 * setup Fixed fields,
2900 	 */
2901 	setup_cnf->Category.category = ACTION_CATEGORY_TDLS;
2902 	setup_cnf->Action.action = TDLS_SETUP_CONFIRM;
2903 	setup_cnf->DialogToken.token = dialog;
2904 
2905 	populate_dot11f_link_iden(mac, pe_session,
2906 				  LINK_IDEN_ADDR_OFFSET(setup_cnf), peer_mac,
2907 				  TDLS_INITIATOR);
2908 	/*
2909 	 * TODO: we need to see if we have to support conditions where we have
2910 	 * EDCA parameter info element is needed a) if we need different QOS
2911 	 * parameters for off channel operations or QOS is not supported on
2912 	 * AP link and we wanted to QOS on direct link.
2913 	 */
2914 
2915 	/* Check self and peer WMM capable */
2916 	if ((1 == mac->lim.gLimTDLSWmmMode) &&
2917 	    (CHECK_BIT(peerCapability, TDLS_PEER_WMM_CAP))) {
2918 		pe_debug("populate WMM praram in Setup Confirm");
2919 		populate_dot11f_wmm_params(mac, &setup_cnf->WMMParams,
2920 					   pe_session);
2921 	}
2922 
2923 	/* Check peer is VHT capable */
2924 	if (CHECK_BIT(peerCapability, TDLS_PEER_VHT_CAP)) {
2925 		populate_dot11f_vht_operation(mac,
2926 					      pe_session,
2927 					      &setup_cnf->VHTOperation);
2928 		populate_dot11f_ht_info(mac, &setup_cnf->HTInfo, pe_session);
2929 	} else if (CHECK_BIT(peerCapability, TDLS_PEER_HT_CAP)) {       /* Check peer is HT capable */
2930 		populate_dot11f_ht_info(mac, &setup_cnf->HTInfo, pe_session);
2931 	}
2932 
2933 	lim_tdls_fill_setup_cnf_he_op(mac, peerCapability, setup_cnf,
2934 				      pe_session);
2935 
2936 	if (wlan_vdev_mlme_is_mlo_vdev(pe_session->vdev))
2937 		mlo_ie_len = lim_send_tdls_mgmt_frame_mlo(mac, pe_session);
2938 
2939 	if (lim_is_session_eht_capable(pe_session)) {
2940 		eht_cap_ie = lim_ieee80211_pack_ehtcap_tdls(mac, pe_session,
2941 							    &eht_cap_ie_len);
2942 		if (!eht_cap_ie) {
2943 			pe_err("malloc failed for eht_cap_ie");
2944 			qdf_mem_free(setup_cnf);
2945 			return QDF_STATUS_E_FAILURE;
2946 		}
2947 	}
2948 	/*
2949 	 * now we pack it.  First, how much space are we going to need?
2950 	 */
2951 	status = dot11f_get_packed_tdls_setup_cnf_size(mac, setup_cnf,
2952 						       &nPayload);
2953 	if (DOT11F_FAILED(status)) {
2954 		pe_err("Failed to calculate the packed size for a Setup Confirm (0x%08x)",
2955 			status);
2956 		/* We'll fall back on the worst case scenario: */
2957 		nPayload = sizeof(tDot11fProbeRequest);
2958 	} else if (DOT11F_WARNED(status)) {
2959 		pe_warn("There were warnings while calculating the packed size for Setup Confirm (0x%08x)",
2960 			status);
2961 	}
2962 
2963 	/*
2964 	 * This frame is going out from PE as data frames with special ethertype
2965 	 * 89-0d.
2966 	 * 8 bytes of RFC 1042 header
2967 	 */
2968 
2969 	nBytes = nPayload + ((IS_QOS_ENABLED(pe_session))
2970 			     ? sizeof(tSirMacDataHdr3a) :
2971 			     sizeof(tSirMacMgmtHdr))
2972 		 + sizeof(eth_890d_header)
2973 		 + PAYLOAD_TYPE_TDLS_SIZE + addIeLen + eht_cap_ie_len
2974 		 + mlo_ie_len;
2975 
2976 #ifndef NO_PAD_TDLS_MIN_8023_SIZE
2977 	/* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64)
2978 	   Hence AP itself padding some bytes, which caused teardown packet is dropped at
2979 	   receiver side. To avoid such IOT issue, we added some extra bytes to meet data frame size >= 64
2980 	 */
2981 	if (nPayload + PAYLOAD_TYPE_TDLS_SIZE < MIN_IEEE_8023_SIZE) {
2982 		padLen =
2983 			MIN_IEEE_8023_SIZE - (nPayload + PAYLOAD_TYPE_TDLS_SIZE);
2984 
2985 		/* if padLen is less than minimum vendorSpecific (5), pad up to 5 */
2986 		if (padLen < MIN_VENDOR_SPECIFIC_IE_SIZE)
2987 			padLen = MIN_VENDOR_SPECIFIC_IE_SIZE;
2988 
2989 		nBytes += padLen;
2990 	}
2991 #endif
2992 
2993 	/* Ok-- try to allocate memory from MGMT PKT pool */
2994 	qdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
2995 				      (void **)&pPacket);
2996 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2997 		pe_err("Failed to allocate %d bytes for a TDLS Setup Confirm",
2998 			nBytes);
2999 		qdf_mem_free(eht_cap_ie);
3000 		qdf_mem_free(setup_cnf);
3001 		return QDF_STATUS_E_NOMEM;
3002 	}
3003 
3004 	/* zero out the memory */
3005 	qdf_mem_zero(pFrame, nBytes);
3006 
3007 	/*
3008 	 * IE formation, memory allocation is completed, Now form TDLS discovery
3009 	 * request frame
3010 	 */
3011 
3012 	/* fill out the buffer descriptor */
3013 
3014 	header_offset = lim_prepare_tdls_frame_header(mac, pFrame,
3015 				LINK_IDEN_ADDR_OFFSET(setup_cnf),
3016 				TDLS_LINK_AP,
3017 				TDLS_INITIATOR,
3018 				(ac == WIFI_AC_VI) ? TID_AC_VI : TID_AC_BK,
3019 				pe_session);
3020 
3021 	status = dot11f_pack_tdls_setup_cnf(mac, setup_cnf, pFrame
3022 					    + header_offset, nPayload, &nPayload);
3023 
3024 	if (DOT11F_FAILED(status)) {
3025 		pe_err("Failed to pack a TDLS discovery req (0x%08x)", status);
3026 		cds_packet_free((void *)pPacket);
3027 		qdf_mem_free(eht_cap_ie);
3028 		qdf_mem_free(setup_cnf);
3029 		return QDF_STATUS_E_FAILURE;
3030 	} else if (DOT11F_WARNED(status)) {
3031 		pe_warn("There were warnings while packing TDLS Discovery Request (0x%08x)",
3032 			status);
3033 	}
3034 
3035 	lim_cp_stats_cstats_log_setup_confirm_evt(setup_cnf, pe_session);
3036 
3037 	qdf_mem_free(setup_cnf);
3038 
3039 	/* Copy the additional IE. */
3040 	/* TODO : addIe is added at the end of the frame. This means it doesn't */
3041 	/* follow the order. This should be ok, but we should consider changing this */
3042 	/* if there is any IOT issue. */
3043 	if (addIeLen != 0) {
3044 		qdf_mem_copy(pFrame + header_offset + nPayload, addIe,
3045 			     addIeLen);
3046 		nPayload += addIeLen;
3047 	}
3048 
3049 	if (eht_cap_ie_len) {
3050 		/* Copy the EHT IE to the end of the frame */
3051 		qdf_mem_copy(pFrame + header_offset + nPayload,
3052 			     eht_cap_ie, eht_cap_ie_len);
3053 		qdf_mem_free(eht_cap_ie);
3054 
3055 		nPayload += eht_cap_ie_len;
3056 	}
3057 
3058 	if (mlo_ie_len) {
3059 		qdf_status = lim_fill_complete_mlo_ie(pe_session, mlo_ie_len,
3060 						      pFrame + header_offset +
3061 						      nPayload);
3062 
3063 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
3064 			pe_debug("assemble ml ie error");
3065 			mlo_ie_len = 0;
3066 		}
3067 
3068 		nPayload += mlo_ie_len;
3069 	}
3070 #ifndef NO_PAD_TDLS_MIN_8023_SIZE
3071 	if (padLen != 0) {
3072 		/* QCOM VENDOR OUI = { 0x00, 0xA0, 0xC6, type = 0x0000 }; */
3073 		uint8_t *padVendorSpecific =
3074 			pFrame + header_offset + nPayload + addIeLen;
3075 		/* make QCOM_VENDOR_OUI, and type = 0x0000, and all the payload to be zero */
3076 		padVendorSpecific[0] = 221;
3077 		padVendorSpecific[1] = padLen - 2;
3078 		padVendorSpecific[2] = 0x00;
3079 		padVendorSpecific[3] = 0xA0;
3080 		padVendorSpecific[4] = 0xC6;
3081 
3082 		pe_debug("Padding Vendor Specific Ie Len: %d", padLen);
3083 
3084 		/* padding zero if more than 5 bytes are required */
3085 		if (padLen > MIN_VENDOR_SPECIFIC_IE_SIZE)
3086 			qdf_mem_zero(pFrame + header_offset + nPayload +
3087 				    addIeLen + MIN_VENDOR_SPECIFIC_IE_SIZE,
3088 				    padLen - MIN_VENDOR_SPECIFIC_IE_SIZE);
3089 	}
3090 #endif
3091 
3092 	pe_debug("[TDLS] action: %d (%s) -AP-> OTA peer="QDF_MAC_ADDR_FMT,
3093 		TDLS_SETUP_CONFIRM,
3094 		lim_trace_tdls_action_string(TDLS_SETUP_CONFIRM),
3095 	       QDF_MAC_ADDR_REF(peer_mac.bytes));
3096 
3097 	mac->lim.tdls_frm_session_id = pe_session->smeSessionId;
3098 	vdev_id = lim_get_assoc_link_vdev_id(pe_session);
3099 	lim_diag_mgmt_tx_event_report(mac, (tpSirMacMgmtHdr) pFrame,
3100 				      pe_session, QDF_STATUS_SUCCESS,
3101 				      QDF_STATUS_SUCCESS);
3102 
3103 	qdf_status = wma_tx_frame_with_tx_complete_send(mac, pPacket,
3104 						     (uint16_t) nBytes,
3105 						     TID_AC_VI,
3106 						     pFrame,
3107 						     vdev_id, true);
3108 
3109 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
3110 		mac->lim.tdls_frm_session_id = NO_SESSION;
3111 		pe_err("could not send TDLS Setup Confirm frame");
3112 		return QDF_STATUS_E_FAILURE;
3113 
3114 	}
3115 
3116 	return QDF_STATUS_SUCCESS;
3117 }
3118 
3119 /* This Function is similar to populate_dot11f_ht_caps, except that
3120  * the HT Capabilities are considered from the AddStaReq rather from
3121  * the cfg.dat as in populate_dot11f_ht_caps
3122  */
3123 static QDF_STATUS
3124 lim_tdls_populate_dot11f_ht_caps(struct mac_context *mac,
3125 				 struct pe_session *pe_session,
3126 				 struct tdls_add_sta_req *add_sta_req,
3127 				 tDot11fIEHTCaps *pDot11f)
3128 {
3129 	uint32_t nCfgValue;
3130 	uint8_t nCfgValue8;
3131 	tSirMacHTParametersInfo *pHTParametersInfo;
3132 	union {
3133 		uint16_t nCfgValue16;
3134 		struct mlme_ht_capabilities_info ht_cap_info;
3135 		tSirMacExtendedHTCapabilityInfo extHtCapInfo;
3136 	} uHTCapabilityInfo;
3137 
3138 	tSirMacTxBFCapabilityInfo *pTxBFCapabilityInfo;
3139 	tSirMacASCapabilityInfo *pASCapabilityInfo;
3140 
3141 	nCfgValue = add_sta_req->ht_cap.hc_cap;
3142 
3143 	uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF;
3144 
3145 	pDot11f->advCodingCap = uHTCapabilityInfo.ht_cap_info.adv_coding_cap;
3146 	pDot11f->mimoPowerSave = uHTCapabilityInfo.ht_cap_info.mimo_power_save;
3147 	pDot11f->greenField = uHTCapabilityInfo.ht_cap_info.green_field;
3148 	pDot11f->shortGI20MHz = uHTCapabilityInfo.ht_cap_info.short_gi_20_mhz;
3149 	pDot11f->shortGI40MHz = uHTCapabilityInfo.ht_cap_info.short_gi_40_mhz;
3150 	pDot11f->txSTBC = uHTCapabilityInfo.ht_cap_info.tx_stbc;
3151 	pDot11f->rxSTBC = uHTCapabilityInfo.ht_cap_info.rx_stbc;
3152 	pDot11f->delayedBA = uHTCapabilityInfo.ht_cap_info.delayed_ba;
3153 	pDot11f->maximalAMSDUsize =
3154 		uHTCapabilityInfo.ht_cap_info.maximal_amsdu_size;
3155 	pDot11f->dsssCckMode40MHz =
3156 		uHTCapabilityInfo.ht_cap_info.dsss_cck_mode_40_mhz;
3157 	pDot11f->psmp = uHTCapabilityInfo.ht_cap_info.psmp;
3158 	pDot11f->stbcControlFrame =
3159 		uHTCapabilityInfo.ht_cap_info.stbc_control_frame;
3160 	pDot11f->lsigTXOPProtection =
3161 		uHTCapabilityInfo.ht_cap_info.l_sig_tx_op_protection;
3162 
3163 	/*
3164 	 * All sessionized entries will need the check below
3165 	 * Only in case of NO session
3166 	 */
3167 	if (!pe_session) {
3168 		pDot11f->supportedChannelWidthSet =
3169 			uHTCapabilityInfo.ht_cap_info.
3170 			supported_channel_width_set;
3171 	} else {
3172 		pDot11f->supportedChannelWidthSet =
3173 			pe_session->htSupportedChannelWidthSet;
3174 	}
3175 
3176 	/* Ensure that shortGI40MHz is Disabled if supportedChannelWidthSet is
3177 	   eHT_CHANNEL_WIDTH_20MHZ */
3178 	if (pDot11f->supportedChannelWidthSet == eHT_CHANNEL_WIDTH_20MHZ) {
3179 		pDot11f->shortGI40MHz = 0;
3180 	}
3181 
3182 	pe_debug("SupportedChnlWidth: %d, mimoPS: %d, GF: %d, shortGI20:%d, shortGI40: %d, dsssCck: %d",
3183 		pDot11f->supportedChannelWidthSet,
3184 		pDot11f->mimoPowerSave,
3185 		pDot11f->greenField,
3186 		pDot11f->shortGI20MHz,
3187 		pDot11f->shortGI40MHz,
3188 		pDot11f->dsssCckMode40MHz);
3189 
3190 	nCfgValue = add_sta_req->ht_cap.ampdu_param;
3191 
3192 	nCfgValue8 = (uint8_t) nCfgValue;
3193 	pHTParametersInfo = (tSirMacHTParametersInfo *) &nCfgValue8;
3194 
3195 	pDot11f->maxRxAMPDUFactor = pHTParametersInfo->maxRxAMPDUFactor;
3196 	pDot11f->mpduDensity = pHTParametersInfo->mpduDensity;
3197 	pDot11f->reserved1 = pHTParametersInfo->reserved;
3198 
3199 	pe_debug("AMPDU Param: %x", nCfgValue);
3200 	qdf_mem_copy(pDot11f->supportedMCSSet, add_sta_req->ht_cap.mcsset,
3201 		     SIZE_OF_SUPPORTED_MCS_SET);
3202 
3203 	nCfgValue = add_sta_req->ht_cap.extcap;
3204 
3205 	uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF;
3206 
3207 	pDot11f->pco = uHTCapabilityInfo.extHtCapInfo.pco;
3208 	pDot11f->transitionTime = uHTCapabilityInfo.extHtCapInfo.transitionTime;
3209 	pDot11f->mcsFeedback = uHTCapabilityInfo.extHtCapInfo.mcsFeedback;
3210 
3211 	nCfgValue = add_sta_req->ht_cap.txbf_cap;
3212 
3213 	pTxBFCapabilityInfo = (tSirMacTxBFCapabilityInfo *) &nCfgValue;
3214 	pDot11f->txBF = pTxBFCapabilityInfo->txBF;
3215 	pDot11f->rxStaggeredSounding = pTxBFCapabilityInfo->rxStaggeredSounding;
3216 	pDot11f->txStaggeredSounding = pTxBFCapabilityInfo->txStaggeredSounding;
3217 	pDot11f->rxZLF = pTxBFCapabilityInfo->rxZLF;
3218 	pDot11f->txZLF = pTxBFCapabilityInfo->txZLF;
3219 	pDot11f->implicitTxBF = pTxBFCapabilityInfo->implicitTxBF;
3220 	pDot11f->calibration = pTxBFCapabilityInfo->calibration;
3221 	pDot11f->explicitCSITxBF = pTxBFCapabilityInfo->explicitCSITxBF;
3222 	pDot11f->explicitUncompressedSteeringMatrix =
3223 		pTxBFCapabilityInfo->explicitUncompressedSteeringMatrix;
3224 	pDot11f->explicitBFCSIFeedback =
3225 		pTxBFCapabilityInfo->explicitBFCSIFeedback;
3226 	pDot11f->explicitUncompressedSteeringMatrixFeedback =
3227 		pTxBFCapabilityInfo->explicitUncompressedSteeringMatrixFeedback;
3228 	pDot11f->explicitCompressedSteeringMatrixFeedback =
3229 		pTxBFCapabilityInfo->explicitCompressedSteeringMatrixFeedback;
3230 	pDot11f->csiNumBFAntennae = pTxBFCapabilityInfo->csiNumBFAntennae;
3231 	pDot11f->uncompressedSteeringMatrixBFAntennae =
3232 		pTxBFCapabilityInfo->uncompressedSteeringMatrixBFAntennae;
3233 	pDot11f->compressedSteeringMatrixBFAntennae =
3234 		pTxBFCapabilityInfo->compressedSteeringMatrixBFAntennae;
3235 
3236 	nCfgValue = add_sta_req->ht_cap.antenna;
3237 
3238 	nCfgValue8 = (uint8_t) nCfgValue;
3239 
3240 	pASCapabilityInfo = (tSirMacASCapabilityInfo *) &nCfgValue8;
3241 	pDot11f->antennaSelection = pASCapabilityInfo->antennaSelection;
3242 	pDot11f->explicitCSIFeedbackTx =
3243 		pASCapabilityInfo->explicitCSIFeedbackTx;
3244 	pDot11f->antennaIndicesFeedbackTx =
3245 		pASCapabilityInfo->antennaIndicesFeedbackTx;
3246 	pDot11f->explicitCSIFeedback = pASCapabilityInfo->explicitCSIFeedback;
3247 	pDot11f->antennaIndicesFeedback =
3248 		pASCapabilityInfo->antennaIndicesFeedback;
3249 	pDot11f->rxAS = pASCapabilityInfo->rxAS;
3250 	pDot11f->txSoundingPPDUs = pASCapabilityInfo->txSoundingPPDUs;
3251 
3252 	pDot11f->present = add_sta_req->htcap_present;
3253 
3254 	return QDF_STATUS_SUCCESS;
3255 
3256 }
3257 
3258 static QDF_STATUS
3259 lim_tdls_populate_dot11f_vht_caps(struct mac_context *mac,
3260 				  struct tdls_add_sta_req *add_sta_req,
3261 				  tDot11fIEVHTCaps *pDot11f)
3262 {
3263 	uint32_t nCfgValue = 0;
3264 	union {
3265 		uint32_t nCfgValue32;
3266 		tSirMacVHTCapabilityInfo vhtCapInfo;
3267 	} uVHTCapabilityInfo;
3268 	union {
3269 		uint16_t nCfgValue16;
3270 		tSirMacVHTTxSupDataRateInfo vhtTxSupDataRateInfo;
3271 		tSirMacVHTRxSupDataRateInfo vhtRxsupDataRateInfo;
3272 	} uVHTSupDataRateInfo;
3273 
3274 	pDot11f->present = add_sta_req->vhtcap_present;
3275 
3276 	nCfgValue = add_sta_req->vht_cap.vht_capinfo;
3277 	uVHTCapabilityInfo.nCfgValue32 = nCfgValue;
3278 
3279 	pDot11f->maxMPDULen = uVHTCapabilityInfo.vhtCapInfo.maxMPDULen;
3280 	pDot11f->supportedChannelWidthSet =
3281 		uVHTCapabilityInfo.vhtCapInfo.supportedChannelWidthSet;
3282 	pDot11f->ldpcCodingCap = uVHTCapabilityInfo.vhtCapInfo.ldpcCodingCap;
3283 	pDot11f->shortGI80MHz = uVHTCapabilityInfo.vhtCapInfo.shortGI80MHz;
3284 	pDot11f->shortGI160and80plus80MHz =
3285 		uVHTCapabilityInfo.vhtCapInfo.shortGI160and80plus80MHz;
3286 	pDot11f->txSTBC = uVHTCapabilityInfo.vhtCapInfo.txSTBC;
3287 	pDot11f->rxSTBC = uVHTCapabilityInfo.vhtCapInfo.rxSTBC;
3288 	pDot11f->suBeamFormerCap = 0;
3289 	pDot11f->suBeamformeeCap = 0;
3290 	pDot11f->csnofBeamformerAntSup =
3291 		uVHTCapabilityInfo.vhtCapInfo.csnofBeamformerAntSup;
3292 	pDot11f->numSoundingDim = uVHTCapabilityInfo.vhtCapInfo.numSoundingDim;
3293 	pDot11f->muBeamformerCap = 0;
3294 	pDot11f->muBeamformeeCap = 0;
3295 	pDot11f->vhtTXOPPS = uVHTCapabilityInfo.vhtCapInfo.vhtTXOPPS;
3296 	pDot11f->htcVHTCap = uVHTCapabilityInfo.vhtCapInfo.htcVHTCap;
3297 	pDot11f->maxAMPDULenExp = uVHTCapabilityInfo.vhtCapInfo.maxAMPDULenExp;
3298 	pDot11f->vhtLinkAdaptCap =
3299 		uVHTCapabilityInfo.vhtCapInfo.vhtLinkAdaptCap;
3300 	pDot11f->rxAntPattern = uVHTCapabilityInfo.vhtCapInfo.rxAntPattern;
3301 	pDot11f->txAntPattern = uVHTCapabilityInfo.vhtCapInfo.txAntPattern;
3302 	pDot11f->extended_nss_bw_supp =
3303 		uVHTCapabilityInfo.vhtCapInfo.extended_nss_bw_supp;
3304 
3305 	pDot11f->rxMCSMap = add_sta_req->vht_cap.supp_mcs.rx_mcs_map;
3306 
3307 	nCfgValue = add_sta_req->vht_cap.supp_mcs.rx_highest;
3308 	uVHTSupDataRateInfo.nCfgValue16 = nCfgValue & 0xffff;
3309 	pDot11f->rxHighSupDataRate =
3310 		uVHTSupDataRateInfo.vhtRxsupDataRateInfo.rxSupDataRate;
3311 	pDot11f->max_nsts_total =
3312 		uVHTSupDataRateInfo.vhtRxsupDataRateInfo.max_nsts_total;
3313 
3314 	pDot11f->txMCSMap = add_sta_req->vht_cap.supp_mcs.tx_mcs_map;
3315 
3316 	nCfgValue = add_sta_req->vht_cap.supp_mcs.tx_highest;
3317 	uVHTSupDataRateInfo.nCfgValue16 = nCfgValue & 0xffff;
3318 	pDot11f->txSupDataRate =
3319 		uVHTSupDataRateInfo.vhtTxSupDataRateInfo.txSupDataRate;
3320 
3321 	pDot11f->vht_extended_nss_bw_cap =
3322 	uVHTSupDataRateInfo.vhtTxSupDataRateInfo.vht_extended_nss_bw_cap;
3323 
3324 	lim_log_vht_cap(mac, pDot11f);
3325 
3326 	return QDF_STATUS_SUCCESS;
3327 }
3328 
3329 #ifdef WLAN_FEATURE_11BE
3330 static void
3331 lim_tdls_populate_eht_mcs(struct mac_context *mac_ctx, tpDphHashNode stads,
3332 			  struct pe_session *session_entry)
3333 {
3334 	lim_populate_eht_mcs_set(mac_ctx, &stads->supportedRates,
3335 				 &stads->eht_config, session_entry,
3336 				 session_entry->nss);
3337 }
3338 #else
3339 static void
3340 lim_tdls_populate_eht_mcs(struct mac_context *mac_ctx, tpDphHashNode stads,
3341 			  struct pe_session *session_entry)
3342 {
3343 }
3344 #endif
3345 
3346 /**
3347  * lim_tdls_populate_matching_rate_set() - populate matching rate set
3348  *
3349  * @mac_ctx  - global MAC context
3350  * @stads - station hash entry
3351  * @supp_rate_set - pointer to supported rate set
3352  * @supp_rates_len - length of the supported rates
3353  * @supp_mcs_set - pointer to supported MSC set
3354  * @session_entry - pointer to PE session entry
3355  * @vht_caps - pointer to VHT capability
3356  *
3357  *
3358  * This function gets set of available rates from the config and compare them
3359  * against the set of received supported rates. After the comparison station
3360  * entry's rates is populated with 11A rates and 11B rates.
3361  *
3362  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure.
3363  */
3364 static QDF_STATUS
3365 lim_tdls_populate_matching_rate_set(struct mac_context *mac_ctx,
3366 				    tpDphHashNode stads,
3367 				    uint8_t *supp_rate_set,
3368 				    uint8_t supp_rates_len,
3369 				    uint8_t *supp_mcs_set,
3370 				    struct pe_session *session_entry,
3371 				    tDot11fIEVHTCaps *vht_caps)
3372 {
3373 	tSirMacRateSet temp_rate_set;
3374 	uint32_t i, j, is_a_rate;
3375 	uint32_t phymode;
3376 	uint8_t mcsSet[SIZE_OF_SUPPORTED_MCS_SET];
3377 	struct supported_rates *rates;
3378 	uint8_t a_rateindex = 0;
3379 	uint8_t b_rateindex = 0;
3380 	uint8_t nss;
3381 	qdf_size_t val_len;
3382 
3383 	is_a_rate = 0;
3384 
3385 	lim_get_phy_mode(mac_ctx, &phymode, NULL);
3386 
3387 	/**
3388 	 * Copy received rates in temp_rate_set, the parser has ensured
3389 	 * unicity of the rates so there cannot be more than 12 .
3390 	 */
3391 	if (supp_rates_len > SIR_MAC_MAX_NUMBER_OF_RATES) {
3392 		pe_warn("Supported rates length: %d more than the Max limit, reset to Max",
3393 			supp_rates_len);
3394 		supp_rates_len = SIR_MAC_MAX_NUMBER_OF_RATES;
3395 	}
3396 
3397 	for (i = 0; i < supp_rates_len; i++)
3398 		temp_rate_set.rate[i] = supp_rate_set[i];
3399 
3400 	temp_rate_set.numRates = supp_rates_len;
3401 
3402 	rates = &stads->supportedRates;
3403 	qdf_mem_zero(rates, sizeof(*rates));
3404 
3405 	for (j = 0; j < temp_rate_set.numRates; j++) {
3406 		if ((b_rateindex > SIR_NUM_11B_RATES) ||
3407 		    (a_rateindex > SIR_NUM_11A_RATES)) {
3408 			pe_warn("Invalid number of rates (11b->%d, 11a->%d)",
3409 				b_rateindex, a_rateindex);
3410 			return QDF_STATUS_E_FAILURE;
3411 		}
3412 		if (sirIsArate(temp_rate_set.rate[j] & 0x7f)) {
3413 			is_a_rate = 1;
3414 			if (a_rateindex < SIR_NUM_11A_RATES)
3415 				rates->llaRates[a_rateindex++] =
3416 						temp_rate_set.rate[j];
3417 		} else {
3418 			if (b_rateindex < SIR_NUM_11B_RATES)
3419 				rates->llbRates[b_rateindex++] =
3420 						temp_rate_set.rate[j];
3421 		}
3422 	}
3423 
3424 	if (wlan_reg_is_5ghz_ch_freq(session_entry->curr_op_freq))
3425 		nss = mac_ctx->vdev_type_nss_5g.tdls;
3426 	else
3427 		nss = mac_ctx->vdev_type_nss_2g.tdls;
3428 
3429 	nss = QDF_MIN(nss, mac_ctx->user_configured_nss);
3430 
3431 	/* compute the matching MCS rate set, if peer is 11n capable and self mode is 11n */
3432 #ifdef FEATURE_WLAN_TDLS
3433 	if (stads->mlmStaContext.htCapability)
3434 #else
3435 	if (IS_DOT11_MODE_HT(session_entry->dot11mode) &&
3436 	    (stads->mlmStaContext.htCapability))
3437 #endif
3438 	{
3439 		val_len = SIZE_OF_SUPPORTED_MCS_SET;
3440 		if (wlan_mlme_get_cfg_str(
3441 			mcsSet,
3442 			&mac_ctx->mlme_cfg->rates.supported_mcs_set,
3443 			&val_len) != QDF_STATUS_SUCCESS) {
3444 			/* Could not get rateset from CFG. Log error. */
3445 			pe_err("could not retrieve supportedMCSSet");
3446 			return QDF_STATUS_E_FAILURE;
3447 		}
3448 
3449 		if (NSS_1x1_MODE == nss)
3450 			mcsSet[1] = 0;
3451 		for (i = 0; i < val_len; i++)
3452 			stads->supportedRates.supportedMCSSet[i] =
3453 				mcsSet[i] & supp_mcs_set[i];
3454 
3455 		pe_debug("MCS Rate Set Bitmap from CFG and DPH");
3456 		for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++) {
3457 			pe_debug("%x %x", mcsSet[i],
3458 				stads->supportedRates.supportedMCSSet[i]);
3459 		}
3460 	}
3461 	lim_populate_vht_mcs_set(mac_ctx, &stads->supportedRates, vht_caps,
3462 				 session_entry, nss, NULL);
3463 
3464 	lim_tdls_populate_eht_mcs(mac_ctx, stads, session_entry);
3465 
3466 	lim_tdls_populate_he_matching_rate_set(mac_ctx, stads, nss,
3467 					       session_entry);
3468 	/**
3469 	 * Set the erpEnabled bit if the phy is in G mode and at least
3470 	 * one A rate is supported
3471 	 */
3472 	if ((phymode == WNI_CFG_PHY_MODE_11G) && is_a_rate)
3473 		stads->erpEnabled = eHAL_SET;
3474 
3475 	return QDF_STATUS_SUCCESS;
3476 }
3477 
3478 static void lim_tdls_fill_session_vht_width(struct pe_session *pe_session,
3479 					    tDphHashNode *sta)
3480 {
3481 	if (pe_session->ch_width)
3482 		sta->vhtSupportedChannelWidthSet =
3483 			       pe_session->ch_width - 1;
3484 	else
3485 		sta->vhtSupportedChannelWidthSet =
3486 				pe_session->ch_width;
3487 }
3488 
3489 static inline enum phy_ch_width
3490 lim_reg_bw_to_ht_ch_width(uint16_t reg_max_bw)
3491 {
3492 	return reg_max_bw > 20 ? CH_WIDTH_40MHZ : CH_WIDTH_20MHZ;
3493 }
3494 
3495 #ifdef WLAN_FEATURE_11BE
3496 static void
3497 lim_tdls_populate_dot11f_eht_caps(struct pe_session *pe_session,
3498 				  tDphHashNode *sta,
3499 				  struct tdls_add_sta_req *add_sta_req)
3500 {
3501 	if (add_sta_req->ehtcap_present) {
3502 		pe_debug("copy eht config from pe_session");
3503 		qdf_mem_copy(&sta->eht_config, &pe_session->eht_config,
3504 			     sizeof(sta->eht_config));
3505 		qdf_mem_copy(&sta->eht_op, &pe_session->eht_op,
3506 			     sizeof(sta->eht_op));
3507 	}
3508 }
3509 #else
3510 static inline void
3511 lim_tdls_populate_dot11f_eht_caps(struct pe_session *pe_session,
3512 				  tDphHashNode *sta,
3513 				  struct tdls_add_sta_req *add_sta_req)
3514 {
3515 }
3516 #endif
3517 
3518 /*
3519  * update HASH node entry info
3520  */
3521 static void lim_tdls_update_hash_node_info(struct mac_context *mac,
3522 					   tDphHashNode *sta,
3523 					   struct tdls_add_sta_req *add_sta_req,
3524 					   struct pe_session *pe_session)
3525 {
3526 	tDot11fIEHTCaps htCap = {0,};
3527 	tDot11fIEHTCaps *htCaps;
3528 	tDot11fIEVHTCaps *pVhtCaps = NULL;
3529 	tDot11fIEVHTCaps *pVhtCaps_txbf = NULL;
3530 	tDot11fIEVHTCaps vhtCap;
3531 	uint8_t cbMode, selfDot11Mode;
3532 	bool wide_band_peer = false;
3533 	uint16_t reg_max_bw = 0;
3534 	uint16_t reg_ch_width = 0;
3535 
3536 	if (add_sta_req->tdls_oper == TDLS_OPER_ADD) {
3537 		populate_dot11f_ht_caps(mac, pe_session, &htCap);
3538 	} else if (add_sta_req->tdls_oper == TDLS_OPER_UPDATE) {
3539 		lim_tdls_populate_dot11f_ht_caps(mac, NULL,
3540 						 add_sta_req, &htCap);
3541 		sta->rmfEnabled = add_sta_req->is_pmf;
3542 	}
3543 
3544 	lim_tdls_populate_dot11f_eht_caps(pe_session, sta, add_sta_req);
3545 
3546 	reg_max_bw = wlan_reg_get_max_chwidth(mac->pdev,
3547 					      pe_session->curr_op_freq);
3548 
3549 	wide_band_peer = lim_is_wide_band_set(add_sta_req->extn_capability) &&
3550 		    wlan_cfg80211_tdls_is_fw_wideband_capable(pe_session->vdev);
3551 	selfDot11Mode = mac->mlme_cfg->dot11_mode.dot11_mode;
3552 	htCaps = &htCap;
3553 	if (htCaps->present && IS_DOT11_MODE_HT(selfDot11Mode)) {
3554 		sta->mlmStaContext.htCapability = 1;
3555 		sta->htGreenfield = htCaps->greenField;
3556 		/*
3557 		 * sta->htSupportedChannelWidthSet should have the base
3558 		 * channel capability. The htSupportedChannelWidthSet of the
3559 		 * TDLS link on base channel should be less than or equal to
3560 		 * channel width of STA-AP link. So take this setting from the
3561 		 * pe_session.
3562 		 */
3563 		/*
3564 		 * Since, now wideband is supported, bw should be restricted
3565 		 * only in case of dfs channel
3566 		 */
3567 		pe_debug("peer htSupportedChannelWidthSet: 0x%x "
3568 				"pe session htSupportedChannelWidthSet: 0x%x",
3569 				htCaps->supportedChannelWidthSet,
3570 				pe_session->htSupportedChannelWidthSet);
3571 
3572 		if (!wide_band_peer ||
3573 		    wlan_reg_is_dfs_for_freq(mac->pdev,
3574 					     pe_session->curr_op_freq) ||
3575 		    wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq)) {
3576 			sta->htSupportedChannelWidthSet =
3577 				(htCaps->supportedChannelWidthSet <
3578 				 pe_session->htSupportedChannelWidthSet) ?
3579 				htCaps->supportedChannelWidthSet :
3580 				pe_session->htSupportedChannelWidthSet;
3581 		} else {
3582 			reg_ch_width = lim_reg_bw_to_ht_ch_width(reg_max_bw);
3583 
3584 			pe_debug("regulatory max bw %d MHz ch_width 0x%x",
3585 					reg_max_bw,
3586 					reg_ch_width);
3587 
3588 			sta->htSupportedChannelWidthSet =
3589 				(htCaps->supportedChannelWidthSet <
3590 				 reg_ch_width) ?
3591 				htCaps->supportedChannelWidthSet :
3592 				reg_ch_width;
3593 		}
3594 
3595 		pe_debug("sta->htSupportedChannelWidthSet: 0x%x",
3596 			 sta->htSupportedChannelWidthSet);
3597 
3598 		sta->ch_width = sta->htSupportedChannelWidthSet;
3599 		sta->htMIMOPSState = htCaps->mimoPowerSave;
3600 		sta->htMaxAmsduLength = htCaps->maximalAMSDUsize;
3601 		sta->htAMpduDensity = htCaps->mpduDensity;
3602 		sta->htDsssCckRate40MHzSupport = htCaps->dsssCckMode40MHz;
3603 		sta->htShortGI20Mhz = htCaps->shortGI20MHz;
3604 		sta->htShortGI40Mhz = htCaps->shortGI40MHz;
3605 		sta->htMaxRxAMpduFactor = htCaps->maxRxAMPDUFactor;
3606 		lim_fill_rx_highest_supported_rate(mac,
3607 						   &sta->supportedRates.
3608 						   rxHighestDataRate,
3609 						   htCaps->supportedMCSSet);
3610 		sta->ht_caps = add_sta_req->ht_cap.hc_cap;
3611 	} else {
3612 		sta->mlmStaContext.htCapability = 0;
3613 	}
3614 	lim_tdls_populate_dot11f_vht_caps(mac, add_sta_req, &vhtCap);
3615 	pVhtCaps = &vhtCap;
3616 	if (pVhtCaps->present && IS_DOT11_MODE_VHT(selfDot11Mode)) {
3617 		sta->mlmStaContext.vhtCapability = 1;
3618 
3619 		/*
3620 		 * 11.21.1 General: The channel width of the TDLS direct
3621 		 * link on the base channel shall not exceed the channel
3622 		 * width of the BSS to which the TDLS peer STAs are
3623 		 * associated, if the base channel is dfs channel and peer is
3624 		 * not wide band supported
3625 		 */
3626 		if (!wide_band_peer ||
3627 		    wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq)) {
3628 			lim_tdls_fill_session_vht_width(pe_session, sta);
3629 		} else {
3630 			if (pVhtCaps->supportedChannelWidthSet >=
3631 			    VHT_CAP_NO_160M_SUPP)
3632 				sta->vhtSupportedChannelWidthSet =
3633 						WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
3634 
3635 			if (wlan_reg_is_dfs_for_freq(mac->pdev,
3636 						    pe_session->curr_op_freq)) {
3637 				lim_tdls_fill_session_vht_width(pe_session,
3638 								sta);
3639 			}
3640 		}
3641 
3642 		if (sta->htSupportedChannelWidthSet) {
3643 			if (sta->vhtSupportedChannelWidthSet >
3644 			    WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ)
3645 				sta->ch_width = CH_WIDTH_160MHZ;
3646 			else
3647 				sta->ch_width =
3648 					   sta->vhtSupportedChannelWidthSet + 1;
3649 		} else {
3650 			sta->ch_width = CH_WIDTH_20MHZ;
3651 		}
3652 
3653 		pe_debug("vhtSupportedChannelWidthSet: %hu htSupportedChannelWidthSet: %hu sta_ch_width %d",
3654 			 sta->vhtSupportedChannelWidthSet,
3655 			 sta->htSupportedChannelWidthSet,
3656 			 sta->ch_width);
3657 
3658 		sta->vhtLdpcCapable = pVhtCaps->ldpcCodingCap;
3659 		sta->vhtBeamFormerCapable = 0;
3660 		pVhtCaps_txbf = (tDot11fIEVHTCaps *) (&add_sta_req->vht_cap);
3661 		pVhtCaps_txbf->suBeamformeeCap = 0;
3662 		pVhtCaps_txbf->suBeamFormerCap = 0;
3663 		pVhtCaps_txbf->muBeamformerCap = 0;
3664 		pVhtCaps_txbf->muBeamformeeCap = 0;
3665 		sta->vht_caps = add_sta_req->vht_cap.vht_capinfo;
3666 	} else {
3667 		sta->mlmStaContext.vhtCapability = 0;
3668 		sta->vhtSupportedChannelWidthSet =
3669 			WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
3670 	}
3671 
3672 	if (IS_DOT11_MODE_HE(selfDot11Mode))
3673 		lim_tdls_update_node_he_caps(mac, add_sta_req, sta, pe_session,
3674 					     wide_band_peer);
3675 	else
3676 		pe_debug("Not populating he cap as SelfDot11Mode not HE %d",
3677 			 selfDot11Mode);
3678 	/*
3679 	 * Calculate the Secondary Coannel Offset if our
3680 	 * own channel bonding state is enabled
3681 	 */
3682 	if (pe_session->htSupportedChannelWidthSet) {
3683 		cbMode = lim_select_cb_mode(sta, pe_session,
3684 				    wlan_reg_freq_to_chan(
3685 				    mac->pdev, pe_session->curr_op_freq),
3686 				    sta->vhtSupportedChannelWidthSet);
3687 
3688 		if (sta->mlmStaContext.vhtCapability)
3689 			sta->htSecondaryChannelOffset =
3690 					lim_get_htcb_state(cbMode);
3691 		else
3692 			sta->htSecondaryChannelOffset = cbMode;
3693 	}
3694 	/* Lets enable QOS parameter */
3695 	sta->qosMode = (add_sta_req->capability & CAPABILITIES_QOS_OFFSET)
3696 				|| add_sta_req->htcap_present;
3697 	sta->wmeEnabled = 1;
3698 	sta->lleEnabled = 0;
3699 	/*  TDLS Dummy AddSTA does not have qosInfo , is it OK ??
3700 	 */
3701 	sta->qos.capability.qosInfo =
3702 		(*(tSirMacQosInfoStation *) &add_sta_req->uapsd_queues);
3703 
3704 	/* populate matching rate set */
3705 
3706 	/* TDLS Dummy AddSTA does not have HTCap,VHTCap,Rates info , is it OK ??
3707 	 */
3708 
3709 	lim_tdls_populate_matching_rate_set(mac, sta,
3710 					    add_sta_req->supported_rates,
3711 					    add_sta_req->supported_rates_length,
3712 					    add_sta_req->ht_cap.mcsset,
3713 					    pe_session, pVhtCaps);
3714 
3715 	lim_tdls_check_and_force_he_ldpc_cap(pe_session, sta);
3716 
3717 	/*  TDLS Dummy AddSTA does not have right capability , is it OK ??
3718 	 */
3719 	sta->mlmStaContext.capabilityInfo =
3720 		(*(tSirMacCapabilityInfo *) &add_sta_req->capability);
3721 
3722 	return;
3723 }
3724 
3725 /*
3726  * Add STA for TDLS setup procedure
3727  */
3728 static QDF_STATUS lim_tdls_setup_add_sta(struct mac_context *mac,
3729 					    struct tdls_add_sta_req *pAddStaReq,
3730 					    struct pe_session *pe_session)
3731 {
3732 	tpDphHashNode sta = NULL;
3733 	QDF_STATUS status = QDF_STATUS_SUCCESS;
3734 	uint16_t aid = 0;
3735 
3736 	sta = dph_lookup_hash_entry(mac, pAddStaReq->peermac.bytes, &aid,
3737 				       &pe_session->dph.dphHashTable);
3738 	if (!sta && pAddStaReq->tdls_oper == TDLS_OPER_UPDATE) {
3739 		pe_err("TDLS update peer is given without peer creation");
3740 		return QDF_STATUS_E_FAILURE;
3741 	}
3742 	if (sta && pAddStaReq->tdls_oper == TDLS_OPER_ADD) {
3743 		pe_err("TDLS entry for peer: "QDF_MAC_ADDR_FMT " already exist, cannot add new entry",
3744 			QDF_MAC_ADDR_REF(pAddStaReq->peermac.bytes));
3745 			return QDF_STATUS_E_FAILURE;
3746 	}
3747 
3748 	if (sta && sta->staType != STA_ENTRY_TDLS_PEER) {
3749 		pe_err("Non TDLS entry for peer: "QDF_MAC_ADDR_FMT " already exist",
3750 			QDF_MAC_ADDR_REF(pAddStaReq->peermac.bytes));
3751 			return QDF_STATUS_E_FAILURE;
3752 	}
3753 
3754 	if (!sta) {
3755 		aid = lim_assign_peer_idx(mac, pe_session);
3756 
3757 		if (!aid) {
3758 			pe_err("No more free AID for peer: "QDF_MAC_ADDR_FMT,
3759 				QDF_MAC_ADDR_REF(pAddStaReq->peermac.bytes));
3760 			return QDF_STATUS_E_FAILURE;
3761 		}
3762 
3763 		/* Set the aid in peerAIDBitmap as it has been assigned to TDLS peer */
3764 		SET_PEER_AID_BITMAP(pe_session->peerAIDBitmap, aid);
3765 
3766 		pe_debug("Aid: %d, for peer: " QDF_MAC_ADDR_FMT,
3767 			aid, QDF_MAC_ADDR_REF(pAddStaReq->peermac.bytes));
3768 		sta =
3769 			dph_get_hash_entry(mac, aid,
3770 					   &pe_session->dph.dphHashTable);
3771 
3772 		if (sta) {
3773 			(void)lim_del_sta(mac, sta, false /*asynchronous */,
3774 					  pe_session);
3775 			lim_delete_dph_hash_entry(mac, sta->staAddr, aid,
3776 						  pe_session);
3777 		}
3778 
3779 		sta = dph_add_hash_entry(mac, pAddStaReq->peermac.bytes,
3780 					 aid, &pe_session->dph.dphHashTable);
3781 
3782 		if (!sta) {
3783 			pe_err("add hash entry failed");
3784 			QDF_ASSERT(0);
3785 			return QDF_STATUS_E_FAILURE;
3786 		}
3787 	}
3788 
3789 	lim_tdls_update_hash_node_info(mac, sta, pAddStaReq, pe_session);
3790 
3791 	sta->staType = STA_ENTRY_TDLS_PEER;
3792 
3793 	status =
3794 		lim_add_sta(mac, sta,
3795 			    (pAddStaReq->tdls_oper ==
3796 			     TDLS_OPER_UPDATE) ? true : false, pe_session);
3797 
3798 	if (QDF_STATUS_SUCCESS != status) {
3799 		/* should not fail */
3800 		QDF_ASSERT(0);
3801 	}
3802 	return status;
3803 }
3804 
3805 /*
3806  * Del STA, after Link is teardown or discovery response sent on direct link
3807  */
3808 static QDF_STATUS lim_tdls_del_sta(struct mac_context *mac,
3809 				      struct qdf_mac_addr peerMac,
3810 				      struct pe_session *pe_session,
3811 				      bool resp_reqd)
3812 {
3813 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
3814 	uint16_t peerIdx = 0;
3815 	tpDphHashNode sta;
3816 
3817 	sta = dph_lookup_hash_entry(mac, peerMac.bytes, &peerIdx,
3818 				       &pe_session->dph.dphHashTable);
3819 
3820 	if (sta && sta->staType == STA_ENTRY_TDLS_PEER)
3821 		status = lim_del_sta(mac, sta, resp_reqd, pe_session);
3822 	else
3823 		pe_debug("TDLS peer "QDF_MAC_ADDR_FMT" not found",
3824 			 QDF_MAC_ADDR_REF(peerMac.bytes));
3825 
3826 	return status;
3827 }
3828 
3829 /*
3830  * Once Link is setup with PEER, send Add STA ind to SME
3831  */
3832 static QDF_STATUS lim_send_sme_tdls_add_sta_rsp(struct mac_context *mac,
3833 						uint8_t sessionId,
3834 						tSirMacAddr peerMac,
3835 						uint8_t updateSta,
3836 						tDphHashNode *sta, uint8_t status)
3837 {
3838 	struct scheduler_msg msg = { 0 };
3839 	struct tdls_add_sta_rsp *add_sta_rsp;
3840 	QDF_STATUS ret;
3841 
3842 	msg.type = eWNI_SME_TDLS_ADD_STA_RSP;
3843 
3844 	add_sta_rsp = qdf_mem_malloc(sizeof(*add_sta_rsp));
3845 	if (!add_sta_rsp)
3846 		return QDF_STATUS_E_NOMEM;
3847 
3848 	add_sta_rsp->session_id = sessionId;
3849 	add_sta_rsp->status_code = status;
3850 
3851 	if (peerMac) {
3852 		qdf_mem_copy(add_sta_rsp->peermac.bytes,
3853 			     (uint8_t *) peerMac, QDF_MAC_ADDR_SIZE);
3854 	}
3855 	if (updateSta)
3856 		add_sta_rsp->tdls_oper = TDLS_OPER_UPDATE;
3857 	else
3858 		add_sta_rsp->tdls_oper = TDLS_OPER_ADD;
3859 
3860 	add_sta_rsp->psoc = mac->psoc;
3861 	msg.bodyptr = add_sta_rsp;
3862 	msg.callback = tgt_tdls_add_peer_rsp;
3863 
3864 	ret = scheduler_post_message(QDF_MODULE_ID_PE,
3865 				     QDF_MODULE_ID_TDLS,
3866 				     QDF_MODULE_ID_TARGET_IF, &msg);
3867 	if (QDF_IS_STATUS_ERROR(ret)) {
3868 		pe_err("post msg fail, %d", ret);
3869 		qdf_mem_free(add_sta_rsp);
3870 	}
3871 
3872 	return ret;
3873 }
3874 
3875 /*
3876  * STA RSP received from HAL
3877  */
3878 QDF_STATUS lim_process_tdls_add_sta_rsp(struct mac_context *mac, void *msg,
3879 					struct pe_session *pe_session)
3880 {
3881 	tAddStaParams *pAddStaParams = (tAddStaParams *) msg;
3882 	uint8_t status = QDF_STATUS_SUCCESS;
3883 	tDphHashNode *sta = NULL;
3884 	uint16_t aid = 0;
3885 
3886 	SET_LIM_PROCESS_DEFD_MESGS(mac, true);
3887 	pe_debug("staMac: "QDF_MAC_ADDR_FMT,
3888 	       QDF_MAC_ADDR_REF(pAddStaParams->staMac));
3889 
3890 	if (pAddStaParams->status != QDF_STATUS_SUCCESS) {
3891 		QDF_ASSERT(0);
3892 		pe_err("Add sta failed ");
3893 		status = QDF_STATUS_E_FAILURE;
3894 		goto add_sta_error;
3895 	}
3896 
3897 	sta = dph_lookup_hash_entry(mac, pAddStaParams->staMac, &aid,
3898 				       &pe_session->dph.dphHashTable);
3899 	if (!sta) {
3900 		pe_err("sta is NULL ");
3901 		status = QDF_STATUS_E_FAILURE;
3902 		goto add_sta_error;
3903 	}
3904 
3905 	sta->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE;
3906 	sta->valid = 1;
3907 add_sta_error:
3908 	status = lim_send_sme_tdls_add_sta_rsp(mac, pe_session->smeSessionId,
3909 					       pAddStaParams->staMac,
3910 					       pAddStaParams->updateSta, sta,
3911 					       status);
3912 	qdf_mem_free(pAddStaParams);
3913 	return status;
3914 }
3915 
3916 /**
3917  * lim_send_tdls_comp_mgmt_rsp() - Send Response to upper layers
3918  * @mac_ctx:          Pointer to Global MAC structure
3919  * @msg_type:         Indicates message type
3920  * @result_code:       Indicates the result of previously issued
3921  *                    eWNI_SME_msg_type_REQ message
3922  * @vdev_id: vdev id
3923  *
3924  * This function is called by lim_process_sme_req_messages() to send
3925  * eWNI_SME_START_RSP, eWNI_SME_STOP_BSS_RSP
3926  * or eWNI_SME_SWITCH_CHL_RSP messages to applications above MAC
3927  * Software.
3928  *
3929  * Return: None
3930  */
3931 
3932 static void
3933 lim_send_tdls_comp_mgmt_rsp(struct mac_context *mac_ctx, uint16_t msg_type,
3934 	 tSirResultCodes result_code, uint8_t vdev_id)
3935 {
3936 	struct scheduler_msg msg = {0};
3937 	struct tdls_send_mgmt_rsp *sme_rsp;
3938 	QDF_STATUS status;
3939 
3940 	pe_debug("vdev:%d Sending message %s with reasonCode %s", vdev_id,
3941 		 lim_msg_str(msg_type), lim_result_code_str(result_code));
3942 
3943 	sme_rsp = qdf_mem_malloc(sizeof(*sme_rsp));
3944 	if (!sme_rsp)
3945 		return;
3946 
3947 	sme_rsp->status_code = (enum legacy_result_code)result_code;
3948 	sme_rsp->vdev_id = vdev_id;
3949 	sme_rsp->psoc = mac_ctx->psoc;
3950 
3951 	msg.type = msg_type;
3952 	msg.bodyptr = sme_rsp;
3953 	msg.callback = tgt_tdls_send_mgmt_rsp;
3954 	status = scheduler_post_message(QDF_MODULE_ID_PE,
3955 					QDF_MODULE_ID_TDLS,
3956 					QDF_MODULE_ID_TARGET_IF, &msg);
3957 	if (QDF_IS_STATUS_ERROR(status)) {
3958 		pe_err("post msg fail, %d", status);
3959 		qdf_mem_free(sme_rsp);
3960 	}
3961 }
3962 
3963 QDF_STATUS lim_process_sme_tdls_mgmt_send_req(struct mac_context *mac_ctx,
3964 					      void *msg)
3965 {
3966 	struct tdls_send_mgmt_request *send_req = msg;
3967 	struct pe_session *session_entry;
3968 	uint8_t session_id;
3969 	uint16_t ie_len;
3970 	tSirResultCodes result_code = eSIR_SME_INVALID_PARAMETERS;
3971 
3972 	pe_debug("Send Mgmt Received");
3973 	session_entry = pe_find_session_by_bssid(mac_ctx,
3974 						 send_req->bssid.bytes,
3975 						 &session_id);
3976 	if (!session_entry) {
3977 		pe_err("PE Session does not exist for given sme session_id %d",
3978 		       send_req->session_id);
3979 		goto lim_tdls_send_mgmt_error;
3980 	}
3981 
3982 	/* check if we are in proper state to work as TDLS client */
3983 	if (!LIM_IS_STA_ROLE(session_entry)) {
3984 		pe_err("send mgmt received in wrong system Role: %d",
3985 		       GET_LIM_SYSTEM_ROLE(session_entry));
3986 		goto lim_tdls_send_mgmt_error;
3987 	}
3988 
3989 	if (lim_is_roam_synch_in_progress(mac_ctx->psoc, session_entry)) {
3990 		pe_err("roaming in progress, reject mgmt! for session %d",
3991 		       send_req->session_id);
3992 		result_code = eSIR_SME_REFUSED;
3993 		goto lim_tdls_send_mgmt_error;
3994 	}
3995 
3996 	/*
3997 	 * if we are still good, go ahead and check if we are in proper state to
3998 	 * do TDLS discovery req/rsp/....frames.
3999 	 */
4000 	if ((session_entry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
4001 	    (session_entry->limSmeState != eLIM_SME_LINK_EST_STATE)) {
4002 		pe_err("send mgmt received in invalid LIMsme state: %d",
4003 		       session_entry->limSmeState);
4004 		goto lim_tdls_send_mgmt_error;
4005 	}
4006 
4007 	cds_tdls_tx_rx_mgmt_event(ACTION_CATEGORY_TDLS,
4008 		SIR_MAC_ACTION_TX, SIR_MAC_MGMT_ACTION,
4009 		send_req->req_type, send_req->peer_mac.bytes);
4010 
4011 	ie_len = send_req->length - sizeof(*send_req);
4012 
4013 	switch (send_req->req_type) {
4014 	case TDLS_DISCOVERY_REQUEST:
4015 		pe_debug("Transmit Discovery Request Frame");
4016 		/* format TDLS discovery request frame and transmit it */
4017 		lim_send_tdls_dis_req_frame(mac_ctx, send_req->peer_mac,
4018 					    send_req->dialog, session_entry,
4019 					    send_req->ac);
4020 		result_code = eSIR_SME_SUCCESS;
4021 		break;
4022 	case TDLS_DISCOVERY_RESPONSE:
4023 		pe_debug("Transmit Discovery Response Frame");
4024 		/* Send a response mgmt action frame */
4025 		lim_send_tdls_dis_rsp_frame(mac_ctx, send_req->peer_mac,
4026 					    send_req->dialog, session_entry,
4027 					    send_req->add_ie, ie_len);
4028 		result_code = eSIR_SME_SUCCESS;
4029 		break;
4030 	case TDLS_SETUP_REQUEST:
4031 		pe_debug("Transmit Setup Request Frame");
4032 		lim_send_tdls_link_setup_req_frame(mac_ctx,
4033 						   send_req->peer_mac,
4034 						   send_req->dialog,
4035 						   session_entry,
4036 						   send_req->add_ie, ie_len,
4037 						   send_req->ac);
4038 		result_code = eSIR_SME_SUCCESS;
4039 		break;
4040 	case TDLS_SETUP_RESPONSE:
4041 		pe_debug("Transmit Setup Response Frame");
4042 		lim_send_tdls_setup_rsp_frame(mac_ctx,
4043 					      send_req->peer_mac,
4044 					      send_req->dialog, session_entry,
4045 					      send_req->status_code,
4046 					      send_req->add_ie, ie_len,
4047 					      send_req->ac);
4048 		result_code = eSIR_SME_SUCCESS;
4049 		break;
4050 	case TDLS_SETUP_CONFIRM:
4051 		pe_debug("Transmit Setup Confirm Frame");
4052 		lim_send_tdls_link_setup_cnf_frame(mac_ctx,
4053 						   send_req->peer_mac,
4054 						   send_req->dialog,
4055 						   send_req->peer_capability,
4056 						   session_entry,
4057 						   send_req->add_ie, ie_len,
4058 						   send_req->ac);
4059 		result_code = eSIR_SME_SUCCESS;
4060 		break;
4061 	case TDLS_TEARDOWN:
4062 		pe_debug("Transmit Teardown Frame");
4063 		lim_send_tdls_teardown_frame(mac_ctx,
4064 					     send_req->peer_mac,
4065 					     send_req->status_code,
4066 					     send_req->responder,
4067 					     session_entry,
4068 					     send_req->add_ie, ie_len,
4069 					     send_req->ac);
4070 		result_code = eSIR_SME_SUCCESS;
4071 		break;
4072 	case TDLS_PEER_TRAFFIC_INDICATION:
4073 		break;
4074 	case TDLS_CHANNEL_SWITCH_REQUEST:
4075 		break;
4076 	case TDLS_CHANNEL_SWITCH_RESPONSE:
4077 		break;
4078 	case TDLS_PEER_TRAFFIC_RESPONSE:
4079 		break;
4080 	default:
4081 		break;
4082 	}
4083 
4084 lim_tdls_send_mgmt_error:
4085 	lim_send_tdls_comp_mgmt_rsp(mac_ctx, eWNI_SME_TDLS_SEND_MGMT_RSP,
4086 				    result_code, send_req->session_id);
4087 
4088 	return QDF_STATUS_SUCCESS;
4089 }
4090 
4091 /*
4092  * Once link is teardown, send Del Peer Ind to SME
4093  */
4094 static QDF_STATUS lim_send_sme_tdls_del_sta_rsp(struct mac_context *mac,
4095 						uint8_t sessionId,
4096 						struct qdf_mac_addr peerMac,
4097 						tDphHashNode *sta, uint8_t status)
4098 {
4099 	struct scheduler_msg msg = { 0 };
4100 	struct tdls_del_sta_rsp *del_sta_rsp;
4101 	QDF_STATUS ret;
4102 
4103 	msg.type = eWNI_SME_TDLS_DEL_STA_RSP;
4104 
4105 	del_sta_rsp = qdf_mem_malloc(sizeof(*del_sta_rsp));
4106 	if (!del_sta_rsp)
4107 		return QDF_STATUS_E_NOMEM;
4108 
4109 	del_sta_rsp->session_id = sessionId;
4110 	del_sta_rsp->status_code = status;
4111 
4112 	qdf_copy_macaddr(&del_sta_rsp->peermac, &peerMac);
4113 
4114 	del_sta_rsp->psoc = mac->psoc;
4115 	msg.bodyptr = del_sta_rsp;
4116 	msg.callback = tgt_tdls_del_peer_rsp;
4117 	ret = scheduler_post_message(QDF_MODULE_ID_PE,
4118 				     QDF_MODULE_ID_TDLS,
4119 				     QDF_MODULE_ID_TARGET_IF, &msg);
4120 	if (QDF_IS_STATUS_ERROR(ret)) {
4121 		pe_err("post msg fail, %d", ret);
4122 		qdf_mem_free(del_sta_rsp);
4123 	}
4124 
4125 	return ret;
4126 }
4127 
4128 QDF_STATUS lim_process_sme_tdls_add_sta_req(struct mac_context *mac,
4129 					    void *msg)
4130 {
4131 	struct tdls_add_sta_req *add_sta_req = msg;
4132 	struct pe_session *pe_session;
4133 	uint8_t session_id;
4134 
4135 	pe_debug("TDLS Add STA Request Received");
4136 	pe_session =
4137 		pe_find_session_by_bssid(mac, add_sta_req->bssid.bytes,
4138 					 &session_id);
4139 	if (!pe_session) {
4140 		pe_err("PE Session does not exist for given sme sessionId: %d",
4141 		       add_sta_req->session_id);
4142 		goto lim_tdls_add_sta_error;
4143 	}
4144 
4145 	/* check if we are in proper state to work as TDLS client */
4146 	if (!LIM_IS_STA_ROLE(pe_session)) {
4147 		pe_err("send mgmt received in wrong system Role: %d",
4148 			  GET_LIM_SYSTEM_ROLE(pe_session));
4149 		goto lim_tdls_add_sta_error;
4150 	}
4151 
4152 	if (lim_is_roam_synch_in_progress(mac->psoc, pe_session)) {
4153 		pe_err("roaming in progress, reject add sta! for session %d",
4154 		       add_sta_req->session_id);
4155 		goto lim_tdls_add_sta_error;
4156 	}
4157 
4158 	/*
4159 	 * if we are still good, go ahead and check if we are in proper state to
4160 	 * do TDLS discovery req/rsp/....frames.
4161 	 */
4162 	if ((pe_session->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
4163 	    (pe_session->limSmeState != eLIM_SME_LINK_EST_STATE)) {
4164 		pe_err("send mgmt received in invalid LIMsme state: %d",
4165 			pe_session->limSmeState);
4166 		goto lim_tdls_add_sta_error;
4167 	}
4168 
4169 
4170 	/* To start with, send add STA request to HAL */
4171 	if (QDF_STATUS_E_FAILURE == lim_tdls_setup_add_sta(mac, add_sta_req, pe_session)) {
4172 		pe_err("Add TDLS Station request failed");
4173 		goto lim_tdls_add_sta_error;
4174 	}
4175 	return QDF_STATUS_SUCCESS;
4176 lim_tdls_add_sta_error:
4177 	lim_send_sme_tdls_add_sta_rsp(mac,
4178 				      add_sta_req->session_id,
4179 				      add_sta_req->peermac.bytes,
4180 				      (add_sta_req->tdls_oper == TDLS_OPER_UPDATE),
4181 				      NULL, QDF_STATUS_E_FAILURE);
4182 
4183 	return QDF_STATUS_SUCCESS;
4184 }
4185 
4186 QDF_STATUS lim_process_sme_tdls_del_sta_req(struct mac_context *mac,
4187 					    void *msg)
4188 {
4189 	struct tdls_del_sta_req *del_sta_req = msg;
4190 	struct pe_session *pe_session;
4191 	uint8_t session_id;
4192 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
4193 	tSirMacAddr peer;
4194 
4195 	pe_debug("TDLS Delete STA Request Received");
4196 	pe_session =
4197 		pe_find_session_by_bssid(mac, del_sta_req->bssid.bytes,
4198 					 &session_id);
4199 	if (!pe_session) {
4200 		pe_err("PE Session does not exist for given vdev id: %d",
4201 		       del_sta_req->session_id);
4202 		lim_send_sme_tdls_del_sta_rsp(mac, del_sta_req->session_id,
4203 					      del_sta_req->peermac, NULL,
4204 					      QDF_STATUS_E_FAILURE);
4205 		return QDF_STATUS_E_FAILURE;
4206 	}
4207 
4208 	/* check if we are in proper state to work as TDLS client */
4209 	if (!LIM_IS_STA_ROLE(pe_session)) {
4210 		pe_err("Del sta received in wrong system Role %d",
4211 		       GET_LIM_SYSTEM_ROLE(pe_session));
4212 		goto lim_tdls_del_sta_error;
4213 	}
4214 
4215 	if (lim_is_roam_synch_in_progress(mac->psoc, pe_session)) {
4216 		pe_err("roaming in progress, reject del sta! for session %d",
4217 		       del_sta_req->session_id);
4218 		lim_send_sme_tdls_del_sta_rsp(mac, del_sta_req->session_id,
4219 					      del_sta_req->peermac, NULL,
4220 					      QDF_STATUS_E_FAILURE);
4221 		return QDF_STATUS_E_FAILURE;
4222 	}
4223 
4224 	/*
4225 	 * if we are still good, go ahead and check if we are in proper state to
4226 	 * do TDLS discovery req/rsp/....frames.
4227 	 */
4228 	if ((pe_session->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
4229 	    (pe_session->limSmeState != eLIM_SME_LINK_EST_STATE)) {
4230 
4231 		pe_err("Del Sta received in invalid LIMsme state: %d",
4232 		       pe_session->limSmeState);
4233 		goto lim_tdls_del_sta_error;
4234 	}
4235 
4236 	qdf_mem_copy(peer, del_sta_req->peermac.bytes, sizeof(tSirMacAddr));
4237 	lim_send_deauth_mgmt_frame(mac, REASON_DEAUTH_NETWORK_LEAVING,
4238 				   peer, pe_session, false);
4239 	status = lim_tdls_del_sta(mac, del_sta_req->peermac,
4240 				  pe_session, true);
4241 	if (status == QDF_STATUS_SUCCESS)
4242 		return status;
4243 
4244 lim_tdls_del_sta_error:
4245 	lim_send_sme_tdls_del_sta_rsp(mac, pe_session->smeSessionId,
4246 				      del_sta_req->peermac, NULL, QDF_STATUS_E_FAILURE);
4247 
4248 	return status;
4249 }
4250 
4251 /**
4252  * lim_check_aid_and_delete_peer() - Function to check aid and delete peer
4253  * @p_mac: pointer to mac context
4254  * @session_entry: pointer to PE session
4255  *
4256  * This function verifies aid and delete's peer with that aid from hash table
4257  *
4258  * Return: None
4259  */
4260 static void lim_check_aid_and_delete_peer(struct mac_context *p_mac,
4261 					  struct pe_session *session_entry)
4262 {
4263 	tpDphHashNode stads = NULL;
4264 	int i, aid;
4265 	size_t aid_bitmap_size = sizeof(session_entry->peerAIDBitmap);
4266 	struct qdf_mac_addr mac_addr;
4267 	QDF_STATUS status;
4268 	/*
4269 	 * Check all the set bit in peerAIDBitmap and delete the peer
4270 	 * (with that aid) entry from the hash table and add the aid
4271 	 * in free pool
4272 	 */
4273 	for (i = 0; i < aid_bitmap_size / sizeof(uint32_t); i++) {
4274 		for (aid = 0; aid < (sizeof(uint32_t) << 3); aid++) {
4275 			if (!CHECK_BIT(session_entry->peerAIDBitmap[i], aid))
4276 				continue;
4277 			stads = dph_get_hash_entry(p_mac,
4278 					(aid + i * (sizeof(uint32_t) << 3)),
4279 					&session_entry->dph.dphHashTable);
4280 
4281 			if (!stads)
4282 				goto skip;
4283 
4284 			pe_debug("Deleting "QDF_MAC_ADDR_FMT,
4285 				QDF_MAC_ADDR_REF(stads->staAddr));
4286 
4287 			if (!lim_is_roam_synch_in_progress(p_mac->psoc,
4288 							   session_entry)) {
4289 				lim_send_deauth_mgmt_frame(p_mac,
4290 					REASON_DEAUTH_NETWORK_LEAVING,
4291 					stads->staAddr, session_entry, false);
4292 			}
4293 			/* Delete TDLS peer */
4294 			qdf_mem_copy(mac_addr.bytes, stads->staAddr,
4295 				     QDF_MAC_ADDR_SIZE);
4296 
4297 			status = lim_tdls_del_sta(p_mac, mac_addr,
4298 						  session_entry, false);
4299 
4300 			dph_delete_hash_entry(p_mac,
4301 				stads->staAddr, stads->assocId,
4302 				&session_entry->dph.dphHashTable);
4303 skip:
4304 			lim_release_peer_idx(p_mac,
4305 				(aid + i * (sizeof(uint32_t) << 3)),
4306 				session_entry);
4307 			CLEAR_BIT(session_entry->peerAIDBitmap[i], aid);
4308 		}
4309 	}
4310 }
4311 
4312 void lim_update_tdls_set_state_for_fw(struct pe_session *session_entry,
4313 				      bool value)
4314 {
4315 	session_entry->tdls_send_set_state_disable  = value;
4316 }
4317 
4318 void lim_update_tdls_2g_bw(struct pe_session *session)
4319 {
4320 	struct wlan_objmgr_psoc *psoc = NULL;
4321 
4322 	/*
4323 	 * For 2.4 GHz band, if AP switches its BW from 40 MHz to 20 Mhz, it
4324 	 * changes its beacon respectivily with ch_width 20 Mhz without STA
4325 	 * disconnection.
4326 	 * This will result in TDLS remaining on 40 MHz and not following APs BW
4327 	 * on 2.4 GHz.
4328 	 * Better Teardown the link here and with traffic going on between peers
4329 	 * the tdls connection will again be restablished with the new BW
4330 	 */
4331 	if (!wlan_reg_is_24ghz_ch_freq(session->curr_op_freq))
4332 		return;
4333 
4334 	psoc = wlan_vdev_get_psoc(session->vdev);
4335 	if (!psoc)
4336 		return;
4337 
4338 	wlan_tdls_teardown_links(psoc);
4339 }
4340 
4341 /**
4342  * lim_delete_tdls_peers() - delete tdls peers
4343  *
4344  * @mac_ctx - global MAC context
4345  * @session_entry - PE session entry
4346  *
4347  * Delete all the TDLS peer connected before leaving the BSS
4348  *
4349  * Return: QDF_STATUS_SUCCESS on success, error code otherwise
4350  */
4351 QDF_STATUS lim_delete_tdls_peers(struct mac_context *mac_ctx,
4352 				    struct pe_session *session_entry)
4353 {
4354 
4355 	if (!session_entry) {
4356 		pe_err("NULL session_entry");
4357 		return QDF_STATUS_E_FAILURE;
4358 	}
4359 
4360 	lim_check_aid_and_delete_peer(mac_ctx, session_entry);
4361 
4362 	tgt_tdls_delete_all_peers_indication(mac_ctx->psoc,
4363 					     session_entry->smeSessionId);
4364 
4365 	if (lim_is_roam_synch_in_progress(mac_ctx->psoc, session_entry))
4366 		return QDF_STATUS_SUCCESS;
4367 
4368 	/* In case of CSA, Only peers in lim and TDLS component
4369 	 * needs to be removed and set state disable command
4370 	 * should not be sent to fw as there is no way to enable
4371 	 * TDLS in FW after vdev restart.
4372 	 */
4373 	if (session_entry->tdls_send_set_state_disable) {
4374 		tgt_tdls_peers_deleted_notification(mac_ctx->psoc,
4375 						    session_entry->
4376 						    smeSessionId);
4377 	}
4378 
4379 	/* reset the set_state_disable flag */
4380 	session_entry->tdls_send_set_state_disable = true;
4381 	return QDF_STATUS_SUCCESS;
4382 }
4383 
4384 /**
4385  * lim_process_sme_del_all_tdls_peers(): process delete tdls peers
4386  * @p_mac: pointer to mac context
4387  * @msg_buf: message buffer
4388  *
4389  * This function processes request to delete tdls peers
4390  *
4391  * Return: Success: QDF_STATUS_SUCCESS Failure: Error value
4392  */
4393 QDF_STATUS lim_process_sme_del_all_tdls_peers(struct mac_context *p_mac,
4394 						 uint32_t *msg_buf)
4395 {
4396 	struct tdls_del_all_tdls_peers *msg;
4397 	struct pe_session *session_entry;
4398 	uint8_t session_id;
4399 
4400 	msg = (struct tdls_del_all_tdls_peers *)msg_buf;
4401 	if (!msg) {
4402 		pe_err("NULL msg");
4403 		return QDF_STATUS_E_FAILURE;
4404 	}
4405 
4406 	session_entry = pe_find_session_by_bssid(p_mac,
4407 						 msg->bssid.bytes, &session_id);
4408 	if (!session_entry) {
4409 		pe_debug("NULL pe_session");
4410 		return QDF_STATUS_E_FAILURE;
4411 	}
4412 
4413 	lim_check_aid_and_delete_peer(p_mac, session_entry);
4414 
4415 	tgt_tdls_peers_deleted_notification(p_mac->psoc,
4416 					    session_entry->smeSessionId);
4417 
4418 	return QDF_STATUS_SUCCESS;
4419 }
4420 
4421 /**
4422  * lim_process_tdls_del_sta_rsp() - Handle WDA_DELETE_STA_RSP for TDLS
4423  * @mac_ctx: Global MAC context
4424  * @lim_msg: LIM message
4425  * @pe_session: PE session
4426  *
4427  * Return: None
4428  */
4429 void lim_process_tdls_del_sta_rsp(struct mac_context *mac_ctx,
4430 				  struct scheduler_msg *lim_msg,
4431 				  struct pe_session *session_entry)
4432 {
4433 	tpDeleteStaParams del_sta_params = (tpDeleteStaParams) lim_msg->bodyptr;
4434 	tpDphHashNode sta_ds;
4435 	uint16_t peer_idx = 0;
4436 	struct qdf_mac_addr peer_mac;
4437 
4438 	if (!del_sta_params) {
4439 		pe_err("del_sta_params is NULL");
4440 		return;
4441 	}
4442 
4443 	qdf_mem_copy(peer_mac.bytes,
4444 		     del_sta_params->staMac, QDF_MAC_ADDR_SIZE);
4445 
4446 	sta_ds = dph_lookup_hash_entry(mac_ctx, del_sta_params->staMac,
4447 			&peer_idx, &session_entry->dph.dphHashTable);
4448 	if (!sta_ds) {
4449 		pe_err("DPH Entry for STA: %X is missing release the serialization command",
4450 		       DPH_STA_HASH_INDEX_PEER);
4451 		lim_send_sme_tdls_del_sta_rsp(mac_ctx,
4452 					      session_entry->smeSessionId,
4453 					      peer_mac, NULL,
4454 					      QDF_STATUS_SUCCESS);
4455 		goto skip_event;
4456 	}
4457 
4458 	if (QDF_STATUS_SUCCESS != del_sta_params->status) {
4459 		pe_err("DEL STA failed!");
4460 		lim_send_sme_tdls_del_sta_rsp(mac_ctx,
4461 				      session_entry->smeSessionId,
4462 				      peer_mac, NULL, QDF_STATUS_E_FAILURE);
4463 		goto skip_event;
4464 	}
4465 
4466 	pe_debug("DEL STA success");
4467 
4468 	/* now send indication to SME-->HDD->TL to remove STA from TL */
4469 
4470 	lim_send_sme_tdls_del_sta_rsp(mac_ctx, session_entry->smeSessionId,
4471 				      peer_mac, sta_ds,
4472 				      QDF_STATUS_SUCCESS);
4473 	lim_release_peer_idx(mac_ctx, sta_ds->assocId, session_entry);
4474 
4475 	/* Clear the aid in peerAIDBitmap as this aid is now in freepool */
4476 	CLEAR_PEER_AID_BITMAP(session_entry->peerAIDBitmap,
4477 			      sta_ds->assocId);
4478 	lim_delete_dph_hash_entry(mac_ctx, sta_ds->staAddr, sta_ds->assocId,
4479 				  session_entry);
4480 
4481 skip_event:
4482 	qdf_mem_free(del_sta_params);
4483 	lim_msg->bodyptr = NULL;
4484 }
4485 
4486 
4487 #endif
4488