xref: /linux/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c (revision 07fdad3a93756b872da7b53647715c48d0f4a2d0)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /*
3  * Copyright (C) 2024-2025 Intel Corporation
4  */
5 
6 #include <linux/dmi.h>
7 
8 #include "fw/regulatory.h"
9 #include "fw/acpi.h"
10 #include "fw/uefi.h"
11 
12 #include "regulatory.h"
13 #include "mld.h"
14 #include "hcmd.h"
15 
16 void iwl_mld_get_bios_tables(struct iwl_mld *mld)
17 {
18 	int ret;
19 
20 	iwl_acpi_get_guid_lock_status(&mld->fwrt);
21 
22 	ret = iwl_bios_get_ppag_table(&mld->fwrt);
23 	if (ret < 0) {
24 		IWL_DEBUG_RADIO(mld,
25 				"PPAG BIOS table invalid or unavailable. (%d)\n",
26 				ret);
27 	}
28 
29 	ret = iwl_bios_get_wrds_table(&mld->fwrt);
30 	if (ret < 0) {
31 		IWL_DEBUG_RADIO(mld,
32 				"WRDS SAR BIOS table invalid or unavailable. (%d)\n",
33 				ret);
34 
35 		/* If not available, don't fail and don't bother with EWRD and
36 		 * WGDS
37 		 */
38 
39 		if (!iwl_bios_get_wgds_table(&mld->fwrt)) {
40 			/* If basic SAR is not available, we check for WGDS,
41 			 * which should *not* be available either. If it is
42 			 * available, issue an error, because we can't use SAR
43 			 * Geo without basic SAR.
44 			 */
45 			IWL_ERR(mld, "BIOS contains WGDS but no WRDS\n");
46 		}
47 
48 	} else {
49 		ret = iwl_bios_get_ewrd_table(&mld->fwrt);
50 		/* If EWRD is not available, we can still use
51 		 * WRDS, so don't fail.
52 		 */
53 		if (ret < 0)
54 			IWL_DEBUG_RADIO(mld,
55 					"EWRD SAR BIOS table invalid or unavailable. (%d)\n",
56 					ret);
57 
58 		ret = iwl_bios_get_wgds_table(&mld->fwrt);
59 		if (ret < 0)
60 			IWL_DEBUG_RADIO(mld,
61 					"Geo SAR BIOS table invalid or unavailable. (%d)\n",
62 					ret);
63 		/* we don't fail if the table is not available */
64 	}
65 
66 	iwl_uefi_get_uats_table(mld->trans, &mld->fwrt);
67 
68 	iwl_bios_get_phy_filters(&mld->fwrt);
69 }
70 
71 static int iwl_mld_geo_sar_init(struct iwl_mld *mld)
72 {
73 	u32 cmd_id = WIDE_ID(PHY_OPS_GROUP, PER_CHAIN_LIMIT_OFFSET_CMD);
74 	/* Only set to South Korea if the table revision is 1 */
75 	__le32 sk = cpu_to_le32(mld->fwrt.geo_rev == 1 ? 1 : 0);
76 	union iwl_geo_tx_power_profiles_cmd cmd = {
77 		.v5.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES),
78 		.v5.table_revision = sk,
79 	};
80 	int ret;
81 
82 	ret = iwl_sar_geo_fill_table(&mld->fwrt, &cmd.v5.table[0][0],
83 				     ARRAY_SIZE(cmd.v5.table[0]),
84 				     BIOS_GEO_MAX_PROFILE_NUM);
85 
86 	/* It is a valid scenario to not support SAR, or miss wgds table,
87 	 * but in that case there is no need to send the command.
88 	 */
89 	if (ret)
90 		return 0;
91 
92 	return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, sizeof(cmd.v5));
93 }
94 
95 int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)
96 {
97 	u32 cmd_id = REDUCE_TX_POWER_CMD;
98 	struct iwl_dev_tx_power_cmd cmd = {
99 		.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS),
100 		.v10.flags = cpu_to_le32(mld->fwrt.reduced_power_flags),
101 	};
102 	int ret;
103 
104 	/* TODO: CDB - support IWL_NUM_CHAIN_TABLES_V2 */
105 	ret = iwl_sar_fill_profile(&mld->fwrt, &cmd.v10.per_chain[0][0][0],
106 				   IWL_NUM_CHAIN_TABLES, IWL_NUM_SUB_BANDS_V2,
107 				   prof_a, prof_b);
108 	/* return on error or if the profile is disabled (positive number) */
109 	if (ret)
110 		return ret;
111 
112 	return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd,
113 				    sizeof(cmd.common) + sizeof(cmd.v10));
114 }
115 
116 int iwl_mld_init_sar(struct iwl_mld *mld)
117 {
118 	int chain_a_prof = 1;
119 	int chain_b_prof = 1;
120 	int ret;
121 
122 	/* If no profile was chosen by the user yet, choose profile 1 (WRDS) as
123 	 * default for both chains
124 	 */
125 	if (mld->fwrt.sar_chain_a_profile && mld->fwrt.sar_chain_b_profile) {
126 		chain_a_prof = mld->fwrt.sar_chain_a_profile;
127 		chain_b_prof = mld->fwrt.sar_chain_b_profile;
128 	}
129 
130 	ret = iwl_mld_config_sar_profile(mld, chain_a_prof, chain_b_prof);
131 	if (ret < 0)
132 		return ret;
133 
134 	if (ret)
135 		return 0;
136 
137 	return iwl_mld_geo_sar_init(mld);
138 }
139 
140 int iwl_mld_init_sgom(struct iwl_mld *mld)
141 {
142 	int ret;
143 	struct iwl_host_cmd cmd = {
144 		.id = WIDE_ID(REGULATORY_AND_NVM_GROUP,
145 			      SAR_OFFSET_MAPPING_TABLE_CMD),
146 		.data[0] = &mld->fwrt.sgom_table,
147 		.len[0] =  sizeof(mld->fwrt.sgom_table),
148 		.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
149 	};
150 
151 	if (!mld->fwrt.sgom_enabled) {
152 		IWL_DEBUG_RADIO(mld, "SGOM table is disabled\n");
153 		return 0;
154 	}
155 
156 	ret = iwl_mld_send_cmd(mld, &cmd);
157 	if (ret)
158 		IWL_ERR(mld,
159 			"failed to send SAR_OFFSET_MAPPING_CMD (%d)\n", ret);
160 
161 	return ret;
162 }
163 
164 static int iwl_mld_ppag_send_cmd(struct iwl_mld *mld)
165 {
166 	struct iwl_fw_runtime *fwrt = &mld->fwrt;
167 	union iwl_ppag_table_cmd cmd = {
168 		.v7.ppag_config_info.table_source = fwrt->ppag_bios_source,
169 		.v7.ppag_config_info.table_revision = fwrt->ppag_bios_rev,
170 		.v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags),
171 	};
172 	int ret;
173 
174 	IWL_DEBUG_RADIO(fwrt,
175 			"PPAG MODE bits going to be sent: %d\n",
176 			fwrt->ppag_flags);
177 
178 	for (int chain = 0; chain < IWL_NUM_CHAIN_LIMITS; chain++) {
179 		for (int subband = 0; subband < IWL_NUM_SUB_BANDS_V2; subband++) {
180 			cmd.v7.gain[chain][subband] =
181 				fwrt->ppag_chains[chain].subbands[subband];
182 			IWL_DEBUG_RADIO(fwrt,
183 					"PPAG table: chain[%d] band[%d]: gain = %d\n",
184 					chain, subband, cmd.v7.gain[chain][subband]);
185 		}
186 	}
187 
188 	IWL_DEBUG_RADIO(mld, "Sending PER_PLATFORM_ANT_GAIN_CMD\n");
189 	ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(PHY_OPS_GROUP,
190 						PER_PLATFORM_ANT_GAIN_CMD),
191 				   &cmd, sizeof(cmd.v7));
192 	if (ret < 0)
193 		IWL_ERR(mld, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n",
194 			ret);
195 
196 	return ret;
197 }
198 
199 int iwl_mld_init_ppag(struct iwl_mld *mld)
200 {
201 	/* no need to read the table, done in INIT stage */
202 
203 	if (!(iwl_is_ppag_approved(&mld->fwrt)))
204 		return 0;
205 
206 	return iwl_mld_ppag_send_cmd(mld);
207 }
208 
209 void iwl_mld_configure_lari(struct iwl_mld *mld)
210 {
211 	struct iwl_fw_runtime *fwrt = &mld->fwrt;
212 	struct iwl_lari_config_change_cmd cmd = {
213 		.config_bitmap = iwl_get_lari_config_bitmap(fwrt),
214 	};
215 	bool has_raw_dsm_capa = fw_has_capa(&fwrt->fw->ucode_capa,
216 					    IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE);
217 	int ret;
218 	u32 value;
219 
220 	ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_11AX_ENABLEMENT, &value);
221 	if (!ret) {
222 		if (!has_raw_dsm_capa)
223 			value &= DSM_11AX_ALLOW_BITMAP;
224 		cmd.oem_11ax_allow_bitmap = cpu_to_le32(value);
225 	}
226 
227 	ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value);
228 	if (!ret) {
229 		if (!has_raw_dsm_capa)
230 			value &= DSM_UNII4_ALLOW_BITMAP;
231 		cmd.oem_unii4_allow_bitmap = cpu_to_le32(value);
232 	}
233 
234 	ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value);
235 	if (!ret) {
236 		if (!has_raw_dsm_capa)
237 			value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V12;
238 		cmd.chan_state_active_bitmap = cpu_to_le32(value);
239 	}
240 
241 	ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_6E, &value);
242 	if (!ret)
243 		cmd.oem_uhb_allow_bitmap = cpu_to_le32(value);
244 
245 	ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_FORCE_DISABLE_CHANNELS, &value);
246 	if (!ret) {
247 		if (!has_raw_dsm_capa)
248 			value &= DSM_FORCE_DISABLE_CHANNELS_ALLOWED_BITMAP;
249 		cmd.force_disable_channels_bitmap = cpu_to_le32(value);
250 	}
251 
252 	ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENERGY_DETECTION_THRESHOLD,
253 			       &value);
254 	if (!ret) {
255 		if (!has_raw_dsm_capa)
256 			value &= DSM_EDT_ALLOWED_BITMAP;
257 		cmd.edt_bitmap = cpu_to_le32(value);
258 	}
259 
260 	ret = iwl_bios_get_wbem(fwrt, &value);
261 	if (!ret)
262 		cmd.oem_320mhz_allow_bitmap = cpu_to_le32(value);
263 
264 	ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_11BE, &value);
265 	if (!ret)
266 		cmd.oem_11be_allow_bitmap = cpu_to_le32(value);
267 
268 	if (!cmd.config_bitmap &&
269 	    !cmd.oem_uhb_allow_bitmap &&
270 	    !cmd.oem_11ax_allow_bitmap &&
271 	    !cmd.oem_unii4_allow_bitmap &&
272 	    !cmd.chan_state_active_bitmap &&
273 	    !cmd.force_disable_channels_bitmap &&
274 	    !cmd.edt_bitmap &&
275 	    !cmd.oem_320mhz_allow_bitmap &&
276 	    !cmd.oem_11be_allow_bitmap)
277 		return;
278 
279 	IWL_DEBUG_RADIO(mld,
280 			"sending LARI_CONFIG_CHANGE, config_bitmap=0x%x, oem_11ax_allow_bitmap=0x%x\n",
281 			le32_to_cpu(cmd.config_bitmap),
282 			le32_to_cpu(cmd.oem_11ax_allow_bitmap));
283 	IWL_DEBUG_RADIO(mld,
284 			"sending LARI_CONFIG_CHANGE, oem_unii4_allow_bitmap=0x%x, chan_state_active_bitmap=0x%x\n",
285 			le32_to_cpu(cmd.oem_unii4_allow_bitmap),
286 			le32_to_cpu(cmd.chan_state_active_bitmap));
287 	IWL_DEBUG_RADIO(mld,
288 			"sending LARI_CONFIG_CHANGE, oem_uhb_allow_bitmap=0x%x, force_disable_channels_bitmap=0x%x\n",
289 			le32_to_cpu(cmd.oem_uhb_allow_bitmap),
290 			le32_to_cpu(cmd.force_disable_channels_bitmap));
291 	IWL_DEBUG_RADIO(mld,
292 			"sending LARI_CONFIG_CHANGE, edt_bitmap=0x%x, oem_320mhz_allow_bitmap=0x%x\n",
293 			le32_to_cpu(cmd.edt_bitmap),
294 			le32_to_cpu(cmd.oem_320mhz_allow_bitmap));
295 	IWL_DEBUG_RADIO(mld,
296 			"sending LARI_CONFIG_CHANGE, oem_11be_allow_bitmap=0x%x\n",
297 			le32_to_cpu(cmd.oem_11be_allow_bitmap));
298 
299 	ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(REGULATORY_AND_NVM_GROUP,
300 						LARI_CONFIG_CHANGE), &cmd);
301 	if (ret)
302 		IWL_DEBUG_RADIO(mld,
303 				"Failed to send LARI_CONFIG_CHANGE (%d)\n",
304 				ret);
305 }
306 
307 void iwl_mld_init_uats(struct iwl_mld *mld)
308 {
309 	int ret;
310 	struct iwl_host_cmd cmd = {
311 		.id = WIDE_ID(REGULATORY_AND_NVM_GROUP,
312 			      MCC_ALLOWED_AP_TYPE_CMD),
313 		.data[0] = &mld->fwrt.uats_table,
314 		.len[0] =  sizeof(mld->fwrt.uats_table),
315 		.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
316 	};
317 
318 	if (!mld->fwrt.uats_valid)
319 		return;
320 
321 	ret = iwl_mld_send_cmd(mld, &cmd);
322 	if (ret)
323 		IWL_ERR(mld, "failed to send MCC_ALLOWED_AP_TYPE_CMD (%d)\n",
324 			ret);
325 }
326 
327 void iwl_mld_init_tas(struct iwl_mld *mld)
328 {
329 	int ret;
330 	struct iwl_tas_data data = {};
331 	struct iwl_tas_config_cmd cmd = {};
332 	u32 cmd_id = WIDE_ID(REGULATORY_AND_NVM_GROUP, TAS_CONFIG);
333 
334 	BUILD_BUG_ON(ARRAY_SIZE(data.block_list_array) !=
335 		     IWL_WTAS_BLACK_LIST_MAX);
336 	BUILD_BUG_ON(ARRAY_SIZE(cmd.block_list_array) !=
337 		     IWL_WTAS_BLACK_LIST_MAX);
338 
339 	if (!fw_has_capa(&mld->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TAS_CFG)) {
340 		IWL_DEBUG_RADIO(mld, "TAS not enabled in FW\n");
341 		return;
342 	}
343 
344 	ret = iwl_bios_get_tas_table(&mld->fwrt, &data);
345 	if (ret < 0) {
346 		IWL_DEBUG_RADIO(mld,
347 				"TAS table invalid or unavailable. (%d)\n",
348 				ret);
349 		return;
350 	}
351 
352 	if (!iwl_is_tas_approved()) {
353 		IWL_DEBUG_RADIO(mld,
354 				"System vendor '%s' is not in the approved list, disabling TAS in US and Canada.\n",
355 				dmi_get_system_info(DMI_SYS_VENDOR) ?: "<unknown>");
356 		if ((!iwl_add_mcc_to_tas_block_list(data.block_list_array,
357 						    &data.block_list_size,
358 						    IWL_MCC_US)) ||
359 		    (!iwl_add_mcc_to_tas_block_list(data.block_list_array,
360 						    &data.block_list_size,
361 						    IWL_MCC_CANADA))) {
362 			IWL_DEBUG_RADIO(mld,
363 					"Unable to add US/Canada to TAS block list, disabling TAS\n");
364 			return;
365 		}
366 	} else {
367 		IWL_DEBUG_RADIO(mld,
368 				"System vendor '%s' is in the approved list.\n",
369 				dmi_get_system_info(DMI_SYS_VENDOR) ?: "<unknown>");
370 	}
371 
372 	cmd.block_list_size = cpu_to_le16(data.block_list_size);
373 	for (u8 i = 0; i < data.block_list_size; i++)
374 		cmd.block_list_array[i] =
375 			cpu_to_le16(data.block_list_array[i]);
376 	cmd.tas_config_info.table_source = data.table_source;
377 	cmd.tas_config_info.table_revision = data.table_revision;
378 	cmd.tas_config_info.value = cpu_to_le32(data.tas_selection);
379 
380 	ret = iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd);
381 	if (ret)
382 		IWL_DEBUG_RADIO(mld, "failed to send TAS_CONFIG (%d)\n", ret);
383 }
384