xref: /freebsd/sys/contrib/dev/iwlwifi/fw/regulatory.c (revision a4128aad8503277614f2d214011ef60a19447b83)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /*
3  * Copyright (C) 2023 Intel Corporation
4  */
5 #if defined(__FreeBSD__)
6 #include <linux/bitfield.h>
7 #endif
8 #include <linux/dmi.h>
9 #include "iwl-drv.h"
10 #include "iwl-debug.h"
11 #include "regulatory.h"
12 #include "fw/runtime.h"
13 #include "fw/uefi.h"
14 
15 #define GET_BIOS_TABLE(__name, ...)					\
16 do {									\
17 	int ret = -ENOENT;						\
18 	if (fwrt->uefi_tables_lock_status > UEFI_WIFI_GUID_UNLOCKED)	\
19 		ret = iwl_uefi_get_ ## __name(__VA_ARGS__);		\
20 	if (ret < 0)							\
21 		ret = iwl_acpi_get_ ## __name(__VA_ARGS__);		\
22 	return ret;							\
23 } while (0)
24 
25 #define IWL_BIOS_TABLE_LOADER(__name)					\
26 int iwl_bios_get_ ## __name(struct iwl_fw_runtime *fwrt)		\
27 {GET_BIOS_TABLE(__name, fwrt); }					\
28 IWL_EXPORT_SYMBOL(iwl_bios_get_ ## __name)
29 
30 #define IWL_BIOS_TABLE_LOADER_DATA(__name, data_type)			\
31 int iwl_bios_get_ ## __name(struct iwl_fw_runtime *fwrt,		\
32 			    data_type * data)				\
33 {GET_BIOS_TABLE(__name, fwrt, data); }					\
34 IWL_EXPORT_SYMBOL(iwl_bios_get_ ## __name)
35 
36 IWL_BIOS_TABLE_LOADER(wrds_table);
37 IWL_BIOS_TABLE_LOADER(ewrd_table);
38 IWL_BIOS_TABLE_LOADER(wgds_table);
39 IWL_BIOS_TABLE_LOADER(ppag_table);
40 IWL_BIOS_TABLE_LOADER_DATA(tas_table, struct iwl_tas_data);
41 IWL_BIOS_TABLE_LOADER_DATA(pwr_limit, u64);
42 IWL_BIOS_TABLE_LOADER_DATA(mcc, char);
43 IWL_BIOS_TABLE_LOADER_DATA(eckv, u32);
44 IWL_BIOS_TABLE_LOADER_DATA(wbem, u32);
45 
46 
47 static const struct dmi_system_id dmi_ppag_approved_list[] = {
48 	{ .ident = "HP",
49 	  .matches = {
50 			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
51 		},
52 	},
53 	{ .ident = "SAMSUNG",
54 	  .matches = {
55 			DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
56 		},
57 	},
58 	{ .ident = "MSFT",
59 	  .matches = {
60 			DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
61 		},
62 	},
63 	{ .ident = "ASUS",
64 	  .matches = {
65 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
66 		},
67 	},
68 	{ .ident = "GOOGLE-HP",
69 	  .matches = {
70 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
71 			DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
72 		},
73 	},
74 	{ .ident = "GOOGLE-ASUS",
75 	  .matches = {
76 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
77 			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek COMPUTER INC."),
78 		},
79 	},
80 	{ .ident = "GOOGLE-SAMSUNG",
81 	  .matches = {
82 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
83 			DMI_MATCH(DMI_BOARD_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
84 		},
85 	},
86 	{ .ident = "DELL",
87 	  .matches = {
88 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
89 		},
90 	},
91 	{ .ident = "DELL",
92 	  .matches = {
93 			DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
94 		},
95 	},
96 	{ .ident = "RAZER",
97 	  .matches = {
98 			DMI_MATCH(DMI_SYS_VENDOR, "Razer"),
99 		},
100 	},
101 	{ .ident = "Honor",
102 	  .matches = {
103 			DMI_MATCH(DMI_SYS_VENDOR, "HONOR"),
104 		},
105 	},
106 	{}
107 };
108 
109 static const struct dmi_system_id dmi_tas_approved_list[] = {
110 	{ .ident = "HP",
111 	  .matches = {
112 			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
113 		},
114 	},
115 	{ .ident = "SAMSUNG",
116 	  .matches = {
117 			DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
118 		},
119 	},
120 		{ .ident = "LENOVO",
121 	  .matches = {
122 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
123 		},
124 	},
125 	{ .ident = "DELL",
126 	  .matches = {
127 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
128 		},
129 	},
130 	{ .ident = "MSFT",
131 	  .matches = {
132 			DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
133 		},
134 	},
135 	{ .ident = "Acer",
136 	  .matches = {
137 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
138 		},
139 	},
140 	{ .ident = "ASUS",
141 	  .matches = {
142 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
143 		},
144 	},
145 	{ .ident = "GOOGLE-HP",
146 	  .matches = {
147 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
148 			DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
149 		},
150 	},
151 	{ .ident = "MSI",
152 	  .matches = {
153 			DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."),
154 		},
155 	},
156 	{ .ident = "Honor",
157 	  .matches = {
158 			DMI_MATCH(DMI_SYS_VENDOR, "HONOR"),
159 		},
160 	},
161 	/* keep last */
162 	{}
163 };
164 
165 bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
166 {
167 	/*
168 	 * The PER_CHAIN_LIMIT_OFFSET_CMD command is not supported on
169 	 * earlier firmware versions.  Unfortunately, we don't have a
170 	 * TLV API flag to rely on, so rely on the major version which
171 	 * is in the first byte of ucode_ver.  This was implemented
172 	 * initially on version 38 and then backported to 17.  It was
173 	 * also backported to 29, but only for 7265D devices.  The
174 	 * intention was to have it in 36 as well, but not all 8000
175 	 * family got this feature enabled.  The 8000 family is the
176 	 * only one using version 36, so skip this version entirely.
177 	 */
178 	return IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) >= 38 ||
179 		(IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 17 &&
180 		 fwrt->trans->hw_rev != CSR_HW_REV_TYPE_3160) ||
181 		(IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 29 &&
182 		 ((fwrt->trans->hw_rev & CSR_HW_REV_TYPE_MSK) ==
183 		  CSR_HW_REV_TYPE_7265D));
184 }
185 IWL_EXPORT_SYMBOL(iwl_sar_geo_support);
186 
187 int iwl_sar_geo_fill_table(struct iwl_fw_runtime *fwrt,
188 			   struct iwl_per_chain_offset *table,
189 			   u32 n_bands, u32 n_profiles)
190 {
191 	int i, j;
192 
193 	if (!fwrt->geo_enabled)
194 		return -ENODATA;
195 
196 	if (!iwl_sar_geo_support(fwrt))
197 		return -EOPNOTSUPP;
198 
199 	for (i = 0; i < n_profiles; i++) {
200 		for (j = 0; j < n_bands; j++) {
201 			struct iwl_per_chain_offset *chain =
202 				&table[i * n_bands + j];
203 
204 			chain->max_tx_power =
205 				cpu_to_le16(fwrt->geo_profiles[i].bands[j].max);
206 			chain->chain_a =
207 				fwrt->geo_profiles[i].bands[j].chains[0];
208 			chain->chain_b =
209 				fwrt->geo_profiles[i].bands[j].chains[1];
210 			IWL_DEBUG_RADIO(fwrt,
211 					"SAR geographic profile[%d] Band[%d]: chain A = %d chain B = %d max_tx_power = %d\n",
212 					i, j,
213 					fwrt->geo_profiles[i].bands[j].chains[0],
214 					fwrt->geo_profiles[i].bands[j].chains[1],
215 					fwrt->geo_profiles[i].bands[j].max);
216 		}
217 	}
218 
219 	return 0;
220 }
221 IWL_EXPORT_SYMBOL(iwl_sar_geo_fill_table);
222 
223 static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,
224 			      __le16 *per_chain, u32 n_subbands,
225 			      int prof_a, int prof_b)
226 {
227 	int profs[BIOS_SAR_NUM_CHAINS] = { prof_a, prof_b };
228 	int i, j;
229 
230 	for (i = 0; i < BIOS_SAR_NUM_CHAINS; i++) {
231 		struct iwl_sar_profile *prof;
232 
233 		/* don't allow SAR to be disabled (profile 0 means disable) */
234 		if (profs[i] == 0)
235 			return -EPERM;
236 
237 		/* we are off by one, so allow up to BIOS_SAR_MAX_PROFILE_NUM */
238 		if (profs[i] > BIOS_SAR_MAX_PROFILE_NUM)
239 			return -EINVAL;
240 
241 		/* profiles go from 1 to 4, so decrement to access the array */
242 		prof = &fwrt->sar_profiles[profs[i] - 1];
243 
244 		/* if the profile is disabled, do nothing */
245 		if (!prof->enabled) {
246 			IWL_DEBUG_RADIO(fwrt, "SAR profile %d is disabled.\n",
247 					profs[i]);
248 			/*
249 			 * if one of the profiles is disabled, we
250 			 * ignore all of them and return 1 to
251 			 * differentiate disabled from other failures.
252 			 */
253 			return 1;
254 		}
255 
256 		IWL_DEBUG_INFO(fwrt,
257 			       "SAR EWRD: chain %d profile index %d\n",
258 			       i, profs[i]);
259 		IWL_DEBUG_RADIO(fwrt, "  Chain[%d]:\n", i);
260 		for (j = 0; j < n_subbands; j++) {
261 			per_chain[i * n_subbands + j] =
262 				cpu_to_le16(prof->chains[i].subbands[j]);
263 			IWL_DEBUG_RADIO(fwrt, "    Band[%d] = %d * .125dBm\n",
264 					j, prof->chains[i].subbands[j]);
265 		}
266 	}
267 
268 	return 0;
269 }
270 
271 int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt,
272 			 __le16 *per_chain, u32 n_tables, u32 n_subbands,
273 			 int prof_a, int prof_b)
274 {
275 	int i, ret = 0;
276 
277 	for (i = 0; i < n_tables; i++) {
278 		ret = iwl_sar_fill_table(fwrt,
279 			&per_chain[i * n_subbands * BIOS_SAR_NUM_CHAINS],
280 			n_subbands, prof_a, prof_b);
281 		if (ret)
282 			break;
283 	}
284 
285 	return ret;
286 }
287 IWL_EXPORT_SYMBOL(iwl_sar_fill_profile);
288 
289 static bool iwl_ppag_value_valid(struct iwl_fw_runtime *fwrt, int chain,
290 				 int subband)
291 {
292 	s8 ppag_val = fwrt->ppag_chains[chain].subbands[subband];
293 
294 	if ((subband == 0 &&
295 	     (ppag_val > IWL_PPAG_MAX_LB || ppag_val < IWL_PPAG_MIN_LB)) ||
296 	    (subband != 0 &&
297 	     (ppag_val > IWL_PPAG_MAX_HB || ppag_val < IWL_PPAG_MIN_HB))) {
298 		IWL_DEBUG_RADIO(fwrt, "Invalid PPAG value: %d\n", ppag_val);
299 		return false;
300 	}
301 	return true;
302 }
303 
304 int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
305 			union iwl_ppag_table_cmd *cmd, int *cmd_size)
306 {
307 	u8 cmd_ver;
308 	int i, j, num_sub_bands;
309 	s8 *gain;
310 	bool send_ppag_always;
311 
312 	/* many firmware images for JF lie about this */
313 	if (CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id) ==
314 	    CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_JF))
315 		return -EOPNOTSUPP;
316 
317 	if (!fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_PPAG)) {
318 		IWL_DEBUG_RADIO(fwrt,
319 				"PPAG capability not supported by FW, command not sent.\n");
320 		return -EINVAL;
321 	}
322 
323 	cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
324 					WIDE_ID(PHY_OPS_GROUP,
325 						PER_PLATFORM_ANT_GAIN_CMD), 1);
326 	/*
327 	 * Starting from ver 4, driver needs to send the PPAG CMD regardless
328 	 * if PPAG is enabled/disabled or valid/invalid.
329 	 */
330 	send_ppag_always = cmd_ver > 3;
331 
332 	/* Don't send PPAG if it is disabled */
333 	if (!send_ppag_always && !fwrt->ppag_flags) {
334 		IWL_DEBUG_RADIO(fwrt, "PPAG not enabled, command not sent.\n");
335 		return -EINVAL;
336 	}
337 
338 	/* The 'flags' field is the same in v1 and in v2 so we can just
339 	 * use v1 to access it.
340 	 */
341 	cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags);
342 
343 	IWL_DEBUG_RADIO(fwrt, "PPAG cmd ver is %d\n", cmd_ver);
344 	if (cmd_ver == 1) {
345 		num_sub_bands = IWL_NUM_SUB_BANDS_V1;
346 		gain = cmd->v1.gain[0];
347 		*cmd_size = sizeof(cmd->v1);
348 		if (fwrt->ppag_ver >= 1) {
349 			/* in this case FW supports revision 0 */
350 			IWL_DEBUG_RADIO(fwrt,
351 					"PPAG table rev is %d, send truncated table\n",
352 					fwrt->ppag_ver);
353 		}
354 	} else if (cmd_ver >= 2 && cmd_ver <= 6) {
355 		num_sub_bands = IWL_NUM_SUB_BANDS_V2;
356 		gain = cmd->v2.gain[0];
357 		*cmd_size = sizeof(cmd->v2);
358 		if (fwrt->ppag_ver == 0) {
359 			/* in this case FW supports revisions 1,2 or 3 */
360 			IWL_DEBUG_RADIO(fwrt,
361 					"PPAG table rev is 0, send padded table\n");
362 		}
363 	} else {
364 		IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n");
365 		return -EINVAL;
366 	}
367 
368 	/* ppag mode */
369 	IWL_DEBUG_RADIO(fwrt,
370 			"PPAG MODE bits were read from bios: %d\n",
371 			le32_to_cpu(cmd->v1.flags));
372 
373 	if (cmd_ver == 5)
374 		cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V5_MASK);
375 	else if (cmd_ver < 5)
376 		cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V4_MASK);
377 
378 	if ((cmd_ver == 1 &&
379 	     !fw_has_capa(&fwrt->fw->ucode_capa,
380 			  IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) ||
381 	    (cmd_ver == 2 && fwrt->ppag_ver >= 2)) {
382 		cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
383 		IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n");
384 	} else {
385 		IWL_DEBUG_RADIO(fwrt, "isn't masking ppag China bit\n");
386 	}
387 
388 	IWL_DEBUG_RADIO(fwrt,
389 			"PPAG MODE bits going to be sent: %d\n",
390 			le32_to_cpu(cmd->v1.flags));
391 
392 	for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
393 		for (j = 0; j < num_sub_bands; j++) {
394 			if (!send_ppag_always &&
395 			    !iwl_ppag_value_valid(fwrt, i, j))
396 				return -EINVAL;
397 
398 			gain[i * num_sub_bands + j] =
399 				fwrt->ppag_chains[i].subbands[j];
400 			IWL_DEBUG_RADIO(fwrt,
401 					"PPAG table: chain[%d] band[%d]: gain = %d\n",
402 					i, j, gain[i * num_sub_bands + j]);
403 		}
404 	}
405 
406 	return 0;
407 }
408 IWL_EXPORT_SYMBOL(iwl_fill_ppag_table);
409 
410 bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt)
411 {
412 	if (!dmi_check_system(dmi_ppag_approved_list)) {
413 		IWL_DEBUG_RADIO(fwrt,
414 				"System vendor '%s' is not in the approved list, disabling PPAG.\n",
415 				dmi_get_system_info(DMI_SYS_VENDOR) ?: "<unknown>");
416 		fwrt->ppag_flags = 0;
417 		return false;
418 	}
419 
420 	return true;
421 }
422 IWL_EXPORT_SYMBOL(iwl_is_ppag_approved);
423 
424 bool iwl_is_tas_approved(void)
425 {
426 	return dmi_check_system(dmi_tas_approved_list);
427 }
428 IWL_EXPORT_SYMBOL(iwl_is_tas_approved);
429 
430 int iwl_parse_tas_selection(struct iwl_fw_runtime *fwrt,
431 			    struct iwl_tas_data *tas_data,
432 			    const u32 tas_selection)
433 {
434 	u8 override_iec = u32_get_bits(tas_selection,
435 				       IWL_WTAS_OVERRIDE_IEC_MSK);
436 	u8 enabled_iec = u32_get_bits(tas_selection, IWL_WTAS_ENABLE_IEC_MSK);
437 	u8 usa_tas_uhb = u32_get_bits(tas_selection, IWL_WTAS_USA_UHB_MSK);
438 	int enabled = tas_selection & IWL_WTAS_ENABLED_MSK;
439 
440 	IWL_DEBUG_RADIO(fwrt, "TAS selection as read from BIOS: 0x%x\n",
441 			tas_selection);
442 
443 	tas_data->usa_tas_uhb_allowed = usa_tas_uhb;
444 	tas_data->override_tas_iec = override_iec;
445 	tas_data->enable_tas_iec = enabled_iec;
446 
447 	return enabled;
448 }
449 
450 static __le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
451 {
452 	int ret;
453 	u32 val;
454 	__le32 config_bitmap = 0;
455 
456 	switch (CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id)) {
457 	case IWL_CFG_RF_TYPE_HR1:
458 	case IWL_CFG_RF_TYPE_HR2:
459 	case IWL_CFG_RF_TYPE_JF1:
460 	case IWL_CFG_RF_TYPE_JF2:
461 		ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_INDONESIA_5G2,
462 				       &val);
463 
464 		if (!ret && val == DSM_VALUE_INDONESIA_ENABLE)
465 			config_bitmap |=
466 			    cpu_to_le32(LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK);
467 		break;
468 	default:
469 		break;
470 	}
471 
472 	ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_DISABLE_SRD, &val);
473 	if (!ret) {
474 		if (val == DSM_VALUE_SRD_PASSIVE)
475 			config_bitmap |=
476 				cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK);
477 		else if (val == DSM_VALUE_SRD_DISABLE)
478 			config_bitmap |=
479 				cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK);
480 	}
481 
482 	if (fw_has_capa(&fwrt->fw->ucode_capa,
483 			IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT)) {
484 		ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_REGULATORY_CONFIG,
485 				       &val);
486 		/*
487 		 * China 2022 enable if the BIOS object does not exist or
488 		 * if it is enabled in BIOS.
489 		 */
490 		if (ret < 0 || val & DSM_MASK_CHINA_22_REG)
491 			config_bitmap |=
492 				cpu_to_le32(LARI_CONFIG_ENABLE_CHINA_22_REG_SUPPORT_MSK);
493 	}
494 
495 	return config_bitmap;
496 }
497 
498 static size_t iwl_get_lari_config_cmd_size(u8 cmd_ver)
499 {
500 	size_t cmd_size;
501 
502 	switch (cmd_ver) {
503 	case 12:
504 	case 11:
505 		cmd_size = sizeof(struct iwl_lari_config_change_cmd);
506 		break;
507 	case 10:
508 		cmd_size = sizeof(struct iwl_lari_config_change_cmd_v10);
509 		break;
510 	case 9:
511 	case 8:
512 	case 7:
513 		cmd_size = sizeof(struct iwl_lari_config_change_cmd_v7);
514 		break;
515 	case 6:
516 		cmd_size = sizeof(struct iwl_lari_config_change_cmd_v6);
517 		break;
518 	case 5:
519 		cmd_size = sizeof(struct iwl_lari_config_change_cmd_v5);
520 		break;
521 	case 4:
522 		cmd_size = sizeof(struct iwl_lari_config_change_cmd_v4);
523 		break;
524 	case 3:
525 		cmd_size = sizeof(struct iwl_lari_config_change_cmd_v3);
526 		break;
527 	case 2:
528 		cmd_size = sizeof(struct iwl_lari_config_change_cmd_v2);
529 		break;
530 	default:
531 		cmd_size = sizeof(struct iwl_lari_config_change_cmd_v1);
532 		break;
533 	}
534 	return cmd_size;
535 }
536 
537 int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt,
538 			 struct iwl_lari_config_change_cmd *cmd,
539 			 size_t *cmd_size)
540 {
541 	int ret;
542 	u32 value;
543 	u8 cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
544 					   WIDE_ID(REGULATORY_AND_NVM_GROUP,
545 						   LARI_CONFIG_CHANGE), 1);
546 
547 	memset(cmd, 0, sizeof(*cmd));
548 	*cmd_size = iwl_get_lari_config_cmd_size(cmd_ver);
549 
550 	cmd->config_bitmap = iwl_get_lari_config_bitmap(fwrt);
551 
552 	ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_11AX_ENABLEMENT, &value);
553 	if (!ret)
554 		cmd->oem_11ax_allow_bitmap = cpu_to_le32(value);
555 
556 	ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value);
557 	if (!ret) {
558 		if (cmd_ver < 9)
559 			value &= DSM_UNII4_ALLOW_BITMAP_CMD_V8;
560 		else
561 			value &= DSM_UNII4_ALLOW_BITMAP;
562 
563 		cmd->oem_unii4_allow_bitmap = cpu_to_le32(value);
564 	}
565 
566 	ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value);
567 	if (!ret) {
568 		if (cmd_ver < 8)
569 			value &= ~ACTIVATE_5G2_IN_WW_MASK;
570 		if (cmd_ver < 12)
571 			value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V11;
572 
573 		cmd->chan_state_active_bitmap = cpu_to_le32(value);
574 	}
575 
576 	ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_6E, &value);
577 	if (!ret)
578 		cmd->oem_uhb_allow_bitmap = cpu_to_le32(value);
579 
580 	ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_FORCE_DISABLE_CHANNELS, &value);
581 	if (!ret)
582 		cmd->force_disable_channels_bitmap = cpu_to_le32(value);
583 
584 	ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENERGY_DETECTION_THRESHOLD,
585 			       &value);
586 	if (!ret)
587 		cmd->edt_bitmap = cpu_to_le32(value);
588 
589 	ret = iwl_bios_get_wbem(fwrt, &value);
590 	if (!ret)
591 		cmd->oem_320mhz_allow_bitmap = cpu_to_le32(value);
592 
593 	ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_11BE, &value);
594 	if (!ret)
595 		cmd->oem_11be_allow_bitmap = cpu_to_le32(value);
596 
597 	if (cmd->config_bitmap ||
598 	    cmd->oem_uhb_allow_bitmap ||
599 	    cmd->oem_11ax_allow_bitmap ||
600 	    cmd->oem_unii4_allow_bitmap ||
601 	    cmd->chan_state_active_bitmap ||
602 	    cmd->force_disable_channels_bitmap ||
603 	    cmd->edt_bitmap ||
604 	    cmd->oem_320mhz_allow_bitmap ||
605 	    cmd->oem_11be_allow_bitmap) {
606 		IWL_DEBUG_RADIO(fwrt,
607 				"sending LARI_CONFIG_CHANGE, config_bitmap=0x%x, oem_11ax_allow_bitmap=0x%x\n",
608 				le32_to_cpu(cmd->config_bitmap),
609 				le32_to_cpu(cmd->oem_11ax_allow_bitmap));
610 		IWL_DEBUG_RADIO(fwrt,
611 				"sending LARI_CONFIG_CHANGE, oem_unii4_allow_bitmap=0x%x, chan_state_active_bitmap=0x%x, cmd_ver=%d\n",
612 				le32_to_cpu(cmd->oem_unii4_allow_bitmap),
613 				le32_to_cpu(cmd->chan_state_active_bitmap),
614 				cmd_ver);
615 		IWL_DEBUG_RADIO(fwrt,
616 				"sending LARI_CONFIG_CHANGE, oem_uhb_allow_bitmap=0x%x, force_disable_channels_bitmap=0x%x\n",
617 				le32_to_cpu(cmd->oem_uhb_allow_bitmap),
618 				le32_to_cpu(cmd->force_disable_channels_bitmap));
619 		IWL_DEBUG_RADIO(fwrt,
620 				"sending LARI_CONFIG_CHANGE, edt_bitmap=0x%x, oem_320mhz_allow_bitmap=0x%x\n",
621 				le32_to_cpu(cmd->edt_bitmap),
622 				le32_to_cpu(cmd->oem_320mhz_allow_bitmap));
623 		IWL_DEBUG_RADIO(fwrt,
624 				"sending LARI_CONFIG_CHANGE, oem_11be_allow_bitmap=0x%x\n",
625 				le32_to_cpu(cmd->oem_11be_allow_bitmap));
626 	} else {
627 		return 1;
628 	}
629 
630 	return 0;
631 }
632 IWL_EXPORT_SYMBOL(iwl_fill_lari_config);
633 
634 int iwl_bios_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
635 		     u32 *value)
636 {
637 	GET_BIOS_TABLE(dsm, fwrt, func, value);
638 }
639 IWL_EXPORT_SYMBOL(iwl_bios_get_dsm);
640