Skip to content

Commit b62b306

Browse files
committed
Merge branch 'pm-sleep'
Merge updates related to system sleep for 5.16-rc1: - Clean up hib_wait_io() (Falla Coulibaly). - Fix sparse warnings in hibernation-related code (Anders Roxell). - Use vzalloc() and kzalloc() instead of their open-coded equivalents in hibernation-related code (Cai Huoqing). - Prevent user space from crashing the kernel by attempting to restore the system state from a swap partition in use (Ye Bin). - Do not let "syscore" devices runtime-suspend during system PM transitions (Rafael Wysocki). - Do not pause cpuidle in the suspend-to-idle path (Rafael Wysocki). - Pause cpuidle later and resume it earlier during system PM transitions (Rafael Wysocki). - Make system suspend code use valid_state() consistently (Rafael Wysocki). - Add support for enabling wakeup IRQs after invoking the ->runtime_suspend() callback and make two drivers use it (Chunfeng Yun). * pm-sleep: usb: mtu3: enable wake-up interrupt after runtime_suspend called usb: xhci-mtk: enable wake-up interrupt after runtime_suspend called PM / wakeirq: support enabling wake-up irq after runtime_suspend called PM: suspend: Use valid_state() consistently PM: sleep: Pause cpuidle later and resume it earlier during system transitions PM: suspend: Do not pause cpuidle in the suspend-to-idle path PM: sleep: Do not let "syscore" devices runtime-suspend during system transitions PM: hibernate: Get block device exclusively in swsusp_check() PM: hibernate: swap: Use vzalloc() and kzalloc() PM: hibernate: fix sparse warnings Revert "PM: sleep: Do not assume that "mem" is always present" PM: hibernate: Remove blk_status_to_errno in hib_wait_io PM: sleep: Do not assume that "mem" is always present
2 parents 1fec161 + 7ddae8c commit b62b306

File tree

11 files changed

+141
-65
lines changed

11 files changed

+141
-65
lines changed

drivers/base/power/main.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
#include <linux/suspend.h>
3333
#include <trace/events/power.h>
3434
#include <linux/cpufreq.h>
35-
#include <linux/cpuidle.h>
3635
#include <linux/devfreq.h>
3736
#include <linux/timer.h>
3837

@@ -747,8 +746,6 @@ void dpm_resume_noirq(pm_message_t state)
747746

748747
resume_device_irqs();
749748
device_wakeup_disarm_wake_irqs();
750-
751-
cpuidle_resume();
752749
}
753750

754751
/**
@@ -1051,7 +1048,7 @@ static void device_complete(struct device *dev, pm_message_t state)
10511048
const char *info = NULL;
10521049

10531050
if (dev->power.syscore)
1054-
return;
1051+
goto out;
10551052

10561053
device_lock(dev);
10571054

@@ -1081,6 +1078,7 @@ static void device_complete(struct device *dev, pm_message_t state)
10811078

10821079
device_unlock(dev);
10831080

1081+
out:
10841082
pm_runtime_put(dev);
10851083
}
10861084

@@ -1336,8 +1334,6 @@ int dpm_suspend_noirq(pm_message_t state)
13361334
{
13371335
int ret;
13381336

1339-
cpuidle_pause();
1340-
13411337
device_wakeup_arm_wake_irqs();
13421338
suspend_device_irqs();
13431339

@@ -1794,9 +1790,6 @@ static int device_prepare(struct device *dev, pm_message_t state)
17941790
int (*callback)(struct device *) = NULL;
17951791
int ret = 0;
17961792

1797-
if (dev->power.syscore)
1798-
return 0;
1799-
18001793
/*
18011794
* If a device's parent goes into runtime suspend at the wrong time,
18021795
* it won't be possible to resume the device. To prevent this we
@@ -1805,6 +1798,9 @@ static int device_prepare(struct device *dev, pm_message_t state)
18051798
*/
18061799
pm_runtime_get_noresume(dev);
18071800

1801+
if (dev->power.syscore)
1802+
return 0;
1803+
18081804
device_lock(dev);
18091805

18101806
dev->power.wakeup_path = false;

drivers/base/power/power.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ extern u64 pm_runtime_active_time(struct device *dev);
2525

