diff options
| author | sunil paidimarri <hisunil@codeaurora.org> | 2016-05-17 17:06:12 -0700 |
|---|---|---|
| committer | Kyle Yan <kyan@codeaurora.org> | 2016-06-15 16:16:49 -0700 |
| commit | 0bc7633e036cbdaf2228fab00a12033daf7513e6 (patch) | |
| tree | 226bee21397308d2648b3e4f0ef48d7c6328e5bf | |
| parent | ea60e2fbe4a8361877e3b381b2728a9dbd981f65 (diff) | |
msm: ipa: clear uC interrupt only before processing
Clearing Non uC interrupts before processing will
result in clearing interrupt data.
Change-Id: I47ea7c22250264da206e1fb8691e77224c825ab0
CRs-Fixed: 1008549
Signed-off-by: sunil paidimarri <hisunil@codeaurora.org>
| -rw-r--r-- | drivers/platform/msm/ipa/ipa_v2/ipa_interrupts.c | 49 | ||||
| -rw-r--r-- | drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c | 29 |
2 files changed, 66 insertions, 12 deletions
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_interrupts.c b/drivers/platform/msm/ipa/ipa_v2/ipa_interrupts.c index f30fd4c60171..17f577ab6c4c 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_interrupts.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_interrupts.c @@ -151,31 +151,58 @@ fail_alloc_work: return res; } +static inline bool is_uc_irq(int irq_num) +{ + if (ipa_interrupt_to_cb[irq_num].interrupt >= IPA_UC_IRQ_0 && + ipa_interrupt_to_cb[irq_num].interrupt <= IPA_UC_IRQ_3) + return true; + else + return false; +} + static void ipa_process_interrupts(bool isr_context) { u32 reg; u32 bmsk; u32 i = 0; u32 en; + bool uc_irq; en = ipa_read_reg(ipa_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee)); reg = ipa_read_reg(ipa_ctx->mmio, IPA_IRQ_STTS_EE_n_ADDR(ipa_ee)); while (en & reg) { - /* Clear interrupt before processing to avoid - clearing unhandled interrupts */ - ipa_write_reg(ipa_ctx->mmio, - IPA_IRQ_CLR_EE_n_ADDR(ipa_ee), reg); - - /* Process the interrupts */ bmsk = 1; for (i = 0; i < IPA_IRQ_NUM_MAX; i++) { - if (en & reg & bmsk) - handle_interrupt(i, isr_context); + if (!(en & reg & bmsk)) { + bmsk = bmsk << 1; + continue; + } + uc_irq = is_uc_irq(i); + /* + * Clear uC interrupt before processing to avoid + * clearing unhandled interrupts + */ + if (uc_irq) + ipa_write_reg(ipa_ctx->mmio, + IPA_IRQ_CLR_EE_n_ADDR(ipa_ee), bmsk); + + /* Process the interrupts */ + handle_interrupt(i, isr_context); + + /* + * Clear non uC interrupt after processing + * to avoid clearing interrupt data + */ + if (!uc_irq) + ipa_write_reg(ipa_ctx->mmio, + IPA_IRQ_CLR_EE_n_ADDR(ipa_ee), bmsk); + bmsk = bmsk << 1; } - - /* Check pending interrupts that may have - been raised since last read */ + /* + * Check pending interrupts that may have + * been raised since last read + */ reg = ipa_read_reg(ipa_ctx->mmio, IPA_IRQ_STTS_EE_n_ADDR(ipa_ee)); } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c b/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c index 45d3b13049bc..f0102a703812 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c @@ -235,6 +235,15 @@ static void ipa3_tx_suspend_interrupt_wa(void) IPADBG_LOW("Exit\n"); } +static inline bool is_uc_irq(int irq_num) +{ + if (ipa_interrupt_to_cb[irq_num].interrupt >= IPA_UC_IRQ_0 && + ipa_interrupt_to_cb[irq_num].interrupt <= IPA_UC_IRQ_3) + return true; + else + return false; +} + static void ipa3_process_interrupts(bool isr_context) { u32 reg; @@ -242,6 +251,7 @@ static void ipa3_process_interrupts(bool isr_context) u32 i = 0; u32 en; unsigned long flags; + bool uc_irq; IPADBG_LOW("Enter\n"); @@ -252,6 +262,16 @@ static void ipa3_process_interrupts(bool isr_context) bmsk = 1; for (i = 0; i < IPA_IRQ_NUM_MAX; i++) { if (en & reg & bmsk) { + uc_irq = is_uc_irq(i); + + /* + * Clear uC interrupt before processing to avoid + * clearing unhandled interrupts + */ + if (uc_irq) + ipa3_uc_rg10_write_reg(IPA_IRQ_CLR_EE_n, + ipa_ee, bmsk); + /* * handle the interrupt with spin_lock * unlocked to avoid calling client in atomic @@ -262,6 +282,14 @@ static void ipa3_process_interrupts(bool isr_context) spin_unlock_irqrestore(&suspend_wa_lock, flags); ipa3_handle_interrupt(i, isr_context); spin_lock_irqsave(&suspend_wa_lock, flags); + + /* + * Clear non uC interrupt after processing + * to avoid clearing interrupt data + */ + if (!uc_irq) + ipa3_uc_rg10_write_reg(IPA_IRQ_CLR_EE_n, + ipa_ee, bmsk); } bmsk = bmsk << 1; } @@ -272,7 +300,6 @@ static void ipa3_process_interrupts(bool isr_context) if (ipa3_ctx->apply_rg10_wa && ipa3_ctx->uc_ctx.uc_failed) break; - ipa3_uc_rg10_write_reg(IPA_IRQ_CLR_EE_n, ipa_ee, reg); reg = ipahal_read_reg_n(IPA_IRQ_STTS_EE_n, ipa_ee); /* since the suspend interrupt HW bug we must * read again the EN register, otherwise the while is endless |
