Skip to content

Commit

Permalink
ARM: 7872/1: Support arch_irq_work_raise() via self IPIs
Browse files Browse the repository at this point in the history
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: Stephen Boyd <[email protected]>
Reviewed-by: Kevin Hilman <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Signed-off-by: Russell King <[email protected]>
  • Loading branch information
bebarino authored and Russell King committed Nov 7, 2013
1 parent 8d45144 commit bf18525
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 1 deletion.
2 changes: 1 addition & 1 deletion arch/arm/include/asm/hardirq.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <linux/threads.h>
#include <asm/irq.h>

#define NR_IPI 6
#define NR_IPI 7

typedef struct {
unsigned int __softirq_pending;
Expand Down
18 changes: 18 additions & 0 deletions arch/arm/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/clockchips.h>
#include <linux/completion.h>
#include <linux/cpufreq.h>
#include <linux/irq_work.h>

#include <linux/atomic.h>
#include <asm/smp.h>
Expand Down Expand Up @@ -66,6 +67,7 @@ enum ipi_msg_type {
IPI_CALL_FUNC,
IPI_CALL_FUNC_SINGLE,
IPI_CPU_STOP,
IPI_IRQ_WORK,
};

static DECLARE_COMPLETION(cpu_running);
Expand Down Expand Up @@ -448,6 +450,13 @@ void arch_send_call_function_single_ipi(int cpu)
smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
}

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

static const char *ipi_types[NR_IPI] = {
#define S(x,s) [x] = s
S(IPI_WAKEUP, "CPU wakeup interrupts"),
Expand All @@ -456,6 +465,7 @@ static const char *ipi_types[NR_IPI] = {
S(IPI_CALL_FUNC, "Function call interrupts"),
S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"),
S(IPI_CPU_STOP, "CPU stop interrupts"),
S(IPI_IRQ_WORK, "IRQ work interrupts"),
};

void show_ipi_list(struct seq_file *p, int prec)
Expand Down Expand Up @@ -565,6 +575,14 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
irq_exit();
break;

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

default:
printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
cpu, ipinr);
Expand Down

0 comments on commit bf18525

Please sign in to comment.