summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRajeev Kumar <rajekuma@qca.qualcomm.com>2014-02-13 13:15:53 -0800
committerAkash Patel <c_akashp@qca.qualcomm.com>2014-02-18 01:00:26 -0800
commit151dc450ed91a71e28e3efa8efbd1a2d5e47af6e (patch)
treeb2a5c3de96923f0603dc823bdd0c2aff3a15c065
parentc5c8601e08b476f4aedb298bd14033baa32288d3 (diff)
qcacld: Fix of double free panic caused by vdev detach event
vdev detach event timeout is started in atomic context and when its freed usig vos_mem_free() SLUB debug enabled driver complains about double free and calls panic. To fix this issue allow memory allocation in vos_mem_malloc_debug() using GFP_KERNEL and still maintain meta info for timer/memory management. Change-Id: Id172413a53deba23f4034568505c198aa09b0839 CRs-Fixed: 615743
-rw-r--r--CORE/VOSS/src/vos_memory.c30
1 files changed, 14 insertions, 16 deletions
diff --git a/CORE/VOSS/src/vos_memory.c b/CORE/VOSS/src/vos_memory.c
index 00fb555922b9..9b531f2eec5f 100644
--- a/CORE/VOSS/src/vos_memory.c
+++ b/CORE/VOSS/src/vos_memory.c
@@ -179,6 +179,9 @@ v_VOID_t * vos_mem_malloc_debug( v_SIZE_t size, char* fileName, v_U32_t lineNum)
struct s_vos_mem_struct* memStruct;
v_VOID_t* memPtr = NULL;
v_SIZE_t new_size;
+ int flags = GFP_KERNEL;
+ unsigned long IrqFlags;
+
if (size > (1024*1024))
{
@@ -189,14 +192,12 @@ v_VOID_t * vos_mem_malloc_debug( v_SIZE_t size, char* fileName, v_U32_t lineNum)
if (in_interrupt())
{
- VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s is being"
- "called from interrupt context, using GPF_ATOMIC.", __func__);
- return kmalloc(size, GFP_ATOMIC);
+ flags = GFP_ATOMIC;
}
new_size = size + sizeof(struct s_vos_mem_struct) + 8;
- memStruct = (struct s_vos_mem_struct*)kmalloc(new_size,GFP_KERNEL);
+ memStruct = (struct s_vos_mem_struct*)kmalloc(new_size, flags);
if(memStruct != NULL)
{
@@ -209,9 +210,9 @@ v_VOID_t * vos_mem_malloc_debug( v_SIZE_t size, char* fileName, v_U32_t lineNum)
vos_mem_copy(&memStruct->header[0], &WLAN_MEM_HEADER[0], sizeof(WLAN_MEM_HEADER));
vos_mem_copy( (v_U8_t*)(memStruct + 1) + size, &WLAN_MEM_TAIL[0], sizeof(WLAN_MEM_TAIL));
- spin_lock(&vosMemList.lock);
+ spin_lock_irqsave(&vosMemList.lock, IrqFlags);
vosStatus = hdd_list_insert_front(&vosMemList, &memStruct->pNode);
- spin_unlock(&vosMemList.lock);
+ spin_unlock_irqrestore(&vosMemList.lock, IrqFlags);
if(VOS_STATUS_SUCCESS != vosStatus)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
@@ -225,14 +226,16 @@ v_VOID_t * vos_mem_malloc_debug( v_SIZE_t size, char* fileName, v_U32_t lineNum)
v_VOID_t vos_mem_free( v_VOID_t *ptr )
{
+ unsigned long IrqFlags;
+
if (ptr != NULL)
{
VOS_STATUS vosStatus;
struct s_vos_mem_struct* memStruct = ((struct s_vos_mem_struct*)ptr) - 1;
- spin_lock(&vosMemList.lock);
+ spin_lock_irqsave(&vosMemList.lock, IrqFlags);
vosStatus = hdd_list_remove_node(&vosMemList, &memStruct->pNode);
- spin_unlock(&vosMemList.lock);
+ spin_unlock_irqrestore(&vosMemList.lock, IrqFlags);
if(VOS_STATUS_SUCCESS == vosStatus)
{
@@ -261,6 +264,7 @@ v_VOID_t vos_mem_free( v_VOID_t *ptr )
#else
v_VOID_t * vos_mem_malloc( v_SIZE_t size )
{
+ int flags = GFP_KERNEL;
#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC
v_VOID_t* pmem;
#endif
@@ -271,8 +275,7 @@ v_VOID_t * vos_mem_malloc( v_SIZE_t size )
}
if (in_interrupt())
{
- VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s cannot be called from interrupt context!!!", __func__);
- return NULL;
+ flags = GFP_ATOMIC;
}
#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC
if(size > WCNSS_PRE_ALLOC_GET_THRESHOLD)
@@ -282,7 +285,7 @@ v_VOID_t * vos_mem_malloc( v_SIZE_t size )
return pmem;
}
#endif
- return kmalloc(size, GFP_KERNEL);
+ return kmalloc(size, flags);
}
v_VOID_t vos_mem_free( v_VOID_t *ptr )
@@ -290,11 +293,6 @@ v_VOID_t vos_mem_free( v_VOID_t *ptr )
if (ptr == NULL)
return;
- if (in_interrupt())
- {
- VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s cannot be called from interrupt context!!!", __func__);
- return;
- }
#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC
if(wcnss_prealloc_put(ptr))
return;