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

Commit eb631bb5 authored by Larry Bassel's avatar Larry Bassel Committed by Catalin Marinas
Browse files

arm64: Support arch_irq_work_raise() via self IPIs



Support for arch_irq_work_raise() was missing from
arm64 (a prerequisite for FULL_NOHZ).

This patch is based on the arm32 patch ARM 7872/1.

commit bf18525f
Author: Stephen Boyd <sboyd@codeaurora.org>
Date:   Tue Oct 29 20:32:56 2013 +0100

    ARM: 7872/1: Support arch_irq_work_raise() via self IPIs

    By default, IRQ work is run from the tick interrupt (see
    irq_work_run() in update_process_times()). When we're in full
    NOHZ mode, restarting the tick requires the use of IRQ work and
    if the only place we run IRQ work is in the tick interrupt we
    have an unbreakable cycle. Implement arch_irq_work_raise() via
    self IPIs to break this cycle and get the tick started again.
    Note that we implement this via IPIs which are only available on
    SMP builds. This shouldn't be a problem because full NOHZ is only
    supported on SMP builds anyway.

    Signed-off-by: default avatarStephen Boyd <sboyd@codeaurora.org>
    Reviewed-by: default avatarKevin Hilman <khilman@linaro.org>
    Cc: Frederic Weisbecker <fweisbec@gmail.com>
    Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>

Signed-off-by: default avatarLarry Bassel <larry.bassel@linaro.org>
Reviewed-by: default avatarKevin Hilman <khilman@linaro.org>
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent ebdc9447
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -20,7 +20,7 @@
#include <linux/threads.h>
#include <linux/threads.h>
#include <asm/irq.h>
#include <asm/irq.h>


#define NR_IPI	5
#define NR_IPI	6


typedef struct {
typedef struct {
	unsigned int __softirq_pending;
	unsigned int __softirq_pending;
+19 −0
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@
#include <linux/clockchips.h>
#include <linux/clockchips.h>
#include <linux/completion.h>
#include <linux/completion.h>
#include <linux/of.h>
#include <linux/of.h>
#include <linux/irq_work.h>


#include <asm/atomic.h>
#include <asm/atomic.h>
#include <asm/cacheflush.h>
#include <asm/cacheflush.h>
@@ -62,6 +63,7 @@ enum ipi_msg_type {
	IPI_CALL_FUNC_SINGLE,
	IPI_CALL_FUNC_SINGLE,
	IPI_CPU_STOP,
	IPI_CPU_STOP,
	IPI_TIMER,
	IPI_TIMER,
	IPI_IRQ_WORK,
};
};


/*
/*
@@ -455,6 +457,14 @@ void arch_send_call_function_single_ipi(int cpu)
	smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
	smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
}
}


#ifdef CONFIG_IRQ_WORK
void arch_irq_work_raise(void)
{
	if (smp_cross_call)
		smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK);
}
#endif

static const char *ipi_types[NR_IPI] = {
static const char *ipi_types[NR_IPI] = {
#define S(x,s)	[x - IPI_RESCHEDULE] = s
#define S(x,s)	[x - IPI_RESCHEDULE] = s
	S(IPI_RESCHEDULE, "Rescheduling interrupts"),
	S(IPI_RESCHEDULE, "Rescheduling interrupts"),
@@ -462,6 +472,7 @@ static const char *ipi_types[NR_IPI] = {
	S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"),
	S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"),
	S(IPI_CPU_STOP, "CPU stop interrupts"),
	S(IPI_CPU_STOP, "CPU stop interrupts"),
	S(IPI_TIMER, "Timer broadcast interrupts"),
	S(IPI_TIMER, "Timer broadcast interrupts"),
	S(IPI_IRQ_WORK, "IRQ work interrupts"),
};
};


void show_ipi_list(struct seq_file *p, int prec)
void show_ipi_list(struct seq_file *p, int prec)
@@ -554,6 +565,14 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
		break;
		break;
#endif
#endif


#ifdef CONFIG_IRQ_WORK
	case IPI_IRQ_WORK:
		irq_enter();
		irq_work_run();
		irq_exit();
		break;
#endif

	default:
	default:
		pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr);
		pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr);
		break;
		break;