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

Commit 512a906a authored by George Shen's avatar George Shen
Browse files

msm: cvp: Cancel pending synx during SSR



The change helps camera gracefully handle SSR case.

Change-Id: I7ac1612a3b59cdf993cfe5ced347da69b2ad416b
Signed-off-by: default avatarGeorge Shen <sqiao@codeaurora.org>
parent 1c0ece44
Loading
Loading
Loading
Loading
+77 −41
Original line number Diff line number Diff line
@@ -301,7 +301,8 @@ static int cvp_fence_proc(struct msm_cvp_inst *inst,
	sq = &inst->session_queue_fence;
	ktid = pkt->client_data.kdata;

	if (cvp_synx_ops(inst, CVP_INPUT_SYNX, fc, &synx_state)) {
	rc = cvp_synx_ops(inst, CVP_INPUT_SYNX, fc, &synx_state);
	if (rc) {
		msm_cvp_unmap_frame(inst, pkt->client_data.kdata);
		goto exit;
	}
@@ -416,6 +417,7 @@ static int cvp_fence_thread(void *data)
	mutex_lock(&q->lock);
	cvp_release_synx(inst, f);
	list_del_init(&f->list);
	state = q->state;
	mutex_unlock(&q->lock);

	dprintk(CVP_SYNX, "%s done with %d ktid %llu frameID %llu rc %d\n",
@@ -423,6 +425,9 @@ static int cvp_fence_thread(void *data)

	cvp_free_fence_data(f);

	if (rc && state != QUEUE_ACTIVE)
		goto exit;

	goto wait;

exit:
@@ -1277,10 +1282,8 @@ static int cvp_drain_fence_sched_list(struct msm_cvp_inst *inst)
	mutex_lock(&q->lock);
	list_for_each_entry(f, &q->sched_list, list) {
		ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
		dprintk(CVP_SYNX, "%s: frame %llu is in sched_list\n",
			__func__, ktid);
		dprintk(CVP_SYNX, "%s: frameID %llu is in sched_list\n",
			__func__, f->frame_id);
		dprintk(CVP_SYNX, "%s: frame %llu %llu is in sched_list\n",
			__func__, ktid, f->frame_id);
		++count;
	}
	mutex_unlock(&q->lock);
@@ -1312,26 +1315,13 @@ static int cvp_drain_fence_sched_list(struct msm_cvp_inst *inst)
	return rc;
}

static int cvp_flush_all(struct msm_cvp_inst *inst)
static void cvp_clean_fence_queue(struct msm_cvp_inst *inst, int synx_state)
{
	int rc = 0;
	struct msm_cvp_inst *s;
	struct cvp_fence_queue *q;
	struct cvp_fence_command *f, *d;
	struct cvp_hfi_device *hdev;
	u64 ktid;

	if (!inst || !inst->core) {
		dprintk(CVP_ERR, "%s: invalid params\n", __func__);
		return -EINVAL;
	}

	s = cvp_get_inst_validate(inst->core, inst);
	if (!s)
		return -ECONNRESET;

	q = &inst->fence_cmd_queue;
	hdev = inst->core->device;

	mutex_lock(&q->lock);
	q->mode = OP_DRAINING;
@@ -1339,14 +1329,12 @@ static int cvp_flush_all(struct msm_cvp_inst *inst)
	list_for_each_entry_safe(f, d, &q->wait_list, list) {
		ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);

		dprintk(CVP_SESS, "%s: flush frame %llu from wait_list\n",
			__func__, ktid);
		dprintk(CVP_SESS, "%s: flush frameID %llu from wait_list\n",
			__func__, f->frame_id);
		dprintk(CVP_SYNX, "%s: (%#x) flush frame %llu %llu wait_list\n",
			__func__, hash32_ptr(inst->session), ktid, f->frame_id);

		list_del_init(&f->list);
		msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata);
		cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f);
		cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f, synx_state);
		cvp_release_synx(inst, f);
		cvp_free_fence_data(f);
	}
