Loading include/linux/cpu.h +1 −0 Original line number Diff line number Diff line Loading @@ -288,6 +288,7 @@ void cpu_startup_entry(enum cpuhp_state state); void cpu_idle(void); void cpu_idle_poll_ctrl(bool enable); void per_cpu_idle_poll_ctrl(int cpu, bool enable); void arch_cpu_idle(void); void arch_cpu_idle_prepare(void); Loading kernel/cpu/idle.c +25 −2 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ #include <linux/tick.h> #include <linux/mm.h> #include <linux/stackprotector.h> #include <linux/percpu.h> #include <asm/tlb.h> Loading @@ -26,6 +27,24 @@ void cpu_idle_poll_ctrl(bool enable) mb(); } static DEFINE_PER_CPU(int, idle_force_poll); void per_cpu_idle_poll_ctrl(int cpu, bool enable) { if (enable) { per_cpu(idle_force_poll, cpu)++; } else { per_cpu(idle_force_poll, cpu)--; WARN_ON_ONCE(per_cpu(idle_force_poll, cpu) < 0); } /* * Make sure poll mode is entered on the relevant CPU after the flag is * set */ mb(); } #ifdef CONFIG_GENERIC_IDLE_POLL_SETUP static int __init cpu_idle_poll_setup(char *__unused) { Loading @@ -47,7 +66,8 @@ static inline int cpu_idle_poll(void) rcu_idle_enter(); trace_cpu_idle_rcuidle(0, smp_processor_id()); local_irq_enable(); while (!tif_need_resched() && cpu_idle_force_poll) while (!tif_need_resched() && (cpu_idle_force_poll || __get_cpu_var(idle_force_poll))) cpu_relax(); trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); rcu_idle_exit(); Loading Loading @@ -89,7 +109,9 @@ static void cpu_idle_loop(void) * know that the IPI is going to arrive right * away */ if (cpu_idle_force_poll || tick_check_broadcast_expired()) { if (cpu_idle_force_poll || tick_check_broadcast_expired() || __get_cpu_var(idle_force_poll)) { cpu_idle_poll(); } else { if (!current_clr_polling_and_test()) { Loading Loading @@ -133,5 +155,6 @@ void cpu_startup_entry(enum cpuhp_state state) #endif __current_set_polling(); arch_cpu_idle_prepare(); per_cpu(idle_force_poll, smp_processor_id()) = 0; cpu_idle_loop(); } Loading
include/linux/cpu.h +1 −0 Original line number Diff line number Diff line Loading @@ -288,6 +288,7 @@ void cpu_startup_entry(enum cpuhp_state state); void cpu_idle(void); void cpu_idle_poll_ctrl(bool enable); void per_cpu_idle_poll_ctrl(int cpu, bool enable); void arch_cpu_idle(void); void arch_cpu_idle_prepare(void); Loading
kernel/cpu/idle.c +25 −2 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ #include <linux/tick.h> #include <linux/mm.h> #include <linux/stackprotector.h> #include <linux/percpu.h> #include <asm/tlb.h> Loading @@ -26,6 +27,24 @@ void cpu_idle_poll_ctrl(bool enable) mb(); } static DEFINE_PER_CPU(int, idle_force_poll); void per_cpu_idle_poll_ctrl(int cpu, bool enable) { if (enable) { per_cpu(idle_force_poll, cpu)++; } else { per_cpu(idle_force_poll, cpu)--; WARN_ON_ONCE(per_cpu(idle_force_poll, cpu) < 0); } /* * Make sure poll mode is entered on the relevant CPU after the flag is * set */ mb(); } #ifdef CONFIG_GENERIC_IDLE_POLL_SETUP static int __init cpu_idle_poll_setup(char *__unused) { Loading @@ -47,7 +66,8 @@ static inline int cpu_idle_poll(void) rcu_idle_enter(); trace_cpu_idle_rcuidle(0, smp_processor_id()); local_irq_enable(); while (!tif_need_resched() && cpu_idle_force_poll) while (!tif_need_resched() && (cpu_idle_force_poll || __get_cpu_var(idle_force_poll))) cpu_relax(); trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); rcu_idle_exit(); Loading Loading @@ -89,7 +109,9 @@ static void cpu_idle_loop(void) * know that the IPI is going to arrive right * away */ if (cpu_idle_force_poll || tick_check_broadcast_expired()) { if (cpu_idle_force_poll || tick_check_broadcast_expired() || __get_cpu_var(idle_force_poll)) { cpu_idle_poll(); } else { if (!current_clr_polling_and_test()) { Loading Loading @@ -133,5 +155,6 @@ void cpu_startup_entry(enum cpuhp_state state) #endif __current_set_polling(); arch_cpu_idle_prepare(); per_cpu(idle_force_poll, smp_processor_id()) = 0; cpu_idle_loop(); }