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
lim_trace_tdls_action_string(uint8_t tdlsActionCode)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 */
lim_init_tdls_data(struct mac_context * mac,struct pe_session * pe_session)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
is_duplicate_chan(uint8_t * arr,uint8_t index,uint8_t ch_id)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
populate_dot11f_tdls_offchannel_params(struct mac_context * mac,struct pe_session * pe_session,tDot11fIESuppChannels * suppChannels,tDot11fIESuppOperatingClasses * suppOperClasses)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 */
lim_tdls_copy_self_mac(struct pe_session * session,uint8_t * init_sta_addr)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
lim_tdls_copy_self_mac(struct pe_session * session,uint8_t * init_sta_addr)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
populate_dot11f_link_iden(struct mac_context * mac,struct pe_session * pe_session,tDot11fIELinkIdentifier * linkIden,struct qdf_mac_addr peer_mac,uint8_t reqType)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
populate_dot11f_tdls_ext_capability(struct mac_context * mac,struct pe_session * pe_session,tDot11fIEExtCap * extCapability)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 */
lim_prepare_tdls_frame_header(struct mac_context * mac,uint8_t * pFrame,tDot11fIELinkIdentifier * link_iden,uint8_t tdlsLinkType,uint8_t reqType,uint8_t tid,struct pe_session * pe_session)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 */
lim_mgmt_tdls_tx_complete(void * context,qdf_nbuf_t buf,uint32_t tx_complete,void * params)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 */
lim_get_assoc_link_vdev_id(struct pe_session * session)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
lim_get_assoc_link_vdev_id(struct pe_session * session)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 */
lim_send_tdls_dis_req_frame(struct mac_context * mac,struct qdf_mac_addr peer_mac,uint8_t dialog,struct pe_session * pe_session,enum wifi_traffic_ac ac)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 */
populate_dot11f_tdls_ht_vht_cap(struct mac_context * mac,uint32_t selfDot11Mode,tDot11fIEHTCaps * htCap,tDot11fIEVHTCaps * vhtCap,struct pe_session * pe_session)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
lim_tdls_populate_dot11f_6hgz_he_caps(struct mac_context * mac,struct tdls_add_sta_req * add_sta_req,tDot11fIEhe_6ghz_band_cap * pDot11f)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
lim_populate_tdls_setup_6g_cap(struct mac_context * mac,tDot11fIEhe_6ghz_band_cap * hecap_6g,struct pe_session * session)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
lim_tdls_populate_dot11f_6hgz_he_caps(struct mac_context * mac,struct tdls_add_sta_req * add_sta_req,tDot11fIEhe_6ghz_band_cap * pDot11f)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
lim_populate_tdls_setup_6g_cap(struct mac_context * mac,tDot11fIEhe_6ghz_band_cap * hecap_6g,struct pe_session * session)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
lim_fill_session_he_width(struct pe_session * session,tDot11fIEhe_cap * heCap)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
lim_tdls_set_he_chan_width(struct mac_context * mac,tDot11fIEhe_cap * heCap,struct pe_session * session,bool wideband_sta)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
lim_tdls_populate_ppe_caps(struct mac_context * mac,struct pe_session * session,tDot11fIEhe_cap * he_cap)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
populate_dot11f_set_tdls_he_cap(struct mac_context * mac,uint32_t selfDot11Mode,tDot11fIEhe_cap * heCap,tDot11fIEhe_6ghz_band_cap * hecap_6g,struct pe_session * session)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
lim_tdls_fill_dis_rsp_he_cap(struct mac_context * mac,uint32_t selfDot11Mode,tDot11fTDLSDisRsp * tdls_dis_rsp,struct pe_session * pe_session)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
lim_tdls_fill_setup_req_he_cap(struct mac_context * mac,uint32_t selfDot11Mode,tDot11fTDLSSetupReq * tdls_setup_req,struct pe_session * pe_session)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
lim_tdls_fill_setup_rsp_he_cap(struct mac_context * mac,uint32_t selfDot11Mode,tDot11fTDLSSetupRsp * tdls_setup_rsp,struct pe_session * pe_session)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
lim_tdls_populate_he_operations(struct mac_context * mac,struct pe_session * pe_session,tDot11fIEhe_op * he_op)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
lim_tdls_fill_setup_cnf_he_op(struct mac_context * mac,uint32_t peer_capability,tDot11fTDLSSetupCnf * tdls_setup_cnf,struct pe_session * pe_session)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
lim_tdls_fill_he_wideband_offchannel_mcs(struct mac_context * mac_ctx,tpDphHashNode stads,uint8_t nss,struct pe_session * session)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
lim_tdls_populate_he_matching_rate_set(struct mac_context * mac_ctx,tpDphHashNode stads,uint8_t nss,struct pe_session * session)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
lim_tdls_populate_dot11f_he_caps(struct mac_context * mac,struct tdls_add_sta_req * add_sta_req,tDot11fIEhe_cap * pDot11f)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
lim_tdls_check_and_force_he_ldpc_cap(struct pe_session * pe_session,tDphHashNode * sta)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
lim_tdls_get_he_ch_width(struct pe_session * pe_session,tDot11fIEhe_cap * he_cap)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
lim_tdls_update_node_he_caps(struct mac_context * mac,struct tdls_add_sta_req * add_sta_req,tDphHashNode * sta,struct pe_session * pe_session,bool wide_band_peer)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
lim_tdls_fill_dis_rsp_he_cap(struct mac_context * mac,uint32_t selfDot11Mode,tDot11fTDLSDisRsp * tdls_dis_rsp,struct pe_session * pe_session)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
lim_tdls_fill_setup_req_he_cap(struct mac_context * mac,uint32_t selfDot11Mode,tDot11fTDLSSetupReq * tdls_setup_req,struct pe_session * pe_session)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
lim_tdls_fill_setup_rsp_he_cap(struct mac_context * mac,uint32_t selfDot11Mode,tDot11fTDLSSetupRsp * tdls_setup_rsp,struct pe_session * pe_session)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
lim_tdls_fill_setup_cnf_he_op(struct mac_context * mac,uint32_t peer_capability,tDot11fTDLSSetupCnf * tdls_setup_cnf,struct pe_session * pe_session)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
lim_tdls_populate_he_matching_rate_set(struct mac_context * mac_ctx,tpDphHashNode stads,uint8_t nss,struct pe_session * session)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
lim_tdls_update_node_he_caps(struct mac_context * mac,struct tdls_add_sta_req * add_sta_req,tDphHashNode * sta,struct pe_session * pe_session,bool wide_band_peer)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
lim_tdls_check_and_force_he_ldpc_cap(struct pe_session * pe_session,tDphHashNode * sta)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 *
lim_ieee80211_pack_ehtcap_tdls(struct mac_context * mac,struct pe_session * pe_session,uint8_t * len)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 *
lim_ieee80211_pack_ehtcap_tdls(struct mac_context * mac,struct pe_session * pe_session,uint8_t * len)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 */
lim_send_tdls_dis_rsp_frame(struct mac_context * mac,struct qdf_mac_addr peer_mac,uint8_t dialog,struct pe_session * pe_session,uint8_t * addIe,uint16_t addIeLen)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 */
populate_dotf_tdls_vht_aid(struct mac_context * mac,uint32_t selfDot11Mode,struct qdf_mac_addr peerMac,tDot11fIEAID * Aid,struct pe_session * pe_session)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
wma_tx_frame_with_tx_complete_send(struct mac_context * mac,void * pPacket,uint16_t nBytes,uint8_t tid,uint8_t * pFrame,uint8_t smeSessionId,bool flag)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
wma_tx_frame_with_tx_complete_send(struct mac_context * mac,void * pPacket,uint16_t nBytes,uint8_t tid,uint8_t * pFrame,uint8_t smeSessionId,bool flag)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
lim_is_wide_band_set(uint8_t * ext_capability)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
lim_send_tdls_link_setup_req_frame(struct mac_context * mac,struct qdf_mac_addr peer_mac,uint8_t dialog,struct pe_session * pe_session,uint8_t * addIe,uint16_t addIeLen,enum wifi_traffic_ac ac)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
lim_send_tdls_teardown_frame(struct mac_context * mac,struct qdf_mac_addr peer_mac,uint16_t reason,uint8_t responder,struct pe_session * pe_session,uint8_t * addIe,uint16_t addIeLen,enum wifi_traffic_ac ac)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
lim_send_tdls_setup_rsp_frame(struct mac_context * mac,struct qdf_mac_addr peer_mac,uint8_t dialog,struct pe_session * pe_session,etdlsLinkSetupStatus setupStatus,uint8_t * addIe,uint16_t addIeLen,enum wifi_traffic_ac ac)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
lim_send_tdls_link_setup_cnf_frame(struct mac_context * mac,struct qdf_mac_addr peer_mac,uint8_t dialog,uint32_t peerCapability,struct pe_session * pe_session,uint8_t * addIe,uint16_t addIeLen,enum wifi_traffic_ac ac)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
lim_tdls_populate_dot11f_ht_caps(struct mac_context * mac,struct pe_session * pe_session,struct tdls_add_sta_req * add_sta_req,tDot11fIEHTCaps * pDot11f)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
lim_tdls_populate_dot11f_vht_caps(struct mac_context * mac,struct tdls_add_sta_req * add_sta_req,tDot11fIEVHTCaps * pDot11f)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
lim_tdls_populate_eht_mcs(struct mac_context * mac_ctx,tpDphHashNode stads,struct pe_session * session_entry)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->ch_width);
3337 }
3338 #else
3339 static void
lim_tdls_populate_eht_mcs(struct mac_context * mac_ctx,tpDphHashNode stads,struct pe_session * session_entry)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
lim_tdls_populate_matching_rate_set(struct mac_context * mac_ctx,tpDphHashNode stads,uint8_t * supp_rate_set,uint8_t supp_rates_len,uint8_t * supp_mcs_set,struct pe_session * session_entry,tDot11fIEVHTCaps * vht_caps)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
lim_tdls_fill_session_vht_width(struct pe_session * pe_session,tDphHashNode * sta)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
lim_reg_bw_to_ht_ch_width(uint16_t reg_max_bw)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
lim_tdls_populate_dot11f_eht_caps(struct pe_session * pe_session,tDphHashNode * sta,struct tdls_add_sta_req * add_sta_req)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
lim_tdls_populate_dot11f_eht_caps(struct pe_session * pe_session,tDphHashNode * sta,struct tdls_add_sta_req * add_sta_req)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 */
lim_tdls_update_hash_node_info(struct mac_context * mac,tDphHashNode * sta,struct tdls_add_sta_req * add_sta_req,struct pe_session * pe_session)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 */
lim_tdls_setup_add_sta(struct mac_context * mac,struct tdls_add_sta_req * pAddStaReq,struct pe_session * pe_session)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 */
lim_tdls_del_sta(struct mac_context * mac,struct qdf_mac_addr peerMac,struct pe_session * pe_session,bool resp_reqd)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 */
lim_send_sme_tdls_add_sta_rsp(struct mac_context * mac,uint8_t sessionId,tSirMacAddr peerMac,uint8_t updateSta,tDphHashNode * sta,uint8_t status)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 */
lim_process_tdls_add_sta_rsp(struct mac_context * mac,void * msg,struct pe_session * pe_session)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
lim_send_tdls_comp_mgmt_rsp(struct mac_context * mac_ctx,uint16_t msg_type,tSirResultCodes result_code,uint8_t vdev_id)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
lim_process_sme_tdls_mgmt_send_req(struct mac_context * mac_ctx,void * msg)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 */
lim_send_sme_tdls_del_sta_rsp(struct mac_context * mac,uint8_t sessionId,struct qdf_mac_addr peerMac,tDphHashNode * sta,uint8_t status)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
lim_process_sme_tdls_add_sta_req(struct mac_context * mac,void * msg)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
lim_process_sme_tdls_del_sta_req(struct mac_context * mac,void * msg)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 */
lim_check_aid_and_delete_peer(struct mac_context * p_mac,struct pe_session * session_entry)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
lim_update_tdls_set_state_for_fw(struct pe_session * session_entry,bool value)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
lim_update_tdls_2g_bw(struct pe_session * session)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 */
lim_delete_tdls_peers(struct mac_context * mac_ctx,struct pe_session * session_entry)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 */
lim_process_sme_del_all_tdls_peers(struct mac_context * p_mac,uint32_t * msg_buf)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 */
lim_process_tdls_del_sta_rsp(struct mac_context * mac_ctx,struct scheduler_msg * lim_msg,struct pe_session * session_entry)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