@@ -934,9 +934,10 @@ static int ghes_proc(struct ghes *ghes)
return rc;
}
-static void ghes_add_timer(struct ghes *ghes)
+static void ghes_add_timer(struct ghes *ghes, bool probe)
{
struct acpi_hest_generic *g = ghes->generic;
+ static int cpu_running_timer;
unsigned long expire;
if (!g->notify.poll_interval) {
@@ -946,7 +947,16 @@ static void ghes_add_timer(struct ghes *ghes)
}
expire = jiffies + msecs_to_jiffies(g->notify.poll_interval);
ghes->timer.expires = round_jiffies_relative(expire);
- add_timer(&ghes->timer);
+
+ if (probe) {
+ cpu_running_timer = cpumask_next(cpu_running_timer, cpu_online_mask);
+ if (cpu_running_timer >= nr_cpu_ids)
+ cpu_running_timer = cpumask_first(cpu_online_mask);
+
+ add_timer_on(&ghes->timer, cpu_running_timer);
+ } else {
+ add_timer_on(&ghes->timer, raw_smp_processor_id());
+ }
}
static void ghes_poll_func(struct timer_list *t)
@@ -958,7 +968,7 @@ static void ghes_poll_func(struct timer_list *t)
ghes_proc(ghes);
spin_unlock_irqrestore(&ghes_notify_lock_irq, flags);
if (!(ghes->flags & GHES_EXITING))
- ghes_add_timer(ghes);
+ ghes_add_timer(ghes, false);
}
static irqreturn_t ghes_irq_func(int irq, void *data)
@@ -1388,7 +1398,7 @@ static int ghes_probe(struct platform_device *ghes_dev)
switch (generic->notify.type) {
case ACPI_HEST_NOTIFY_POLLED:
timer_setup(&ghes->timer, ghes_poll_func, 0);
- ghes_add_timer(ghes);
+ ghes_add_timer(ghes, true);
break;
case ACPI_HEST_NOTIFY_EXTERNAL:
/* External interrupt vector is GSI */
Kernel needs to set up a timer for each poll type notification, On some system, these are tens of thousands of timers, which expires periodically and preempt one CPU which calls ghes_probe at boot stage so load balance evenly timers to all online cpus, reduce task jitter Signed-off-by: Li RongQing <lirongqing@baidu.com> --- drivers/acpi/apei/ghes.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-)