diff options
Diffstat (limited to 'drivers/gpu/drm/xe/xe_guc_submit.c')
| -rw-r--r-- | drivers/gpu/drm/xe/xe_guc_submit.c | 377 |
1 files changed, 61 insertions, 316 deletions
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 7a4218f76024..a27ea931b956 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -17,7 +17,6 @@ #include "abi/guc_actions_abi.h" #include "abi/guc_actions_slpc_abi.h" #include "abi/guc_klvs_abi.h" -#include "regs/xe_lrc_layout.h" #include "xe_assert.h" #include "xe_bo.h" #include "xe_devcoredump.h" @@ -36,7 +35,6 @@ #include "xe_guc_klv_helpers.h" #include "xe_guc_submit_types.h" #include "xe_hw_engine.h" -#include "xe_hw_fence.h" #include "xe_lrc.h" #include "xe_macros.h" #include "xe_map.h" @@ -71,11 +69,8 @@ exec_queue_to_guc(struct xe_exec_queue *q) #define EXEC_QUEUE_STATE_KILLED (1 << 7) #define EXEC_QUEUE_STATE_WEDGED (1 << 8) #define EXEC_QUEUE_STATE_BANNED (1 << 9) -#define EXEC_QUEUE_STATE_CHECK_TIMEOUT (1 << 10) -#define EXEC_QUEUE_STATE_EXTRA_REF (1 << 11) -#define EXEC_QUEUE_STATE_PENDING_RESUME (1 << 12) -#define EXEC_QUEUE_STATE_PENDING_TDR_EXIT (1 << 13) -#define EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND (1 << 14) +#define EXEC_QUEUE_STATE_PENDING_RESUME (1 << 10) +#define EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND (1 << 11) static bool exec_queue_registered(struct xe_exec_queue *q) { @@ -207,36 +202,6 @@ static void set_exec_queue_wedged(struct xe_exec_queue *q) atomic_or(EXEC_QUEUE_STATE_WEDGED, &q->guc->state); } -static bool exec_queue_check_timeout(struct xe_exec_queue *q) -{ - return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_CHECK_TIMEOUT; -} - -static void set_exec_queue_check_timeout(struct xe_exec_queue *q) -{ - atomic_or(EXEC_QUEUE_STATE_CHECK_TIMEOUT, &q->guc->state); -} - -static void clear_exec_queue_check_timeout(struct xe_exec_queue *q) -{ - atomic_and(~EXEC_QUEUE_STATE_CHECK_TIMEOUT, &q->guc->state); -} - -static bool exec_queue_extra_ref(struct xe_exec_queue *q) -{ - return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_EXTRA_REF; -} - -static void set_exec_queue_extra_ref(struct xe_exec_queue *q) -{ - atomic_or(EXEC_QUEUE_STATE_EXTRA_REF, &q->guc->state); -} - -static void clear_exec_queue_extra_ref(struct xe_exec_queue *q) -{ - atomic_and(~EXEC_QUEUE_STATE_EXTRA_REF, &q->guc->state); -} - static bool exec_queue_pending_resume(struct xe_exec_queue *q) { return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_PENDING_RESUME; @@ -252,21 +217,6 @@ static void clear_exec_queue_pending_resume(struct xe_exec_queue *q) atomic_and(~EXEC_QUEUE_STATE_PENDING_RESUME, &q->guc->state); } -static bool exec_queue_pending_tdr_exit(struct xe_exec_queue *q) -{ - return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_PENDING_TDR_EXIT; -} - -static void set_exec_queue_pending_tdr_exit(struct xe_exec_queue *q) -{ - atomic_or(EXEC_QUEUE_STATE_PENDING_TDR_EXIT, &q->guc->state); -} - -static void clear_exec_queue_pending_tdr_exit(struct xe_exec_queue *q) -{ - atomic_and(~EXEC_QUEUE_STATE_PENDING_TDR_EXIT, &q->guc->state); -} - static bool exec_queue_idle_skip_suspend(struct xe_exec_queue *q) { return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND; @@ -603,10 +553,7 @@ static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q) /** to wakeup xe_wait_user_fence ioctl if exec queue is reset */ wake_up_all(&xe->ufence_wq); - if (xe_exec_queue_is_lr(q)) - queue_work(guc_to_gt(guc)->ordered_wq, &q->guc->lr_tdr); - else - xe_sched_tdr_queue_imm(&q->guc->sched); + xe_sched_tdr_queue_imm(&q->guc->sched); } static void xe_guc_exec_queue_group_trigger_cleanup(struct xe_exec_queue *q) @@ -639,19 +586,19 @@ static void xe_guc_exec_queue_reset_trigger_cleanup(struct xe_exec_queue *q) WRITE_ONCE(group->banned, true); set_exec_queue_reset(primary); - if (!exec_queue_banned(primary) && !exec_queue_check_timeout(primary)) + if (!exec_queue_banned(primary)) xe_guc_exec_queue_trigger_cleanup(primary); mutex_lock(&group->list_lock); list_for_each_entry(eq, &group->list, multi_queue.link) { set_exec_queue_reset(eq); - if (!exec_queue_banned(eq) && !exec_queue_check_timeout(eq)) + if (!exec_queue_banned(eq)) xe_guc_exec_queue_trigger_cleanup(eq); } mutex_unlock(&group->list_lock); } else { set_exec_queue_reset(q); - if (!exec_queue_banned(q) && !exec_queue_check_timeout(q)) + if (!exec_queue_banned(q)) xe_guc_exec_queue_trigger_cleanup(q); } } @@ -994,14 +941,6 @@ static void register_exec_queue(struct xe_exec_queue *q, int ctx_type) parallel_write(xe, map, wq_desc.wq_status, WQ_STATUS_ACTIVE); } - /* - * We must keep a reference for LR engines if engine is registered with - * the GuC as jobs signal immediately and can't destroy an engine if the - * GuC has a reference to it. - */ - if (xe_exec_queue_is_lr(q)) - xe_exec_queue_get(q); - set_exec_queue_registered(q); trace_xe_exec_queue_register(q); if (xe_exec_queue_is_multi_queue_primary(q)) @@ -1202,7 +1141,7 @@ guc_exec_queue_run_job(struct drm_sched_job *drm_job) struct xe_sched_job *job = to_xe_sched_job(drm_job); struct xe_exec_queue *q = job->q; struct xe_guc *guc = exec_queue_to_guc(q); - bool lr = xe_exec_queue_is_lr(q), killed_or_banned_or_wedged = + bool killed_or_banned_or_wedged = exec_queue_killed_or_banned_or_wedged(q); xe_gt_assert(guc_to_gt(guc), !(exec_queue_destroyed(q) || exec_queue_pending_disable(q)) || @@ -1232,14 +1171,6 @@ guc_exec_queue_run_job(struct drm_sched_job *drm_job) } run_job_out: - /* - * We don't care about job-fence ordering in LR VMs because these fences - * are never exported; they are used solely to keep jobs on the pending - * list. Once a queue enters an error state, there's no need to track - * them. - */ - if (killed_or_banned_or_wedged && lr) - xe_sched_job_set_error(job, -ECANCELED); return job->fence; } @@ -1291,8 +1222,7 @@ static void disable_scheduling_deregister(struct xe_guc *guc, xe_gt_warn(q->gt, "Pending enable/disable failed to respond\n"); xe_sched_submission_start(sched); xe_gt_reset_async(q->gt); - if (!xe_exec_queue_is_lr(q)) - xe_sched_tdr_queue_imm(sched); + xe_sched_tdr_queue_imm(sched); return; } @@ -1339,8 +1269,9 @@ void xe_guc_submit_wedge(struct xe_guc *guc) err = devm_add_action_or_reset(guc_to_xe(guc)->drm.dev, guc_submit_wedged_fini, guc); if (err) { - xe_gt_err(gt, "Failed to register clean-up on wedged.mode=2; " - "Although device is wedged.\n"); + xe_gt_err(gt, "Failed to register clean-up in wedged.mode=%s; " + "Although device is wedged.\n", + xe_wedged_mode_to_string(XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET)); return; } @@ -1355,7 +1286,7 @@ static bool guc_submit_hint_wedged(struct xe_guc *guc) { struct xe_device *xe = guc_to_xe(guc); - if (xe->wedged.mode != 2) + if (xe->wedged.mode != XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET) return false; if (xe_device_wedged(xe)) @@ -1366,84 +1297,6 @@ static bool guc_submit_hint_wedged(struct xe_guc *guc) return true; } -static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w) -{ - struct xe_guc_exec_queue *ge = - container_of(w, struct xe_guc_exec_queue, lr_tdr); - struct xe_exec_queue *q = ge->q; - struct xe_guc *guc = exec_queue_to_guc(q); - struct xe_gpu_scheduler *sched = &ge->sched; - struct xe_sched_job *job; - bool wedged = false; - - xe_gt_assert(guc_to_gt(guc), xe_exec_queue_is_lr(q)); - - if (vf_recovery(guc)) - return; - - trace_xe_exec_queue_lr_cleanup(q); - - if (!exec_queue_killed(q)) - wedged = guc_submit_hint_wedged(exec_queue_to_guc(q)); - - /* Kill the run_job / process_msg entry points */ - xe_sched_submission_stop(sched); - - /* - * Engine state now mostly stable, disable scheduling / deregister if - * needed. This cleanup routine might be called multiple times, where - * the actual async engine deregister drops the final engine ref. - * Calling disable_scheduling_deregister will mark the engine as - * destroyed and fire off the CT requests to disable scheduling / - * deregister, which we only want to do once. We also don't want to mark - * the engine as pending_disable again as this may race with the - * xe_guc_deregister_done_handler() which treats it as an unexpected - * state. - */ - if (!wedged && exec_queue_registered(q) && !exec_queue_destroyed(q)) { - struct xe_guc *guc = exec_queue_to_guc(q); - int ret; - - set_exec_queue_banned(q); - disable_scheduling_deregister(guc, q); - - /* - * Must wait for scheduling to be disabled before signalling - * any fences, if GT broken the GT reset code should signal us. - */ - ret = wait_event_timeout(guc->ct.wq, - !exec_queue_pending_disable(q) || - xe_guc_read_stopped(guc) || - vf_recovery(guc), HZ * 5); - if (vf_recovery(guc)) - return; - - if (!ret) { - xe_gt_warn(q->gt, "Schedule disable failed to respond, guc_id=%d\n", - q->guc->id); - xe_devcoredump(q, NULL, "Schedule disable failed to respond, guc_id=%d\n", - q->guc->id); - xe_sched_submission_start(sched); - xe_gt_reset_async(q->gt); - return; - } - } - - if (!exec_queue_killed(q) && !xe_lrc_ring_is_idle(q->lrc[0])) - xe_devcoredump(q, NULL, "LR job cleanup, guc_id=%d", q->guc->id); - - xe_hw_fence_irq_stop(q->fence_irq); - - xe_sched_submission_start(sched); - - spin_lock(&sched->base.job_list_lock); - list_for_each_entry(job, &sched->base.pending_list, drm.list) - xe_sched_job_set_error(job, -ECANCELED); - spin_unlock(&sched->base.job_list_lock); - - xe_hw_fence_irq_start(q->fence_irq); -} - #define ADJUST_FIVE_PERCENT(__t) mul_u64_u32_div(__t, 105, 100) static bool check_timeout(struct xe_exec_queue *q, struct xe_sched_job *job) @@ -1462,7 +1315,16 @@ static bool check_timeout(struct xe_exec_queue *q, struct xe_sched_job *job) return xe_sched_invalidate_job(job, 2); } - ctx_timestamp = lower_32_bits(xe_lrc_ctx_timestamp(q->lrc[0])); + ctx_timestamp = lower_32_bits(xe_lrc_timestamp(q->lrc[0])); + if (ctx_timestamp == job->sample_timestamp) { + xe_gt_warn(gt, "Check job timeout: seqno=%u, lrc_seqno=%u, guc_id=%d, timestamp stuck", + xe_sched_job_seqno(job), xe_sched_job_lrc_seqno(job), + q->guc->id); + + return xe_sched_invalidate_job(job, 0); + } + + job->sample_timestamp = ctx_timestamp; ctx_job_timestamp = xe_lrc_ctx_job_timestamp(q->lrc[0]); /* @@ -1516,8 +1378,7 @@ static void enable_scheduling(struct xe_exec_queue *q) xe_gt_warn(guc_to_gt(guc), "Schedule enable failed to respond"); set_exec_queue_banned(q); xe_gt_reset_async(q->gt); - if (!xe_exec_queue_is_lr(q)) - xe_sched_tdr_queue_imm(&q->guc->sched); + xe_sched_tdr_queue_imm(&q->guc->sched); } } @@ -1543,33 +1404,11 @@ static void disable_scheduling(struct xe_exec_queue *q, bool immediate) G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1); } -static void __deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q) -{ - u32 action[] = { - XE_GUC_ACTION_DEREGISTER_CONTEXT, - q->guc->id, - }; - - xe_gt_assert(guc_to_gt(guc), !exec_queue_destroyed(q)); - xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q)); - xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_enable(q)); - xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_disable(q)); - - set_exec_queue_destroyed(q); - trace_xe_exec_queue_deregister(q); - - if (xe_exec_queue_is_multi_queue_secondary(q)) - handle_deregister_done(guc, q); - else - xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), - G2H_LEN_DW_DEREGISTER_CONTEXT, 1); -} - static enum drm_gpu_sched_stat guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) { struct xe_sched_job *job = to_xe_sched_job(drm_job); - struct xe_sched_job *tmp_job; + struct drm_sched_job *tmp_job; struct xe_exec_queue *q = job->q; struct xe_gpu_scheduler *sched = &q->guc->sched; struct xe_guc *guc = exec_queue_to_guc(q); @@ -1577,10 +1416,9 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) struct xe_device *xe = guc_to_xe(guc); int err = -ETIME; pid_t pid = -1; - int i = 0; bool wedged = false, skip_timeout_check; - xe_gt_assert(guc_to_gt(guc), !xe_exec_queue_is_lr(q)); + xe_gt_assert(guc_to_gt(guc), !exec_queue_destroyed(q)); /* * TDR has fired before free job worker. Common if exec queue @@ -1597,14 +1435,17 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) /* Must check all state after stopping scheduler */ skip_timeout_check = exec_queue_reset(q) || - exec_queue_killed_or_banned_or_wedged(q) || - exec_queue_destroyed(q); + exec_queue_killed_or_banned_or_wedged(q); /* Skip timeout check if multi-queue group is banned */ if (xe_exec_queue_is_multi_queue(q) && READ_ONCE(q->multi_queue.group->banned)) skip_timeout_check = true; + /* LR jobs can only get here if queue has been killed or hit an error */ + if (xe_exec_queue_is_lr(q)) + xe_gt_assert(guc_to_gt(guc), skip_timeout_check); + /* * FIXME: In multi-queue scenario, the TDR must ensure that the whole * multi-queue group is off the HW before signaling the fences to avoid @@ -1628,23 +1469,24 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) } /* - * XXX: Sampling timeout doesn't work in wedged mode as we have to - * modify scheduling state to read timestamp. We could read the - * timestamp from a register to accumulate current running time but this - * doesn't work for SRIOV. For now assuming timeouts in wedged mode are - * genuine timeouts. + * Check if job is actually timed out, if so restart job execution and TDR */ + if (!skip_timeout_check && !check_timeout(q, job)) + goto rearm; + if (!exec_queue_killed(q)) wedged = guc_submit_hint_wedged(exec_queue_to_guc(q)); - /* Engine state now stable, disable scheduling to check timestamp */ - if (!wedged && exec_queue_registered(q)) { + set_exec_queue_banned(q); + + /* Kick job / queue off hardware */ + if (!wedged && (exec_queue_enabled(q) || exec_queue_pending_disable(q))) { int ret; if (exec_queue_reset(q)) err = -EIO; - if (!exec_queue_destroyed(q)) { + if (xe_uc_fw_is_running(&guc->fw)) { /* * Wait for any pending G2H to flush out before * modifying state @@ -1659,13 +1501,6 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) if (!ret || xe_guc_read_stopped(guc)) goto trigger_reset; - /* - * Flag communicates to G2H handler that schedule - * disable originated from a timeout check. The G2H then - * avoid triggering cleanup or deregistering the exec - * queue. - */ - set_exec_queue_check_timeout(q); disable_scheduling(q, skip_timeout_check); } @@ -1679,6 +1514,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) */ smp_rmb(); ret = wait_event_timeout(guc->ct.wq, + !xe_uc_fw_is_running(&guc->fw) || !exec_queue_pending_disable(q) || xe_guc_read_stopped(guc) || vf_recovery(guc), HZ * 5); @@ -1693,24 +1529,12 @@ trigger_reset: xe_devcoredump(q, job, "Schedule disable failed to respond, guc_id=%d, ret=%d, guc_read=%d", q->guc->id, ret, xe_guc_read_stopped(guc)); - set_exec_queue_extra_ref(q); - xe_exec_queue_get(q); /* GT reset owns this */ - set_exec_queue_banned(q); xe_gt_reset_async(q->gt); xe_sched_tdr_queue_imm(sched); goto rearm; } } - /* - * Check if job is actually timed out, if so restart job execution and TDR - */ - if (!wedged && !skip_timeout_check && !check_timeout(q, job) && - !exec_queue_reset(q) && exec_queue_registered(q)) { - clear_exec_queue_check_timeout(q); - goto sched_enable; - } - if (q->vm && q->vm->xef) { process_name = q->vm->xef->process_name; pid = q->vm->xef->pid; @@ -1741,28 +1565,16 @@ trigger_reset: if (!wedged && (q->flags & EXEC_QUEUE_FLAG_KERNEL || (q->flags & EXEC_QUEUE_FLAG_VM && !exec_queue_killed(q)))) { if (!xe_sched_invalidate_job(job, 2)) { - clear_exec_queue_check_timeout(q); xe_gt_reset_async(q->gt); goto rearm; } } - /* Finish cleaning up exec queue via deregister */ - set_exec_queue_banned(q); - if (!wedged && exec_queue_registered(q) && !exec_queue_destroyed(q)) { - set_exec_queue_extra_ref(q); - xe_exec_queue_get(q); - __deregister_exec_queue(guc, q); - } - - /* Stop fence signaling */ - xe_hw_fence_irq_stop(q->fence_irq); + /* Mark all outstanding jobs as bad, thus completing them */ + xe_sched_job_set_error(job, err); + drm_sched_for_each_pending_job(tmp_job, &sched->base, NULL) + xe_sched_job_set_error(to_xe_sched_job(tmp_job), -ECANCELED); - /* - * Fence state now stable, stop / start scheduler which cleans up any - * fences that are complete - */ - xe_sched_add_pending_job(sched, job); xe_sched_submission_start(sched); if (xe_exec_queue_is_multi_queue(q)) @@ -1770,20 +1582,12 @@ trigger_reset: else xe_guc_exec_queue_trigger_cleanup(q); - /* Mark all outstanding jobs as bad, thus completing them */ - spin_lock(&sched->base.job_list_lock); - list_for_each_entry(tmp_job, &sched->base.pending_list, drm.list) - xe_sched_job_set_error(tmp_job, !i++ ? err : -ECANCELED); - spin_unlock(&sched->base.job_list_lock); - - /* Start fence signaling */ - xe_hw_fence_irq_start(q->fence_irq); - - return DRM_GPU_SCHED_STAT_RESET; + /* + * We want the job added back to the pending list so it gets freed; this + * is what DRM_GPU_SCHED_STAT_NO_HANG does. + */ + return DRM_GPU_SCHED_STAT_NO_HANG; -sched_enable: - set_exec_queue_pending_tdr_exit(q); - enable_scheduling(q); rearm: /* * XXX: Ideally want to adjust timeout based on current execution time @@ -1829,8 +1633,6 @@ static void __guc_exec_queue_destroy_async(struct work_struct *w) mutex_unlock(&group->list_lock); } - if (xe_exec_queue_is_lr(q)) - cancel_work_sync(&ge->lr_tdr); /* Confirm no work left behind accessing device structures */ cancel_delayed_work_sync(&ge->sched.base.work_tdr); @@ -2134,9 +1936,6 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) if (err) goto err_sched; - if (xe_exec_queue_is_lr(q)) - INIT_WORK(&q->guc->lr_tdr, xe_guc_exec_queue_lr_cleanup); - mutex_lock(&guc->submission_state.lock); err = alloc_guc_id(guc, q); @@ -2432,9 +2231,7 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q) /* Clean up lost G2H + reset engine state */ if (exec_queue_registered(q)) { - if (exec_queue_extra_ref(q) || xe_exec_queue_is_lr(q)) - xe_exec_queue_put(q); - else if (exec_queue_destroyed(q)) + if (exec_queue_destroyed(q)) __guc_exec_queue_destroy(guc, q); } if (q->guc->suspend_pending) { @@ -2464,9 +2261,6 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q) trace_xe_sched_job_ban(job); ban = true; } - } else if (xe_exec_queue_is_lr(q) && - !xe_lrc_ring_is_idle(q->lrc[0])) { - ban = true; } if (ban) { @@ -2546,11 +2340,8 @@ static void guc_exec_queue_revert_pending_state_change(struct xe_guc *guc, q->guc->id); } - if (pending_enable && !pending_resume && - !exec_queue_pending_tdr_exit(q)) { + if (pending_enable && !pending_resume) { clear_exec_queue_registered(q); - if (xe_exec_queue_is_lr(q)) - xe_exec_queue_put(q); xe_gt_dbg(guc_to_gt(guc), "Replay REGISTER - guc_id=%d", q->guc->id); } @@ -2558,7 +2349,6 @@ static void guc_exec_queue_revert_pending_state_change(struct xe_guc *guc, if (pending_enable) { clear_exec_queue_enabled(q); clear_exec_queue_pending_resume(q); - clear_exec_queue_pending_tdr_exit(q); clear_exec_queue_pending_enable(q); xe_gt_dbg(guc_to_gt(guc), "Replay ENABLE - guc_id=%d", q->guc->id); @@ -2566,11 +2356,7 @@ static void guc_exec_queue_revert_pending_state_change(struct xe_guc *guc, if (exec_queue_destroyed(q) && exec_queue_registered(q)) { clear_exec_queue_destroyed(q); - if (exec_queue_extra_ref(q)) - xe_exec_queue_put(q); - else - q->guc->needs_cleanup = true; - clear_exec_queue_extra_ref(q); + q->guc->needs_cleanup = true; xe_gt_dbg(guc_to_gt(guc), "Replay CLEANUP - guc_id=%d", q->guc->id); } @@ -2588,7 +2374,6 @@ static void guc_exec_queue_revert_pending_state_change(struct xe_guc *guc, if (!pending_enable) set_exec_queue_enabled(q); clear_exec_queue_pending_disable(q); - clear_exec_queue_check_timeout(q); xe_gt_dbg(guc_to_gt(guc), "Replay DISABLE - guc_id=%d", q->guc->id); } @@ -2623,10 +2408,7 @@ static void guc_exec_queue_pause(struct xe_guc *guc, struct xe_exec_queue *q) /* Stop scheduling + flush any DRM scheduler operations */ xe_sched_submission_stop(sched); - if (xe_exec_queue_is_lr(q)) - cancel_work_sync(&q->guc->lr_tdr); - else - cancel_delayed_work_sync(&sched->base.work_tdr); + cancel_delayed_work_sync(&sched->base.work_tdr); guc_exec_queue_revert_pending_state_change(guc, q); @@ -2753,11 +2535,12 @@ static void guc_exec_queue_unpause_prepare(struct xe_guc *guc, struct xe_exec_queue *q) { struct xe_gpu_scheduler *sched = &q->guc->sched; - struct xe_sched_job *job = NULL, *__job; + struct xe_sched_job *job = NULL; + struct drm_sched_job *s_job; bool restore_replay = false; - list_for_each_entry(__job, &sched->base.pending_list, drm.list) { - job = __job; + drm_sched_for_each_pending_job(s_job, &sched->base, NULL) { + job = to_xe_sched_job(s_job); restore_replay |= job->restore_replay; if (restore_replay) { xe_gt_dbg(guc_to_gt(guc), "Replay JOB - guc_id=%d, seqno=%d", @@ -2881,7 +2664,7 @@ void xe_guc_submit_unpause_vf(struct xe_guc *guc) * created after resfix done. */ if (q->guc->id != index || - !READ_ONCE(q->guc->sched.base.pause_submit)) + !drm_sched_is_stopped(&q->guc->sched.base)) continue; guc_exec_queue_unpause(guc, q); @@ -2967,13 +2750,10 @@ static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q, q->guc->resume_time = ktime_get(); clear_exec_queue_pending_resume(q); - clear_exec_queue_pending_tdr_exit(q); clear_exec_queue_pending_enable(q); smp_wmb(); wake_up_all(&guc->ct.wq); } else { - bool check_timeout = exec_queue_check_timeout(q); - xe_gt_assert(guc_to_gt(guc), runnable_state == 0); xe_gt_assert(guc_to_gt(guc), exec_queue_pending_disable(q)); @@ -2981,11 +2761,11 @@ static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q, suspend_fence_signal(q); clear_exec_queue_pending_disable(q); } else { - if (exec_queue_banned(q) || check_timeout) { + if (exec_queue_banned(q)) { smp_wmb(); wake_up_all(&guc->ct.wq); } - if (!check_timeout && exec_queue_destroyed(q)) { + if (exec_queue_destroyed(q)) { /* * Make sure to clear the pending_disable only * after sampling the destroyed state. We want @@ -3048,11 +2828,7 @@ static void handle_deregister_done(struct xe_guc *guc, struct xe_exec_queue *q) trace_xe_exec_queue_deregister_done(q); clear_exec_queue_registered(q); - - if (exec_queue_extra_ref(q) || xe_exec_queue_is_lr(q)) - xe_exec_queue_put(q); - else - __guc_exec_queue_destroy(guc, q); + __guc_exec_queue_destroy(guc, q); } int xe_guc_deregister_done_handler(struct xe_guc *guc, u32 *msg, u32 len) @@ -3386,29 +3162,6 @@ xe_guc_exec_queue_snapshot_capture(struct xe_exec_queue *q) snapshot->multi_queue.primary = xe_exec_queue_multi_queue_primary(q)->guc->id; snapshot->multi_queue.pos = q->multi_queue.pos; } - spin_lock(&sched->base.job_list_lock); - snapshot->pending_list_size = list_count_nodes(&sched->base.pending_list); - snapshot->pending_list = kmalloc_array(snapshot->pending_list_size, - sizeof(struct pending_list_snapshot), - GFP_ATOMIC); - - if (snapshot->pending_list) { - struct xe_sched_job *job_iter; - - i = 0; - list_for_each_entry(job_iter, &sched->base.pending_list, drm.list) { - snapshot->pending_list[i].seqno = - xe_sched_job_seqno(job_iter); - snapshot->pending_list[i].fence = - dma_fence_is_signaled(job_iter->fence) ? 1 : 0; - snapshot->pending_list[i].finished = - dma_fence_is_signaled(&job_iter->drm.s_fence->finished) - ? 1 : 0; - i++; - } - } - - spin_unlock(&sched->base.job_list_lock); return snapshot; } @@ -3472,13 +3225,6 @@ xe_guc_exec_queue_snapshot_print(struct xe_guc_submit_exec_queue_snapshot *snaps drm_printf(p, "\tMulti queue primary GuC ID: %d\n", snapshot->multi_queue.primary); drm_printf(p, "\tMulti queue position: %d\n", snapshot->multi_queue.pos); } - - for (i = 0; snapshot->pending_list && i < snapshot->pending_list_size; - i++) - drm_printf(p, "\tJob: seqno=%d, fence=%d, finished=%d\n", - snapshot->pending_list[i].seqno, - snapshot->pending_list[i].fence, - snapshot->pending_list[i].finished); } /** @@ -3501,7 +3247,6 @@ void xe_guc_exec_queue_snapshot_free(struct xe_guc_submit_exec_queue_snapshot *s xe_lrc_snapshot_free(snapshot->lrc[i]); kfree(snapshot->lrc); } - kfree(snapshot->pending_list); kfree(snapshot); } |