2626
#define WAKE_IRQ_DEDICATED_ALLOCATED BIT(0)
2727
#define WAKE_IRQ_DEDICATED_MANAGED BIT(1)
28+
#define WAKE_IRQ_DEDICATED_REVERSE BIT(2)
2829
#define WAKE_IRQ_DEDICATED_MASK (WAKE_IRQ_DEDICATED_ALLOCATED | \
29-
WAKE_IRQ_DEDICATED_MANAGED)
30+
WAKE_IRQ_DEDICATED_MANAGED | \
31+
WAKE_IRQ_DEDICATED_REVERSE)
3032

3133
struct wake_irq {
3234
struct device *dev;
@@ -39,7 +41,8 @@ extern void dev_pm_arm_wake_irq(struct wake_irq *wirq);
3941
extern void dev_pm_disarm_wake_irq(struct wake_irq *wirq);
4042
extern void dev_pm_enable_wake_irq_check(struct device *dev,
4143
bool can_change_status);
42-
extern void dev_pm_disable_wake_irq_check(struct device *dev);
44+
extern void dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable);
45+
extern void dev_pm_enable_wake_irq_complete(struct device *dev);
4346

4447
#ifdef CONFIG_PM_SLEEP
4548

drivers/base/power/runtime.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,8 @@ static int rpm_suspend(struct device *dev, int rpmflags)
645645
if (retval)
646646
goto fail;
647647

648+
dev_pm_enable_wake_irq_complete(dev);
649+
648650
no_callback:
649651
__update_runtime_status(dev, RPM_SUSPENDED);
650652
pm_runtime_deactivate_timer(dev);
@@ -690,7 +692,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
690692
return retval;
691693

692694
fail:
693-
dev_pm_disable_wake_irq_check(dev);
695+
dev_pm_disable_wake_irq_check(dev, true);
694696
__update_runtime_status(dev, RPM_ACTIVE);
695697
dev->power.deferred_resume = false;
696698
wake_up_all(&dev->power.wait_queue);
@@ -873,7 +875,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
873875

874876
callback = RPM_GET_CALLBACK(dev, runtime_resume);
875877

876-
dev_pm_disable_wake_irq_check(dev);
878+
dev_pm_disable_wake_irq_check(dev, false);
877879
retval = rpm_callback(callback, dev);
878880
if (retval) {
879881
__update_runtime_status(dev, RPM_SUSPENDED);

drivers/base/power/wakeirq.c

Lines changed: 80 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -142,24 +142,7 @@ static irqreturn_t handle_threaded_wake_irq(int irq, void *_wirq)
142142
return IRQ_HANDLED;
143143
}
144144

145-
/**
146-
* dev_pm_set_dedicated_wake_irq - Request a dedicated wake-up interrupt
147-
* @dev: Device entry
148-
* @irq: Device wake-up interrupt
149-
*
150-
* Unless your hardware has separate wake-up interrupts in addition
151-
* to the device IO interrupts, you don't need this.
152-
*
153-
* Sets up a threaded interrupt handler for a device that has
154-
* a dedicated wake-up interrupt in addition to the device IO
155-
* interrupt.
156-
*
157-
* The interrupt starts disabled, and needs to be managed for
158-
* the device by the bus code or the device driver using
159-
* dev_pm_enable_wake_irq() and dev_pm_disable_wake_irq()
160-
* functions.
161-
*/
162-
int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
145+
static int __dev_pm_set_dedicated_wake_irq(struct device *dev, int irq, unsigned int flag)
163146
{
164147
struct wake_irq *wirq;
165148
int err;
@@ -197,7 +180,7 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
197180
if (err)
198181
goto err_free_irq;
199182

200-
wirq->status = WAKE_IRQ_DEDICATED_ALLOCATED;
183+
wirq->status = WAKE_IRQ_DEDICATED_ALLOCATED | flag;
201184

202185
return err;
203186

@@ -210,8 +193,57 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
210193

211194
return err;
212195
}
196+
197+
198+
/**
199+
* dev_pm_set_dedicated_wake_irq - Request a dedicated wake-up interrupt
200+
* @dev: Device entry
201+
* @irq: Device wake-up interrupt
202+
*
203+
* Unless your hardware has separate wake-up interrupts in addition
204+
* to the device IO interrupts, you don't need this.
205+
*
206+
* Sets up a threaded interrupt handler for a device that has
207+
* a dedicated wake-up interrupt in addition to the device IO
208+
* interrupt.
209+
*
210+
* The interrupt starts disabled, and needs to be managed for
211+
* the device by the bus code or the device driver using
212+
* dev_pm_enable_wake_irq*() and dev_pm_disable_wake_irq*()
213+
* functions.
214+
*/
215+
int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
216+
{
217+
return __dev_pm_set_dedicated_wake_irq(dev, irq, 0);
218+
}
213219
EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq);
214220

