diff --git a/include/config.h b/include/config.h index fa522c3b41..918ba2130f 100644 --- a/include/config.h +++ b/include/config.h @@ -1431,6 +1431,13 @@ /* Support stopping in S5 on shutdown */ #undef CONFIG_POWER_SHUTDOWN_PAUSE_IN_S5 +/* + * Detect power signal interrupt storms, defined as more than + * CONFIG_POWER_SIGNAL_INTERRUPT_STORM_DETECT_THRESHOLD occurences of a single + * power signal interrupt within one second. + */ +#undef CONFIG_POWER_SIGNAL_INTERRUPT_STORM_DETECT_THRESHOLD + /* Use part of the EC's data EEPROM to hold persistent storage for the AP. */ #undef CONFIG_PSTORE diff --git a/power/common.c b/power/common.c index 204ef2221e..c75865ea53 100644 --- a/power/common.c +++ b/power/common.c @@ -456,8 +456,42 @@ static void siglog_add(enum gpio_signal signal) #define SIGLOG(S) #endif /* CONFIG_BRINGUP */ +#ifdef CONFIG_POWER_SIGNAL_INTERRUPT_STORM_DETECT_THRESHOLD +/* + * Print an interrupt storm warning when we receive more than + * CONFIG_POWER_SIGNAL_INTERRUPT_STORM_DETECT_THRESHOLD interrupts of a + * single source within 1 second. + */ +static int power_signal_interrupt_count[POWER_SIGNAL_COUNT]; + +static void reset_power_signal_interrupt_count(void) +{ + int i; + + for (i = 0; i < POWER_SIGNAL_COUNT; ++i) + power_signal_interrupt_count[i] = 0; +} +DECLARE_HOOK(HOOK_SECOND, + reset_power_signal_interrupt_count, + HOOK_PRIO_DEFAULT); +#endif + void power_signal_interrupt(enum gpio_signal signal) { +#ifdef CONFIG_POWER_SIGNAL_INTERRUPT_STORM_DETECT_THRESHOLD + int i; + + /* Tally our interrupts and print a warning if necessary. */ + for (i = 0; i < POWER_SIGNAL_COUNT; ++i) { + if (power_signal_list[i].gpio == signal) { + if (power_signal_interrupt_count[i]++ == + CONFIG_POWER_SIGNAL_INTERRUPT_STORM_DETECT_THRESHOLD) + CPRINTS("Interrupt storm! Signal %d\n", i); + break; + } + } +#endif + SIGLOG(signal); /* Shadow signals and compare with our desired signal state. */