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