From 15da8a56d79de47536975b68136d7c22a8080ada Mon Sep 17 00:00:00 2001 From: Jinwei Chen Date: Tue, 22 May 2018 16:12:10 +0800 Subject: [PATCH] qcacmn: fix tx desc allocate from freed pool issue The avail_desc is not set to 0 when the tx desc pool is freed, later if still try to allocate tx desc by judgement of avail_desc, panic happens. Change-Id: Ia4565da1caa6898c6d4293e2658cf4ccf89563fa CRs-Fixed: 2246328 --- dp/wifi3.0/dp_tx_desc.c | 1 + dp/wifi3.0/dp_tx_desc.h | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/dp/wifi3.0/dp_tx_desc.c b/dp/wifi3.0/dp_tx_desc.c index 4c86296b3c59..8ae706525446 100644 --- a/dp/wifi3.0/dp_tx_desc.c +++ b/dp/wifi3.0/dp_tx_desc.c @@ -166,6 +166,7 @@ QDF_STATUS dp_tx_desc_pool_free(struct dp_soc *soc, uint8_t pool_id) qdf_mem_multi_pages_free(soc->osdev, &tx_desc_pool->desc_pages, 0, true); TX_DESC_LOCK_DESTROY(&tx_desc_pool->lock); + TX_DESC_POOL_MEMBER_CLEAN(tx_desc_pool); return QDF_STATUS_SUCCESS; } diff --git a/dp/wifi3.0/dp_tx_desc.h b/dp/wifi3.0/dp_tx_desc.h index 038a325b8cce..9d7c0a1d5d5c 100644 --- a/dp/wifi3.0/dp_tx_desc.h +++ b/dp/wifi3.0/dp_tx_desc.h @@ -56,11 +56,29 @@ #define TX_DESC_LOCK_DESTROY(lock) #define TX_DESC_LOCK_LOCK(lock) #define TX_DESC_LOCK_UNLOCK(lock) +#define TX_DESC_POOL_MEMBER_CLEAN(_tx_desc_pool) \ +do { \ + (_tx_desc_pool)->elem_size = 0; \ + (_tx_desc_pool)->freelist = NULL; \ + (_tx_desc_pool)->pool_size = 0; \ + (_tx_desc_pool)->avail_desc = 0; \ + (_tx_desc_pool)->start_th = 0; \ + (_tx_desc_pool)->stop_th = 0; \ + (_tx_desc_pool)->status = FLOW_POOL_INACTIVE; \ +} while (0) #else /* !QCA_LL_TX_FLOW_CONTROL_V2 */ #define TX_DESC_LOCK_CREATE(lock) qdf_spinlock_create(lock) #define TX_DESC_LOCK_DESTROY(lock) qdf_spinlock_destroy(lock) #define TX_DESC_LOCK_LOCK(lock) qdf_spin_lock_bh(lock) #define TX_DESC_LOCK_UNLOCK(lock) qdf_spin_unlock_bh(lock) +#define TX_DESC_POOL_MEMBER_CLEAN(_tx_desc_pool) \ +do { \ + (_tx_desc_pool)->elem_size = 0; \ + (_tx_desc_pool)->num_allocated = 0; \ + (_tx_desc_pool)->freelist = NULL; \ + (_tx_desc_pool)->elem_count = 0; \ + (_tx_desc_pool)->num_free = 0; \ +} while (0) #endif /* !QCA_LL_TX_FLOW_CONTROL_V2 */ #define MAX_POOL_BUFF_COUNT 10000 @@ -149,7 +167,8 @@ dp_tx_desc_alloc(struct dp_soc *soc, uint8_t desc_pool_id) if (pool) { qdf_spin_lock_bh(&pool->flow_pool_lock); - if (pool->avail_desc) { + if (pool->status <= FLOW_POOL_ACTIVE_PAUSED && + pool->avail_desc) { tx_desc = dp_tx_get_desc_flow_pool(pool); tx_desc->pool_id = desc_pool_id; tx_desc->flags = DP_TX_DESC_FLAG_ALLOCATED; @@ -205,7 +224,6 @@ dp_tx_desc_free(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc, case FLOW_POOL_INVALID: if (pool->avail_desc == pool->pool_size) { dp_tx_desc_pool_free(soc, desc_pool_id); - pool->status = FLOW_POOL_INACTIVE; qdf_spin_unlock_bh(&pool->flow_pool_lock); qdf_print("%s %d pool is freed!!\n", __func__, __LINE__);