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