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  *
22  * This file sch_api.cc contains functions related to the API exposed
23  * by scheduler module
24  *
25  * Author:      Sandesh Goel
26  * Date:        02/25/02
27  * History:-
28  * Date            Modified by    Modification Information
29  * --------------------------------------------------------------------
30  *
31  */
32 #include "cds_api.h"
33 #include "ani_global.h"
34 #include "wni_cfg.h"
35 
36 #include "sir_mac_prot_def.h"
37 #include "sir_mac_prop_exts.h"
38 #include "sir_common.h"
39 
40 #include "lim_api.h"
41 
42 #include "sch_api.h"
43 
44 #include "lim_trace.h"
45 #include "lim_types.h"
46 #include "lim_utils.h"
47 
48 #include "wma_types.h"
49 #include "lim_mlo.h"
50 
51 #include <target_if_vdev_mgr_tx_ops.h>
52 #include <wlan_cmn_ieee80211.h>
53 #include <wlan_mgmt_txrx_utils_api.h>
54 #include <wlan_p2p_cfg_api.h>
55 
56 /* Fils Discovery Frame */
57 /**
58  * struct fd_action_header - FILS Discovery Action frame header
59  * @action_header: WLAN Action frame header
60  * @fd_frame_cntl: FILS Discovery Frame Control
61  * @timestamp:     Time stamp
62  * @bcn_interval:  Beacon Interval
63  * @elem:          variable len sub element fields
64  */
65 struct fd_action_header {
66 	struct action_frm_hdr action_header;
67 	uint16_t              fd_frame_cntl;
68 	uint8_t               timestamp[WLAN_TIMESTAMP_LEN];
69 	uint16_t              bcn_interval;
70 	uint8_t               elem[];
71 } qdf_packed;
72 
73 /**
74  * struct tpe_ie - Transmit Power Enevolpe IE
75  * @tpe_header:           WLAN IE Header
76  * @max_tx_pwr_count:     Maximum Transmit Power Count
77  * @max_tx_pwr_interpret: Maximum Transmit Power Interpretation
78  * @max_tx_pwr_category:  Maximum Transmit Power category
79  * @tx_pwr_info:          Transmit power Information
80  * @elem:                 variable len sub element fields
81  */
82 struct tpe_ie {
83 	struct ie_header tpe_header;
84 	union {
85 		struct {
86 			uint8_t max_tx_pwr_count:3;
87 			uint8_t max_tx_pwr_interpret:3;
88 			uint8_t max_tx_pwr_category:2;
89 		};
90 		uint8_t tx_pwr_info;
91 	};
92 	uint8_t elem[];
93 } qdf_packed;
94 
95 #ifdef WLAN_FEATURE_11BE_MLO
96 /**
97  * lim_notify_link_info() - notify partner link to update beacon template
98  * @pe_session: pointer to pe session
99  *
100  * Return: void
101  */
lim_notify_link_info(struct pe_session * pe_session)102 static void lim_notify_link_info(struct pe_session *pe_session)
103 {
104 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS];
105 	uint16_t vdev_count = 0;
106 	int link;
107 
108 	if (!pe_session->mlo_link_info.upt_bcn_mlo_ie &&
109 	    !mlme_is_notify_co_located_ap_update_rnr(pe_session->vdev))
110 		return;
111 	pe_session->mlo_link_info.upt_bcn_mlo_ie = false;
112 	mlme_set_notify_co_located_ap_update_rnr(pe_session->vdev, false);
113 	pe_debug("vdev id %d mlo notify beacon change info to partner link",
114 		 wlan_vdev_get_id(pe_session->vdev));
115 	lim_get_mlo_vdev_list(pe_session, &vdev_count,
116 			      wlan_vdev_list);
117 	for (link = 0; link < vdev_count; link++) {
118 		if (!wlan_vdev_list[link])
119 			continue;
120 		if (wlan_vdev_list[link] == pe_session->vdev) {
121 			lim_mlo_release_vdev_ref(wlan_vdev_list[link]);
122 			continue;
123 		}
124 		lim_partner_link_info_change(wlan_vdev_list[link]);
125 		lim_mlo_release_vdev_ref(wlan_vdev_list[link]);
126 	}
127 }
128 
129 /**
130  * lim_update_sch_mlo_partner() - update partner information needed in mlo IE
131  * @mac: pointer to mac
132  * @pe_session: pointer to pe session
133  * @bcn_param: pointer to tpSendbeaconParams
134  *
135  * Return: void
136  */
lim_update_sch_mlo_partner(struct mac_context * mac,struct pe_session * pe_session,tpSendbeaconParams bcn_param)137 static void lim_update_sch_mlo_partner(struct mac_context *mac,
138 				       struct pe_session *pe_session,
139 				       tpSendbeaconParams bcn_param)
140 {
141 	int link;
142 	struct ml_sch_partner_info *sch_info;
143 	struct ml_bcn_partner_info *bcn_info;
144 
145 	bcn_param->mlo_partner.num_links = mac->sch.sch_mlo_partner.num_links;
146 	for (link = 0; link < mac->sch.sch_mlo_partner.num_links; link++) {
147 		sch_info = &mac->sch.sch_mlo_partner.partner_info[link];
148 		bcn_info = &bcn_param->mlo_partner.partner_info[link];
149 		bcn_info->vdev_id = sch_info->vdev_id;
150 		bcn_info->beacon_interval = sch_info->beacon_interval;
151 		bcn_info->csa_switch_count_offset = sch_info->bcn_csa_cnt_ofst;
152 		bcn_info->ext_csa_switch_count_offset =
153 					sch_info->bcn_ext_csa_cnt_ofst;
154 	}
155 }
156 #else
lim_notify_link_info(struct pe_session * pe_session)157 static void lim_notify_link_info(struct pe_session *pe_session)
158 {
159 }
160 
lim_update_sch_mlo_partner(struct mac_context * mac,struct pe_session * pe_session,tpSendbeaconParams bcn_param)161 static void lim_update_sch_mlo_partner(struct mac_context *mac,
162 				       struct pe_session *pe_session,
163 				       tpSendbeaconParams bcn_param)
164 {
165 }
166 #endif
167 
168 #ifdef WLAN_FEATURE_11BE
169 /**
170  * lim_fd_cap_channel_width320() - populate the capability field for
171  * 320 channel width in the fils discovery template
172  * @pe_session: pointer to pe session
173  * @fd_cap: pointer to fils discovery capability variable
174  *
175  * Return: void
176  */
lim_fd_cap_channel_width320(struct pe_session * pe_session,uint8_t * fd_cap)177 static void lim_fd_cap_channel_width320(struct pe_session *pe_session,
178 					uint8_t *fd_cap)
179 {
180 	if (pe_session->ch_width == CH_WIDTH_320MHZ) {
181 		*fd_cap |= (WLAN_FD_CHWIDTH_320 << WLAN_FD_CAP_BSS_CHWIDTH_S);
182 	} else {
183 		pe_err("channel width : %d is not supported",
184 		       pe_session->ch_width);
185 	}
186 }
187 
188 /**
189  * lim_populate_fd_capability() - populate the capability field for
190  * EHT phymode in the fils discovery template
191  * @cur_phymode: current phymode
192  * @fd_cap: pointer to fils discovery capability variable
193  *
194  * Return: void
195  */
lim_fd_cap_phymode_EHT(enum wlan_phymode phymode,uint8_t * fd_cap)196 static void lim_fd_cap_phymode_EHT(enum wlan_phymode phymode, uint8_t *fd_cap)
197 {
198 	switch (phymode) {
199 	case WLAN_PHYMODE_11BEA_EHT20:
200 	case WLAN_PHYMODE_11BEG_EHT20:
201 	case WLAN_PHYMODE_11BEA_EHT40:
202 	case WLAN_PHYMODE_11BEG_EHT40:
203 	case WLAN_PHYMODE_11BEG_EHT40PLUS:
204 	case WLAN_PHYMODE_11BEG_EHT40MINUS:
205 	case WLAN_PHYMODE_11BEA_EHT80:
206 	case WLAN_PHYMODE_11BEA_EHT160:
207 	case WLAN_PHYMODE_11BEA_EHT320:
208 		*fd_cap |= (WLAN_FD_CAP_PHY_INDEX_EHT <<
209 						WLAN_FD_CAP_PHY_INDEX_S);
210 		break;
211 	default:
212 		*fd_cap |= (WLAN_FD_CAP_PHY_INDEX_NON_HT_OFDM <<
213 						WLAN_FD_CAP_PHY_INDEX_S);
214 		break;
215 	}
216 }
217 #else
lim_fd_cap_channel_width320(struct pe_session * pe_session,uint8_t * fd_cap)218 static void lim_fd_cap_channel_width320(struct pe_session *pe_session,
219 					uint8_t *fd_cap)
220 {
221 	pe_err("channel width : %d is not supported", pe_session->ch_width);
222 }
223 
lim_fd_cap_phymode_EHT(enum wlan_phymode phymode,uint8_t * fd_cap)224 static void lim_fd_cap_phymode_EHT(enum wlan_phymode phymode, uint8_t *fd_cap)
225 {
226 	*fd_cap |= (WLAN_FD_CAP_PHY_INDEX_NON_HT_OFDM <<
227 						WLAN_FD_CAP_PHY_INDEX_S);
228 }
229 #endif /* WLAN_FEATURE_11BE */
230 
231 /**
232  * lim_populate_fd_capability() - populate the capability field in the
233  * fils discovery template
234  * @pe_session: pointer to pe session
235  * @cur_phymode: current phymode
236  * @fd_cap: pointer to fils discovery capability array
237  *
238  * Return: void
239  */
lim_populate_fd_capability(struct pe_session * pe_session,enum wlan_phymode cur_phymode,uint8_t * fd_cap)240 static void lim_populate_fd_capability(struct pe_session *pe_session,
241 				       enum wlan_phymode cur_phymode,
242 				       uint8_t *fd_cap)
243 {
244 	/* Setting ESS and Privacy bits */
245 	fd_cap[0] |= ((!WLAN_FD_CAP_ESS_ENABLE << WLAN_FD_CAP_ESS_S) |
246 		((pe_session->privacy) << WLAN_FD_CAP_PRIVACY_S));
247 
248 	/* Channel Width Selection */
249 	switch (pe_session->ch_width) {
250 	case CH_WIDTH_20MHZ:
251 		fd_cap[0] |= (WLAN_FD_CHWIDTH_20 << WLAN_FD_CAP_BSS_CHWIDTH_S);
252 		break;
253 	case CH_WIDTH_40MHZ:
254 		fd_cap[0] |= (WLAN_FD_CHWIDTH_40 << WLAN_FD_CAP_BSS_CHWIDTH_S);
255 		break;
256 	case CH_WIDTH_80MHZ:
257 		fd_cap[0] |= (WLAN_FD_CHWIDTH_80 << WLAN_FD_CAP_BSS_CHWIDTH_S);
258 		break;
259 	case CH_WIDTH_160MHZ:
260 	case CH_WIDTH_80P80MHZ:
261 		fd_cap[0] |= (WLAN_FD_CHWIDTH_160_80_80 <<
262 						WLAN_FD_CAP_BSS_CHWIDTH_S);
263 		break;
264 	default:
265 		lim_fd_cap_channel_width320(pe_session, &fd_cap[0]);
266 		break;
267 	}
268 
269 	/* Max Num of Spatial Steam */
270 	switch (pe_session->nss) {
271 	case WLAN_FD_CAP_NSS_MODE_1:
272 	case WLAN_FD_CAP_NSS_MODE_2:
273 		fd_cap[0] |= ((pe_session->nss - 1) << WLAN_FD_CAP_NSS_S);
274 		break;
275 	case WLAN_FD_CAP_NSS_MODE_3:
276 	case WLAN_FD_CAP_NSS_MODE_4:
277 	case WLAN_FD_CAP_NSS_MODE_5:
278 	case WLAN_FD_CAP_NSS_MODE_6:
279 	case WLAN_FD_CAP_NSS_MODE_7:
280 	case WLAN_FD_CAP_NSS_MODE_8:
281 		fd_cap[0] |= (WLAN_FD_CAP_NSS_GTE_5 << WLAN_FD_CAP_NSS_S);
282 		break;
283 	default:
284 		pe_err("NSS value: %d is not supported", pe_session->nss);
285 		break;
286 	}
287 
288 	/* Set PHY index */
289 	switch (cur_phymode) {
290 	case WLAN_PHYMODE_11AXA_HE20:
291 	case WLAN_PHYMODE_11AXG_HE20:
292 	case WLAN_PHYMODE_11AXA_HE40:
293 	case WLAN_PHYMODE_11AXG_HE40:
294 	case WLAN_PHYMODE_11AXG_HE40PLUS:
295 	case WLAN_PHYMODE_11AXG_HE40MINUS:
296 	case WLAN_PHYMODE_11AXA_HE80:
297 	case WLAN_PHYMODE_11AXA_HE160:
298 	case WLAN_PHYMODE_11AXA_HE80_80:
299 		fd_cap[1] |= (WLAN_FD_CAP_PHY_INDEX_HE <<
300 					WLAN_FD_CAP_PHY_INDEX_S);
301 		break;
302 	case WLAN_PHYMODE_11AC_VHT20:
303 	case WLAN_PHYMODE_11AC_VHT40:
304 	case WLAN_PHYMODE_11AC_VHT80:
305 	case WLAN_PHYMODE_11AC_VHT160:
306 	case WLAN_PHYMODE_11AC_VHT80_80:
307 		fd_cap[1] |= (WLAN_FD_CAP_PHY_INDEX_VHT <<
308 					WLAN_FD_CAP_PHY_INDEX_S);
309 		break;
310 	case WLAN_PHYMODE_11NA_HT20:
311 	case WLAN_PHYMODE_11NG_HT20:
312 	case WLAN_PHYMODE_11NG_HT40PLUS:
313 	case WLAN_PHYMODE_11NG_HT40MINUS:
314 	case WLAN_PHYMODE_11NG_HT40:
315 	case WLAN_PHYMODE_11NA_HT40:
316 		fd_cap[1] |= (WLAN_FD_CAP_PHY_INDEX_HT <<
317 					WLAN_FD_CAP_PHY_INDEX_S);
318 		break;
319 	default:
320 		lim_fd_cap_phymode_EHT(cur_phymode, &fd_cap[1]);
321 		break;
322 	}
323 
324 	/* FILS Min Rate */
325 	fd_cap[1] |= (WLAN_FD_CAP_MIN_RATE << WLAN_FD_CAP_MIN_RATE_S);
326 }
327 
328 /**
329  * lim_populate_fd_tmpl_frame() - populate the fils discovery frame
330  * @mac: pointer to mac structure
331  * @frm: pointer to fils discovery frame
332  * @pe_session:pointer to pe session
333  * @frame_size: pointer to fils discovery frame size
334  *
335  * return: success: QDF_STATUS_SUCCESS failure: QDF_STATUS_E_FAILURE
336  */
lim_populate_fd_tmpl_frame(struct mac_context * mac,struct pe_session * pe_session,uint8_t * frm,uint32_t * frame_size)337 static QDF_STATUS lim_populate_fd_tmpl_frame(struct mac_context *mac,
338 					     struct pe_session *pe_session,
339 					     uint8_t *frm, uint32_t *frame_size)
340 {
341 	uint16_t fd_cntl_subfield = 0;
342 	struct fd_action_header *fd_header;
343 	struct wlan_objmgr_vdev *vdev;
344 	uint8_t fd_cap[WLAN_FD_CAP_LEN] = {0};
345 	uint8_t length = 0;
346 	uint8_t ssid_len = 0, ssid[WLAN_SSID_MAX_LEN + 1] = {0};
347 	uint32_t shortssid;
348 	uint16_t chwidth = pe_session->ch_width;
349 	qdf_freq_t cur_chan_freq = pe_session->curr_op_freq;
350 	struct wlan_channel *des_chan;
351 	enum wlan_phymode cur_phymode;
352 	uint16_t tpe_num = 0;
353 	tDot11fIEtransmit_power_env tpe[WLAN_MAX_NUM_TPE_IE];
354 	struct tpe_ie *tpe_ie;
355 	uint8_t i, idx;
356 	tSirMacMgmtHdr *mac_hdr;
357 	struct qdf_mac_addr broadcast_mac_addr = QDF_MAC_ADDR_BCAST_INIT;
358 
359 	pe_debug("FD TMPL freq: %d chWidth: %d", cur_chan_freq, chwidth);
360 
361 	vdev = pe_session->vdev;
362 	if (!vdev) {
363 		pe_err("VDEV is NULL");
364 		return QDF_STATUS_E_FAILURE;
365 	}
366 
367 	des_chan = wlan_vdev_mlme_get_des_chan(vdev);
368 	if (!des_chan) {
369 		pe_err("des_chan is NULL");
370 		return QDF_STATUS_E_FAILURE;
371 	}
372 
373 	cur_phymode = des_chan->ch_phymode;
374 
375 	lim_populate_mac_header(mac, frm, SIR_MAC_MGMT_FRAME,
376 				SIR_MAC_MGMT_ACTION, broadcast_mac_addr.bytes,
377 				pe_session->self_mac_addr);
378 	mac_hdr = (tpSirMacMgmtHdr)frm;
379 	sir_copy_mac_addr(mac_hdr->bssId, pe_session->bssId);
380 	frm += sizeof(*mac_hdr);
381 	*frame_size = sizeof(*mac_hdr);
382 
383 	/* filling fd header */
384 	fd_header = (struct fd_action_header *)frm;
385 	fd_header->action_header.action_category = ACTION_CATEGORY_PUBLIC;
386 	fd_header->action_header.action_code  = WLAN_ACTION_FILS_DISCOVERY;
387 
388 	/*
389 	 * FILS DIscovery Frame Control Subfield - 2 byte
390 	 * Enable Short SSID
391 	 * When the Short SSID Indicator subfield is equal to 1,
392 	 * the SSID Length subfield is equal to 3
393 	 */
394 	fd_cntl_subfield = WLAN_FD_SSID_LEN_PRES(WLAN_FD_FRAMECNTL_SHORTSSID_LEN);
395 	fd_cntl_subfield |= WLAN_FD_FRAMECNTL_SHORTSSID;
396 
397 	if (wlan_reg_is_6ghz_chan_freq(cur_chan_freq)) {
398 		fd_cntl_subfield |= WLAN_FD_FRAMECNTL_CAP;
399 		length = WLAN_FD_CAP_LEN;
400 	}
401 
402 	/* For 80+80 set Channel center freq segment 1 */
403 	if (IS_WLAN_PHYMODE_160MHZ(cur_phymode)) {
404 		fd_cntl_subfield |= WLAN_FD_FRAMECNTL_CH_CENTERFREQ;
405 		length += 1;
406 	}
407 
408 	/* Update the length field */
409 	/*Indicates length from FD cap to Mobility Domain */
410 	if (length)
411 		fd_cntl_subfield |= WLAN_FD_FRAMECNTL_LEN_PRES;
412 
413 	/* FD Control - 2 bytes */
414 	fd_header->fd_frame_cntl = qdf_cpu_to_le16(fd_cntl_subfield);
415 
416 	/* Timestamp - 8 bytes */
417 	qdf_mem_zero(fd_header->timestamp, sizeof(fd_header->timestamp));
418 
419 	/* Beacon Interval - 2 bytes */
420 	fd_header->bcn_interval =
421 		qdf_cpu_to_le16(pe_session->beaconParams.beaconInterval);
422 
423 	*frame_size += sizeof(*fd_header);
424 
425 	/* Variable length data */
426 	frm = &fd_header->elem[0];
427 
428 	/* Short SSID - 4 bytes */
429 	wlan_vdev_mlme_get_ssid(vdev, ssid, &ssid_len);
430 	shortssid = wlan_construct_shortssid(ssid, ssid_len);
431 	*(uint32_t *)frm = qdf_cpu_to_le32(shortssid);
432 	frm += 4;
433 	*frame_size += 4;
434 
435 	/* Length - 1 byte */
436 	if (length) {
437 		*frm = length;
438 		pe_debug("length: %d", length);
439 		frm++;
440 		*frame_size += length + 1;
441 	}
442 
443 	/* FD Capabilities - 2 bytes */
444 	if (WLAN_FD_IS_CAP_PRESENT(fd_cntl_subfield)) {
445 		lim_populate_fd_capability(pe_session, cur_phymode, &fd_cap[0]);
446 		qdf_mem_copy(frm, fd_cap, WLAN_FD_CAP_LEN);
447 		frm += WLAN_FD_CAP_LEN;
448 	}
449 
450 	/* Channel Center Freq Segment 1 - 1 byte */
451 	if (WLAN_FD_IS_FRAMECNTL_CH_CENTERFREQ(fd_cntl_subfield)) {
452 		/* spec has seg0 and seg1 naming while we use seg1 and seg2 */
453 		*frm = des_chan->ch_freq_seg1;
454 		frm++;
455 	}
456 
457 	/* Add TPE IE */
458 	if ((wlan_reg_is_6ghz_chan_freq(cur_chan_freq)) ||
459 	    (pe_session->vhtCapability)) {
460 		populate_dot11f_tx_power_env(mac, &tpe[0], chwidth,
461 					     cur_chan_freq, &tpe_num, false);
462 		if (tpe_num > WLAN_MAX_NUM_TPE_IE) {
463 			pe_err("tpe_num  %d greater than max size", tpe_num);
464 			return QDF_STATUS_E_FAILURE;
465 		}
466 
467 		for (idx = 0; idx < tpe_num; idx++) {
468 			/* filling tpe_header header */
469 			tpe_ie = (struct tpe_ie *)frm;
470 			tpe_ie->tpe_header.ie_id = WLAN_ELEMID_VHT_TX_PWR_ENVLP;
471 
472 			if (tpe[idx].num_tx_power > WLAN_MAX_NUM_TPE_IE) {
473 				pe_err("num_tx_power %d greater than max num",
474 				       tpe[idx].num_tx_power);
475 				return QDF_STATUS_E_FAILURE;
476 			}
477 
478 			/* +1 for including tx power info */
479 			tpe_ie->tpe_header.ie_len  = tpe[idx].num_tx_power + 1;
480 
481 			if (tpe_ie->tpe_header.ie_len < WLAN_TPE_IE_MIN_LEN ||
482 			    tpe_ie->tpe_header.ie_len > WLAN_TPE_IE_MAX_LEN) {
483 				pe_err("tpe length %d less than min len or greater than max len",
484 				       tpe_ie->tpe_header.ie_len);
485 				return QDF_STATUS_E_FAILURE;
486 			}
487 
488 			tpe_ie->max_tx_pwr_count = tpe[idx].max_tx_pwr_count;
489 			tpe_ie->max_tx_pwr_interpret =
490 						tpe[idx].max_tx_pwr_interpret;
491 			tpe_ie->max_tx_pwr_category =
492 						tpe[idx].max_tx_pwr_category;
493 			frm = &tpe_ie->elem[0];
494 
495 			for (i = 0; i < tpe[idx].num_tx_power; i++) {
496 				*frm = tpe[idx].tx_power[i];
497 				frm++;
498 			}
499 
500 			/* +2 for including element id and length */
501 			*frame_size += tpe_ie->tpe_header.ie_len + 2;
502 		}
503 	}
504 
505 	return QDF_STATUS_SUCCESS;
506 }
507 
508 /**
509  * lim_send_fils_discovery_template() - send fils discovery template to
510  * target_if
511  * @mac: pointer to mac structure
512  * @pe_session:pe session
513  *
514  * return: status
515  */
lim_send_fils_discovery_template(struct mac_context * mac,struct pe_session * pe_session)516 static QDF_STATUS lim_send_fils_discovery_template(struct mac_context *mac,
517 						   struct pe_session *pe_session)
518 {
519 	struct fils_discovery_tmpl_params *fd_params;
520 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
521 	uint32_t n_bytes = sizeof(*fd_params);
522 
523 	fd_params = qdf_mem_malloc(n_bytes);
524 
525 	if (!fd_params)
526 		return QDF_STATUS_E_NOMEM;
527 
528 	fd_params->vdev_id = pe_session->vdev_id;
529 
530 	fd_params->frm = qdf_mem_malloc(SIR_MAX_FD_TMPL_SIZE);
531 	if (!(fd_params->frm)) {
532 		qdf_mem_free(fd_params);
533 		return QDF_STATUS_E_NOMEM;
534 	}
535 
536 	status = lim_populate_fd_tmpl_frame(mac, pe_session, fd_params->frm,
537 					    &n_bytes);
538 
539 	if (QDF_IS_STATUS_ERROR(status)) {
540 		pe_err("FAIL bytes %d retcode[%X]", n_bytes, status);
541 		goto memfree;
542 	}
543 
544 	fd_params->tmpl_len = n_bytes;
545 	fd_params->tmpl_len_aligned = roundup(fd_params->tmpl_len,
546 					      sizeof(uint32_t));
547 
548 	/* Sending data to wmi layer via target_if */
549 	status = target_if_vdev_mgr_send_fd_tmpl(pe_session->vdev,
550 						 fd_params);
551 	if (QDF_IS_STATUS_ERROR(status)) {
552 		pe_err("FAIL bytes %d retcode[%X]", n_bytes, status);
553 	}
554 
555 memfree:
556 	qdf_mem_free(fd_params->frm);
557 	qdf_mem_free(fd_params);
558 	return status;
559 }
560 
sch_send_beacon_req(struct mac_context * mac,uint8_t * beaconPayload,uint16_t size,struct pe_session * pe_session,enum sir_bcn_update_reason reason)561 QDF_STATUS sch_send_beacon_req(struct mac_context *mac, uint8_t *beaconPayload,
562 			       uint16_t size, struct pe_session *pe_session,
563 			       enum sir_bcn_update_reason reason)
564 {
565 	struct scheduler_msg msgQ = {0};
566 	tpSendbeaconParams beaconParams = NULL;
567 	QDF_STATUS retCode;
568 
569 	if (LIM_IS_AP_ROLE(pe_session) &&
570 	   (mac->sch.beacon_changed)) {
571 		retCode = lim_send_probe_rsp_template_to_hal(mac,
572 				pe_session,
573 				&pe_session->DefProbeRspIeBitmap[0]);
574 		if (QDF_STATUS_SUCCESS != retCode)
575 			pe_err("FAILED to send probe response template with retCode %d",
576 				retCode);
577 		/*Fils Discovery Template */
578 		retCode = lim_send_fils_discovery_template(mac, pe_session);
579 		if (QDF_STATUS_SUCCESS != retCode)
580 			pe_err("FAILED to send fils discovery template retCode %d",
581 			       retCode);
582 	}
583 
584 	beaconParams = qdf_mem_malloc(sizeof(tSendbeaconParams));
585 	if (!beaconParams)
586 		return QDF_STATUS_E_NOMEM;
587 
588 	msgQ.type = WMA_SEND_BEACON_REQ;
589 
590 	/* No Dialog Token reqd, as a response is not solicited */
591 	msgQ.reserved = 0;
592 
593 	/* Fill in tSendbeaconParams members */
594 	qdf_mem_copy(beaconParams->bssId, pe_session->bssId,
595 		     sizeof(pe_session->bssId));
596 
597 
598 	beaconParams->timIeOffset = pe_session->schBeaconOffsetBegin;
599 	if (pe_session->dfsIncludeChanSwIe) {
600 		beaconParams->csa_count_offset = mac->sch.csa_count_offset;
601 		beaconParams->ecsa_count_offset = mac->sch.ecsa_count_offset;
602 	}
603 	lim_update_sch_mlo_partner(mac, pe_session, beaconParams);
604 	beaconParams->vdev_id = pe_session->smeSessionId;
605 	beaconParams->reason = reason;
606 
607 	/* p2pIeOffset should be atleast greater than timIeOffset */
608 	if ((mac->sch.p2p_ie_offset != 0) &&
609 	    (mac->sch.p2p_ie_offset <
610 	     pe_session->schBeaconOffsetBegin)) {
611 		pe_err("Invalid p2pIeOffset:[%d]",
612 			mac->sch.p2p_ie_offset);
613 		QDF_ASSERT(0);
614 		qdf_mem_free(beaconParams);
615 		return QDF_STATUS_E_FAILURE;
616 	}
617 	beaconParams->p2pIeOffset = mac->sch.p2p_ie_offset;
618 
619 	if (size > SIR_MAX_BEACON_SIZE) {
620 		pe_err("beacon size (%d) exceed host limit %d",
621 		       size, SIR_MAX_BEACON_SIZE);
622 		QDF_ASSERT(0);
623 		qdf_mem_free(beaconParams);
624 		return QDF_STATUS_E_FAILURE;
625 	}
626 	qdf_mem_copy(beaconParams->beacon, beaconPayload, size);
627 
628 	beaconParams->beaconLength = (uint32_t) size;
629 	msgQ.bodyptr = beaconParams;
630 	msgQ.bodyval = 0;
631 
632 	MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, msgQ.type));
633 	retCode = wma_post_ctrl_msg(mac, &msgQ);
634 	if (QDF_STATUS_SUCCESS != retCode)
635 		pe_err("Posting SEND_BEACON_REQ to HAL failed, reason=%X",
636 			retCode);
637 
638 	if (QDF_IS_STATUS_SUCCESS(retCode)) {
639 		if (wlan_vdev_mlme_is_mlo_ap(pe_session->vdev))
640 			lim_notify_link_info(pe_session);
641 		else
642 			lim_ap_mlme_vdev_rnr_notify(pe_session);
643 	}
644 
645 	return retCode;
646 }
647 
lim_remove_p2p_ie_from_add_ie(struct mac_context * mac,struct pe_session * pe_session,uint8_t * addIeWoP2pIe,uint32_t * addnIELenWoP2pIe)648 static uint32_t lim_remove_p2p_ie_from_add_ie(struct mac_context *mac,
649 					      struct pe_session *pe_session,
650 					      uint8_t *addIeWoP2pIe,
651 					      uint32_t *addnIELenWoP2pIe)
652 {
653 	uint32_t left = pe_session->add_ie_params.probeRespDataLen;
654 	uint8_t *ptr = pe_session->add_ie_params.probeRespData_buff;
655 	uint8_t elem_id, elem_len;
656 	uint32_t offset = 0;
657 	uint8_t eid = 0xDD;
658 
659 	qdf_mem_copy(addIeWoP2pIe, ptr, left);
660 	*addnIELenWoP2pIe = left;
661 
662 	if (addIeWoP2pIe) {
663 		while (left >= 2) {
664 			elem_id  = ptr[0];
665 			elem_len = ptr[1];
666 			left -= 2;
667 			if (elem_len > left) {
668 				pe_err("Invalid IEs");
669 				return QDF_STATUS_E_FAILURE;
670 			}
671 			if ((elem_id == eid) &&
672 				(!qdf_mem_cmp(&ptr[2],
673 					"\x50\x6f\x9a\x09", 4))) {
674 				left -= elem_len;
675 				ptr += (elem_len + 2);
676 				qdf_mem_copy(&addIeWoP2pIe[offset], ptr, left);
677 				*addnIELenWoP2pIe -= (2 + elem_len);
678 			} else {
679 				left -= elem_len;
680 				ptr += (elem_len + 2);
681 				offset += 2 + elem_len;
682 			}
683 		}
684 	}
685 	return QDF_STATUS_SUCCESS;
686 }
687 
lim_send_probe_rsp_template_to_hal(struct mac_context * mac,struct pe_session * pe_session,uint32_t * IeBitmap)688 uint32_t lim_send_probe_rsp_template_to_hal(struct mac_context *mac,
689 					    struct pe_session *pe_session,
690 					    uint32_t *IeBitmap)
691 {
692 	struct scheduler_msg msgQ = {0};
693 	uint8_t *pFrame2Hal = pe_session->pSchProbeRspTemplate;
694 	tpSendProbeRespParams pprobeRespParams = NULL;
695 	uint32_t retCode = QDF_STATUS_E_FAILURE;
696 	uint32_t nPayload, nBytes = 0, nStatus;
697 	tpSirMacMgmtHdr pMacHdr;
698 	uint32_t addnIEPresent = false;
699 	uint8_t *addIE = NULL;
700 	uint8_t *addIeWoP2pIe = NULL;
701 	uint32_t addnIELenWoP2pIe = 0;
702 	uint32_t retStatus;
703 	tDot11fIEExtCap extracted_extcap;
704 	bool extcap_present = false;
705 	tDot11fProbeResponse *prb_rsp_frm;
706 	QDF_STATUS status;
707 	uint16_t addn_ielen = 0;
708 	uint16_t mlo_ie_len;
709 
710 	/* Check if probe response IE is present or not */
711 	addnIEPresent = (pe_session->add_ie_params.probeRespDataLen != 0);
712 	if (addnIEPresent) {
713 		/*
714 		* probe response template should not have P2P IE.
715 		* In case probe request has P2P IE or WPS IE, the
716 		* probe request will be forwarded to the Host and
717 		* Host will send the probe response. In other cases
718 		* FW will send the probe response. So, if the template
719 		* has P2P IE, the probe response sent to non P2P devices
720 		* by the FW, may also have P2P IE which will fail
721 		* P2P cert case 6.1.3
722 		*/
723 		addIeWoP2pIe = qdf_mem_malloc(pe_session->add_ie_params.
724 						probeRespDataLen);
725 		if (!addIeWoP2pIe)
726 			return QDF_STATUS_E_NOMEM;
727 
728 		retStatus = lim_remove_p2p_ie_from_add_ie(mac, pe_session,
729 					addIeWoP2pIe, &addnIELenWoP2pIe);
730 		if (retStatus != QDF_STATUS_SUCCESS) {
731 			qdf_mem_free(addIeWoP2pIe);
732 			return QDF_STATUS_E_FAILURE;
733 		}
734 
735 		/* Probe rsp IE available */
736 		/*need to check the data length */
737 		addIE = qdf_mem_malloc(addnIELenWoP2pIe);
738 		if (!addIE) {
739 			qdf_mem_free(addIeWoP2pIe);
740 			return QDF_STATUS_E_NOMEM;
741 		}
742 		addn_ielen = addnIELenWoP2pIe;
743 
744 		if (addn_ielen <= WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN &&
745 		    addn_ielen && (nBytes + addn_ielen) <= SIR_MAX_PACKET_SIZE)
746 			qdf_mem_copy(addIE, addIeWoP2pIe, addnIELenWoP2pIe);
747 
748 		qdf_mem_free(addIeWoP2pIe);
749 
750 		qdf_mem_zero((uint8_t *)&extracted_extcap,
751 			     sizeof(tDot11fIEExtCap));
752 		status = lim_strip_extcap_update_struct(mac, addIE,
753 				&addn_ielen, &extracted_extcap);
754 		if (QDF_STATUS_SUCCESS != status) {
755 			pe_debug("extcap not extracted");
756 		} else {
757 			extcap_present = true;
758 		}
759 	}
760 
761 	/*
762 	 * Extcap IE now support variable length, merge Extcap IE from addn_ie
763 	 * may change the frame size. Therefore, MUST merge ExtCap IE before
764 	 * dot11f get packed payload size.
765 	 */
766 	prb_rsp_frm = &pe_session->probeRespFrame;
767 	if (extcap_present) {
768 		lim_merge_extcap_struct(&prb_rsp_frm->ExtCap,
769 					&extracted_extcap,
770 					true);
771 		populate_dot11f_bcn_prot_extcaps(mac, pe_session,
772 						 &prb_rsp_frm->ExtCap);
773 	}
774 
775 	nStatus = dot11f_get_packed_probe_response_size(mac,
776 			&pe_session->probeRespFrame, &nPayload);
777 	if (DOT11F_FAILED(nStatus)) {
778 		pe_err("Failed to calculate the packed size for a Probe Response (0x%08x)",
779 			nStatus);
780 		/* We'll fall back on the worst case scenario: */
781 		nPayload = sizeof(tDot11fProbeResponse);
782 	} else if (DOT11F_WARNED(nStatus)) {
783 		pe_err("There were warnings while calculating the packed size for a Probe Response (0x%08x)",
784 			nStatus);
785 	}
786 
787 	mlo_ie_len = lim_get_frame_mlo_ie_len(pe_session);
788 	nBytes += nPayload + sizeof(tSirMacMgmtHdr) + mlo_ie_len;
789 
790 	if (addnIEPresent) {
791 		if ((nBytes + addn_ielen) <= SIR_MAX_PROBE_RESP_SIZE)
792 			nBytes += addn_ielen;
793 		else
794 			addnIEPresent = false;  /* Dont include the IE. */
795 	}
796 
797 	/* Make sure we are not exceeding allocated len */
798 	if (nBytes > SIR_MAX_PROBE_RESP_SIZE) {
799 		pe_err("nBytes %d greater than max size", nBytes);
800 		qdf_mem_free(addIE);
801 		return QDF_STATUS_E_FAILURE;
802 	}
803 
804 	/* Paranoia: */
805 	qdf_mem_zero(pFrame2Hal, nBytes);
806 
807 	/* Next, we fill out the buffer descriptor: */
808 	lim_populate_mac_header(mac, pFrame2Hal, SIR_MAC_MGMT_FRAME,
809 					     SIR_MAC_MGMT_PROBE_RSP,
810 					     pe_session->self_mac_addr,
811 					     pe_session->self_mac_addr);
812 
813 	pMacHdr = (tpSirMacMgmtHdr) pFrame2Hal;
814 
815 	sir_copy_mac_addr(pMacHdr->bssId, pe_session->bssId);
816 
817 	/* That done, pack the Probe Response: */
818 	nStatus =
819 		dot11f_pack_probe_response(mac, &pe_session->probeRespFrame,
820 					   pFrame2Hal + sizeof(tSirMacMgmtHdr),
821 					   nPayload, &nPayload);
822 
823 	if (DOT11F_FAILED(nStatus)) {
824 		pe_err("Failed to pack a Probe Response (0x%08x)",
825 			nStatus);
826 
827 		qdf_mem_free(addIE);
828 		return retCode; /* allocated! */
829 	} else if (DOT11F_WARNED(nStatus)) {
830 		pe_warn("There were warnings while packing a P"
831 			"robe Response (0x%08x)", nStatus);
832 	}
833 
834 	if (mlo_ie_len) {
835 		status = lim_fill_complete_mlo_ie(pe_session, mlo_ie_len,
836 					 pFrame2Hal + sizeof(tSirMacMgmtHdr) +
837 					      nPayload);
838 		if (QDF_IS_STATUS_ERROR(status)) {
839 			pe_debug("assemble ml ie error");
840 			mlo_ie_len = 0;
841 		}
842 		nPayload += mlo_ie_len;
843 	}
844 
845 	if (addnIEPresent) {
846 		qdf_mem_copy(&pFrame2Hal[nBytes - addn_ielen],
847 			     &addIE[0], addn_ielen);
848 	}
849 
850 	qdf_mem_free(addIE);
851 
852 	pprobeRespParams = qdf_mem_malloc(sizeof(tSendProbeRespParams));
853 	if (!pprobeRespParams) {
854 		pe_err("malloc failed for bytes %d", nBytes);
855 	} else {
856 		sir_copy_mac_addr(pprobeRespParams->bssId, pe_session->bssId);
857 		qdf_mem_copy(pprobeRespParams->probeRespTemplate,
858 			     pFrame2Hal, nBytes);
859 		pprobeRespParams->probeRespTemplateLen = nBytes;
860 		qdf_mem_copy(pprobeRespParams->ucProxyProbeReqValidIEBmap,
861 			     IeBitmap, (sizeof(uint32_t) * 8));
862 		if (pe_session->opmode == QDF_P2P_GO_MODE &&
863 		    cfg_p2p_is_go_ignore_non_p2p_probe_req(mac->psoc)) {
864 			pe_debug("GO ignore non-P2P probe req");
865 			pprobeRespParams->go_ignore_non_p2p_probe_req = true;
866 		}
867 
868 		msgQ.type = WMA_SEND_PROBE_RSP_TMPL;
869 		msgQ.reserved = 0;
870 		msgQ.bodyptr = pprobeRespParams;
871 		msgQ.bodyval = 0;
872 
873 		retCode = wma_post_ctrl_msg(mac, &msgQ);
874 		if (QDF_STATUS_SUCCESS != retCode) {
875 			pe_err("FAIL bytes %d retcode[%X]", nBytes, retCode);
876 			qdf_mem_free(pprobeRespParams);
877 		}
878 	}
879 
880 	return retCode;
881 }
882 
883 /**
884  * sch_gen_timing_advert_frame() - Generate the TA frame and populate the buffer
885  * @mac: the global MAC context
886  * @self_addr: the self MAC address
887  * @buf: the buffer that will contain the frame
888  * @timestamp_offset: return for the offset of the timestamp field
889  * @time_value_offset: return for the time_value field in the TA IE
890  *
891  * Return: the length of the buffer on success and error code on failure.
892  */
sch_gen_timing_advert_frame(struct mac_context * mac_ctx,tSirMacAddr self_addr,uint8_t ** buf,uint32_t * timestamp_offset,uint32_t * time_value_offset)893 int sch_gen_timing_advert_frame(struct mac_context *mac_ctx, tSirMacAddr self_addr,
894 	uint8_t **buf, uint32_t *timestamp_offset, uint32_t *time_value_offset)
895 {
896 	tDot11fTimingAdvertisementFrame frame = {};
897 	uint32_t payload_size, buf_size;
898 	QDF_STATUS status;
899 	uint32_t ret;
900 	struct qdf_mac_addr wildcard_bssid = {
901 		{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
902 	};
903 
904 	/* Populate the TA fields */
905 	status = populate_dot11f_timing_advert_frame(mac_ctx, &frame);
906 	if (!QDF_IS_STATUS_SUCCESS(status)) {
907 		pe_err("Error populating TA frame %x", status);
908 		return qdf_status_to_os_return(status);
909 	}
910 
911 	ret = dot11f_get_packed_timing_advertisement_frame_size(mac_ctx,
912 		&frame, &payload_size);
913 	if (DOT11F_FAILED(ret)) {
914 		pe_err("Error getting packed frame size %x", ret);
915 		return -EINVAL;
916 	}
917 	if (DOT11F_WARNED(ret))
918 		pe_warn("Warning getting packed frame size");
919 
920 	buf_size = sizeof(tSirMacMgmtHdr) + payload_size;
921 	*buf = qdf_mem_malloc(buf_size);
922 	if (!*buf)
923 		return -ENOMEM;
924 
925 	payload_size = 0;
926 	ret = dot11f_pack_timing_advertisement_frame(mac_ctx, &frame,
927 		*buf + sizeof(tSirMacMgmtHdr), buf_size -
928 		sizeof(tSirMacMgmtHdr), &payload_size);
929 	pe_debug("TA payload size2 = %d", payload_size);
930 	if (DOT11F_FAILED(ret)) {
931 		pe_err("Error packing frame %x", ret);
932 		goto fail;
933 	}
934 	if (DOT11F_WARNED(ret))
935 		pe_warn("Warning packing frame");
936 
937 	lim_populate_mac_header(mac_ctx, *buf, SIR_MAC_MGMT_FRAME,
938 		SIR_MAC_MGMT_TIME_ADVERT, wildcard_bssid.bytes, self_addr);
939 
940 	/* The timestamp field is right after the header */
941 	*timestamp_offset = sizeof(tSirMacMgmtHdr);
942 
943 	*time_value_offset = sizeof(tSirMacMgmtHdr) +
944 		sizeof(tDot11fFfTimeStamp) + sizeof(tDot11fFfCapabilities);
945 
946 	/* Add the Country IE length */
947 	dot11f_get_packed_ie_country(mac_ctx, &frame.Country,
948 		time_value_offset);
949 	/* Add 2 for Country IE EID and Length fields */
950 	*time_value_offset += 2;
951 
952 	/* Add the PowerConstraint IE size */
953 	if (frame.Country.present == 1)
954 		*time_value_offset += 3;
955 
956 	/* Add the offset inside TA IE */
957 	*time_value_offset += 3;
958 
959 	return payload_size + sizeof(tSirMacMgmtHdr);
960 
961 fail:
962 	qdf_mem_free(*buf);
963 	*buf = NULL;
964 	return -EINVAL;
965 }
966