diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 83e39fb986..3ace465997 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -1434,9 +1434,16 @@ static void hdd_process_ll_stats(tSirLLStatsResults *results, if (stats) qdf_list_insert_back(&priv->ll_stats_q, &stats->ll_stats_node); - if (!priv->request_bitmap) + if (!priv->request_bitmap) { exit: + /* Thread which invokes this function has allocated memory in + * WMA for radio stats, that memory should be freed from the + * same thread to avoid any race conditions between two threads + */ + sme_radio_tx_mem_free(); osif_request_complete(request); + } + } static void hdd_debugfs_process_ll_stats(struct hdd_adapter *adapter, @@ -1474,8 +1481,15 @@ static void hdd_debugfs_process_ll_stats(struct hdd_adapter *adapter, hdd_err("INVALID LL_STATS_NOTIFY RESPONSE"); } - if (!priv->request_bitmap) + if (!priv->request_bitmap) { + /* Thread which invokes this function has allocated memory in + * WMA for radio stats, that memory should be freed from the + * same thread to avoid any race conditions between two threads + */ + sme_radio_tx_mem_free(); osif_request_complete(request); + } + } void wlan_hdd_cfg80211_link_layer_stats_callback(hdd_handle_t hdd_handle, @@ -2003,11 +2017,12 @@ static int wlan_hdd_send_ll_stats_req(struct hdd_adapter *adapter, qdf_spin_lock(&priv->ll_stats_lock); priv->request_bitmap = 0; qdf_spin_unlock(&priv->ll_stats_lock); + sme_radio_tx_mem_free(); ret = -ETIMEDOUT; } else { hdd_update_station_stats_cached_timestamp(adapter); } - sme_radio_tx_mem_free(); + qdf_spin_lock(&priv->ll_stats_lock); status = qdf_list_remove_front(&priv->ll_stats_q, &ll_node); qdf_spin_unlock(&priv->ll_stats_lock); diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index e068e760d0..c18ece1e29 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1014,6 +1014,7 @@ typedef struct { ol_txrx_pktdump_cb wma_mgmt_rx_packetdump_cb; bool rcpi_enabled; tSirLLStatsResults *link_stats_results; + qdf_mutex_t radio_stats_lock; uint64_t tx_fail_cnt; #ifdef FEATURE_WLM_STATS struct wma_wlm_stats_data wlm_data; diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index b922d1ba7f..8196e39a89 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3205,6 +3205,12 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, goto err_event_init; } + qdf_status = qdf_mutex_create(&wma_handle->radio_stats_lock); + if (QDF_IS_STATUS_ERROR(qdf_status)) { + wma_err("Failed to create radio stats mutex"); + goto err_event_init; + } + qdf_list_create(&wma_handle->wma_hold_req_queue, MAX_ENTRY_HOLD_REQ_QUEUE); qdf_spinlock_create(&wma_handle->wma_hold_req_q_lock); @@ -3493,6 +3499,10 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; err_dbglog_init: + qdf_status = qdf_mutex_destroy(&wma_handle->radio_stats_lock); + if (QDF_IS_STATUS_ERROR(qdf_status)) + wma_err("Failed to destroy radio stats mutex"); + qdf_wake_lock_destroy(&wma_handle->wmi_cmd_rsp_wake_lock); qdf_runtime_lock_deinit(&wma_handle->sap_prevent_runtime_pm_lock); qdf_runtime_lock_deinit(&wma_handle->wmi_cmd_rsp_runtime_lock); @@ -4543,6 +4553,10 @@ QDF_STATUS wma_close(void) wma_unified_radio_tx_mem_free(wma_handle); + qdf_status = qdf_mutex_destroy(&wma_handle->radio_stats_lock); + if (QDF_IS_STATUS_ERROR(qdf_status)) + wma_err("Failed to destroy radio stats mutex"); + if (wma_handle->pdev) { wlan_objmgr_pdev_release_ref(wma_handle->pdev, WLAN_LEGACY_WMA_ID); diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 9655eb15ad..1986a80436 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -1830,19 +1830,9 @@ void wma_unified_link_stats_results_mem_free( } } -/** - * 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) + +static int __wma_unified_radio_tx_mem_free(tp_wma_handle wma_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); @@ -1852,20 +1842,30 @@ int wma_unified_radio_tx_mem_free(void *handle) } /** - * wma_unified_radio_tx_power_level_stats_event_handler() - tx power level stats + * wma_unified_radio_tx_mem_free() - Free radio tx power stats memory * @handle: WMI handle - * @cmd_param_info: command param info - * @len: Length of @cmd_param_info - * - * This is the WMI event handler function to receive radio stats tx - * power level stats. * * Return: 0 on success, error number otherwise. */ -static int wma_unified_radio_tx_power_level_stats_event_handler(void *handle, - u_int8_t *cmd_param_info, u_int32_t len) +int wma_unified_radio_tx_mem_free(void *handle) { tp_wma_handle wma_handle = (tp_wma_handle) handle; + int ret; + + if (!wma_handle->link_stats_results) + return 0; + qdf_mutex_acquire(&wma_handle->radio_stats_lock); + ret = __wma_unified_radio_tx_mem_free(wma_handle); + qdf_mutex_release(&wma_handle->radio_stats_lock); + + return ret; +} + +static int __wma_unified_radio_tx_power_level_stats_event_handler( + tp_wma_handle wma_handle, + u_int8_t *cmd_param_info, + u_int32_t len) +{ WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *param_tlvs; wmi_tx_power_level_stats_evt_fixed_param *fixed_param; uint8_t *tx_power_level_values; @@ -2012,6 +2012,35 @@ post_stats: return 0; } +/** + * wma_unified_radio_tx_power_level_stats_event_handler() - tx power level stats + * @handle: WMI handle + * @cmd_param_info: command param info + * @len: Length of @cmd_param_info + * + * This is the WMI event handler function to receive radio stats tx + * power level stats. + * + * Return: 0 on success, error number otherwise. + */ +static int wma_unified_radio_tx_power_level_stats_event_handler( + void *handle, + u_int8_t *cmd_param_info, + u_int32_t len) +{ + tp_wma_handle wma_handle = (tp_wma_handle)handle; + int ret; + + qdf_mutex_acquire(&wma_handle->radio_stats_lock); + ret = __wma_unified_radio_tx_power_level_stats_event_handler( + wma_handle, + cmd_param_info, + len); + qdf_mutex_release(&wma_handle->radio_stats_lock); + + return ret; +} + static int wma_copy_chan_stats(uint32_t num_chan, struct wifi_channel_stats *channels, struct wifi_radio_stats *rs_results) @@ -2020,6 +2049,7 @@ static int wma_copy_chan_stats(uint32_t num_chan, struct wifi_channel_stats *channels_in_prev_event = rs_results->channels; if (!rs_results->channels) { + wma_debug("Num of channels in first event %d", num_chan); /* It means this is the first event for this radio */ rs_results->num_channels = num_chan; rs_results->channels = channels; @@ -2033,6 +2063,7 @@ static int wma_copy_chan_stats(uint32_t num_chan, return 0; } + wma_debug("Num of channels in Second event %d", num_chan); rs_results->num_channels += num_chan; rs_results->channels = qdf_mem_malloc(rs_results->num_channels * sizeof(*channels)); @@ -2055,19 +2086,11 @@ static int wma_copy_chan_stats(uint32_t num_chan, return 0; } -/** - * wma_unified_link_radio_stats_event_handler() - radio link stats event handler - * @handle: wma handle - * @cmd_param_info: data received with event from fw - * @len: length of data - * - * Return: 0 for success or error code - */ -static int wma_unified_link_radio_stats_event_handler(void *handle, - uint8_t *cmd_param_info, - uint32_t len) +static int +__wma_unified_link_radio_stats_event_handler(tp_wma_handle wma_handle, + uint8_t *cmd_param_info, + uint32_t len) { - tp_wma_handle wma_handle = (tp_wma_handle) handle; WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *param_tlvs; wmi_radio_link_stats_event_fixed_param *fixed_param; wmi_radio_link_stats *radio_stats; @@ -2314,6 +2337,29 @@ link_radio_stats_cb: return 0; } +/** + * wma_unified_link_radio_stats_event_handler() - radio link stats event handler + * @handle: wma handle + * @cmd_param_info: data received with event from fw + * @len: length of data + * + * Return: 0 for success or error code + */ +static int wma_unified_link_radio_stats_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len) +{ + tp_wma_handle wma_handle = (tp_wma_handle)handle; + int ret; + + qdf_mutex_acquire(&wma_handle->radio_stats_lock); + ret = __wma_unified_link_radio_stats_event_handler(wma_handle, + cmd_param_info, len); + qdf_mutex_release(&wma_handle->radio_stats_lock); + + return ret; +} + #ifdef WLAN_PEER_PS_NOTIFICATION /** * wma_peer_ps_evt_handler() - handler for PEER power state change.