Browse Source

qcacld-3.0: Set sme power stats response cb and context to NULL

Currently if the power stats command is invoked from multiple
threads, then the thread which invokes the command at the last
will overwrite the request manager cookie in the mac context.
Now when host gets response for these multiple requests, hdd
calback hdd_power_debugstats_cb will be invoked for each response
with the same cookie. in hdd_power_debugstats_cb host allocates
memory for the private data and this memory will also be
allocated multiple times and the last allocations will overwrite
the initial memory allocs which will lead to the memory leaks.

To address above issue set the sme power stats response cb and
context to NULL so that the callback is invoked only once.

Change-Id: I6fae0f96771ba505f06c1be14a8907b56efede24
CRs-Fixed: 2857855
Ashish Kumar Dhanotiya 4 years ago
parent
commit
203218df88

+ 2 - 1
core/hdd/src/wlan_hdd_sysfs.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-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
@@ -277,6 +277,7 @@ static ssize_t __show_device_power_stats(struct hdd_context *hdd_ctx,
 	ret_cnt = osif_request_wait_for_response(request);
 	if (ret_cnt) {
 		hdd_err("Target response timed out Power stats");
+		sme_reset_power_debug_stats_cb(hdd_ctx->mac_handle);
 		ret_cnt = -ETIMEDOUT;
 		goto cleanup;
 	}

+ 18 - 0
core/sme/inc/sme_api.h

@@ -2316,6 +2316,24 @@ QDF_STATUS sme_set_lost_link_info_cb(mac_handle_t mac_handle,
 QDF_STATUS sme_update_new_channel_event(mac_handle_t mac_handle,
 					uint8_t session_id);
 #ifdef WLAN_POWER_DEBUG
+/**
+ * sme_reset_power_debug_stats_cb() - SME API to reset Power debug stats cb
+ * @mac_handle: Opaque handle to the global MAC context
+ *
+ * Resets the power stats callback and context to NULL
+ *
+ * Return: None
+ */
+void sme_reset_power_debug_stats_cb(mac_handle_t mac_handle);
+
+/**
+ * sme_power_debug_stats_req() - SME API to collect Power debug stats
+ * @mac_handle: Opaque handle to the global MAC context
+ * @callback_fn: Pointer to the callback function for Power stats event
+ * @power_stats_context: Pointer to context
+ *
+ * Return: QDF_STATUS
+ */
 QDF_STATUS sme_power_debug_stats_req(
 		mac_handle_t mac_handle,
 		void (*callback_fn)(struct power_stats_response *response,

+ 18 - 7
core/sme/src/common/sme_api.c

@@ -10236,13 +10236,19 @@ QDF_STATUS sme_ll_stats_set_thresh(mac_handle_t mac_handle,
 #endif /* WLAN_FEATURE_LINK_LAYER_STATS */
 
 #ifdef WLAN_POWER_DEBUG
-/**
- * sme_power_debug_stats_req() - SME API to collect Power debug stats
- * @callback_fn: Pointer to the callback function for Power stats event
- * @power_stats_context: Pointer to context
- *
- * Return: QDF_STATUS
- */
+void sme_reset_power_debug_stats_cb(mac_handle_t mac_handle)
+{
+	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = sme_acquire_global_lock(&mac_ctx->sme);
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		mac_ctx->sme.power_debug_stats_context = NULL;
+		mac_ctx->sme.power_stats_resp_callback = NULL;
+		sme_release_global_lock(&mac_ctx->sme);
+	}
+}
+
 QDF_STATUS sme_power_debug_stats_req(
 		mac_handle_t mac_handle,
 		void (*callback_fn)(struct power_stats_response *response,
@@ -10261,6 +10267,11 @@ QDF_STATUS sme_power_debug_stats_req(
 			return QDF_STATUS_E_FAILURE;
 		}
 
+		if (mac_ctx->sme.power_debug_stats_context ||
+		    mac_ctx->sme.power_stats_resp_callback) {
+			sme_err("Already one power stats req in progress");
+			return QDF_STATUS_E_ALREADY;
+		}
 		mac_ctx->sme.power_debug_stats_context = power_stats_context;
 		mac_ctx->sme.power_stats_resp_callback = callback_fn;
 		msg.bodyptr = NULL;

+ 4 - 0
core/wma/src/wma_features.c

@@ -4580,6 +4580,10 @@ int wma_unified_power_debug_stats_event_handler(void *handle,
 
 	mac->sme.power_stats_resp_callback(power_stats_results,
 			mac->sme.power_debug_stats_context);
+
+	mac->sme.power_stats_resp_callback = NULL;
+	mac->sme.power_debug_stats_context = NULL;
+
 	qdf_mem_free(power_stats_results);
 	return 0;
 }