diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index e54e240f0fb6..5a8a658a3c0b 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -5663,7 +5663,9 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, break; case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG: { struct cam_isp_bw_config *bw_config; + struct cam_isp_bw_config *bw_config_u; struct cam_isp_prepare_hw_update_data *prepare_hw_data; + size_t bw_config_size; CAM_WARN_RATE_LIMIT_CUSTOM(CAM_PERF, 300, 1, "Deprecated Blob TYPE_BW_CONFIG"); @@ -5672,11 +5674,26 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, return -EINVAL; } - bw_config = (struct cam_isp_bw_config *)blob_data; + bw_config_u = (struct cam_isp_bw_config *)blob_data; - if (bw_config->num_rdi > CAM_IFE_RDI_NUM_MAX) { - CAM_ERR(CAM_ISP, "Invalid num_rdi %u in bw config", + if (bw_config_u->num_rdi > CAM_IFE_RDI_NUM_MAX || !bw_config_u->num_rdi) { + CAM_ERR(CAM_ISP, "Invalid num_rdi %u in bw config, ctx_idx: %u", + bw_config_u->num_rdi, ife_mgr_ctx->ctx_index); + return -EINVAL; + } + + bw_config_size = sizeof(struct cam_isp_bw_config) + ((bw_config_u->num_rdi-1)* + sizeof(struct cam_isp_bw_vote)); + + rc = cam_common_mem_kdup((void **)&bw_config, bw_config_u, bw_config_size); + if (rc) { + CAM_ERR(CAM_ISP, "Alloc and copy request bw_config failed"); + return rc; + } + if (bw_config_u->num_rdi != bw_config->num_rdi) { + CAM_ERR(CAM_ISP, "num_rdi changed,userspace:%d, kernel:%d", bw_config_u->num_rdi, bw_config->num_rdi); + cam_common_mem_free(bw_config); return -EINVAL; } @@ -5689,6 +5706,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, "Max size exceeded in bw config num_rdi:%u size per port:%lu", bw_config->num_rdi, sizeof(struct cam_isp_bw_vote)); + cam_common_mem_free(bw_config); return -EINVAL; } } @@ -5701,12 +5719,14 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, blob_size, sizeof(struct cam_isp_bw_config) + (bw_config->num_rdi - 1) * sizeof(struct cam_isp_bw_vote)); + cam_common_mem_free(bw_config); return -EINVAL; } if (!prepare || !prepare->priv || (bw_config->usage_type >= CAM_IFE_HW_NUM_MAX)) { CAM_ERR(CAM_ISP, "Invalid inputs"); + cam_common_mem_free(bw_config); return -EINVAL; } @@ -5717,11 +5737,13 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, bw_config, sizeof(prepare_hw_data->bw_config[0])); prepare_hw_data->bw_config_version = CAM_ISP_BW_CONFIG_V1; prepare_hw_data->bw_config_valid[bw_config->usage_type] = true; + cam_common_mem_free(bw_config); } break; case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2: { size_t bw_config_size = 0; struct cam_isp_bw_config_v2 *bw_config; + struct cam_isp_bw_config_v2 *bw_config_u; struct cam_isp_prepare_hw_update_data *prepare_hw_data; if (blob_size < sizeof(struct cam_isp_bw_config_v2)) { @@ -5729,12 +5751,28 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, return -EINVAL; } - bw_config = (struct cam_isp_bw_config_v2 *)blob_data; + bw_config_u = (struct cam_isp_bw_config_v2 *)blob_data; - if ((bw_config->num_paths > CAM_ISP_MAX_PER_PATH_VOTES) || - !bw_config->num_paths) { - CAM_ERR(CAM_ISP, "Invalid num paths %d", - bw_config->num_paths); + if (bw_config_u->num_paths > CAM_ISP_MAX_PER_PATH_VOTES || + !bw_config_u->num_paths) { + CAM_ERR(CAM_ISP, "Invalid num paths %d ctx_idx: %u", + bw_config_u->num_paths, ife_mgr_ctx->ctx_index); + return -EINVAL; + } + + bw_config_size = sizeof(struct cam_isp_bw_config_v2) + ((bw_config_u->num_paths-1)* + sizeof(struct cam_axi_per_path_bw_vote)); + + rc = cam_common_mem_kdup((void **)&bw_config, bw_config_u, bw_config_size); + if (rc) { + CAM_ERR(CAM_ISP, "Alloc and copy request bw_config failed"); + return rc; + } + + if (bw_config_u->num_paths != bw_config->num_paths) { + CAM_ERR(CAM_ISP, "num_paths changed,userspace:%d, kernel:%d", bw_config_u->num_paths, + bw_config->num_paths); + cam_common_mem_free(bw_config); return -EINVAL; } @@ -5749,6 +5787,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, bw_config->num_paths - 1, sizeof( struct cam_axi_per_path_bw_vote)); + cam_common_mem_free(bw_config); return -EINVAL; } } @@ -5762,12 +5801,14 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, blob_size, bw_config->num_paths, sizeof(struct cam_isp_bw_config_v2), sizeof(struct cam_axi_per_path_bw_vote)); + cam_common_mem_free(bw_config); return -EINVAL; } if (!prepare || !prepare->priv || (bw_config->usage_type >= CAM_IFE_HW_NUM_MAX)) { CAM_ERR(CAM_ISP, "Invalid inputs"); + cam_common_mem_free(bw_config); return -EINVAL; } @@ -5785,6 +5826,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, prepare_hw_data->bw_config_version = CAM_ISP_BW_CONFIG_V2; prepare_hw_data->bw_config_valid[bw_config->usage_type] = true; + cam_common_mem_free(bw_config); } break; case CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG: { diff --git a/drivers/cam_utils/cam_common_util.c b/drivers/cam_utils/cam_common_util.c index dbcb31d7bf0e..8267b9b0ada4 100644 --- a/drivers/cam_utils/cam_common_util.c +++ b/drivers/cam_utils/cam_common_util.c @@ -1,11 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. */ #include #include #include +#include #include "cam_common_util.h" #include "cam_debug_util.h" @@ -48,3 +50,36 @@ uint32_t cam_common_util_remove_duplicate_arr(int32_t *arr, uint32_t num) return wr_idx; } + +int cam_common_mem_kdup(void **dst, + void *src, size_t size) +{ + gfp_t flag = GFP_KERNEL; + + if (!src || !dst || !size) { + CAM_ERR(CAM_UTIL, "Invalid params src: %pK dst: %pK size: %u", + src, dst, size); + return -EINVAL; + } + + if (!in_task()) + flag = GFP_ATOMIC; + + *dst = kvzalloc(size, flag); + if (!*dst) { + CAM_ERR(CAM_UTIL, "Failed to allocate memory with size: %u", size); + return -ENOMEM; + } + + memcpy(*dst, src, size); + CAM_DBG(CAM_UTIL, "Allocate and copy memory with size: %u", size); + + return 0; +} +EXPORT_SYMBOL(cam_common_mem_kdup); + +void cam_common_mem_free(void *memory) +{ + kvfree(memory); +} +EXPORT_SYMBOL(cam_common_mem_free); diff --git a/drivers/cam_utils/cam_common_util.h b/drivers/cam_utils/cam_common_util.h index ebe75f6eb5e9..9c2e5300100a 100644 --- a/drivers/cam_utils/cam_common_util.h +++ b/drivers/cam_utils/cam_common_util.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _CAM_COMMON_UTIL_H_ @@ -64,4 +65,22 @@ int cam_common_util_get_string_index(const char **strings, uint32_t cam_common_util_remove_duplicate_arr(int32_t *array, uint32_t num); +/** + * @brief: Memory alloc and copy + * + * @dst: Address of destination address of memory + * @src: Source address of memory + * @size: Length of memory + * + * @return 0 if success in register non-zero if failes + */ +int cam_common_mem_kdup(void **dst, void *src, size_t size); + +/** + * @brief: Free the memory + * + * @memory: Address of memory + */ +void cam_common_mem_free(void *memory); + #endif /* _CAM_COMMON_UTIL_H_ */