xref: /wlan-dirver/qcacld-3.0/core/hdd/src/wlan_hdd_eht.c (revision 2933838e5c361d2ceff0278c7bf3d087c9189fff)
1 /*
2  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /**
19  * DOC: wlan_hdd_eht.c
20  *
21  * WLAN Host Device Driver file for 802.11be (Extremely High Throughput)
22  * support.
23  *
24  */
25 
26 #include "wlan_hdd_main.h"
27 #include "wlan_hdd_eht.h"
28 #include "osif_sync.h"
29 #include "wlan_utility.h"
30 #include "wlan_mlme_ucfg_api.h"
31 #include "qc_sap_ioctl.h"
32 #include "wma_api.h"
33 #include "wlan_osif_features.h"
34 #include "wlan_psoc_mlme_ucfg_api.h"
35 
36 #if defined(WLAN_FEATURE_11BE) && defined(CFG80211_11BE_BASIC)
37 #define CHAN_WIDTH_SET_40MHZ_IN_2G \
38 	IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G
39 #define CHAN_WIDTH_SET_40MHZ_80MHZ_IN_5G \
40 	IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G
41 #define CHAN_WIDTH_SET_160MHZ_IN_5G \
42 	IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G
43 #define CHAN_WIDTH_SET_80PLUS80_MHZ_IN_5G \
44 	IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G
45 
46 void hdd_update_tgt_eht_cap(struct hdd_context *hdd_ctx,
47 			    struct wma_tgt_cfg *cfg)
48 {
49 	tDot11fIEeht_cap eht_cap_ini = {0};
50 
51 	ucfg_mlme_update_tgt_eht_cap(hdd_ctx->psoc, cfg);
52 	sme_update_tgt_eht_cap(hdd_ctx->mac_handle, cfg, &eht_cap_ini);
53 }
54 
55 void wlan_hdd_get_mlo_link_id(struct hdd_beacon_data *beacon,
56 			      uint8_t *link_id, uint8_t *num_link)
57 {
58 	const uint8_t *ie;
59 	uint8_t len;
60 	uint8_t link_len;
61 	*num_link = 0;
62 
63 	ie = wlan_get_ext_ie_ptr_from_ext_id(MLO_IE_OUI_TYPE, MLO_IE_OUI_SIZE,
64 					     beacon->tail, beacon->tail_len);
65 	if (ie) {
66 		hdd_debug("find a mlo ie in beacon data");
67 		*num_link = 1;
68 		ie++; /* WLAN_MAC_EID_EXT */
69 		len = *ie++; /* length */
70 		ie++; /* MLO_IE_OUI_TYPE */
71 		len--;
72 		ie++; /* Multi-Link Control field 2octets */
73 		ie++;
74 		len--;
75 		len--;
76 		ie++; /* Common Info Length */
77 		len--;
78 		ie += QDF_MAC_ADDR_SIZE; /* mld mac addr */
79 		len -= QDF_MAC_ADDR_SIZE;
80 		*link_id = *ie++; /* link id */
81 		len--;
82 		while (len > 0) {
83 			ie++; /* sub element ID */
84 			len--;
85 			link_len = *ie++; /* length of sub element ID */
86 			len--;
87 			ie += link_len;
88 			len -= link_len;
89 			(*num_link)++;
90 		}
91 	} else {
92 		hdd_debug("there is no mlo ie in beacon data");
93 	}
94 }
95 
96 void wlan_hdd_check_11be_support(struct hdd_beacon_data *beacon,
97 				 struct sap_config *config)
98 {
99 	const uint8_t *ie;
100 
101 	ie = wlan_get_ext_ie_ptr_from_ext_id(EHT_CAP_OUI_TYPE, EHT_CAP_OUI_SIZE,
102 					     beacon->tail, beacon->tail_len);
103 	if (ie)
104 		config->SapHw_mode = eCSR_DOT11_MODE_11be;
105 }
106 
107 static void
108 hdd_update_wiphy_eht_caps_6ghz(struct hdd_context *hdd_ctx,
109 			       tDot11fIEeht_cap eht_cap)
110 {
111 	struct ieee80211_supported_band *band_6g =
112 		   hdd_ctx->wiphy->bands[HDD_NL80211_BAND_6GHZ];
113 	uint8_t *phy_info =
114 		    hdd_ctx->iftype_data_6g->eht_cap.eht_cap_elem.phy_cap_info;
115 	struct ieee80211_sband_iftype_data *iftype_sta;
116 	struct ieee80211_sband_iftype_data *iftype_ap;
117 
118 	if (!band_6g || !phy_info) {
119 		hdd_debug("6ghz not supported in wiphy");
120 		return;
121 	}
122 
123 	hdd_ctx->iftype_data_6g->types_mask =
124 		(BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP));
125 	band_6g->n_iftype_data = EHT_OPMODE_SUPPORTED;
126 	band_6g->iftype_data = hdd_ctx->iftype_data_6g;
127 	iftype_sta = hdd_ctx->iftype_data_6g;
128 	iftype_ap = hdd_ctx->iftype_data_6g + 1;
129 
130 
131 	hdd_ctx->iftype_data_6g->eht_cap.has_eht = eht_cap.present;
132 	if (hdd_ctx->iftype_data_6g->eht_cap.has_eht &&
133 	    !hdd_ctx->iftype_data_6g->he_cap.has_he) {
134 		hdd_debug("6 GHz HE caps not present");
135 		hdd_ctx->iftype_data_6g->eht_cap.has_eht = false;
136 		band_6g->n_iftype_data = 1;
137 		return;
138 	}
139 
140 	if (eht_cap.support_320mhz_6ghz)
141 		phy_info[0] |= IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
142 
143 	if (eht_cap.su_beamformer)
144 		phy_info[0] |= IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER;
145 
146 	if (eht_cap.su_beamformee)
147 		phy_info[0] |= IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE;
148 
149 	qdf_mem_copy(iftype_ap, hdd_ctx->iftype_data_6g,
150 		     sizeof(struct ieee80211_supported_band));
151 
152 	iftype_sta->types_mask = BIT(NL80211_IFTYPE_STATION);
153 	iftype_ap->types_mask = BIT(NL80211_IFTYPE_AP);
154 }
155 
156 #ifdef CFG80211_RU_PUNCT_SUPPORT
157 static void hdd_update_wiphy_punct_support(struct hdd_context *hdd_ctx)
158 {
159 	/*
160 	 * ru_punct_supp_bw is the minimum BW of puncture.
161 	 * If it is set to 80, then 160 and 320 puncture bandwidth will also be
162 	 * supported in this case.
163 	 * If it is set to 320, then only 320 puncture bandwidth is supported.
164 	 */
165 	hdd_ctx->wiphy->ru_punct_supp_bw = NL80211_RU_PUNCT_SUPP_BW_80;
166 	hdd_debug("ru_punct_supp_bw: %d", hdd_ctx->wiphy->ru_punct_supp_bw);
167 }
168 #else
169 static void hdd_update_wiphy_punct_support(struct hdd_context *hdd_ctx)
170 {
171 }
172 #endif
173 
174 void hdd_update_wiphy_eht_cap(struct hdd_context *hdd_ctx)
175 {
176 	tDot11fIEeht_cap eht_cap_cfg;
177 	struct ieee80211_supported_band *band_2g =
178 			hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ];
179 	struct ieee80211_supported_band *band_5g =
180 			hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ];
181 	QDF_STATUS status;
182 	uint8_t *phy_info_5g =
183 		    hdd_ctx->iftype_data_5g->eht_cap.eht_cap_elem.phy_cap_info;
184 	uint8_t *phy_info_2g =
185 		    hdd_ctx->iftype_data_2g->eht_cap.eht_cap_elem.phy_cap_info;
186 	bool eht_capab;
187 	struct ieee80211_sband_iftype_data *iftype_sta;
188 	struct ieee80211_sband_iftype_data *iftype_ap;
189 
190 	hdd_enter();
191 
192 	ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab);
193 	if (!eht_capab)
194 		return;
195 
196 	status = ucfg_mlme_cfg_get_eht_caps(hdd_ctx->psoc, &eht_cap_cfg);
197 	if (QDF_IS_STATUS_ERROR(status))
198 		return;
199 
200 	if (eht_cap_cfg.present)
201 		hdd_update_wiphy_punct_support(hdd_ctx);
202 
203 	if (band_2g) {
204 		iftype_sta = hdd_ctx->iftype_data_2g;
205 		iftype_ap = hdd_ctx->iftype_data_2g + 1;
206 		hdd_ctx->iftype_data_2g->types_mask =
207 			(BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP));
208 		band_2g->n_iftype_data = EHT_OPMODE_SUPPORTED;
209 		band_2g->iftype_data = hdd_ctx->iftype_data_2g;
210 
211 		hdd_ctx->iftype_data_2g->eht_cap.has_eht = eht_cap_cfg.present;
212 		if (hdd_ctx->iftype_data_2g->eht_cap.has_eht &&
213 		    !hdd_ctx->iftype_data_2g->he_cap.has_he) {
214 			hdd_debug("2.4 GHz HE caps not present");
215 			hdd_ctx->iftype_data_2g->eht_cap.has_eht = false;
216 			band_2g->n_iftype_data = 1;
217 			goto band_5ghz;
218 		}
219 
220 		if (eht_cap_cfg.su_beamformer)
221 			phy_info_2g[0] |= IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER;
222 
223 		if (eht_cap_cfg.su_beamformee)
224 			phy_info_2g[0] |= IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE;
225 
226 		qdf_mem_copy(iftype_ap, hdd_ctx->iftype_data_2g,
227 			     sizeof(struct ieee80211_supported_band));
228 
229 		iftype_sta->types_mask = BIT(NL80211_IFTYPE_STATION);
230 		iftype_ap->types_mask = BIT(NL80211_IFTYPE_AP);
231 	}
232 
233 band_5ghz:
234 	if (band_5g) {
235 		iftype_sta = hdd_ctx->iftype_data_5g;
236 		iftype_ap = hdd_ctx->iftype_data_5g + 1;
237 		hdd_ctx->iftype_data_5g->types_mask =
238 			(BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP));
239 		band_5g->n_iftype_data = EHT_OPMODE_SUPPORTED;
240 		band_5g->iftype_data = hdd_ctx->iftype_data_5g;
241 
242 		hdd_ctx->iftype_data_5g->eht_cap.has_eht = eht_cap_cfg.present;
243 		if (hdd_ctx->iftype_data_5g->eht_cap.has_eht &&
244 		    !hdd_ctx->iftype_data_5g->he_cap.has_he) {
245 			hdd_debug("5 GHz HE caps not present");
246 			hdd_ctx->iftype_data_5g->eht_cap.has_eht = false;
247 			band_5g->n_iftype_data = 1;
248 			goto band_6ghz;
249 		}
250 
251 		if (eht_cap_cfg.su_beamformer)
252 			phy_info_5g[0] |= IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER;
253 
254 		if (eht_cap_cfg.su_beamformee)
255 			phy_info_5g[0] |= IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE;
256 
257 		qdf_mem_copy(iftype_ap, hdd_ctx->iftype_data_5g,
258 			     sizeof(struct ieee80211_supported_band));
259 
260 		iftype_sta->types_mask = BIT(NL80211_IFTYPE_STATION);
261 		iftype_ap->types_mask = BIT(NL80211_IFTYPE_AP);
262 	}
263 
264 band_6ghz:
265 	hdd_update_wiphy_eht_caps_6ghz(hdd_ctx, eht_cap_cfg);
266 
267 	hdd_exit();
268 }
269 
270 int hdd_set_11be_rate_code(struct hdd_adapter *adapter, uint16_t rate_code)
271 {
272 	uint8_t preamble = 0, nss = 0, rix = 0;
273 	int ret;
274 	struct sap_config *sap_config = NULL;
275 
276 	if (adapter->device_mode == QDF_SAP_MODE)
277 		sap_config = &adapter->session.ap.sap_config;
278 
279 	if (!sap_config) {
280 		if (!sme_is_feature_supported_by_fw(DOT11BE)) {
281 			hdd_err_rl("Target does not support 11be");
282 			return -EIO;
283 		}
284 	} else if (sap_config->SapHw_mode != eCSR_DOT11_MODE_11be &&
285 		   sap_config->SapHw_mode != eCSR_DOT11_MODE_11be_ONLY) {
286 		hdd_err_rl("Invalid hw mode, SAP hw_mode= 0x%x, ch_freq = %d",
287 			   sap_config->SapHw_mode, sap_config->chan_freq);
288 		return -EIO;
289 	}
290 
291 	if ((rate_code >> 8) != WMI_RATE_PREAMBLE_EHT) {
292 		hdd_err_rl("Invalid input: %x", rate_code);
293 		return -EIO;
294 	}
295 
296 	rix = RC_2_RATE_IDX_11BE(rate_code);
297 	preamble = rate_code >> 8;
298 	nss = HT_RC_2_STREAMS_11BE(rate_code) + 1;
299 
300 	hdd_debug("SET_11BE_RATE rate_code %d rix %d preamble %x nss %d",
301 		  rate_code, rix, preamble, nss);
302 
303 	ret = wma_cli_set_command(adapter->vdev_id,
304 				  wmi_vdev_param_fixed_rate,
305 				  rate_code, VDEV_CMD);
306 
307 	return ret;
308 }
309 
310 /**
311  * hdd_map_eht_gi_to_os() - map txrate_gi to os guard interval
312  * @guard_interval: guard interval get from fw rate
313  *
314  * Return: os guard interval value
315  */
316 static inline uint8_t hdd_map_eht_gi_to_os(enum txrate_gi guard_interval)
317 {
318 	switch (guard_interval) {
319 	case TXRATE_GI_0_8_US:
320 		return NL80211_RATE_INFO_EHT_GI_0_8;
321 	case TXRATE_GI_1_6_US:
322 		return NL80211_RATE_INFO_EHT_GI_1_6;
323 	case TXRATE_GI_3_2_US:
324 		return NL80211_RATE_INFO_EHT_GI_3_2;
325 	default:
326 		return NL80211_RATE_INFO_EHT_GI_0_8;
327 	}
328 }
329 
330 /**
331  * wlan_hdd_fill_os_eht_rateflags() - Fill EHT related rate_info
332  * @os_rate: rate info for os
333  * @rate_flags: rate flags
334  * @dcm: dcm from rate
335  * @guard_interval: guard interval from rate
336  *
337  * Return: none
338  */
339 void wlan_hdd_fill_os_eht_rateflags(struct rate_info *os_rate,
340 				    enum tx_rate_info rate_flags,
341 				    uint8_t dcm,
342 				    enum txrate_gi guard_interval)
343 {
344 	/* as fw not yet report ofdma to host, so don't
345 	 * fill RATE_INFO_BW_EHT_RU.
346 	 */
347 	if (rate_flags & (TX_RATE_EHT80 | TX_RATE_EHT40 |
348 	    TX_RATE_EHT20 | TX_RATE_EHT160 | TX_RATE_EHT320)) {
349 		if (rate_flags & TX_RATE_EHT320)
350 			hdd_set_rate_bw(os_rate, HDD_RATE_BW_320);
351 		else if (rate_flags & TX_RATE_EHT160)
352 			hdd_set_rate_bw(os_rate, HDD_RATE_BW_160);
353 		else if (rate_flags & TX_RATE_EHT80)
354 			hdd_set_rate_bw(os_rate, HDD_RATE_BW_80);
355 		else if (rate_flags & TX_RATE_EHT40)
356 			hdd_set_rate_bw(os_rate, HDD_RATE_BW_40);
357 
358 		os_rate->flags |= RATE_INFO_FLAGS_EHT_MCS;
359 	}
360 }
361 
362 #ifdef FEATURE_RX_LINKSPEED_ROAM_TRIGGER
363 void
364 wlan_hdd_refill_os_eht_rateflags(struct rate_info *os_rate, uint8_t preamble)
365 {
366 	if (preamble == DOT11_BE)
367 		os_rate->flags |= RATE_INFO_FLAGS_EHT_MCS;
368 }
369 
370 void
371 wlan_hdd_refill_os_eht_bw(struct rate_info *os_rate, enum rx_tlv_bw bw)
372 {
373 	if (bw == RX_TLV_BW_320MHZ)
374 		os_rate->bw = RATE_INFO_BW_320;
375 	else
376 		os_rate->bw = RATE_INFO_BW_20; /* Invalid bw: set 20M */
377 }
378 #endif
379 #endif
380