diff options
author | Suraj Kandpal <suraj.kandpal@intel.com> | 2024-10-28 17:51:12 +0530 |
---|---|---|
committer | Suraj Kandpal <suraj.kandpal@intel.com> | 2024-10-28 17:51:12 +0530 |
commit | 2e13f730b1cd34153c5413f7e291682ff8a1fe06 (patch) | |
tree | dd2879d61a66aeaeef0190f4572a95dd68511010 | |
parent | a092bc531da99903b88e7306ad45ee1f92efef9d (diff) |
2024y-10m-28d-12h-19m-31s UTC: drm-tip rerere cache update
git version 2.34.1
-rw-r--r-- | rr-cache/427a56bdebcb80f084372bfcd4fb5f57615d3739/postimage | 977 | ||||
-rw-r--r-- | rr-cache/427a56bdebcb80f084372bfcd4fb5f57615d3739/preimage | 980 |
2 files changed, 0 insertions, 1957 deletions
diff --git a/rr-cache/427a56bdebcb80f084372bfcd4fb5f57615d3739/postimage b/rr-cache/427a56bdebcb80f084372bfcd4fb5f57615d3739/postimage deleted file mode 100644 index 1bb66db47265..000000000000 --- a/rr-cache/427a56bdebcb80f084372bfcd4fb5f57615d3739/postimage +++ /dev/null @@ -1,977 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright © 2022 Intel Corporation - */ - -#include "xe_gt.h" - -#include <linux/minmax.h> - -#include <drm/drm_managed.h> -#include <uapi/drm/xe_drm.h> - -#include <generated/xe_wa_oob.h> - -#include <generated/xe_wa_oob.h> - -#include "instructions/xe_gfxpipe_commands.h" -#include "instructions/xe_mi_commands.h" -#include "regs/xe_gt_regs.h" -#include "xe_assert.h" -#include "xe_bb.h" -#include "xe_bo.h" -#include "xe_device.h" -#include "xe_exec_queue.h" -#include "xe_execlist.h" -#include "xe_force_wake.h" -#include "xe_ggtt.h" -#include "xe_gsc.h" -#include "xe_gt_ccs_mode.h" -#include "xe_gt_clock.h" -#include "xe_gt_freq.h" -#include "xe_gt_idle.h" -#include "xe_gt_mcr.h" -#include "xe_gt_pagefault.h" -#include "xe_gt_printk.h" -#include "xe_gt_sriov_pf.h" -#include "xe_gt_sysfs.h" -#include "xe_gt_tlb_invalidation.h" -#include "xe_gt_topology.h" -#include "xe_guc_exec_queue_types.h" -#include "xe_guc_pc.h" -#include "xe_hw_fence.h" -#include "xe_hw_engine_class_sysfs.h" -#include "xe_irq.h" -#include "xe_lmtt.h" -#include "xe_lrc.h" -#include "xe_map.h" -#include "xe_migrate.h" -#include "xe_mmio.h" -#include "xe_pat.h" -#include "xe_pcode.h" -#include "xe_pm.h" -#include "xe_mocs.h" -#include "xe_reg_sr.h" -#include "xe_ring_ops.h" -#include "xe_sa.h" -#include "xe_sched_job.h" -#include "xe_sriov.h" -#include "xe_tuning.h" -#include "xe_uc.h" -#include "xe_uc_fw.h" -#include "xe_vm.h" -#include "xe_wa.h" -#include "xe_wopcm.h" - -static void gt_fini(struct drm_device *drm, void *arg) -{ - struct xe_gt *gt = arg; - - destroy_workqueue(gt->ordered_wq); -} - -struct xe_gt *xe_gt_alloc(struct xe_tile *tile) -{ - struct xe_gt *gt; - int err; - - gt = drmm_kzalloc(&tile_to_xe(tile)->drm, sizeof(*gt), GFP_KERNEL); - if (!gt) - return ERR_PTR(-ENOMEM); - - gt->tile = tile; - gt->ordered_wq = alloc_ordered_workqueue("gt-ordered-wq", 0); - - err = drmm_add_action_or_reset(>_to_xe(gt)->drm, gt_fini, gt); - if (err) - return ERR_PTR(err); - - return gt; -} - -void xe_gt_sanitize(struct xe_gt *gt) -{ - /* - * FIXME: if xe_uc_sanitize is called here, on TGL driver will not - * reload - */ - gt->uc.guc.submission_state.enabled = false; -} - -static void xe_gt_enable_host_l2_vram(struct xe_gt *gt) -{ - u32 reg; - int err; - - if (!XE_WA(gt, 16023588340)) - return; - - err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (WARN_ON(err)) - return; - - if (!xe_gt_is_media_type(gt)) { - xe_mmio_write32(gt, SCRATCH1LPFC, EN_L3_RW_CCS_CACHE_FLUSH); - reg = xe_gt_mcr_unicast_read_any(gt, XE2_GAMREQSTRM_CTRL); - reg |= CG_DIS_CNTLBUS; - xe_gt_mcr_multicast_write(gt, XE2_GAMREQSTRM_CTRL, reg); - } - - xe_gt_mcr_multicast_write(gt, XEHPC_L3CLOS_MASK(3), 0x3); - xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); -} - -static void xe_gt_disable_host_l2_vram(struct xe_gt *gt) -{ - u32 reg; - int err; - - if (!XE_WA(gt, 16023588340)) - return; - - if (xe_gt_is_media_type(gt)) - return; - - err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (WARN_ON(err)) - return; - - reg = xe_gt_mcr_unicast_read_any(gt, XE2_GAMREQSTRM_CTRL); - reg &= ~CG_DIS_CNTLBUS; - xe_gt_mcr_multicast_write(gt, XE2_GAMREQSTRM_CTRL, reg); - - xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); -} - -/** - * xe_gt_remove() - Clean up the GT structures before driver removal - * @gt: the GT object - * - * This function should only act on objects/structures that must be cleaned - * before the driver removal callback is complete and therefore can't be - * deferred to a drmm action. - */ -void xe_gt_remove(struct xe_gt *gt) -{ - int i; - - xe_uc_remove(>->uc); - - for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) - xe_hw_fence_irq_finish(>->fence_irq[i]); - - xe_gt_disable_host_l2_vram(gt); -} - -static void gt_reset_worker(struct work_struct *w); - -static int emit_nop_job(struct xe_gt *gt, struct xe_exec_queue *q) -{ - struct xe_sched_job *job; - struct xe_bb *bb; - struct dma_fence *fence; - long timeout; - - bb = xe_bb_new(gt, 4, false); - if (IS_ERR(bb)) - return PTR_ERR(bb); - - job = xe_bb_create_job(q, bb); - if (IS_ERR(job)) { - xe_bb_free(bb, NULL); - return PTR_ERR(job); - } - - xe_sched_job_arm(job); - fence = dma_fence_get(&job->drm.s_fence->finished); - xe_sched_job_push(job); - - timeout = dma_fence_wait_timeout(fence, false, HZ); - dma_fence_put(fence); - xe_bb_free(bb, NULL); - if (timeout < 0) - return timeout; - else if (!timeout) - return -ETIME; - - return 0; -} - -/* - * Convert back from encoded value to type-safe, only to be used when reg.mcr - * is true - */ -static struct xe_reg_mcr to_xe_reg_mcr(const struct xe_reg reg) -{ - return (const struct xe_reg_mcr){.__reg.raw = reg.raw }; -} - -static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q) -{ - struct xe_reg_sr *sr = &q->hwe->reg_lrc; - struct xe_reg_sr_entry *entry; - unsigned long idx; - struct xe_sched_job *job; - struct xe_bb *bb; - struct dma_fence *fence; - long timeout; - int count = 0; - - if (q->hwe->class == XE_ENGINE_CLASS_RENDER) - /* Big enough to emit all of the context's 3DSTATE */ - bb = xe_bb_new(gt, xe_gt_lrc_size(gt, q->hwe->class), false); - else - /* Just pick a large BB size */ - bb = xe_bb_new(gt, SZ_4K, false); - - if (IS_ERR(bb)) - return PTR_ERR(bb); - - xa_for_each(&sr->xa, idx, entry) - ++count; - - if (count) { - xe_gt_dbg(gt, "LRC WA %s save-restore batch\n", sr->name); - - bb->cs[bb->len++] = MI_LOAD_REGISTER_IMM | MI_LRI_NUM_REGS(count); - - xa_for_each(&sr->xa, idx, entry) { - struct xe_reg reg = entry->reg; - struct xe_reg_mcr reg_mcr = to_xe_reg_mcr(reg); - u32 val; - - /* - * Skip reading the register if it's not really needed - */ - if (reg.masked) - val = entry->clr_bits << 16; - else if (entry->clr_bits + 1) - val = (reg.mcr ? - xe_gt_mcr_unicast_read_any(gt, reg_mcr) : - xe_mmio_read32(gt, reg)) & (~entry->clr_bits); - else - val = 0; - - val |= entry->set_bits; - - bb->cs[bb->len++] = reg.addr; - bb->cs[bb->len++] = val; - xe_gt_dbg(gt, "REG[0x%x] = 0x%08x", reg.addr, val); - } - } - - xe_lrc_emit_hwe_state_instructions(q, bb); - - job = xe_bb_create_job(q, bb); - if (IS_ERR(job)) { - xe_bb_free(bb, NULL); - return PTR_ERR(job); - } - - xe_sched_job_arm(job); - fence = dma_fence_get(&job->drm.s_fence->finished); - xe_sched_job_push(job); - - timeout = dma_fence_wait_timeout(fence, false, HZ); - dma_fence_put(fence); - xe_bb_free(bb, NULL); - if (timeout < 0) - return timeout; - else if (!timeout) - return -ETIME; - - return 0; -} - -int xe_gt_record_default_lrcs(struct xe_gt *gt) -{ - struct xe_device *xe = gt_to_xe(gt); - struct xe_hw_engine *hwe; - enum xe_hw_engine_id id; - int err = 0; - - for_each_hw_engine(hwe, gt, id) { - struct xe_exec_queue *q, *nop_q; - void *default_lrc; - - if (gt->default_lrc[hwe->class]) - continue; - - xe_reg_sr_init(&hwe->reg_lrc, hwe->name, xe); - xe_wa_process_lrc(hwe); - xe_hw_engine_setup_default_lrc_state(hwe); - xe_tuning_process_lrc(hwe); - - default_lrc = drmm_kzalloc(&xe->drm, - xe_gt_lrc_size(gt, hwe->class), - GFP_KERNEL); - if (!default_lrc) - return -ENOMEM; - - q = xe_exec_queue_create(xe, NULL, BIT(hwe->logical_instance), 1, - hwe, EXEC_QUEUE_FLAG_KERNEL, 0); - if (IS_ERR(q)) { - err = PTR_ERR(q); - xe_gt_err(gt, "hwe %s: xe_exec_queue_create failed (%pe)\n", - hwe->name, q); - return err; - } - - /* Prime golden LRC with known good state */ - err = emit_wa_job(gt, q); - if (err) { - xe_gt_err(gt, "hwe %s: emit_wa_job failed (%pe) guc_id=%u\n", - hwe->name, ERR_PTR(err), q->guc->id); - goto put_exec_queue; - } - - nop_q = xe_exec_queue_create(xe, NULL, BIT(hwe->logical_instance), - 1, hwe, EXEC_QUEUE_FLAG_KERNEL, 0); - if (IS_ERR(nop_q)) { - err = PTR_ERR(nop_q); - xe_gt_err(gt, "hwe %s: nop xe_exec_queue_create failed (%pe)\n", - hwe->name, nop_q); - goto put_exec_queue; - } - - /* Switch to different LRC */ - err = emit_nop_job(gt, nop_q); - if (err) { - xe_gt_err(gt, "hwe %s: nop emit_nop_job failed (%pe) guc_id=%u\n", - hwe->name, ERR_PTR(err), nop_q->guc->id); - goto put_nop_q; - } - - /* Reload golden LRC to record the effect of any indirect W/A */ - err = emit_nop_job(gt, q); - if (err) { - xe_gt_err(gt, "hwe %s: emit_nop_job failed (%pe) guc_id=%u\n", - hwe->name, ERR_PTR(err), q->guc->id); - goto put_nop_q; - } - - xe_map_memcpy_from(xe, default_lrc, - &q->lrc[0]->bo->vmap, - xe_lrc_pphwsp_offset(q->lrc[0]), - xe_gt_lrc_size(gt, hwe->class)); - - gt->default_lrc[hwe->class] = default_lrc; -put_nop_q: - xe_exec_queue_put(nop_q); -put_exec_queue: - xe_exec_queue_put(q); - if (err) - break; - } - - return err; -} - -int xe_gt_init_early(struct xe_gt *gt) -{ - int err; - - if (IS_SRIOV_PF(gt_to_xe(gt))) { - err = xe_gt_sriov_pf_init_early(gt); - if (err) - return err; - } - - xe_reg_sr_init(>->reg_sr, "GT", gt_to_xe(gt)); - - err = xe_wa_init(gt); - if (err) - return err; - - xe_wa_process_gt(gt); - xe_wa_process_oob(gt); - xe_tuning_process_gt(gt); - - xe_force_wake_init_gt(gt, gt_to_fw(gt)); - xe_pcode_init(gt); - spin_lock_init(>->global_invl_lock); - - return 0; -} - -static void dump_pat_on_error(struct xe_gt *gt) -{ - struct drm_printer p; - char prefix[32]; - - snprintf(prefix, sizeof(prefix), "[GT%u Error]", gt->info.id); - p = drm_dbg_printer(>_to_xe(gt)->drm, DRM_UT_DRIVER, prefix); - - xe_pat_dump(gt, &p); -} - -static int gt_fw_domain_init(struct xe_gt *gt) -{ - int err, i; - - err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (err) - goto err_hw_fence_irq; - - if (!xe_gt_is_media_type(gt)) { - err = xe_ggtt_init(gt_to_tile(gt)->mem.ggtt); - if (err) - goto err_force_wake; - if (IS_SRIOV_PF(gt_to_xe(gt))) - xe_lmtt_init(>_to_tile(gt)->sriov.pf.lmtt); - } - - /* Enable per hw engine IRQs */ - xe_irq_enable_hwe(gt); - - /* Rerun MCR init as we now have hw engine list */ - xe_gt_mcr_init(gt); - - err = xe_hw_engines_init_early(gt); - if (err) - goto err_force_wake; - - err = xe_hw_engine_class_sysfs_init(gt); - if (err) - goto err_force_wake; - - /* Initialize CCS mode sysfs after early initialization of HW engines */ - err = xe_gt_ccs_mode_sysfs_init(gt); - if (err) - goto err_force_wake; - - /* - * Stash hardware-reported version. Since this register does not exist - * on pre-MTL platforms, reading it there will (correctly) return 0. - */ - gt->info.gmdid = xe_mmio_read32(gt, GMD_ID); - - err = xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); - XE_WARN_ON(err); - - return 0; - -err_force_wake: - dump_pat_on_error(gt); - xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); -err_hw_fence_irq: - for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) - xe_hw_fence_irq_finish(>->fence_irq[i]); - - return err; -} - -static int all_fw_domain_init(struct xe_gt *gt) -{ - int err, i; - - err = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - if (err) - goto err_hw_fence_irq; - - xe_gt_mcr_set_implicit_defaults(gt); - xe_reg_sr_apply_mmio(>->reg_sr, gt); - - err = xe_gt_clock_init(gt); - if (err) - goto err_force_wake; - - xe_mocs_init(gt); - err = xe_execlist_init(gt); - if (err) - goto err_force_wake; - - err = xe_hw_engines_init(gt); - if (err) - goto err_force_wake; - - err = xe_uc_init_post_hwconfig(>->uc); - if (err) - goto err_force_wake; - - if (!xe_gt_is_media_type(gt)) { - /* - * USM has its only SA pool to non-block behind user operations - */ - if (gt_to_xe(gt)->info.has_usm) { - struct xe_device *xe = gt_to_xe(gt); - - gt->usm.bb_pool = xe_sa_bo_manager_init(gt_to_tile(gt), - IS_DGFX(xe) ? SZ_1M : SZ_512K, 16); - if (IS_ERR(gt->usm.bb_pool)) { - err = PTR_ERR(gt->usm.bb_pool); - goto err_force_wake; - } - } - } - - if (!xe_gt_is_media_type(gt)) { - struct xe_tile *tile = gt_to_tile(gt); - - tile->migrate = xe_migrate_init(tile); - if (IS_ERR(tile->migrate)) { - err = PTR_ERR(tile->migrate); - goto err_force_wake; - } - } - - err = xe_uc_init_hw(>->uc); - if (err) - goto err_force_wake; - - /* Configure default CCS mode of 1 engine with all resources */ - if (xe_gt_ccs_mode_enabled(gt)) { - gt->ccs_mode = 1; - xe_gt_apply_ccs_mode(gt); - } - - if (IS_SRIOV_PF(gt_to_xe(gt)) && !xe_gt_is_media_type(gt)) - xe_lmtt_init_hw(>_to_tile(gt)->sriov.pf.lmtt); - - if (IS_SRIOV_PF(gt_to_xe(gt))) - xe_gt_sriov_pf_init_hw(gt); - - err = xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL); - XE_WARN_ON(err); - - return 0; - -err_force_wake: - xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL); -err_hw_fence_irq: - for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) - xe_hw_fence_irq_finish(>->fence_irq[i]); - - return err; -} - -/* - * Initialize enough GT to be able to load GuC in order to obtain hwconfig and - * enable CTB communication. - */ -int xe_gt_init_hwconfig(struct xe_gt *gt) -{ - int err; - - err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (err) - goto out; - - xe_gt_mcr_init_early(gt); - xe_pat_init(gt); - - err = xe_uc_init(>->uc); - if (err) - goto out_fw; - - err = xe_uc_init_hwconfig(>->uc); - if (err) - goto out_fw; - - xe_gt_topology_init(gt); - xe_gt_mcr_init(gt); - xe_gt_enable_host_l2_vram(gt); - -out_fw: - xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); -out: - return err; -} - -int xe_gt_init(struct xe_gt *gt) -{ - int err; - int i; - - INIT_WORK(>->reset.worker, gt_reset_worker); - - for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) { - gt->ring_ops[i] = xe_ring_ops_get(gt, i); - xe_hw_fence_irq_init(>->fence_irq[i]); - } - - err = xe_gt_tlb_invalidation_init(gt); - if (err) - return err; - - err = xe_gt_pagefault_init(gt); - if (err) - return err; - - xe_mocs_init_early(gt); - - err = xe_gt_sysfs_init(gt); - if (err) - return err; - - err = gt_fw_domain_init(gt); - if (err) - return err; - - err = xe_gt_idle_init(>->gtidle); - if (err) - return err; - - err = xe_gt_freq_init(gt); - if (err) - return err; - - xe_force_wake_init_engines(gt, gt_to_fw(gt)); - - err = all_fw_domain_init(gt); - if (err) - return err; - - xe_gt_record_user_engines(gt); - - return 0; -} - -void xe_gt_record_user_engines(struct xe_gt *gt) -{ - struct xe_hw_engine *hwe; - enum xe_hw_engine_id id; - - gt->user_engines.mask = 0; - memset(gt->user_engines.instances_per_class, 0, - sizeof(gt->user_engines.instances_per_class)); - - for_each_hw_engine(hwe, gt, id) { - if (xe_hw_engine_is_reserved(hwe)) - continue; - - gt->user_engines.mask |= BIT_ULL(id); - gt->user_engines.instances_per_class[hwe->class]++; - } - - xe_gt_assert(gt, (gt->user_engines.mask | gt->info.engine_mask) - == gt->info.engine_mask); -} - -static int do_gt_reset(struct xe_gt *gt) -{ - int err; - - xe_gsc_wa_14015076503(gt, true); - - xe_mmio_write32(gt, GDRST, GRDOM_FULL); - err = xe_mmio_wait32(gt, GDRST, GRDOM_FULL, 0, 5000, NULL, false); - if (err) - xe_gt_err(gt, "failed to clear GRDOM_FULL (%pe)\n", - ERR_PTR(err)); - - xe_gsc_wa_14015076503(gt, false); - - return err; -} - -static int vf_gt_restart(struct xe_gt *gt) -{ - int err; - - err = xe_uc_sanitize_reset(>->uc); - if (err) - return err; - - err = xe_uc_init_hw(>->uc); - if (err) - return err; - - err = xe_uc_start(>->uc); - if (err) - return err; - - return 0; -} - -static int do_gt_restart(struct xe_gt *gt) -{ - struct xe_hw_engine *hwe; - enum xe_hw_engine_id id; - int err; - - if (IS_SRIOV_VF(gt_to_xe(gt))) - return vf_gt_restart(gt); - - xe_pat_init(gt); - - xe_gt_enable_host_l2_vram(gt); - - xe_gt_mcr_set_implicit_defaults(gt); - xe_reg_sr_apply_mmio(>->reg_sr, gt); - - err = xe_wopcm_init(>->uc.wopcm); - if (err) - return err; - - for_each_hw_engine(hwe, gt, id) - xe_hw_engine_enable_ring(hwe); - - err = xe_uc_sanitize_reset(>->uc); - if (err) - return err; - - err = xe_uc_init_hw(>->uc); - if (err) - return err; - - if (IS_SRIOV_PF(gt_to_xe(gt)) && !xe_gt_is_media_type(gt)) - xe_lmtt_init_hw(>_to_tile(gt)->sriov.pf.lmtt); - - if (IS_SRIOV_PF(gt_to_xe(gt))) - xe_gt_sriov_pf_init_hw(gt); - - xe_mocs_init(gt); - err = xe_uc_start(>->uc); - if (err) - return err; - - for_each_hw_engine(hwe, gt, id) { - xe_reg_sr_apply_mmio(&hwe->reg_sr, gt); - xe_reg_sr_apply_whitelist(hwe); - } - - /* Get CCS mode in sync between sw/hw */ - xe_gt_apply_ccs_mode(gt); - - /* Restore GT freq to expected values */ - xe_gt_sanitize_freq(gt); - - if (IS_SRIOV_PF(gt_to_xe(gt))) - xe_gt_sriov_pf_restart(gt); - - return 0; -} - -static int gt_reset(struct xe_gt *gt) -{ - int err; - - if (xe_device_wedged(gt_to_xe(gt))) - return -ECANCELED; - - /* We only support GT resets with GuC submission */ - if (!xe_device_uc_enabled(gt_to_xe(gt))) - return -ENODEV; - - xe_gt_info(gt, "reset started\n"); - - if (xe_fault_inject_gt_reset()) { - err = -ECANCELED; - goto err_fail; - } - - xe_pm_runtime_get(gt_to_xe(gt)); - xe_gt_sanitize(gt); - - err = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - if (err) - goto err_msg; - - xe_uc_gucrc_disable(>->uc); - xe_uc_stop_prepare(>->uc); - xe_gt_pagefault_reset(gt); - - xe_uc_stop(>->uc); - - xe_gt_tlb_invalidation_reset(gt); - - err = do_gt_reset(gt); - if (err) - goto err_out; - - err = do_gt_restart(gt); - if (err) - goto err_out; - - err = xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL); - XE_WARN_ON(err); - xe_pm_runtime_put(gt_to_xe(gt)); - - xe_gt_info(gt, "reset done\n"); - - return 0; - -err_out: - XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); -err_msg: - XE_WARN_ON(xe_uc_start(>->uc)); - xe_pm_runtime_put(gt_to_xe(gt)); -err_fail: - xe_gt_err(gt, "reset failed (%pe)\n", ERR_PTR(err)); - - xe_device_declare_wedged(gt_to_xe(gt)); - - return err; -} - -static void gt_reset_worker(struct work_struct *w) -{ - struct xe_gt *gt = container_of(w, typeof(*gt), reset.worker); - - gt_reset(gt); -} - -void xe_gt_reset_async(struct xe_gt *gt) -{ - xe_gt_info(gt, "trying reset\n"); - - /* Don't do a reset while one is already in flight */ - if (!xe_fault_inject_gt_reset() && xe_uc_reset_prepare(>->uc)) - return; - - xe_gt_info(gt, "reset queued\n"); - queue_work(gt->ordered_wq, >->reset.worker); -} - -void xe_gt_suspend_prepare(struct xe_gt *gt) -{ - XE_WARN_ON(xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL)); - - xe_uc_stop_prepare(>->uc); - - XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); -} - -int xe_gt_suspend(struct xe_gt *gt) -{ - int err; - - xe_gt_dbg(gt, "suspending\n"); - xe_gt_sanitize(gt); - - err = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - if (err) - goto err_msg; - - err = xe_uc_suspend(>->uc); - if (err) - goto err_force_wake; - - xe_gt_idle_disable_pg(gt); - - xe_gt_disable_host_l2_vram(gt); - - XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); - xe_gt_dbg(gt, "suspended\n"); - - return 0; - -err_force_wake: - XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); -err_msg: - xe_gt_err(gt, "suspend failed (%pe)\n", ERR_PTR(err)); - - return err; -} - -/** - * xe_gt_sanitize_freq() - Restore saved frequencies if necessary. - * @gt: the GT object - * - * Called after driver init/GSC load completes to restore GT frequencies if we - * limited them for any WAs. - */ -int xe_gt_sanitize_freq(struct xe_gt *gt) -{ - int ret = 0; - - if ((!xe_uc_fw_is_available(>->uc.gsc.fw) || - xe_uc_fw_is_loaded(>->uc.gsc.fw)) && XE_WA(gt, 22019338487)) - ret = xe_guc_pc_restore_stashed_freq(>->uc.guc.pc); - - return ret; -} - -int xe_gt_resume(struct xe_gt *gt) -{ - int err; - - xe_gt_dbg(gt, "resuming\n"); - err = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - if (err) - goto err_msg; - - err = do_gt_restart(gt); - if (err) - goto err_force_wake; - - xe_gt_idle_enable_pg(gt); - - XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); - xe_gt_dbg(gt, "resumed\n"); - - return 0; - -err_force_wake: - XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); -err_msg: - xe_gt_err(gt, "resume failed (%pe)\n", ERR_PTR(err)); - - return err; -} - -struct xe_hw_engine *xe_gt_hw_engine(struct xe_gt *gt, - enum xe_engine_class class, - u16 instance, bool logical) -{ - struct xe_hw_engine *hwe; - enum xe_hw_engine_id id; - - for_each_hw_engine(hwe, gt, id) - if (hwe->class == class && - ((!logical && hwe->instance == instance) || - (logical && hwe->logical_instance == instance))) - return hwe; - - return NULL; -} - -struct xe_hw_engine *xe_gt_any_hw_engine_by_reset_domain(struct xe_gt *gt, - enum xe_engine_class class) -{ - struct xe_hw_engine *hwe; - enum xe_hw_engine_id id; - - for_each_hw_engine(hwe, gt, id) { - switch (class) { - case XE_ENGINE_CLASS_RENDER: - case XE_ENGINE_CLASS_COMPUTE: - if (hwe->class == XE_ENGINE_CLASS_RENDER || - hwe->class == XE_ENGINE_CLASS_COMPUTE) - return hwe; - break; - default: - if (hwe->class == class) - return hwe; - } - } - - return NULL; -} - -struct xe_hw_engine *xe_gt_any_hw_engine(struct xe_gt *gt) -{ - struct xe_hw_engine *hwe; - enum xe_hw_engine_id id; - - for_each_hw_engine(hwe, gt, id) - return hwe; - - return NULL; -} - -/** - * xe_gt_declare_wedged() - Declare GT wedged - * @gt: the GT object - * - * Wedge the GT which stops all submission, saves desired debug state, and - * cleans up anything which could timeout. - */ -void xe_gt_declare_wedged(struct xe_gt *gt) -{ - xe_gt_assert(gt, gt_to_xe(gt)->wedged.mode); - - xe_uc_declare_wedged(>->uc); - xe_gt_tlb_invalidation_reset(gt); -} diff --git a/rr-cache/427a56bdebcb80f084372bfcd4fb5f57615d3739/preimage b/rr-cache/427a56bdebcb80f084372bfcd4fb5f57615d3739/preimage deleted file mode 100644 index 8895c3b8bb56..000000000000 --- a/rr-cache/427a56bdebcb80f084372bfcd4fb5f57615d3739/preimage +++ /dev/null @@ -1,980 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright © 2022 Intel Corporation - */ - -#include "xe_gt.h" - -#include <linux/minmax.h> - -#include <drm/drm_managed.h> -#include <uapi/drm/xe_drm.h> -<<<<<<< -======= - -#include <generated/xe_wa_oob.h> ->>>>>>> - -#include <generated/xe_wa_oob.h> - -#include "instructions/xe_gfxpipe_commands.h" -#include "instructions/xe_mi_commands.h" -#include "regs/xe_gt_regs.h" -#include "xe_assert.h" -#include "xe_bb.h" -#include "xe_bo.h" -#include "xe_device.h" -#include "xe_exec_queue.h" -#include "xe_execlist.h" -#include "xe_force_wake.h" -#include "xe_ggtt.h" -#include "xe_gsc.h" -#include "xe_gt_ccs_mode.h" -#include "xe_gt_clock.h" -#include "xe_gt_freq.h" -#include "xe_gt_idle.h" -#include "xe_gt_mcr.h" -#include "xe_gt_pagefault.h" -#include "xe_gt_printk.h" -#include "xe_gt_sriov_pf.h" -#include "xe_gt_sysfs.h" -#include "xe_gt_tlb_invalidation.h" -#include "xe_gt_topology.h" -#include "xe_guc_exec_queue_types.h" -#include "xe_guc_pc.h" -#include "xe_hw_fence.h" -#include "xe_hw_engine_class_sysfs.h" -#include "xe_irq.h" -#include "xe_lmtt.h" -#include "xe_lrc.h" -#include "xe_map.h" -#include "xe_migrate.h" -#include "xe_mmio.h" -#include "xe_pat.h" -#include "xe_pcode.h" -#include "xe_pm.h" -#include "xe_mocs.h" -#include "xe_reg_sr.h" -#include "xe_ring_ops.h" -#include "xe_sa.h" -#include "xe_sched_job.h" -#include "xe_sriov.h" -#include "xe_tuning.h" -#include "xe_uc.h" -#include "xe_uc_fw.h" -#include "xe_vm.h" -#include "xe_wa.h" -#include "xe_wopcm.h" - -static void gt_fini(struct drm_device *drm, void *arg) -{ - struct xe_gt *gt = arg; - - destroy_workqueue(gt->ordered_wq); -} - -struct xe_gt *xe_gt_alloc(struct xe_tile *tile) -{ - struct xe_gt *gt; - int err; - - gt = drmm_kzalloc(&tile_to_xe(tile)->drm, sizeof(*gt), GFP_KERNEL); - if (!gt) - return ERR_PTR(-ENOMEM); - - gt->tile = tile; - gt->ordered_wq = alloc_ordered_workqueue("gt-ordered-wq", 0); - - err = drmm_add_action_or_reset(>_to_xe(gt)->drm, gt_fini, gt); - if (err) - return ERR_PTR(err); - - return gt; -} - -void xe_gt_sanitize(struct xe_gt *gt) -{ - /* - * FIXME: if xe_uc_sanitize is called here, on TGL driver will not - * reload - */ - gt->uc.guc.submission_state.enabled = false; -} - -static void xe_gt_enable_host_l2_vram(struct xe_gt *gt) -{ - u32 reg; - int err; - - if (!XE_WA(gt, 16023588340)) - return; - - err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (WARN_ON(err)) - return; - - if (!xe_gt_is_media_type(gt)) { - xe_mmio_write32(gt, SCRATCH1LPFC, EN_L3_RW_CCS_CACHE_FLUSH); - reg = xe_gt_mcr_unicast_read_any(gt, XE2_GAMREQSTRM_CTRL); - reg |= CG_DIS_CNTLBUS; - xe_gt_mcr_multicast_write(gt, XE2_GAMREQSTRM_CTRL, reg); - } - - xe_gt_mcr_multicast_write(gt, XEHPC_L3CLOS_MASK(3), 0x3); - xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); -} - -static void xe_gt_disable_host_l2_vram(struct xe_gt *gt) -{ - u32 reg; - int err; - - if (!XE_WA(gt, 16023588340)) - return; - - if (xe_gt_is_media_type(gt)) - return; - - err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (WARN_ON(err)) - return; - - reg = xe_gt_mcr_unicast_read_any(gt, XE2_GAMREQSTRM_CTRL); - reg &= ~CG_DIS_CNTLBUS; - xe_gt_mcr_multicast_write(gt, XE2_GAMREQSTRM_CTRL, reg); - - xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); -} - -/** - * xe_gt_remove() - Clean up the GT structures before driver removal - * @gt: the GT object - * - * This function should only act on objects/structures that must be cleaned - * before the driver removal callback is complete and therefore can't be - * deferred to a drmm action. - */ -void xe_gt_remove(struct xe_gt *gt) -{ - int i; - - xe_uc_remove(>->uc); - - for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) - xe_hw_fence_irq_finish(>->fence_irq[i]); - - xe_gt_disable_host_l2_vram(gt); -} - -static void gt_reset_worker(struct work_struct *w); - -static int emit_nop_job(struct xe_gt *gt, struct xe_exec_queue *q) -{ - struct xe_sched_job *job; - struct xe_bb *bb; - struct dma_fence *fence; - long timeout; - - bb = xe_bb_new(gt, 4, false); - if (IS_ERR(bb)) - return PTR_ERR(bb); - - job = xe_bb_create_job(q, bb); - if (IS_ERR(job)) { - xe_bb_free(bb, NULL); - return PTR_ERR(job); - } - - xe_sched_job_arm(job); - fence = dma_fence_get(&job->drm.s_fence->finished); - xe_sched_job_push(job); - - timeout = dma_fence_wait_timeout(fence, false, HZ); - dma_fence_put(fence); - xe_bb_free(bb, NULL); - if (timeout < 0) - return timeout; - else if (!timeout) - return -ETIME; - - return 0; -} - -/* - * Convert back from encoded value to type-safe, only to be used when reg.mcr - * is true - */ -static struct xe_reg_mcr to_xe_reg_mcr(const struct xe_reg reg) -{ - return (const struct xe_reg_mcr){.__reg.raw = reg.raw }; -} - -static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q) -{ - struct xe_reg_sr *sr = &q->hwe->reg_lrc; - struct xe_reg_sr_entry *entry; - unsigned long idx; - struct xe_sched_job *job; - struct xe_bb *bb; - struct dma_fence *fence; - long timeout; - int count = 0; - - if (q->hwe->class == XE_ENGINE_CLASS_RENDER) - /* Big enough to emit all of the context's 3DSTATE */ - bb = xe_bb_new(gt, xe_gt_lrc_size(gt, q->hwe->class), false); - else - /* Just pick a large BB size */ - bb = xe_bb_new(gt, SZ_4K, false); - - if (IS_ERR(bb)) - return PTR_ERR(bb); - - xa_for_each(&sr->xa, idx, entry) - ++count; - - if (count) { - xe_gt_dbg(gt, "LRC WA %s save-restore batch\n", sr->name); - - bb->cs[bb->len++] = MI_LOAD_REGISTER_IMM | MI_LRI_NUM_REGS(count); - - xa_for_each(&sr->xa, idx, entry) { - struct xe_reg reg = entry->reg; - struct xe_reg_mcr reg_mcr = to_xe_reg_mcr(reg); - u32 val; - - /* - * Skip reading the register if it's not really needed - */ - if (reg.masked) - val = entry->clr_bits << 16; - else if (entry->clr_bits + 1) - val = (reg.mcr ? - xe_gt_mcr_unicast_read_any(gt, reg_mcr) : - xe_mmio_read32(gt, reg)) & (~entry->clr_bits); - else - val = 0; - - val |= entry->set_bits; - - bb->cs[bb->len++] = reg.addr; - bb->cs[bb->len++] = val; - xe_gt_dbg(gt, "REG[0x%x] = 0x%08x", reg.addr, val); - } - } - - xe_lrc_emit_hwe_state_instructions(q, bb); - - job = xe_bb_create_job(q, bb); - if (IS_ERR(job)) { - xe_bb_free(bb, NULL); - return PTR_ERR(job); - } - - xe_sched_job_arm(job); - fence = dma_fence_get(&job->drm.s_fence->finished); - xe_sched_job_push(job); - - timeout = dma_fence_wait_timeout(fence, false, HZ); - dma_fence_put(fence); - xe_bb_free(bb, NULL); - if (timeout < 0) - return timeout; - else if (!timeout) - return -ETIME; - - return 0; -} - -int xe_gt_record_default_lrcs(struct xe_gt *gt) -{ - struct xe_device *xe = gt_to_xe(gt); - struct xe_hw_engine *hwe; - enum xe_hw_engine_id id; - int err = 0; - - for_each_hw_engine(hwe, gt, id) { - struct xe_exec_queue *q, *nop_q; - void *default_lrc; - - if (gt->default_lrc[hwe->class]) - continue; - - xe_reg_sr_init(&hwe->reg_lrc, hwe->name, xe); - xe_wa_process_lrc(hwe); - xe_hw_engine_setup_default_lrc_state(hwe); - xe_tuning_process_lrc(hwe); - - default_lrc = drmm_kzalloc(&xe->drm, - xe_gt_lrc_size(gt, hwe->class), - GFP_KERNEL); - if (!default_lrc) - return -ENOMEM; - - q = xe_exec_queue_create(xe, NULL, BIT(hwe->logical_instance), 1, - hwe, EXEC_QUEUE_FLAG_KERNEL, 0); - if (IS_ERR(q)) { - err = PTR_ERR(q); - xe_gt_err(gt, "hwe %s: xe_exec_queue_create failed (%pe)\n", - hwe->name, q); - return err; - } - - /* Prime golden LRC with known good state */ - err = emit_wa_job(gt, q); - if (err) { - xe_gt_err(gt, "hwe %s: emit_wa_job failed (%pe) guc_id=%u\n", - hwe->name, ERR_PTR(err), q->guc->id); - goto put_exec_queue; - } - - nop_q = xe_exec_queue_create(xe, NULL, BIT(hwe->logical_instance), - 1, hwe, EXEC_QUEUE_FLAG_KERNEL, 0); - if (IS_ERR(nop_q)) { - err = PTR_ERR(nop_q); - xe_gt_err(gt, "hwe %s: nop xe_exec_queue_create failed (%pe)\n", - hwe->name, nop_q); - goto put_exec_queue; - } - - /* Switch to different LRC */ - err = emit_nop_job(gt, nop_q); - if (err) { - xe_gt_err(gt, "hwe %s: nop emit_nop_job failed (%pe) guc_id=%u\n", - hwe->name, ERR_PTR(err), nop_q->guc->id); - goto put_nop_q; - } - - /* Reload golden LRC to record the effect of any indirect W/A */ - err = emit_nop_job(gt, q); - if (err) { - xe_gt_err(gt, "hwe %s: emit_nop_job failed (%pe) guc_id=%u\n", - hwe->name, ERR_PTR(err), q->guc->id); - goto put_nop_q; - } - - xe_map_memcpy_from(xe, default_lrc, - &q->lrc[0]->bo->vmap, - xe_lrc_pphwsp_offset(q->lrc[0]), - xe_gt_lrc_size(gt, hwe->class)); - - gt->default_lrc[hwe->class] = default_lrc; -put_nop_q: - xe_exec_queue_put(nop_q); -put_exec_queue: - xe_exec_queue_put(q); - if (err) - break; - } - - return err; -} - -int xe_gt_init_early(struct xe_gt *gt) -{ - int err; - - if (IS_SRIOV_PF(gt_to_xe(gt))) { - err = xe_gt_sriov_pf_init_early(gt); - if (err) - return err; - } - - xe_reg_sr_init(>->reg_sr, "GT", gt_to_xe(gt)); - - err = xe_wa_init(gt); - if (err) - return err; - - xe_wa_process_gt(gt); - xe_wa_process_oob(gt); - xe_tuning_process_gt(gt); - - xe_force_wake_init_gt(gt, gt_to_fw(gt)); - xe_pcode_init(gt); - spin_lock_init(>->global_invl_lock); - - return 0; -} - -static void dump_pat_on_error(struct xe_gt *gt) -{ - struct drm_printer p; - char prefix[32]; - - snprintf(prefix, sizeof(prefix), "[GT%u Error]", gt->info.id); - p = drm_dbg_printer(>_to_xe(gt)->drm, DRM_UT_DRIVER, prefix); - - xe_pat_dump(gt, &p); -} - -static int gt_fw_domain_init(struct xe_gt *gt) -{ - int err, i; - - err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (err) - goto err_hw_fence_irq; - - if (!xe_gt_is_media_type(gt)) { - err = xe_ggtt_init(gt_to_tile(gt)->mem.ggtt); - if (err) - goto err_force_wake; - if (IS_SRIOV_PF(gt_to_xe(gt))) - xe_lmtt_init(>_to_tile(gt)->sriov.pf.lmtt); - } - - /* Enable per hw engine IRQs */ - xe_irq_enable_hwe(gt); - - /* Rerun MCR init as we now have hw engine list */ - xe_gt_mcr_init(gt); - - err = xe_hw_engines_init_early(gt); - if (err) - goto err_force_wake; - - err = xe_hw_engine_class_sysfs_init(gt); - if (err) - goto err_force_wake; - - /* Initialize CCS mode sysfs after early initialization of HW engines */ - err = xe_gt_ccs_mode_sysfs_init(gt); - if (err) - goto err_force_wake; - - /* - * Stash hardware-reported version. Since this register does not exist - * on pre-MTL platforms, reading it there will (correctly) return 0. - */ - gt->info.gmdid = xe_mmio_read32(gt, GMD_ID); - - err = xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); - XE_WARN_ON(err); - - return 0; - -err_force_wake: - dump_pat_on_error(gt); - xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); -err_hw_fence_irq: - for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) - xe_hw_fence_irq_finish(>->fence_irq[i]); - - return err; -} - -static int all_fw_domain_init(struct xe_gt *gt) -{ - int err, i; - - err = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - if (err) - goto err_hw_fence_irq; - - xe_gt_mcr_set_implicit_defaults(gt); - xe_reg_sr_apply_mmio(>->reg_sr, gt); - - err = xe_gt_clock_init(gt); - if (err) - goto err_force_wake; - - xe_mocs_init(gt); - err = xe_execlist_init(gt); - if (err) - goto err_force_wake; - - err = xe_hw_engines_init(gt); - if (err) - goto err_force_wake; - - err = xe_uc_init_post_hwconfig(>->uc); - if (err) - goto err_force_wake; - - if (!xe_gt_is_media_type(gt)) { - /* - * USM has its only SA pool to non-block behind user operations - */ - if (gt_to_xe(gt)->info.has_usm) { - struct xe_device *xe = gt_to_xe(gt); - - gt->usm.bb_pool = xe_sa_bo_manager_init(gt_to_tile(gt), - IS_DGFX(xe) ? SZ_1M : SZ_512K, 16); - if (IS_ERR(gt->usm.bb_pool)) { - err = PTR_ERR(gt->usm.bb_pool); - goto err_force_wake; - } - } - } - - if (!xe_gt_is_media_type(gt)) { - struct xe_tile *tile = gt_to_tile(gt); - - tile->migrate = xe_migrate_init(tile); - if (IS_ERR(tile->migrate)) { - err = PTR_ERR(tile->migrate); - goto err_force_wake; - } - } - - err = xe_uc_init_hw(>->uc); - if (err) - goto err_force_wake; - - /* Configure default CCS mode of 1 engine with all resources */ - if (xe_gt_ccs_mode_enabled(gt)) { - gt->ccs_mode = 1; - xe_gt_apply_ccs_mode(gt); - } - - if (IS_SRIOV_PF(gt_to_xe(gt)) && !xe_gt_is_media_type(gt)) - xe_lmtt_init_hw(>_to_tile(gt)->sriov.pf.lmtt); - - if (IS_SRIOV_PF(gt_to_xe(gt))) - xe_gt_sriov_pf_init_hw(gt); - - err = xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL); - XE_WARN_ON(err); - - return 0; - -err_force_wake: - xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL); -err_hw_fence_irq: - for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) - xe_hw_fence_irq_finish(>->fence_irq[i]); - - return err; -} - -/* - * Initialize enough GT to be able to load GuC in order to obtain hwconfig and - * enable CTB communication. - */ -int xe_gt_init_hwconfig(struct xe_gt *gt) -{ - int err; - - err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (err) - goto out; - - xe_gt_mcr_init_early(gt); - xe_pat_init(gt); - - err = xe_uc_init(>->uc); - if (err) - goto out_fw; - - err = xe_uc_init_hwconfig(>->uc); - if (err) - goto out_fw; - - xe_gt_topology_init(gt); - xe_gt_mcr_init(gt); - xe_gt_enable_host_l2_vram(gt); - -out_fw: - xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); -out: - return err; -} - -int xe_gt_init(struct xe_gt *gt) -{ - int err; - int i; - - INIT_WORK(>->reset.worker, gt_reset_worker); - - for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) { - gt->ring_ops[i] = xe_ring_ops_get(gt, i); - xe_hw_fence_irq_init(>->fence_irq[i]); - } - - err = xe_gt_tlb_invalidation_init(gt); - if (err) - return err; - - err = xe_gt_pagefault_init(gt); - if (err) - return err; - - xe_mocs_init_early(gt); - - err = xe_gt_sysfs_init(gt); - if (err) - return err; - - err = gt_fw_domain_init(gt); - if (err) - return err; - - err = xe_gt_idle_init(>->gtidle); - if (err) - return err; - - err = xe_gt_freq_init(gt); - if (err) - return err; - - xe_force_wake_init_engines(gt, gt_to_fw(gt)); - - err = all_fw_domain_init(gt); - if (err) - return err; - - xe_gt_record_user_engines(gt); - - return 0; -} - -void xe_gt_record_user_engines(struct xe_gt *gt) -{ - struct xe_hw_engine *hwe; - enum xe_hw_engine_id id; - - gt->user_engines.mask = 0; - memset(gt->user_engines.instances_per_class, 0, - sizeof(gt->user_engines.instances_per_class)); - - for_each_hw_engine(hwe, gt, id) { - if (xe_hw_engine_is_reserved(hwe)) - continue; - - gt->user_engines.mask |= BIT_ULL(id); - gt->user_engines.instances_per_class[hwe->class]++; - } - - xe_gt_assert(gt, (gt->user_engines.mask | gt->info.engine_mask) - == gt->info.engine_mask); -} - -static int do_gt_reset(struct xe_gt *gt) -{ - int err; - - xe_gsc_wa_14015076503(gt, true); - - xe_mmio_write32(gt, GDRST, GRDOM_FULL); - err = xe_mmio_wait32(gt, GDRST, GRDOM_FULL, 0, 5000, NULL, false); - if (err) - xe_gt_err(gt, "failed to clear GRDOM_FULL (%pe)\n", - ERR_PTR(err)); - - xe_gsc_wa_14015076503(gt, false); - - return err; -} - -static int vf_gt_restart(struct xe_gt *gt) -{ - int err; - - err = xe_uc_sanitize_reset(>->uc); - if (err) - return err; - - err = xe_uc_init_hw(>->uc); - if (err) - return err; - - err = xe_uc_start(>->uc); - if (err) - return err; - - return 0; -} - -static int do_gt_restart(struct xe_gt *gt) -{ - struct xe_hw_engine *hwe; - enum xe_hw_engine_id id; - int err; - - if (IS_SRIOV_VF(gt_to_xe(gt))) - return vf_gt_restart(gt); - - xe_pat_init(gt); - - xe_gt_enable_host_l2_vram(gt); - - xe_gt_mcr_set_implicit_defaults(gt); - xe_reg_sr_apply_mmio(>->reg_sr, gt); - - err = xe_wopcm_init(>->uc.wopcm); - if (err) - return err; - - for_each_hw_engine(hwe, gt, id) - xe_hw_engine_enable_ring(hwe); - - err = xe_uc_sanitize_reset(>->uc); - if (err) - return err; - - err = xe_uc_init_hw(>->uc); - if (err) - return err; - - if (IS_SRIOV_PF(gt_to_xe(gt)) && !xe_gt_is_media_type(gt)) - xe_lmtt_init_hw(>_to_tile(gt)->sriov.pf.lmtt); - - if (IS_SRIOV_PF(gt_to_xe(gt))) - xe_gt_sriov_pf_init_hw(gt); - - xe_mocs_init(gt); - err = xe_uc_start(>->uc); - if (err) - return err; - - for_each_hw_engine(hwe, gt, id) { - xe_reg_sr_apply_mmio(&hwe->reg_sr, gt); - xe_reg_sr_apply_whitelist(hwe); - } - - /* Get CCS mode in sync between sw/hw */ - xe_gt_apply_ccs_mode(gt); - - /* Restore GT freq to expected values */ - xe_gt_sanitize_freq(gt); - - if (IS_SRIOV_PF(gt_to_xe(gt))) - xe_gt_sriov_pf_restart(gt); - - return 0; -} - -static int gt_reset(struct xe_gt *gt) -{ - int err; - - if (xe_device_wedged(gt_to_xe(gt))) - return -ECANCELED; - - /* We only support GT resets with GuC submission */ - if (!xe_device_uc_enabled(gt_to_xe(gt))) - return -ENODEV; - - xe_gt_info(gt, "reset started\n"); - - if (xe_fault_inject_gt_reset()) { - err = -ECANCELED; - goto err_fail; - } - - xe_pm_runtime_get(gt_to_xe(gt)); - xe_gt_sanitize(gt); - - err = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - if (err) - goto err_msg; - - xe_uc_gucrc_disable(>->uc); - xe_uc_stop_prepare(>->uc); - xe_gt_pagefault_reset(gt); - - xe_uc_stop(>->uc); - - xe_gt_tlb_invalidation_reset(gt); - - err = do_gt_reset(gt); - if (err) - goto err_out; - - err = do_gt_restart(gt); - if (err) - goto err_out; - - err = xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL); - XE_WARN_ON(err); - xe_pm_runtime_put(gt_to_xe(gt)); - - xe_gt_info(gt, "reset done\n"); - - return 0; - -err_out: - XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); -err_msg: - XE_WARN_ON(xe_uc_start(>->uc)); - xe_pm_runtime_put(gt_to_xe(gt)); -err_fail: - xe_gt_err(gt, "reset failed (%pe)\n", ERR_PTR(err)); - - xe_device_declare_wedged(gt_to_xe(gt)); - - return err; -} - -static void gt_reset_worker(struct work_struct *w) -{ - struct xe_gt *gt = container_of(w, typeof(*gt), reset.worker); - - gt_reset(gt); -} - -void xe_gt_reset_async(struct xe_gt *gt) -{ - xe_gt_info(gt, "trying reset\n"); - - /* Don't do a reset while one is already in flight */ - if (!xe_fault_inject_gt_reset() && xe_uc_reset_prepare(>->uc)) - return; - - xe_gt_info(gt, "reset queued\n"); - queue_work(gt->ordered_wq, >->reset.worker); -} - -void xe_gt_suspend_prepare(struct xe_gt *gt) -{ - XE_WARN_ON(xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL)); - - xe_uc_stop_prepare(>->uc); - - XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); -} - -int xe_gt_suspend(struct xe_gt *gt) -{ - int err; - - xe_gt_dbg(gt, "suspending\n"); - xe_gt_sanitize(gt); - - err = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - if (err) - goto err_msg; - - err = xe_uc_suspend(>->uc); - if (err) - goto err_force_wake; - - xe_gt_idle_disable_pg(gt); - - xe_gt_disable_host_l2_vram(gt); - - XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); - xe_gt_dbg(gt, "suspended\n"); - - return 0; - -err_force_wake: - XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); -err_msg: - xe_gt_err(gt, "suspend failed (%pe)\n", ERR_PTR(err)); - - return err; -} - -/** - * xe_gt_sanitize_freq() - Restore saved frequencies if necessary. - * @gt: the GT object - * - * Called after driver init/GSC load completes to restore GT frequencies if we - * limited them for any WAs. - */ -int xe_gt_sanitize_freq(struct xe_gt *gt) -{ - int ret = 0; - - if ((!xe_uc_fw_is_available(>->uc.gsc.fw) || - xe_uc_fw_is_loaded(>->uc.gsc.fw)) && XE_WA(gt, 22019338487)) - ret = xe_guc_pc_restore_stashed_freq(>->uc.guc.pc); - - return ret; -} - -int xe_gt_resume(struct xe_gt *gt) -{ - int err; - - xe_gt_dbg(gt, "resuming\n"); - err = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - if (err) - goto err_msg; - - err = do_gt_restart(gt); - if (err) - goto err_force_wake; - - xe_gt_idle_enable_pg(gt); - - XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); - xe_gt_dbg(gt, "resumed\n"); - - return 0; - -err_force_wake: - XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); -err_msg: - xe_gt_err(gt, "resume failed (%pe)\n", ERR_PTR(err)); - - return err; -} - -struct xe_hw_engine *xe_gt_hw_engine(struct xe_gt *gt, - enum xe_engine_class class, - u16 instance, bool logical) -{ - struct xe_hw_engine *hwe; - enum xe_hw_engine_id id; - - for_each_hw_engine(hwe, gt, id) - if (hwe->class == class && - ((!logical && hwe->instance == instance) || - (logical && hwe->logical_instance == instance))) - return hwe; - - return NULL; -} - -struct xe_hw_engine *xe_gt_any_hw_engine_by_reset_domain(struct xe_gt *gt, - enum xe_engine_class class) -{ - struct xe_hw_engine *hwe; - enum xe_hw_engine_id id; - - for_each_hw_engine(hwe, gt, id) { - switch (class) { - case XE_ENGINE_CLASS_RENDER: - case XE_ENGINE_CLASS_COMPUTE: - if (hwe->class == XE_ENGINE_CLASS_RENDER || - hwe->class == XE_ENGINE_CLASS_COMPUTE) - return hwe; - break; - default: - if (hwe->class == class) - return hwe; - } - } - - return NULL; -} - -struct xe_hw_engine *xe_gt_any_hw_engine(struct xe_gt *gt) -{ - struct xe_hw_engine *hwe; - enum xe_hw_engine_id id; - - for_each_hw_engine(hwe, gt, id) - return hwe; - - return NULL; -} - -/** - * xe_gt_declare_wedged() - Declare GT wedged - * @gt: the GT object - * - * Wedge the GT which stops all submission, saves desired debug state, and - * cleans up anything which could timeout. - */ -void xe_gt_declare_wedged(struct xe_gt *gt) -{ - xe_gt_assert(gt, gt_to_xe(gt)->wedged.mode); - - xe_uc_declare_wedged(>->uc); - xe_gt_tlb_invalidation_reset(gt); -} |