qcacld-3.0: Free link_layer_stats results properly

As per the logic implemented in the FW, it will send a dummy event for
link layer stats in case the buffer allocation fails. In this case,
there can occur a scenario in host wherein we are not properly freeing
the previously allocated memory.

In the event handler wma_unified_link_radio_stats_event_handler, if the
event is dummy, we are updating the value of the num_radios inside
wma_handle->link_layer_results. This num_radios is later used to free
any allocated memory. On setting it to zero, we are preventing that
memfree to occur; leading to a memleak.

To fix this, in case there is a dummy event, first free any possible
previous results before setting the num_radios to be zero.

Change-Id: Ibe4ddf1a137a33130100483cefb004b7dae4ce02
CRs-Fixed: 2610754
This commit is contained in:
Sourav Mohapatra 2020-01-28 16:29:11 +05:30 • committed by nshrivas
commit 2cbc99c302
2 changed files with 44 additions and 9 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2012-2020 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
@ -186,6 +186,17 @@ bool wma_is_rx_ldpc_supported_for_channel(uint32_t ch_freq);
#ifdef WLAN_FEATURE_LINK_LAYER_STATS
int wma_unified_radio_tx_mem_free(void *handle);
/*
* wma_unified_link_stats_results_mem_free() - Free the memory for
* link_stats_results->results allocated when event comes.
* @link_stats_results: pointer to the memory that is to be freed
*
* Return: None
*/
void
wma_unified_link_stats_results_mem_free(tSirLLStatsResults *link_stats_results);
#else /* WLAN_FEATURE_LINK_LAYER_STATS */
static inline int wma_unified_radio_tx_mem_free(void *handle)
{

View file

@ -1699,23 +1699,23 @@ static int wma_unified_link_peer_stats_event_handler(void *handle,
}
/**
* wma_unified_radio_tx_mem_free() - Free radio tx power stats memory
* @handle: WMI handle
* wma_unified_link_stats_results_mem_free() - Free link stats results memory
* #link_stats_results: pointer to link stats result
*
* Return: 0 on success, error number otherwise.
*/
int wma_unified_radio_tx_mem_free(void *handle)
void wma_unified_link_stats_results_mem_free(
tSirLLStatsResults *link_stats_results)
{
tp_wma_handle wma_handle = (tp_wma_handle) handle;
struct wifi_radio_stats *rs_results;
uint32_t i = 0;
if (!wma_handle->link_stats_results)
return 0;
if (!link_stats_results)
return;
rs_results = (struct wifi_radio_stats *)
&wma_handle->link_stats_results->results[0];
for (i = 0; i < wma_handle->link_stats_results->num_radio; i++) {
&link_stats_results->results[0];
for (i = 0; i < link_stats_results->num_radio; i++) {
if (rs_results->tx_time_per_power_level) {
qdf_mem_free(rs_results->tx_time_per_power_level);
rs_results->tx_time_per_power_level = NULL;
@ -1727,6 +1727,22 @@ int wma_unified_radio_tx_mem_free(void *handle)
}
rs_results++;
}
}
/**
* wma_unified_radio_tx_mem_free() - Free radio tx power stats memory
* @handle: WMI handle
*
* Return: 0 on success, error number otherwise.
*/
int wma_unified_radio_tx_mem_free(void *handle)
{
tp_wma_handle wma_handle = (tp_wma_handle) handle;
if (!wma_handle->link_stats_results)
return 0;
wma_unified_link_stats_results_mem_free(wma_handle->link_stats_results);
qdf_mem_free(wma_handle->link_stats_results);
wma_handle->link_stats_results = NULL;
@ -1961,6 +1977,14 @@ static int wma_unified_link_radio_stats_event_handler(void *handle,
if (!wma_handle->link_stats_results)
return -ENOMEM;
}
/*
* Free the already allocated memory, if any, before setting
* the num_radio to 0
*/
wma_unified_link_stats_results_mem_free(
wma_handle->link_stats_results);
link_stats_results = wma_handle->link_stats_results;
link_stats_results->num_radio = fixed_param->num_radio;
goto link_radio_stats_cb;