diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 0297cbba21..d0e912a59c 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -94,6 +94,7 @@ #endif #include "wlan_hdd_lro.h" #include "cds_utils.h" +#include "wlan_hdd_request_manager.h" #define HDD_FINISH_ULA_TIME_OUT 800 #define HDD_SET_MCBC_FILTERS_TO_FW 1 @@ -4219,60 +4220,43 @@ static int iw_get_range(struct net_device *dev, struct iw_request_info *info, return ret; } +struct class_a_stats { + tCsrGlobalClassAStatsInfo class_a_stats; +}; + /** * hdd_get_class_a_statistics_cb() - Get Class A stats callback function - * @pStats: pointer to Class A stats - * @pContext: user context originally registered with SME + * @stats: pointer to Class A stats + * @context: user context originally registered with SME (always the + * cookie from the request context) * * Return: None */ -static void hdd_get_class_a_statistics_cb(void *pStats, void *pContext) +static void hdd_get_class_a_statistics_cb(void *stats, void *context) { - struct statsContext *pStatsContext; - tCsrGlobalClassAStatsInfo *pClassAStats; - hdd_adapter_t *pAdapter; + struct hdd_request *request; + struct class_a_stats *priv; + tCsrGlobalClassAStatsInfo *returned_stats; - if ((NULL == pStats) || (NULL == pContext)) { - hdd_err("Bad param, pStats [%p] pContext [%p]", - pStats, pContext); + ENTER(); + if ((NULL == stats) || (NULL == context)) { + hdd_err("Bad param, stats [%p] context [%p]", + stats, context); return; } - pClassAStats = pStats; - pStatsContext = pContext; - pAdapter = pStatsContext->pAdapter; - - /* there is a race condition that exists between this callback - * function and the caller since the caller could time out - * either before or while this code is executing. we use a - * spinlock to serialize these actions - */ - spin_lock(&hdd_context_lock); - - if ((NULL == pAdapter) || - (STATS_CONTEXT_MAGIC != pStatsContext->magic)) { - /* the caller presumably timed out so there is nothing - * we can do - */ - spin_unlock(&hdd_context_lock); - hdd_warn("Invalid context, pAdapter [%p] magic [%08x]", - pAdapter, pStatsContext->magic); + request = hdd_request_get(context); + if (!request) { + hdd_err("Obsolete request"); return; } - /* context is valid so caller is still waiting */ - - /* paranoia: invalidate the magic */ - pStatsContext->magic = 0; - - /* copy over the stats. do so as a struct copy */ - pAdapter->hdd_stats.ClassA_stat = *pClassAStats; - - /* notify the caller */ - complete(&pStatsContext->completion); - - /* serialization is complete */ - spin_unlock(&hdd_context_lock); + returned_stats = stats; + priv = hdd_request_priv(request); + priv->class_a_stats = *returned_stats; + hdd_request_complete(request); + hdd_request_put(request); + EXIT(); } /** @@ -4285,8 +4269,14 @@ QDF_STATUS wlan_hdd_get_class_astats(hdd_adapter_t *pAdapter) { hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); QDF_STATUS hstatus; - unsigned long rc; - static struct statsContext context; + int ret; + void *cookie; + struct hdd_request *request; + struct class_a_stats *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_STATS, + }; if (NULL == pAdapter) { hdd_err("pAdapter is NULL"); @@ -4298,10 +4288,13 @@ QDF_STATUS wlan_hdd_get_class_astats(hdd_adapter_t *pAdapter) return QDF_STATUS_SUCCESS; } - /* we are connected so prepare our callback context */ - init_completion(&context.completion); - context.pAdapter = pAdapter; - context.magic = STATS_CONTEXT_MAGIC; + request = hdd_request_alloc(¶ms); + if (!request) { + hdd_err("Request allocation failure"); + return QDF_STATUS_E_NOMEM; + } + cookie = hdd_request_cookie(request); + /* query only for Class A statistics (which include link speed) */ hstatus = sme_get_statistics(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_HDD, SME_GLOBAL_CLASSA_STATS, @@ -4309,38 +4302,31 @@ QDF_STATUS wlan_hdd_get_class_astats(hdd_adapter_t *pAdapter) 0, /* not periodic */ false, /* non-cached results */ pHddStaCtx->conn_info.staId[0], - &context, pAdapter->sessionId); + cookie, pAdapter->sessionId); if (QDF_STATUS_SUCCESS != hstatus) { hdd_warn("Unable to retrieve Class A statistics"); - /* we'll returned a cached value below */ - } else { - /* request was sent -- wait for the response */ - rc = wait_for_completion_timeout - (&context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); - if (!rc) { - hdd_warn("SME timed out while retrieving Class A statistics"); - } + goto return_cached_results; } - /* either we never sent a request, we sent a request and - * received a response or we sent a request and timed out. if - * we never sent a request or if we sent a request and got a - * response, we want to clear the magic out of paranoia. if - * we timed out there is a race condition such that the - * callback function could be executing at the same time we - * are. of primary concern is if the callback function had - * already verified the "magic" but had not yet set the - * completion variable when a timeout occurred. we serialize - * these activities by invalidating the magic while holding a - * shared spinlock which will cause us to block if the - * callback is currently executing - */ - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); + /* request was sent -- wait for the response */ + ret = hdd_request_wait_for_response(request); + if (ret) { + hdd_warn("SME timed out while retrieving Class A statistics"); + goto return_cached_results; + } + + /* update the adapter with the fresh results */ + priv = hdd_request_priv(request); + pAdapter->hdd_stats.ClassA_stat = priv->class_a_stats; + +return_cached_results: + /* + * either we never sent a request, we sent a request and + * received a response or we sent a request and timed out. + * regardless we are done with the request. + */ + hdd_request_put(request); - /* either callback updated pAdapter stats or it has cached data */ return QDF_STATUS_SUCCESS; }