From 2e1f0d59694acde537501377d9c5404f90fd2b62 Mon Sep 17 00:00:00 2001 From: Rachit Kankane Date: Thu, 15 Oct 2020 18:24:21 +0530 Subject: [PATCH] qcacld-3.0: Fix memory leak in LL Stats Due to low memory in Host, sometimes memory allocation might fail. Free allocated memory to LL stats substructures in case of such failures. Change-Id: I2f3956d14348c57502d27aecef6225246a7970fa CRs-Fixed: 2795970 --- core/hdd/src/wlan_hdd_stats.c | 53 ++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index bb6b04e28515..a822454e61b3 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -880,6 +880,25 @@ static int hdd_llstats_radio_fill_channels(struct hdd_adapter *adapter, return 0; } +/** + * hdd_llstats_free_radio_stats() - free wifi_radio_stats member pointers + * @radiostat: Pointer to stats data + * + * Return: void + */ +static void hdd_llstats_free_radio_stats(struct wifi_radio_stats *radiostat) +{ + if (radiostat->total_num_tx_power_levels && + radiostat->tx_time_per_power_level) { + qdf_mem_free(radiostat->tx_time_per_power_level); + radiostat->tx_time_per_power_level = NULL; + } + if (radiostat->num_channels && radiostat->channels) { + qdf_mem_free(radiostat->channels); + radiostat->channels = NULL; + } +} + /** * hdd_llstats_post_radio_stats() - post radio stats * @adapter: Pointer to device adapter @@ -887,12 +906,12 @@ static int hdd_llstats_radio_fill_channels(struct hdd_adapter *adapter, * @radiostat: Pointer to stats data * @num_radio: Number of radios * - * Return: 0 on success; errno on failure + * Return: void */ -static int hdd_llstats_post_radio_stats(struct hdd_adapter *adapter, - u32 more_data, - struct wifi_radio_stats *radiostat, - u32 num_radio) +static void hdd_llstats_post_radio_stats(struct hdd_adapter *adapter, + u32 more_data, + struct wifi_radio_stats *radiostat, + u32 num_radio) { struct sk_buff *vendor_event; struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); @@ -913,7 +932,8 @@ static int hdd_llstats_post_radio_stats(struct hdd_adapter *adapter, if (!vendor_event) { hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed"); - return -ENOMEM; + hdd_llstats_free_radio_stats(radiostat); + goto failure; } if (nla_put_u32(vendor_event, @@ -962,6 +982,7 @@ static int hdd_llstats_post_radio_stats(struct hdd_adapter *adapter, QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS, radiostat->num_channels)) { hdd_err("QCA_WLAN_VENDOR_ATTR put fail"); + hdd_llstats_free_radio_stats(radiostat); goto failure; } @@ -973,11 +994,7 @@ static int hdd_llstats_post_radio_stats(struct hdd_adapter *adapter, sizeof(u32) * radiostat->total_num_tx_power_levels, radiostat->tx_time_per_power_level); - qdf_mem_free(radiostat->tx_time_per_power_level); - radiostat->tx_time_per_power_level = NULL; if (ret) { - qdf_mem_free(radiostat->channels); - radiostat->channels = NULL; hdd_err("nla_put fail"); goto failure; } @@ -986,18 +1003,17 @@ static int hdd_llstats_post_radio_stats(struct hdd_adapter *adapter, if (radiostat->num_channels) { ret = hdd_llstats_radio_fill_channels(adapter, radiostat, vendor_event); - qdf_mem_free(radiostat->channels); - radiostat->channels = NULL; if (ret) goto failure; } cfg80211_vendor_cmd_reply(vendor_event); - return 0; + hdd_llstats_free_radio_stats(radiostat); + return; failure: kfree_skb(vendor_event); - return -EINVAL; + hdd_llstats_free_radio_stats(radiostat); } /** @@ -1019,7 +1035,7 @@ hdd_link_layer_process_radio_stats(struct hdd_adapter *adapter, struct wifi_radio_stats *radio_stat, u32 num_radio) { - int i, nr, ret; + int i, nr; struct wifi_radio_stats *radio_stat_save = radio_stat; /* @@ -1054,11 +1070,8 @@ hdd_link_layer_process_radio_stats(struct hdd_adapter *adapter, radio_stat = radio_stat_save; for (nr = 0; nr < num_radio; nr++) { - ret = hdd_llstats_post_radio_stats(adapter, more_data, - radio_stat, num_radio); - if (ret) - return; - + hdd_llstats_post_radio_stats(adapter, more_data, + radio_stat, num_radio); radio_stat++; }