xref: /linux/drivers/net/wireless/ath/ath12k/acpi.c (revision 1a9239bb4253f9076b5b4b2a1a4e8d7defd77a95)
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