From c4343d66a4f5f3e0668cdc56095dfa96c1f0aea4 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Mon, 15 Mar 2021 19:25:23 +0530 Subject: [PATCH] sched: idle: Add support to print wake irqs during s2idle syscore ops prints wake irq during "deep" suspend exit however syscore ops do not execute for "s2idle" suspend. Add changes to print wakeup irq during "s2idle" mode exit. The change prints wakeup irq from the first cpu waking up from s2idle during which local irqs on the cpu is disabled. Change-Id: Idd05d42f30b97cc5f9d62627339e21731f131673 Signed-off-by: Maulik Shah --- drivers/irqchip/Kconfig | 8 ++++++++ drivers/irqchip/irq-gic-v3.c | 8 ++++++++ include/linux/irqchip/arm-gic-v3.h | 4 ++++ kernel/sched/idle.c | 25 +++++++++++++++++++++++++ 4 files changed, 45 insertions(+) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index d039126411beb..6c4d8619c4e1b 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -37,6 +37,7 @@ config ARM_GIC_V3 select IRQ_DOMAIN_HIERARCHY select PARTITION_PERCPU select GENERIC_IRQ_EFFECTIVE_AFF_MASK + select QGKI_SHOW_S2IDLE_WAKE_IRQ if QGKI config ARM_GIC_V3_ITS bool @@ -516,4 +517,11 @@ config SIFIVE_PLIC If you don't know what to do here, say Y. +config QGKI_SHOW_S2IDLE_WAKE_IRQ + bool "Qualcomm Technologies, Inc. (QTI) SHOW S2IDLE WAKE IRQ" + depends on ARM_GIC_V3 + help + When this option is selected, first cpu waking up from s2idle + prints the interrupts pending and enabled at GIC. + endmenu diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index dcaa003b9417e..19ddb4c52bd6c 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -1244,6 +1245,13 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, #define gic_smp_init() do { } while(0) #endif +#ifdef CONFIG_QGKI_SHOW_S2IDLE_WAKE_IRQ +void gic_s2idle_wake(void) +{ + gic_resume_one(&gic_data); +} +#endif /* CONFIG_QGKI_SHOW_S2IDLE_WAKE_IRQ */ + #ifdef CONFIG_CPU_PM static int gic_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd, void *v) diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index 5cc10cf7cb3e6..2f349fb5f1965 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -638,6 +638,10 @@ static inline bool gic_enable_sre(void) return !!(val & ICC_SRE_EL1_SRE); } +#ifdef CONFIG_QGKI_SHOW_S2IDLE_WAKE_IRQ +void gic_s2idle_wake(void); +#endif /* CONFIG_QGKI_SHOW_S2IDLE_WAKE_IRQ */ + #endif #endif diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index 251a7df055d6b..93b3195bfd971 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c @@ -8,6 +8,9 @@ */ #include "sched.h" +#ifdef CONFIG_QGKI_SHOW_S2IDLE_WAKE_IRQ +#include +#endif /* CONFIG_QGKI_SHOW_S2IDLE_WAKE_IRQ */ #include /* Linker adds these: start and end of __cpuidle functions */ @@ -128,6 +131,11 @@ static int call_cpuidle(struct cpuidle_driver *drv, struct cpuidle_device *dev, * set, and it returns with polling set. If it ever stops polling, it * must clear the polling bit. */ + +#ifdef CONFIG_QGKI_SHOW_S2IDLE_WAKE_IRQ +static cpumask_t cpu_state; +#endif /* CONFIG_QGKI_SHOW_S2IDLE_WAKE_IRQ */ + static void cpuidle_idle_call(void) { struct cpuidle_device *dev = cpuidle_get_device(); @@ -169,9 +177,26 @@ static void cpuidle_idle_call(void) if (idle_should_enter_s2idle() || dev->use_deepest_state) { if (idle_should_enter_s2idle()) { + +#ifdef CONFIG_QGKI_SHOW_S2IDLE_WAKE_IRQ + bool print_wake_irq; + + cpumask_set_cpu(dev->cpu, &cpu_state); +#endif /* CONFIG_QGKI_SHOW_S2IDLE_WAKE_IRQ */ + rcu_idle_enter(); entered_state = cpuidle_enter_s2idle(drv, dev); + +#ifdef CONFIG_QGKI_SHOW_S2IDLE_WAKE_IRQ + print_wake_irq = cpumask_weight(&cpu_state) == + cpumask_weight(cpu_online_mask) ? + true : false; + cpumask_clear_cpu(dev->cpu, &cpu_state); + if (print_wake_irq) + gic_s2idle_wake(); +#endif /* CONFIG_QGKI_SHOW_S2IDLE_WAKE_IRQ */ + if (entered_state > 0) { local_irq_enable(); goto exit_idle;