diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index aab8ba40ce38..847f96fe1d3d 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -52,6 +52,11 @@ #define CREATE_TRACE_POINTS #include +#ifdef CONFIG_QGKI_LPM_IPI_CHECK +DEFINE_PER_CPU(bool, pending_ipi); +EXPORT_PER_CPU_SYMBOL(pending_ipi); +#endif /* CONFIG_QGKI_LPM_IPI_CHECK */ + /* * as from 2.5, kernels no longer have an init_tasks structure * so we need some other way of telling a new secondary core @@ -521,6 +526,13 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = { static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) { +#ifdef CONFIG_QGKI_LPM_IPI_CHECK + unsigned int cpu; + + for_each_cpu(cpu, target) + per_cpu(pending_ipi, cpu) = true; +#endif /* CONFIG_QGKI_LPM_IPI_CHECK */ + trace_ipi_raise_rcuidle(target, ipi_types[ipinr]); __smp_cross_call(target, ipinr); } @@ -695,6 +707,11 @@ void handle_IPI(int ipinr, struct pt_regs *regs) if ((unsigned)ipinr < NR_IPI) trace_ipi_exit_rcuidle(ipi_types[ipinr]); + +#ifdef CONFIG_QGKI_LPM_IPI_CHECK + this_cpu_write(pending_ipi, false); +#endif /* CONFIG_QGKI_LPM_IPI_CHECK */ + set_irq_regs(old_regs); } diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 76eefdc78afc..14e176fabb98 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -57,6 +57,11 @@ DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number); EXPORT_PER_CPU_SYMBOL(cpu_number); +#ifdef CONFIG_QGKI_LPM_IPI_CHECK +DEFINE_PER_CPU(bool, pending_ipi); +EXPORT_PER_CPU_SYMBOL(pending_ipi); +#endif /* CONFIG_QGKI_LPM_IPI_CHECK */ + /* * as from 2.5, kernels no longer have an init_tasks structure * so we need some other way of telling a new secondary core @@ -772,6 +777,13 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = { static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) { +#ifdef CONFIG_QGKI_LPM_IPI_CHECK + unsigned int cpu; + + for_each_cpu(cpu, target) + per_cpu(pending_ipi, cpu) = true; +#endif /* CONFIG_QGKI_LPM_IPI_CHECK */ + trace_ipi_raise(target, ipi_types[ipinr]); __smp_cross_call(target, ipinr); } @@ -957,6 +969,11 @@ void handle_IPI(int ipinr, struct pt_regs *regs) if ((unsigned)ipinr < NR_IPI) trace_ipi_exit_rcuidle(ipi_types[ipinr]); + +#ifdef CONFIG_QGKI_LPM_IPI_CHECK + this_cpu_write(pending_ipi, false); +#endif /* CONFIG_QGKI_LPM_IPI_CHECK */ + set_irq_regs(old_regs); } diff --git a/include/linux/smp.h b/include/linux/smp.h index 6fc856c9eda5..e21278d66a4b 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -136,6 +136,27 @@ static inline int get_boot_cpu_id(void) return __boot_cpu_id; } +#ifdef CONFIG_QGKI_LPM_IPI_CHECK +DECLARE_PER_CPU(bool, pending_ipi); + +static inline bool is_IPI_pending(const struct cpumask *mask) +{ + unsigned int cpu; + + for_each_cpu(cpu, mask) { + if (per_cpu(pending_ipi, cpu)) + return true; + } + + return false; +} +#else +static inline bool is_IPI_pending(const struct cpumask *mask) +{ + return false; +} +#endif /* CONFIG_QGKI_LPM_IPI_CHECK */ + #else /* !SMP */ static inline void smp_send_stop(void) { } @@ -178,6 +199,11 @@ static inline int get_boot_cpu_id(void) return 0; } +static inline bool is_IPI_pending(const struct cpumask *mask) +{ + return false; +} + #endif /* !SMP */ /**