Commit c4d59b86 authored by Jayan John's avatar Jayan John Committed by Hari Kanigeri

SYSLINK Heapbuf aligned with IPC 50 and Syslink 2_00_00_08 changes

This patch aligns heapbuf code with IPC 50 and Syslink 2_00_00_08 changes.
Signed-off-by: default avatarJayan John <x00jayan@ti.com>
parent 7bf9e881
...@@ -23,6 +23,12 @@ ...@@ -23,6 +23,12 @@
#include <heap.h> #include <heap.h>
#include <listmp.h> #include <listmp.h>
/*!
* @def LISTMP_MODULEID
* @brief Unique module ID.
*/
#define HEAPBUF_MODULEID (0x4cd5)
/* /*
* Creation of Heap Buf succesful. * Creation of Heap Buf succesful.
*/ */
...@@ -34,28 +40,52 @@ ...@@ -34,28 +40,52 @@
#define HEAPBUF_VERSION (1) #define HEAPBUF_VERSION (1)
/* /*
* Structure defining parameters for the Heap Buf module * Structure defining config parameters for the HeapBuf module.
*/
struct heapbuf_config {
u32 max_name_len; /* Maximum length of name */
bool use_nameserver; /* To have this module use the NameServer or not */
bool track_max_allocs; /* Track the maximum number of allocated blocks */
};
/*
* Structure defining parameters for the HeapBuf module
*/ */
struct heapbuf_params { struct heapbuf_params {
void *lock_handle; void *gate;
bool exact; /* Only allocate on exact match of rquested size */ bool exact; /* Only allocate on exact match of rquested size */
char *name; /* Name when using nameserver */ char *name; /* Name when using nameserver */
int resource_id; /* Resource id of the hardware linked list */
bool cache_flag; /* Whether to perform cache coherency calls */
u32 align; /* Alignment (in MAUs, power of 2) of each block */ u32 align; /* Alignment (in MAUs, power of 2) of each block */
u32 num_blocks; /* Number of fixed-size blocks */ u32 num_blocks; /* Number of fixed-size blocks */
u32 block_size; /* Size (in MAUs) of each block*/ u32 block_size; /* Size (in MAUs) of each block*/
void *shared_addr; /* Physical address of the shared memory */ void *shared_addr; /* Physical address of the shared memory */
u32 shared_addr_size; /* Size of shareAddr */ u32 shared_addr_size; /* Size of shareAddr */
void *shared_buf; /* Physical address of the shared buffers */
u32 shared_buf_size; /* Size of sharedBuf */
};
/*
* Stats structure for the getExtendedStats API.
*/
struct heapbuf_extended_stats {
u32 max_allocated_blocks;
/* maximum number of blocks allocated from this heap instance */
u32 num_allocated_blocks;
/* total number of blocks currently allocated from this heap instance*/
}; };
/* /*
* Function to get default configuration for the heapbuf module * Function to get default configuration for the heapbuf module
*/ */
int heapbuf_get_config(struct heap_config *cfgparams); int heapbuf_get_config(struct heapbuf_config *cfgparams);
/* /*
* Function to setup the heapbuf module * Function to setup the heapbuf module
*/ */
int heapbuf_setup(const struct heap_config *config); int heapbuf_setup(const struct heapbuf_config *cfg);
/* /*
* Function to destroy the heapbuf module * Function to destroy the heapbuf module
...@@ -75,42 +105,48 @@ void *heapbuf_create(const struct heapbuf_params *params); ...@@ -75,42 +105,48 @@ void *heapbuf_create(const struct heapbuf_params *params);
/* /*
* Deletes a instance of heapbuf module * Deletes a instance of heapbuf module
*/ */
int heapbuf_delete(void **handle); int heapbuf_delete(void **handle_ptr);
/* /*
* Opens a created instance of heapbuf module * Opens a created instance of heapbuf module
*/ */
int heapbuf_open(void **handle, const struct heapbuf_params *params); int heapbuf_open(void **handle_ptr, struct heapbuf_params *params);
/* /*
* Closes previously opened/created instance of heapbuf module * Closes previously opened/created instance of heapbuf module
*/ */
int heapbuf_close(void *handle); int heapbuf_close(void *handle_ptr);
/* /*
* Returns the amount of shared memory required for creation * Returns the amount of shared memory required for creation
* of each instance * of each instance
*/ */
int heapbuf_shared_memreq(const struct heapbuf_params *params); int heapbuf_shared_memreq(const struct heapbuf_params *params, u32 *buf_size);
/* /*
* Allocate a block * Allocate a block
*/ */
void *heapbuf_alloc(void *handle, u32 size, u32 align); void *heapbuf_alloc(void *hphandle, u32 size, u32 align);
/* /*
* Frees the block to this heapbuf * Frees the block to this heapbuf
*/ */
int heapbuf_free(void *handle, void *block, u32 size); int heapbuf_free(void *hphandle, void *block, u32 size);
/* /*
* Get memory statistics * Get memory statistics
*/ */
int heapbuf_get_stats(void *handle, struct memory_stats *stats); int heapbuf_get_stats(void *hphandle, struct memory_stats *stats);
/*
* Indicate whether the heap may block during an alloc or free call
*/
bool heapbuf_isblocking(void *handle);
/* /*
* Get extended statistics * Get extended statistics
*/ */
int heapbuf_get_extended_stats(void *handle, struct heap_extended_stats *stats); int heapbuf_get_extended_stats(void *hphandle,
#endif /* _HEAPBUF_H_ */ struct heapbuf_extended_stats *stats);
#endif /* _HEAPBUF_H_ */
...@@ -135,11 +135,11 @@ union heapbuf_arg { ...@@ -135,11 +135,11 @@ union heapbuf_arg {
} params_init; } params_init;
struct { struct {
struct heap_config *config; struct heapbuf_config *config;
} get_config; } get_config;
struct { struct {
struct heap_config *config; struct heapbuf_config *config;
} setup; } setup;
struct { struct {
...@@ -182,12 +182,13 @@ union heapbuf_arg { ...@@ -182,12 +182,13 @@ union heapbuf_arg {
struct { struct {
void *handle; void *handle;
struct heap_extended_stats *stats; struct heapbuf_extended_stats *stats;
} get_extended_stats; } get_extended_stats;
struct { struct {
void *handle; void *handle;
struct heapbuf_params *params; struct heapbuf_params *params;
u32 buf_size;
u32 bytes; u32 bytes;
} shared_memreq; } shared_memreq;
}; };
......
/* /*
* heapbuf.h * heapbuf.c
* *
* Heap module manages fixed size buffers that can be used * Heap module manages fixed size buffers that can be used
* in a multiprocessor system with shared memory. * in a multiprocessor system with shared memory.
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <gt.h> #include <gt.h>
#include <atomic_linux.h>
#include <multiproc.h> #include <multiproc.h>
#include <nameserver.h> #include <nameserver.h>
#include <sharedregion.h> #include <sharedregion.h>
...@@ -31,26 +32,28 @@ ...@@ -31,26 +32,28 @@
#include <listmp.h> #include <listmp.h>
#include <listmp_sharedmemory.h> #include <listmp_sharedmemory.h>
/* /*
* Name of the reserved nameserver used for heapbuf. * Name of the reserved nameserver used for heapbuf.
*/ */
#define HEAPBUF_NAMESERVER "HeapBuf" #define HEAPBUF_NAMESERVER "HeapBuf"
#define HEAPBUF_MAX_NAME_LEN 32 #define HEAPBUF_MAX_NAME_LEN 32
#define HEAPBUF_CACHESIZE 128 #define HEAPBUF_CACHESIZE 128
/* brief Macro to make a correct module magic number with refCount */
#define HEAPBUF_MAKE_MAGICSTAMP(x) ((HEAPBUF_MODULEID << 12) | (x))
/* /*
* Structure defining attribute parameters for the heapbuf module * Structure defining attribute parameters for the heapbuf module
*/ */
struct heapbuf_attrs { struct heapbuf_attrs {
u32 version; volatile u32 version;
u32 status; volatile u32 status;
u32 num_free_blocks; volatile u32 num_free_blocks;
u32 min_free_blocks; volatile u32 min_free_blocks;
u32 block_size; volatile u32 block_size;
u32 align; volatile u32 align;
u32 num_blocks; volatile u32 num_blocks;
char *buf; volatile u32 buf_size;
volatile char *buf;
}; };
/* /*
...@@ -67,30 +70,35 @@ struct heapbuf_proc_attrs { ...@@ -67,30 +70,35 @@ struct heapbuf_proc_attrs {
* Structure for heapbuf module state * Structure for heapbuf module state
*/ */
struct heapbuf_module_object { struct heapbuf_module_object {
atomic_t ref_count; /* Reference count */
void *ns_handle;
struct list_head obj_list; /* List holding created objects */ struct list_head obj_list; /* List holding created objects */
void *nshandle; struct mutex *local_lock; /* lock for protecting obj_list */
struct mutex *list_lock; /* lock for protecting obj_list */ struct heapbuf_config cfg;
struct heap_config cfg; struct heapbuf_config default_cfg; /* Default config values */
struct heap_config defaultcfg; /* Default config values */
struct heapbuf_params default_inst_params; /* Default instance struct heapbuf_params default_inst_params; /* Default instance
creation parameters */ creation parameters */
}; };
struct heapbuf_module_object heapbuf_state = { struct heapbuf_module_object heapbuf_state = {
.obj_list = LIST_HEAD_INIT(heapbuf_state.obj_list), .obj_list = LIST_HEAD_INIT(heapbuf_state.obj_list),
.defaultcfg.max_name_len = HEAPBUF_MAX_NAME_LEN, .default_cfg.max_name_len = HEAPBUF_MAX_NAME_LEN,
.defaultcfg.track_max_allocs = false, .default_cfg.use_nameserver = true,
.default_inst_params.lock_handle = NULL, .default_cfg.track_max_allocs = false,
.default_inst_params.gate = NULL,
.default_inst_params.exact = false, .default_inst_params.exact = false,
.default_inst_params.name = NULL, .default_inst_params.name = NULL,
.default_inst_params.resource_id = 0,
.default_inst_params.cache_flag = false,
.default_inst_params.align = 1, .default_inst_params.align = 1,
.default_inst_params.num_blocks = 0, .default_inst_params.num_blocks = 0,
.default_inst_params.block_size = 0, .default_inst_params.block_size = 0,
.default_inst_params.shared_addr = NULL, .default_inst_params.shared_addr = NULL,
.default_inst_params.shared_addr_size = 0 .default_inst_params.shared_addr_size = 0,
.default_inst_params.shared_buf = NULL,
.default_inst_params.shared_buf_size = 0
}; };
/* /*
* Structure for the handle for the heapbuf * Structure for the handle for the heapbuf
*/ */
...@@ -99,11 +107,11 @@ struct heapbuf_obj { ...@@ -99,11 +107,11 @@ struct heapbuf_obj {
struct heapbuf_params params; /* The creation parameter structure */ struct heapbuf_params params; /* The creation parameter structure */
struct heapbuf_attrs *attrs; /* The shared attributes structure */ struct heapbuf_attrs *attrs; /* The shared attributes structure */
void *free_list; /* List of free buffers */ void *free_list; /* List of free buffers */
struct mutex *lock_handle; /* Lock used for list */ struct mutex *gate; /* Lock used for critical region management */
void *nskey; /*! nameserver key required for remove */ void *ns_key; /* nameserver key required for remove */
struct heapbuf_proc_attrs *owner; /* owner processor info */ struct heapbuf_proc_attrs owner; /* owner processor info */
struct heapbuf_proc_attrs *remote; /* Remote processor info */ void *top; /* Pointer to the top object */
void *top; bool cacheFlag; /* added for future use */
}; };
/* /*
...@@ -112,16 +120,18 @@ struct heapbuf_obj { ...@@ -112,16 +120,18 @@ struct heapbuf_obj {
* This will get default configuration for the * This will get default configuration for the
* heapbuf module * heapbuf module
*/ */
int heapbuf_get_config(struct heap_config *cfgparams) int heapbuf_get_config(struct heapbuf_config *cfgparams)
{ {
BUG_ON(cfgparams == NULL); BUG_ON(cfgparams == NULL);
if (heapbuf_state.nshandle == NULL) if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
memcpy(cfgparams, &heapbuf_state.defaultcfg, HEAPBUF_MAKE_MAGICSTAMP(0),
sizeof(struct heap_config)); HEAPBUF_MAKE_MAGICSTAMP(1)) == true)
memcpy(cfgparams, &heapbuf_state.default_cfg,
sizeof(struct heapbuf_config));
else else
memcpy(cfgparams, &heapbuf_state.cfg, memcpy(cfgparams, &heapbuf_state.cfg,
sizeof(struct heap_config)); sizeof(struct heapbuf_config));
return 0; return 0;
} }
EXPORT_SYMBOL(heapbuf_get_config); EXPORT_SYMBOL(heapbuf_get_config);
...@@ -130,45 +140,79 @@ EXPORT_SYMBOL(heapbuf_get_config); ...@@ -130,45 +140,79 @@ EXPORT_SYMBOL(heapbuf_get_config);
* ======== heapbuf_setup ======== * ======== heapbuf_setup ========
* Purpose: * Purpose:
* This will setup the heapbuf module * This will setup the heapbuf module
*
* This function sets up the HeapBuf module. This function
* must be called before any other instance-level APIs can be
* invoked.
* Module-level configuration needs to be provided to this
* function. If the user wishes to change some specific config
* parameters, then heapbuf_getconfig can be called to get
* the configuration filled with the default values. After this,
* only the required configuration values can be changed. If the
* user does not wish to make any change in the default parameters,
* the application can simply call HeapBuf_setup with NULL
* parameters. The default parameters would get automatically used.
*/ */
int heapbuf_setup(const struct heap_config *config) int heapbuf_setup(const struct heapbuf_config *cfg)
{ {
struct nameserver_params params; struct nameserver_params params;
void *nshandle = NULL; struct heapbuf_config tmp_cfg;
void *ns_handle = NULL;
s32 retval = 0; s32 retval = 0;
BUG_ON(config == NULL); /* This sets the ref_count variable not initialized, upper 16 bits is
* written with module Id to ensure correctness of ref_count variable
*/
atomic_cmpmask_and_set(&heapbuf_state.ref_count,
HEAPBUF_MAKE_MAGICSTAMP(0),
HEAPBUF_MAKE_MAGICSTAMP(0));
if (atomic_inc_return(&heapbuf_state.ref_count)
!= HEAPBUF_MAKE_MAGICSTAMP(1)) {
retval = -EEXIST;
goto error;
}
if (cfg == NULL) {
heapbuf_get_config(&tmp_cfg);
cfg = &tmp_cfg;
}
if (config->max_name_len == 0 || if (cfg->max_name_len == 0 ||
config->max_name_len > HEAPBUF_MAX_NAME_LEN) { cfg->max_name_len > HEAPBUF_MAX_NAME_LEN) {
retval = -EINVAL; retval = -EINVAL;
goto error; goto error;
} }
heapbuf_state.list_lock = kmalloc(sizeof(struct mutex), GFP_KERNEL); heapbuf_state.local_lock = kmalloc(sizeof(struct mutex), GFP_KERNEL);
if (heapbuf_state.list_lock == NULL) { if (heapbuf_state.local_lock == NULL) {
retval = -ENOMEM; retval = -ENOMEM;
goto error; goto error;
} }
nameserver_params_init(&params); if (likely((cfg->use_nameserver == true))) {
params.max_value_len = sizeof(u32); retval = nameserver_get_params(NULL, &params);
params.max_name_len = config->max_name_len; params.max_value_len = sizeof(u32);
nshandle = nameserver_create(HEAPBUF_NAMESERVER, &params); params.max_name_len = cfg->max_name_len;
if (nshandle == NULL) { ns_handle = nameserver_create(HEAPBUF_NAMESERVER, &params);
retval = -EFAULT; if (ns_handle == NULL) {
goto ns_create_fail; retval = -EFAULT;
goto ns_create_fail;
}
heapbuf_state.ns_handle = ns_handle;
} }
heapbuf_state.nshandle = nshandle; memcpy(&heapbuf_state.cfg, cfg, sizeof(struct heapbuf_config));
memcpy(&heapbuf_state.cfg, config, sizeof(struct heap_config)); mutex_init(heapbuf_state.local_lock);
mutex_init(heapbuf_state.list_lock);
return 0; return 0;
ns_create_fail: ns_create_fail:
kfree(heapbuf_state.list_lock); kfree(heapbuf_state.local_lock);
error: error:
atomic_set(&heapbuf_state.ref_count,
HEAPBUF_MAKE_MAGICSTAMP(0));
printk(KERN_ERR "heapbuf_setup failed status: %x\n", retval); printk(KERN_ERR "heapbuf_setup failed status: %x\n", retval);
return retval; return retval;
} }
...@@ -185,37 +229,56 @@ int heapbuf_destroy(void) ...@@ -185,37 +229,56 @@ int heapbuf_destroy(void)
struct mutex *lock = NULL; struct mutex *lock = NULL;
struct heapbuf_obj *obj = NULL; struct heapbuf_obj *obj = NULL;
if (WARN_ON(heapbuf_state.nshandle == NULL)) { if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
HEAPBUF_MAKE_MAGICSTAMP(0),
HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV; retval = -ENODEV;
goto error; goto error;
} }
/* Check if any heapbuf instances have not been deleted/closed so far. if (atomic_dec_return(&heapbuf_state.ref_count)
* if there any, delete or close them == HEAPBUF_MAKE_MAGICSTAMP(0)) {
*/ /* Temporarily increment ref_count here. */
list_for_each_entry(obj, &heapbuf_state.obj_list, list_elem) { atomic_set(&heapbuf_state.ref_count,
if (obj->owner->proc_id == multiproc_get_id(NULL)) HEAPBUF_MAKE_MAGICSTAMP(1));
heapbuf_delete(&obj->top);
else /* Check if any heapbuf instances have not been deleted/closed
heapbuf_close(obj->top); * so far. if there any, delete or close them
*/
list_for_each_entry(obj, &heapbuf_state.obj_list, list_elem) {
if (obj->owner.proc_id == multiproc_get_id(NULL))
heapbuf_delete(&obj->top);
else
heapbuf_close(obj->top);
if (list_empty(&heapbuf_state.obj_list)) if (list_empty(&heapbuf_state.obj_list))
break; break;
} }
retval = nameserver_delete(&heapbuf_state.nshandle); /* Again reset ref_count. */
if (unlikely(retval != 0)) atomic_set(&heapbuf_state.ref_count,
goto error; HEAPBUF_MAKE_MAGICSTAMP(0));
retval = mutex_lock_interruptible(heapbuf_state.list_lock); if (likely(heapbuf_state.cfg.use_nameserver == true)) {
if (retval) retval = nameserver_delete(&heapbuf_state.ns_handle);
goto error; if (unlikely(retval != 0))
goto error;
}
retval = mutex_lock_interruptible(heapbuf_state.local_lock);
if (retval)
goto error;
lock = heapbuf_state.local_lock;
heapbuf_state.local_lock = NULL;
mutex_unlock(lock);
kfree(lock);
memset(&heapbuf_state.cfg, 0, sizeof(struct heap_config));
atomic_set(&heapbuf_state.ref_count,
HEAPBUF_MAKE_MAGICSTAMP(0));
}
lock = heapbuf_state.list_lock;
heapbuf_state.list_lock = NULL;
mutex_unlock(lock);
kfree(lock);
memset(&heapbuf_state.cfg, 0, sizeof(struct heap_config));
return 0; return 0;
error: error:
...@@ -234,7 +297,14 @@ void heapbuf_params_init(void *handle, ...@@ -234,7 +297,14 @@ void heapbuf_params_init(void *handle,
struct heapbuf_params *params) struct heapbuf_params *params)
{ {
struct heapbuf_obj *obj = NULL; struct heapbuf_obj *obj = NULL;
struct heap_object *object = NULL; s32 retval = 0;
if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
HEAPBUF_MAKE_MAGICSTAMP(0),
HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto error;
}
BUG_ON(params == NULL); BUG_ON(params == NULL);
...@@ -242,10 +312,12 @@ void heapbuf_params_init(void *handle, ...@@ -242,10 +312,12 @@ void heapbuf_params_init(void *handle,
memcpy(params, &heapbuf_state.default_inst_params, memcpy(params, &heapbuf_state.default_inst_params,
sizeof(struct heapbuf_params)); sizeof(struct heapbuf_params));
else { else {
object = (struct heap_object *)handle; obj = (struct heapbuf_obj *)handle;
obj = (struct heapbuf_obj *)object->obj; memcpy(params, (void *)&obj->params,
memcpy(&obj->params, params, sizeof(struct heapbuf_params)); sizeof(struct heapbuf_params));
} }
error:
printk(KERN_ERR "heapbuf_params_init failed status: %x\n", retval);
} }
EXPORT_SYMBOL(heapbuf_params_init); EXPORT_SYMBOL(heapbuf_params_init);
...@@ -260,8 +332,8 @@ EXPORT_SYMBOL(heapbuf_params_init); ...@@ -260,8 +332,8 @@ EXPORT_SYMBOL(heapbuf_params_init);
* used by heapbuf is provided by the consumer of * used by heapbuf is provided by the consumer of
* heapbuf module * heapbuf module
*/ */
static void *_heapbuf_create(const struct heapbuf_params *params, int _heapbuf_create(void **handle_ptr, const struct heapbuf_params *params,
u32 createflag) u32 create_flag)
{ {
struct heap_object *handle = NULL; struct heap_object *handle = NULL;
struct heapbuf_obj *obj = NULL; struct heapbuf_obj *obj = NULL;
...@@ -274,8 +346,22 @@ static void *_heapbuf_create(const struct heapbuf_params *params, ...@@ -274,8 +346,22 @@ static void *_heapbuf_create(const struct heapbuf_params *params,
u32 shared_shmbase; u32 shared_shmbase;
void *entry = NULL; void *entry = NULL;
if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
HEAPBUF_MAKE_MAGICSTAMP(0),
HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto error;
}
BUG_ON(handle_ptr == NULL);
BUG_ON(params == NULL); BUG_ON(params == NULL);
/* No need for parameter checks, since this is an internal function. */
/* Initialize return parameter. */
*handle_ptr = NULL;
handle = kmalloc(sizeof(struct heap_object), GFP_KERNEL); handle = kmalloc(sizeof(struct heap_object), GFP_KERNEL);
if (handle == NULL) { if (handle == NULL) {
retval = -ENOMEM; retval = -ENOMEM;
...@@ -292,19 +378,19 @@ static void *_heapbuf_create(const struct heapbuf_params *params, ...@@ -292,19 +378,19 @@ static void *_heapbuf_create(const struct heapbuf_params *params,
handle->alloc = &heapbuf_alloc; handle->alloc = &heapbuf_alloc;
handle->free = &heapbuf_free; handle->free = &heapbuf_free;
handle->get_stats = &heapbuf_get_stats; handle->get_stats = &heapbuf_get_stats;
handle->get_extended_stats = &heapbuf_get_extended_stats;
/* Create the shared list */ /* Create the shared list */
listmp_sharedmemory_params_init(NULL, &listmp_params); listmp_sharedmemory_params_init(NULL, &listmp_params);
listmp_params.shared_addr = (u32 *)((u32) (params->shared_addr) listmp_params.shared_addr = (u32 *)((u32) (params->shared_addr)
+ HEAPBUF_CACHESIZE); + ((sizeof(struct heapbuf_attrs)
+ (HEAPBUF_CACHESIZE - 1))
& ~(HEAPBUF_CACHESIZE - 1)));
listmp_params.shared_addr_size = listmp_params.shared_addr_size =
listmp_sharedmemory_shared_memreq(&listmp_params); listmp_sharedmemory_shared_memreq(&listmp_params);
listmp_params.lock_handle = params->lock_handle; listmp_params.gate = NULL;
obj->lock_handle = params->lock_handle;
/* Assign the memory with proper cache line padding */ /* Assign the memory with proper cache line padding */
obj->attrs = (struct heapbuf_attrs *) params->shared_addr; obj->attrs = (struct heapbuf_attrs *) params->shared_addr;
if (createflag == false) if (create_flag == false)
listmp_sharedmemory_open(&obj->free_list, &listmp_params); listmp_sharedmemory_open(&obj->free_list, &listmp_params);
else { else {
obj->free_list = listmp_sharedmemory_create(&listmp_params); obj->free_list = listmp_sharedmemory_create(&listmp_params);
...@@ -320,12 +406,12 @@ static void *_heapbuf_create(const struct heapbuf_params *params, ...@@ -320,12 +406,12 @@ static void *_heapbuf_create(const struct heapbuf_params *params,
obj->attrs->block_size = params->block_size; obj->attrs->block_size = params->block_size;
obj->attrs->align = params->align; obj->attrs->align = params->align;
obj->attrs->num_blocks = params->num_blocks; obj->attrs->num_blocks = params->num_blocks;
obj->attrs->buf = (char *)((u32 *)(obj->attrs) + obj->attrs->buf_size = params->shared_buf_size;
HEAPBUF_CACHESIZE + listmp_params.shared_addr_size); buf = params->shared_buf;
buf = obj->attrs->buf;
align = obj->attrs->align; align = obj->attrs->align;
buf = (char *)(((u32)buf + (align - 1)) & ~(align - 1)); buf = (char *)(((u32)buf + (align - 1)) & ~(align - 1));
obj->attrs->buf = buf; obj->attrs->buf = buf;
/* /*
* Split the buffer into blocks that are length * Split the buffer into blocks that are length
* block_size" and add into the free_list Queue * block_size" and add into the free_list Queue
...@@ -338,6 +424,8 @@ static void *_heapbuf_create(const struct heapbuf_params *params, ...@@ -338,6 +424,8 @@ static void *_heapbuf_create(const struct heapbuf_params *params,
} }
} }
obj->gate = params->gate;
/* Populate the params member */ /* Populate the params member */
memcpy(&obj->params, params, sizeof(struct heapbuf_params)); memcpy(&obj->params, params, sizeof(struct heapbuf_params));
if (params->name != NULL) { if (params->name != NULL) {
...@@ -352,40 +440,35 @@ static void *_heapbuf_create(const struct heapbuf_params *params, ...@@ -352,40 +440,35 @@ static void *_heapbuf_create(const struct heapbuf_params *params,
strlen(params->name) + 1); strlen(params->name) + 1);
} }
/* Update processor information */ if (create_flag == true) {
obj->owner = kmalloc(sizeof(struct heapbuf_proc_attrs), GFP_KERNEL); obj->owner.creator = true;
obj->remote = kmalloc(sizeof(struct heapbuf_proc_attrs), GFP_KERNEL); obj->owner.open_count = 1;
if (obj->owner == NULL || obj->remote == NULL) { obj->owner.proc_id = multiproc_get_id(NULL);
retval = -ENOMEM; obj->top = handle;
goto proc_attr_alloc_error; obj->attrs->status = HEAPBUF_CREATED;
}
if (createflag == true) {
obj->remote->creator = false;
obj->remote->open_count = 0;
obj->remote->proc_id = MULTIPROC_INVALIDID;
obj->owner->creator = true;
obj->owner->open_count = 1;
obj->owner->proc_id = multiproc_get_id(NULL);
obj->top = handle;
obj->attrs->status = HEAPBUF_CREATED;
} else { } else {
obj->remote->creator = true; obj->owner.creator = false;
obj->remote->open_count = 1; obj->owner.open_count = 0;
obj->remote->proc_id = MULTIPROC_INVALIDID; obj->owner.proc_id = MULTIPROC_INVALIDID;
obj->owner->creator = false; obj->top = handle;
obj->owner->open_count = 0;
obj->owner->proc_id = multiproc_get_id("SysM3");
obj->top = handle;
} }
if (createflag == true) { retval = mutex_lock_interruptible(heapbuf_state.local_lock);
if (retval)
goto lock_error;
INIT_LIST_HEAD(&obj->list_elem);
list_add_tail(&obj->list_elem, &heapbuf_state.obj_list);
mutex_unlock(heapbuf_state.local_lock);
if ((likely(heapbuf_state.cfg.use_nameserver == true))
&& (create_flag == true)) {
/* We will store a shared pointer in the nameserver */ /* We will store a shared pointer in the nameserver */
shmindex = sharedregion_get_index(params->shared_addr); shmindex = sharedregion_get_index(params->shared_addr);
shared_shmbase = (u32)sharedregion_get_srptr( shared_shmbase = (u32)sharedregion_get_srptr(
params->shared_addr, shmindex); params->shared_addr, shmindex);
if (obj->params.name != NULL) { if (obj->params.name != NULL) {
entry = nameserver_add_uint32(heapbuf_state.nshandle, entry = nameserver_add_uint32(heapbuf_state.ns_handle,
params->name, params->name,
(u32)(shared_shmbase)); (u32)(shared_shmbase));
if (entry == NULL) { if (entry == NULL) {
...@@ -395,24 +478,32 @@ static void *_heapbuf_create(const struct heapbuf_params *params, ...@@ -395,24 +478,32 @@ static void *_heapbuf_create(const struct heapbuf_params *params,
} }
} }
retval = mutex_lock_interruptible(heapbuf_state.list_lock); *handle_ptr = (void *)handle;
if (retval) return retval;
goto lock_error;
INIT_LIST_HEAD(&obj->list_elem);
list_add_tail(&obj->list_elem, &heapbuf_state.obj_list);
mutex_unlock(heapbuf_state.list_lock);
return (void *)handle;
ns_add_error: /* Fall through */ ns_add_error:
lock_error: /* Fall through */ retval = mutex_lock_interruptible(heapbuf_state.local_lock);
proc_attr_alloc_error: list_del(&obj->list_elem);
kfree(obj->owner); mutex_unlock(heapbuf_state.local_lock);
kfree(obj->remote);
lock_error:
if (obj->params.name != NULL) {
if (obj->ns_key != NULL) {
nameserver_remove_entry(heapbuf_state.ns_handle,
obj->ns_key);
obj->ns_key = NULL;
}
kfree(obj->params.name);
}
name_alloc_error: /* Fall through */ name_alloc_error: /* Fall through */
listmp_sharedmemory_delete((listmp_sharedmemory_handle *) if (create_flag == true)
&obj->free_list); listmp_sharedmemory_delete((listmp_sharedmemory_handle *)
&obj->free_list);
else
listmp_sharedmemory_close((listmp_sharedmemory_handle *)
&obj->free_list);
listmp_error: listmp_error:
kfree(obj); kfree(obj);
...@@ -421,7 +512,7 @@ obj_alloc_error: ...@@ -421,7 +512,7 @@ obj_alloc_error:
error: error:
printk(KERN_ERR "_heapbuf_create failed status: %x\n", retval); printk(KERN_ERR "_heapbuf_create failed status: %x\n", retval);
return NULL; return retval;
} }
/* /*
...@@ -431,33 +522,47 @@ error: ...@@ -431,33 +522,47 @@ error:
*/ */
void *heapbuf_create(const struct heapbuf_params *params) void *heapbuf_create(const struct heapbuf_params *params)
{ {
s32 retval = 0; s32 retval = 0;
u32 size;
void *handle = NULL; void *handle = NULL;
u32 buf_size;
BUG_ON(params == NULL); if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
if (WARN_ON(heapbuf_state.nshandle == NULL)) { HEAPBUF_MAKE_MAGICSTAMP(0),
HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV; retval = -ENODEV;
goto error; goto error;
} }
if (params->shared_addr == NULL) { BUG_ON(params == NULL);
if ((params->shared_addr) == NULL ||
params->shared_buf == NULL) {
retval = -EINVAL; retval = -EINVAL;
goto error; goto error;
} }
size = heapbuf_shared_memreq(params); if ((params->shared_addr_size)
if (params->shared_addr_size < size) { < heapbuf_shared_memreq(params, &buf_size)) {
/* if Shared memory size is less than required */
retval = -EINVAL; retval = -EINVAL;
goto error; goto error;
} }
handle = _heapbuf_create(params, true); if (params->shared_buf_size < buf_size) {
return handle; /* if shared memory size is less than required */
retval = -EINVAL;
goto error;
}
retval = _heapbuf_create((void **)&handle, params, true);
if (retval < 0)
goto error;
return (void *)handle;
error: error:
printk(KERN_ERR "heapbuf_create failed status: %x\n", retval); printk(KERN_ERR "heapbuf_create failed status: %x\n", retval);
return handle; return (void *)handle;
} }
EXPORT_SYMBOL(heapbuf_create); EXPORT_SYMBOL(heapbuf_create);
...@@ -466,7 +571,7 @@ EXPORT_SYMBOL(heapbuf_create); ...@@ -466,7 +571,7 @@ EXPORT_SYMBOL(heapbuf_create);
* Purpose: * Purpose:
* This will delete an instance of heapbuf module * This will delete an instance of heapbuf module
*/ */
int heapbuf_delete(void **hphandle) int heapbuf_delete(void **handle_ptr)
{ {
struct heap_object *handle = NULL; struct heap_object *handle = NULL;
struct heapbuf_obj *obj = NULL; struct heapbuf_obj *obj = NULL;
...@@ -474,58 +579,79 @@ int heapbuf_delete(void **hphandle) ...@@ -474,58 +579,79 @@ int heapbuf_delete(void **hphandle)
s32 retval = 0; s32 retval = 0;
u16 myproc_id; u16 myproc_id;
BUG_ON(hphandle == NULL); BUG_ON(handle_ptr == NULL);
if (WARN_ON(heapbuf_state.nshandle == NULL)) { handle = (struct heap_object *)(*handle_ptr);
retval = -ENODEV;
goto error;
}
handle = (struct heap_object *)(*hphandle);
if (WARN_ON(handle == NULL)) { if (WARN_ON(handle == NULL)) {
retval = -EINVAL; retval = -EINVAL;
goto error; goto error;
} }
if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
HEAPBUF_MAKE_MAGICSTAMP(0),
HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto error;
}
obj = (struct heapbuf_obj *)handle->obj; obj = (struct heapbuf_obj *)handle->obj;
if (obj == NULL)
goto error;
myproc_id = multiproc_get_id(NULL); myproc_id = multiproc_get_id(NULL);
if (obj->owner->proc_id != myproc_id) { if (obj->owner.proc_id != myproc_id) {
retval = -EPERM; retval = -EPERM;
goto error; goto error;
} }
if (obj->owner->open_count != 1 || obj->remote->open_count != 0) { if (likely(obj->gate != NULL)) {
retval = mutex_lock_interruptible(obj->gate);
if (retval)
goto gate_error;
}
if (obj->owner.open_count > 1) {
retval = -EBUSY; retval = -EBUSY;
goto device_busy_error;; goto device_busy_error;;
} }
retval = mutex_lock_interruptible(heapbuf_state.list_lock); if (obj->owner.open_count != 1) {
retval = -EBUSY;
goto device_busy_error;;
}
retval = mutex_lock_interruptible(heapbuf_state.local_lock);
if (retval) if (retval)
goto list_lock_error; goto local_lock_error;
list_del(&obj->list_elem); list_del(&obj->list_elem);
mutex_unlock(heapbuf_state.list_lock); mutex_unlock(heapbuf_state.local_lock);
params = (struct heapbuf_params *) &obj->params; params = (struct heapbuf_params *) &obj->params;
if (params->name != NULL) { if (likely(params->name != NULL)) {
retval = nameserver_remove(heapbuf_state.nshandle,
params->name);
if (retval != 0)
goto ns_remove_error;
kfree(params->name); kfree(params->name);
if (likely(heapbuf_state.cfg.use_nameserver == true)) {
retval = nameserver_remove(heapbuf_state.ns_handle,
params->name);
if (retval != 0)
goto ns_remove_error;
obj->ns_key = NULL;
}
} }
if (likely(obj->gate != NULL))
mutex_unlock(obj->gate);
retval = listmp_sharedmemory_delete(&obj->free_list); retval = listmp_sharedmemory_delete(&obj->free_list);
kfree(obj->owner);
kfree(obj->remote);
kfree(obj); kfree(obj);
kfree(handle); kfree(handle);
*hphandle = NULL; *handle_ptr = NULL;
return 0; return 0;
ns_remove_error: /* Fall through */ ns_remove_error: /* Fall through */
list_lock_error: /* Fall through */ gate_error: /* Fall through */
local_lock_error: /* Fall through */
device_busy_error: device_busy_error:
/* mutex_unlock(obj->lock_handle); */ if (likely(obj->gate != NULL))
mutex_unlock(obj->gate);
error: error:
printk(KERN_ERR "heapbuf_delete failed status: %x\n", retval); printk(KERN_ERR "heapbuf_delete failed status: %x\n", retval);
...@@ -539,29 +665,35 @@ EXPORT_SYMBOL(heapbuf_delete); ...@@ -539,29 +665,35 @@ EXPORT_SYMBOL(heapbuf_delete);
* This will opens a created instance of heapbuf * This will opens a created instance of heapbuf
* module * module
*/ */
int heapbuf_open(void **hphandle, int heapbuf_open(void **handle_ptr,
const struct heapbuf_params *params) struct heapbuf_params *params)
{ {
struct heapbuf_obj *obj = NULL; struct heapbuf_obj *obj = NULL;
bool found = false; bool found = false;
u32 size;
s32 retval = 0; s32 retval = 0;
u16 myproc_id; u16 myproc_id;
u32 shared_shm_base;
struct heapbuf_attrs *attrs;
BUG_ON(hphandle == NULL); BUG_ON(handle_ptr == NULL);
BUG_ON(params == NULL); BUG_ON(params == NULL);
if (WARN_ON(heapbuf_state.nshandle == NULL)) {
retval = -ENODEV; if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
HEAPBUF_MAKE_MAGICSTAMP(0),
HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto error; goto error;
} }
if ((params->name == NULL) && (params->shared_addr == (u32)NULL)) { if ((heapbuf_state.cfg.use_nameserver == false)
&& (params->shared_addr == (u32)NULL)) {
retval = -EINVAL; retval = -EINVAL;
goto error; goto error;
} }
size = heapbuf_shared_memreq(params); if ((heapbuf_state.cfg.use_nameserver == true)
if (params->shared_addr != NULL && params->shared_addr_size < size) { && (params->shared_addr == (u32)NULL)
&& (params->name == NULL)) {
retval = -EINVAL; retval = -EINVAL;
goto error; goto error;
} }
...@@ -577,18 +709,52 @@ int heapbuf_open(void **hphandle, ...@@ -577,18 +709,52 @@ int heapbuf_open(void **hphandle,
if (found == true) { if (found == true) {
retval = mutex_lock_interruptible( retval = mutex_lock_interruptible(
heapbuf_state.list_lock); heapbuf_state.local_lock);
if (obj->owner->proc_id == myproc_id) if (obj->owner.proc_id == myproc_id)
obj->owner->open_count++; obj->owner.open_count++;
else *handle_ptr = obj->top;
obj->remote->open_count++; mutex_unlock(heapbuf_state.local_lock);
*hphandle = obj->top;
mutex_unlock(heapbuf_state.list_lock);
} }
} }
if (found == false) if (likely(found == false)) {
*hphandle = (void *)_heapbuf_create(params, false); if (unlikely(params->shared_addr == NULL)) {
if (likely(heapbuf_state.cfg.use_nameserver == true)) {
/* Find in name server */
retval = nameserver_get(heapbuf_state.ns_handle,
params->name,
&shared_shm_base,
sizeof(u32),
NULL);
if (retval < 0)
goto error;
/*
* Convert from shared region pointer
* to local address
*/
params->shared_addr = sharedregion_get_ptr
(&shared_shm_base);
if (params->shared_addr == NULL) {
retval = -EINVAL;
goto error;
}
}
}
attrs = (struct heapbuf_attrs *)(params->shared_addr);
if (unlikely(attrs->status != (HEAPBUF_CREATED)))
retval = -ENXIO; /* Not created */
else if (unlikely(attrs->version != (HEAPBUF_VERSION))) {
retval = -EINVAL;
goto error;
}
retval = _heapbuf_create((void **)handle_ptr, params, false);
if (retval < 0)
goto error;
}
return 0; return 0;
...@@ -604,63 +770,79 @@ EXPORT_SYMBOL(heapbuf_open); ...@@ -604,63 +770,79 @@ EXPORT_SYMBOL(heapbuf_open);
* This will closes previously opened/created instance * This will closes previously opened/created instance
* of heapbuf module * of heapbuf module
*/ */
int heapbuf_close(void *hphandle) int heapbuf_close(void *handle_ptr)
{ {
struct heap_object *handle = NULL; struct heap_object *handle = NULL;
struct heapbuf_obj *obj = NULL; struct heapbuf_obj *obj = NULL;
struct heapbuf_params *params = NULL;
s32 retval = 0; s32 retval = 0;
u16 myproc_id = 0; u16 myproc_id = 0;
if (WARN_ON(heapbuf_state.nshandle == NULL)) { if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
retval = -EINVAL; HEAPBUF_MAKE_MAGICSTAMP(0),
HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto error; goto error;
} }
if (WARN_ON(hphandle == NULL)) { if (WARN_ON(handle_ptr == NULL)) {
retval = -EINVAL; retval = -EINVAL;
goto error; goto error;
} }
handle = (struct heap_object *)(hphandle); handle = (struct heap_object *)(handle_ptr);
obj = (struct heapbuf_obj *)handle->obj; obj = (struct heapbuf_obj *)handle->obj;
retval = mutex_lock_interruptible(heapbuf_state.list_lock);
if (retval)
goto error;
myproc_id = multiproc_get_id(NULL); if (obj != NULL) {
/* opening an instance created locally */ retval = mutex_lock_interruptible(heapbuf_state.local_lock);
if (obj->owner->proc_id == myproc_id) { if (retval)
if (obj->owner->open_count > 1) goto error;
obj->owner->open_count--;
myproc_id = multiproc_get_id(NULL);
/* opening an instance created locally */
if (obj->owner.proc_id == myproc_id) {
if (obj->owner.open_count > 1)
obj->owner.open_count--;
}
goto owner_close_done; /* Check if HeapBuf is opened on same processor*/
} else if ((((struct heapbuf_obj *)obj)->owner.creator == false)
obj->remote->open_count--; && (obj->owner.open_count == 0)) {
list_del(&obj->list_elem);
if (obj->remote->open_count == 0) { /* Take the local lock */
list_del(&obj->list_elem); if (likely(obj->gate != NULL)) {
listmp_sharedmemory_close((listmp_sharedmemory_handle *) retval = mutex_lock_interruptible(obj->gate);
obj->free_list); if (retval)
kfree(obj->owner); goto error;
kfree(obj->remote); }
kfree(obj);
kfree(handle); params = (struct heapbuf_params *)&obj->params;
handle = NULL; if (likely((params->name) != NULL))
} kfree(params->name); /* Free memory */
/* Release the local lock */
if (likely(obj->gate != NULL))
mutex_unlock(obj->gate);
owner_close_done: /* Delete the list */
mutex_unlock(heapbuf_state.list_lock); listmp_sharedmemory_close((listmp_sharedmemory_handle *)
obj->free_list);
kfree(handle);
handle = NULL;
}
mutex_unlock(heapbuf_state.local_lock);
}
return 0; return 0;
error: error:
printk(KERN_ERR "heapbuf_close failed status: %x\n", retval); printk(KERN_ERR "heapbuf_close failed status: %x\n", retval);
return retval; return retval;
} }
EXPORT_SYMBOL(heapbuf_close); EXPORT_SYMBOL(heapbuf_close);
/* /*
* ======== heapbuf_free ======== * ======== heapbuf_alloc ========
* Purpose: * Purpose:
* This will allocs a block of memory * This will allocs a block of memory
*/ */
...@@ -671,8 +853,12 @@ void *heapbuf_alloc(void *hphandle, u32 size, u32 align) ...@@ -671,8 +853,12 @@ void *heapbuf_alloc(void *hphandle, u32 size, u32 align)
char *block = NULL; char *block = NULL;
s32 retval = 0; s32 retval = 0;
if (WARN_ON(heapbuf_state.nshandle == NULL)) if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
HEAPBUF_MAKE_MAGICSTAMP(0),
HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto error; goto error;
}
if (WARN_ON(hphandle == NULL)) if (WARN_ON(hphandle == NULL))
goto error; goto error;
...@@ -683,14 +869,26 @@ void *heapbuf_alloc(void *hphandle, u32 size, u32 align) ...@@ -683,14 +869,26 @@ void *heapbuf_alloc(void *hphandle, u32 size, u32 align)
handle = (struct heap_object *)(hphandle); handle = (struct heap_object *)(hphandle);
obj = (struct heapbuf_obj *)handle->obj; obj = (struct heapbuf_obj *)handle->obj;
if (size > obj->attrs->block_size)
if ((obj->params.exact == true)
&& (size != obj->attrs->block_size))
goto error; goto error;
retval = mutex_lock_interruptible(heapbuf_state.list_lock); if (size > obj->attrs->block_size)
if (retval)
goto error; goto error;
if (likely(obj->gate != NULL)) {
retval = mutex_lock_interruptible(obj->gate);
if (retval)
goto error;
}
block = listmp_get_head((void *)obj->free_list); block = listmp_get_head((void *)obj->free_list);
if (block == NULL) {
retval = -ENOMEM;
goto error;
}
obj->attrs->num_free_blocks--; obj->attrs->num_free_blocks--;
/* /*
* Keep track of the min number of free for this heapbuf, if user * Keep track of the min number of free for this heapbuf, if user
...@@ -707,7 +905,8 @@ void *heapbuf_alloc(void *hphandle, u32 size, u32 align) ...@@ -707,7 +905,8 @@ void *heapbuf_alloc(void *hphandle, u32 size, u32 align)
obj->attrs->num_free_blocks; obj->attrs->num_free_blocks;
} }
mutex_unlock(heapbuf_state.list_lock); if (likely(obj->gate != NULL))
mutex_unlock(obj->gate);
return block; return block;
error: error:
printk(KERN_ERR "heapbuf_alloc failed status: %x\n", retval); printk(KERN_ERR "heapbuf_alloc failed status: %x\n", retval);
...@@ -726,8 +925,10 @@ int heapbuf_free(void *hphandle, void *block, u32 size) ...@@ -726,8 +925,10 @@ int heapbuf_free(void *hphandle, void *block, u32 size)
struct heapbuf_obj *obj = NULL; struct heapbuf_obj *obj = NULL;
s32 retval = 0; s32 retval = 0;
if (WARN_ON(heapbuf_state.nshandle == NULL)) { if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
retval = -EINVAL; HEAPBUF_MAKE_MAGICSTAMP(0),
HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto error; goto error;
} }
...@@ -743,13 +944,15 @@ int heapbuf_free(void *hphandle, void *block, u32 size) ...@@ -743,13 +944,15 @@ int heapbuf_free(void *hphandle, void *block, u32 size)
handle = (struct heap_object *)(hphandle); handle = (struct heap_object *)(hphandle);
obj = (struct heapbuf_obj *)handle->obj; obj = (struct heapbuf_obj *)handle->obj;
retval = mutex_lock_interruptible(heapbuf_state.list_lock); if (likely(obj->gate != NULL)) {
if (retval) retval = mutex_lock_interruptible(obj->gate);
goto error; if (retval)
goto error;
}
retval = listmp_put_tail((void *)obj->free_list, block); retval = listmp_put_tail((void *)obj->free_list, block);
obj->attrs->num_free_blocks++; obj->attrs->num_free_blocks++;
mutex_unlock(heapbuf_state.list_lock); if (likely(obj->gate != NULL))
mutex_unlock(obj->gate);
return 0; return 0;
error: error:
...@@ -770,12 +973,15 @@ int heapbuf_get_stats(void *hphandle, struct memory_stats *stats) ...@@ -770,12 +973,15 @@ int heapbuf_get_stats(void *hphandle, struct memory_stats *stats)
u32 block_size; u32 block_size;
s32 retval = 0; s32 retval = 0;
BUG_ON(stats == NULL); if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
if (WARN_ON(heapbuf_state.nshandle == NULL)) { HEAPBUF_MAKE_MAGICSTAMP(0),
retval = -EINVAL; HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto error; goto error;
} }
BUG_ON(stats == NULL);
if (WARN_ON(hphandle == NULL)) { if (WARN_ON(hphandle == NULL)) {
retval = -EINVAL; retval = -EINVAL;
goto error; goto error;
...@@ -783,12 +989,15 @@ int heapbuf_get_stats(void *hphandle, struct memory_stats *stats) ...@@ -783,12 +989,15 @@ int heapbuf_get_stats(void *hphandle, struct memory_stats *stats)
object = (struct heap_object *)(hphandle); object = (struct heap_object *)(hphandle);
obj = (struct heapbuf_obj *)object->obj; obj = (struct heapbuf_obj *)object->obj;
if (likely(obj->gate != NULL)) {
retval = mutex_lock_interruptible(obj->gate);
if (retval)
goto error;
}
block_size = obj->attrs->block_size; block_size = obj->attrs->block_size;
stats->total_size = (u32 *)(block_size * obj->attrs->num_blocks); stats->total_size = (u32 *)(block_size * obj->attrs->num_blocks);
retval = mutex_lock_interruptible(heapbuf_state.list_lock);
if (retval)
goto error;
stats->total_free_size = (u32 *)(block_size * stats->total_free_size = (u32 *)(block_size *
obj->attrs->num_free_blocks); obj->attrs->num_free_blocks);
if (obj->attrs->num_free_blocks) if (obj->attrs->num_free_blocks)
...@@ -796,7 +1005,8 @@ int heapbuf_get_stats(void *hphandle, struct memory_stats *stats) ...@@ -796,7 +1005,8 @@ int heapbuf_get_stats(void *hphandle, struct memory_stats *stats)
else else
stats->largest_free_size = (u32 *)0; stats->largest_free_size = (u32 *)0;
mutex_unlock(heapbuf_state.list_lock); if (likely(obj->gate != NULL))
mutex_unlock(obj->gate);
return 0; return 0;
error: error:
...@@ -805,20 +1015,54 @@ error: ...@@ -805,20 +1015,54 @@ error:
} }
EXPORT_SYMBOL(heapbuf_get_stats); EXPORT_SYMBOL(heapbuf_get_stats);
/*
* ======== heapbuf_isblocking ========
* Purpose:
* Indicate whether the heap may block during an alloc or free call
*/
bool heapbuf_isblocking(void *handle)
{
bool isblocking = false;
s32 retval = 0;
if (WARN_ON(handle == NULL)) {
retval = -EINVAL;
goto error;
}
/* TBD: Figure out how to determine whether the gate is blocking */
isblocking = true;
/* retval true Heap blocks during alloc/free calls */
/* retval false Heap does not block during alloc/free calls */
return isblocking;
error:
printk(KERN_ERR "heapbuf_isblocking status: %x\n", retval);
return isblocking;
}
EXPORT_SYMBOL(heapbuf_isblocking);
/* /*
* ======== heapbuf_get_extended_stats ======== * ======== heapbuf_get_extended_stats ========
* Purpose: * Purpose:
* This will get extended statistics * This will get extended statistics
*/ */
int heapbuf_get_extended_stats(void *hphandle, int heapbuf_get_extended_stats(void *hphandle,
struct heap_extended_stats *stats) struct heapbuf_extended_stats *stats)
{ {
struct heap_object *object = NULL; struct heap_object *object = NULL;
struct heapbuf_obj *obj = NULL; struct heapbuf_obj *obj = NULL;
s32 retval = 0; s32 retval = 0;
if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
HEAPBUF_MAKE_MAGICSTAMP(0),
HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto error;
}
BUG_ON(stats == NULL); BUG_ON(stats == NULL);
if (WARN_ON(heapbuf_state.nshandle == NULL)) { if (WARN_ON(heapbuf_state.ns_handle == NULL)) {
retval = -EINVAL; retval = -EINVAL;
goto error; goto error;
} }
...@@ -830,9 +1074,11 @@ int heapbuf_get_extended_stats(void *hphandle, ...@@ -830,9 +1074,11 @@ int heapbuf_get_extended_stats(void *hphandle,
object = (struct heap_object *)(hphandle); object = (struct heap_object *)(hphandle);
obj = (struct heapbuf_obj *)object->obj; obj = (struct heapbuf_obj *)object->obj;
retval = mutex_lock_interruptible(heapbuf_state.list_lock); if (likely(obj->gate != NULL)) {
if (retval) retval = mutex_lock_interruptible(obj->gate);
goto error; if (retval)
goto error;
}
/* /*
* The maximum number of allocations for this heapbuf (for any given * The maximum number of allocations for this heapbuf (for any given
...@@ -855,7 +1101,8 @@ int heapbuf_get_extended_stats(void *hphandle, ...@@ -855,7 +1101,8 @@ int heapbuf_get_extended_stats(void *hphandle,
*/ */
stats->num_allocated_blocks = obj->attrs->num_blocks stats->num_allocated_blocks = obj->attrs->num_blocks
- obj->attrs->num_free_blocks; - obj->attrs->num_free_blocks;
mutex_unlock(heapbuf_state.list_lock); if (likely(obj->gate != NULL))
mutex_unlock(obj->gate);
error: error:
printk(KERN_ERR "heapbuf_get_extended_stats status: %x\n", printk(KERN_ERR "heapbuf_get_extended_stats status: %x\n",
...@@ -870,17 +1117,25 @@ EXPORT_SYMBOL(heapbuf_get_extended_stats); ...@@ -870,17 +1117,25 @@ EXPORT_SYMBOL(heapbuf_get_extended_stats);
* This will get amount of shared memory required for * This will get amount of shared memory required for
* creation of each instance * creation of each instance
*/ */
int heapbuf_shared_memreq(const struct heapbuf_params *params) int heapbuf_shared_memreq(const struct heapbuf_params *params, u32 *buf_size)
{ {
s32 retval = 0; int state_size = 0;
listmp_sharedmemory_params listmp_params; listmp_sharedmemory_params listmp_params;
BUG_ON(params == NULL); BUG_ON(params == NULL);
retval = params->num_blocks * params->block_size;
listmp_sharedmemory_params_init(NULL, &listmp_params); /* Size for attrs */
retval += listmp_sharedmemory_shared_memreq(&listmp_params); state_size = (sizeof(struct heapbuf_attrs) + (HEAPBUF_CACHESIZE - 1))
retval += HEAPBUF_CACHESIZE; /* Add in attrs */ & ~(HEAPBUF_CACHESIZE - 1);
return retval;
listmp_params_init(NULL, &listmp_params);
listmp_params.resource_id = params->resource_id;
state_size += listmp_shared_memreq(&listmp_params);
/* Determine size for the buffer */
*buf_size = params->num_blocks * params->block_size;
return state_size;
} }
EXPORT_SYMBOL(heapbuf_shared_memreq); EXPORT_SYMBOL(heapbuf_shared_memreq);
...@@ -252,7 +252,8 @@ static int heapbuf_ioctl_shared_memreq(struct heapbuf_cmd_args *cargs) ...@@ -252,7 +252,8 @@ static int heapbuf_ioctl_shared_memreq(struct heapbuf_cmd_args *cargs)
goto exit; goto exit;
} }
bytes = heapbuf_shared_memreq(&params); bytes = heapbuf_shared_memreq(&params,
&cargs->args.shared_memreq.buf_size);
cargs->args.shared_memreq.bytes = bytes; cargs->args.shared_memreq.bytes = bytes;
cargs->api_status = 0; cargs->api_status = 0;
...@@ -268,13 +269,13 @@ exit: ...@@ -268,13 +269,13 @@ exit:
*/ */
static int heapbuf_ioctl_get_config(struct heapbuf_cmd_args *cargs) static int heapbuf_ioctl_get_config(struct heapbuf_cmd_args *cargs)
{ {
struct heap_config config; struct heapbuf_config config;
s32 status = 0; s32 status = 0;
ulong size; ulong size;
cargs->api_status = heapbuf_get_config(&config); cargs->api_status = heapbuf_get_config(&config);
size = copy_to_user(cargs->args.get_config.config, &config, size = copy_to_user(cargs->args.get_config.config, &config,
sizeof(struct heap_config)); sizeof(struct heapbuf_config));
if (size) if (size)
status = -EFAULT; status = -EFAULT;
...@@ -288,12 +289,12 @@ static int heapbuf_ioctl_get_config(struct heapbuf_cmd_args *cargs) ...@@ -288,12 +289,12 @@ static int heapbuf_ioctl_get_config(struct heapbuf_cmd_args *cargs)
*/ */
static int heapbuf_ioctl_setup(struct heapbuf_cmd_args *cargs) static int heapbuf_ioctl_setup(struct heapbuf_cmd_args *cargs)
{ {
struct heap_config config; struct heapbuf_config config;
s32 status = 0; s32 status = 0;
ulong size; ulong size;
size = copy_from_user(&config, cargs->args.setup.config, size = copy_from_user(&config, cargs->args.setup.config,
sizeof(struct heap_config)); sizeof(struct heapbuf_config));
if (size) { if (size) {
status = -EFAULT; status = -EFAULT;
goto exit; goto exit;
...@@ -348,7 +349,7 @@ exit: ...@@ -348,7 +349,7 @@ exit:
*/ */
static int heapbuf_ioctl_get_extended_stats(struct heapbuf_cmd_args *cargs) static int heapbuf_ioctl_get_extended_stats(struct heapbuf_cmd_args *cargs)
{ {
struct heap_extended_stats stats; struct heapbuf_extended_stats stats;
s32 status = 0; s32 status = 0;
ulong size; ulong size;
...@@ -358,7 +359,7 @@ static int heapbuf_ioctl_get_extended_stats(struct heapbuf_cmd_args *cargs) ...@@ -358,7 +359,7 @@ static int heapbuf_ioctl_get_extended_stats(struct heapbuf_cmd_args *cargs)
goto exit; goto exit;
size = copy_to_user(cargs->args.get_extended_stats.stats, &stats, size = copy_to_user(cargs->args.get_extended_stats.stats, &stats,
sizeof(struct heap_extended_stats)); sizeof(struct heapbuf_extended_stats));
if (size) if (size)
status = -EFAULT; status = -EFAULT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment