diff options
Diffstat (limited to 'drivers/base/power/wakeirq.c')
| -rw-r--r-- | drivers/base/power/wakeirq.c | 91 |
1 files changed, 37 insertions, 54 deletions
diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c index d487a6bac630..8aa28c08b289 100644 --- a/drivers/base/power/wakeirq.c +++ b/drivers/base/power/wakeirq.c @@ -103,6 +103,32 @@ void dev_pm_clear_wake_irq(struct device *dev) } EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq); +static void devm_pm_clear_wake_irq(void *dev) +{ + dev_pm_clear_wake_irq(dev); +} + +/** + * devm_pm_set_wake_irq - device-managed variant of dev_pm_set_wake_irq + * @dev: Device entry + * @irq: Device IO interrupt + * + * + * Attach a device IO interrupt as a wake IRQ, same with dev_pm_set_wake_irq, + * but the device will be auto clear wake capability on driver detach. + */ +int devm_pm_set_wake_irq(struct device *dev, int irq) +{ + int ret; + + ret = dev_pm_set_wake_irq(dev, irq); + if (ret) + return ret; + + return devm_add_action_or_reset(dev, devm_pm_clear_wake_irq, dev); +} +EXPORT_SYMBOL_GPL(devm_pm_set_wake_irq); + /** * handle_threaded_wake_irq - Handler for dedicated wake-up interrupts * @irq: Device specific dedicated wake-up interrupt @@ -194,7 +220,6 @@ err_free: return err; } - /** * dev_pm_set_dedicated_wake_irq - Request a dedicated wake-up interrupt * @dev: Device entry @@ -206,11 +231,6 @@ err_free: * Sets up a threaded interrupt handler for a device that has * a dedicated wake-up interrupt in addition to the device IO * interrupt. - * - * The interrupt starts disabled, and needs to be managed for - * the device by the bus code or the device driver using - * dev_pm_enable_wake_irq*() and dev_pm_disable_wake_irq*() - * functions. */ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq) { @@ -232,11 +252,6 @@ EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq); * the status of WAKE_IRQ_DEDICATED_REVERSE to tell rpm_suspend() * to enable dedicated wake-up interrupt after running the runtime suspend * callback for @dev. - * - * The interrupt starts disabled, and needs to be managed for - * the device by the bus code or the device driver using - * dev_pm_enable_wake_irq*() and dev_pm_disable_wake_irq*() - * functions. */ int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq) { @@ -245,44 +260,6 @@ int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq) EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq_reverse); /** - * dev_pm_enable_wake_irq - Enable device wake-up interrupt - * @dev: Device - * - * Optionally called from the bus code or the device driver for - * runtime_resume() to override the PM runtime core managed wake-up - * interrupt handling to enable the wake-up interrupt. - * - * Note that for runtime_suspend()) the wake-up interrupts - * should be unconditionally enabled unlike for suspend() - * that is conditional. - */ -void dev_pm_enable_wake_irq(struct device *dev) -{ - struct wake_irq *wirq = dev->power.wakeirq; - - if (wirq && (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED)) - enable_irq(wirq->irq); -} -EXPORT_SYMBOL_GPL(dev_pm_enable_wake_irq); - -/** - * dev_pm_disable_wake_irq - Disable device wake-up interrupt - * @dev: Device - * - * Optionally called from the bus code or the device driver for - * runtime_suspend() to override the PM runtime core managed wake-up - * interrupt handling to disable the wake-up interrupt. - */ -void dev_pm_disable_wake_irq(struct device *dev) -{ - struct wake_irq *wirq = dev->power.wakeirq; - - if (wirq && (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED)) - disable_irq_nosync(wirq->irq); -} -EXPORT_SYMBOL_GPL(dev_pm_disable_wake_irq); - -/** * dev_pm_enable_wake_irq_check - Checks and enables wake-up interrupt * @dev: Device * @can_change_status: Can change wake-up interrupt status @@ -314,8 +291,10 @@ void dev_pm_enable_wake_irq_check(struct device *dev, return; enable: - if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE)) + if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE)) { enable_irq(wirq->irq); + wirq->status |= WAKE_IRQ_DEDICATED_ENABLED; + } } /** @@ -336,8 +315,10 @@ void dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable) if (cond_disable && (wirq->status & WAKE_IRQ_DEDICATED_REVERSE)) return; - if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED) + if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED) { + wirq->status &= ~WAKE_IRQ_DEDICATED_ENABLED; disable_irq_nosync(wirq->irq); + } } /** @@ -358,8 +339,10 @@ void dev_pm_enable_wake_irq_complete(struct device *dev) return; if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED && - wirq->status & WAKE_IRQ_DEDICATED_REVERSE) + wirq->status & WAKE_IRQ_DEDICATED_REVERSE) { enable_irq(wirq->irq); + wirq->status |= WAKE_IRQ_DEDICATED_ENABLED; + } } /** @@ -376,7 +359,7 @@ void dev_pm_arm_wake_irq(struct wake_irq *wirq) if (device_may_wakeup(wirq->dev)) { if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED && - !pm_runtime_status_suspended(wirq->dev)) + !(wirq->status & WAKE_IRQ_DEDICATED_ENABLED)) enable_irq(wirq->irq); enable_irq_wake(wirq->irq); @@ -399,7 +382,7 @@ void dev_pm_disarm_wake_irq(struct wake_irq *wirq) disable_irq_wake(wirq->irq); if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED && - !pm_runtime_status_suspended(wirq->dev)) + !(wirq->status & WAKE_IRQ_DEDICATED_ENABLED)) disable_irq_nosync(wirq->irq); } } |
