Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0bc7633e authored by sunil paidimarri's avatar sunil paidimarri Committed by Kyle Yan
Browse files

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: default avatarsunil paidimarri <hisunil@codeaurora.org>
parent ea60e2fb
Loading
Loading
Loading
Loading
+38 −11
Original line number Diff line number Diff line
@@ -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 */
		bmsk = 1;
		for (i = 0; i < IPA_IRQ_NUM_MAX; i++) {
			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), reg);
					IPA_IRQ_CLR_EE_n_ADDR(ipa_ee), bmsk);

			/* Process the interrupts */
		bmsk = 1;
		for (i = 0; i < IPA_IRQ_NUM_MAX; i++) {
			if (en & reg & bmsk)
			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));
	}
+28 −1
Original line number Diff line number Diff line
@@ -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