@@ -1354,16 +1342,63 @@ static int cvp_flush_all(struct msm_cvp_inst *inst)
	list_for_each_entry(f, &q->sched_list, list) {
		ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);

		dprintk(CVP_SESS, "%s: flush frame %llu from sched_list\n",
			__func__, ktid);
		dprintk(CVP_SESS, "%s: flush frameID %llu from sched_list\n",
			__func__, f->frame_id);
		cvp_cancel_synx(inst, CVP_INPUT_SYNX, f);
		dprintk(CVP_SYNX, "%s: (%#x)flush frame %llu %llu sched_list\n",
			__func__, hash32_ptr(inst->session), ktid, f->frame_id);
		cvp_cancel_synx(inst, CVP_INPUT_SYNX, f, synx_state);
	}

	mutex_unlock(&q->lock);
}

int cvp_stop_clean_fence_queue(struct msm_cvp_inst *inst)
{
	struct cvp_fence_queue *q;
	u32 count = 0, max_retries = 100;

	cvp_clean_fence_queue(inst, SYNX_STATE_SIGNALED_ERROR);
	cvp_fence_thread_stop(inst);

	/* Waiting for all output synx sent */
	q = &inst->fence_cmd_queue;
retry:
	mutex_lock(&q->lock);
	if (list_empty(&q->sched_list)) {
		mutex_unlock(&q->lock);
		return 0;
	}
	mutex_unlock(&q->lock);
	usleep_range(500, 1000);
	if (++count > max_retries)
		return -EBUSY;

	goto retry;
}

static int cvp_flush_all(struct msm_cvp_inst *inst)
{
	int rc = 0;
	struct msm_cvp_inst *s;
	struct cvp_fence_queue *q;
	struct cvp_hfi_device *hdev;

	if (!inst || !inst->core) {
		dprintk(CVP_ERR, "%s: invalid params\n", __func__);
		return -EINVAL;
	}

	s = cvp_get_inst_validate(inst->core, inst);
	if (!s)
		return -ECONNRESET;

	dprintk(CVP_SESS, "session %llx (%#x)flush all starts\n",
			inst, hash32_ptr(inst->session));
	q = &inst->fence_cmd_queue;
	hdev = inst->core->device;

	cvp_clean_fence_queue(inst, SYNX_STATE_SIGNALED_CANCEL);

	dprintk(CVP_SESS, "%s: send flush to fw\n", __func__);
	dprintk(CVP_SESS, "%s: (%#x) send flush to fw\n",
			__func__, hash32_ptr(inst->session));

	/* Send flush to FW */
	rc = call_hfi_op(hdev, session_flush, (void *)inst->session);
@@ -1379,7 +1414,8 @@ static int cvp_flush_all(struct msm_cvp_inst *inst)
		dprintk(CVP_WARN, "%s: wait for signal failed, rc %d\n",
		__func__, rc);

	dprintk(CVP_SESS, "%s: received flush from fw\n", __func__);
	dprintk(CVP_SESS, "%s: (%#x) received flush from fw\n",
			__func__, hash32_ptr(inst->session));

exit:
	rc = cvp_drain_fence_sched_list(inst);
@@ -1442,6 +1478,8 @@ static int cvp_flush_frame(struct msm_cvp_inst *inst, u64 frame_id)
	if (!s)
		return -ECONNRESET;

	dprintk(CVP_SESS, "Session %llx, flush frame with id %llu\n",
			inst, frame_id);
	q = &inst->fence_cmd_queue;

	mutex_lock(&q->lock);
@@ -1455,14 +1493,13 @@ static int cvp_flush_frame(struct msm_cvp_inst *inst, u64 frame_id)

		ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);

		dprintk(CVP_SESS, "%s: flush frame %llu from wait_list\n",
			__func__, ktid);
		dprintk(CVP_SESS, "%s: flush frameID %llu from wait_list\n",
			__func__, f->frame_id);
		dprintk(CVP_SYNX, "%s: flush frame %llu %llu from wait_list\n",
			__func__, ktid, f->frame_id);

		list_del_init(&f->list);
		msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata);
		cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f);
		cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f,
				SYNX_STATE_SIGNALED_CANCEL);
		cvp_release_synx(inst, f);
		cvp_free_fence_data(f);
	}
