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