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