@@ -1473,11 +1510,10 @@ static int cvp_flush_frame(struct msm_cvp_inst *inst, u64 frame_id)

		ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);

		dprintk(CVP_SESS, "%s: flush frame %llu from sched_list\n",
			__func__, ktid);
		dprintk(CVP_SESS, "%s: flush frameID %llu from sched_list\n",
			__func__, f->frame_id);
		cvp_cancel_synx(inst, CVP_INPUT_SYNX, f);
		dprintk(CVP_SYNX, "%s: flush frame %llu %llu from sched_list\n",
			__func__, ktid, f->frame_id);
		cvp_cancel_synx(inst, CVP_INPUT_SYNX, f,
				SYNX_STATE_SIGNALED_CANCEL);
	}

	mutex_unlock(&q->lock);
+1 −0
Original line number Diff line number Diff line
@@ -33,4 +33,5 @@ int msm_cvp_handle_syscall(struct msm_cvp_inst *inst, struct cvp_kmd_arg *arg);
int msm_cvp_session_init(struct msm_cvp_inst *inst);
int msm_cvp_session_deinit(struct msm_cvp_inst *inst);
int msm_cvp_session_queue_stop(struct msm_cvp_inst *inst);
int cvp_stop_clean_fence_queue(struct msm_cvp_inst *inst);
#endif
+6 −1
Original line number Diff line number Diff line
@@ -498,6 +498,10 @@ static void msm_cvp_unmap_frame_buf(struct msm_cvp_inst *inst,
		} else if (atomic_dec_and_test(&smem->refcount)) {
			clear_bit(smem->bitmap_index,
				&inst->dma_cache.usage_bitmap);
			dprintk(CVP_MEM, "smem %x %d iova %#x to be reused\n",
					hash32_ptr(inst->session),
					smem->size,
					smem->device_addr);
		}
	}

@@ -515,7 +519,8 @@ void msm_cvp_unmap_frame(struct msm_cvp_inst *inst, u64 ktid)
	}

	ktid &= (FENCE_BIT - 1);
	dprintk(CVP_MEM, "%s: unmap frame %llu\n", __func__, ktid);
	dprintk(CVP_MEM, "%s: (%#x) unmap frame %llu\n",
			__func__, hash32_ptr(inst->session), ktid);

	found = false;
	mutex_lock(&inst->frames.lock);
+7 −1
Original line number Diff line number Diff line
@@ -402,6 +402,8 @@ int wait_for_sess_signal_receipt(struct msm_cvp_inst *inst,
		call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
		dump_hfi_queue(hdev->hfi_device_data);
		rc = -EIO;
	} else if (inst->state == MSM_CVP_CORE_INVALID) {
		rc = -ECONNRESET;
	} else {
		rc = 0;
	}
@@ -623,7 +625,7 @@ static void handle_sys_error(enum hal_command_response cmd, void *data)
	struct msm_cvp_core *core = NULL;
	struct cvp_hfi_device *hdev = NULL;
	struct msm_cvp_inst *inst = NULL;
	int rc = 0;
	int i, rc = 0;
	unsigned long flags = 0;
	enum cvp_core_state cur_state;

