diff options
Diffstat (limited to 'drivers/net/ipa')
-rw-r--r-- | drivers/net/ipa/ipa_interrupt.c | 10 | ||||
-rw-r--r-- | drivers/net/ipa/ipa_interrupt.h | 16 | ||||
-rw-r--r-- | drivers/net/ipa/ipa_power.c | 17 |
3 files changed, 43 insertions, 0 deletions
diff --git a/drivers/net/ipa/ipa_interrupt.c b/drivers/net/ipa/ipa_interrupt.c index fd982cec8068..c19cd27ac852 100644 --- a/drivers/net/ipa/ipa_interrupt.c +++ b/drivers/net/ipa/ipa_interrupt.c @@ -152,6 +152,16 @@ void ipa_interrupt_disable(struct ipa *ipa, enum ipa_irq_id ipa_irq) ipa_interrupt_enabled_update(ipa); } +void ipa_interrupt_irq_disable(struct ipa *ipa) +{ + disable_irq(ipa->interrupt->irq); +} + +void ipa_interrupt_irq_enable(struct ipa *ipa) +{ + enable_irq(ipa->interrupt->irq); +} + /* Common function used to enable/disable TX_SUSPEND for an endpoint */ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt, u32 endpoint_id, bool enable) diff --git a/drivers/net/ipa/ipa_interrupt.h b/drivers/net/ipa/ipa_interrupt.h index 764a65e6b503..12e3e798ccb3 100644 --- a/drivers/net/ipa/ipa_interrupt.h +++ b/drivers/net/ipa/ipa_interrupt.h @@ -68,6 +68,22 @@ void ipa_interrupt_enable(struct ipa *ipa, enum ipa_irq_id ipa_irq); void ipa_interrupt_disable(struct ipa *ipa, enum ipa_irq_id ipa_irq); /** + * ipa_interrupt_irq_enable() - Enable IPA interrupts + * @ipa: IPA pointer + * + * This enables the IPA interrupt line + */ +void ipa_interrupt_irq_enable(struct ipa *ipa); + +/** + * ipa_interrupt_irq_disable() - Disable IPA interrupts + * @ipa: IPA pointer + * + * This disables the IPA interrupt line + */ +void ipa_interrupt_irq_disable(struct ipa *ipa); + +/** * ipa_interrupt_config() - Configure the IPA interrupt framework * @ipa: IPA pointer * diff --git a/drivers/net/ipa/ipa_power.c b/drivers/net/ipa/ipa_power.c index a282512ebd2d..921eecf3eff6 100644 --- a/drivers/net/ipa/ipa_power.c +++ b/drivers/net/ipa/ipa_power.c @@ -181,6 +181,17 @@ static int ipa_suspend(struct device *dev) __set_bit(IPA_POWER_FLAG_SYSTEM, ipa->power->flags); + /* Increment the disable depth to ensure that the IRQ won't + * be re-enabled until the matching _enable call in + * ipa_resume(). We do this to ensure that the interrupt + * handler won't run whilst PM runtime is disabled. + * + * Note that disabling the IRQ is NOT the same as disabling + * irq wake. If wakeup is enabled for the IPA then the IRQ + * will still cause the system to wake up, see irq_set_irq_wake(). + */ + ipa_interrupt_irq_disable(ipa); + return pm_runtime_force_suspend(dev); } @@ -193,6 +204,12 @@ static int ipa_resume(struct device *dev) __clear_bit(IPA_POWER_FLAG_SYSTEM, ipa->power->flags); + /* Now that PM runtime is enabled again it's safe + * to turn the IRQ back on and process any data + * that was received during suspend. + */ + ipa_interrupt_irq_enable(ipa); + return ret; } |