PM/Suspend: Introduce two new platform callbacks to avoid breakage

Commit 900af0d973856d6feb6fc088c2d0d3fde57707d3 (PM: Change suspend
code ordering) changed the ordering of suspend code in such a way
that the platform .prepare() callback is now executed after the
device drivers' late suspend callbacks have run. Unfortunately, this
turns out to break ARM platforms that need to talk via I2C to power
control devices during the .prepare() callback.

For this reason introduce two new platform suspend callbacks,
.prepare_late() and .wake(), that will be called just prior to
disabling non-boot CPUs and right after bringing them back on line,
respectively, and use them instead of .prepare() and .finish() for
ACPI suspend. Make the PM core execute the .prepare() and .finish()
platform suspend callbacks where they were executed previously (that
is, right after calling the regular suspend methods provided by
device drivers and right before executing their regular resume
methods, respectively).

It is not necessary to make analogous changes to the hibernation
code and data structures at the moment, because they are only used
by ACPI platforms.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
Acked-by: Len Brown <len.brown@intel.com>

+47 -21
+4 -4
drivers/acpi/sleep.c
··· 300 300 static struct platform_suspend_ops acpi_suspend_ops = { 301 301 .valid = acpi_suspend_state_valid, 302 302 .begin = acpi_suspend_begin, 303 - .prepare = acpi_pm_prepare, 303 + .prepare_late = acpi_pm_prepare, 304 304 .enter = acpi_suspend_enter, 305 - .finish = acpi_pm_finish, 305 + .wake = acpi_pm_finish, 306 306 .end = acpi_pm_end, 307 307 }; 308 308 ··· 328 328 static struct platform_suspend_ops acpi_suspend_ops_old = { 329 329 .valid = acpi_suspend_state_valid, 330 330 .begin = acpi_suspend_begin_old, 331 - .prepare = acpi_pm_disable_gpes, 331 + .prepare_late = acpi_pm_disable_gpes, 332 332 .enter = acpi_suspend_enter, 333 - .finish = acpi_pm_finish, 333 + .wake = acpi_pm_finish, 334 334 .end = acpi_pm_end, 335 335 .recover = acpi_pm_finish, 336 336 };
+26 -10
include/linux/suspend.h
··· 58 58 * by @begin(). 59 59 * @prepare() is called right after devices have been suspended (ie. the 60 60 * appropriate .suspend() method has been executed for each device) and 61 - * before the nonboot CPUs are disabled (it is executed with IRQs enabled). 62 - * This callback is optional. It returns 0 on success or a negative 63 - * error code otherwise, in which case the system cannot enter the desired 64 - * sleep state (@enter() and @finish() will not be called in that case). 61 + * before device drivers' late suspend callbacks are executed. It returns 62 + * 0 on success or a negative error code otherwise, in which case the 63 + * system cannot enter the desired sleep state (@prepare_late(), @enter(), 64 + * @wake(), and @finish() will not be called in that case). 65 + * 66 + * @prepare_late: Finish preparing the platform for entering the system sleep 67 + * state indicated by @begin(). 68 + * @prepare_late is called before disabling nonboot CPUs and after 69 + * device drivers' late suspend callbacks have been executed. It returns 70 + * 0 on success or a negative error code otherwise, in which case the 71 + * system cannot enter the desired sleep state (@enter() and @wake()). 65 72 * 66 73 * @enter: Enter the system sleep state indicated by @begin() or represented by 67 74 * the argument if @begin() is not implemented. ··· 76 69 * error code otherwise, in which case the system cannot enter the desired 77 70 * sleep state. 78 71 * 79 - * @finish: Called when the system has just left a sleep state, right after 80 - * the nonboot CPUs have been enabled and before devices are resumed (it is 81 - * executed with IRQs enabled). 72 + * @wake: Called when the system has just left a sleep state, right after 73 + * the nonboot CPUs have been enabled and before device drivers' early 74 + * resume callbacks are executed. 75 + * This callback is optional, but should be implemented by the platforms 76 + * that implement @prepare_late(). If implemented, it is always called 77 + * after @enter(), even if @enter() fails. 78 + * 79 + * @finish: Finish wake-up of the platform. 80 + * @finish is called right prior to calling device drivers' regular suspend 81 + * callbacks. 82 82 * This callback is optional, but should be implemented by the platforms 83 83 * that implement @prepare(). If implemented, it is always called after 84 - * @enter() (even if @enter() fails). 84 + * @enter() and @wake(), if implemented, even if any of them fails. 85 85 * 86 86 * @end: Called by the PM core right after resuming devices, to indicate to 87 87 * the platform that the system has returned to the working state or 88 88 * the transition to the sleep state has been aborted. 89 89 * This callback is optional, but should be implemented by the platforms 90 - * that implement @begin(), but platforms implementing @begin() should 91 - * also provide a @end() which cleans up transitions aborted before 90 + * that implement @begin(). Accordingly, platforms implementing @begin() 91 + * should also provide a @end() which cleans up transitions aborted before 92 92 * @enter(). 93 93 * 94 94 * @recover: Recover the platform from a suspend failure. ··· 107 93 int (*valid)(suspend_state_t state); 108 94 int (*begin)(suspend_state_t state); 109 95 int (*prepare)(void); 96 + int (*prepare_late)(void); 110 97 int (*enter)(suspend_state_t state); 98 + void (*wake)(void); 111 99 void (*finish)(void); 112 100 void (*end)(void); 113 101 void (*recover)(void);
+17 -7
kernel/power/main.c
··· 291 291 292 292 device_pm_lock(); 293 293 294 + if (suspend_ops->prepare) { 295 + error = suspend_ops->prepare(); 296 + if (error) 297 + goto Done; 298 + } 299 + 294 300 error = device_power_down(PMSG_SUSPEND); 295 301 if (error) { 296 302 printk(KERN_ERR "PM: Some devices failed to power down\n"); 297 - goto Done; 303 + goto Platfrom_finish; 298 304 } 299 305 300 - if (suspend_ops->prepare) { 301 - error = suspend_ops->prepare(); 306 + if (suspend_ops->prepare_late) { 307 + error = suspend_ops->prepare_late(); 302 308 if (error) 303 309 goto Power_up_devices; 304 310 } 305 311 306 312 if (suspend_test(TEST_PLATFORM)) 307 - goto Platfrom_finish; 313 + goto Platform_wake; 308 314 309 315 error = disable_nonboot_cpus(); 310 316 if (error || suspend_test(TEST_CPUS)) ··· 332 326 Enable_cpus: 333 327 enable_nonboot_cpus(); 334 328 335 - Platfrom_finish: 336 - if (suspend_ops->finish) 337 - suspend_ops->finish(); 329 + Platform_wake: 330 + if (suspend_ops->wake) 331 + suspend_ops->wake(); 338 332 339 333 Power_up_devices: 340 334 device_power_up(PMSG_RESUME); 335 + 336 + Platfrom_finish: 337 + if (suspend_ops->finish) 338 + suspend_ops->finish(); 341 339 342 340 Done: 343 341 device_pm_unlock();