@@ -663,6 +665,10 @@ static void handle_sys_error(enum hal_command_response cmd, void *data)
				inst->cur_cmd_type, inst->state);
		if (inst->state != MSM_CVP_CORE_INVALID) {
			change_cvp_inst_state(inst, MSM_CVP_CORE_INVALID);
			if (cvp_stop_clean_fence_queue(inst))
				dprintk(CVP_ERR, "Failed to clean fences\n");
			for (i = 0; i < ARRAY_SIZE(inst->completions); i++)
				complete(&inst->completions[i]);
			spin_lock_irqsave(&inst->event_handler.lock, flags);
			inst->event_handler.event = CVP_SSR_EVENT;
			spin_unlock_irqrestore(
+20 −15
Original line number Diff line number Diff line
@@ -73,8 +73,8 @@ int cvp_import_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc,
			rc = synx_import(ssid, &params);
			if (rc) {
				dprintk(CVP_ERR,
					"%s: synx_import failed\n",
					__func__);
					"%s: %d synx_import failed\n",
					__func__, h_synx);
				return rc;
			}
		}
@@ -102,8 +102,8 @@ int cvp_release_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc)
			rc = synx_release(ssid, h_synx);
			if (rc)
				dprintk(CVP_ERR,
				"%s: synx_release %d failed\n",
				__func__, i);
				"%s: synx_release %d, %d failed\n",
				__func__, h_synx, i);
		}
	}
	return rc;
@@ -111,14 +111,14 @@ int cvp_release_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc)

static int cvp_cancel_synx_impl(struct msm_cvp_inst *inst,
			enum cvp_synx_type type,
			struct cvp_fence_command *fc)
			struct cvp_fence_command *fc,
			int synx_state)
{
	int rc = 0;
	int i;
	int h_synx;
	struct synx_session ssid;
	int start = 0, end = 0;
	int synx_state = SYNX_STATE_SIGNALED_CANCEL;

	ssid = inst->synx_session_id;

@@ -137,11 +137,12 @@ static int cvp_cancel_synx_impl(struct msm_cvp_inst *inst,
		h_synx = fc->synx[i];
		if (h_synx) {
			rc = synx_signal(ssid, h_synx, synx_state);
			if (rc) {
				dprintk(CVP_ERR, "%s: synx_signal %d failed\n",
				__func__, i);
				synx_state = SYNX_STATE_SIGNALED_ERROR;
			}
			dprintk(CVP_SYNX, "Cancel synx %d session %llx\n",
					h_synx, inst);
			if (rc)
				dprintk(CVP_ERR,
					"%s: synx_signal %d %d %d failed\n",
				__func__, h_synx, i, synx_state);
		}
	}

@@ -151,14 +152,14 @@ static int cvp_cancel_synx_impl(struct msm_cvp_inst *inst,
}

int cvp_cancel_synx(struct msm_cvp_inst *inst, enum cvp_synx_type type,
		struct cvp_fence_command *fc)
		struct cvp_fence_command *fc, int synx_state)
{
	if (fc->signature != 0xFEEDFACE) {
		dprintk(CVP_ERR, "%s deprecated synx path\n", __func__);
			return -EINVAL;
		}

	return cvp_cancel_synx_impl(inst, type, fc);
	return cvp_cancel_synx_impl(inst, type, fc, synx_state);
}

static int cvp_wait_synx(struct synx_session ssid, u32 *synx, u32 num_synx,
@@ -186,6 +187,8 @@ static int cvp_wait_synx(struct synx_session ssid, u32 *synx, u32 num_synx,
				}
				return rc;
			}
			dprintk(CVP_SYNX, "Wait synx %d returned succes\n",
					h_synx);
		}
		++i;
	}
@@ -203,10 +206,12 @@ static int cvp_signal_synx(struct synx_session ssid, u32 *synx, u32 num_synx,
		if (h_synx) {
			rc = synx_signal(ssid, h_synx, synx_state);
			if (rc) {
				dprintk(CVP_ERR, "%s: synx_signal %d failed\n",
				current->comm, i);
				dprintk(CVP_ERR,
					"%s: synx_signal %d %d failed\n",
					current->comm, h_synx, i);
				synx_state = SYNX_STATE_SIGNALED_ERROR;
			}
			dprintk(CVP_SYNX, "Signaled synx %d\n", h_synx);
		}
		++i;
	}
Loading