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 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 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 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 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 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 167 int is_apmf_bios_input_notifications_supported(struct amd_pmf_dev *pdev) 168 { 169 return !!(pdev->notifications & CUSTOM_BIOS_INPUT_BITS); 170 } 171 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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