Parcourir la source

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 <[email protected]>
Govindaraj Rajagopal il y a 4 ans
Parent
commit
3e4248dfb0

+ 0 - 12
driver/vidc/inc/msm_vidc_driver.h

@@ -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);

+ 2 - 8
driver/vidc/inc/msm_vidc_inst.h

@@ -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;

+ 0 - 5
driver/vidc/inc/msm_vidc_internal.h

@@ -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,

+ 30 - 1
driver/vidc/inc/msm_vidc_memory.h

@@ -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_

+ 1 - 1
driver/vidc/src/msm_vdec.c

@@ -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;
 }

+ 8 - 5
driver/vidc/src/msm_vidc.c

@@ -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);

+ 22 - 262
driver/vidc/src/msm_vidc_driver.c

@@ -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)

+ 166 - 0
driver/vidc/src/msm_vidc_memory.c

@@ -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,

+ 3 - 2
driver/vidc/src/venus_hfi_response.c

@@ -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;