diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index c90e6b491b..8dcf1f6524 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -1883,10 +1883,21 @@ static irqreturn_t swrm_wakeup_interrupt(int irq, void *dev) pr_err("%s: swrm or dev is null\n", __func__); return IRQ_NONE; } + mutex_lock(&swrm->devlock); if (!swrm->dev_up) { - if (swrm->wake_irq > 0) - disable_irq_nosync(swrm->wake_irq); + if (swrm->wake_irq > 0) { + if (unlikely(!irq_get_irq_data(swrm->wake_irq))) { + pr_err("%s: irq data is NULL\n", __func__); + mutex_unlock(&swrm->devlock); + return IRQ_NONE; + } + mutex_lock(&swrm->irq_lock); + if (!irqd_irq_disabled( + irq_get_irq_data(swrm->wake_irq))) + disable_irq_nosync(swrm->wake_irq); + mutex_unlock(&swrm->irq_lock); + } mutex_unlock(&swrm->devlock); return ret; } @@ -1895,8 +1906,17 @@ static irqreturn_t swrm_wakeup_interrupt(int irq, void *dev) dev_err(swrm->dev, "%s Failed to hold suspend\n", __func__); goto exit; } - if (swrm->wake_irq > 0) - disable_irq_nosync(swrm->wake_irq); + if (swrm->wake_irq > 0) { + if (unlikely(!irq_get_irq_data(swrm->wake_irq))) { + pr_err("%s: irq data is NULL\n", __func__); + return IRQ_NONE; + } + mutex_lock(&swrm->irq_lock); + if (!irqd_irq_disabled( + irq_get_irq_data(swrm->wake_irq))) + disable_irq_nosync(swrm->wake_irq); + mutex_unlock(&swrm->irq_lock); + } pm_runtime_get_sync(swrm->dev); pm_runtime_mark_last_busy(swrm->dev); pm_runtime_put_autosuspend(swrm->dev); @@ -2376,6 +2396,7 @@ static int swrm_probe(struct platform_device *pdev) init_completion(&swrm->reset); init_completion(&swrm->broadcast); init_completion(&swrm->clk_off_complete); + mutex_init(&swrm->irq_lock); mutex_init(&swrm->mlock); mutex_init(&swrm->reslock); mutex_init(&swrm->force_down_lock); @@ -2522,6 +2543,7 @@ err_mstr_fail: else if (swrm->irq) free_irq(swrm->irq, swrm); err_irq_fail: + mutex_destroy(&swrm->irq_lock); mutex_destroy(&swrm->mlock); mutex_destroy(&swrm->reslock); mutex_destroy(&swrm->force_down_lock); @@ -2554,6 +2576,7 @@ static int swrm_remove(struct platform_device *pdev) swr_unregister_master(&swrm->master); msm_aud_evt_unregister_client(&swrm->event_notifier); device_init_wakeup(swrm->dev, false); + mutex_destroy(&swrm->irq_lock); mutex_destroy(&swrm->mlock); mutex_destroy(&swrm->reslock); mutex_destroy(&swrm->iolock); @@ -2608,6 +2631,20 @@ static int swrm_runtime_resume(struct device *dev) if ((swrm->state == SWR_MSTR_DOWN) || (swrm->state == SWR_MSTR_SSR && swrm->dev_up)) { if (swrm->clk_stop_mode0_supp) { + if (swrm->wake_irq > 0) { + if (unlikely(!irq_get_irq_data + (swrm->wake_irq))) { + pr_err("%s: irq data is NULL\n", + __func__); + mutex_unlock(&swrm->reslock); + return IRQ_NONE; + } + mutex_lock(&swrm->irq_lock); + if (!irqd_irq_disabled( + irq_get_irq_data(swrm->wake_irq))) + disable_irq_nosync(swrm->wake_irq); + mutex_unlock(&swrm->irq_lock); + } if (swrm->ipc_wakeup) msm_aud_evt_blocking_notifier_call_chain( SWR_WAKE_IRQ_DEREGISTER, (void *)swrm); diff --git a/soc/swr-mstr-ctrl.h b/soc/swr-mstr-ctrl.h index b07a80db61..654dd0e703 100644 --- a/soc/swr-mstr-ctrl.h +++ b/soc/swr-mstr-ctrl.h @@ -124,6 +124,7 @@ struct swr_mstr_ctrl { struct mutex mlock; struct mutex reslock; struct mutex pm_lock; + struct mutex irq_lock; u32 swrm_base_reg; char __iomem *swrm_dig_base; char __iomem *swrm_hctl_reg;