Add platform-level registration helpers that will ease transition of the arch/platform power-off callbacks to the new sys-off based API, allowing us to remove the global pm_power_off variable in the future.
Unified · Split
| @@ -141,6 +141,9 @@ int devm_register_sys_off_handler(struct device *dev, · 140 unmodified lines | ||
| 141 | 141 | int (*callback)(struct sys_off_data *data), |
| 142 | 142 | void *cb_data); |
| 143 | 143 | |
| 144 | +int register_platform_power_off(void (*power_off)(void)); | |
| 145 | +void unregister_platform_power_off(void (*power_off)(void)); | |
| 146 | + | |
| 144 | 147 | /* |
| 145 | 148 | * Architecture independent implemenations of sys_reboot commands. |
| 146 | 149 | */ |
| @@ -469,6 +469,61 @@ int devm_register_sys_off_handler(struct device *dev, · 468 unmodified lines | ||
| 469 | 469 | } |
| 470 | 470 | EXPORT_SYMBOL_GPL(devm_register_sys_off_handler); |
| 471 | 471 | |
| 472 | +static struct sys_off_handler *platform_power_off_handler; | |
| 473 | + | |
| 474 | +static int platform_power_off_notify(struct sys_off_data *data) | |
| 475 | +{ | |
| 476 | + void (*platform_power_power_off_cb)(void) = data->cb_data; | |
| 477 | + | |
| 478 | + platform_power_power_off_cb(); | |
| 479 | + | |
| 480 | + return NOTIFY_DONE; | |
| 481 | +} | |
| 482 | + | |
| 483 | +/** | |
| 484 | + * register_platform_power_off - Register platform-level power-off callback | |
| 485 | + * @power_off: Power-off callback | |
| 486 | + * | |
| 487 | + * Registers power-off callback that will be called as last step | |
| 488 | + * of the power-off sequence. This callback is expected to be invoked | |
| 489 | + * for the last resort. Only one platform power-off callback is allowed | |
| 490 | + * to be registered at a time. | |
| 491 | + * | |
| 492 | + * Returns zero on success, or error code on failure. | |
| 493 | + */ | |
| 494 | +int register_platform_power_off(void (*power_off)(void)) | |
| 495 | +{ | |
| 496 | + struct sys_off_handler *handler; | |
| 497 | + | |
| 498 | + handler = register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, | |
| 499 | + SYS_OFF_PRIO_PLATFORM, | |
| 500 | + platform_power_off_notify, | |
| 501 | + power_off); | |
| 502 | + if (IS_ERR(handler)) | |
| 503 | + return PTR_ERR(handler); | |
| 504 | + | |
| 505 | + platform_power_off_handler = handler; | |
| 506 | + | |
| 507 | + return 0; | |
| 508 | +} | |
| 509 | +EXPORT_SYMBOL_GPL(register_platform_power_off); | |
| 510 | + | |
| 511 | +/** | |
| 512 | + * unregister_platform_power_off - Unregister platform-level power-off callback | |
| 513 | + * @power_off: Power-off callback | |
| 514 | + * | |
| 515 | + * Unregisters previously registered platform power-off callback. | |
| 516 | + */ | |
| 517 | +void unregister_platform_power_off(void (*power_off)(void)) | |
| 518 | +{ | |
| 519 | + if (platform_power_off_handler && | |
| 520 | + platform_power_off_handler->cb_data == power_off) { | |
| 521 | + unregister_sys_off_handler(platform_power_off_handler); | |
| 522 | + platform_power_off_handler = NULL; | |
| 523 | + } | |
| 524 | +} | |
| 525 | +EXPORT_SYMBOL_GPL(unregister_platform_power_off); | |
| 526 | + | |
| 472 | 527 | static int legacy_pm_power_off_prepare(struct sys_off_data *data) |
| 473 | 528 | { |
| 474 | 529 | if (pm_power_off_prepare) |