Explorar el Código

qcacmn: Add synchronization for flush log completion

Currently there is no synchronization for flush log completion
between fw and userspace. When host driver receives command to
flush logs, it sends the command to fw and releases the control
of the userspace thread, it does not wait for the flush log
completion event from the fw and because of which user space
does not know when the host and fw completes the log flush.

To address above issue add a logic to wait for fw event of
flush log completion before host returns control to userspace.

Change-Id: I04fa0aead146d2b7b8627e4101c6dcd99d3947e9
CRs-Fixed: 2983387
Ashish Kumar Dhanotiya hace 4 años
padre
commit
fdac28ef95

+ 12 - 1
utils/logging/inc/wlan_logging_sock_svc.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -69,12 +69,23 @@ int wlan_logging_notifier_init(bool dump_at_kernel_enable);
 int wlan_logging_notifier_deinit(bool dump_at_kernel_enable);
 
 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
+/**
+ * wlan_logging_wait_for_flush_log_completion() -  Wait for flush log completion
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_logging_wait_for_flush_log_completion(void);
+
 void wlan_logging_set_per_pkt_stats(void);
 void wlan_logging_set_fw_flush_complete(void);
 void wlan_flush_host_logs_for_fatal(void);
 void wlan_logging_set_active(bool active);
 void wlan_set_console_log_levels(uint32_t console_log_levels);
 #else
+static inline QDF_STATUS wlan_logging_wait_for_flush_log_completion(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
 static inline void wlan_flush_host_logs_for_fatal(void) {}
 static inline void wlan_logging_set_per_pkt_stats(void) {}
 static inline void wlan_logging_set_fw_flush_complete(void) {}

+ 28 - 0
utils/logging/src/wlan_logging_sock_svc.c

@@ -109,6 +109,8 @@ DEFINE_RATELIMIT_STATE(panic_wifilog_ratelimit,
 		       PANIC_WIFILOG_PRINT_RATE_LIMIT_PERIOD,
 		       PANIC_WIFILOG_PRINT_RATE_LIMIT_BURST_DEFAULT);
 
+#define FLUSH_LOG_COMPLETION_TIMEOUT 3000
+
 struct log_msg {
 	struct list_head node;
 	unsigned int radio;
@@ -192,6 +194,8 @@ struct wlan_logging {
 	bool is_flush_timer_initialized;
 	uint32_t flush_timer_period;
 	qdf_spinlock_t flush_timer_lock;
+
+	qdf_event_t flush_log_completion;
 };
 
 /* This global variable is intentionally not marked static because it
@@ -765,6 +769,20 @@ static void send_flush_completion_to_user(uint8_t ring_id)
 }
 #endif
 
+static void wlan_logging_set_flush_log_completion(void)
+{
+	qdf_event_set(&gwlan_logging.flush_log_completion);
+}
+
+QDF_STATUS wlan_logging_wait_for_flush_log_completion(void)
+{
+	qdf_event_reset(&gwlan_logging.flush_log_completion);
+
+	return qdf_wait_for_event_completion(
+					&gwlan_logging.flush_log_completion,
+					FLUSH_LOG_COMPLETION_TIMEOUT);
+}
+
 static void setup_flush_timer(void)
 {
 	qdf_spin_lock(&gwlan_logging.flush_timer_lock);
@@ -850,6 +868,7 @@ static int wlan_logging_thread(void *Arg)
 				send_flush_completion_to_user(
 						RING_ID_DRIVER_DEBUG);
 #endif
+				wlan_logging_set_flush_log_completion();
 			} else {
 				gwlan_logging.is_flush_complete = true;
 				/* Flush all current host logs*/
@@ -1064,6 +1083,7 @@ int wlan_logging_sock_init_svc(void)
 {
 	int i = 0, j, pkt_stats_size;
 	unsigned long irq_flag;
+	QDF_STATUS status;
 
 	spin_lock_init(&gwlan_logging.spin_lock);
 	spin_lock_init(&gwlan_logging.pkt_stats_lock);
@@ -1147,6 +1167,12 @@ int wlan_logging_sock_init_svc(void)
 	gwlan_logging.is_active = true;
 	gwlan_logging.is_flush_complete = false;
 
+	status = qdf_event_create(&gwlan_logging.flush_log_completion);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		qdf_err("Flush log completion event init failed");
+		goto err3;
+	}
+
 	return 0;
 
 err3:
@@ -1178,6 +1204,8 @@ int wlan_logging_sock_deinit_svc(void)
 	if (!gwlan_logging.pcur_node)
 		return 0;
 
+	qdf_event_destroy(&gwlan_logging.flush_log_completion);
+
 	INIT_COMPLETION(gwlan_logging.shutdown_comp);
 	gwlan_logging.exit = true;
 	gwlan_logging.is_active = false;