Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clocksource: exynos_mct: Set IRQ affinity when the CPU goes online

Some variants of Exynos MCT, namely exynos4210-mct at the moment, use
normal, shared interrupts for local timers. This means that each
interrupt must have correct affinity set to fire only on CPU
corresponding to given local timer.

However after recent conversion of clocksource drivers to not use the
local timer API for local timer initialization any more, the point of
time when local timers get initialized changed and irq_set_affinity()
fails because the CPU is not marked as online yet.

This patch fixes this by moving the call to irq_set_affinity() to
CPU_ONLINE notification, so the affinity is being set when the CPU goes
online.

This fixes a regression introduced by commit
ee98d27df6 ARM: EXYNOS4: Divorce mct from local timer API
which rendered all Exynos4210 based boards unbootable due to
failing irq_set_affinity() making local timers inoperatible.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>

authored by

Tomasz Figa and committed by
Daniel Lezcano
5df718d8 7b0dd72a

+9 -1
+9 -1
drivers/clocksource/exynos_mct.c
··· 428 428 evt->irq); 429 429 return -EIO; 430 430 } 431 - irq_set_affinity(evt->irq, cpumask_of(cpu)); 432 431 } else { 433 432 enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0); 434 433 } ··· 448 449 unsigned long action, void *hcpu) 449 450 { 450 451 struct mct_clock_event_device *mevt; 452 + unsigned int cpu; 451 453 452 454 /* 453 455 * Grab cpu pointer in each case to avoid spurious ··· 458 458 case CPU_STARTING: 459 459 mevt = this_cpu_ptr(&percpu_mct_tick); 460 460 exynos4_local_timer_setup(&mevt->evt); 461 + break; 462 + case CPU_ONLINE: 463 + cpu = (unsigned long)hcpu; 464 + if (mct_int_type == MCT_INT_SPI) 465 + irq_set_affinity(mct_irqs[MCT_L0_IRQ + cpu], 466 + cpumask_of(cpu)); 461 467 break; 462 468 case CPU_DYING: 463 469 mevt = this_cpu_ptr(&percpu_mct_tick); ··· 506 500 &percpu_mct_tick); 507 501 WARN(err, "MCT: can't request IRQ %d (%d)\n", 508 502 mct_irqs[MCT_L0_IRQ], err); 503 + } else { 504 + irq_set_affinity(mct_irqs[MCT_L0_IRQ], cpumask_of(0)); 509 505 } 510 506 511 507 err = register_cpu_notifier(&exynos4_mct_cpu_nb);