Skip to content

Commit 8527beb

Browse files
jhovoldrafaeljw
authored andcommitted
PM: sleep: wakeirq: fix wake irq arming
The decision whether to enable a wake irq during suspend can not be done based on the runtime PM state directly as a driver may use wake irqs without implementing runtime PM. Such drivers specifically leave the state set to the default 'suspended' and the wake irq is thus never enabled at suspend. Add a new wake irq flag to track whether a dedicated wake irq has been enabled at runtime suspend and therefore must not be enabled at system suspend. Note that pm_runtime_enabled() can not be used as runtime PM is always disabled during late suspend. Fixes: 6972805 ("PM / wakeirq: Fix unbalanced IRQ enable for wakeirq") Cc: 4.16+ <stable@vger.kernel.org> # 4.16+ Signed-off-by: Johan Hovold <johan+linaro@kernel.org> Reviewed-by: Tony Lindgren <tony@atomide.com> Tested-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 6eaae19 commit 8527beb

File tree

2 files changed

+9
-4
lines changed

2 files changed

+9
-4
lines changed

drivers/base/power/power.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ extern u64 pm_runtime_active_time(struct device *dev);
2929
#define WAKE_IRQ_DEDICATED_MASK (WAKE_IRQ_DEDICATED_ALLOCATED | \
3030
WAKE_IRQ_DEDICATED_MANAGED | \
3131
WAKE_IRQ_DEDICATED_REVERSE)
32+
#define WAKE_IRQ_DEDICATED_ENABLED BIT(3)
3233

3334
struct wake_irq {
3435
struct device *dev;

drivers/base/power/wakeirq.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,10 @@ void dev_pm_enable_wake_irq_check(struct device *dev,
314314
return;
315315

316316
enable:
317-
if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE))
317+
if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE)) {
318318
enable_irq(wirq->irq);
319+
wirq->status |= WAKE_IRQ_DEDICATED_ENABLED;
320+
}
319321
}
320322

321323
/**
@@ -336,8 +338,10 @@ void dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable)
336338
if (cond_disable && (wirq->status & WAKE_IRQ_DEDICATED_REVERSE))
337339
return;
338340

339-
if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED)
341+
if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED) {
342+
wirq->status &= ~WAKE_IRQ_DEDICATED_ENABLED;
340343
disable_irq_nosync(wirq->irq);
344+
}
341345
}
342346

343347
/**
@@ -376,7 +380,7 @@ void dev_pm_arm_wake_irq(struct wake_irq *wirq)
376380

377381
if (device_may_wakeup(wirq->dev)) {
378382
if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED &&
379-
!pm_runtime_status_suspended(wirq->dev))
383+
!(wirq->status & WAKE_IRQ_DEDICATED_ENABLED))
380384
enable_irq(wirq->irq);
381385

382386
enable_irq_wake(wirq->irq);
@@ -399,7 +403,7 @@ void dev_pm_disarm_wake_irq(struct wake_irq *wirq)
399403
disable_irq_wake(wirq->irq);
400404

401405
if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED &&
402-
!pm_runtime_status_suspended(wirq->dev))
406+
!(wirq->status & WAKE_IRQ_DEDICATED_ENABLED))
403407
disable_irq_nosync(wirq->irq);
404408
}
405409
}

0 commit comments

Comments
 (0)