162306a36Sopenharmony_ci// SPDX-License-Identifier: MIT 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright © 2019 Intel Corporation 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <drm/drm_managed.h> 762306a36Sopenharmony_ci#include <drm/intel-gtt.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include "gem/i915_gem_internal.h" 1062306a36Sopenharmony_ci#include "gem/i915_gem_lmem.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "i915_drv.h" 1362306a36Sopenharmony_ci#include "i915_perf_oa_regs.h" 1462306a36Sopenharmony_ci#include "i915_reg.h" 1562306a36Sopenharmony_ci#include "intel_context.h" 1662306a36Sopenharmony_ci#include "intel_engine_pm.h" 1762306a36Sopenharmony_ci#include "intel_engine_regs.h" 1862306a36Sopenharmony_ci#include "intel_ggtt_gmch.h" 1962306a36Sopenharmony_ci#include "intel_gt.h" 2062306a36Sopenharmony_ci#include "intel_gt_buffer_pool.h" 2162306a36Sopenharmony_ci#include "intel_gt_clock_utils.h" 2262306a36Sopenharmony_ci#include "intel_gt_debugfs.h" 2362306a36Sopenharmony_ci#include "intel_gt_mcr.h" 2462306a36Sopenharmony_ci#include "intel_gt_pm.h" 2562306a36Sopenharmony_ci#include "intel_gt_print.h" 2662306a36Sopenharmony_ci#include "intel_gt_regs.h" 2762306a36Sopenharmony_ci#include "intel_gt_requests.h" 2862306a36Sopenharmony_ci#include "intel_migrate.h" 2962306a36Sopenharmony_ci#include "intel_mocs.h" 3062306a36Sopenharmony_ci#include "intel_pci_config.h" 3162306a36Sopenharmony_ci#include "intel_rc6.h" 3262306a36Sopenharmony_ci#include "intel_renderstate.h" 3362306a36Sopenharmony_ci#include "intel_rps.h" 3462306a36Sopenharmony_ci#include "intel_sa_media.h" 3562306a36Sopenharmony_ci#include "intel_gt_sysfs.h" 3662306a36Sopenharmony_ci#include "intel_tlb.h" 3762306a36Sopenharmony_ci#include "intel_uncore.h" 3862306a36Sopenharmony_ci#include "shmem_utils.h" 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_civoid intel_gt_common_init_early(struct intel_gt *gt) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci spin_lock_init(gt->irq_lock); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci INIT_LIST_HEAD(>->closed_vma); 4562306a36Sopenharmony_ci spin_lock_init(>->closed_lock); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci init_llist_head(>->watchdog.list); 4862306a36Sopenharmony_ci INIT_WORK(>->watchdog.work, intel_gt_watchdog_work); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci intel_gt_init_buffer_pool(gt); 5162306a36Sopenharmony_ci intel_gt_init_reset(gt); 5262306a36Sopenharmony_ci intel_gt_init_requests(gt); 5362306a36Sopenharmony_ci intel_gt_init_timelines(gt); 5462306a36Sopenharmony_ci intel_gt_init_tlb(gt); 5562306a36Sopenharmony_ci intel_gt_pm_init_early(gt); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci intel_wopcm_init_early(>->wopcm); 5862306a36Sopenharmony_ci intel_uc_init_early(>->uc); 5962306a36Sopenharmony_ci intel_rps_init_early(>->rps); 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci/* Preliminary initialization of Tile 0 */ 6362306a36Sopenharmony_ciint intel_root_gt_init_early(struct drm_i915_private *i915) 6462306a36Sopenharmony_ci{ 6562306a36Sopenharmony_ci struct intel_gt *gt = to_gt(i915); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci gt->i915 = i915; 6862306a36Sopenharmony_ci gt->uncore = &i915->uncore; 6962306a36Sopenharmony_ci gt->irq_lock = drmm_kzalloc(&i915->drm, sizeof(*gt->irq_lock), GFP_KERNEL); 7062306a36Sopenharmony_ci if (!gt->irq_lock) 7162306a36Sopenharmony_ci return -ENOMEM; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci intel_gt_common_init_early(gt); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci return 0; 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic int intel_gt_probe_lmem(struct intel_gt *gt) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci struct drm_i915_private *i915 = gt->i915; 8162306a36Sopenharmony_ci unsigned int instance = gt->info.id; 8262306a36Sopenharmony_ci int id = INTEL_REGION_LMEM_0 + instance; 8362306a36Sopenharmony_ci struct intel_memory_region *mem; 8462306a36Sopenharmony_ci int err; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci mem = intel_gt_setup_lmem(gt); 8762306a36Sopenharmony_ci if (IS_ERR(mem)) { 8862306a36Sopenharmony_ci err = PTR_ERR(mem); 8962306a36Sopenharmony_ci if (err == -ENODEV) 9062306a36Sopenharmony_ci return 0; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci gt_err(gt, "Failed to setup region(%d) type=%d\n", 9362306a36Sopenharmony_ci err, INTEL_MEMORY_LOCAL); 9462306a36Sopenharmony_ci return err; 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci mem->id = id; 9862306a36Sopenharmony_ci mem->instance = instance; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci intel_memory_region_set_name(mem, "local%u", mem->instance); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci GEM_BUG_ON(!HAS_REGION(i915, id)); 10362306a36Sopenharmony_ci GEM_BUG_ON(i915->mm.regions[id]); 10462306a36Sopenharmony_ci i915->mm.regions[id] = mem; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci return 0; 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ciint intel_gt_assign_ggtt(struct intel_gt *gt) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci /* Media GT shares primary GT's GGTT */ 11262306a36Sopenharmony_ci if (gt->type == GT_MEDIA) { 11362306a36Sopenharmony_ci gt->ggtt = to_gt(gt->i915)->ggtt; 11462306a36Sopenharmony_ci } else { 11562306a36Sopenharmony_ci gt->ggtt = i915_ggtt_create(gt->i915); 11662306a36Sopenharmony_ci if (IS_ERR(gt->ggtt)) 11762306a36Sopenharmony_ci return PTR_ERR(gt->ggtt); 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci list_add_tail(>->ggtt_link, >->ggtt->gt_list); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci return 0; 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ciint intel_gt_init_mmio(struct intel_gt *gt) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci intel_gt_init_clock_frequency(gt); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci intel_uc_init_mmio(>->uc); 13062306a36Sopenharmony_ci intel_sseu_info_init(gt); 13162306a36Sopenharmony_ci intel_gt_mcr_init(gt); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci return intel_engines_init_mmio(gt); 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic void init_unused_ring(struct intel_gt *gt, u32 base) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci struct intel_uncore *uncore = gt->uncore; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci intel_uncore_write(uncore, RING_CTL(base), 0); 14162306a36Sopenharmony_ci intel_uncore_write(uncore, RING_HEAD(base), 0); 14262306a36Sopenharmony_ci intel_uncore_write(uncore, RING_TAIL(base), 0); 14362306a36Sopenharmony_ci intel_uncore_write(uncore, RING_START(base), 0); 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic void init_unused_rings(struct intel_gt *gt) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci struct drm_i915_private *i915 = gt->i915; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci if (IS_I830(i915)) { 15162306a36Sopenharmony_ci init_unused_ring(gt, PRB1_BASE); 15262306a36Sopenharmony_ci init_unused_ring(gt, SRB0_BASE); 15362306a36Sopenharmony_ci init_unused_ring(gt, SRB1_BASE); 15462306a36Sopenharmony_ci init_unused_ring(gt, SRB2_BASE); 15562306a36Sopenharmony_ci init_unused_ring(gt, SRB3_BASE); 15662306a36Sopenharmony_ci } else if (GRAPHICS_VER(i915) == 2) { 15762306a36Sopenharmony_ci init_unused_ring(gt, SRB0_BASE); 15862306a36Sopenharmony_ci init_unused_ring(gt, SRB1_BASE); 15962306a36Sopenharmony_ci } else if (GRAPHICS_VER(i915) == 3) { 16062306a36Sopenharmony_ci init_unused_ring(gt, PRB1_BASE); 16162306a36Sopenharmony_ci init_unused_ring(gt, PRB2_BASE); 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ciint intel_gt_init_hw(struct intel_gt *gt) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci struct drm_i915_private *i915 = gt->i915; 16862306a36Sopenharmony_ci struct intel_uncore *uncore = gt->uncore; 16962306a36Sopenharmony_ci int ret; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci gt->last_init_time = ktime_get(); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci /* Double layer security blanket, see i915_gem_init() */ 17462306a36Sopenharmony_ci intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci if (HAS_EDRAM(i915) && GRAPHICS_VER(i915) < 9) 17762306a36Sopenharmony_ci intel_uncore_rmw(uncore, HSW_IDICR, 0, IDIHASHMSK(0xf)); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci if (IS_HASWELL(i915)) 18062306a36Sopenharmony_ci intel_uncore_write(uncore, 18162306a36Sopenharmony_ci HSW_MI_PREDICATE_RESULT_2, 18262306a36Sopenharmony_ci IS_HASWELL_GT3(i915) ? 18362306a36Sopenharmony_ci LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci /* Apply the GT workarounds... */ 18662306a36Sopenharmony_ci intel_gt_apply_workarounds(gt); 18762306a36Sopenharmony_ci /* ...and determine whether they are sticking. */ 18862306a36Sopenharmony_ci intel_gt_verify_workarounds(gt, "init"); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci intel_gt_init_swizzling(gt); 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci /* 19362306a36Sopenharmony_ci * At least 830 can leave some of the unused rings 19462306a36Sopenharmony_ci * "active" (ie. head != tail) after resume which 19562306a36Sopenharmony_ci * will prevent c3 entry. Makes sure all unused rings 19662306a36Sopenharmony_ci * are totally idle. 19762306a36Sopenharmony_ci */ 19862306a36Sopenharmony_ci init_unused_rings(gt); 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci ret = i915_ppgtt_init_hw(gt); 20162306a36Sopenharmony_ci if (ret) { 20262306a36Sopenharmony_ci gt_err(gt, "Enabling PPGTT failed (%d)\n", ret); 20362306a36Sopenharmony_ci goto out; 20462306a36Sopenharmony_ci } 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci /* We can't enable contexts until all firmware is loaded */ 20762306a36Sopenharmony_ci ret = intel_uc_init_hw(>->uc); 20862306a36Sopenharmony_ci if (ret) { 20962306a36Sopenharmony_ci gt_probe_error(gt, "Enabling uc failed (%d)\n", ret); 21062306a36Sopenharmony_ci goto out; 21162306a36Sopenharmony_ci } 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci intel_mocs_init(gt); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ciout: 21662306a36Sopenharmony_ci intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL); 21762306a36Sopenharmony_ci return ret; 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic void gen6_clear_engine_error_register(struct intel_engine_cs *engine) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci GEN6_RING_FAULT_REG_RMW(engine, RING_FAULT_VALID, 0); 22362306a36Sopenharmony_ci GEN6_RING_FAULT_REG_POSTING_READ(engine); 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cii915_reg_t intel_gt_perf_limit_reasons_reg(struct intel_gt *gt) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci /* GT0_PERF_LIMIT_REASONS is available only for Gen11+ */ 22962306a36Sopenharmony_ci if (GRAPHICS_VER(gt->i915) < 11) 23062306a36Sopenharmony_ci return INVALID_MMIO_REG; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci return gt->type == GT_MEDIA ? 23362306a36Sopenharmony_ci MTL_MEDIA_PERF_LIMIT_REASONS : GT0_PERF_LIMIT_REASONS; 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_civoid 23762306a36Sopenharmony_ciintel_gt_clear_error_registers(struct intel_gt *gt, 23862306a36Sopenharmony_ci intel_engine_mask_t engine_mask) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci struct drm_i915_private *i915 = gt->i915; 24162306a36Sopenharmony_ci struct intel_uncore *uncore = gt->uncore; 24262306a36Sopenharmony_ci u32 eir; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci if (GRAPHICS_VER(i915) != 2) 24562306a36Sopenharmony_ci intel_uncore_write(uncore, PGTBL_ER, 0); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci if (GRAPHICS_VER(i915) < 4) 24862306a36Sopenharmony_ci intel_uncore_write(uncore, IPEIR(RENDER_RING_BASE), 0); 24962306a36Sopenharmony_ci else 25062306a36Sopenharmony_ci intel_uncore_write(uncore, IPEIR_I965, 0); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci intel_uncore_write(uncore, EIR, 0); 25362306a36Sopenharmony_ci eir = intel_uncore_read(uncore, EIR); 25462306a36Sopenharmony_ci if (eir) { 25562306a36Sopenharmony_ci /* 25662306a36Sopenharmony_ci * some errors might have become stuck, 25762306a36Sopenharmony_ci * mask them. 25862306a36Sopenharmony_ci */ 25962306a36Sopenharmony_ci gt_dbg(gt, "EIR stuck: 0x%08x, masking\n", eir); 26062306a36Sopenharmony_ci intel_uncore_rmw(uncore, EMR, 0, eir); 26162306a36Sopenharmony_ci intel_uncore_write(uncore, GEN2_IIR, 26262306a36Sopenharmony_ci I915_MASTER_ERROR_INTERRUPT); 26362306a36Sopenharmony_ci } 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) { 26662306a36Sopenharmony_ci intel_gt_mcr_multicast_rmw(gt, XEHP_RING_FAULT_REG, 26762306a36Sopenharmony_ci RING_FAULT_VALID, 0); 26862306a36Sopenharmony_ci intel_gt_mcr_read_any(gt, XEHP_RING_FAULT_REG); 26962306a36Sopenharmony_ci } else if (GRAPHICS_VER(i915) >= 12) { 27062306a36Sopenharmony_ci intel_uncore_rmw(uncore, GEN12_RING_FAULT_REG, RING_FAULT_VALID, 0); 27162306a36Sopenharmony_ci intel_uncore_posting_read(uncore, GEN12_RING_FAULT_REG); 27262306a36Sopenharmony_ci } else if (GRAPHICS_VER(i915) >= 8) { 27362306a36Sopenharmony_ci intel_uncore_rmw(uncore, GEN8_RING_FAULT_REG, RING_FAULT_VALID, 0); 27462306a36Sopenharmony_ci intel_uncore_posting_read(uncore, GEN8_RING_FAULT_REG); 27562306a36Sopenharmony_ci } else if (GRAPHICS_VER(i915) >= 6) { 27662306a36Sopenharmony_ci struct intel_engine_cs *engine; 27762306a36Sopenharmony_ci enum intel_engine_id id; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci for_each_engine_masked(engine, gt, engine_mask, id) 28062306a36Sopenharmony_ci gen6_clear_engine_error_register(engine); 28162306a36Sopenharmony_ci } 28262306a36Sopenharmony_ci} 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_cistatic void gen6_check_faults(struct intel_gt *gt) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci struct intel_engine_cs *engine; 28762306a36Sopenharmony_ci enum intel_engine_id id; 28862306a36Sopenharmony_ci u32 fault; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci for_each_engine(engine, gt, id) { 29162306a36Sopenharmony_ci fault = GEN6_RING_FAULT_REG_READ(engine); 29262306a36Sopenharmony_ci if (fault & RING_FAULT_VALID) { 29362306a36Sopenharmony_ci gt_dbg(gt, "Unexpected fault\n" 29462306a36Sopenharmony_ci "\tAddr: 0x%08lx\n" 29562306a36Sopenharmony_ci "\tAddress space: %s\n" 29662306a36Sopenharmony_ci "\tSource ID: %d\n" 29762306a36Sopenharmony_ci "\tType: %d\n", 29862306a36Sopenharmony_ci fault & PAGE_MASK, 29962306a36Sopenharmony_ci fault & RING_FAULT_GTTSEL_MASK ? 30062306a36Sopenharmony_ci "GGTT" : "PPGTT", 30162306a36Sopenharmony_ci RING_FAULT_SRCID(fault), 30262306a36Sopenharmony_ci RING_FAULT_FAULT_TYPE(fault)); 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistatic void xehp_check_faults(struct intel_gt *gt) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci u32 fault; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci /* 31262306a36Sopenharmony_ci * Although the fault register now lives in an MCR register range, 31362306a36Sopenharmony_ci * the GAM registers are special and we only truly need to read 31462306a36Sopenharmony_ci * the "primary" GAM instance rather than handling each instance 31562306a36Sopenharmony_ci * individually. intel_gt_mcr_read_any() will automatically steer 31662306a36Sopenharmony_ci * toward the primary instance. 31762306a36Sopenharmony_ci */ 31862306a36Sopenharmony_ci fault = intel_gt_mcr_read_any(gt, XEHP_RING_FAULT_REG); 31962306a36Sopenharmony_ci if (fault & RING_FAULT_VALID) { 32062306a36Sopenharmony_ci u32 fault_data0, fault_data1; 32162306a36Sopenharmony_ci u64 fault_addr; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci fault_data0 = intel_gt_mcr_read_any(gt, XEHP_FAULT_TLB_DATA0); 32462306a36Sopenharmony_ci fault_data1 = intel_gt_mcr_read_any(gt, XEHP_FAULT_TLB_DATA1); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci fault_addr = ((u64)(fault_data1 & FAULT_VA_HIGH_BITS) << 44) | 32762306a36Sopenharmony_ci ((u64)fault_data0 << 12); 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci gt_dbg(gt, "Unexpected fault\n" 33062306a36Sopenharmony_ci "\tAddr: 0x%08x_%08x\n" 33162306a36Sopenharmony_ci "\tAddress space: %s\n" 33262306a36Sopenharmony_ci "\tEngine ID: %d\n" 33362306a36Sopenharmony_ci "\tSource ID: %d\n" 33462306a36Sopenharmony_ci "\tType: %d\n", 33562306a36Sopenharmony_ci upper_32_bits(fault_addr), lower_32_bits(fault_addr), 33662306a36Sopenharmony_ci fault_data1 & FAULT_GTT_SEL ? "GGTT" : "PPGTT", 33762306a36Sopenharmony_ci GEN8_RING_FAULT_ENGINE_ID(fault), 33862306a36Sopenharmony_ci RING_FAULT_SRCID(fault), 33962306a36Sopenharmony_ci RING_FAULT_FAULT_TYPE(fault)); 34062306a36Sopenharmony_ci } 34162306a36Sopenharmony_ci} 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_cistatic void gen8_check_faults(struct intel_gt *gt) 34462306a36Sopenharmony_ci{ 34562306a36Sopenharmony_ci struct intel_uncore *uncore = gt->uncore; 34662306a36Sopenharmony_ci i915_reg_t fault_reg, fault_data0_reg, fault_data1_reg; 34762306a36Sopenharmony_ci u32 fault; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci if (GRAPHICS_VER(gt->i915) >= 12) { 35062306a36Sopenharmony_ci fault_reg = GEN12_RING_FAULT_REG; 35162306a36Sopenharmony_ci fault_data0_reg = GEN12_FAULT_TLB_DATA0; 35262306a36Sopenharmony_ci fault_data1_reg = GEN12_FAULT_TLB_DATA1; 35362306a36Sopenharmony_ci } else { 35462306a36Sopenharmony_ci fault_reg = GEN8_RING_FAULT_REG; 35562306a36Sopenharmony_ci fault_data0_reg = GEN8_FAULT_TLB_DATA0; 35662306a36Sopenharmony_ci fault_data1_reg = GEN8_FAULT_TLB_DATA1; 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci fault = intel_uncore_read(uncore, fault_reg); 36062306a36Sopenharmony_ci if (fault & RING_FAULT_VALID) { 36162306a36Sopenharmony_ci u32 fault_data0, fault_data1; 36262306a36Sopenharmony_ci u64 fault_addr; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci fault_data0 = intel_uncore_read(uncore, fault_data0_reg); 36562306a36Sopenharmony_ci fault_data1 = intel_uncore_read(uncore, fault_data1_reg); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci fault_addr = ((u64)(fault_data1 & FAULT_VA_HIGH_BITS) << 44) | 36862306a36Sopenharmony_ci ((u64)fault_data0 << 12); 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci gt_dbg(gt, "Unexpected fault\n" 37162306a36Sopenharmony_ci "\tAddr: 0x%08x_%08x\n" 37262306a36Sopenharmony_ci "\tAddress space: %s\n" 37362306a36Sopenharmony_ci "\tEngine ID: %d\n" 37462306a36Sopenharmony_ci "\tSource ID: %d\n" 37562306a36Sopenharmony_ci "\tType: %d\n", 37662306a36Sopenharmony_ci upper_32_bits(fault_addr), lower_32_bits(fault_addr), 37762306a36Sopenharmony_ci fault_data1 & FAULT_GTT_SEL ? "GGTT" : "PPGTT", 37862306a36Sopenharmony_ci GEN8_RING_FAULT_ENGINE_ID(fault), 37962306a36Sopenharmony_ci RING_FAULT_SRCID(fault), 38062306a36Sopenharmony_ci RING_FAULT_FAULT_TYPE(fault)); 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_civoid intel_gt_check_and_clear_faults(struct intel_gt *gt) 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci struct drm_i915_private *i915 = gt->i915; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci /* From GEN8 onwards we only have one 'All Engine Fault Register' */ 38962306a36Sopenharmony_ci if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) 39062306a36Sopenharmony_ci xehp_check_faults(gt); 39162306a36Sopenharmony_ci else if (GRAPHICS_VER(i915) >= 8) 39262306a36Sopenharmony_ci gen8_check_faults(gt); 39362306a36Sopenharmony_ci else if (GRAPHICS_VER(i915) >= 6) 39462306a36Sopenharmony_ci gen6_check_faults(gt); 39562306a36Sopenharmony_ci else 39662306a36Sopenharmony_ci return; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci intel_gt_clear_error_registers(gt, ALL_ENGINES); 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_civoid intel_gt_flush_ggtt_writes(struct intel_gt *gt) 40262306a36Sopenharmony_ci{ 40362306a36Sopenharmony_ci struct intel_uncore *uncore = gt->uncore; 40462306a36Sopenharmony_ci intel_wakeref_t wakeref; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci /* 40762306a36Sopenharmony_ci * No actual flushing is required for the GTT write domain for reads 40862306a36Sopenharmony_ci * from the GTT domain. Writes to it "immediately" go to main memory 40962306a36Sopenharmony_ci * as far as we know, so there's no chipset flush. It also doesn't 41062306a36Sopenharmony_ci * land in the GPU render cache. 41162306a36Sopenharmony_ci * 41262306a36Sopenharmony_ci * However, we do have to enforce the order so that all writes through 41362306a36Sopenharmony_ci * the GTT land before any writes to the device, such as updates to 41462306a36Sopenharmony_ci * the GATT itself. 41562306a36Sopenharmony_ci * 41662306a36Sopenharmony_ci * We also have to wait a bit for the writes to land from the GTT. 41762306a36Sopenharmony_ci * An uncached read (i.e. mmio) seems to be ideal for the round-trip 41862306a36Sopenharmony_ci * timing. This issue has only been observed when switching quickly 41962306a36Sopenharmony_ci * between GTT writes and CPU reads from inside the kernel on recent hw, 42062306a36Sopenharmony_ci * and it appears to only affect discrete GTT blocks (i.e. on LLC 42162306a36Sopenharmony_ci * system agents we cannot reproduce this behaviour, until Cannonlake 42262306a36Sopenharmony_ci * that was!). 42362306a36Sopenharmony_ci */ 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci wmb(); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci if (INTEL_INFO(gt->i915)->has_coherent_ggtt) 42862306a36Sopenharmony_ci return; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci intel_gt_chipset_flush(gt); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci with_intel_runtime_pm_if_in_use(uncore->rpm, wakeref) { 43362306a36Sopenharmony_ci unsigned long flags; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci spin_lock_irqsave(&uncore->lock, flags); 43662306a36Sopenharmony_ci intel_uncore_posting_read_fw(uncore, 43762306a36Sopenharmony_ci RING_HEAD(RENDER_RING_BASE)); 43862306a36Sopenharmony_ci spin_unlock_irqrestore(&uncore->lock, flags); 43962306a36Sopenharmony_ci } 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_civoid intel_gt_chipset_flush(struct intel_gt *gt) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci wmb(); 44562306a36Sopenharmony_ci if (GRAPHICS_VER(gt->i915) < 6) 44662306a36Sopenharmony_ci intel_ggtt_gmch_flush(); 44762306a36Sopenharmony_ci} 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_civoid intel_gt_driver_register(struct intel_gt *gt) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci intel_gsc_init(>->gsc, gt->i915); 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci intel_rps_driver_register(>->rps); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci intel_gt_debugfs_register(gt); 45662306a36Sopenharmony_ci intel_gt_sysfs_register(gt); 45762306a36Sopenharmony_ci} 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_cistatic int intel_gt_init_scratch(struct intel_gt *gt, unsigned int size) 46062306a36Sopenharmony_ci{ 46162306a36Sopenharmony_ci struct drm_i915_private *i915 = gt->i915; 46262306a36Sopenharmony_ci struct drm_i915_gem_object *obj; 46362306a36Sopenharmony_ci struct i915_vma *vma; 46462306a36Sopenharmony_ci int ret; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci obj = i915_gem_object_create_lmem(i915, size, 46762306a36Sopenharmony_ci I915_BO_ALLOC_VOLATILE | 46862306a36Sopenharmony_ci I915_BO_ALLOC_GPU_ONLY); 46962306a36Sopenharmony_ci if (IS_ERR(obj) && !IS_METEORLAKE(i915)) /* Wa_22018444074 */ 47062306a36Sopenharmony_ci obj = i915_gem_object_create_stolen(i915, size); 47162306a36Sopenharmony_ci if (IS_ERR(obj)) 47262306a36Sopenharmony_ci obj = i915_gem_object_create_internal(i915, size); 47362306a36Sopenharmony_ci if (IS_ERR(obj)) { 47462306a36Sopenharmony_ci gt_err(gt, "Failed to allocate scratch page\n"); 47562306a36Sopenharmony_ci return PTR_ERR(obj); 47662306a36Sopenharmony_ci } 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci vma = i915_vma_instance(obj, >->ggtt->vm, NULL); 47962306a36Sopenharmony_ci if (IS_ERR(vma)) { 48062306a36Sopenharmony_ci ret = PTR_ERR(vma); 48162306a36Sopenharmony_ci goto err_unref; 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci ret = i915_ggtt_pin(vma, NULL, 0, PIN_HIGH); 48562306a36Sopenharmony_ci if (ret) 48662306a36Sopenharmony_ci goto err_unref; 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci gt->scratch = i915_vma_make_unshrinkable(vma); 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci return 0; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_cierr_unref: 49362306a36Sopenharmony_ci i915_gem_object_put(obj); 49462306a36Sopenharmony_ci return ret; 49562306a36Sopenharmony_ci} 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_cistatic void intel_gt_fini_scratch(struct intel_gt *gt) 49862306a36Sopenharmony_ci{ 49962306a36Sopenharmony_ci i915_vma_unpin_and_release(>->scratch, 0); 50062306a36Sopenharmony_ci} 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_cistatic struct i915_address_space *kernel_vm(struct intel_gt *gt) 50362306a36Sopenharmony_ci{ 50462306a36Sopenharmony_ci if (INTEL_PPGTT(gt->i915) > INTEL_PPGTT_ALIASING) 50562306a36Sopenharmony_ci return &i915_ppgtt_create(gt, I915_BO_ALLOC_PM_EARLY)->vm; 50662306a36Sopenharmony_ci else 50762306a36Sopenharmony_ci return i915_vm_get(>->ggtt->vm); 50862306a36Sopenharmony_ci} 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_cistatic int __engines_record_defaults(struct intel_gt *gt) 51162306a36Sopenharmony_ci{ 51262306a36Sopenharmony_ci struct i915_request *requests[I915_NUM_ENGINES] = {}; 51362306a36Sopenharmony_ci struct intel_engine_cs *engine; 51462306a36Sopenharmony_ci enum intel_engine_id id; 51562306a36Sopenharmony_ci int err = 0; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci /* 51862306a36Sopenharmony_ci * As we reset the gpu during very early sanitisation, the current 51962306a36Sopenharmony_ci * register state on the GPU should reflect its defaults values. 52062306a36Sopenharmony_ci * We load a context onto the hw (with restore-inhibit), then switch 52162306a36Sopenharmony_ci * over to a second context to save that default register state. We 52262306a36Sopenharmony_ci * can then prime every new context with that state so they all start 52362306a36Sopenharmony_ci * from the same default HW values. 52462306a36Sopenharmony_ci */ 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci for_each_engine(engine, gt, id) { 52762306a36Sopenharmony_ci struct intel_renderstate so; 52862306a36Sopenharmony_ci struct intel_context *ce; 52962306a36Sopenharmony_ci struct i915_request *rq; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci /* We must be able to switch to something! */ 53262306a36Sopenharmony_ci GEM_BUG_ON(!engine->kernel_context); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci ce = intel_context_create(engine); 53562306a36Sopenharmony_ci if (IS_ERR(ce)) { 53662306a36Sopenharmony_ci err = PTR_ERR(ce); 53762306a36Sopenharmony_ci goto out; 53862306a36Sopenharmony_ci } 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci err = intel_renderstate_init(&so, ce); 54162306a36Sopenharmony_ci if (err) 54262306a36Sopenharmony_ci goto err; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci rq = i915_request_create(ce); 54562306a36Sopenharmony_ci if (IS_ERR(rq)) { 54662306a36Sopenharmony_ci err = PTR_ERR(rq); 54762306a36Sopenharmony_ci goto err_fini; 54862306a36Sopenharmony_ci } 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci err = intel_engine_emit_ctx_wa(rq); 55162306a36Sopenharmony_ci if (err) 55262306a36Sopenharmony_ci goto err_rq; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci err = intel_renderstate_emit(&so, rq); 55562306a36Sopenharmony_ci if (err) 55662306a36Sopenharmony_ci goto err_rq; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_cierr_rq: 55962306a36Sopenharmony_ci requests[id] = i915_request_get(rq); 56062306a36Sopenharmony_ci i915_request_add(rq); 56162306a36Sopenharmony_cierr_fini: 56262306a36Sopenharmony_ci intel_renderstate_fini(&so, ce); 56362306a36Sopenharmony_cierr: 56462306a36Sopenharmony_ci if (err) { 56562306a36Sopenharmony_ci intel_context_put(ce); 56662306a36Sopenharmony_ci goto out; 56762306a36Sopenharmony_ci } 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci /* Flush the default context image to memory, and enable powersaving. */ 57162306a36Sopenharmony_ci if (intel_gt_wait_for_idle(gt, I915_GEM_IDLE_TIMEOUT) == -ETIME) { 57262306a36Sopenharmony_ci err = -EIO; 57362306a36Sopenharmony_ci goto out; 57462306a36Sopenharmony_ci } 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci for (id = 0; id < ARRAY_SIZE(requests); id++) { 57762306a36Sopenharmony_ci struct i915_request *rq; 57862306a36Sopenharmony_ci struct file *state; 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci rq = requests[id]; 58162306a36Sopenharmony_ci if (!rq) 58262306a36Sopenharmony_ci continue; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci if (rq->fence.error) { 58562306a36Sopenharmony_ci err = -EIO; 58662306a36Sopenharmony_ci goto out; 58762306a36Sopenharmony_ci } 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci GEM_BUG_ON(!test_bit(CONTEXT_ALLOC_BIT, &rq->context->flags)); 59062306a36Sopenharmony_ci if (!rq->context->state) 59162306a36Sopenharmony_ci continue; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci /* Keep a copy of the state's backing pages; free the obj */ 59462306a36Sopenharmony_ci state = shmem_create_from_object(rq->context->state->obj); 59562306a36Sopenharmony_ci if (IS_ERR(state)) { 59662306a36Sopenharmony_ci err = PTR_ERR(state); 59762306a36Sopenharmony_ci goto out; 59862306a36Sopenharmony_ci } 59962306a36Sopenharmony_ci rq->engine->default_state = state; 60062306a36Sopenharmony_ci } 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ciout: 60362306a36Sopenharmony_ci /* 60462306a36Sopenharmony_ci * If we have to abandon now, we expect the engines to be idle 60562306a36Sopenharmony_ci * and ready to be torn-down. The quickest way we can accomplish 60662306a36Sopenharmony_ci * this is by declaring ourselves wedged. 60762306a36Sopenharmony_ci */ 60862306a36Sopenharmony_ci if (err) 60962306a36Sopenharmony_ci intel_gt_set_wedged(gt); 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci for (id = 0; id < ARRAY_SIZE(requests); id++) { 61262306a36Sopenharmony_ci struct intel_context *ce; 61362306a36Sopenharmony_ci struct i915_request *rq; 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci rq = requests[id]; 61662306a36Sopenharmony_ci if (!rq) 61762306a36Sopenharmony_ci continue; 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci ce = rq->context; 62062306a36Sopenharmony_ci i915_request_put(rq); 62162306a36Sopenharmony_ci intel_context_put(ce); 62262306a36Sopenharmony_ci } 62362306a36Sopenharmony_ci return err; 62462306a36Sopenharmony_ci} 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_cistatic int __engines_verify_workarounds(struct intel_gt *gt) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci struct intel_engine_cs *engine; 62962306a36Sopenharmony_ci enum intel_engine_id id; 63062306a36Sopenharmony_ci int err = 0; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) 63362306a36Sopenharmony_ci return 0; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci for_each_engine(engine, gt, id) { 63662306a36Sopenharmony_ci if (intel_engine_verify_workarounds(engine, "load")) 63762306a36Sopenharmony_ci err = -EIO; 63862306a36Sopenharmony_ci } 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci /* Flush and restore the kernel context for safety */ 64162306a36Sopenharmony_ci if (intel_gt_wait_for_idle(gt, I915_GEM_IDLE_TIMEOUT) == -ETIME) 64262306a36Sopenharmony_ci err = -EIO; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci return err; 64562306a36Sopenharmony_ci} 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_cistatic void __intel_gt_disable(struct intel_gt *gt) 64862306a36Sopenharmony_ci{ 64962306a36Sopenharmony_ci intel_gt_set_wedged_on_fini(gt); 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci intel_gt_suspend_prepare(gt); 65262306a36Sopenharmony_ci intel_gt_suspend_late(gt); 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci GEM_BUG_ON(intel_gt_pm_is_awake(gt)); 65562306a36Sopenharmony_ci} 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ciint intel_gt_wait_for_idle(struct intel_gt *gt, long timeout) 65862306a36Sopenharmony_ci{ 65962306a36Sopenharmony_ci long remaining_timeout; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci /* If the device is asleep, we have no requests outstanding */ 66262306a36Sopenharmony_ci if (!intel_gt_pm_is_awake(gt)) 66362306a36Sopenharmony_ci return 0; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci while ((timeout = intel_gt_retire_requests_timeout(gt, timeout, 66662306a36Sopenharmony_ci &remaining_timeout)) > 0) { 66762306a36Sopenharmony_ci cond_resched(); 66862306a36Sopenharmony_ci if (signal_pending(current)) 66962306a36Sopenharmony_ci return -EINTR; 67062306a36Sopenharmony_ci } 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci if (timeout) 67362306a36Sopenharmony_ci return timeout; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci if (remaining_timeout < 0) 67662306a36Sopenharmony_ci remaining_timeout = 0; 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci return intel_uc_wait_for_idle(>->uc, remaining_timeout); 67962306a36Sopenharmony_ci} 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ciint intel_gt_init(struct intel_gt *gt) 68262306a36Sopenharmony_ci{ 68362306a36Sopenharmony_ci int err; 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci err = i915_inject_probe_error(gt->i915, -ENODEV); 68662306a36Sopenharmony_ci if (err) 68762306a36Sopenharmony_ci return err; 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci intel_gt_init_workarounds(gt); 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci /* 69262306a36Sopenharmony_ci * This is just a security blanket to placate dragons. 69362306a36Sopenharmony_ci * On some systems, we very sporadically observe that the first TLBs 69462306a36Sopenharmony_ci * used by the CS may be stale, despite us poking the TLB reset. If 69562306a36Sopenharmony_ci * we hold the forcewake during initialisation these problems 69662306a36Sopenharmony_ci * just magically go away. 69762306a36Sopenharmony_ci */ 69862306a36Sopenharmony_ci intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL); 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci err = intel_gt_init_scratch(gt, 70162306a36Sopenharmony_ci GRAPHICS_VER(gt->i915) == 2 ? SZ_256K : SZ_4K); 70262306a36Sopenharmony_ci if (err) 70362306a36Sopenharmony_ci goto out_fw; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci intel_gt_pm_init(gt); 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci gt->vm = kernel_vm(gt); 70862306a36Sopenharmony_ci if (!gt->vm) { 70962306a36Sopenharmony_ci err = -ENOMEM; 71062306a36Sopenharmony_ci goto err_pm; 71162306a36Sopenharmony_ci } 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci intel_set_mocs_index(gt); 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci err = intel_engines_init(gt); 71662306a36Sopenharmony_ci if (err) 71762306a36Sopenharmony_ci goto err_engines; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci err = intel_uc_init(>->uc); 72062306a36Sopenharmony_ci if (err) 72162306a36Sopenharmony_ci goto err_engines; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci err = intel_gt_resume(gt); 72462306a36Sopenharmony_ci if (err) 72562306a36Sopenharmony_ci goto err_uc_init; 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci err = intel_gt_init_hwconfig(gt); 72862306a36Sopenharmony_ci if (err) 72962306a36Sopenharmony_ci gt_err(gt, "Failed to retrieve hwconfig table: %pe\n", ERR_PTR(err)); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci err = __engines_record_defaults(gt); 73262306a36Sopenharmony_ci if (err) 73362306a36Sopenharmony_ci goto err_gt; 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci err = __engines_verify_workarounds(gt); 73662306a36Sopenharmony_ci if (err) 73762306a36Sopenharmony_ci goto err_gt; 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci err = i915_inject_probe_error(gt->i915, -EIO); 74062306a36Sopenharmony_ci if (err) 74162306a36Sopenharmony_ci goto err_gt; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci intel_uc_init_late(>->uc); 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci intel_migrate_init(>->migrate, gt); 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci goto out_fw; 74862306a36Sopenharmony_cierr_gt: 74962306a36Sopenharmony_ci __intel_gt_disable(gt); 75062306a36Sopenharmony_ci intel_uc_fini_hw(>->uc); 75162306a36Sopenharmony_cierr_uc_init: 75262306a36Sopenharmony_ci intel_uc_fini(>->uc); 75362306a36Sopenharmony_cierr_engines: 75462306a36Sopenharmony_ci intel_engines_release(gt); 75562306a36Sopenharmony_ci i915_vm_put(fetch_and_zero(>->vm)); 75662306a36Sopenharmony_cierr_pm: 75762306a36Sopenharmony_ci intel_gt_pm_fini(gt); 75862306a36Sopenharmony_ci intel_gt_fini_scratch(gt); 75962306a36Sopenharmony_ciout_fw: 76062306a36Sopenharmony_ci if (err) 76162306a36Sopenharmony_ci intel_gt_set_wedged_on_init(gt); 76262306a36Sopenharmony_ci intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); 76362306a36Sopenharmony_ci return err; 76462306a36Sopenharmony_ci} 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_civoid intel_gt_driver_remove(struct intel_gt *gt) 76762306a36Sopenharmony_ci{ 76862306a36Sopenharmony_ci __intel_gt_disable(gt); 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci intel_migrate_fini(>->migrate); 77162306a36Sopenharmony_ci intel_uc_driver_remove(>->uc); 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci intel_engines_release(gt); 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci intel_gt_flush_buffer_pool(gt); 77662306a36Sopenharmony_ci} 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_civoid intel_gt_driver_unregister(struct intel_gt *gt) 77962306a36Sopenharmony_ci{ 78062306a36Sopenharmony_ci intel_wakeref_t wakeref; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci intel_gt_sysfs_unregister(gt); 78362306a36Sopenharmony_ci intel_rps_driver_unregister(>->rps); 78462306a36Sopenharmony_ci intel_gsc_fini(>->gsc); 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci /* 78762306a36Sopenharmony_ci * If we unload the driver and wedge before the GSC worker is complete, 78862306a36Sopenharmony_ci * the worker will hit an error on its submission to the GSC engine and 78962306a36Sopenharmony_ci * then exit. This is hard to hit for a user, but it is reproducible 79062306a36Sopenharmony_ci * with skipping selftests. The error is handled gracefully by the 79162306a36Sopenharmony_ci * worker, so there are no functional issues, but we still end up with 79262306a36Sopenharmony_ci * an error message in dmesg, which is something we want to avoid as 79362306a36Sopenharmony_ci * this is a supported scenario. We could modify the worker to better 79462306a36Sopenharmony_ci * handle a wedging occurring during its execution, but that gets 79562306a36Sopenharmony_ci * complicated for a couple of reasons: 79662306a36Sopenharmony_ci * - We do want the error on runtime wedging, because there are 79762306a36Sopenharmony_ci * implications for subsystems outside of GT (i.e., PXP, HDCP), it's 79862306a36Sopenharmony_ci * only the error on driver unload that we want to silence. 79962306a36Sopenharmony_ci * - The worker is responsible for multiple submissions (GSC FW load, 80062306a36Sopenharmony_ci * HuC auth, SW proxy), so all of those will have to be adapted to 80162306a36Sopenharmony_ci * handle the wedged_on_fini scenario. 80262306a36Sopenharmony_ci * Therefore, it's much simpler to just wait for the worker to be done 80362306a36Sopenharmony_ci * before wedging on driver removal, also considering that the worker 80462306a36Sopenharmony_ci * will likely already be idle in the great majority of non-selftest 80562306a36Sopenharmony_ci * scenarios. 80662306a36Sopenharmony_ci */ 80762306a36Sopenharmony_ci intel_gsc_uc_flush_work(>->uc.gsc); 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci /* 81062306a36Sopenharmony_ci * Upon unregistering the device to prevent any new users, cancel 81162306a36Sopenharmony_ci * all in-flight requests so that we can quickly unbind the active 81262306a36Sopenharmony_ci * resources. 81362306a36Sopenharmony_ci */ 81462306a36Sopenharmony_ci intel_gt_set_wedged_on_fini(gt); 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci /* Scrub all HW state upon release */ 81762306a36Sopenharmony_ci with_intel_runtime_pm(gt->uncore->rpm, wakeref) 81862306a36Sopenharmony_ci __intel_gt_reset(gt, ALL_ENGINES); 81962306a36Sopenharmony_ci} 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_civoid intel_gt_driver_release(struct intel_gt *gt) 82262306a36Sopenharmony_ci{ 82362306a36Sopenharmony_ci struct i915_address_space *vm; 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci vm = fetch_and_zero(>->vm); 82662306a36Sopenharmony_ci if (vm) /* FIXME being called twice on error paths :( */ 82762306a36Sopenharmony_ci i915_vm_put(vm); 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci intel_wa_list_free(>->wa_list); 83062306a36Sopenharmony_ci intel_gt_pm_fini(gt); 83162306a36Sopenharmony_ci intel_gt_fini_scratch(gt); 83262306a36Sopenharmony_ci intel_gt_fini_buffer_pool(gt); 83362306a36Sopenharmony_ci intel_gt_fini_hwconfig(gt); 83462306a36Sopenharmony_ci} 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_civoid intel_gt_driver_late_release_all(struct drm_i915_private *i915) 83762306a36Sopenharmony_ci{ 83862306a36Sopenharmony_ci struct intel_gt *gt; 83962306a36Sopenharmony_ci unsigned int id; 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci /* We need to wait for inflight RCU frees to release their grip */ 84262306a36Sopenharmony_ci rcu_barrier(); 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci for_each_gt(gt, i915, id) { 84562306a36Sopenharmony_ci intel_uc_driver_late_release(>->uc); 84662306a36Sopenharmony_ci intel_gt_fini_requests(gt); 84762306a36Sopenharmony_ci intel_gt_fini_reset(gt); 84862306a36Sopenharmony_ci intel_gt_fini_timelines(gt); 84962306a36Sopenharmony_ci intel_gt_fini_tlb(gt); 85062306a36Sopenharmony_ci intel_engines_free(gt); 85162306a36Sopenharmony_ci } 85262306a36Sopenharmony_ci} 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_cistatic int intel_gt_tile_setup(struct intel_gt *gt, phys_addr_t phys_addr) 85562306a36Sopenharmony_ci{ 85662306a36Sopenharmony_ci int ret; 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci if (!gt_is_root(gt)) { 85962306a36Sopenharmony_ci struct intel_uncore *uncore; 86062306a36Sopenharmony_ci spinlock_t *irq_lock; 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci uncore = drmm_kzalloc(>->i915->drm, sizeof(*uncore), GFP_KERNEL); 86362306a36Sopenharmony_ci if (!uncore) 86462306a36Sopenharmony_ci return -ENOMEM; 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci irq_lock = drmm_kzalloc(>->i915->drm, sizeof(*irq_lock), GFP_KERNEL); 86762306a36Sopenharmony_ci if (!irq_lock) 86862306a36Sopenharmony_ci return -ENOMEM; 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci gt->uncore = uncore; 87162306a36Sopenharmony_ci gt->irq_lock = irq_lock; 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci intel_gt_common_init_early(gt); 87462306a36Sopenharmony_ci } 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci intel_uncore_init_early(gt->uncore, gt); 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci ret = intel_uncore_setup_mmio(gt->uncore, phys_addr); 87962306a36Sopenharmony_ci if (ret) 88062306a36Sopenharmony_ci return ret; 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci gt->phys_addr = phys_addr; 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci return 0; 88562306a36Sopenharmony_ci} 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ciint intel_gt_probe_all(struct drm_i915_private *i915) 88862306a36Sopenharmony_ci{ 88962306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(i915->drm.dev); 89062306a36Sopenharmony_ci struct intel_gt *gt = to_gt(i915); 89162306a36Sopenharmony_ci const struct intel_gt_definition *gtdef; 89262306a36Sopenharmony_ci phys_addr_t phys_addr; 89362306a36Sopenharmony_ci unsigned int mmio_bar; 89462306a36Sopenharmony_ci unsigned int i; 89562306a36Sopenharmony_ci int ret; 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci mmio_bar = intel_mmio_bar(GRAPHICS_VER(i915)); 89862306a36Sopenharmony_ci phys_addr = pci_resource_start(pdev, mmio_bar); 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci /* 90162306a36Sopenharmony_ci * We always have at least one primary GT on any device 90262306a36Sopenharmony_ci * and it has been already initialized early during probe 90362306a36Sopenharmony_ci * in i915_driver_probe() 90462306a36Sopenharmony_ci */ 90562306a36Sopenharmony_ci gt->i915 = i915; 90662306a36Sopenharmony_ci gt->name = "Primary GT"; 90762306a36Sopenharmony_ci gt->info.engine_mask = INTEL_INFO(i915)->platform_engine_mask; 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci gt_dbg(gt, "Setting up %s\n", gt->name); 91062306a36Sopenharmony_ci ret = intel_gt_tile_setup(gt, phys_addr); 91162306a36Sopenharmony_ci if (ret) 91262306a36Sopenharmony_ci return ret; 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci i915->gt[0] = gt; 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci if (!HAS_EXTRA_GT_LIST(i915)) 91762306a36Sopenharmony_ci return 0; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci for (i = 1, gtdef = &INTEL_INFO(i915)->extra_gt_list[i - 1]; 92062306a36Sopenharmony_ci gtdef->name != NULL; 92162306a36Sopenharmony_ci i++, gtdef = &INTEL_INFO(i915)->extra_gt_list[i - 1]) { 92262306a36Sopenharmony_ci gt = drmm_kzalloc(&i915->drm, sizeof(*gt), GFP_KERNEL); 92362306a36Sopenharmony_ci if (!gt) { 92462306a36Sopenharmony_ci ret = -ENOMEM; 92562306a36Sopenharmony_ci goto err; 92662306a36Sopenharmony_ci } 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci gt->i915 = i915; 92962306a36Sopenharmony_ci gt->name = gtdef->name; 93062306a36Sopenharmony_ci gt->type = gtdef->type; 93162306a36Sopenharmony_ci gt->info.engine_mask = gtdef->engine_mask; 93262306a36Sopenharmony_ci gt->info.id = i; 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci gt_dbg(gt, "Setting up %s\n", gt->name); 93562306a36Sopenharmony_ci if (GEM_WARN_ON(range_overflows_t(resource_size_t, 93662306a36Sopenharmony_ci gtdef->mapping_base, 93762306a36Sopenharmony_ci SZ_16M, 93862306a36Sopenharmony_ci pci_resource_len(pdev, mmio_bar)))) { 93962306a36Sopenharmony_ci ret = -ENODEV; 94062306a36Sopenharmony_ci goto err; 94162306a36Sopenharmony_ci } 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci switch (gtdef->type) { 94462306a36Sopenharmony_ci case GT_TILE: 94562306a36Sopenharmony_ci ret = intel_gt_tile_setup(gt, phys_addr + gtdef->mapping_base); 94662306a36Sopenharmony_ci break; 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci case GT_MEDIA: 94962306a36Sopenharmony_ci ret = intel_sa_mediagt_setup(gt, phys_addr + gtdef->mapping_base, 95062306a36Sopenharmony_ci gtdef->gsi_offset); 95162306a36Sopenharmony_ci break; 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci case GT_PRIMARY: 95462306a36Sopenharmony_ci /* Primary GT should not appear in extra GT list */ 95562306a36Sopenharmony_ci default: 95662306a36Sopenharmony_ci MISSING_CASE(gtdef->type); 95762306a36Sopenharmony_ci ret = -ENODEV; 95862306a36Sopenharmony_ci } 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci if (ret) 96162306a36Sopenharmony_ci goto err; 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci i915->gt[i] = gt; 96462306a36Sopenharmony_ci } 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci return 0; 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_cierr: 96962306a36Sopenharmony_ci i915_probe_error(i915, "Failed to initialize %s! (%d)\n", gtdef->name, ret); 97062306a36Sopenharmony_ci return ret; 97162306a36Sopenharmony_ci} 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ciint intel_gt_tiles_init(struct drm_i915_private *i915) 97462306a36Sopenharmony_ci{ 97562306a36Sopenharmony_ci struct intel_gt *gt; 97662306a36Sopenharmony_ci unsigned int id; 97762306a36Sopenharmony_ci int ret; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci for_each_gt(gt, i915, id) { 98062306a36Sopenharmony_ci ret = intel_gt_probe_lmem(gt); 98162306a36Sopenharmony_ci if (ret) 98262306a36Sopenharmony_ci return ret; 98362306a36Sopenharmony_ci } 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci return 0; 98662306a36Sopenharmony_ci} 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_civoid intel_gt_info_print(const struct intel_gt_info *info, 98962306a36Sopenharmony_ci struct drm_printer *p) 99062306a36Sopenharmony_ci{ 99162306a36Sopenharmony_ci drm_printf(p, "available engines: %x\n", info->engine_mask); 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci intel_sseu_dump(&info->sseu, p); 99462306a36Sopenharmony_ci} 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_cienum i915_map_type intel_gt_coherent_map_type(struct intel_gt *gt, 99762306a36Sopenharmony_ci struct drm_i915_gem_object *obj, 99862306a36Sopenharmony_ci bool always_coherent) 99962306a36Sopenharmony_ci{ 100062306a36Sopenharmony_ci /* 100162306a36Sopenharmony_ci * Wa_22016122933: always return I915_MAP_WC for Media 100262306a36Sopenharmony_ci * version 13.0 when the object is on the Media GT 100362306a36Sopenharmony_ci */ 100462306a36Sopenharmony_ci if (i915_gem_object_is_lmem(obj) || intel_gt_needs_wa_22016122933(gt)) 100562306a36Sopenharmony_ci return I915_MAP_WC; 100662306a36Sopenharmony_ci if (HAS_LLC(gt->i915) || always_coherent) 100762306a36Sopenharmony_ci return I915_MAP_WB; 100862306a36Sopenharmony_ci else 100962306a36Sopenharmony_ci return I915_MAP_WC; 101062306a36Sopenharmony_ci} 1011