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