Skip to content

Commit bf18525

Browse files
bebarinoRussell King
authored andcommitted
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: Stephen Boyd <[email protected]> Reviewed-by: Kevin Hilman <[email protected]> Cc: Frederic Weisbecker <[email protected]> Signed-off-by: Russell King <[email protected]>
1 parent 8d45144 commit bf18525

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

arch/arm/include/asm/hardirq.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include <linux/threads.h>
66
#include <asm/irq.h>
77

8-
#define NR_IPI 6
8+
#define NR_IPI 7
99

1010
typedef struct {
1111
unsigned int __softirq_pending;

arch/arm/kernel/smp.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/clockchips.h>
2626
#include <linux/completion.h>
2727
#include <linux/cpufreq.h>
28+
#include <linux/irq_work.h>
2829

2930
#include <linux/atomic.h>
3031
#include <asm/smp.h>
@@ -66,6 +67,7 @@ enum ipi_msg_type {
6667
IPI_CALL_FUNC,
6768
IPI_CALL_FUNC_SINGLE,
6869
IPI_CPU_STOP,
70+
IPI_IRQ_WORK,
6971
};
7072

7173
static DECLARE_COMPLETION(cpu_running);
@@ -448,6 +450,13 @@ void arch_send_call_function_single_ipi(int cpu)
448450
smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
449451
}
450452

453+
#ifdef CONFIG_IRQ_WORK
454+
void arch_irq_work_raise(void)
455+
{
456+
smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK);
457+
}
458+
#endif
459+
451460
static const char *ipi_types[NR_IPI] = {
452461
#define S(x,s) [x] = s
453462
S(IPI_WAKEUP, "CPU wakeup interrupts"),
@@ -456,6 +465,7 @@ static const char *ipi_types[NR_IPI] = {
456465
S(IPI_CALL_FUNC, "Function call interrupts"),
457466
S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"),
458467
S(IPI_CPU_STOP, "CPU stop interrupts"),
468+
S(IPI_IRQ_WORK, "IRQ work interrupts"),
459469
};
460470

461471
void show_ipi_list(struct seq_file *p, int prec)
@@ -565,6 +575,14 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
565575
irq_exit();
566576
break;
567577

578+
#ifdef CONFIG_IRQ_WORK
579+
case IPI_IRQ_WORK:
580+
irq_enter();
581+
irq_work_run();
582+
irq_exit();
583+
break;
584+
#endif
585+
568586
default:
569587
printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
570588
cpu, ipinr);

0 commit comments

Comments
 (0)