qcacmn: Add reduction limit to qdf_flex_mem
Add the ability to prevent qdf_flex_mem_pool from freeing memory segments unless there are more than some minimum number in the pool already. Change-Id: I20bde2ed629b97924ea71b4f7f46a2c1fc1bab28 CRs-Fixed: 2229511
This commit is contained in:
@@ -45,6 +45,7 @@ linux/src/qdf_perf.o \
|
||||
linux/src/qdf_threads.o \
|
||||
linux/src/qdf_trace.o \
|
||||
linux/src/qdf_file.o \
|
||||
src/qdf_flex_mem.o \
|
||||
src/qdf_parse.o \
|
||||
src/qdf_str.o \
|
||||
src/qdf_types.o
|
||||
|
@@ -44,11 +44,13 @@
|
||||
* qdf_flex_mem_pool - a pool of memory segments
|
||||
* @seg_list: the list containing the memory segments
|
||||
* @lock: spinlock for protecting internal data structures
|
||||
* @reduction_limit: the minimum number of segments to keep during reduction
|
||||
* @item_size: the size of the items the pool will allocate
|
||||
*/
|
||||
struct qdf_flex_mem_pool {
|
||||
qdf_list_t seg_list;
|
||||
struct qdf_spinlock lock;
|
||||
uint16_t reduction_limit;
|
||||
uint16_t item_size;
|
||||
};
|
||||
|
||||
@@ -70,8 +72,9 @@ struct qdf_flex_mem_segment {
|
||||
* DEFINE_QDF_FLEX_MEM_POOL() - define a new flex mem pool with one segment
|
||||
* @name: the name of the pool variable
|
||||
* @size_of_item: size of the items the pool will allocate
|
||||
* @rm_limit: min number of segments to keep during reduction
|
||||
*/
|
||||
#define DEFINE_QDF_FLEX_MEM_POOL(name, size_of_item) \
|
||||
#define DEFINE_QDF_FLEX_MEM_POOL(name, size_of_item, rm_limit) \
|
||||
struct qdf_flex_mem_pool name; \
|
||||
uint8_t __ ## name ## _head_bytes[QDF_FM_BITMAP_BITS * (size_of_item)];\
|
||||
struct qdf_flex_mem_segment __ ## name ## _head = { \
|
||||
@@ -81,6 +84,7 @@ struct qdf_flex_mem_segment {
|
||||
}; \
|
||||
struct qdf_flex_mem_pool name = { \
|
||||
.seg_list = QDF_LIST_INIT_SINGLE(__ ## name ## _head.node), \
|
||||
.reduction_limit = (rm_limit), \
|
||||
.item_size = (size_of_item), \
|
||||
}
|
||||
|
||||
@@ -126,4 +130,14 @@ void *qdf_flex_mem_alloc(struct qdf_flex_mem_pool *pool);
|
||||
*/
|
||||
void qdf_flex_mem_free(struct qdf_flex_mem_pool *pool, void *ptr);
|
||||
|
||||
/**
|
||||
* qdf_flex_mem_release() - release unused segments
|
||||
* @pool: the pool to operate against
|
||||
*
|
||||
* This function physically releases as much unused pool memory as possible.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void qdf_flex_mem_release(struct qdf_flex_mem_pool *pool);
|
||||
|
||||
#endif /* __QDF_FLEX_MEM_H */
|
||||
|
@@ -109,6 +109,9 @@ static inline void qdf_list_create(__qdf_list_t *list, uint32_t max_size)
|
||||
#define qdf_list_for_each(list_ptr, cursor, node_field) \
|
||||
__qdf_list_for_each(list_ptr, cursor, node_field)
|
||||
|
||||
#define qdf_list_for_each_del(list_ptr, cursor, next, node_field) \
|
||||
__qdf_list_for_each_del(list_ptr, cursor, next, node_field)
|
||||
|
||||
/**
|
||||
* qdf_init_list_head() - initialize list head
|
||||
* @list_head: pointer to list head
|
||||
|
@@ -79,6 +79,9 @@ static inline void __qdf_list_create(__qdf_list_t *list, uint32_t max_size)
|
||||
#define __qdf_list_for_each(list_ptr, cursor, node_field) \
|
||||
list_for_each_entry(cursor, &(list_ptr)->anchor, node_field)
|
||||
|
||||
#define __qdf_list_for_each_del(list_ptr, cursor, next, node_field) \
|
||||
list_for_each_entry_safe(cursor, next, &(list_ptr)->anchor, node_field)
|
||||
|
||||
/**
|
||||
* __qdf_init_list_head() - initialize list head
|
||||
* @list_head: pointer to list head
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include "qdf_list.h"
|
||||
#include "qdf_lock.h"
|
||||
#include "qdf_mem.h"
|
||||
#include "qdf_module.h"
|
||||
#include "qdf_trace.h"
|
||||
#include "qdf_util.h"
|
||||
|
||||
@@ -27,17 +28,20 @@ void qdf_flex_mem_init(struct qdf_flex_mem_pool *pool)
|
||||
{
|
||||
qdf_spinlock_create(&pool->lock);
|
||||
}
|
||||
qdf_export_symbol(qdf_flex_mem_init);
|
||||
|
||||
void qdf_flex_mem_deinit(struct qdf_flex_mem_pool *pool)
|
||||
{
|
||||
qdf_spinlock_destroy(&pool->lock);
|
||||
}
|
||||
qdf_export_symbol(qdf_flex_mem_deinit);
|
||||
|
||||
static struct qdf_flex_mem_segment *qdf_flex_mem_seg_alloc(uint16_t item_size)
|
||||
static struct qdf_flex_mem_segment *
|
||||
qdf_flex_mem_seg_alloc(struct qdf_flex_mem_pool *pool)
|
||||
{
|
||||
size_t bytes_size = item_size * QDF_FM_BITMAP_BITS;
|
||||
size_t total_size = sizeof(struct qdf_flex_mem_segment) + bytes_size;
|
||||
struct qdf_flex_mem_segment *seg;
|
||||
size_t total_size = sizeof(struct qdf_flex_mem_segment) +
|
||||
pool->item_size * QDF_FM_BITMAP_BITS;
|
||||
|
||||
seg = qdf_mem_malloc(total_size);
|
||||
if (!seg)
|
||||
@@ -70,7 +74,7 @@ static void *__qdf_flex_mem_alloc(struct qdf_flex_mem_pool *pool)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
seg = qdf_flex_mem_seg_alloc(pool->item_size);
|
||||
seg = qdf_flex_mem_seg_alloc(pool);
|
||||
if (!seg)
|
||||
return NULL;
|
||||
|
||||
@@ -94,10 +98,18 @@ void *qdf_flex_mem_alloc(struct qdf_flex_mem_pool *pool)
|
||||
|
||||
return ptr;
|
||||
}
|
||||
qdf_export_symbol(qdf_flex_mem_alloc);
|
||||
|
||||
static void qdf_flex_mem_seg_free(struct qdf_flex_mem_pool *pool,
|
||||
struct qdf_flex_mem_segment *seg)
|
||||
{
|
||||
if (!seg->dynamic)
|
||||
return;
|
||||
|
||||
if (qdf_list_size(&pool->seg_list) <= pool->reduction_limit)
|
||||
return;
|
||||
|
||||
|
||||
qdf_list_remove_node(&pool->seg_list, &seg->node);
|
||||
qdf_mem_free(seg);
|
||||
}
|
||||
@@ -120,7 +132,7 @@ static void __qdf_flex_mem_free(struct qdf_flex_mem_pool *pool, void *ptr)
|
||||
QDF_BUG(index < QDF_FM_BITMAP_BITS);
|
||||
|
||||
seg->used_bitmap ^= (QDF_FM_BITMAP)1 << index;
|
||||
if (!seg->used_bitmap && seg->dynamic)
|
||||
if (!seg->used_bitmap)
|
||||
qdf_flex_mem_seg_free(pool, seg);
|
||||
|
||||
return;
|
||||
@@ -144,4 +156,33 @@ void qdf_flex_mem_free(struct qdf_flex_mem_pool *pool, void *ptr)
|
||||
__qdf_flex_mem_free(pool, ptr);
|
||||
qdf_spin_unlock_bh(&pool->lock);
|
||||
}
|
||||
qdf_export_symbol(qdf_flex_mem_free);
|
||||
|
||||
static void __qdf_flex_mem_release(struct qdf_flex_mem_pool *pool)
|
||||
{
|
||||
struct qdf_flex_mem_segment *seg;
|
||||
struct qdf_flex_mem_segment *next;
|
||||
|
||||
qdf_list_for_each_del(&pool->seg_list, seg, next, node) {
|
||||
if (!seg->dynamic)
|
||||
continue;
|
||||
|
||||
if (seg->used_bitmap != 0)
|
||||
continue;
|
||||
|
||||
qdf_list_remove_node(&pool->seg_list, &seg->node);
|
||||
qdf_mem_free(seg);
|
||||
}
|
||||
}
|
||||
|
||||
void qdf_flex_mem_release(struct qdf_flex_mem_pool *pool)
|
||||
{
|
||||
QDF_BUG(pool);
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
qdf_spin_lock_bh(&pool->lock);
|
||||
__qdf_flex_mem_release(pool);
|
||||
qdf_spin_unlock_bh(&pool->lock);
|
||||
}
|
||||
qdf_export_symbol(qdf_flex_mem_release);
|
||||
|
Reference in New Issue
Block a user