summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsunil paidimarri <hisunil@codeaurora.org>2016-05-17 17:06:12 -0700
committerKyle Yan <kyan@codeaurora.org>2016-06-15 16:16:49 -0700
commit0bc7633e036cbdaf2228fab00a12033daf7513e6 (patch)
tree226bee21397308d2648b3e4f0ef48d7c6328e5bf
parentea60e2fbe4a8361877e3b381b2728a9dbd981f65 (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.c49
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c29
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