Browse Source

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

Camera Software Integration 1 year ago
parent
commit
477f423ee1

+ 47 - 31
drivers/cam_cre/cam_cre_hw_mgr/cam_cre_hw_mgr.c

@@ -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;
+			task_data->req_idx);
+		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;

+ 6 - 4
drivers/cam_cre/cam_cre_hw_mgr/cam_cre_hw_mgr.h

@@ -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
@@ -146,14 +146,16 @@ struct cam_cre_clk_info {
 /**
  * struct cre_cmd_work_data
  *
- * @type:       Type of work data
- * @data:       Private data
- * @req_id:     Request Idx
+ * @type:        Type of work data
+ * @data:        Private data
+ * @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;
 };
 
 /**

+ 3 - 2
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/top/cre_top.c

@@ -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(