]>
Commit | Line | Data |
---|---|---|
67bda23a GKH |
1 | From 8527beb12087238d4387607597b4020bc393c4b4 Mon Sep 17 00:00:00 2001 |
2 | From: Johan Hovold <johan+linaro@kernel.org> | |
3 | Date: Thu, 13 Jul 2023 16:57:39 +0200 | |
4 | Subject: PM: sleep: wakeirq: fix wake irq arming | |
5 | ||
6 | From: Johan Hovold <johan+linaro@kernel.org> | |
7 | ||
8 | commit 8527beb12087238d4387607597b4020bc393c4b4 upstream. | |
9 | ||
10 | The decision whether to enable a wake irq during suspend can not be done | |
11 | based on the runtime PM state directly as a driver may use wake irqs | |
12 | without implementing runtime PM. Such drivers specifically leave the | |
13 | state set to the default 'suspended' and the wake irq is thus never | |
14 | enabled at suspend. | |
15 | ||
16 | Add a new wake irq flag to track whether a dedicated wake irq has been | |
17 | enabled at runtime suspend and therefore must not be enabled at system | |
18 | suspend. | |
19 | ||
20 | Note that pm_runtime_enabled() can not be used as runtime PM is always | |
21 | disabled during late suspend. | |
22 | ||
23 | Fixes: 69728051f5bf ("PM / wakeirq: Fix unbalanced IRQ enable for wakeirq") | |
24 | Cc: 4.16+ <stable@vger.kernel.org> # 4.16+ | |
25 | Signed-off-by: Johan Hovold <johan+linaro@kernel.org> | |
26 | Reviewed-by: Tony Lindgren <tony@atomide.com> | |
27 | Tested-by: Tony Lindgren <tony@atomide.com> | |
28 | Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> | |
29 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
30 | --- | |
31 | drivers/base/power/power.h | 1 + | |
32 | drivers/base/power/wakeirq.c | 12 ++++++++---- | |
33 | 2 files changed, 9 insertions(+), 4 deletions(-) | |
34 | ||
35 | --- a/drivers/base/power/power.h | |
36 | +++ b/drivers/base/power/power.h | |
37 | @@ -29,6 +29,7 @@ extern u64 pm_runtime_active_time(struct | |
38 | #define WAKE_IRQ_DEDICATED_MASK (WAKE_IRQ_DEDICATED_ALLOCATED | \ | |
39 | WAKE_IRQ_DEDICATED_MANAGED | \ | |
40 | WAKE_IRQ_DEDICATED_REVERSE) | |
41 | +#define WAKE_IRQ_DEDICATED_ENABLED BIT(3) | |
42 | ||
43 | struct wake_irq { | |
44 | struct device *dev; | |
45 | --- a/drivers/base/power/wakeirq.c | |
46 | +++ b/drivers/base/power/wakeirq.c | |
47 | @@ -314,8 +314,10 @@ void dev_pm_enable_wake_irq_check(struct | |
48 | return; | |
49 | ||
50 | enable: | |
51 | - if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE)) | |
52 | + if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE)) { | |
53 | enable_irq(wirq->irq); | |
54 | + wirq->status |= WAKE_IRQ_DEDICATED_ENABLED; | |
55 | + } | |
56 | } | |
57 | ||
58 | /** | |
59 | @@ -336,8 +338,10 @@ void dev_pm_disable_wake_irq_check(struc | |
60 | if (cond_disable && (wirq->status & WAKE_IRQ_DEDICATED_REVERSE)) | |
61 | return; | |
62 | ||
63 | - if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED) | |
64 | + if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED) { | |
65 | + wirq->status &= ~WAKE_IRQ_DEDICATED_ENABLED; | |
66 | disable_irq_nosync(wirq->irq); | |
67 | + } | |
68 | } | |
69 | ||
70 | /** | |
71 | @@ -376,7 +380,7 @@ void dev_pm_arm_wake_irq(struct wake_irq | |
72 | ||
73 | if (device_may_wakeup(wirq->dev)) { | |
74 | if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED && | |
75 | - !pm_runtime_status_suspended(wirq->dev)) | |
76 | + !(wirq->status & WAKE_IRQ_DEDICATED_ENABLED)) | |
77 | enable_irq(wirq->irq); | |
78 | ||
79 | enable_irq_wake(wirq->irq); | |
80 | @@ -399,7 +403,7 @@ void dev_pm_disarm_wake_irq(struct wake_ | |
81 | disable_irq_wake(wirq->irq); | |
82 | ||
83 | if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED && | |
84 | - !pm_runtime_status_suspended(wirq->dev)) | |
85 | + !(wirq->status & WAKE_IRQ_DEDICATED_ENABLED)) | |
86 | disable_irq_nosync(wirq->irq); | |
87 | } | |
88 | } |