221+
/**
222+
* dev_pm_set_dedicated_wake_irq_reverse - Request a dedicated wake-up interrupt
223+
* with reverse enable ordering
224+
* @dev: Device entry
225+
* @irq: Device wake-up interrupt
226+
*
227+
* Unless your hardware has separate wake-up interrupts in addition
228+
* to the device IO interrupts, you don't need this.
229+
*
230+
* Sets up a threaded interrupt handler for a device that has a dedicated
231+
* wake-up interrupt in addition to the device IO interrupt. It sets
232+
* the status of WAKE_IRQ_DEDICATED_REVERSE to tell rpm_suspend()
233+
* to enable dedicated wake-up interrupt after running the runtime suspend
234+
* callback for @dev.
235+
*
236+
* The interrupt starts disabled, and needs to be managed for
237+
* the device by the bus code or the device driver using
238+
* dev_pm_enable_wake_irq*() and dev_pm_disable_wake_irq*()
239+
* functions.
240+
*/
241+
int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq)
242+
{
243+
return __dev_pm_set_dedicated_wake_irq(dev, irq, WAKE_IRQ_DEDICATED_REVERSE);
244+
}
245+
EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq_reverse);
246+
215247
/**
216248
* dev_pm_enable_wake_irq - Enable device wake-up interrupt
217249
* @dev: Device
@@ -282,27 +314,54 @@ void dev_pm_enable_wake_irq_check(struct device *dev,
282314
return;
283315

284316
enable:
285-
enable_irq(wirq->irq);
317+
if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE))
318+
enable_irq(wirq->irq);
286319
}
287320

288321
/**
289322
* dev_pm_disable_wake_irq_check - Checks and disables wake-up interrupt
290323
* @dev: Device
324+
* @cond_disable: if set, also check WAKE_IRQ_DEDICATED_REVERSE
291325
*
292326
* Disables wake-up interrupt conditionally based on status.
293327
* Should be only called from rpm_suspend() and rpm_resume() path.
294328
*/
295-
void dev_pm_disable_wake_irq_check(struct device *dev)
329+
void dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable)
296330
{
297331
struct wake_irq *wirq = dev->power.wakeirq;
298332

299333
if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK))
300334
return;
301335

336+
if (cond_disable && (wirq->status & WAKE_IRQ_DEDICATED_REVERSE))
337+
return;
338+
302339
if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED)
303340
disable_irq_nosync(wirq->irq);
304341
}
305342

