浏览代码

qcacmn: Add support for rate limiting QDF trace prints

The existing QDF implementation does the following
1. The QDF trace either prints to the console
2. The QDF trace message  is directed to the utils,
   which based on log level
	a. redirects to a user space daemon or
	b. redirects to console

There is excessive logging detection in the utils code
before redirecting the prints to  the console.
If the number of prints to console is more than
the configured threshold, we assert in development builds.

Moving the API for excessive logging detection from utils to
QDF trace.

The configuration for detection of excessive logging currently
is only for the number of prints per second.
Adding time configuration also to detection of excess logging
to the console.

CRs-Fixed: 2809752
Change-Id: Iecc408fc9b576fa900a6d7ee793639f1dde3110d
Vivek 4 年之前
父节点
当前提交
3327a6a92b
共有 3 个文件被更改,包括 121 次插入34 次删除
  1. 37 0
      qdf/inc/qdf_trace.h
  2. 77 0
      qdf/linux/src/qdf_trace.c
  3. 7 34
      utils/logging/src/wlan_logging_sock_svc.c

+ 37 - 0
qdf/inc/qdf_trace.h

@@ -596,6 +596,43 @@ QDF_STATUS qdf_trace_spin_lock_init(void)
 #endif
 #endif
 
+#ifdef WLAN_MAX_LOGS_PER_SEC
+/**
+ * qdf_detected_excessive_logging() - Excessive logging detected
+ *
+ * Track logging count using a quasi-tumbling window.
+ * If the max logging count for a given window is exceeded,
+ * return true else fails.
+ *
+ * Return: true/false
+ */
+bool qdf_detected_excessive_logging(void);
+
+/**
+ * qdf_rl_print_count_set() - set the ratelimiting print count
+ * @rl_print_time: ratelimiting print count
+ *
+ * Return: none
+ */
+void qdf_rl_print_count_set(uint32_t rl_print_count);
+
+/**
+ * qdf_rl_print_time_set() - set the ratelimiting print time
+ * @rl_print_time: ratelimiting print time
+ *
+ * Return: none
+ */
+void qdf_rl_print_time_set(uint32_t rl_print_time);
+
+#else /* WLAN_MAX_LOGS_PER_SEC */
+static inline bool qdf_detected_excessive_logging(void)
+{
+	return false;
+}
+static inline void qdf_rl_print_count_set(uint32_t rl_print_count) {}
+static inline void qdf_rl_print_time_set(uint32_t rl_print_time) {}
+#endif /* WLAN_MAX_LOGS_PER_SEC */
+
 #ifdef ENABLE_MTRACE_LOG
 /**
  * qdf_mtrace_log() - Logs a message tracepoint to DIAG

+ 77 - 0
qdf/linux/src/qdf_trace.c

@@ -3207,9 +3207,86 @@ void qdf_trace_display(void)
 }
 qdf_export_symbol(qdf_trace_display);
 
+#ifdef WLAN_MAX_LOGS_PER_SEC
+static qdf_time_t __log_window_end;
+static qdf_atomic_t __log_window_count;
+uint32_t qdf_rl_print_count = WLAN_MAX_LOGS_PER_SEC;
+uint32_t qdf_rl_print_time = 1;
+uint32_t qdf_rl_print_supressed;
+
+/**
+ * qdf_detected_excessive_logging() - Excessive logging detected
+ *
+ * Track logging count using a quasi-tumbling window.
+ * If the max logging count for a given window is exceeded,
+ * return true else fails.
+ *
+ * Return: true/false
+ */
+bool qdf_detected_excessive_logging(void)
+{
+	qdf_time_t now = qdf_system_ticks();
+	bool excessive_prints = false;
+
+	/*
+	 * 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_atomic_read(&__log_window_count)) {
+		__log_window_end = now + (qdf_system_ticks_per_sec * qdf_rl_print_time);
+	} else if (qdf_system_time_after(now, __log_window_end)) {
+		__log_window_end = now + (qdf_system_ticks_per_sec * qdf_rl_print_time);
+		qdf_atomic_set(&__log_window_count, 0);
+	}
+
+	if (qdf_atomic_inc_return(&__log_window_count) > qdf_rl_print_count)
+		excessive_prints = true;
+
+	return excessive_prints;
+}
+
+void qdf_rl_print_count_set(uint32_t rl_print_count)
+{
+	qdf_rl_print_count = rl_print_count;
+}
+
+qdf_export_symbol(qdf_rl_print_count_set);
+
+void qdf_rl_print_time_set(uint32_t rl_print_time)
+{
+	qdf_rl_print_time = rl_print_time;
+}
+
+qdf_export_symbol(qdf_rl_print_time_set);
+
+static inline void qdf_rl_print_supressed_log(void)
+{
+	if (qdf_rl_print_supressed) {
+		pr_err("QDF Ratelimiting: %d prints supressed",
+		       qdf_rl_print_supressed);
+		qdf_rl_print_supressed = 0;
+	}
+}
+
+static inline void qdf_rl_print_supressed_inc(void)
+{
+	qdf_rl_print_supressed++;
+}
+#else
+#define qdf_rl_print_supressed_log()
+#define qdf_rl_print_supressed_inc()
+#endif /* WLAN_MAX_LOGS_PER_SEC */
+
 #ifdef QDF_TRACE_PRINT_ENABLE
 static inline void print_to_console(char *str_buffer)
 {
+	if (qdf_detected_excessive_logging()) {
+		qdf_rl_print_supressed_inc();
+		return;
+	}
+	qdf_rl_print_supressed_log();
 	pr_err("%s\n", str_buffer);
 }
 #else

+ 7 - 34
utils/logging/src/wlan_logging_sock_svc.c

@@ -308,41 +308,14 @@ static int wlan_add_user_log_time_stamp(char *tbuf, size_t tbuf_sz, uint64_t ts)
 }
 
 #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)
+static inline void wlan_panic_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_atomic_read(&__log_window_count)) {
-		__log_window_end_ticks = now + qdf_system_ticks_per_sec;
-	} else 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)
+	if (qdf_detected_excessive_logging())
 		QDF_DEBUG_PANIC("Exceeded %d logs per second",
 				WLAN_MAX_LOGS_PER_SEC);
 }
 #else
-static inline void assert_on_excessive_logging(void) { }
+static inline void wlan_panic_on_excessive_logging(void) {}
 #endif /* WLAN_MAX_LOGS_PER_SEC */
 
 static inline void
@@ -351,19 +324,19 @@ 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();
+		wlan_panic_on_excessive_logging();
 		break;
 	case QDF_TRACE_LEVEL_ERROR:
 		pr_err("%s %s\n", timestamp, msg);
-		assert_on_excessive_logging();
+		wlan_panic_on_excessive_logging();
 		break;
 	case QDF_TRACE_LEVEL_WARN:
 		pr_warn("%s %s\n", timestamp, msg);
-		assert_on_excessive_logging();
+		wlan_panic_on_excessive_logging();
 		break;
 	case QDF_TRACE_LEVEL_INFO:
 		pr_info("%s %s\n", timestamp, msg);
-		assert_on_excessive_logging();
+		wlan_panic_on_excessive_logging();
 		break;
 	case QDF_TRACE_LEVEL_INFO_HIGH:
 	case QDF_TRACE_LEVEL_INFO_MED: