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 Acked-by: Mohammed Javid <mjavid@qti.qualcomm.com> Signed-off-by: sunil paidimarri <hisunil@codeaurora.org>
This commit is contained in:
parent
f290807c52
commit
a78f95743c
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -16,6 +16,7 @@
|
|||
|
||||
struct ipa_interrupt_info {
|
||||
ipa_irq_handler_t handler;
|
||||
enum ipa_irq_type interrupt;
|
||||
void *private_data;
|
||||
bool deferred_flag;
|
||||
};
|
||||
|
@ -126,37 +127,52 @@ 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_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));
|
||||
}
|
||||
|
@ -221,6 +237,7 @@ int ipa_add_interrupt_handler(enum ipa_irq_type interrupt,
|
|||
ipa_interrupt_to_cb[interrupt].deferred_flag = deferred_flag;
|
||||
ipa_interrupt_to_cb[interrupt].handler = handler;
|
||||
ipa_interrupt_to_cb[interrupt].private_data = private_data;
|
||||
ipa_interrupt_to_cb[interrupt].interrupt = interrupt;
|
||||
|
||||
val = ipa_read_reg(ipa_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee));
|
||||
IPADBG("read IPA_IRQ_EN_EE_n_ADDR register. reg = %d\n", val);
|
||||
|
|
Loading…
Reference in New Issue