/* Complete an atom that has returned '1' from kbase_process_soft_job (i.e. has waited)
 *
 * @param katom     The atom to complete
 */
static void complete_soft_job(kbase_jd_atom *katom)
{
	kbase_context *kctx = katom->kctx;

	mutex_lock(&kctx->jctx.lock);
	OSK_DLIST_REMOVE(&kctx->waiting_soft_jobs, katom, dep_item[0]);
	kbase_finish_soft_job(katom);
	if (jd_done_nolock(katom))
	{
		kbasep_js_try_schedule_head_ctx( kctx->kbdev );
	}
	mutex_unlock(&kctx->jctx.lock);
}
static void kbase_fence_cancel_wait(kbase_jd_atom *katom)
{
	if (sync_fence_cancel_async(katom->fence, &katom->sync_waiter) != 0)
	{
		/* The wait wasn't cancelled - leave the cleanup for kbase_fence_wait_callback */
		return;
	}

	/* Wait was cancelled - zap the atoms */
	katom->event_code = BASE_JD_EVENT_JOB_CANCELLED;

	kbase_finish_soft_job(katom);

	if (jd_done_nolock(katom))
	{
		kbasep_js_try_schedule_head_ctx( katom->kctx->kbdev );
	}
}
static void kbase_replay_process_worker(struct work_struct *data)
{
	struct kbase_jd_atom *katom;
	struct kbase_context *kctx;
	struct kbase_jd_context *jctx;
	bool need_to_try_schedule_context = false;

	struct base_jd_atom_v2 t_atom, f_atom;
	struct kbase_jd_atom *t_katom, *f_katom;
	base_jd_prio atom_prio;

	katom = container_of(data, struct kbase_jd_atom, work);
	kctx = katom->kctx;
	jctx = &kctx->jctx;

	mutex_lock(&jctx->lock);

	atom_prio = kbasep_js_sched_prio_to_atom_prio(katom->sched_priority);

	if (kbasep_replay_create_atoms(
			kctx, &t_atom, &f_atom, atom_prio) != 0) {
		katom->event_code = BASE_JD_EVENT_JOB_CANCELLED;
		goto out;
	}

	t_katom = &jctx->atoms[t_atom.atom_number];
	f_katom = &jctx->atoms[f_atom.atom_number];

	if (kbasep_replay_parse_payload(kctx, katom, &t_atom, &f_atom) != 0) {
		kbasep_release_katom(kctx, t_atom.atom_number);
		kbasep_release_katom(kctx, f_atom.atom_number);
		katom->event_code = BASE_JD_EVENT_JOB_CANCELLED;
		goto out;
	}

	kbasep_replay_reset_softjob(katom, f_katom);

	need_to_try_schedule_context |= jd_submit_atom(kctx, &t_atom, t_katom);
	if (t_katom->event_code == BASE_JD_EVENT_JOB_INVALID) {
		dev_err(kctx->kbdev->dev, "Replay failed to submit atom\n");
		kbasep_release_katom(kctx, f_atom.atom_number);
		katom->event_code = BASE_JD_EVENT_JOB_CANCELLED;
		goto out;
	}
	need_to_try_schedule_context |= jd_submit_atom(kctx, &f_atom, f_katom);
	if (f_katom->event_code == BASE_JD_EVENT_JOB_INVALID) {
		dev_err(kctx->kbdev->dev, "Replay failed to submit atom\n");
		katom->event_code = BASE_JD_EVENT_JOB_CANCELLED;
		goto out;
	}

	katom->event_code = BASE_JD_EVENT_DONE;

out:
	if (katom->event_code != BASE_JD_EVENT_DONE) {
		kbase_disjoint_state_down(kctx->kbdev);

		need_to_try_schedule_context |= jd_done_nolock(katom, NULL);
	}

	if (need_to_try_schedule_context)
		kbase_js_sched_all(kctx->kbdev);

	mutex_unlock(&jctx->lock);
}