Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8f597234 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: icp: Enqueue the abort cmd in workq"

parents 64acbccf 0db96286
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -642,6 +642,7 @@ int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx)
			ctx->dev_name, ctx->ctx_id);

	flush_args.num_req_pending = 0;
	flush_args.last_flush_req = ctx->last_flush_req;
	while (true) {
		spin_lock(&ctx->lock);
		if (list_empty(&temp_list)) {
+3 −0
Original line number Diff line number Diff line
@@ -235,6 +235,8 @@ struct cam_hw_config_args {
 * @num_req_active:        Num request to flush, valid when flush type is REQ
 * @flush_req_active:      Request active pointers to flush
 * @flush_type:            The flush type
 * @last_flush_req:        last flush req_id notified to hw_mgr for the
 *                         given stream
 *
 */
struct cam_hw_flush_args {
@@ -244,6 +246,7 @@ struct cam_hw_flush_args {
	uint32_t                        num_req_active;
	void                           *flush_req_active[20];
	enum flush_type_t               flush_type;
	uint32_t                        last_flush_req;
};

/**
+133 −4
Original line number Diff line number Diff line
@@ -2672,11 +2672,93 @@ static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr)
		hw_mgr->a5_jtag_debug);
}

static int cam_icp_retry_wait_for_abort(
	struct cam_icp_hw_ctx_data *ctx_data)
{
	int retry_cnt = 1;
	unsigned long rem_jiffies;
	int timeout = 1000;

	CAM_WARN(CAM_ICP, "FW timeout in abort ctx: %u retry_left: %d",
		ctx_data->ctx_id, retry_cnt);
	while (retry_cnt > 0) {
		rem_jiffies = wait_for_completion_timeout(
			&ctx_data->wait_complete,
			msecs_to_jiffies((timeout)));
		if (!rem_jiffies) {
			retry_cnt--;
			if (retry_cnt > 0) {
				CAM_WARN(CAM_ICP,
					"FW timeout in abort ctx: %u retry_left: %u",
					ctx_data->ctx_id, retry_cnt);
				continue;
			}
		}

		if (retry_cnt > 0)
			return 0;
	}

	return -ETIMEDOUT;
}

static int cam_icp_mgr_abort_handle_wq(
	void *priv, void *data)
{
	int rc;
	size_t packet_size;
	struct hfi_cmd_work_data   *task_data = NULL;
	struct cam_icp_hw_ctx_data *ctx_data;
	struct hfi_cmd_ipebps_async *abort_cmd;

	if (!data || !priv) {
		CAM_ERR(CAM_ICP, "Invalid params %pK %pK", data, priv);
		return -EINVAL;
	}

	task_data = (struct hfi_cmd_work_data *)data;
	ctx_data =
		(struct cam_icp_hw_ctx_data *)task_data->data;
	packet_size =
		sizeof(struct hfi_cmd_ipebps_async) +
		sizeof(struct hfi_cmd_abort) -
		sizeof(((struct hfi_cmd_ipebps_async *)0)->payload.direct);
	abort_cmd = kzalloc(packet_size, GFP_KERNEL);
	CAM_DBG(CAM_ICP, "abort pkt size = %d", (int) packet_size);
	if (!abort_cmd) {
		rc = -ENOMEM;
		return rc;
	}

	abort_cmd->size = packet_size;
	abort_cmd->pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_DIRECT;
	if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS)
		abort_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_BPS_ABORT;
	else
		abort_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_IPE_ABORT;

	abort_cmd->num_fw_handles = 1;
	abort_cmd->fw_handles[0] = ctx_data->fw_handle;
	abort_cmd->user_data1 = PTR_TO_U64(ctx_data);
	abort_cmd->user_data2 = (uint64_t)0x0;

	rc = hfi_write_cmd(abort_cmd);
	if (rc) {
		kfree(abort_cmd);
		return rc;
	}
	CAM_DBG(CAM_ICP, "fw_handle = %x ctx_data = %pK ctx_id %d",
		ctx_data->fw_handle, ctx_data, ctx_data->ctx_id);

	kfree(abort_cmd);
	return rc;
}

static int cam_icp_mgr_abort_handle(
	struct cam_icp_hw_ctx_data *ctx_data)
{
	int rc = 0;
	unsigned long rem_jiffies;
	unsigned long rem_jiffies = 0;
	size_t packet_size;
	int timeout = 1000;
	struct hfi_cmd_ipebps_async *abort_cmd;
@@ -2808,6 +2890,7 @@ static int cam_icp_mgr_release_ctx(struct cam_icp_hw_mgr *hw_mgr, int ctx_id)

	hw_mgr->ctx_data[ctx_id].fw_handle = 0;
	hw_mgr->ctx_data[ctx_id].scratch_mem_size = 0;
	hw_mgr->ctx_data[ctx_id].last_flush_req = 0;
	for (i = 0; i < CAM_FRAME_CMD_MAX; i++)
		clear_bit(i, hw_mgr->ctx_data[ctx_id].hfi_frame_process.bitmap);
	kfree(hw_mgr->ctx_data[ctx_id].hfi_frame_process.bitmap);
@@ -3415,6 +3498,10 @@ static int cam_icp_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args)
			CAM_ERR(CAM_ICP, "Fail to send reconfig io cmd");
	}

	if (req_id <= ctx_data->last_flush_req)
		CAM_WARN(CAM_ICP,
			"Anomaly submitting flushed req %llu [last_flush %llu] in ctx %u",
			req_id, ctx_data->last_flush_req, ctx_data->ctx_id);
	rc = cam_icp_mgr_enqueue_config(hw_mgr, config_args);
	if (rc)
		goto config_err;
@@ -4433,6 +4520,46 @@ static int cam_icp_mgr_flush_req(struct cam_icp_hw_ctx_data *ctx_data,
	return 0;
}

static int cam_icp_mgr_enqueue_abort(
	struct cam_icp_hw_ctx_data *ctx_data)
{
	int timeout = 1000, rc;
	unsigned long rem_jiffies = 0;
	struct hfi_cmd_work_data *task_data;
	struct crm_workq_task *task;

	task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work);
	if (!task) {
		CAM_ERR(CAM_ICP, "no empty task");
		return -ENOMEM;
	}

	reinit_completion(&ctx_data->wait_complete);
	task_data = (struct hfi_cmd_work_data *)task->payload;
	task_data->data = (void *)ctx_data;
	task_data->type = ICP_WORKQ_TASK_CMD_TYPE;
	task->process_cb = cam_icp_mgr_abort_handle_wq;
	cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr,
		CRM_TASK_PRIORITY_0);

	rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete,
		msecs_to_jiffies((timeout)));
	if (!rem_jiffies) {
		rc = cam_icp_retry_wait_for_abort(ctx_data);
		if (rc) {
			CAM_ERR(CAM_ICP,
				"FW timeout/err in abort handle command ctx: %u",
				ctx_data->ctx_id);
			cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
			cam_hfi_queue_dump();
			return rc;
		}
	}

	CAM_DBG(CAM_ICP, "Abort after flush is success");
	return 0;
}

static int cam_icp_mgr_hw_dump(void *hw_priv, void *hw_dump_args)
{
	struct cam_hw_dump_args *dump_args = hw_dump_args;
@@ -4550,8 +4677,10 @@ static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args)
		return -EINVAL;
	}

	CAM_DBG(CAM_REQ, "ctx_id %d Flush type %d",
		ctx_data->ctx_id, flush_args->flush_type);
	ctx_data->last_flush_req = flush_args->last_flush_req;
	CAM_DBG(CAM_REQ, "ctx_id %d Flush type %d last_flush_req %u",
		ctx_data->ctx_id, flush_args->flush_type,
		ctx_data->last_flush_req);

	switch (flush_args->flush_type) {
	case CAM_FLUSH_TYPE_ALL:
@@ -4559,7 +4688,7 @@ static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args)
		if (!atomic_read(&hw_mgr->recovery)
			&& flush_args->num_req_active) {
			mutex_unlock(&hw_mgr->hw_mgr_mutex);
			cam_icp_mgr_abort_handle(ctx_data);
			cam_icp_mgr_enqueue_abort(ctx_data);
		} else {
			mutex_unlock(&hw_mgr->hw_mgr_mutex);
		}
+3 −1
Original line number Diff line number Diff line
/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -219,6 +219,7 @@ struct cam_ctx_clk_info {
 * @watch_dog: watchdog timer handle
 * @watch_dog_reset_counter: Counter for watch dog reset
 * @icp_dev_io_info: io config resource
 * @last_flush_req: last flush req for this ctx
 */
struct cam_icp_hw_ctx_data {
	void *context_priv;
@@ -239,6 +240,7 @@ struct cam_icp_hw_ctx_data {
	struct cam_req_mgr_timer *watch_dog;
	uint32_t watch_dog_reset_counter;
	struct cam_icp_acquire_dev_info icp_dev_io_info;
	uint64_t last_flush_req;
};

/**
+3 −2
Original line number Diff line number Diff line
/* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -410,8 +410,9 @@ static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr)
	if (closest_mapping) {
		buf_handle = GET_MEM_HANDLE(idx, closest_mapping->ion_fd);
		CAM_INFO(CAM_SMMU,
			"Closest map fd %d 0x%lx 0x%lx-0x%lx buf=%pK mem %0x",
			"Closest map fd %d 0x%lx %llu-%llu 0x%lx-0x%lx buf=%pK mem %0x",
			closest_mapping->ion_fd, current_addr,
			mapping->len, closest_mapping->len,
			(unsigned long)closest_mapping->paddr,
			(unsigned long)closest_mapping->paddr + mapping->len,
			closest_mapping->buf,