acpi.c 13 KB

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