Merge "msm: camera: cre: Fix null pointer dereference in CRE driver" into camera-kernel.lnx.7.0

This commit is contained in:
Camera Software Integration
2024-02-11 07:20:30 -08:00
committed by Gerrit - the friendly Code Review server
3 changed files with 56 additions and 37 deletions

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 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 <linux/mutex.h>
@@ -760,38 +760,38 @@ static int cam_cre_mgr_process_cmd(void *priv, void *data)
task_data = (struct cre_cmd_work_data *)data;
mutex_lock(&hw_mgr->hw_mgr_mutex);
mutex_lock(&ctx_data->ctx_mutex);
if (ctx_data->ctx_state != CRE_CTX_STATE_ACQUIRED) {
mutex_unlock(&hw_mgr->hw_mgr_mutex);
CAM_ERR(CAM_CRE, "ctx id :%u is not in use",
ctx_data->ctx_id);
return -EINVAL;
rc = -EINVAL;
goto err;
}
if (task_data->req_idx >= CAM_CTX_REQ_MAX) {
mutex_unlock(&hw_mgr->hw_mgr_mutex);
CAM_ERR(CAM_CRE, "Invalid reqIdx = %llu",
task_data->req_idx);
return -EINVAL;
rc = -EINVAL;
goto err;
}
if (task_data->request_id <= ctx_data->last_flush_req) {
CAM_WARN(CAM_CRE,
"request %lld has been flushed, reject packet", task_data->request_id);
rc = -EINVAL;
goto err;
}
cre_req = ctx_data->req_list[task_data->req_idx];
if (cre_req->request_id > ctx_data->last_flush_req)
ctx_data->last_flush_req = 0;
if (cre_req->request_id <= ctx_data->last_flush_req) {
CAM_WARN(CAM_CRE,
"request %lld has been flushed, reject packet",
cre_req->request_id, ctx_data->last_flush_req);
mutex_unlock(&hw_mgr->hw_mgr_mutex);
return -EINVAL;
}
if (!cam_cre_is_pending_request(ctx_data)) {
CAM_WARN(CAM_CRE, "no pending req, req %lld last flush %lld",
cre_req->request_id, ctx_data->last_flush_req);
mutex_unlock(&hw_mgr->hw_mgr_mutex);
return -EINVAL;
rc = -EINVAL;
goto err;
}
hw_mgr = task_data->data;
num_batch = cre_req->num_batch;
@@ -815,7 +815,8 @@ static int cam_cre_mgr_process_cmd(void *priv, void *data)
cam_cre_device_timer_reset(cre_hw_mgr);
CAM_ERR(CAM_CRE,
"Timedout waiting for bufdone on last frame");
return -ETIMEDOUT;
rc = -EINVAL;
goto err;
} else {
reinit_completion(&ctx_data->cre_top->bufdone);
CAM_INFO(CAM_CRE,
@@ -827,6 +828,8 @@ static int cam_cre_mgr_process_cmd(void *priv, void *data)
cam_cre_mgr_update_reg_set(hw_mgr, cre_req, i);
cam_cre_ctx_wait_for_idle_irq(ctx_data);
}
err:
mutex_unlock(&ctx_data->ctx_mutex);
mutex_unlock(&hw_mgr->hw_mgr_mutex);
return rc;
@@ -857,16 +860,16 @@ static int32_t cam_cre_mgr_process_msg(void *priv, void *data)
cfg_req = list_first_entry(&hw_mgr->hw_config_req_list,
struct cam_cre_hw_cfg_req, list);
if (!cfg_req) {
CAM_ERR(CAM_JPEG, "no request");
CAM_ERR(CAM_CRE, "Hw config req list empty");
rc = -EFAULT;
mutex_unlock(&hw_mgr->hw_mgr_mutex);
return rc;
}
list_del_init(&cfg_req->list);
mutex_unlock(&hw_mgr->hw_mgr_mutex);
if (cfg_req->ctx_id < 0) {
CAM_ERR(CAM_CRE, "No valid context to handle error");
mutex_unlock(&hw_mgr->hw_mgr_mutex);
return -EINVAL;
}
@@ -877,18 +880,25 @@ static int32_t cam_cre_mgr_process_msg(void *priv, void *data)
if (ctx->ctx_state != CRE_CTX_STATE_ACQUIRED) {
CAM_DBG(CAM_CRE, "ctx id: %d not in right state: %d",
cfg_req->ctx_id, ctx->ctx_state);
mutex_unlock(&ctx->ctx_mutex);
return -EINVAL;
rc = -EINVAL;
goto end;
}
active_req_idx = find_next_bit(ctx->bitmap, ctx->bits, ctx->last_done_req_idx);
CAM_DBG(CAM_CRE, "Ctx %d active_req_idx %d last_done_req_idx %d", ctx->ctx_id,
active_req_idx, ctx->last_done_req_idx);
if (active_req_idx >= CAM_CTX_REQ_MAX) {
CAM_WARN(CAM_CRE, "ctx %d not valid req idx active_req_idx %d", active_req_idx);
rc = -EINVAL;
goto end;
}
active_req = ctx->req_list[active_req_idx];
if (!active_req) {
CAM_ERR(CAM_CRE, "Active req cannot be null");
return -EINVAL;
rc = -EINVAL;
goto end;
}
if (irq_data.error) {
@@ -924,8 +934,10 @@ static int32_t cam_cre_mgr_process_msg(void *priv, void *data)
ctx->req_list[active_req_idx] = NULL;
}
}
end:
list_add_tail(&cfg_req->list, &hw_mgr->free_req_list);
mutex_unlock(&ctx->ctx_mutex);
mutex_unlock(&hw_mgr->hw_mgr_mutex);
return rc;
}
@@ -2344,6 +2356,7 @@ static int cam_cre_mgr_enqueue_config(struct cam_cre_hw_mgr *hw_mgr,
task_data = (struct cre_cmd_work_data *)task->payload;
task_data->data = (void *)hw_mgr;
task_data->req_idx = cre_req->req_idx;
task_data->request_id = cre_req->request_id;
task_data->type = CRE_WORKQ_TASK_CMD_TYPE;
task->process_cb = cam_cre_mgr_process_cmd;
@@ -2366,7 +2379,6 @@ static int cam_cre_mgr_config_hw(void *hw_priv, void *hw_config_args)
struct cam_cre_request *cre_req = NULL;
struct cam_cre_hw_cfg_req *cfg_req = NULL;
CAM_DBG(CAM_CRE, "E");
if (!hw_mgr || !config_args) {
CAM_ERR(CAM_CRE, "Invalid arguments %pK %pK",
hw_mgr, config_args);
@@ -2382,18 +2394,16 @@ static int cam_cre_mgr_config_hw(void *hw_priv, void *hw_config_args)
mutex_lock(&hw_mgr->hw_mgr_mutex);
mutex_lock(&ctx_data->ctx_mutex);
if (ctx_data->ctx_state != CRE_CTX_STATE_ACQUIRED) {
mutex_unlock(&ctx_data->ctx_mutex);
mutex_unlock(&hw_mgr->hw_mgr_mutex);
CAM_ERR(CAM_CRE, "ctx id :%u is not in use",
ctx_data->ctx_id);
return -EINVAL;
rc= -EINVAL;
goto end;
}
if (list_empty(&hw_mgr->free_req_list)) {
mutex_unlock(&ctx_data->ctx_mutex);
mutex_unlock(&hw_mgr->hw_mgr_mutex);
CAM_ERR(CAM_JPEG, "list empty");
return -ENOMEM;
CAM_ERR(CAM_CRE, "No request in free list");
rc = -ENOMEM;
goto end;
}
cfg_req = list_first_entry(&hw_mgr->free_req_list,
@@ -2405,14 +2415,19 @@ static int cam_cre_mgr_config_hw(void *hw_priv, void *hw_config_args)
cam_cre_mgr_cre_clk_update(hw_mgr, ctx_data, cre_req->req_idx);
ctx_data->req_list[cre_req->req_idx]->submit_timestamp = ktime_get();
CAM_DBG(CAM_CRE, "ctx id :%u req id %lld", ctx_data->ctx_id, cre_req->request_id);
cfg_req->req_id = cre_req->request_id;
cfg_req->ctx_id = ctx_data->ctx_id;
if (cre_req->request_id <= ctx_data->last_flush_req)
if (cre_req->request_id <= ctx_data->last_flush_req) {
CAM_WARN(CAM_CRE,
"Anomaly submitting flushed req %llu [last_flush %llu] in ctx %u",
cre_req->request_id, ctx_data->last_flush_req,
ctx_data->ctx_id);
rc = -EINVAL;
goto end;
}
list_add_tail(&cfg_req->list, &hw_mgr->hw_config_req_list);
@@ -2429,6 +2444,7 @@ static int cam_cre_mgr_config_hw(void *hw_priv, void *hw_config_args)
return rc;
config_err:
cam_cre_mgr_handle_config_err(config_args, ctx_data);
end:
mutex_unlock(&ctx_data->ctx_mutex);
mutex_unlock(&hw_mgr->hw_mgr_mutex);
return rc;

View File

@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 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.
*/
#ifndef CAM_CRE_HW_MGR_H
@@ -148,12 +148,14 @@ struct cam_cre_clk_info {
*
* @type: Type of work data
* @data: Private data
* @req_id: Request Idx
* @req_idx: Request Idx
* @request_id: Request id
*/
struct cre_cmd_work_data {
uint32_t type;
void *data;
int64_t req_idx;
uint64_t request_id;
};
/**

View File

@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/platform_device.h>
#include <linux/delay.h>
@@ -46,8 +47,8 @@ static int cam_cre_top_reset(struct cam_cre_hw *cre_hw_info,
cam_io_w_mb(top_reg_val->irq_mask,
cre_hw_info->top_reg_offset->base + top_reg->irq_mask);
/* CRE SW RESET */
cam_io_w_mb(top_reg_val->sw_reset_cmd,
/* CRE HW RESET */
cam_io_w_mb(top_reg_val->hw_reset_cmd,
cre_hw_info->top_reg_offset->base + top_reg->reset_cmd);
rc = wait_for_completion_timeout(