1 // SPDX-License-Identifier: BSD-3-Clause-Clear
2 /*
3 * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
4 * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
5 */
6
7 #include "core.h"
8 #include "acpi.h"
9 #include "debug.h"
10
ath12k_acpi_dsm_get_data(struct ath12k_base * ab,int func)11 static int ath12k_acpi_dsm_get_data(struct ath12k_base *ab, int func)
12 {
13 union acpi_object *obj;
14 acpi_handle root_handle;
15 int ret, i;
16
17 root_handle = ACPI_HANDLE(ab->dev);
18 if (!root_handle) {
19 ath12k_dbg(ab, ATH12K_DBG_BOOT, "invalid acpi handler\n");
20 return -EOPNOTSUPP;
21 }
22
23 obj = acpi_evaluate_dsm(root_handle, ab->hw_params->acpi_guid, 0, func,
24 NULL);
25
26 if (!obj) {
27 ath12k_dbg(ab, ATH12K_DBG_BOOT, "acpi_evaluate_dsm() failed\n");
28 return -ENOENT;
29 }
30
31 if (obj->type == ACPI_TYPE_INTEGER) {
32 switch (func) {
33 case ATH12K_ACPI_DSM_FUNC_SUPPORT_FUNCS:
34 ab->acpi.func_bit = obj->integer.value;
35 break;
36 case ATH12K_ACPI_DSM_FUNC_DISABLE_FLAG:
37 ab->acpi.bit_flag = obj->integer.value;
38 break;
39 }
40 } else if (obj->type == ACPI_TYPE_STRING) {
41 switch (func) {
42 case ATH12K_ACPI_DSM_FUNC_BDF_EXT:
43 if (obj->string.length <= ATH12K_ACPI_BDF_ANCHOR_STRING_LEN ||
44 obj->string.length > ATH12K_ACPI_BDF_MAX_LEN ||
45 memcmp(obj->string.pointer, ATH12K_ACPI_BDF_ANCHOR_STRING,
46 ATH12K_ACPI_BDF_ANCHOR_STRING_LEN)) {
47 ath12k_warn(ab, "invalid ACPI DSM BDF size: %d\n",
48 obj->string.length);
49 ret = -EINVAL;
50 goto out;
51 }
52
53 memcpy(ab->acpi.bdf_string, obj->string.pointer,
54 obj->buffer.length);
55
56 break;
57 }
58 } else if (obj->type == ACPI_TYPE_BUFFER) {
59 switch (func) {
60 case ATH12K_ACPI_DSM_FUNC_SUPPORT_FUNCS:
61 if (obj->buffer.length < ATH12K_ACPI_DSM_FUNC_MIN_BITMAP_SIZE ||
62 obj->buffer.length > ATH12K_ACPI_DSM_FUNC_MAX_BITMAP_SIZE) {
63 ath12k_warn(ab, "invalid ACPI DSM func size: %d\n",
64 obj->buffer.length);
65 ret = -EINVAL;
66 goto out;
67 }
68
69 ab->acpi.func_bit = 0;
70 for (i = 0; i < obj->buffer.length; i++)
71 ab->acpi.func_bit += obj->buffer.pointer[i] << (i * 8);
72
73 break;
74 case ATH12K_ACPI_DSM_FUNC_TAS_CFG:
75 if (obj->buffer.length != ATH12K_ACPI_DSM_TAS_CFG_SIZE) {
76 ath12k_warn(ab, "invalid ACPI DSM TAS config size: %d\n",
77 obj->buffer.length);
78 ret = -EINVAL;
79 goto out;
80 }
81
82 memcpy(&ab->acpi.tas_cfg, obj->buffer.pointer,
83 obj->buffer.length);
84
85 break;
86 case ATH12K_ACPI_DSM_FUNC_TAS_DATA:
87 if (obj->buffer.length != ATH12K_ACPI_DSM_TAS_DATA_SIZE) {
88 ath12k_warn(ab, "invalid ACPI DSM TAS data size: %d\n",
89 obj->buffer.length);
90 ret = -EINVAL;
91 goto out;
92 }
93
94 memcpy(&ab->acpi.tas_sar_power_table, obj->buffer.pointer,
95 obj->buffer.length);
96
97 break;
98 case ATH12K_ACPI_DSM_FUNC_BIOS_SAR:
99 if (obj->buffer.length != ATH12K_ACPI_DSM_BIOS_SAR_DATA_SIZE) {
100 ath12k_warn(ab, "invalid ACPI BIOS SAR data size: %d\n",
101 obj->buffer.length);
102 ret = -EINVAL;
103 goto out;
104 }
105
106 memcpy(&ab->acpi.bios_sar_data, obj->buffer.pointer,
107 obj->buffer.length);
108
109 break;
110 case ATH12K_ACPI_DSM_FUNC_GEO_OFFSET:
111 if (obj->buffer.length != ATH12K_ACPI_DSM_GEO_OFFSET_DATA_SIZE) {
112 ath12k_warn(ab, "invalid ACPI GEO OFFSET data size: %d\n",
113 obj->buffer.length);
114 ret = -EINVAL;
115 goto out;
116 }
117
118 memcpy(&ab->acpi.geo_offset_data, obj->buffer.pointer,
119 obj->buffer.length);
120
121 break;
122 case ATH12K_ACPI_DSM_FUNC_INDEX_CCA:
123 if (obj->buffer.length != ATH12K_ACPI_DSM_CCA_DATA_SIZE) {
124 ath12k_warn(ab, "invalid ACPI DSM CCA data size: %d\n",
125 obj->buffer.length);
126 ret = -EINVAL;
127 goto out;
128 }
129
130 memcpy(&ab->acpi.cca_data, obj->buffer.pointer,
131 obj->buffer.length);
132
133 break;
134 case ATH12K_ACPI_DSM_FUNC_INDEX_BAND_EDGE:
135 if (obj->buffer.length != ATH12K_ACPI_DSM_BAND_EDGE_DATA_SIZE) {
136 ath12k_warn(ab, "invalid ACPI DSM band edge data size: %d\n",
137 obj->buffer.length);
138 ret = -EINVAL;
139 goto out;
140 }
141
142 memcpy(&ab->acpi.band_edge_power, obj->buffer.pointer,
143 obj->buffer.length);
144
145 break;
146 }
147 } else {
148 ath12k_warn(ab, "ACPI DSM method returned an unsupported object type: %d\n",
149 obj->type);
150 ret = -EINVAL;
151 goto out;
152 }
153
154 ret = 0;
155
156 out:
157 ACPI_FREE(obj);
158 return ret;
159 }
160
ath12k_acpi_set_power_limit(struct ath12k_base * ab)161 static int ath12k_acpi_set_power_limit(struct ath12k_base *ab)
162 {
163 const u8 *tas_sar_power_table = ab->acpi.tas_sar_power_table;
164 int ret;
165
166 if (tas_sar_power_table[0] != ATH12K_ACPI_TAS_DATA_VERSION ||
167 tas_sar_power_table[1] != ATH12K_ACPI_TAS_DATA_ENABLE) {
168 ath12k_warn(ab, "latest ACPI TAS data is invalid\n");
169 return -EINVAL;
170 }
171
172 ret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_DATA_TYPE,
173 tas_sar_power_table,
174 ATH12K_ACPI_DSM_TAS_DATA_SIZE);
175 if (ret) {
176 ath12k_warn(ab, "failed to send ACPI TAS data table: %d\n", ret);
177 return ret;
178 }
179
180 return ret;
181 }
182
ath12k_acpi_set_bios_sar_power(struct ath12k_base * ab)183 static int ath12k_acpi_set_bios_sar_power(struct ath12k_base *ab)
184 {
185 int ret;
186
187 if (ab->acpi.bios_sar_data[0] != ATH12K_ACPI_POWER_LIMIT_VERSION ||
188 ab->acpi.bios_sar_data[1] != ATH12K_ACPI_POWER_LIMIT_ENABLE_FLAG) {
189 ath12k_warn(ab, "invalid latest ACPI BIOS SAR data\n");
190 return -EINVAL;
191 }
192
193 ret = ath12k_wmi_set_bios_sar_cmd(ab, ab->acpi.bios_sar_data);
194 if (ret) {
195 ath12k_warn(ab, "failed to set ACPI BIOS SAR table: %d\n", ret);
196 return ret;
197 }
198
199 return 0;
200 }
201
ath12k_acpi_dsm_notify(acpi_handle handle,u32 event,void * data)202 static void ath12k_acpi_dsm_notify(acpi_handle handle, u32 event, void *data)
203 {
204 int ret;
205 struct ath12k_base *ab = data;
206
207 if (event == ATH12K_ACPI_NOTIFY_EVENT) {
208 ath12k_warn(ab, "unknown acpi notify %u\n", event);
209 return;
210 }
211
212 if (!ab->acpi.acpi_tas_enable) {
213 ath12k_dbg(ab, ATH12K_DBG_BOOT, "acpi_tas_enable is false\n");
214 return;
215 }
216
217 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_DATA);
218 if (ret) {
219 ath12k_warn(ab, "failed to update ACPI TAS data table: %d\n", ret);
220 return;
221 }
222
223 ret = ath12k_acpi_set_power_limit(ab);
224 if (ret) {
225 ath12k_warn(ab, "failed to set ACPI TAS power limit data: %d", ret);
226 return;
227 }
228
229 if (!ab->acpi.acpi_bios_sar_enable)
230 return;
231
232 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_BIOS_SAR);
233 if (ret) {
234 ath12k_warn(ab, "failed to update BIOS SAR: %d\n", ret);
235 return;
236 }
237
238 ret = ath12k_acpi_set_bios_sar_power(ab);
239 if (ret) {
240 ath12k_warn(ab, "failed to set BIOS SAR power limit: %d\n", ret);
241 return;
242 }
243 }
244
ath12k_acpi_set_bios_sar_params(struct ath12k_base * ab)245 static int ath12k_acpi_set_bios_sar_params(struct ath12k_base *ab)
246 {
247 int ret;
248
249 ret = ath12k_wmi_set_bios_sar_cmd(ab, ab->acpi.bios_sar_data);
250 if (ret) {
251 ath12k_warn(ab, "failed to set ACPI BIOS SAR table: %d\n", ret);
252 return ret;
253 }
254
255 ret = ath12k_wmi_set_bios_geo_cmd(ab, ab->acpi.geo_offset_data);
256 if (ret) {
257 ath12k_warn(ab, "failed to set ACPI BIOS GEO table: %d\n", ret);
258 return ret;
259 }
260
261 return 0;
262 }
263
ath12k_acpi_set_tas_params(struct ath12k_base * ab)264 static int ath12k_acpi_set_tas_params(struct ath12k_base *ab)
265 {
266 int ret;
267
268 ret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_CONFIG_TYPE,
269 ab->acpi.tas_cfg,
270 ATH12K_ACPI_DSM_TAS_CFG_SIZE);
271 if (ret) {
272 ath12k_warn(ab, "failed to send ACPI TAS config table parameter: %d\n",
273 ret);
274 return ret;
275 }
276
277 ret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_DATA_TYPE,
278 ab->acpi.tas_sar_power_table,
279 ATH12K_ACPI_DSM_TAS_DATA_SIZE);
280 if (ret) {
281 ath12k_warn(ab, "failed to send ACPI TAS data table parameter: %d\n",
282 ret);
283 return ret;
284 }
285
286 return 0;
287 }
288
ath12k_acpi_get_disable_rfkill(struct ath12k_base * ab)289 bool ath12k_acpi_get_disable_rfkill(struct ath12k_base *ab)
290 {
291 return ab->acpi.acpi_disable_rfkill;
292 }
293
ath12k_acpi_get_disable_11be(struct ath12k_base * ab)294 bool ath12k_acpi_get_disable_11be(struct ath12k_base *ab)
295 {
296 return ab->acpi.acpi_disable_11be;
297 }
298
ath12k_acpi_set_dsm_func(struct ath12k_base * ab)299 void ath12k_acpi_set_dsm_func(struct ath12k_base *ab)
300 {
301 int ret;
302 u8 *buf;
303
304 if (!ab->hw_params->acpi_guid)
305 /* not supported with this hardware */
306 return;
307
308 if (ab->acpi.acpi_tas_enable) {
309 ret = ath12k_acpi_set_tas_params(ab);
310 if (ret) {
311 ath12k_warn(ab, "failed to send ACPI TAS parameters: %d\n", ret);
312 return;
313 }
314 }
315
316 if (ab->acpi.acpi_bios_sar_enable) {
317 ret = ath12k_acpi_set_bios_sar_params(ab);
318 if (ret) {
319 ath12k_warn(ab, "failed to send ACPI BIOS SAR: %d\n", ret);
320 return;
321 }
322 }
323
324 if (ab->acpi.acpi_cca_enable) {
325 buf = ab->acpi.cca_data + ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET;
326 ret = ath12k_wmi_set_bios_cmd(ab,
327 WMI_BIOS_PARAM_CCA_THRESHOLD_TYPE,
328 buf,
329 ATH12K_ACPI_CCA_THR_OFFSET_LEN);
330 if (ret) {
331 ath12k_warn(ab, "failed to set ACPI DSM CCA threshold: %d\n",
332 ret);
333 return;
334 }
335 }
336
337 if (ab->acpi.acpi_band_edge_enable) {
338 ret = ath12k_wmi_set_bios_cmd(ab,
339 WMI_BIOS_PARAM_TYPE_BANDEDGE,
340 ab->acpi.band_edge_power,
341 sizeof(ab->acpi.band_edge_power));
342 if (ret) {
343 ath12k_warn(ab,
344 "failed to set ACPI DSM band edge channel power: %d\n",
345 ret);
346 return;
347 }
348 }
349 }
350
ath12k_acpi_start(struct ath12k_base * ab)351 int ath12k_acpi_start(struct ath12k_base *ab)
352 {
353 acpi_status status;
354 int ret;
355
356 ab->acpi.acpi_tas_enable = false;
357 ab->acpi.acpi_disable_11be = false;
358 ab->acpi.acpi_disable_rfkill = false;
359 ab->acpi.acpi_bios_sar_enable = false;
360 ab->acpi.acpi_cca_enable = false;
361 ab->acpi.acpi_band_edge_enable = false;
362 ab->acpi.acpi_enable_bdf = false;
363 ab->acpi.bdf_string[0] = '\0';
364
365 if (!ab->hw_params->acpi_guid)
366 /* not supported with this hardware */
367 return 0;
368
369 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_SUPPORT_FUNCS);
370 if (ret) {
371 ath12k_dbg(ab, ATH12K_DBG_BOOT, "failed to get ACPI DSM data: %d\n", ret);
372 return ret;
373 }
374
375 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_DISABLE_FLAG)) {
376 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_DISABLE_FLAG);
377 if (ret) {
378 ath12k_warn(ab, "failed to get ACPI DISABLE FLAG: %d\n", ret);
379 return ret;
380 }
381
382 if (ATH12K_ACPI_CHEK_BIT_VALID(ab->acpi,
383 ATH12K_ACPI_DSM_DISABLE_11BE_BIT))
384 ab->acpi.acpi_disable_11be = true;
385
386 if (!ATH12K_ACPI_CHEK_BIT_VALID(ab->acpi,
387 ATH12K_ACPI_DSM_DISABLE_RFKILL_BIT))
388 ab->acpi.acpi_disable_rfkill = true;
389 }
390
391 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_BDF_EXT)) {
392 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_BDF_EXT);
393 if (ret || ab->acpi.bdf_string[0] == '\0') {
394 ath12k_warn(ab, "failed to get ACPI BDF EXT: %d\n", ret);
395 return ret;
396 }
397
398 ab->acpi.acpi_enable_bdf = true;
399 }
400
401 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_TAS_CFG)) {
402 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_CFG);
403 if (ret) {
404 ath12k_warn(ab, "failed to get ACPI TAS config table: %d\n", ret);
405 return ret;
406 }
407 }
408
409 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_TAS_DATA)) {
410 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_DATA);
411 if (ret) {
412 ath12k_warn(ab, "failed to get ACPI TAS data table: %d\n", ret);
413 return ret;
414 }
415
416 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_TAS_CFG) &&
417 ab->acpi.tas_sar_power_table[0] == ATH12K_ACPI_TAS_DATA_VERSION &&
418 ab->acpi.tas_sar_power_table[1] == ATH12K_ACPI_TAS_DATA_ENABLE)
419 ab->acpi.acpi_tas_enable = true;
420 }
421
422 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_BIOS_SAR)) {
423 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_BIOS_SAR);
424 if (ret) {
425 ath12k_warn(ab, "failed to get ACPI bios sar data: %d\n", ret);
426 return ret;
427 }
428 }
429
430 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_GEO_OFFSET)) {
431 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_GEO_OFFSET);
432 if (ret) {
433 ath12k_warn(ab, "failed to get ACPI geo offset data: %d\n", ret);
434 return ret;
435 }
436
437 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_BIOS_SAR) &&
438 ab->acpi.bios_sar_data[0] == ATH12K_ACPI_POWER_LIMIT_VERSION &&
439 ab->acpi.bios_sar_data[1] == ATH12K_ACPI_POWER_LIMIT_ENABLE_FLAG &&
440 !ab->acpi.acpi_tas_enable)
441 ab->acpi.acpi_bios_sar_enable = true;
442 }
443
444 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_CCA)) {
445 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_INDEX_CCA);
446 if (ret) {
447 ath12k_warn(ab, "failed to get ACPI DSM CCA threshold configuration: %d\n",
448 ret);
449 return ret;
450 }
451
452 if (ab->acpi.cca_data[0] == ATH12K_ACPI_CCA_THR_VERSION &&
453 ab->acpi.cca_data[ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET] ==
454 ATH12K_ACPI_CCA_THR_ENABLE_FLAG)
455 ab->acpi.acpi_cca_enable = true;
456 }
457
458 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi,
459 ATH12K_ACPI_FUNC_BIT_BAND_EDGE_CHAN_POWER)) {
460 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_INDEX_BAND_EDGE);
461 if (ret) {
462 ath12k_warn(ab, "failed to get ACPI DSM band edge channel power: %d\n",
463 ret);
464 return ret;
465 }
466
467 if (ab->acpi.band_edge_power[0] == ATH12K_ACPI_BAND_EDGE_VERSION &&
468 ab->acpi.band_edge_power[1] == ATH12K_ACPI_BAND_EDGE_ENABLE_FLAG)
469 ab->acpi.acpi_band_edge_enable = true;
470 }
471
472 status = acpi_install_notify_handler(ACPI_HANDLE(ab->dev),
473 ACPI_DEVICE_NOTIFY,
474 ath12k_acpi_dsm_notify, ab);
475 if (ACPI_FAILURE(status)) {
476 ath12k_warn(ab, "failed to install DSM notify callback: %d\n", status);
477 return -EIO;
478 }
479
480 ab->acpi.started = true;
481
482 return 0;
483 }
484
ath12k_acpi_check_bdf_variant_name(struct ath12k_base * ab)485 int ath12k_acpi_check_bdf_variant_name(struct ath12k_base *ab)
486 {
487 size_t max_len = sizeof(ab->qmi.target.bdf_ext);
488
489 if (!ab->acpi.acpi_enable_bdf)
490 return -ENODATA;
491
492 if (strscpy(ab->qmi.target.bdf_ext, ab->acpi.bdf_string + 4, max_len) < 0)
493 ath12k_dbg(ab, ATH12K_DBG_BOOT,
494 "acpi bdf variant longer than the buffer (variant: %s)\n",
495 ab->acpi.bdf_string);
496
497 return 0;
498 }
499
ath12k_acpi_stop(struct ath12k_base * ab)500 void ath12k_acpi_stop(struct ath12k_base *ab)
501 {
502 if (!ab->acpi.started)
503 return;
504
505 acpi_remove_notify_handler(ACPI_HANDLE(ab->dev),
506 ACPI_DEVICE_NOTIFY,
507 ath12k_acpi_dsm_notify);
508
509 memset(&ab->acpi, 0, sizeof(ab->acpi));
510 }
511