Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/athk/ath12k/acpi.c
178701 views
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
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
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
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
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
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
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
289
bool ath12k_acpi_get_disable_rfkill(struct ath12k_base *ab)
290
{
291
return ab->acpi.acpi_disable_rfkill;
292
}
293
294
bool ath12k_acpi_get_disable_11be(struct ath12k_base *ab)
295
{
296
return ab->acpi.acpi_disable_11be;
297
}
298
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
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
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
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
512