1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * AMD Platform Management Framework Driver
4 *
5 * Copyright (c) 2022, Advanced Micro Devices, Inc.
6 * All Rights Reserved.
7 *
8 * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
9 */
10
11 #include <linux/acpi.h>
12 #include <linux/array_size.h>
13 #include <linux/cleanup.h>
14 #include <linux/dev_printk.h>
15 #include "pmf.h"
16
17 #define APMF_CQL_NOTIFICATION 2
18 #define APMF_AMT_NOTIFICATION 3
19
apmf_if_call(struct amd_pmf_dev * pdev,int fn,struct acpi_buffer * param)20 static union acpi_object *apmf_if_call(struct amd_pmf_dev *pdev, int fn, struct acpi_buffer *param)
21 {
22 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
23 acpi_handle ahandle = ACPI_HANDLE(pdev->dev);
24 struct acpi_object_list apmf_if_arg_list;
25 union acpi_object apmf_if_args[2];
26 acpi_status status;
27
28 apmf_if_arg_list.count = 2;
29 apmf_if_arg_list.pointer = &apmf_if_args[0];
30
31 apmf_if_args[0].type = ACPI_TYPE_INTEGER;
32 apmf_if_args[0].integer.value = fn;
33
34 if (param) {
35 apmf_if_args[1].type = ACPI_TYPE_BUFFER;
36 apmf_if_args[1].buffer.length = param->length;
37 apmf_if_args[1].buffer.pointer = param->pointer;
38 } else {
39 apmf_if_args[1].type = ACPI_TYPE_INTEGER;
40 apmf_if_args[1].integer.value = 0;
41 }
42
43 status = acpi_evaluate_object(ahandle, "APMF", &apmf_if_arg_list, &buffer);
44 if (ACPI_FAILURE(status)) {
45 dev_err(pdev->dev, "APMF method:%d call failed\n", fn);
46 kfree(buffer.pointer);
47 return NULL;
48 }
49
50 return buffer.pointer;
51 }
52
apmf_if_call_store_buffer(struct amd_pmf_dev * pdev,int fn,void * dest,size_t out_sz)53 static int apmf_if_call_store_buffer(struct amd_pmf_dev *pdev, int fn, void *dest, size_t out_sz)
54 {
55 union acpi_object *info;
56 size_t size;
57 int err = 0;
58
59 info = apmf_if_call(pdev, fn, NULL);
60 if (!info)
61 return -EIO;
62
63 if (info->type != ACPI_TYPE_BUFFER) {
64 dev_err(pdev->dev, "object is not a buffer\n");
65 err = -EINVAL;
66 goto out;
67 }
68
69 if (info->buffer.length < 2) {
70 dev_err(pdev->dev, "buffer too small\n");
71 err = -EINVAL;
72 goto out;
73 }
74
75 size = *(u16 *)info->buffer.pointer;
76 if (info->buffer.length < size) {
77 dev_err(pdev->dev, "buffer smaller then headersize %u < %zu\n",
78 info->buffer.length, size);
79 err = -EINVAL;
80 goto out;
81 }
82
83 if (size < out_sz) {
84 dev_err(pdev->dev, "buffer too small %zu\n", size);
85 err = -EINVAL;
86 goto out;
87 }
88
89 memcpy(dest, info->buffer.pointer, out_sz);
90
91 out:
92 kfree(info);
93 return err;
94 }
95
apts_if_call(struct amd_pmf_dev * pdev,u32 state_index)96 static union acpi_object *apts_if_call(struct amd_pmf_dev *pdev, u32 state_index)
97 {
98 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
99 acpi_handle ahandle = ACPI_HANDLE(pdev->dev);
100 struct acpi_object_list apts_if_arg_list;
101 union acpi_object apts_if_args[3];
102 acpi_status status;
103
104 apts_if_arg_list.count = 3;
105 apts_if_arg_list.pointer = &apts_if_args[0];
106
107 apts_if_args[0].type = ACPI_TYPE_INTEGER;
108 apts_if_args[0].integer.value = 1;
109 apts_if_args[1].type = ACPI_TYPE_INTEGER;
110 apts_if_args[1].integer.value = state_index;
111 apts_if_args[2].type = ACPI_TYPE_INTEGER;
112 apts_if_args[2].integer.value = 0;
113
114 status = acpi_evaluate_object(ahandle, "APTS", &apts_if_arg_list, &buffer);
115 if (ACPI_FAILURE(status)) {
116 dev_err(pdev->dev, "APTS state_idx:%u call failed\n", state_index);
117 kfree(buffer.pointer);
118 return NULL;
119 }
120
121 return buffer.pointer;
122 }
123
apts_if_call_store_buffer(struct amd_pmf_dev * pdev,u32 index,void * data,size_t out_sz)124 static int apts_if_call_store_buffer(struct amd_pmf_dev *pdev,
125 u32 index, void *data, size_t out_sz)
126 {
127 union acpi_object *info;
128 size_t size;
129 int err = 0;
130
131 info = apts_if_call(pdev, index);
132 if (!info)
133 return -EIO;
134
135 if (info->type != ACPI_TYPE_BUFFER) {
136 dev_err(pdev->dev, "object is not a buffer\n");
137 err = -EINVAL;
138 goto out;
139 }
140
141 size = *(u16 *)info->buffer.pointer;
142 if (info->buffer.length < size) {
143 dev_err(pdev->dev, "buffer smaller than header size %u < %zu\n",
144 info->buffer.length, size);
145 err = -EINVAL;
146 goto out;
147 }
148
149 if (size < out_sz) {
150 dev_err(pdev->dev, "buffer too small %zu\n", size);
151 err = -EINVAL;
152 goto out;
153 }
154
155 memcpy(data, info->buffer.pointer, out_sz);
156 out:
157 kfree(info);
158 return err;
159 }
160
is_apmf_func_supported(struct amd_pmf_dev * pdev,unsigned long index)161 int is_apmf_func_supported(struct amd_pmf_dev *pdev, unsigned long index)
162 {
163 /* If bit-n is set, that indicates function n+1 is supported */
164 return !!(pdev->supported_func & BIT(index - 1));
165 }
166
is_apmf_bios_input_notifications_supported(struct amd_pmf_dev * pdev)167 int is_apmf_bios_input_notifications_supported(struct amd_pmf_dev *pdev)
168 {
169 return !!(pdev->notifications & CUSTOM_BIOS_INPUT_BITS);
170 }
171
apts_get_static_slider_granular_v2(struct amd_pmf_dev * pdev,struct amd_pmf_apts_granular_output * data,u32 apts_idx)172 int apts_get_static_slider_granular_v2(struct amd_pmf_dev *pdev,
173 struct amd_pmf_apts_granular_output *data, u32 apts_idx)
174 {
175 if (!is_apmf_func_supported(pdev, APMF_FUNC_STATIC_SLIDER_GRANULAR))
176 return -EINVAL;
177
178 return apts_if_call_store_buffer(pdev, apts_idx, data, sizeof(*data));
179 }
180
apmf_get_static_slider_granular_v2(struct amd_pmf_dev * pdev,struct apmf_static_slider_granular_output_v2 * data)181 int apmf_get_static_slider_granular_v2(struct amd_pmf_dev *pdev,
182 struct apmf_static_slider_granular_output_v2 *data)
183 {
184 if (!is_apmf_func_supported(pdev, APMF_FUNC_STATIC_SLIDER_GRANULAR))
185 return -EINVAL;
186
187 return apmf_if_call_store_buffer(pdev, APMF_FUNC_STATIC_SLIDER_GRANULAR,
188 data, sizeof(*data));
189 }
190
apmf_get_static_slider_granular(struct amd_pmf_dev * pdev,struct apmf_static_slider_granular_output * data)191 int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
192 struct apmf_static_slider_granular_output *data)
193 {
194 if (!is_apmf_func_supported(pdev, APMF_FUNC_STATIC_SLIDER_GRANULAR))
195 return -EINVAL;
196
197 return apmf_if_call_store_buffer(pdev, APMF_FUNC_STATIC_SLIDER_GRANULAR,
198 data, sizeof(*data));
199 }
200
apmf_os_power_slider_update(struct amd_pmf_dev * pdev,u8 event)201 int apmf_os_power_slider_update(struct amd_pmf_dev *pdev, u8 event)
202 {
203 struct os_power_slider args;
204 struct acpi_buffer params;
205 union acpi_object *info;
206
207 args.size = sizeof(args);
208 args.slider_event = event;
209
210 params.length = sizeof(args);
211 params.pointer = (void *)&args;
212
213 info = apmf_if_call(pdev, APMF_FUNC_OS_POWER_SLIDER_UPDATE, ¶ms);
214 if (!info)
215 return -EIO;
216
217 kfree(info);
218 return 0;
219 }
220
apmf_sbios_heartbeat_notify(struct work_struct * work)221 static void apmf_sbios_heartbeat_notify(struct work_struct *work)
222 {
223 struct amd_pmf_dev *dev = container_of(work, struct amd_pmf_dev, heart_beat.work);
224 union acpi_object *info;
225
226 dev_dbg(dev->dev, "Sending heartbeat to SBIOS\n");
227 info = apmf_if_call(dev, APMF_FUNC_SBIOS_HEARTBEAT, NULL);
228 if (!info)
229 return;
230
231 schedule_delayed_work(&dev->heart_beat, secs_to_jiffies(dev->hb_interval));
232 kfree(info);
233 }
234
amd_pmf_notify_sbios_heartbeat_event_v2(struct amd_pmf_dev * dev,u8 flag)235 int amd_pmf_notify_sbios_heartbeat_event_v2(struct amd_pmf_dev *dev, u8 flag)
236 {
237 struct sbios_hb_event_v2 args = { };
238 struct acpi_buffer params;
239 union acpi_object *info;
240
241 args.size = sizeof(args);
242
243 switch (flag) {
244 case ON_LOAD:
245 args.load = 1;
246 break;
247 case ON_UNLOAD:
248 args.unload = 1;
249 break;
250 case ON_SUSPEND:
251 args.suspend = 1;
252 break;
253 case ON_RESUME:
254 args.resume = 1;
255 break;
256 default:
257 dev_dbg(dev->dev, "Failed to send v2 heartbeat event, flag:0x%x\n", flag);
258 return -EINVAL;
259 }
260
261 params.length = sizeof(args);
262 params.pointer = &args;
263
264 info = apmf_if_call(dev, APMF_FUNC_SBIOS_HEARTBEAT_V2, ¶ms);
265 if (!info)
266 return -EIO;
267
268 kfree(info);
269 return 0;
270 }
271
apmf_update_fan_idx(struct amd_pmf_dev * pdev,bool manual,u32 idx)272 int apmf_update_fan_idx(struct amd_pmf_dev *pdev, bool manual, u32 idx)
273 {
274 union acpi_object *info;
275 struct apmf_fan_idx args;
276 struct acpi_buffer params;
277
278 args.size = sizeof(args);
279 args.fan_ctl_mode = manual;
280 args.fan_ctl_idx = idx;
281
282 params.length = sizeof(args);
283 params.pointer = (void *)&args;
284
285 info = apmf_if_call(pdev, APMF_FUNC_SET_FAN_IDX, ¶ms);
286 if (!info)
287 return -EIO;
288
289 kfree(info);
290 return 0;
291 }
292
apmf_notify_smart_pc_update(struct amd_pmf_dev * pdev,u32 val,u32 preq,u32 index)293 static int apmf_notify_smart_pc_update(struct amd_pmf_dev *pdev, u32 val, u32 preq, u32 index)
294 {
295 struct amd_pmf_notify_smart_pc_update args;
296 struct acpi_buffer params;
297 union acpi_object *info;
298
299 args.size = sizeof(args);
300 args.pending_req = preq;
301 args.custom_bios[index] = val;
302
303 params.length = sizeof(args);
304 params.pointer = &args;
305
306 info = apmf_if_call(pdev, APMF_FUNC_NOTIFY_SMART_PC_UPDATES, ¶ms);
307 if (!info)
308 return -EIO;
309
310 kfree(info);
311 dev_dbg(pdev->dev, "Notify smart pc update, val: %u\n", val);
312
313 return 0;
314 }
315
apmf_get_auto_mode_def(struct amd_pmf_dev * pdev,struct apmf_auto_mode * data)316 int apmf_get_auto_mode_def(struct amd_pmf_dev *pdev, struct apmf_auto_mode *data)
317 {
318 return apmf_if_call_store_buffer(pdev, APMF_FUNC_AUTO_MODE, data, sizeof(*data));
319 }
320
apmf_get_sbios_requests_v2(struct amd_pmf_dev * pdev,struct apmf_sbios_req_v2 * req)321 int apmf_get_sbios_requests_v2(struct amd_pmf_dev *pdev, struct apmf_sbios_req_v2 *req)
322 {
323 return apmf_if_call_store_buffer(pdev, APMF_FUNC_SBIOS_REQUESTS, req, sizeof(*req));
324 }
325
apmf_get_sbios_requests_v1(struct amd_pmf_dev * pdev,struct apmf_sbios_req_v1 * req)326 int apmf_get_sbios_requests_v1(struct amd_pmf_dev *pdev, struct apmf_sbios_req_v1 *req)
327 {
328 return apmf_if_call_store_buffer(pdev, APMF_FUNC_SBIOS_REQUESTS, req, sizeof(*req));
329 }
330
apmf_get_sbios_requests(struct amd_pmf_dev * pdev,struct apmf_sbios_req * req)331 int apmf_get_sbios_requests(struct amd_pmf_dev *pdev, struct apmf_sbios_req *req)
332 {
333 return apmf_if_call_store_buffer(pdev, APMF_FUNC_SBIOS_REQUESTS,
334 req, sizeof(*req));
335 }
336
337 /* Store custom BIOS inputs data in ring buffer */
amd_pmf_custom_bios_inputs_rb(struct amd_pmf_dev * pmf_dev)338 static void amd_pmf_custom_bios_inputs_rb(struct amd_pmf_dev *pmf_dev)
339 {
340 struct pmf_cbi_ring_buffer *rb = &pmf_dev->cbi_buf;
341 int i;
342
343 guard(mutex)(&pmf_dev->cbi_mutex);
344
345 switch (pmf_dev->cpu_id) {
346 case AMD_CPU_ID_PS:
347 for (i = 0; i < ARRAY_SIZE(custom_bios_inputs_v1); i++)
348 rb->data[rb->head].val[i] = pmf_dev->req1.custom_policy[i];
349 rb->data[rb->head].preq = pmf_dev->req1.pending_req;
350 break;
351 case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT:
352 case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT:
353 for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++)
354 rb->data[rb->head].val[i] = pmf_dev->req.custom_policy[i];
355 rb->data[rb->head].preq = pmf_dev->req.pending_req;
356 break;
357 default:
358 return;
359 }
360
361 if (CIRC_SPACE(rb->head, rb->tail, CUSTOM_BIOS_INPUT_RING_ENTRIES) == 0) {
362 /* Rare case: ensures the newest BIOS input value is kept */
363 dev_warn(pmf_dev->dev, "Overwriting BIOS input value, data may be lost\n");
364 rb->tail = (rb->tail + 1) & (CUSTOM_BIOS_INPUT_RING_ENTRIES - 1);
365 }
366
367 rb->head = (rb->head + 1) & (CUSTOM_BIOS_INPUT_RING_ENTRIES - 1);
368 }
369
amd_pmf_handle_early_preq(struct amd_pmf_dev * pdev)370 static void amd_pmf_handle_early_preq(struct amd_pmf_dev *pdev)
371 {
372 if (!pdev->cb_flag)
373 return;
374
375 amd_pmf_invoke_cmd_enact(pdev);
376 pdev->cb_flag = false;
377 }
378
apmf_event_handler_v2(acpi_handle handle,u32 event,void * data)379 static void apmf_event_handler_v2(acpi_handle handle, u32 event, void *data)
380 {
381 struct amd_pmf_dev *pmf_dev = data;
382 int ret;
383
384 guard(mutex)(&pmf_dev->cb_mutex);
385
386 ret = apmf_get_sbios_requests_v2(pmf_dev, &pmf_dev->req);
387 if (ret) {
388 dev_err(pmf_dev->dev, "Failed to get v2 SBIOS requests: %d\n", ret);
389 return;
390 }
391
392 dev_dbg(pmf_dev->dev, "Pending request (preq): 0x%x\n", pmf_dev->req.pending_req);
393
394 amd_pmf_handle_early_preq(pmf_dev);
395
396 amd_pmf_custom_bios_inputs_rb(pmf_dev);
397 }
398
apmf_event_handler_v1(acpi_handle handle,u32 event,void * data)399 static void apmf_event_handler_v1(acpi_handle handle, u32 event, void *data)
400 {
401 struct amd_pmf_dev *pmf_dev = data;
402 int ret;
403
404 guard(mutex)(&pmf_dev->cb_mutex);
405
406 ret = apmf_get_sbios_requests_v1(pmf_dev, &pmf_dev->req1);
407 if (ret) {
408 dev_err(pmf_dev->dev, "Failed to get v1 SBIOS requests: %d\n", ret);
409 return;
410 }
411
412 dev_dbg(pmf_dev->dev, "Pending request (preq1): 0x%x\n", pmf_dev->req1.pending_req);
413
414 amd_pmf_handle_early_preq(pmf_dev);
415
416 amd_pmf_custom_bios_inputs_rb(pmf_dev);
417 }
418
apmf_event_handler(acpi_handle handle,u32 event,void * data)419 static void apmf_event_handler(acpi_handle handle, u32 event, void *data)
420 {
421 struct amd_pmf_dev *pmf_dev = data;
422 struct apmf_sbios_req req;
423 int ret;
424
425 guard(mutex)(&pmf_dev->update_mutex);
426 ret = apmf_get_sbios_requests(pmf_dev, &req);
427 if (ret) {
428 dev_err(pmf_dev->dev, "Failed to get SBIOS requests:%d\n", ret);
429 return;
430 }
431
432 if (req.pending_req & BIT(APMF_AMT_NOTIFICATION)) {
433 dev_dbg(pmf_dev->dev, "AMT is supported and notifications %s\n",
434 req.amt_event ? "Enabled" : "Disabled");
435 pmf_dev->amt_enabled = !!req.amt_event;
436
437 if (pmf_dev->amt_enabled)
438 amd_pmf_handle_amt(pmf_dev);
439 else
440 amd_pmf_reset_amt(pmf_dev);
441 }
442
443 if (req.pending_req & BIT(APMF_CQL_NOTIFICATION)) {
444 dev_dbg(pmf_dev->dev, "CQL is supported and notifications %s\n",
445 req.cql_event ? "Enabled" : "Disabled");
446
447 /* update the target mode information */
448 if (pmf_dev->amt_enabled)
449 amd_pmf_update_2_cql(pmf_dev, req.cql_event);
450 }
451 }
452
apmf_if_verify_interface(struct amd_pmf_dev * pdev)453 static int apmf_if_verify_interface(struct amd_pmf_dev *pdev)
454 {
455 struct apmf_verify_interface output;
456 int err;
457
458 err = apmf_if_call_store_buffer(pdev, APMF_FUNC_VERIFY_INTERFACE, &output, sizeof(output));
459 if (err)
460 return err;
461
462 /* only set if not already set by a quirk */
463 if (!pdev->supported_func)
464 pdev->supported_func = output.supported_functions;
465
466 dev_dbg(pdev->dev, "supported functions:0x%x notifications:0x%x version:%u\n",
467 output.supported_functions, output.notification_mask, output.version);
468
469 pdev->pmf_if_version = output.version;
470
471 pdev->notifications = output.notification_mask;
472 return 0;
473 }
474
apmf_get_system_params(struct amd_pmf_dev * dev)475 static int apmf_get_system_params(struct amd_pmf_dev *dev)
476 {
477 struct apmf_system_params params;
478 int err;
479
480 if (!is_apmf_func_supported(dev, APMF_FUNC_GET_SYS_PARAMS))
481 return -EINVAL;
482
483 err = apmf_if_call_store_buffer(dev, APMF_FUNC_GET_SYS_PARAMS, ¶ms, sizeof(params));
484 if (err)
485 return err;
486
487 dev_dbg(dev->dev, "system params mask:0x%x flags:0x%x cmd_code:0x%x heartbeat:%d\n",
488 params.valid_mask,
489 params.flags,
490 params.command_code,
491 params.heartbeat_int);
492 params.flags = params.flags & params.valid_mask;
493 dev->hb_interval = params.heartbeat_int;
494
495 return 0;
496 }
497
apmf_get_dyn_slider_def_ac(struct amd_pmf_dev * pdev,struct apmf_dyn_slider_output * data)498 int apmf_get_dyn_slider_def_ac(struct amd_pmf_dev *pdev, struct apmf_dyn_slider_output *data)
499 {
500 return apmf_if_call_store_buffer(pdev, APMF_FUNC_DYN_SLIDER_AC, data, sizeof(*data));
501 }
502
apmf_get_dyn_slider_def_dc(struct amd_pmf_dev * pdev,struct apmf_dyn_slider_output * data)503 int apmf_get_dyn_slider_def_dc(struct amd_pmf_dev *pdev, struct apmf_dyn_slider_output *data)
504 {
505 return apmf_if_call_store_buffer(pdev, APMF_FUNC_DYN_SLIDER_DC, data, sizeof(*data));
506 }
507
508 static apmf_event_handler_t apmf_event_handlers[] = {
509 [PMF_IF_V1] = apmf_event_handler_v1,
510 [PMF_IF_V2] = apmf_event_handler_v2,
511 };
512
apmf_install_handler(struct amd_pmf_dev * pmf_dev)513 int apmf_install_handler(struct amd_pmf_dev *pmf_dev)
514 {
515 acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
516 acpi_status status;
517
518 /* Install the APMF Notify handler */
519 if (is_apmf_func_supported(pmf_dev, APMF_FUNC_AUTO_MODE) &&
520 is_apmf_func_supported(pmf_dev, APMF_FUNC_SBIOS_REQUESTS)) {
521 status = acpi_install_notify_handler(ahandle, ACPI_ALL_NOTIFY,
522 apmf_event_handler, pmf_dev);
523 if (ACPI_FAILURE(status)) {
524 dev_err(pmf_dev->dev, "failed to install notify handler\n");
525 return -ENODEV;
526 }
527
528 /* Call the handler once manually to catch up with possibly missed notifies. */
529 apmf_event_handler(ahandle, 0, pmf_dev);
530 }
531
532 if (!pmf_dev->smart_pc_enabled)
533 return -EINVAL;
534
535 switch (pmf_dev->pmf_if_version) {
536 case PMF_IF_V1:
537 if (!is_apmf_bios_input_notifications_supported(pmf_dev))
538 break;
539 fallthrough;
540 case PMF_IF_V2:
541 status = acpi_install_notify_handler(ahandle, ACPI_ALL_NOTIFY,
542 apmf_event_handlers[pmf_dev->pmf_if_version], pmf_dev);
543 if (ACPI_FAILURE(status)) {
544 dev_err(pmf_dev->dev,
545 "failed to install notify handler v%d for custom BIOS inputs\n",
546 pmf_dev->pmf_if_version);
547 return -ENODEV;
548 }
549 break;
550 default:
551 break;
552 }
553
554 return 0;
555 }
556
apmf_check_smart_pc(struct amd_pmf_dev * pmf_dev)557 int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev)
558 {
559 struct platform_device *pdev = to_platform_device(pmf_dev->dev);
560
561 pmf_dev->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
562 if (!pmf_dev->res) {
563 dev_dbg(pmf_dev->dev, "Failed to get I/O memory resource\n");
564 return -EINVAL;
565 }
566
567 pmf_dev->policy_addr = pmf_dev->res->start;
568 /*
569 * We cannot use resource_size() here because it adds an extra byte to round off the size.
570 * In the case of PMF ResourceTemplate(), this rounding is already handled within the _CRS.
571 * Using resource_size() would increase the resource size by 1, causing a mismatch with the
572 * length field and leading to issues. Therefore, simply use end-start of the ACPI resource
573 * to obtain the actual length.
574 */
575 pmf_dev->policy_sz = pmf_dev->res->end - pmf_dev->res->start;
576
577 if (!pmf_dev->policy_addr || pmf_dev->policy_sz > POLICY_BUF_MAX_SZ ||
578 pmf_dev->policy_sz == 0) {
579 dev_err(pmf_dev->dev, "Incorrect policy params, possibly a SBIOS bug\n");
580 return -EINVAL;
581 }
582
583 return 0;
584 }
585
amd_pmf_smartpc_apply_bios_output(struct amd_pmf_dev * dev,u32 val,u32 preq,u32 idx)586 int amd_pmf_smartpc_apply_bios_output(struct amd_pmf_dev *dev, u32 val, u32 preq, u32 idx)
587 {
588 if (!is_apmf_func_supported(dev, APMF_FUNC_NOTIFY_SMART_PC_UPDATES))
589 return -EINVAL;
590
591 return apmf_notify_smart_pc_update(dev, val, preq, idx);
592 }
593
apmf_acpi_deinit(struct amd_pmf_dev * pmf_dev)594 void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev)
595 {
596 acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
597
598 if (pmf_dev->hb_interval && pmf_dev->pmf_if_version == PMF_IF_V1)
599 cancel_delayed_work_sync(&pmf_dev->heart_beat);
600
601 if (is_apmf_func_supported(pmf_dev, APMF_FUNC_AUTO_MODE) &&
602 is_apmf_func_supported(pmf_dev, APMF_FUNC_SBIOS_REQUESTS))
603 acpi_remove_notify_handler(ahandle, ACPI_ALL_NOTIFY, apmf_event_handler);
604
605 if (!pmf_dev->smart_pc_enabled)
606 return;
607
608 switch (pmf_dev->pmf_if_version) {
609 case PMF_IF_V1:
610 if (!is_apmf_bios_input_notifications_supported(pmf_dev))
611 break;
612 fallthrough;
613 case PMF_IF_V2:
614 acpi_remove_notify_handler(ahandle, ACPI_ALL_NOTIFY,
615 apmf_event_handlers[pmf_dev->pmf_if_version]);
616 break;
617 default:
618 break;
619 }
620 }
621
apmf_acpi_init(struct amd_pmf_dev * pmf_dev)622 int apmf_acpi_init(struct amd_pmf_dev *pmf_dev)
623 {
624 int ret;
625
626 ret = apmf_if_verify_interface(pmf_dev);
627 if (ret) {
628 dev_err(pmf_dev->dev, "APMF verify interface failed :%d\n", ret);
629 goto out;
630 }
631
632 ret = apmf_get_system_params(pmf_dev);
633 if (ret) {
634 dev_dbg(pmf_dev->dev, "APMF apmf_get_system_params failed :%d\n", ret);
635 goto out;
636 }
637
638 if (pmf_dev->hb_interval && pmf_dev->pmf_if_version == PMF_IF_V1) {
639 /* send heartbeats only if the interval is not zero */
640 INIT_DELAYED_WORK(&pmf_dev->heart_beat, apmf_sbios_heartbeat_notify);
641 schedule_delayed_work(&pmf_dev->heart_beat, 0);
642 }
643
644 out:
645 return ret;
646 }
647