video: driver: optimize buffer pool design
Added change to avoid unnecessary list iteration during msm_memory_free also added logic to catch double free request. Change-Id: Ie3fb8019fd039e95ea75ba8f3fbd266af515e5cd Signed-off-by: Govindaraj Rajagopal <grajagop@codeaurora.org>
This commit is contained in:
@@ -28,11 +28,12 @@ enum msm_memory_pool_type {
|
|||||||
|
|
||||||
struct msm_memory_alloc_header {
|
struct msm_memory_alloc_header {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
u32 type;
|
||||||
|
bool busy;
|
||||||
void *buf;
|
void *buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct msm_memory_pool {
|
struct msm_memory_pool {
|
||||||
u32 type;
|
|
||||||
u32 size;
|
u32 size;
|
||||||
char *name;
|
char *name;
|
||||||
struct list_head free_pool; /* list of struct msm_memory_alloc_header */
|
struct list_head free_pool; /* list of struct msm_memory_alloc_header */
|
||||||
@@ -57,7 +58,6 @@ int msm_memory_pools_init(struct msm_vidc_inst *inst);
|
|||||||
void msm_memory_pools_deinit(struct msm_vidc_inst *inst);
|
void msm_memory_pools_deinit(struct msm_vidc_inst *inst);
|
||||||
void *msm_memory_alloc(struct msm_vidc_inst *inst,
|
void *msm_memory_alloc(struct msm_vidc_inst *inst,
|
||||||
enum msm_memory_pool_type type);
|
enum msm_memory_pool_type type);
|
||||||
void msm_memory_free(struct msm_vidc_inst *inst,
|
void msm_memory_free(struct msm_vidc_inst *inst, void *vidc_buf);
|
||||||
enum msm_memory_pool_type type, void *vidc_buf);
|
|
||||||
|
|
||||||
#endif // _MSM_VIDC_MEMORY_H_
|
#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);
|
print_vidc_buffer(VIDC_LOW, "low ", "release done", inst, buf);
|
||||||
/* delete the buffer from release list */
|
/* delete the buffer from release list */
|
||||||
list_del(&buf->list);
|
list_del(&buf->list);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_BUFFER, buf);
|
msm_memory_free(inst, buf);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@@ -1983,7 +1983,7 @@ int msm_vidc_process_readonly_buffers(struct msm_vidc_inst *inst,
|
|||||||
buf->attr |= MSM_VIDC_ATTR_READ_ONLY;
|
buf->attr |= MSM_VIDC_ATTR_READ_ONLY;
|
||||||
print_vidc_buffer(VIDC_LOW, "low ", "ro buf removed", inst, ro_buf);
|
print_vidc_buffer(VIDC_LOW, "low ", "ro buf removed", inst, ro_buf);
|
||||||
list_del(&ro_buf->list);
|
list_del(&ro_buf->list);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_BUFFER, ro_buf);
|
msm_memory_free(inst, ro_buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2010,7 +2010,7 @@ int msm_vidc_memory_unmap_completely(struct msm_vidc_inst *inst,
|
|||||||
if (!map->refcount) {
|
if (!map->refcount) {
|
||||||
msm_vidc_memory_put_dmabuf(inst, map->dmabuf);
|
msm_vidc_memory_put_dmabuf(inst, map->dmabuf);
|
||||||
list_del(&map->list);
|
list_del(&map->list);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_MAP, map);
|
msm_memory_free(inst, map);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2175,7 +2175,7 @@ int msm_vidc_flush_ts(struct msm_vidc_inst *inst)
|
|||||||
i_vpr_l(inst, "%s: flushing ts: val %lld, rank %%lld\n",
|
i_vpr_l(inst, "%s: flushing ts: val %lld, rank %%lld\n",
|
||||||
__func__, ts->sort.val, ts->rank);
|
__func__, ts->sort.val, ts->rank);
|
||||||
list_del(&ts->sort.list);
|
list_del(&ts->sort.list);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_TIMESTAMP, ts);
|
msm_memory_free(inst, ts);
|
||||||
}
|
}
|
||||||
inst->timestamps.count = 0;
|
inst->timestamps.count = 0;
|
||||||
inst->timestamps.rank = 0;
|
inst->timestamps.rank = 0;
|
||||||
@@ -2222,7 +2222,7 @@ int msm_vidc_update_timestamp(struct msm_vidc_inst *inst, u64 timestamp)
|
|||||||
}
|
}
|
||||||
inst->timestamps.count--;
|
inst->timestamps.count--;
|
||||||
list_del(&ts->sort.list);
|
list_del(&ts->sort.list);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_TIMESTAMP, ts);
|
msm_memory_free(inst, ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2268,7 +2268,7 @@ int msm_vidc_put_delayed_unmap(struct msm_vidc_inst *inst, struct msm_vidc_map *
|
|||||||
if (!map->refcount) {
|
if (!map->refcount) {
|
||||||
msm_vidc_memory_put_dmabuf(inst, map->dmabuf);
|
msm_vidc_memory_put_dmabuf(inst, map->dmabuf);
|
||||||
list_del(&map->list);
|
list_del(&map->list);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_MAP, map);
|
msm_memory_free(inst, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@@ -2336,7 +2336,7 @@ int msm_vidc_unmap_driver_buf(struct msm_vidc_inst *inst,
|
|||||||
if (!map->refcount) {
|
if (!map->refcount) {
|
||||||
msm_vidc_memory_put_dmabuf(inst, map->dmabuf);
|
msm_vidc_memory_put_dmabuf(inst, map->dmabuf);
|
||||||
list_del(&map->list);
|
list_del(&map->list);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_MAP, map);
|
msm_memory_free(inst, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@@ -2387,7 +2387,7 @@ int msm_vidc_map_driver_buf(struct msm_vidc_inst *inst,
|
|||||||
rc = msm_vidc_get_delayed_unmap(inst, map);
|
rc = msm_vidc_get_delayed_unmap(inst, map);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
msm_vidc_memory_put_dmabuf(inst, map->dmabuf);
|
msm_vidc_memory_put_dmabuf(inst, map->dmabuf);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_MAP, map);
|
msm_memory_free(inst, map);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2418,7 +2418,7 @@ int msm_vidc_put_driver_buf(struct msm_vidc_inst *inst,
|
|||||||
|
|
||||||
/* delete the buffer from buffers->list */
|
/* delete the buffer from buffers->list */
|
||||||
list_del(&buf->list);
|
list_del(&buf->list);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_BUFFER, buf);
|
msm_memory_free(inst, buf);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -2472,7 +2472,7 @@ struct msm_vidc_buffer *msm_vidc_get_driver_buf(struct msm_vidc_inst *inst,
|
|||||||
error:
|
error:
|
||||||
msm_vidc_memory_put_dmabuf(inst, buf->dmabuf);
|
msm_vidc_memory_put_dmabuf(inst, buf->dmabuf);
|
||||||
list_del(&buf->list);
|
list_del(&buf->list);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_BUFFER, buf);
|
msm_memory_free(inst, buf);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2915,7 +2915,7 @@ int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
|
|||||||
if (map->dmabuf == buffer->dmabuf) {
|
if (map->dmabuf == buffer->dmabuf) {
|
||||||
msm_vidc_memory_unmap(inst->core, map);
|
msm_vidc_memory_unmap(inst->core, map);
|
||||||
list_del(&map->list);
|
list_del(&map->list);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_MAP, map);
|
msm_memory_free(inst, map);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2924,7 +2924,7 @@ int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
|
|||||||
if (alloc->dmabuf == buffer->dmabuf) {
|
if (alloc->dmabuf == buffer->dmabuf) {
|
||||||
msm_vidc_memory_free(inst->core, alloc);
|
msm_vidc_memory_free(inst->core, alloc);
|
||||||
list_del(&alloc->list);
|
list_del(&alloc->list);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_ALLOC, alloc);
|
msm_memory_free(inst, alloc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2932,7 +2932,7 @@ int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
|
|||||||
list_for_each_entry_safe(buf, dummy, &buffers->list, list) {
|
list_for_each_entry_safe(buf, dummy, &buffers->list, list) {
|
||||||
if (buf->dmabuf == buffer->dmabuf) {
|
if (buf->dmabuf == buffer->dmabuf) {
|
||||||
list_del(&buf->list);
|
list_del(&buf->list);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_BUFFER, buf);
|
msm_memory_free(inst, buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4599,20 +4599,20 @@ void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst)
|
|||||||
list_for_each_entry_safe(buf, dummy, &inst->buffers.read_only.list, list) {
|
list_for_each_entry_safe(buf, dummy, &inst->buffers.read_only.list, list) {
|
||||||
print_vidc_buffer(VIDC_ERR, "err ", "destroying ro buffer", inst, buf);
|
print_vidc_buffer(VIDC_ERR, "err ", "destroying ro buffer", inst, buf);
|
||||||
list_del(&buf->list);
|
list_del(&buf->list);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_BUFFER, buf);
|
msm_memory_free(inst, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry_safe(buf, dummy, &inst->buffers.release.list, list) {
|
list_for_each_entry_safe(buf, dummy, &inst->buffers.release.list, list) {
|
||||||
print_vidc_buffer(VIDC_ERR, "err ", "destroying release buffer", inst, buf);
|
print_vidc_buffer(VIDC_ERR, "err ", "destroying release buffer", inst, buf);
|
||||||
list_del(&buf->list);
|
list_del(&buf->list);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_BUFFER, buf);
|
msm_memory_free(inst, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry_safe(ts, dummy_ts, &inst->timestamps.list, sort.list) {
|
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",
|
i_vpr_e(inst, "%s: removing ts: val %lld, rank %lld\n",
|
||||||
__func__, ts->sort.val, ts->rank);
|
__func__, ts->sort.val, ts->rank);
|
||||||
list_del(&ts->sort.list);
|
list_del(&ts->sort.list);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_TIMESTAMP, ts);
|
msm_memory_free(inst, ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry_safe(dbuf, dummy_dbuf, &inst->dmabuf_tracker, list) {
|
list_for_each_entry_safe(dbuf, dummy_dbuf, &inst->dmabuf_tracker, list) {
|
||||||
|
@@ -145,7 +145,7 @@ void msm_vidc_memory_put_dmabuf(struct msm_vidc_inst *inst, struct dma_buf *dmab
|
|||||||
dma_buf_put(buf->dmabuf);
|
dma_buf_put(buf->dmabuf);
|
||||||
|
|
||||||
/* put tracker instance back to pool */
|
/* put tracker instance back to pool */
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_DMABUF, buf);
|
msm_memory_free(inst, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void msm_vidc_memory_put_dmabuf_completely(struct msm_vidc_inst *inst,
|
void msm_vidc_memory_put_dmabuf_completely(struct msm_vidc_inst *inst,
|
||||||
@@ -166,7 +166,7 @@ void msm_vidc_memory_put_dmabuf_completely(struct msm_vidc_inst *inst,
|
|||||||
dma_buf_put(buf->dmabuf);
|
dma_buf_put(buf->dmabuf);
|
||||||
|
|
||||||
/* put tracker instance back to pool */
|
/* put tracker instance back to pool */
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_DMABUF, buf);
|
msm_memory_free(inst, buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -426,6 +426,9 @@ void *msm_memory_alloc(struct msm_vidc_inst *inst, enum msm_memory_pool_type typ
|
|||||||
/* add to busy pool */
|
/* add to busy pool */
|
||||||
list_add_tail(&hdr->list, &pool->busy_pool);
|
list_add_tail(&hdr->list, &pool->busy_pool);
|
||||||
|
|
||||||
|
/* set busy flag to true. This is to catch double free request */
|
||||||
|
hdr->busy = true;
|
||||||
|
|
||||||
return hdr->buf;
|
return hdr->buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,37 +438,46 @@ void *msm_memory_alloc(struct msm_vidc_inst *inst, enum msm_memory_pool_type typ
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
INIT_LIST_HEAD(&hdr->list);
|
INIT_LIST_HEAD(&hdr->list);
|
||||||
|
hdr->type = type;
|
||||||
|
hdr->busy = true;
|
||||||
hdr->buf = (void *)(hdr + 1);
|
hdr->buf = (void *)(hdr + 1);
|
||||||
list_add_tail(&hdr->list, &pool->busy_pool);
|
list_add_tail(&hdr->list, &pool->busy_pool);
|
||||||
|
|
||||||
return hdr->buf;
|
return hdr->buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void msm_memory_free(struct msm_vidc_inst *inst, enum msm_memory_pool_type type,
|
void msm_memory_free(struct msm_vidc_inst *inst, void *vidc_buf)
|
||||||
void *vidc_buf)
|
|
||||||
{
|
{
|
||||||
struct msm_memory_alloc_header *hdr;
|
struct msm_memory_alloc_header *hdr;
|
||||||
struct msm_memory_pool *pool;
|
struct msm_memory_pool *pool;
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
if (!inst || !vidc_buf || type < 0 || type >= MSM_MEM_POOL_MAX) {
|
if (!inst || !vidc_buf) {
|
||||||
d_vpr_e("%s: Invalid params\n", __func__);
|
d_vpr_e("%s: Invalid params\n", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pool = &inst->pool[type];
|
hdr = (struct msm_memory_alloc_header *)vidc_buf - 1;
|
||||||
|
|
||||||
/* sanitize buffer addr */
|
/* sanitize buffer addr */
|
||||||
list_for_each_entry(hdr, &pool->busy_pool, list) {
|
if (hdr->buf != vidc_buf) {
|
||||||
if (hdr->buf == vidc_buf) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
i_vpr_e(inst, "%s: invalid buf addr %#x\n", __func__, vidc_buf);
|
i_vpr_e(inst, "%s: invalid buf addr %#x\n", __func__, vidc_buf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* sanitize pool type */
|
||||||
|
if (hdr->type < 0 || hdr->type >= MSM_MEM_POOL_MAX) {
|
||||||
|
i_vpr_e(inst, "%s: invalid pool type %#x\n", __func__, hdr->type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pool = &inst->pool[hdr->type];
|
||||||
|
|
||||||
|
/* catch double-free request */
|
||||||
|
if (!hdr->busy) {
|
||||||
|
i_vpr_e(inst, "%s: double free request. type %s, addr %#x\n", __func__,
|
||||||
|
pool->name, vidc_buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hdr->busy = false;
|
||||||
|
|
||||||
/* remove from busy pool */
|
/* remove from busy pool */
|
||||||
list_del_init(&hdr->list);
|
list_del_init(&hdr->list);
|
||||||
|
|
||||||
@@ -558,8 +570,6 @@ int msm_memory_pools_init(struct msm_vidc_inst *inst)
|
|||||||
i, buftype_size_name_arr[i].type);
|
i, buftype_size_name_arr[i].type);
|
||||||
return -EINVAL;
|
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].size = buftype_size_name_arr[i].size;
|
||||||
inst->pool[i].name = buftype_size_name_arr[i].name;
|
inst->pool[i].name = buftype_size_name_arr[i].name;
|
||||||
INIT_LIST_HEAD(&inst->pool[i].free_pool);
|
INIT_LIST_HEAD(&inst->pool[i].free_pool);
|
||||||
|
@@ -657,7 +657,7 @@ static int handle_non_read_only_buffer(struct msm_vidc_inst *inst,
|
|||||||
if (found) {
|
if (found) {
|
||||||
print_vidc_buffer(VIDC_LOW, "low ", "ro buf deleted", inst, ro_buf);
|
print_vidc_buffer(VIDC_LOW, "low ", "ro buf deleted", inst, ro_buf);
|
||||||
list_del(&ro_buf->list);
|
list_del(&ro_buf->list);
|
||||||
msm_memory_free(inst, MSM_MEM_POOL_BUFFER, ro_buf);
|
msm_memory_free(inst, ro_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Reference in New Issue
Block a user