343+
/**
344+
* dev_pm_enable_wake_irq_complete - enable wake IRQ not enabled before
345+
* @dev: Device using the wake IRQ
346+
*
347+
* Enable wake IRQ conditionally based on status, mainly used if want to
348+
* enable wake IRQ after running ->runtime_suspend() which depends on
349+
* WAKE_IRQ_DEDICATED_REVERSE.
350+
*
351+
* Should be only called from rpm_suspend() path.
352+
*/
353+
void dev_pm_enable_wake_irq_complete(struct device *dev)
354+
{
355+
struct wake_irq *wirq = dev->power.wakeirq;
356+
357+
if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK))
358+
return;
359+
360+
if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED &&
361+
wirq->status & WAKE_IRQ_DEDICATED_REVERSE)
362+
enable_irq(wirq->irq);
363+
}
364+
306365
/**
307366
* dev_pm_arm_wake_irq - Arm device wake-up
308367
* @wirq: Device wake-up interrupt

drivers/usb/host/xhci-mtk.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ static int xhci_mtk_probe(struct platform_device *pdev)
602602
goto dealloc_usb2_hcd;
603603

604604
if (wakeup_irq > 0) {
605-
ret = dev_pm_set_dedicated_wake_irq(dev, wakeup_irq);
605+
ret = dev_pm_set_dedicated_wake_irq_reverse(dev, wakeup_irq);
606606
if (ret) {
607607
dev_err(dev, "set wakeup irq %d failed\n", wakeup_irq);
608608
goto dealloc_usb3_hcd;

drivers/usb/mtu3/mtu3_plat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ static int mtu3_probe(struct platform_device *pdev)
337337
goto comm_init_err;
338338

339339
if (ssusb->wakeup_irq > 0) {
340-
ret = dev_pm_set_dedicated_wake_irq(dev, ssusb->wakeup_irq);
340+
ret = dev_pm_set_dedicated_wake_irq_reverse(dev, ssusb->wakeup_irq);
341341
if (ret) {
342342
dev_err(dev, "failed to set wakeup irq %d\n", ssusb->wakeup_irq);
343343
goto comm_exit;

include/linux/pm_wakeirq.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
#ifdef CONFIG_PM
1818

1919
extern int dev_pm_set_wake_irq(struct device *dev, int irq);
20-
extern int dev_pm_set_dedicated_wake_irq(struct device *dev,
21-
int irq);
20+
extern int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq);
21+
extern int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq);
2222
extern void dev_pm_clear_wake_irq(struct device *dev);
2323
extern void dev_pm_enable_wake_irq(struct device *dev);
2424
extern void dev_pm_disable_wake_irq(struct device *dev);
@@ -35,6 +35,11 @@ static inline int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
3535
return 0;
3636
}
3737

38+
static inline int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq)
39+
{
40+
return 0;
41+
}
42+
3843
static inline void dev_pm_clear_wake_irq(struct device *dev)
3944
{
4045
}

kernel/power/hibernate.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ static int create_image(int platform_mode)
300300
if (error || hibernation_test(TEST_PLATFORM))
301301
goto Platform_finish;
302302

303-
error = suspend_disable_secondary_cpus();
303+
error = pm_sleep_disable_secondary_cpus();
304304
if (error || hibernation_test(TEST_CPUS))
305305
goto Enable_cpus;
306306

@@ -342,7 +342,7 @@ static int create_image(int platform_mode)
342342
local_irq_enable();
343343

344344
Enable_cpus:
345-
suspend_enable_secondary_cpus();
345+
pm_sleep_enable_secondary_cpus();
346346

347347
/* Allow architectures to do nosmt-specific post-resume dances */
348348
if (!in_suspend)
@@ -466,6 +466,8 @@ static int resume_target_kernel(bool platform_mode)
466466
if (error)
467467
goto Cleanup;
468468

469+
cpuidle_pause();
470+
469471
error = hibernate_resume_nonboot_cpu_disable();
470472
if (error)
471473
goto Enable_cpus;
@@ -509,7 +511,7 @@ static int resume_target_kernel(bool platform_mode)
509511
local_irq_enable();
510512

511513
Enable_cpus:
512-
suspend_enable_secondary_cpus();
514+
pm_sleep_enable_secondary_cpus();
513515

514516
Cleanup:
515517
platform_restore_cleanup(platform_mode);
@@ -587,7 +589,7 @@ int hibernation_platform_enter(void)
587589
if (error)
588590
goto Platform_finish;
589591

590-
error = suspend_disable_secondary_cpus();
592+
error = pm_sleep_disable_secondary_cpus();
591593
if (error)
592594
goto Enable_cpus;
593595

@@ -609,7 +611,7 @@ int hibernation_platform_enter(void)
609611
local_irq_enable();
610612

611613
Enable_cpus:
612-
suspend_enable_secondary_cpus();
614+
pm_sleep_enable_secondary_cpus();
613615

614616
Platform_finish:
615617
hibernation_ops->finish();

kernel/power/power.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include <linux/utsname.h>
55
#include <linux/freezer.h>
66
#include <linux/compiler.h>
7+
#include <linux/cpu.h>
8+
#include <linux/cpuidle.h>
79

810
struct swsusp_info {
911
struct new_utsname uts;
@@ -310,3 +312,15 @@ extern int pm_wake_lock(const char *buf);
310312
extern int pm_wake_unlock(const char *buf);
311313

312314
#endif /* !CONFIG_PM_WAKELOCKS */
315+
316+
static inline int pm_sleep_disable_secondary_cpus(void)
317+
{
318+
cpuidle_pause();
319+
return suspend_disable_secondary_cpus();
320+
}
321+
322+
static inline void pm_sleep_enable_secondary_cpus(void)
323+
{
324+
suspend_enable_secondary_cpus();
325+
cpuidle_resume();
326+
}

0 commit comments

Comments
 (0)