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

committed by
Gerrit - the friendly Code Review server

commit
477f423ee1
@@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
* 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>
|
#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;
|
task_data = (struct cre_cmd_work_data *)data;
|
||||||
|
|
||||||
mutex_lock(&hw_mgr->hw_mgr_mutex);
|
mutex_lock(&hw_mgr->hw_mgr_mutex);
|
||||||
|
mutex_lock(&ctx_data->ctx_mutex);
|
||||||
|
|
||||||
if (ctx_data->ctx_state != CRE_CTX_STATE_ACQUIRED) {
|
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",
|
CAM_ERR(CAM_CRE, "ctx id :%u is not in use",
|
||||||
ctx_data->ctx_id);
|
ctx_data->ctx_id);
|
||||||
return -EINVAL;
|
rc = -EINVAL;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task_data->req_idx >= CAM_CTX_REQ_MAX) {
|
if (task_data->req_idx >= CAM_CTX_REQ_MAX) {
|
||||||
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
|
||||||
CAM_ERR(CAM_CRE, "Invalid reqIdx = %llu",
|
CAM_ERR(CAM_CRE, "Invalid reqIdx = %llu",
|
||||||
task_data->req_idx);
|
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];
|
cre_req = ctx_data->req_list[task_data->req_idx];
|
||||||
if (cre_req->request_id > ctx_data->last_flush_req)
|
if (cre_req->request_id > ctx_data->last_flush_req)
|
||||||
ctx_data->last_flush_req = 0;
|
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)) {
|
if (!cam_cre_is_pending_request(ctx_data)) {
|
||||||
CAM_WARN(CAM_CRE, "no pending req, req %lld last flush %lld",
|
CAM_WARN(CAM_CRE, "no pending req, req %lld last flush %lld",
|
||||||
cre_req->request_id, ctx_data->last_flush_req);
|
cre_req->request_id, ctx_data->last_flush_req);
|
||||||
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
rc = -EINVAL;
|
||||||
return -EINVAL;
|
goto err;
|
||||||
}
|
}
|
||||||
hw_mgr = task_data->data;
|
hw_mgr = task_data->data;
|
||||||
num_batch = cre_req->num_batch;
|
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_cre_device_timer_reset(cre_hw_mgr);
|
||||||
CAM_ERR(CAM_CRE,
|
CAM_ERR(CAM_CRE,
|
||||||
"Timedout waiting for bufdone on last frame");
|
"Timedout waiting for bufdone on last frame");
|
||||||
return -ETIMEDOUT;
|
rc = -EINVAL;
|
||||||
|
goto err;
|
||||||
} else {
|
} else {
|
||||||
reinit_completion(&ctx_data->cre_top->bufdone);
|
reinit_completion(&ctx_data->cre_top->bufdone);
|
||||||
CAM_INFO(CAM_CRE,
|
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_mgr_update_reg_set(hw_mgr, cre_req, i);
|
||||||
cam_cre_ctx_wait_for_idle_irq(ctx_data);
|
cam_cre_ctx_wait_for_idle_irq(ctx_data);
|
||||||
}
|
}
|
||||||
|
err:
|
||||||
|
mutex_unlock(&ctx_data->ctx_mutex);
|
||||||
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
||||||
|
|
||||||
return rc;
|
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,
|
cfg_req = list_first_entry(&hw_mgr->hw_config_req_list,
|
||||||
struct cam_cre_hw_cfg_req, list);
|
struct cam_cre_hw_cfg_req, list);
|
||||||
if (!cfg_req) {
|
if (!cfg_req) {
|
||||||
CAM_ERR(CAM_JPEG, "no request");
|
CAM_ERR(CAM_CRE, "Hw config req list empty");
|
||||||
rc = -EFAULT;
|
rc = -EFAULT;
|
||||||
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
list_del_init(&cfg_req->list);
|
list_del_init(&cfg_req->list);
|
||||||
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
|
||||||
|
|
||||||
if (cfg_req->ctx_id < 0) {
|
if (cfg_req->ctx_id < 0) {
|
||||||
CAM_ERR(CAM_CRE, "No valid context to handle error");
|
CAM_ERR(CAM_CRE, "No valid context to handle error");
|
||||||
|
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
||||||
return -EINVAL;
|
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) {
|
if (ctx->ctx_state != CRE_CTX_STATE_ACQUIRED) {
|
||||||
CAM_DBG(CAM_CRE, "ctx id: %d not in right state: %d",
|
CAM_DBG(CAM_CRE, "ctx id: %d not in right state: %d",
|
||||||
cfg_req->ctx_id, ctx->ctx_state);
|
cfg_req->ctx_id, ctx->ctx_state);
|
||||||
mutex_unlock(&ctx->ctx_mutex);
|
rc = -EINVAL;
|
||||||
return -EINVAL;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
active_req_idx = find_next_bit(ctx->bitmap, ctx->bits, ctx->last_done_req_idx);
|
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,
|
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);
|
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];
|
active_req = ctx->req_list[active_req_idx];
|
||||||
if (!active_req) {
|
if (!active_req) {
|
||||||
CAM_ERR(CAM_CRE, "Active req cannot be null");
|
CAM_ERR(CAM_CRE, "Active req cannot be null");
|
||||||
return -EINVAL;
|
rc = -EINVAL;
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (irq_data.error) {
|
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;
|
ctx->req_list[active_req_idx] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
end:
|
||||||
list_add_tail(&cfg_req->list, &hw_mgr->free_req_list);
|
list_add_tail(&cfg_req->list, &hw_mgr->free_req_list);
|
||||||
mutex_unlock(&ctx->ctx_mutex);
|
mutex_unlock(&ctx->ctx_mutex);
|
||||||
|
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
||||||
return rc;
|
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 = (struct cre_cmd_work_data *)task->payload;
|
||||||
task_data->data = (void *)hw_mgr;
|
task_data->data = (void *)hw_mgr;
|
||||||
task_data->req_idx = cre_req->req_idx;
|
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_data->type = CRE_WORKQ_TASK_CMD_TYPE;
|
||||||
task->process_cb = cam_cre_mgr_process_cmd;
|
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_request *cre_req = NULL;
|
||||||
struct cam_cre_hw_cfg_req *cfg_req = NULL;
|
struct cam_cre_hw_cfg_req *cfg_req = NULL;
|
||||||
|
|
||||||
CAM_DBG(CAM_CRE, "E");
|
|
||||||
if (!hw_mgr || !config_args) {
|
if (!hw_mgr || !config_args) {
|
||||||
CAM_ERR(CAM_CRE, "Invalid arguments %pK %pK",
|
CAM_ERR(CAM_CRE, "Invalid arguments %pK %pK",
|
||||||
hw_mgr, config_args);
|
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(&hw_mgr->hw_mgr_mutex);
|
||||||
mutex_lock(&ctx_data->ctx_mutex);
|
mutex_lock(&ctx_data->ctx_mutex);
|
||||||
if (ctx_data->ctx_state != CRE_CTX_STATE_ACQUIRED) {
|
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",
|
CAM_ERR(CAM_CRE, "ctx id :%u is not in use",
|
||||||
ctx_data->ctx_id);
|
ctx_data->ctx_id);
|
||||||
return -EINVAL;
|
rc= -EINVAL;
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list_empty(&hw_mgr->free_req_list)) {
|
if (list_empty(&hw_mgr->free_req_list)) {
|
||||||
mutex_unlock(&ctx_data->ctx_mutex);
|
CAM_ERR(CAM_CRE, "No request in free list");
|
||||||
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
rc = -ENOMEM;
|
||||||
CAM_ERR(CAM_JPEG, "list empty");
|
goto end;
|
||||||
return -ENOMEM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg_req = list_first_entry(&hw_mgr->free_req_list,
|
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);
|
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();
|
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->req_id = cre_req->request_id;
|
||||||
cfg_req->ctx_id = ctx_data->ctx_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,
|
CAM_WARN(CAM_CRE,
|
||||||
"Anomaly submitting flushed req %llu [last_flush %llu] in ctx %u",
|
"Anomaly submitting flushed req %llu [last_flush %llu] in ctx %u",
|
||||||
cre_req->request_id, ctx_data->last_flush_req,
|
cre_req->request_id, ctx_data->last_flush_req,
|
||||||
ctx_data->ctx_id);
|
ctx_data->ctx_id);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
list_add_tail(&cfg_req->list, &hw_mgr->hw_config_req_list);
|
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;
|
return rc;
|
||||||
config_err:
|
config_err:
|
||||||
cam_cre_mgr_handle_config_err(config_args, ctx_data);
|
cam_cre_mgr_handle_config_err(config_args, ctx_data);
|
||||||
|
end:
|
||||||
mutex_unlock(&ctx_data->ctx_mutex);
|
mutex_unlock(&ctx_data->ctx_mutex);
|
||||||
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
||||||
return rc;
|
return rc;
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
* 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
|
#ifndef CAM_CRE_HW_MGR_H
|
||||||
@@ -146,14 +146,16 @@ struct cam_cre_clk_info {
|
|||||||
/**
|
/**
|
||||||
* struct cre_cmd_work_data
|
* struct cre_cmd_work_data
|
||||||
*
|
*
|
||||||
* @type: Type of work data
|
* @type: Type of work data
|
||||||
* @data: Private data
|
* @data: Private data
|
||||||
* @req_id: Request Idx
|
* @req_idx: Request Idx
|
||||||
|
* @request_id: Request id
|
||||||
*/
|
*/
|
||||||
struct cre_cmd_work_data {
|
struct cre_cmd_work_data {
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
void *data;
|
void *data;
|
||||||
int64_t req_idx;
|
int64_t req_idx;
|
||||||
|
uint64_t request_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
* 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/platform_device.h>
|
||||||
#include <linux/delay.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,
|
cam_io_w_mb(top_reg_val->irq_mask,
|
||||||
cre_hw_info->top_reg_offset->base + top_reg->irq_mask);
|
cre_hw_info->top_reg_offset->base + top_reg->irq_mask);
|
||||||
|
|
||||||
/* CRE SW RESET */
|
/* CRE HW RESET */
|
||||||
cam_io_w_mb(top_reg_val->sw_reset_cmd,
|
cam_io_w_mb(top_reg_val->hw_reset_cmd,
|
||||||
cre_hw_info->top_reg_offset->base + top_reg->reset_cmd);
|
cre_hw_info->top_reg_offset->base + top_reg->reset_cmd);
|
||||||
|
|
||||||
rc = wait_for_completion_timeout(
|
rc = wait_for_completion_timeout(
|
||||||
|
Reference in New Issue
Block a user