video: driver: optimize buffer pool implementation
- Maintain free & busy pool to track buffers separately - track double-free cases during msm_memory_free() - track memory leak, by checking busy pool buffer count. it is expected to be zero at the end of a session. - maintain common api's to init, alloc, free, destroy for all below buffer types. - struct msm_vidc_buffer - struct msm_vidc_alloc - struct msm_vidc_map - struct msm_vidc_timestamp. Change-Id: Ib8655047c3883ea6601344661058d7a629ffd5bd Signed-off-by: Govindaraj Rajagopal <grajagop@codeaurora.org>
This commit is contained in:
@@ -290,18 +290,6 @@ int msm_vidc_release_internal_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
int msm_vidc_vb2_buffer_done(struct msm_vidc_inst *inst,
|
||||
struct msm_vidc_buffer *buf);
|
||||
struct msm_vidc_buffer *msm_vidc_get_vidc_buffer(struct msm_vidc_inst *inst);
|
||||
struct msm_vidc_alloc *msm_vidc_get_alloc_buffer(struct msm_vidc_inst *inst);
|
||||
struct msm_vidc_map *msm_vidc_get_map_buffer(struct msm_vidc_inst *inst);
|
||||
struct msm_vidc_timestamp *msm_vidc_get_ts(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_put_vidc_buffer(struct msm_vidc_inst *inst, struct msm_vidc_buffer *buf);
|
||||
int msm_vidc_put_alloc_buffer(struct msm_vidc_inst *inst, struct msm_vidc_alloc *alloc);
|
||||
int msm_vidc_put_map_buffer(struct msm_vidc_inst *inst, struct msm_vidc_map *map);
|
||||
int msm_vidc_put_ts(struct msm_vidc_inst *inst, struct msm_vidc_timestamp *ts);
|
||||
int msm_vidc_destroy_vidc_buffer(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_destroy_alloc_buffer(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_destroy_map_buffer(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_destroy_ts(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_remove_session(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_add_session(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_session_open(struct msm_vidc_inst *inst);
|
||||
|
@@ -7,6 +7,7 @@
|
||||
#define _MSM_VIDC_INST_H_
|
||||
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_memory.h"
|
||||
#include "hfi_property.h"
|
||||
|
||||
struct msm_vidc_inst;
|
||||
@@ -27,13 +28,6 @@ struct msm_vidc_session_ops {
|
||||
int (*extra_count)(struct msm_vidc_inst *inst, enum msm_vidc_buffer_type type);
|
||||
};
|
||||
|
||||
struct msm_vidc_pool_info {
|
||||
struct msm_vidc_pool allocations;
|
||||
struct msm_vidc_pool mappings;
|
||||
struct msm_vidc_pool buffers;
|
||||
struct msm_vidc_pool timestamps;
|
||||
};
|
||||
|
||||
struct msm_vidc_allocations_info {
|
||||
struct msm_vidc_allocations bin;
|
||||
struct msm_vidc_allocations arp;
|
||||
@@ -119,7 +113,7 @@ struct msm_vidc_inst {
|
||||
struct msm_vidc_rectangle compose;
|
||||
struct msm_vidc_power power;
|
||||
struct vidc_bus_vote_data bus_data;
|
||||
struct msm_vidc_pool_info pool;
|
||||
struct msm_memory_pool pool[MSM_MEM_POOL_MAX];
|
||||
struct msm_vidc_buffers_info buffers;
|
||||
struct msm_vidc_mappings_info mappings;
|
||||
struct msm_vidc_allocations_info allocations;
|
||||
|
@@ -828,11 +828,6 @@ struct msm_vidc_timestamps {
|
||||
u64 rank;
|
||||
};
|
||||
|
||||
struct msm_vidc_pool {
|
||||
struct list_head list;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
enum msm_vidc_allow {
|
||||
MSM_VIDC_DISALLOW = 0,
|
||||
MSM_VIDC_ALLOW,
|
||||
|
@@ -7,7 +7,30 @@
|
||||
#define _MSM_VIDC_MEMORY_H_
|
||||
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_core.h"
|
||||
|
||||
struct msm_vidc_core;
|
||||
struct msm_vidc_inst;
|
||||
|
||||
enum msm_memory_pool_type {
|
||||
MSM_MEM_POOL_BUFFER = 0,
|
||||
MSM_MEM_POOL_MAP,
|
||||
MSM_MEM_POOL_ALLOC,
|
||||
MSM_MEM_POOL_TIMESTAMP,
|
||||
MSM_MEM_POOL_MAX,
|
||||
};
|
||||
|
||||
struct msm_memory_alloc_header {
|
||||
struct list_head list;
|
||||
void *buf;
|
||||
};
|
||||
|
||||
struct msm_memory_pool {
|
||||
u32 type;
|
||||
u32 size;
|
||||
char *name;
|
||||
struct list_head free_pool; /* list of struct msm_memory_alloc_header */
|
||||
struct list_head busy_pool; /* list of struct msm_memory_alloc_header */
|
||||
};
|
||||
|
||||
int msm_vidc_memory_alloc(struct msm_vidc_core *core,
|
||||
struct msm_vidc_alloc *alloc);
|
||||
@@ -19,5 +42,11 @@ int msm_vidc_memory_unmap(struct msm_vidc_core *core,
|
||||
struct msm_vidc_map *map);
|
||||
struct dma_buf *msm_vidc_memory_get_dmabuf(int fd);
|
||||
void msm_vidc_memory_put_dmabuf(void *dmabuf);
|
||||
int msm_memory_pools_init(struct msm_vidc_inst *inst);
|
||||
void msm_memory_pools_deinit(struct msm_vidc_inst *inst);
|
||||
void *msm_memory_alloc(struct msm_vidc_inst *inst,
|
||||
enum msm_memory_pool_type type);
|
||||
void msm_memory_free(struct msm_vidc_inst *inst,
|
||||
enum msm_memory_pool_type type, void *vidc_buf);
|
||||
|
||||
#endif // _MSM_VIDC_MEMORY_H_
|
@@ -1848,7 +1848,7 @@ int msm_vdec_handle_release_buffer(struct msm_vidc_inst *inst,
|
||||
print_vidc_buffer(VIDC_LOW, "low ", "release done", inst, buf);
|
||||
/* delete the buffer from release list */
|
||||
list_del(&buf->list);
|
||||
msm_vidc_put_vidc_buffer(inst, buf);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_BUFFER, buf);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include "msm_vidc_debug.h"
|
||||
#include "msm_vidc_control.h"
|
||||
#include "msm_vidc_power.h"
|
||||
#include "msm_vidc_memory.h"
|
||||
#include "venus_hfi_response.h"
|
||||
|
||||
#define MSM_VIDC_DRV_NAME "msm_vidc_driver"
|
||||
@@ -778,13 +779,15 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
|
||||
kref_init(&inst->kref);
|
||||
mutex_init(&inst->lock);
|
||||
msm_vidc_update_debug_str(inst);
|
||||
|
||||
i_vpr_h(inst, "Opening video instance: %d\n", session_type);
|
||||
|
||||
rc = msm_memory_pools_init(inst);
|
||||
if (rc) {
|
||||
i_vpr_e(inst, "%s: failed to init pool buffers\n", __func__);
|
||||
kfree(inst);
|
||||
return NULL;
|
||||
}
|
||||
INIT_LIST_HEAD(&inst->response_works);
|
||||
INIT_LIST_HEAD(&inst->pool.buffers.list);
|
||||
INIT_LIST_HEAD(&inst->pool.mappings.list);
|
||||
INIT_LIST_HEAD(&inst->pool.allocations.list);
|
||||
INIT_LIST_HEAD(&inst->pool.timestamps.list);
|
||||
INIT_LIST_HEAD(&inst->timestamps.list);
|
||||
INIT_LIST_HEAD(&inst->buffers.input.list);
|
||||
INIT_LIST_HEAD(&inst->buffers.input_meta.list);
|
||||
|
@@ -1980,7 +1980,7 @@ int msm_vidc_process_readonly_buffers(struct msm_vidc_inst *inst,
|
||||
buf->attr |= MSM_VIDC_ATTR_READ_ONLY;
|
||||
print_vidc_buffer(VIDC_LOW, "low ", "ro buf removed", inst, ro_buf);
|
||||
list_del(&ro_buf->list);
|
||||
msm_vidc_put_vidc_buffer(inst, ro_buf);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_BUFFER, ro_buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2007,7 +2007,7 @@ int msm_vidc_memory_unmap_completely(struct msm_vidc_inst *inst,
|
||||
if (!map->refcount) {
|
||||
msm_vidc_memory_put_dmabuf(map->dmabuf);
|
||||
list_del(&map->list);
|
||||
msm_vidc_put_map_buffer(inst, map);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_MAP, map);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2112,7 +2112,7 @@ int msm_vidc_flush_ts(struct msm_vidc_inst *inst)
|
||||
i_vpr_l(inst, "%s: flushing ts: val %lld, rank %%lld\n",
|
||||
__func__, ts->sort.val, ts->rank);
|
||||
list_del(&ts->sort.list);
|
||||
msm_vidc_put_ts(inst, ts);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_TIMESTAMP, ts);
|
||||
}
|
||||
inst->timestamps.count = 0;
|
||||
inst->timestamps.rank = 0;
|
||||
@@ -2130,7 +2130,7 @@ int msm_vidc_update_timestamp(struct msm_vidc_inst *inst, u64 timestamp)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ts = msm_vidc_get_ts(inst);
|
||||
ts = msm_memory_alloc(inst, MSM_MEM_POOL_TIMESTAMP);
|
||||
if (!ts) {
|
||||
i_vpr_e(inst, "%s: ts alloc failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
@@ -2153,229 +2153,12 @@ int msm_vidc_update_timestamp(struct msm_vidc_inst *inst, u64 timestamp)
|
||||
}
|
||||
inst->timestamps.count--;
|
||||
list_del(&ts->sort.list);
|
||||
msm_vidc_put_ts(inst, ts);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_TIMESTAMP, ts);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct msm_vidc_timestamp *msm_vidc_get_ts(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_timestamp *ts = NULL;
|
||||
|
||||
if (!inst) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!list_empty(&inst->pool.timestamps.list)) {
|
||||
ts = list_first_entry(&inst->pool.timestamps.list,
|
||||
struct msm_vidc_timestamp, sort.list);
|
||||
inst->pool.timestamps.count--;
|
||||
list_del(&ts->sort.list);
|
||||
memset(ts, 0, sizeof(struct msm_vidc_timestamp));
|
||||
return ts;
|
||||
}
|
||||
|
||||
ts = kzalloc(sizeof(struct msm_vidc_timestamp), GFP_KERNEL);
|
||||
if (!ts) {
|
||||
i_vpr_e(inst, "%s: ts failed\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
int msm_vidc_put_ts(struct msm_vidc_inst *inst, struct msm_vidc_timestamp *ts)
|
||||
{
|
||||
if (!inst || !ts) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
inst->pool.timestamps.count++;
|
||||
list_add_tail(&ts->sort.list, &inst->pool.timestamps.list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_destroy_ts(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_timestamp *ts, *temp;
|
||||
|
||||
if (!inst) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i_vpr_h(inst, "%s: pool: ts count %u\n", __func__, inst->pool.timestamps.count);
|
||||
|
||||
/* free all timestamps from pool */
|
||||
list_for_each_entry_safe(ts, temp, &inst->pool.timestamps.list, sort.list) {
|
||||
list_del(&ts->sort.list);
|
||||
kfree(ts);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct msm_vidc_buffer *msm_vidc_get_vidc_buffer(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_buffer *buf = NULL;
|
||||
|
||||
if (!inst) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!list_empty(&inst->pool.buffers.list)) {
|
||||
buf = list_first_entry(&inst->pool.buffers.list, struct msm_vidc_buffer, list);
|
||||
inst->pool.buffers.count--;
|
||||
list_del(&buf->list);
|
||||
memset(buf, 0, sizeof(struct msm_vidc_buffer));
|
||||
return buf;
|
||||
}
|
||||
|
||||
buf = kzalloc(sizeof(struct msm_vidc_buffer), GFP_KERNEL);
|
||||
if (!buf) {
|
||||
i_vpr_e(inst, "%s: buf failed\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int msm_vidc_put_vidc_buffer(struct msm_vidc_inst *inst, struct msm_vidc_buffer *buf)
|
||||
{
|
||||
if (!inst || !buf) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
inst->pool.buffers.count++;
|
||||
list_add_tail(&buf->list, &inst->pool.buffers.list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_destroy_vidc_buffer(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_buffer *buf, *dummy;
|
||||
|
||||
if (!inst) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i_vpr_h(inst, "%s: pool: buffer count %u\n", __func__, inst->pool.buffers.count);
|
||||
|
||||
/* free all buffers from pool */
|
||||
list_for_each_entry_safe(buf, dummy, &inst->pool.buffers.list, list) {
|
||||
list_del(&buf->list);
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct msm_vidc_alloc *msm_vidc_get_alloc_buffer(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_alloc *alloc = NULL;
|
||||
|
||||
if (!inst) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!list_empty(&inst->pool.allocations.list)) {
|
||||
alloc = list_first_entry(&inst->pool.allocations.list, struct msm_vidc_alloc, list);
|
||||
inst->pool.allocations.count--;
|
||||
list_del(&alloc->list);
|
||||
memset(alloc, 0, sizeof(struct msm_vidc_alloc));
|
||||
return alloc;
|
||||
}
|
||||
|
||||
alloc = kzalloc(sizeof(struct msm_vidc_alloc), GFP_KERNEL);
|
||||
if (!alloc) {
|
||||
i_vpr_e(inst, "%s: alloc failed\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return alloc;
|
||||
}
|
||||
|
||||
int msm_vidc_put_alloc_buffer(struct msm_vidc_inst *inst, struct msm_vidc_alloc *alloc)
|
||||
{
|
||||
if (!inst || !alloc) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
list_add_tail(&alloc->list, &inst->pool.allocations.list);
|
||||
inst->pool.allocations.count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_destroy_alloc_buffer(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_alloc *alloc, *dummy;
|
||||
|
||||
if (!inst) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i_vpr_h(inst, "%s: pool: allocations count %u\n", __func__, inst->pool.allocations.count);
|
||||
|
||||
/* free all allocations from pool */
|
||||
list_for_each_entry_safe(alloc, dummy, &inst->pool.allocations.list, list) {
|
||||
list_del(&alloc->list);
|
||||
kfree(alloc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct msm_vidc_map *msm_vidc_get_map_buffer(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_map *map = NULL;
|
||||
|
||||
if (!inst) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!list_empty(&inst->pool.mappings.list)) {
|
||||
map = list_first_entry(&inst->pool.mappings.list, struct msm_vidc_map, list);
|
||||
inst->pool.mappings.count--;
|
||||
list_del(&map->list);
|
||||
memset(map, 0, sizeof(struct msm_vidc_map));
|
||||
return map;
|
||||
}
|
||||
|
||||
map = kzalloc(sizeof(struct msm_vidc_map), GFP_KERNEL);
|
||||
if (!map) {
|
||||
i_vpr_e(inst, "%s: map failed\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
int msm_vidc_put_map_buffer(struct msm_vidc_inst *inst, struct msm_vidc_map *map)
|
||||
{
|
||||
if (!inst || !map) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
list_add_tail(&map->list, &inst->pool.mappings.list);
|
||||
inst->pool.mappings.count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_get_delayed_unmap(struct msm_vidc_inst *inst, struct msm_vidc_map *map)
|
||||
{
|
||||
int rc = 0;
|
||||
@@ -2416,32 +2199,12 @@ int msm_vidc_put_delayed_unmap(struct msm_vidc_inst *inst, struct msm_vidc_map *
|
||||
if (!map->refcount) {
|
||||
msm_vidc_memory_put_dmabuf(map->dmabuf);
|
||||
list_del(&map->list);
|
||||
msm_vidc_put_map_buffer(inst, map);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_MAP, map);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_destroy_map_buffer(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_map *map, *dummy;
|
||||
|
||||
if (!inst) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i_vpr_h(inst, "%s: pool: mappings count %u\n", __func__, inst->pool.mappings.count);
|
||||
|
||||
/* free all mappings from pool */
|
||||
list_for_each_entry_safe(map, dummy, &inst->pool.mappings.list, list) {
|
||||
list_del(&map->list);
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_unmap_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type type)
|
||||
{
|
||||
@@ -2504,7 +2267,7 @@ int msm_vidc_unmap_driver_buf(struct msm_vidc_inst *inst,
|
||||
if (!map->refcount) {
|
||||
msm_vidc_memory_put_dmabuf(map->dmabuf);
|
||||
list_del(&map->list);
|
||||
msm_vidc_put_map_buffer(inst, map);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_MAP, map);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -2539,7 +2302,7 @@ int msm_vidc_map_driver_buf(struct msm_vidc_inst *inst,
|
||||
}
|
||||
if (!found) {
|
||||
/* new buffer case */
|
||||
map = msm_vidc_get_map_buffer(inst);
|
||||
map = msm_memory_alloc(inst, MSM_MEM_POOL_MAP);
|
||||
if (!map) {
|
||||
i_vpr_e(inst, "%s: alloc failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
@@ -2555,7 +2318,7 @@ int msm_vidc_map_driver_buf(struct msm_vidc_inst *inst,
|
||||
rc = msm_vidc_get_delayed_unmap(inst, map);
|
||||
if (rc) {
|
||||
msm_vidc_memory_put_dmabuf(map->dmabuf);
|
||||
msm_vidc_put_map_buffer(inst, map);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_MAP, map);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
@@ -2586,7 +2349,7 @@ int msm_vidc_put_driver_buf(struct msm_vidc_inst *inst,
|
||||
|
||||
/* delete the buffer from buffers->list */
|
||||
list_del(&buf->list);
|
||||
msm_vidc_put_vidc_buffer(inst, buf);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_BUFFER, buf);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -2612,7 +2375,7 @@ struct msm_vidc_buffer *msm_vidc_get_driver_buf(struct msm_vidc_inst *inst,
|
||||
if (!buffers)
|
||||
return NULL;
|
||||
|
||||
buf = msm_vidc_get_vidc_buffer(inst);
|
||||
buf = msm_memory_alloc(inst, MSM_MEM_POOL_BUFFER);
|
||||
if (!buf) {
|
||||
i_vpr_e(inst, "%s: alloc failed\n", __func__);
|
||||
return NULL;
|
||||
@@ -2640,7 +2403,7 @@ struct msm_vidc_buffer *msm_vidc_get_driver_buf(struct msm_vidc_inst *inst,
|
||||
error:
|
||||
msm_vidc_memory_put_dmabuf(buf->dmabuf);
|
||||
list_del(&buf->list);
|
||||
msm_vidc_put_vidc_buffer(inst, buf);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_BUFFER, buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3083,7 +2846,7 @@ int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
|
||||
if (map->dmabuf == buffer->dmabuf) {
|
||||
msm_vidc_memory_unmap(inst->core, map);
|
||||
list_del(&map->list);
|
||||
msm_vidc_put_map_buffer(inst, map);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_MAP, map);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3092,7 +2855,7 @@ int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
|
||||
if (alloc->dmabuf == buffer->dmabuf) {
|
||||
msm_vidc_memory_free(inst->core, alloc);
|
||||
list_del(&alloc->list);
|
||||
msm_vidc_put_alloc_buffer(inst, alloc);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_ALLOC, alloc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3100,7 +2863,7 @@ int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
|
||||
list_for_each_entry_safe(buf, dummy, &buffers->list, list) {
|
||||
if (buf->dmabuf == buffer->dmabuf) {
|
||||
list_del(&buf->list);
|
||||
msm_vidc_put_vidc_buffer(inst, buf);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_BUFFER, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3180,7 +2943,7 @@ int msm_vidc_create_internal_buffer(struct msm_vidc_inst *inst,
|
||||
if (!buffers->size)
|
||||
return 0;
|
||||
|
||||
buffer = msm_vidc_get_vidc_buffer(inst);
|
||||
buffer = msm_memory_alloc(inst, MSM_MEM_POOL_BUFFER);
|
||||
if (!buffer) {
|
||||
i_vpr_e(inst, "%s: buf alloc failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
@@ -3191,7 +2954,7 @@ int msm_vidc_create_internal_buffer(struct msm_vidc_inst *inst,
|
||||
buffer->buffer_size = buffers->size;
|
||||
list_add_tail(&buffer->list, &buffers->list);
|
||||
|
||||
alloc = msm_vidc_get_alloc_buffer(inst);
|
||||
alloc = msm_memory_alloc(inst, MSM_MEM_POOL_ALLOC);
|
||||
if (!alloc) {
|
||||
i_vpr_e(inst, "%s: alloc failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
@@ -3207,7 +2970,7 @@ int msm_vidc_create_internal_buffer(struct msm_vidc_inst *inst,
|
||||
return -ENOMEM;
|
||||
list_add_tail(&alloc->list, &allocations->list);
|
||||
|
||||
map = msm_vidc_get_map_buffer(inst);
|
||||
map = msm_memory_alloc(inst, MSM_MEM_POOL_MAP);
|
||||
if (!map) {
|
||||
i_vpr_e(inst, "%s: map alloc failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
@@ -4735,20 +4498,20 @@ void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst)
|
||||
list_for_each_entry_safe(buf, dummy, &inst->buffers.read_only.list, list) {
|
||||
print_vidc_buffer(VIDC_ERR, "err ", "destroying ro buffer", inst, buf);
|
||||
list_del(&buf->list);
|
||||
msm_vidc_put_vidc_buffer(inst, buf);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_BUFFER, buf);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(buf, dummy, &inst->buffers.release.list, list) {
|
||||
print_vidc_buffer(VIDC_ERR, "err ", "destroying release buffer", inst, buf);
|
||||
list_del(&buf->list);
|
||||
msm_vidc_put_vidc_buffer(inst, buf);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_BUFFER, buf);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(ts, dummy_ts, &inst->timestamps.list, sort.list) {
|
||||
i_vpr_e(inst, "%s: removing ts: val %lld, rank %lld\n",
|
||||
__func__, ts->sort.val, ts->rank);
|
||||
list_del(&ts->sort.list);
|
||||
msm_vidc_put_ts(inst, ts);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_TIMESTAMP, ts);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(work, dummy_work, &inst->response_works, list) {
|
||||
@@ -4758,10 +4521,7 @@ void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst)
|
||||
}
|
||||
|
||||
/* destroy buffers from pool */
|
||||
msm_vidc_destroy_vidc_buffer(inst);
|
||||
msm_vidc_destroy_alloc_buffer(inst);
|
||||
msm_vidc_destroy_map_buffer(inst);
|
||||
msm_vidc_destroy_ts(inst);
|
||||
msm_memory_pools_deinit(inst);
|
||||
}
|
||||
|
||||
static void msm_vidc_close_helper(struct kref *kref)
|
||||
|
@@ -314,6 +314,172 @@ int msm_vidc_memory_free(struct msm_vidc_core *core, struct msm_vidc_alloc *mem)
|
||||
|
||||
return rc;
|
||||
};
|
||||
|
||||
void *msm_memory_alloc(struct msm_vidc_inst *inst, enum msm_memory_pool_type type)
|
||||
{
|
||||
struct msm_memory_alloc_header *hdr;
|
||||
struct msm_memory_pool *pool;
|
||||
|
||||
if (!inst || type < 0 || type >= MSM_MEM_POOL_MAX) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
pool = &inst->pool[type];
|
||||
|
||||
if (!list_empty(&pool->free_pool)) {
|
||||
/* get 1st node from free pool */
|
||||
hdr = list_first_entry(&pool->free_pool,
|
||||
struct msm_memory_alloc_header, list);
|
||||
list_del_init(&hdr->list);
|
||||
|
||||
/* reset existing data */
|
||||
memset((char *)hdr->buf, 0, pool->size);
|
||||
|
||||
/* add to busy pool */
|
||||
list_add_tail(&hdr->list, &pool->busy_pool);
|
||||
|
||||
return hdr->buf;
|
||||
}
|
||||
|
||||
hdr = kzalloc(pool->size + sizeof(struct msm_memory_alloc_header), GFP_KERNEL);
|
||||
if (!hdr) {
|
||||
i_vpr_e(inst, "%s: buffer allocation failed\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
INIT_LIST_HEAD(&hdr->list);
|
||||
hdr->buf = (void *)(hdr + 1);
|
||||
list_add_tail(&hdr->list, &pool->busy_pool);
|
||||
|
||||
return hdr->buf;
|
||||
}
|
||||
|
||||
void msm_memory_free(struct msm_vidc_inst *inst, enum msm_memory_pool_type type,
|
||||
void *vidc_buf)
|
||||
{
|
||||
struct msm_memory_alloc_header *hdr;
|
||||
struct msm_memory_pool *pool;
|
||||
bool found = false;
|
||||
|
||||
if (!inst || !vidc_buf || type < 0 || type >= MSM_MEM_POOL_MAX) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return;
|
||||
}
|
||||
pool = &inst->pool[type];
|
||||
|
||||
/* sanitize buffer addr */
|
||||
list_for_each_entry(hdr, &pool->busy_pool, list) {
|
||||
if (hdr->buf == vidc_buf) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
i_vpr_e(inst, "%s: invalid buf addr %#x\n", __func__, vidc_buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* remove from busy pool */
|
||||
list_del_init(&hdr->list);
|
||||
|
||||
/* add to free pool */
|
||||
list_add_tail(&hdr->list, &pool->free_pool);
|
||||
}
|
||||
|
||||
static void msm_vidc_destroy_pool_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_memory_pool_type type)
|
||||
{
|
||||
struct msm_memory_alloc_header *hdr, *dummy;
|
||||
struct msm_memory_pool *pool;
|
||||
u32 fcount = 0, bcount = 0;
|
||||
|
||||
if (!inst || type < 0 || type >= MSM_MEM_POOL_MAX) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return;
|
||||
}
|
||||
pool = &inst->pool[type];
|
||||
|
||||
/* detect memleak: busy pool is expected to be empty here */
|
||||
if (!list_empty(&pool->busy_pool))
|
||||
i_vpr_e(inst, "%s: destroy request on active buffer. type %s\n",
|
||||
__func__, pool->name);
|
||||
|
||||
/* destroy all free buffers */
|
||||
list_for_each_entry_safe(hdr, dummy, &pool->free_pool, list) {
|
||||
list_del(&hdr->list);
|
||||
kfree(hdr);
|
||||
fcount++;
|
||||
}
|
||||
|
||||
/* destroy all busy buffers */
|
||||
list_for_each_entry_safe(hdr, dummy, &pool->busy_pool, list) {
|
||||
list_del(&hdr->list);
|
||||
kfree(hdr);
|
||||
bcount++;
|
||||
}
|
||||
|
||||
i_vpr_h(inst, "%s: type: %23s, count: free %2u, busy %2u\n",
|
||||
__func__, pool->name, fcount, bcount);
|
||||
}
|
||||
|
||||
void msm_memory_pools_deinit(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 i = 0;
|
||||
|
||||
if (!inst) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* destroy all buffers from all pool types */
|
||||
for (i = 0; i < MSM_MEM_POOL_MAX; i++)
|
||||
msm_vidc_destroy_pool_buffers(inst, i);
|
||||
}
|
||||
|
||||
struct msm_vidc_type_size_name {
|
||||
enum msm_memory_pool_type type;
|
||||
u32 size;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static struct msm_vidc_type_size_name buftype_size_name_arr[] = {
|
||||
{MSM_MEM_POOL_BUFFER, sizeof(struct msm_vidc_buffer), "MSM_MEM_POOL_BUFFER" },
|
||||
{MSM_MEM_POOL_MAP, sizeof(struct msm_vidc_map), "MSM_MEM_POOL_MAP" },
|
||||
{MSM_MEM_POOL_ALLOC, sizeof(struct msm_vidc_alloc), "MSM_MEM_POOL_ALLOC" },
|
||||
{MSM_MEM_POOL_TIMESTAMP, sizeof(struct msm_vidc_timestamp), "MSM_MEM_POOL_TIMESTAMP" },
|
||||
};
|
||||
|
||||
int msm_memory_pools_init(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
if (!inst) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ARRAY_SIZE(buftype_size_name_arr) != MSM_MEM_POOL_MAX) {
|
||||
i_vpr_e(inst, "%s: num elements mismatch %u %u\n", __func__,
|
||||
ARRAY_SIZE(buftype_size_name_arr), MSM_MEM_POOL_MAX);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < MSM_MEM_POOL_MAX; i++) {
|
||||
if (i != buftype_size_name_arr[i].type) {
|
||||
i_vpr_e(inst, "%s: type mismatch %u %u\n", __func__,
|
||||
i, buftype_size_name_arr[i].type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
inst->pool[i].type = buftype_size_name_arr[i].type;
|
||||
inst->pool[i].size = buftype_size_name_arr[i].size;
|
||||
inst->pool[i].name = buftype_size_name_arr[i].name;
|
||||
INIT_LIST_HEAD(&inst->pool[i].free_pool);
|
||||
INIT_LIST_HEAD(&inst->pool[i].busy_pool);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
int msm_memory_cache_operations(struct msm_vidc_inst *inst,
|
||||
struct dma_buf *dbuf, enum smem_cache_ops cache_op,
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include "msm_vidc_driver.h"
|
||||
#include "msm_vdec.h"
|
||||
#include "msm_vidc_control.h"
|
||||
#include "msm_vidc_memory.h"
|
||||
|
||||
#define in_range(range, val) (((range.begin) < (val)) && ((range.end) > (val)))
|
||||
|
||||
@@ -593,7 +594,7 @@ static int handle_read_only_buffer(struct msm_vidc_inst *inst,
|
||||
* if present, do nothing
|
||||
*/
|
||||
if (!found) {
|
||||
ro_buf = msm_vidc_get_vidc_buffer(inst);
|
||||
ro_buf = msm_memory_alloc(inst, MSM_MEM_POOL_BUFFER);
|
||||
if (!ro_buf) {
|
||||
i_vpr_e(inst, "%s: buffer alloc failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
@@ -644,7 +645,7 @@ static int handle_non_read_only_buffer(struct msm_vidc_inst *inst,
|
||||
if (found) {
|
||||
print_vidc_buffer(VIDC_LOW, "low ", "ro buf deleted", inst, ro_buf);
|
||||
list_del(&ro_buf->list);
|
||||
msm_vidc_put_vidc_buffer(inst, ro_buf);
|
||||
msm_memory_free(inst, MSM_MEM_POOL_BUFFER, ro_buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user