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

Commit aa6083ed authored by Vineet Gupta's avatar Vineet Gupta
Browse files

ARCv2: SMP: ARConnect debug/robustness



- Handle possible interrupt coalescing from MCIP
- chk if prev IPI ack before sending new

Signed-off-by: default avatarVineet Gupta <vgupta@synopsys.com>
parent 82fea5a1
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -448,9 +448,10 @@ menuconfig ARC_DBG
	bool "ARC debugging"
	default y

if ARC_DBG

config ARC_DW2_UNWIND
	bool "Enable DWARF specific kernel stack unwind"
	depends on ARC_DBG
	default y
	select KALLSYMS
	help
@@ -464,18 +465,26 @@ config ARC_DW2_UNWIND

config ARC_DBG_TLB_PARANOIA
	bool "Paranoia Checks in Low Level TLB Handlers"
	depends on ARC_DBG
	default n

config ARC_DBG_TLB_MISS_COUNT
	bool "Profile TLB Misses"
	default n
	select DEBUG_FS
	depends on ARC_DBG
	help
	  Counts number of I and D TLB Misses and exports them via Debugfs
	  The counters can be cleared via Debugfs as well

if SMP

config ARC_IPI_DBG
	bool "Debug Inter Core interrupts"
	default n

endif

endif

config ARC_UBOOT_SUPPORT
	bool "Support uboot arg Handling"
	default n
+44 −4
Original line number Diff line number Diff line
@@ -33,27 +33,67 @@ void mcip_init_smp(unsigned int cpu)
static void mcip_ipi_send(int cpu)
{
	unsigned long flags;
	int ipi_was_pending;

	/*
	 * NOTE: We must spin here if the other cpu hasn't yet
	 * serviced a previous message. This can burn lots
	 * of time, but we MUST follows this protocol or
	 * ipi messages can be lost!!!
	 * Also, we must release the lock in this loop because
	 * the other side may get to this same loop and not
	 * be able to ack -- thus causing deadlock.
	 */

	do {
		raw_spin_lock_irqsave(&mcip_lock, flags);
		__mcip_cmd(CMD_INTRPT_READ_STATUS, cpu);
		ipi_was_pending = read_aux_reg(ARC_REG_MCIP_READBACK);
		if (ipi_was_pending == 0)
			break; /* break out but keep lock */
		raw_spin_unlock_irqrestore(&mcip_lock, flags);
	} while (1);

	__mcip_cmd(CMD_INTRPT_GENERATE_IRQ, cpu);
	raw_spin_unlock_irqrestore(&mcip_lock, flags);

#ifdef CONFIG_ARC_IPI_DBG
	if (ipi_was_pending)
		pr_info("IPI ACK delayed from cpu %d\n", cpu);
#endif
}

static void mcip_ipi_clear(int irq)
{
	unsigned int cpu;
	unsigned int cpu, c;
	unsigned long flags;
	unsigned int __maybe_unused copy;

	raw_spin_lock_irqsave(&mcip_lock, flags);

	/* Who sent the IPI */
	__mcip_cmd(CMD_INTRPT_CHECK_SOURCE, 0);

	cpu = read_aux_reg(ARC_REG_MCIP_READBACK);	/* 1,2,4,8... */
	copy = cpu = read_aux_reg(ARC_REG_MCIP_READBACK);	/* 1,2,4,8... */

	__mcip_cmd(CMD_INTRPT_GENERATE_ACK, __ffs(cpu)); /* 0,1,2,3... */
	/*
	 * In rare case, multiple concurrent IPIs sent to same target can
	 * possibly be coalesced by MCIP into 1 asserted IRQ, so @cpus can be
	 * "vectored" (multiple bits sets) as opposed to typical single bit
	 */
	do {
		c = __ffs(cpu);			/* 0,1,2,3 */
		__mcip_cmd(CMD_INTRPT_GENERATE_ACK, c);
		cpu &= ~(1U << c);
	} while (cpu);

	raw_spin_unlock_irqrestore(&mcip_lock, flags);

#ifdef CONFIG_ARC_IPI_DBG
	if (c != __ffs(copy))
		pr_info("IPIs from %x coalesced to %x\n",
			copy, raw_smp_processor_id());
#endif
}

volatile int wake_flag;
+16 −4
Original line number Diff line number Diff line
@@ -278,8 +278,10 @@ static void ipi_cpu_stop(void)
	machine_halt();
}

static inline void __do_IPI(unsigned long msg)
static inline int __do_IPI(unsigned long msg)
{
	int rc = 0;

	switch (msg) {
	case IPI_RESCHEDULE:
		scheduler_ipi();
@@ -294,8 +296,10 @@ static inline void __do_IPI(unsigned long msg)
		break;

	default:
		pr_warn("IPI with unexpected msg %ld\n", msg);
		rc = 1;
	}

	return rc;
}

/*
@@ -305,6 +309,7 @@ static inline void __do_IPI(unsigned long msg)
irqreturn_t do_IPI(int irq, void *dev_id)
{
	unsigned long pending;
	unsigned long __maybe_unused copy;

	pr_debug("IPI [%ld] received on cpu %d\n",
		 *this_cpu_ptr(&ipi_data), smp_processor_id());
@@ -316,11 +321,18 @@ irqreturn_t do_IPI(int irq, void *dev_id)
	 * "dequeue" the msg corresponding to this IPI (and possibly other
	 * piggybacked msg from elided IPIs: see ipi_send_msg_one() above)
	 */
	pending = xchg(this_cpu_ptr(&ipi_data), 0);
	copy = pending = xchg(this_cpu_ptr(&ipi_data), 0);

	do {
		unsigned long msg = __ffs(pending);
		__do_IPI(msg);
		int rc;

		rc = __do_IPI(msg);
#ifdef CONFIG_ARC_IPI_DBG
		/* IPI received but no valid @msg */
		if (rc)
			pr_info("IPI with bogus msg %ld in %ld\n", msg, copy);
#endif
		pending &= ~(1U << msg);
	} while (pending);