diff --git a/driver/vidc/inc/msm_vidc_driver.h b/driver/vidc/inc/msm_vidc_driver.h index d9f1aa96a2..706ad5870a 100644 --- a/driver/vidc/inc/msm_vidc_driver.h +++ b/driver/vidc/inc/msm_vidc_driver.h @@ -255,6 +255,15 @@ 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); +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_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_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); diff --git a/driver/vidc/inc/msm_vidc_inst.h b/driver/vidc/inc/msm_vidc_inst.h index e8577be7a6..c62fe592c5 100644 --- a/driver/vidc/inc/msm_vidc_inst.h +++ b/driver/vidc/inc/msm_vidc_inst.h @@ -27,6 +27,12 @@ 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_allocations_info { struct msm_vidc_allocations bin; struct msm_vidc_allocations arp; @@ -111,6 +117,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_vidc_buffers_info buffers; struct msm_vidc_mappings_info mappings; struct msm_vidc_allocations_info allocations; diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index 487e8a3e50..7ee7d1ded7 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -750,7 +750,6 @@ struct msm_vidc_allocations { struct msm_vidc_map { struct list_head list; - bool valid; enum msm_vidc_buffer_type type; enum msm_vidc_buffer_region region; struct dma_buf *dmabuf; @@ -767,7 +766,6 @@ struct msm_vidc_mappings { struct msm_vidc_buffer { struct list_head list; - bool valid; enum msm_vidc_buffer_type type; u32 index; int fd; @@ -790,6 +788,11 @@ struct msm_vidc_buffers { bool reuse; }; +struct msm_vidc_pool { + struct list_head list; + u32 count; +}; + enum msm_vidc_allow { MSM_VIDC_DISALLOW = 0, MSM_VIDC_ALLOW, diff --git a/driver/vidc/inc/msm_vidc_memory.h b/driver/vidc/inc/msm_vidc_memory.h index 7522792de6..cb183ad3f9 100644 --- a/driver/vidc/inc/msm_vidc_memory.h +++ b/driver/vidc/inc/msm_vidc_memory.h @@ -17,8 +17,6 @@ int msm_vidc_memory_map(struct msm_vidc_core *core, struct msm_vidc_map *map); int msm_vidc_memory_unmap(struct msm_vidc_core *core, struct msm_vidc_map *map); -int msm_vidc_memory_unmap_completely(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); diff --git a/driver/vidc/src/msm_vidc.c b/driver/vidc/src/msm_vidc.c index 82d245ca83..eac500eb0d 100644 --- a/driver/vidc/src/msm_vidc.c +++ b/driver/vidc/src/msm_vidc.c @@ -745,6 +745,9 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) handle_session_response_work_handler); 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->buffers.input.list); INIT_LIST_HEAD(&inst->buffers.input_meta.list); INIT_LIST_HEAD(&inst->buffers.output.list); diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index 8c5dba84b2..f580171b73 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -1735,7 +1735,6 @@ static int vb2_buffer_to_driver(struct vb2_buffer *vb2, return -EINVAL; } - buf->valid = true; buf->type = v4l2_type_to_driver(vb2->type, __func__); if (!buf->type) return -EINVAL; @@ -1778,13 +1777,217 @@ 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); - kfree(ro_buf); + msm_vidc_put_vidc_buffer(inst, ro_buf); break; } } return rc; } +int msm_vidc_memory_unmap_completely(struct msm_vidc_inst *inst, + struct msm_vidc_map *map) +{ + int rc = 0; + + if (!inst || !map) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (!map->refcount) + return 0; + + while (map->refcount) { + rc = msm_vidc_memory_unmap(inst->core, map); + if (rc) + break; + if (!map->refcount) { + msm_vidc_memory_put_dmabuf(map->dmabuf); + list_del(&map->list); + msm_vidc_put_map_buffer(inst, map); + break; + } + } + return rc; +} + +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_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) { @@ -1802,7 +2005,7 @@ int msm_vidc_unmap_buffers(struct msm_vidc_inst *inst, return -EINVAL; list_for_each_entry_safe(map, dummy, &mappings->list, list) { - msm_vidc_memory_unmap_completely(inst->core, map); + msm_vidc_memory_unmap_completely(inst, map); } return rc; @@ -1847,8 +2050,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); - kfree(map); - map = NULL; + msm_vidc_put_map_buffer(inst, map); } return rc; @@ -1883,7 +2085,7 @@ int msm_vidc_map_driver_buf(struct msm_vidc_inst *inst, } if (!found) { /* new buffer case */ - map = kzalloc(sizeof(struct msm_vidc_map), GFP_KERNEL); + map = msm_vidc_get_map_buffer(inst); if (!map) { i_vpr_e(inst, "%s: alloc failed\n", __func__); return -ENOMEM; @@ -1900,7 +2102,7 @@ int msm_vidc_map_driver_buf(struct msm_vidc_inst *inst, rc = msm_vidc_memory_map(inst->core, map); if (rc) { msm_vidc_memory_put_dmabuf(map->dmabuf); - kfree(map); + msm_vidc_put_map_buffer(inst, map); return rc; } } @@ -1931,7 +2133,7 @@ int msm_vidc_put_driver_buf(struct msm_vidc_inst *inst, /* delete the buffer from buffers->list */ list_del(&buf->list); - kfree(buf); + msm_vidc_put_vidc_buffer(inst, buf); return rc; } @@ -1957,7 +2159,7 @@ struct msm_vidc_buffer *msm_vidc_get_driver_buf(struct msm_vidc_inst *inst, if (!buffers) return NULL; - buf = kzalloc(sizeof(struct msm_vidc_buffer), GFP_KERNEL); + buf = msm_vidc_get_vidc_buffer(inst); if (!buf) { i_vpr_e(inst, "%s: alloc failed\n", __func__); return NULL; @@ -1985,7 +2187,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); - kfree(buf); + msm_vidc_put_vidc_buffer(inst, buf); return NULL; } @@ -2011,8 +2213,6 @@ struct msm_vidc_buffer *get_meta_buffer(struct msm_vidc_inst *inst, return NULL; } list_for_each_entry(mbuf, &buffers->list, list) { - if (!mbuf->valid) - continue; if (mbuf->index == buf->index) { found = true; break; @@ -2376,7 +2576,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); - kfree(map); + msm_vidc_put_map_buffer(inst, map); break; } } @@ -2385,7 +2585,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); - kfree(alloc); + msm_vidc_put_alloc_buffer(inst, alloc); break; } } @@ -2393,7 +2593,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); - kfree(buf); + msm_vidc_put_vidc_buffer(inst, buf); break; } } @@ -2473,19 +2673,18 @@ int msm_vidc_create_internal_buffer(struct msm_vidc_inst *inst, if (!buffers->size) return 0; - buffer = kzalloc(sizeof(struct msm_vidc_buffer), GFP_KERNEL); + buffer = msm_vidc_get_vidc_buffer(inst); if (!buffer) { i_vpr_e(inst, "%s: buf alloc failed\n", __func__); return -ENOMEM; } INIT_LIST_HEAD(&buffer->list); - buffer->valid = true; buffer->type = buffer_type; buffer->index = index; buffer->buffer_size = buffers->size; list_add_tail(&buffer->list, &buffers->list); - alloc = kzalloc(sizeof(struct msm_vidc_alloc), GFP_KERNEL); + alloc = msm_vidc_get_alloc_buffer(inst); if (!alloc) { i_vpr_e(inst, "%s: alloc failed\n", __func__); return -ENOMEM; @@ -2501,7 +2700,7 @@ int msm_vidc_create_internal_buffer(struct msm_vidc_inst *inst, return -ENOMEM; list_add_tail(&alloc->list, &allocations->list); - map = kzalloc(sizeof(struct msm_vidc_map), GFP_KERNEL); + map = msm_vidc_get_map_buffer(inst); if (!map) { i_vpr_e(inst, "%s: map alloc failed\n", __func__); return -ENOMEM; @@ -3511,7 +3710,7 @@ int msm_vidc_print_inst_info(struct msm_vidc_inst *inst) buffers->extra_count, buffers->actual_count); list_for_each_entry(buf, &buffers->list, list) { - if (!buf->valid || !buf->dmabuf) + if (!buf->dmabuf) continue; dbuf = (struct dma_buf *)buf->dmabuf; i_vpr_e(inst, @@ -3814,7 +4013,7 @@ int msm_vidc_flush_delayed_unmap_buffers(struct msm_vidc_inst *inst, __func__, map->refcount, map->device_addr); msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); } - msm_vidc_memory_unmap_completely(inst->core, map); + msm_vidc_memory_unmap_completely(inst, map); } } } @@ -3876,8 +4075,14 @@ 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); - kfree(buf); + msm_vidc_put_vidc_buffer(inst, buf); } + + /* destroy buffers from pool */ + msm_vidc_destroy_vidc_buffer(inst); + msm_vidc_destroy_alloc_buffer(inst); + msm_vidc_destroy_map_buffer(inst); + } static void msm_vidc_close_helper(struct kref *kref) diff --git a/driver/vidc/src/msm_vidc_memory.c b/driver/vidc/src/msm_vidc_memory.c index 9fe531fbfb..2db0867f3e 100644 --- a/driver/vidc/src/msm_vidc_memory.c +++ b/driver/vidc/src/msm_vidc_memory.c @@ -202,34 +202,6 @@ exit: return rc; } -int msm_vidc_memory_unmap_completely(struct msm_vidc_core *core, - struct msm_vidc_map *map) -{ - int rc = 0; - - if (!core || !map) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - if (!map->refcount) - return 0; - - while (map->refcount) { - rc = msm_vidc_memory_unmap(core, map); - if (rc) - break; - if (!map->refcount) { - msm_vidc_memory_put_dmabuf(map->dmabuf); - list_del(&map->list); - kfree(map); - map = NULL; - break; - } - } - return rc; -} - int msm_vidc_memory_alloc(struct msm_vidc_core *core, struct msm_vidc_alloc *mem) { int rc = 0; diff --git a/driver/vidc/src/venus_hfi_response.c b/driver/vidc/src/venus_hfi_response.c index a9a3a7d640..e63d52b75d 100644 --- a/driver/vidc/src/venus_hfi_response.c +++ b/driver/vidc/src/venus_hfi_response.c @@ -515,11 +515,12 @@ static int handle_read_only_buffer(struct msm_vidc_inst *inst, */ if (buffer->attr & MSM_VIDC_ATTR_READ_ONLY) { if (!found) { - ro_buf = kmemdup(buffer, sizeof(struct msm_vidc_buffer), GFP_KERNEL); + ro_buf = msm_vidc_get_vidc_buffer(inst); if (!ro_buf) { i_vpr_e(inst, "%s: buffer alloc failed\n", __func__); return -ENOMEM; } + memcpy(ro_buf, buffer, sizeof(struct msm_vidc_buffer)); INIT_LIST_HEAD(&ro_buf->list); list_add_tail(&ro_buf->list, &ro_buffers->list); print_vidc_buffer(VIDC_LOW, "low", "ro buf added", inst, ro_buf); @@ -528,8 +529,7 @@ static int handle_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); - kfree(ro_buf); - ro_buf = NULL; + msm_vidc_put_vidc_buffer(inst, ro_buf); } }