diff --git a/techpack/camera/drivers/cam_isp/cam_isp_context.c b/techpack/camera/drivers/cam_isp/cam_isp_context.c index da0a59be2353..b324b25e1a05 100644 --- a/techpack/camera/drivers/cam_isp/cam_isp_context.c +++ b/techpack/camera/drivers/cam_isp/cam_isp_context.c @@ -4791,8 +4791,10 @@ static int __cam_isp_ctx_config_dev_in_top_state( if ((len < sizeof(struct cam_packet)) || ((size_t)cmd->offset >= len - sizeof(struct cam_packet))) { CAM_ERR(CAM_ISP, "invalid buff length: %zu or offset", len); - rc = -EINVAL; - goto free_req; + spin_lock_bh(&ctx->lock); + list_add_tail(&req->list, &ctx->free_req_list); + spin_unlock_bh(&ctx->lock); + return -EINVAL; } remain_len -= (size_t)cmd->offset; diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/techpack/camera/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index c875fc67e0d7..829950936690 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -5993,7 +5993,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"); @@ -6002,10 +6004,24 @@ 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); return -EINVAL; } @@ -6053,6 +6069,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, 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)) { @@ -6060,12 +6077,27 @@ 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); return -EINVAL; } diff --git a/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 029ec542d491..cbe33b043a51 100644 --- a/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1065,9 +1065,10 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) /* Loop through multiple command buffers */ for (i = 1; i < csl_packet->num_cmd_buf; i++) { rc = cam_packet_util_validate_cmd_desc(&cmd_desc[i]); - if (rc) + if (rc) { + cam_mem_put_cpu_buf(config.packet_handle); return rc; - + } total_cmd_buf_in_bytes = cmd_desc[i].length; processed_cmd_buf_in_bytes = 0; if (!total_cmd_buf_in_bytes) @@ -1278,8 +1279,8 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) rc = fctrl->func_tbl.apply_setting(fctrl, 1); if (rc) { CAM_ERR(CAM_FLASH, "cannot apply fire settings rc = %d", rc); - return rc; } + cam_mem_put_cpu_buf(config.packet_handle); return rc; } break; @@ -1344,8 +1345,10 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) goto update_req_mgr; } case CAM_FLASH_PACKET_OPCODE_STREAM_OFF: { - if (fctrl->streamoff_count > 0) + if (fctrl->streamoff_count > 0) { + cam_mem_put_cpu_buf(config.packet_handle); return rc; + } CAM_DBG(CAM_FLASH, "Received Stream off Settings"); i2c_data = &(fctrl->i2c_data); @@ -1362,6 +1365,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) if (rc) { CAM_ERR(CAM_FLASH, "Failed in parsing i2c Stream off packets"); + cam_mem_put_cpu_buf(config.packet_handle); return rc; } break; @@ -1638,6 +1642,8 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) cmd_buf = (uint32_t *)((uint8_t *)cmd_buf_ptr + cmd_desc->offset); if (!cmd_buf) { + cam_mem_put_cpu_buf(cmd_desc->mem_handle); + cam_mem_put_cpu_buf(config.packet_handle); rc = -EINVAL; return rc; } @@ -1654,6 +1660,8 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) CAM_WARN(CAM_FLASH, "Rxed Flash fire ops without linking"); flash_data->cmn_attr.is_settings_valid = false; + cam_mem_put_cpu_buf(cmd_desc->mem_handle); + cam_mem_put_cpu_buf(config.packet_handle); return -EINVAL; } if (remain_len < sizeof(struct cam_flash_set_on_off)) { diff --git a/techpack/camera/drivers/cam_sensor_module/cam_ois/cam_ois_core.c b/techpack/camera/drivers/cam_sensor_module/cam_ois/cam_ois_core.c index e62e00d88d27..d8766a225046 100644 --- a/techpack/camera/drivers/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/techpack/camera/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -493,11 +493,13 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) size_t pkt_len; size_t remain_len = 0; struct cam_packet *csl_packet = NULL; + struct cam_packet *csl_packet_u = NULL; size_t len_of_buff = 0; uint32_t *offset = NULL, *cmd_buf; struct cam_ois_soc_private *soc_private = (struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private; struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info; + size_t packet_size = 0; ioctl_ctrl = (struct cam_control *)arg; if (copy_from_user(&dev_config, @@ -519,22 +521,36 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) CAM_ERR(CAM_OIS, "Inval cam_packet strut size: %zu, len_of_buff: %zu", sizeof(struct cam_packet), pkt_len); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return -EINVAL; + rc = -EINVAL; + goto put_ref; } remain_len -= (size_t)dev_config.offset; - csl_packet = (struct cam_packet *) + csl_packet_u = (struct cam_packet *) (generic_pkt_addr + (uint32_t)dev_config.offset); + packet_size = csl_packet_u->header.size; + if (packet_size <= remain_len) { + rc = cam_common_mem_kdup((void **)&csl_packet, + csl_packet_u, packet_size); + if (rc) { + CAM_ERR(CAM_OIS, "Alloc and copy request %lld packet fail", + csl_packet_u->header.request_id); + goto put_ref; + } + } else { + CAM_ERR(CAM_OIS, "Invalid packet header size %u", + packet_size); + rc = -EINVAL; + goto put_ref; + } if (cam_packet_util_validate_packet(csl_packet, remain_len)) { CAM_ERR(CAM_OIS, "Invalid packet params"); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return -EINVAL; + rc = -EINVAL; + goto end; } - switch (csl_packet->header.op_code & 0xFFFFFF) { case CAM_OIS_PACKET_OPCODE_INIT: offset = (uint32_t *)&csl_packet->payload; @@ -544,8 +560,10 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) /* Loop through multiple command buffers */ for (i = 0; i < csl_packet->num_cmd_buf; i++) { rc = cam_packet_util_validate_cmd_desc(&cmd_desc[i]); - if (rc) - return rc; + if (rc) { + CAM_ERR(CAM_OIS, "Invalid cmd desc"); + goto end; + } total_cmd_buf_in_bytes = cmd_desc[i].length; if (!total_cmd_buf_in_bytes) @@ -556,15 +574,14 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (rc < 0) { CAM_ERR(CAM_OIS, "Failed to get cpu buf : 0x%x", cmd_desc[i].mem_handle); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } cmd_buf = (uint32_t *)generic_ptr; if (!cmd_buf) { CAM_ERR(CAM_OIS, "invalid cmd buf"); + rc = -EINVAL; cam_mem_put_cpu_buf(cmd_desc[i].mem_handle); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return -EINVAL; + goto end; } if ((len_of_buff < sizeof(struct common_header)) || @@ -572,9 +589,9 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) sizeof(struct common_header)))) { CAM_ERR(CAM_OIS, "Invalid length for sensor cmd"); + rc = -EINVAL; cam_mem_put_cpu_buf(cmd_desc[i].mem_handle); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return -EINVAL; + goto end; } remain_len = len_of_buff - cmd_desc[i].offset; cmd_buf += cmd_desc[i].offset / sizeof(uint32_t); @@ -587,9 +604,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (rc < 0) { CAM_ERR(CAM_OIS, "Failed in parsing slave info"); - cam_mem_put_cpu_buf(cmd_desc[i].mem_handle); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + break; } break; case CAMERA_SENSOR_CMD_TYPE_PWR_UP: @@ -603,9 +618,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (rc) { CAM_ERR(CAM_OIS, "Failed: parse power settings"); - cam_mem_put_cpu_buf(cmd_desc[i].mem_handle); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + break; } break; default: @@ -623,9 +636,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (rc < 0) { CAM_ERR(CAM_OIS, "init parsing failed: %d", rc); - cam_mem_put_cpu_buf(cmd_desc[i].mem_handle); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + break; } } else if ((o_ctrl->is_ois_calib != 0) && (o_ctrl->i2c_calib_data.is_settings_valid == @@ -642,22 +653,22 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (rc < 0) { CAM_ERR(CAM_OIS, "Calib parsing failed: %d", rc); - cam_mem_put_cpu_buf(cmd_desc[i].mem_handle); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + break; } } break; } cam_mem_put_cpu_buf(cmd_desc[i].mem_handle); + + if (rc < 0) + goto end; } if (o_ctrl->cam_ois_state != CAM_OIS_CONFIG) { rc = cam_ois_power_up(o_ctrl); if (rc) { CAM_ERR(CAM_OIS, " OIS Power up failed"); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } o_ctrl->cam_ois_state = CAM_OIS_CONFIG; } @@ -714,8 +725,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) CAM_WARN(CAM_OIS, "Not in right state to control OIS: %d", o_ctrl->cam_ois_state); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } offset = (uint32_t *)&csl_packet->payload; offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); @@ -728,23 +738,20 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) cmd_desc, 1, NULL); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } rc = cam_ois_apply_settings(o_ctrl, i2c_reg_settings); if (rc < 0) { CAM_ERR(CAM_OIS, "Cannot apply mode settings"); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } rc = delete_request(i2c_reg_settings); if (rc < 0) { CAM_ERR(CAM_OIS, "Fail deleting Mode data: rc: %d", rc); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } break; case CAM_OIS_PACKET_OPCODE_READ: { @@ -756,16 +763,14 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) CAM_WARN(CAM_OIS, "Not in right state to read OIS: %d", o_ctrl->cam_ois_state); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } CAM_DBG(CAM_OIS, "number of I/O configs: %d:", csl_packet->num_io_configs); if (csl_packet->num_io_configs == 0) { CAM_ERR(CAM_OIS, "No I/O configs to process"); rc = -EINVAL; - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } INIT_LIST_HEAD(&(i2c_read_settings.list_head)); @@ -778,8 +783,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (io_cfg == NULL) { CAM_ERR(CAM_OIS, "I/O config is invalid(NULL)"); rc = -EINVAL; - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } offset = (uint32_t *)&csl_packet->payload; @@ -792,8 +796,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) cmd_desc, 1, &io_cfg[0]); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS read pkt parsing failed: %d", rc); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } rc = cam_sensor_i2c_read_data( @@ -802,8 +805,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (rc < 0) { CAM_ERR(CAM_OIS, "cannot read data rc: %d", rc); delete_request(&i2c_read_settings); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } if (csl_packet->num_io_configs > 1) { @@ -813,8 +815,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) CAM_ERR(CAM_OIS, "write qtimer failed rc: %d", rc); delete_request(&i2c_read_settings); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } } @@ -822,8 +823,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (rc < 0) { CAM_ERR(CAM_OIS, "Failed in deleting the read settings"); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } break; } @@ -833,8 +833,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) CAM_ERR(CAM_OIS, "Not in right state to write time to OIS: %d", o_ctrl->cam_ois_state); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } offset = (uint32_t *)&csl_packet->payload; offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); @@ -847,47 +846,45 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) cmd_desc, 1, NULL); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } rc = cam_ois_update_time(i2c_reg_settings); if (rc < 0) { CAM_ERR(CAM_OIS, "Cannot update time"); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } rc = cam_ois_apply_settings(o_ctrl, i2c_reg_settings); if (rc < 0) { CAM_ERR(CAM_OIS, "Cannot apply mode settings"); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } rc = delete_request(i2c_reg_settings); if (rc < 0) { CAM_ERR(CAM_OIS, "Fail deleting Mode data: rc: %d", rc); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } break; } default: CAM_ERR(CAM_OIS, "Invalid Opcode: %d", (csl_packet->header.op_code & 0xFFFFFF)); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return -EINVAL; + rc = -EINVAL; + goto end; } - if (!rc) { - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; - } + if (!rc) + goto end; + pwr_dwn: - cam_mem_put_cpu_buf(dev_config.packet_handle); cam_ois_power_down(o_ctrl); +end: + cam_common_mem_free(csl_packet); +put_ref: + cam_mem_put_cpu_buf(dev_config.packet_handle); return rc; } diff --git a/techpack/camera/drivers/cam_utils/cam_common_util.c b/techpack/camera/drivers/cam_utils/cam_common_util.c index 23681509f490..c221741bdeff 100644 --- a/techpack/camera/drivers/cam_utils/cam_common_util.c +++ b/techpack/camera/drivers/cam_utils/cam_common_util.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -72,3 +73,36 @@ void cam_common_util_thread_switch_delay_detect( } } + +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 = kzalloc(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) +{ + kfree(memory); +} +EXPORT_SYMBOL(cam_common_mem_free); diff --git a/techpack/camera/drivers/cam_utils/cam_common_util.h b/techpack/camera/drivers/cam_utils/cam_common_util.h index 867aa5753f5a..8ef0c52f90d8 100644 --- a/techpack/camera/drivers/cam_utils/cam_common_util.h +++ b/techpack/camera/drivers/cam_utils/cam_common_util.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _CAM_COMMON_UTIL_H_ @@ -85,4 +86,21 @@ uint32_t cam_common_util_remove_duplicate_arr(int32_t *array, void cam_common_util_thread_switch_delay_detect(const char *token, ktime_t scheduled_time, uint32_t threshold); +/** + * @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_ */