qcacmn: Add excessive logging detection

One of the most common stability issues encountered by the stability
team is watchdog bite due to excessive logging. Add a feature to track
logging to dmesg using a tumbling window and counter, and panic if the
configured maximum number of logs for that window is exceeded.

Change-Id: If83c6dfccb9d191b02a3a7166b065c0a0704f969
CRs-Fixed: 2338385
This commit is contained in:
Dustin Brown
2018-10-22 13:52:28 -07:00
committed by nshrivas
parent 0050ec95b3
commit aaa97751a6
3 changed files with 44 additions and 0 deletions

View File

@@ -299,21 +299,61 @@ static int wlan_add_user_log_time_stamp(char *tbuf, size_t tbuf_sz, uint64_t ts)
#endif /* QCA_WIFI_3_0_ADRASTEA */
#ifdef CONFIG_MCL
#ifdef WLAN_MAX_LOGS_PER_SEC
static qdf_time_t __log_window_end_ticks;
static qdf_atomic_t __log_window_count;
/**
* assert_on_excessive_logging() - Check for and panic on excessive logging
*
* Track logging count using a quasi-tumbling window, 1 second long. If the max
* logging count for a given window is exceeded, panic.
*
* Return: None
*/
static void assert_on_excessive_logging(void)
{
qdf_time_t now = qdf_system_ticks();
/*
* If 'now' is more recent than the end of the window, reset.
*
* Note: This is not thread safe, and can result in more than one reset.
* For our purposes, this is fine.
*/
if (qdf_system_time_after(now, __log_window_end_ticks)) {
__log_window_end_ticks = now + qdf_system_ticks_per_sec;
qdf_atomic_set(&__log_window_count, 0);
}
/* this _is_ thread safe, and results in at most one panic */
if (qdf_atomic_inc_return(&__log_window_count) == WLAN_MAX_LOGS_PER_SEC)
QDF_DEBUG_PANIC("Exceeded %d logs per second",
WLAN_MAX_LOGS_PER_SEC);
}
#else
static inline void assert_on_excessive_logging(void) { }
#endif /* WLAN_MAX_LOGS_PER_SEC */
static inline void
log_to_console(QDF_TRACE_LEVEL level, const char *timestamp, const char *msg)
{
switch (level) {
case QDF_TRACE_LEVEL_FATAL:
pr_alert("%s %s\n", timestamp, msg);
assert_on_excessive_logging();
break;
case QDF_TRACE_LEVEL_ERROR:
pr_err("%s %s\n", timestamp, msg);
assert_on_excessive_logging();
break;
case QDF_TRACE_LEVEL_WARN:
pr_warn("%s %s\n", timestamp, msg);
assert_on_excessive_logging();
break;
case QDF_TRACE_LEVEL_INFO:
pr_info("%s %s\n", timestamp, msg);
assert_on_excessive_logging();
break;
case QDF_TRACE_LEVEL_INFO_HIGH:
case QDF_TRACE_LEVEL_INFO_MED: