From e7d86054712d407590d2f4cfd42786a4e07d9425 Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Fri, 13 Nov 2015 12:01:43 -0800 Subject: [PATCH] qcacld-3.0: Increase SME cmd queue to support max clients connected This is qcacld-2.0 to qcacld-3.0 propagation Currently in SAP mode, if max STA connected a operation to turn off SAP will result in more than SME queue length cmds being enqueued. To fix, this patch: 1) Makes the SME cmd queue length, 3 times the max STA. 2) Because of increased SME cmds, the allocation for all cmds together will fail, hence allocate each SME cmd individually and free them accordingly. Change-Id: Ia1dfc5b00eacd9bdb503ce18927c62f1edd15320 CRs-Fixed: 928840 --- core/sme/inc/sme_inside.h | 8 +++-- core/sme/inc/sme_internal.h | 3 +- core/sme/src/common/sme_api.c | 64 +++++++++++++++++++++++++++-------- 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/core/sme/inc/sme_inside.h b/core/sme/inc/sme_inside.h index e1db6a871d..1d5f28bdea 100644 --- a/core/sme/inc/sme_inside.h +++ b/core/sme/inc/sme_inside.h @@ -59,8 +59,12 @@ ePhyChanBondState csr_convert_cb_ini_value_to_phy_cb_state(uint32_t cbIniValue); /*-------------------------------------------------------------------------- Type declarations ------------------------------------------------------------------------*/ - -#define SME_TOTAL_COMMAND 40 +/* + * In case MAX num of STA are connected to SAP, switching off SAP causes + * two SME cmd to be enqueued for each STA. Keeping SME total cmds as following + * to make sure we have space for these cmds + some additional cmds. + */ +#define SME_TOTAL_COMMAND (HAL_NUM_STA * 3) typedef struct sGenericPmcCmd { uint32_t size; /* sizeof the data in the union, if any */ diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index adc01cbd96..eb1915f10f 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -143,7 +143,8 @@ typedef struct tagSmeStruct { eSmeState state; cdf_mutex_t lkSmeGlobalLock; uint32_t totalSmeCmd; - void *pSmeCmdBufAddr; + /* following pointer contains array of pointers for tSmeCmd* */ + void **pSmeCmdBufAddr; tDblLinkList smeCmdActiveList; tDblLinkList smeCmdPendingList; tDblLinkList smeCmdFreeList; /* preallocated roam cmd list */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index e1651637af..b0337adde4 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -286,6 +286,27 @@ static CDF_STATUS sme_process_hw_mode_trans_ind(tpAniSirGlobal mac, return CDF_STATUS_SUCCESS; } +/** + * free_sme_cmds() - This function frees memory allocated for SME commands + * @mac_ctx: Pointer to Global MAC structure + * + * This function frees memory allocated for SME commands + * + * @Return: void + */ +static void free_sme_cmds(tpAniSirGlobal mac_ctx) +{ + uint32_t idx; + if (NULL == mac_ctx->sme.pSmeCmdBufAddr) + return; + + for (idx = 0; idx < mac_ctx->sme.totalSmeCmd; idx++) + cdf_mem_free(mac_ctx->sme.pSmeCmdBufAddr[idx]); + + cdf_mem_free(mac_ctx->sme.pSmeCmdBufAddr); + mac_ctx->sme.pSmeCmdBufAddr = NULL; +} + static CDF_STATUS init_sme_cmd_list(tpAniSirGlobal pMac) { CDF_STATUS status; @@ -293,6 +314,7 @@ static CDF_STATUS init_sme_cmd_list(tpAniSirGlobal pMac) uint32_t cmd_idx; CDF_STATUS cdf_status; cdf_mc_timer_t *cmdTimeoutTimer = NULL; + uint32_t sme_cmd_ptr_ary_sz; pMac->sme.totalSmeCmd = SME_TOTAL_COMMAND; @@ -316,19 +338,36 @@ static CDF_STATUS init_sme_cmd_list(tpAniSirGlobal pMac) if (!CDF_IS_STATUS_SUCCESS(status)) goto end; - pCmd = cdf_mem_malloc(sizeof(tSmeCmd) * pMac->sme.totalSmeCmd); - if (NULL == pCmd) + /* following pointer contains array of pointers for tSmeCmd* */ + sme_cmd_ptr_ary_sz = sizeof(void *) * pMac->sme.totalSmeCmd; + pMac->sme.pSmeCmdBufAddr = cdf_mem_malloc(sme_cmd_ptr_ary_sz); + if (NULL == pMac->sme.pSmeCmdBufAddr) { status = CDF_STATUS_E_NOMEM; - else { - status = CDF_STATUS_SUCCESS; + goto end; + } - cdf_mem_set(pCmd, sizeof(tSmeCmd) * pMac->sme.totalSmeCmd, 0); - pMac->sme.pSmeCmdBufAddr = pCmd; - - for (cmd_idx = 0; cmd_idx < pMac->sme.totalSmeCmd; cmd_idx++) { - csr_ll_insert_tail(&pMac->sme.smeCmdFreeList, - &pCmd[cmd_idx].Link, LL_ACCESS_LOCK); + status = CDF_STATUS_SUCCESS; + cdf_mem_set(pMac->sme.pSmeCmdBufAddr, sme_cmd_ptr_ary_sz, 0); + for (cmd_idx = 0; cmd_idx < pMac->sme.totalSmeCmd; cmd_idx++) { + /* + * Since total size of all commands together can be huge chunk + * of memory, allocate SME cmd individually. These SME CMDs are + * moved between pending and active queues. And these freeing of + * these queues just manipulates the list but does not actually + * frees SME CMD pointers. Hence store each SME CMD address in + * the array, sme.pSmeCmdBufAddr. This will later facilitate + * freeing up of all SME CMDs with just a for loop. + */ + pMac->sme.pSmeCmdBufAddr[cmd_idx] = + cdf_mem_malloc(sizeof(tSmeCmd)); + if (NULL == pMac->sme.pSmeCmdBufAddr[cmd_idx]) { + status = CDF_STATUS_E_NOMEM; + free_sme_cmds(pMac); + goto end; } + pCmd = (tSmeCmd *)pMac->sme.pSmeCmdBufAddr[cmd_idx]; + csr_ll_insert_tail(&pMac->sme.smeCmdFreeList, + &pCmd->Link, LL_ACCESS_LOCK); } /* This timer is only to debug the active list command timeout */ @@ -449,10 +488,7 @@ static CDF_STATUS free_sme_cmd_list(tpAniSirGlobal pMac) goto done; } - if (NULL != pMac->sme.pSmeCmdBufAddr) { - cdf_mem_free(pMac->sme.pSmeCmdBufAddr); - pMac->sme.pSmeCmdBufAddr = NULL; - } + free_sme_cmds(pMac); status = cdf_mutex_release(&pMac->sme.lkSmeGlobalLock); if (status != CDF_STATUS_SUCCESS) {