UAPI Changes: - Add GuC submission interface version query (Tvrtko Ursulin) Driver Changes: Fixes/improvements/new stuff: - Atomically invalidate userptr on mmu-notifier (Jonathan Cavitt) - Update handling of MMIO triggered reports (Umesh Nerlige Ramappa) - Don't make assumptions about intel_wakeref_t type (Jani Nikula) - Add workaround 14019877138 [xelpg] (Tejas Upadhyay) - Allow for very slow HuC loading [huc] (John Harrison) - Flush context destruction worker at suspend [guc] (Alan Previn) - Close deregister-context race against CT-loss [guc] (Alan Previn) - Avoid circular locking issue on busyness flush [guc] (John Harrison) - Use rc6.supported flag from intel_gt for rc6_enable sysfs (Juan Escamilla) - Reflect the true and current status of rc6_enable (Juan Escamilla) - Wake GT before sending H2G message [mtl] (Vinay Belgaumkar) - Restart the heartbeat timer when forcing a pulse (John Harrison) Future platform enablement: - Extend driver code of Xe_LPG to Xe_LPG+ [xelpg] (Harish Chegondi) - Extend some workarounds/tuning to gfx version 12.74 [xelpg] (Matt Roper) Miscellaneous: - Reconcile Excess struct member kernel-doc warnings (Randy Dunlap) - Change wa and EU_PERF_CNTL registers to MCR type [guc] (Shuicheng Lin) - Add flex arrays to struct i915_syncmap (Erick Archer) - Increasing the sleep time for live_rc6_manual [selftests] (Anirban Sk)
Unified · Split
| @@ -2160,12 +2160,6 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb) · 2159 unmodified lines | |||
| 2160 | 2160 | ||
| 2161 | #ifdef CONFIG_MMU_NOTIFIER | 2161 | #ifdef CONFIG_MMU_NOTIFIER |
| 2162 | if (!err && (eb->args->flags & __EXEC_USERPTR_USED)) { | 2162 | if (!err && (eb->args->flags & __EXEC_USERPTR_USED)) { |
| 2163 | read_lock(&eb->i915->mm.notifier_lock); | ||
| 2164 | |||
| 2165 | /* | ||
| 2166 | * count is always at least 1, otherwise __EXEC_USERPTR_USED | ||
| 2167 | * could not have been set | ||
| 2168 | */ | ||
| 2169 | for (i = 0; i < count; i++) { | 2163 | for (i = 0; i < count; i++) { |
| 2170 | struct eb_vma *ev = &eb->vma[i]; | 2164 | struct eb_vma *ev = &eb->vma[i]; |
| 2171 | struct drm_i915_gem_object *obj = ev->vma->obj; | 2165 | struct drm_i915_gem_object *obj = ev->vma->obj; |
| @@ -2177,8 +2171,6 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb) · 5 unmodified lines | |||
| 2177 | if (err) | 2171 | if (err) |
| 2178 | break; | 2172 | break; |
| 2179 | } | 2173 | } |
| 2180 | |||
| 2181 | read_unlock(&eb->i915->mm.notifier_lock); | ||
| 2182 | } | 2174 | } |
| 2183 | #endif | 2175 | #endif |
| 2184 | 2176 | ||
| @@ -28,6 +28,13 @@ void i915_gem_suspend(struct drm_i915_private *i915) · 27 unmodified lines | |||
| 28 | GEM_TRACE("%s\n", dev_name(i915->drm.dev)); | 28 | GEM_TRACE("%s\n", dev_name(i915->drm.dev)); |
| 29 | 29 | ||
| 30 | intel_wakeref_auto(&i915->runtime_pm.userfault_wakeref, 0); | 30 | intel_wakeref_auto(&i915->runtime_pm.userfault_wakeref, 0); |
| 31 | /* | ||
| 32 | * On rare occasions, we've observed the fence completion triggers | ||
| 33 | * free_engines asynchronously via rcu_call. Ensure those are done. | ||
| 34 | * This path is only called on suspend, so it's an acceptable cost. | ||
| 35 | */ | ||
| 36 | rcu_barrier(); | ||
| 37 | |||
| 31 | flush_workqueue(i915->wq); | 38 | flush_workqueue(i915->wq); |
| 32 | 39 | ||
| 33 | /* | 40 | /* |
| @@ -160,6 +167,9 @@ void i915_gem_suspend_late(struct drm_i915_private *i915) · 126 unmodified lines | |||
| 160 | * machine in an unusable condition. | 167 | * machine in an unusable condition. |
| 161 | */ | 168 | */ |
| 162 | 169 | ||
| 170 | /* Like i915_gem_suspend, flush tasks staged from fence triggers */ | ||
| 171 | rcu_barrier(); | ||
| 172 | |||
| 163 | for_each_gt(gt, i915, i) | 173 | for_each_gt(gt, i915, i) |
| 164 | intel_gt_suspend_late(gt); | 174 | intel_gt_suspend_late(gt); |
| 165 | 175 | ||
| @@ -42,7 +42,6 @@ · 41 unmodified lines | |||
| 42 | #include "i915_drv.h" | 42 | #include "i915_drv.h" |
| 43 | #include "i915_gem_ioctls.h" | 43 | #include "i915_gem_ioctls.h" |
| 44 | #include "i915_gem_object.h" | 44 | #include "i915_gem_object.h" |
| 45 | #include "i915_gem_userptr.h" | ||
| 46 | #include "i915_scatterlist.h" | 45 | #include "i915_scatterlist.h" |
| 47 | 46 | ||
| 48 | #ifdef CONFIG_MMU_NOTIFIER | 47 | #ifdef CONFIG_MMU_NOTIFIER |
| @@ -61,36 +60,7 @@ static bool i915_gem_userptr_invalidate(struct mmu_interval_notifier *mni, · 12 unmodified lines | |||
| 61 | const struct mmu_notifier_range *range, | 60 | const struct mmu_notifier_range *range, |
| 62 | unsigned long cur_seq) | 61 | unsigned long cur_seq) |
| 63 | { | 62 | { |
| 64 | struct drm_i915_gem_object *obj = container_of(mni, struct drm_i915_gem_object, userptr.notifier); | ||
| 65 | struct drm_i915_private *i915 = to_i915(obj->base.dev); | ||
| 66 | long r; | ||
| 67 | |||
| 68 | if (!mmu_notifier_range_blockable(range)) | ||
| 69 | return false; | ||
| 70 | |||
| 71 | write_lock(&i915->mm.notifier_lock); | ||
| 72 | |||
| 73 | mmu_interval_set_seq(mni, cur_seq); | 63 | mmu_interval_set_seq(mni, cur_seq); |
| 74 | |||
| 75 | write_unlock(&i915->mm.notifier_lock); | ||
| 76 | |||
| 77 | /* | ||
| 78 | * We don't wait when the process is exiting. This is valid | ||
| 79 | * because the object will be cleaned up anyway. | ||
| 80 | * | ||
| 81 | * This is also temporarily required as a hack, because we | ||
| 82 | * cannot currently force non-consistent batch buffers to preempt | ||
| 83 | * and reschedule by waiting on it, hanging processes on exit. | ||
| 84 | */ | ||
| 85 | if (current->flags & PF_EXITING) | ||
| 86 | return true; | ||
| 87 | |||
| 88 | /* we will unbind on next submission, still have userptr pins */ | ||
| 89 | r = dma_resv_wait_timeout(obj->base.resv, DMA_RESV_USAGE_BOOKKEEP, false, | ||
| 90 | MAX_SCHEDULE_TIMEOUT); | ||
| 91 | if (r <= 0) | ||
| 92 | drm_err(&i915->drm, "(%ld) failed to wait for idle\n", r); | ||
| 93 | |||
| 94 | return true; | 64 | return true; |
| 95 | } | 65 | } |
| 96 | 66 | ||
| @@ -580,15 +550,3 @@ i915_gem_userptr_ioctl(struct drm_device *dev, · 483 unmodified lines | |||
| 580 | #endif | 550 | #endif |
| 581 | } | 551 | } |
| 582 | 552 | ||
| 583 | int i915_gem_init_userptr(struct drm_i915_private *dev_priv) | ||
| 584 | { | ||
| 585 | #ifdef CONFIG_MMU_NOTIFIER | ||
| 586 | rwlock_init(&dev_priv->mm.notifier_lock); | ||
| 587 | #endif | ||
| 588 | |||
| 589 | return 0; | ||
| 590 | } | ||
| 591 | |||
| 592 | void i915_gem_cleanup_userptr(struct drm_i915_private *dev_priv) | ||
| 593 | { | ||
| 594 | } | ||
| @@ -1,14 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: MIT */ | ||
| 2 | /* | ||
| 3 | * Copyright © 2021 Intel Corporation | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef __I915_GEM_USERPTR_H__ | ||
| 7 | #define __I915_GEM_USERPTR_H__ | ||
| 8 | |||
| 9 | struct drm_i915_private; | ||
| 10 | |||
| 11 | int i915_gem_init_userptr(struct drm_i915_private *dev_priv); | ||
| 12 | void i915_gem_cleanup_userptr(struct drm_i915_private *dev_priv); | ||
| 13 | |||
| 14 | #endif /* __I915_GEM_USERPTR_H__ */ | ||
| @@ -226,7 +226,7 @@ u32 *gen12_emit_aux_table_inv(struct intel_engine_cs *engine, u32 *cs) · 225 unmodified lines | |||
| 226 | static int mtl_dummy_pipe_control(struct i915_request *rq) | 226 | static int mtl_dummy_pipe_control(struct i915_request *rq) |
| 227 | { | 227 | { |
| 228 | /* Wa_14016712196 */ | 228 | /* Wa_14016712196 */ |
| 229 | if (IS_GFX_GT_IP_RANGE(rq->engine->gt, IP_VER(12, 70), IP_VER(12, 71)) || | 229 | if (IS_GFX_GT_IP_RANGE(rq->engine->gt, IP_VER(12, 70), IP_VER(12, 74)) || |
| 230 | IS_DG2(rq->i915)) { | 230 | IS_DG2(rq->i915)) { |
| 231 | u32 *cs; | 231 | u32 *cs; |
| 232 | 232 | ||
| @@ -822,7 +822,7 @@ u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs) · 589 unmodified lines | |||
| 822 | flags |= PIPE_CONTROL_FLUSH_L3; | 822 | flags |= PIPE_CONTROL_FLUSH_L3; |
| 823 | 823 | ||
| 824 | /* Wa_14016712196 */ | 824 | /* Wa_14016712196 */ |
| 825 | if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71)) || IS_DG2(i915)) | 825 | if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74)) || IS_DG2(i915)) |
| 826 | /* dummy PIPE_CONTROL + depth flush */ | 826 | /* dummy PIPE_CONTROL + depth flush */ |
| 827 | cs = gen12_emit_pipe_control(cs, 0, | 827 | cs = gen12_emit_pipe_control(cs, 0, |
| 828 | PIPE_CONTROL_DEPTH_CACHE_FLUSH, 0); | 828 | PIPE_CONTROL_DEPTH_CACHE_FLUSH, 0); |
| @@ -1190,7 +1190,8 @@ static int intel_engine_init_tlb_invalidation(struct intel_engine_cs *engine) · 1189 unmodified lines | |||
| 1190 | num = ARRAY_SIZE(xelpmp_regs); | 1190 | num = ARRAY_SIZE(xelpmp_regs); |
| 1191 | } | 1191 | } |
| 1192 | } else { | 1192 | } else { |
| 1193 | if (GRAPHICS_VER_FULL(i915) == IP_VER(12, 71) || | 1193 | if (GRAPHICS_VER_FULL(i915) == IP_VER(12, 74) || |
| 1194 | GRAPHICS_VER_FULL(i915) == IP_VER(12, 71) || | ||
| 1194 | GRAPHICS_VER_FULL(i915) == IP_VER(12, 70) || | 1195 | GRAPHICS_VER_FULL(i915) == IP_VER(12, 70) || |
| 1195 | GRAPHICS_VER_FULL(i915) == IP_VER(12, 50) || | 1196 | GRAPHICS_VER_FULL(i915) == IP_VER(12, 50) || |
| 1196 | GRAPHICS_VER_FULL(i915) == IP_VER(12, 55)) { | 1197 | GRAPHICS_VER_FULL(i915) == IP_VER(12, 55)) { |
| @@ -290,6 +290,9 @@ static int __intel_engine_pulse(struct intel_engine_cs *engine) · 289 unmodified lines | |||
| 290 | heartbeat_commit(rq, &attr); | 290 | heartbeat_commit(rq, &attr); |
| 291 | GEM_BUG_ON(rq->sched.attr.priority < I915_PRIORITY_BARRIER); | 291 | GEM_BUG_ON(rq->sched.attr.priority < I915_PRIORITY_BARRIER); |
| 292 | 292 | ||
| 293 | /* Ensure the forced pulse gets a full period to execute */ | ||
| 294 | next_heartbeat(engine); | ||
| 295 | |||
| 293 | return 0; | 296 | return 0; |
| 294 | } | 297 | } |
| 295 | 298 | ||
| @@ -176,27 +176,13 @@ static u32 get_residency(struct intel_gt *gt, enum intel_rc6_res_type id) · 175 unmodified lines | |||
| 176 | return DIV_ROUND_CLOSEST_ULL(res, 1000); | 176 | return DIV_ROUND_CLOSEST_ULL(res, 1000); |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | static u8 get_rc6_mask(struct intel_gt *gt) | ||
| 180 | { | ||
| 181 | u8 mask = 0; | ||
| 182 | |||
| 183 | if (HAS_RC6(gt->i915)) | ||
| 184 | mask |= BIT(0); | ||
| 185 | if (HAS_RC6p(gt->i915)) | ||
| 186 | mask |= BIT(1); | ||
| 187 | if (HAS_RC6pp(gt->i915)) | ||
| 188 | mask |= BIT(2); | ||
| 189 | |||
| 190 | return mask; | ||
| 191 | } | ||
| 192 | |||
| 193 | static ssize_t rc6_enable_show(struct kobject *kobj, | 179 | static ssize_t rc6_enable_show(struct kobject *kobj, |
| 194 | struct kobj_attribute *attr, | 180 | struct kobj_attribute *attr, |
| 195 | char *buff) | 181 | char *buff) |
| 196 | { | 182 | { |
| 197 | struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name); | 183 | struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name); |
| 198 | 184 | ||
| 199 | return sysfs_emit(buff, "%x\n", get_rc6_mask(gt)); | 185 | return sysfs_emit(buff, "%x\n", gt->rc6.enabled); |
| 200 | } | 186 | } |
| 201 | 187 | ||
| 202 | static ssize_t rc6_enable_dev_show(struct device *dev, | 188 | static ssize_t rc6_enable_dev_show(struct device *dev, |
| @@ -205,7 +191,7 @@ static ssize_t rc6_enable_dev_show(struct device *dev, · 2 unmodified lines | |||
| 205 | { | 191 | { |
| 206 | struct intel_gt *gt = intel_gt_sysfs_get_drvdata(&dev->kobj, attr->attr.name); | 192 | struct intel_gt *gt = intel_gt_sysfs_get_drvdata(&dev->kobj, attr->attr.name); |
| 207 | 193 | ||
| 208 | return sysfs_emit(buff, "%x\n", get_rc6_mask(gt)); | 194 | return sysfs_emit(buff, "%x\n", gt->rc6.enabled); |
| 209 | } | 195 | } |
| 210 | 196 | ||
| 211 | static u32 __rc6_residency_ms_show(struct intel_gt *gt) | 197 | static u32 __rc6_residency_ms_show(struct intel_gt *gt) |
| @@ -495,7 +495,7 @@ static unsigned int get_mocs_settings(struct drm_i915_private *i915, · 494 unmodified lines | |||
| 495 | memset(table, 0, sizeof(struct drm_i915_mocs_table)); | 495 | memset(table, 0, sizeof(struct drm_i915_mocs_table)); |
| 496 | 496 | ||
| 497 | table->unused_entries_index = I915_MOCS_PTE; | 497 | table->unused_entries_index = I915_MOCS_PTE; |
| 498 | if (IS_GFX_GT_IP_RANGE(to_gt(i915), IP_VER(12, 70), IP_VER(12, 71))) { | 498 | if (IS_GFX_GT_IP_RANGE(to_gt(i915), IP_VER(12, 70), IP_VER(12, 74))) { |
| 499 | table->size = ARRAY_SIZE(mtl_mocs_table); | 499 | table->size = ARRAY_SIZE(mtl_mocs_table); |
| 500 | table->table = mtl_mocs_table; | 500 | table->table = mtl_mocs_table; |
| 501 | table->n_entries = MTL_NUM_MOCS_ENTRIES; | 501 | table->n_entries = MTL_NUM_MOCS_ENTRIES; |
| @@ -123,7 +123,7 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6) · 122 unmodified lines | |||
| 123 | * temporary wa and should be removed after fixing real cause | 123 | * temporary wa and should be removed after fixing real cause |
| 124 | * of forcewake timeouts. | 124 | * of forcewake timeouts. |
| 125 | */ | 125 | */ |
| 126 | if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) | 126 | if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74))) |
| 127 | pg_enable = | 127 | pg_enable = |
| 128 | GEN9_MEDIA_PG_ENABLE | | 128 | GEN9_MEDIA_PG_ENABLE | |
| 129 | GEN11_MEDIA_SAMPLER_PG_ENABLE; | 129 | GEN11_MEDIA_SAMPLER_PG_ENABLE; |
| @@ -789,8 +789,13 @@ static void xelpg_ctx_gt_tuning_init(struct intel_engine_cs *engine, · 788 unmodified lines | |||
| 789 | 789 | ||
| 790 | dg2_ctx_gt_tuning_init(engine, wal); | 790 | dg2_ctx_gt_tuning_init(engine, wal); |
| 791 | 791 | ||
| 792 | if (IS_GFX_GT_IP_STEP(gt, IP_VER(12, 70), STEP_B0, STEP_FOREVER) || | 792 | /* |
| 793 | IS_GFX_GT_IP_STEP(gt, IP_VER(12, 71), STEP_B0, STEP_FOREVER)) | 793 | * Due to Wa_16014892111, the DRAW_WATERMARK tuning must be done in |
| 794 | * gen12_emit_indirect_ctx_rcs() rather than here on some early | ||
| 795 | * steppings. | ||
| 796 | */ | ||
| 797 | if (!(IS_GFX_GT_IP_STEP(gt, IP_VER(12, 70), STEP_A0, STEP_B0) || | ||
| 798 | IS_GFX_GT_IP_STEP(gt, IP_VER(12, 71), STEP_A0, STEP_B0))) | ||
| 794 | wa_add(wal, DRAW_WATERMARK, VERT_WM_VAL, 0x3FF, 0, false); | 799 | wa_add(wal, DRAW_WATERMARK, VERT_WM_VAL, 0x3FF, 0, false); |
| 795 | } | 800 | } |
| 796 | 801 | ||
| @@ -820,6 +825,9 @@ static void xelpg_ctx_workarounds_init(struct intel_engine_cs *engine, · 23 unmodified lines | |||
| 820 | 825 | ||
| 821 | /* Wa_18019271663 */ | 826 | /* Wa_18019271663 */ |
| 822 | wa_masked_en(wal, CACHE_MODE_1, MSAA_OPTIMIZATION_REDUC_DISABLE); | 827 | wa_masked_en(wal, CACHE_MODE_1, MSAA_OPTIMIZATION_REDUC_DISABLE); |
| 828 | |||
| 829 | /* Wa_14019877138 */ | ||
| 830 | wa_mcr_masked_en(wal, XEHP_PSS_CHICKEN, FD_END_COLLECT); | ||
| 823 | } | 831 | } |
| 824 | 832 | ||
| 825 | static void fakewa_disable_nestedbb_mode(struct intel_engine_cs *engine, | 833 | static void fakewa_disable_nestedbb_mode(struct intel_engine_cs *engine, |
| @@ -908,7 +916,7 @@ __intel_engine_init_ctx_wa(struct intel_engine_cs *engine, · 82 unmodified lines | |||
| 908 | if (engine->class != RENDER_CLASS) | 916 | if (engine->class != RENDER_CLASS) |
| 909 | goto done; | 917 | goto done; |
| 910 | 918 | ||
| 911 | if (IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 70), IP_VER(12, 71))) | 919 | if (IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 70), IP_VER(12, 74))) |
| 912 | xelpg_ctx_workarounds_init(engine, wal); | 920 | xelpg_ctx_workarounds_init(engine, wal); |
| 913 | else if (IS_PONTEVECCHIO(i915)) | 921 | else if (IS_PONTEVECCHIO(i915)) |
| 914 | ; /* noop; none at this time */ | 922 | ; /* noop; none at this time */ |
| @@ -1643,7 +1651,7 @@ pvc_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) · 728 unmodified lines | |||
| 1643 | static void | 1651 | static void |
| 1644 | xelpg_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) | 1652 | xelpg_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) |
| 1645 | { | 1653 | { |
| 1646 | /* Wa_14018778641 / Wa_18018781329 */ | 1654 | /* Wa_14018575942 / Wa_18018781329 */ |
| 1647 | wa_mcr_write_or(wal, COMP_MOD_CTRL, FORCE_MISS_FTLB); | 1655 | wa_mcr_write_or(wal, COMP_MOD_CTRL, FORCE_MISS_FTLB); |
| 1648 | 1656 | ||
| 1649 | /* Wa_22016670082 */ | 1657 | /* Wa_22016670082 */ |
| @@ -1710,7 +1718,7 @@ xelpmp_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) · 60 unmodified lines | |||
| 1710 | */ | 1718 | */ |
| 1711 | static void gt_tuning_settings(struct intel_gt *gt, struct i915_wa_list *wal) | 1719 | static void gt_tuning_settings(struct intel_gt *gt, struct i915_wa_list *wal) |
| 1712 | { | 1720 | { |
| 1713 | if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) { | 1721 | if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74))) { |
| 1714 | wa_mcr_write_or(wal, XEHP_L3SCQREG7, BLEND_FILL_CACHING_OPT_DIS); | 1722 | wa_mcr_write_or(wal, XEHP_L3SCQREG7, BLEND_FILL_CACHING_OPT_DIS); |
| 1715 | wa_mcr_write_or(wal, XEHP_SQCM, EN_32B_ACCESS); | 1723 | wa_mcr_write_or(wal, XEHP_SQCM, EN_32B_ACCESS); |
| 1716 | } | 1724 | } |
| @@ -1743,7 +1751,7 @@ gt_init_workarounds(struct intel_gt *gt, struct i915_wa_list *wal) · 26 unmodified lines | |||
| 1743 | return; | 1751 | return; |
| 1744 | } | 1752 | } |
| 1745 | 1753 | ||
| 1746 | if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) | 1754 | if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74))) |
| 1747 | xelpg_gt_workarounds_init(gt, wal); | 1755 | xelpg_gt_workarounds_init(gt, wal); |
| 1748 | else if (IS_PONTEVECCHIO(i915)) | 1756 | else if (IS_PONTEVECCHIO(i915)) |
| 1749 | pvc_gt_workarounds_init(gt, wal); | 1757 | pvc_gt_workarounds_init(gt, wal); |
| @@ -2216,7 +2224,7 @@ void intel_engine_init_whitelist(struct intel_engine_cs *engine) · 466 unmodified lines | |||
| 2216 | 2224 | ||
| 2217 | if (engine->gt->type == GT_MEDIA) | 2225 | if (engine->gt->type == GT_MEDIA) |
| 2218 | ; /* none yet */ | 2226 | ; /* none yet */ |
| 2219 | else if (IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 70), IP_VER(12, 71))) | 2227 | else if (IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 70), IP_VER(12, 74))) |
| 2220 | xelpg_whitelist_build(engine); | 2228 | xelpg_whitelist_build(engine); |
| 2221 | else if (IS_PONTEVECCHIO(i915)) | 2229 | else if (IS_PONTEVECCHIO(i915)) |
| 2222 | pvc_whitelist_build(engine); | 2230 | pvc_whitelist_build(engine); |
| @@ -2828,7 +2836,7 @@ add_render_compute_tuning_settings(struct intel_gt *gt, · 605 unmodified lines | |||
| 2828 | { | 2836 | { |
| 2829 | struct drm_i915_private *i915 = gt->i915; | 2837 | struct drm_i915_private *i915 = gt->i915; |
| 2830 | 2838 | ||
| 2831 | if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71)) || IS_DG2(i915)) | 2839 | if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74)) || IS_DG2(i915)) |
| 2832 | wa_mcr_write_clr_set(wal, RT_CTRL, STACKID_CTRL, STACKID_CTRL_512); | 2840 | wa_mcr_write_clr_set(wal, RT_CTRL, STACKID_CTRL, STACKID_CTRL_512); |
| 2833 | 2841 | ||
| 2834 | /* | 2842 | /* |
| @@ -2881,7 +2889,8 @@ general_render_compute_wa_init(struct intel_engine_cs *engine, struct i915_wa_li · 46 unmodified lines | |||
| 2881 | } | 2889 | } |
| 2882 | 2890 | ||
| 2883 | if (IS_GFX_GT_IP_STEP(gt, IP_VER(12, 70), STEP_B0, STEP_FOREVER) || | 2891 | if (IS_GFX_GT_IP_STEP(gt, IP_VER(12, 70), STEP_B0, STEP_FOREVER) || |
| 2884 | IS_GFX_GT_IP_STEP(gt, IP_VER(12, 71), STEP_B0, STEP_FOREVER)) | 2892 | IS_GFX_GT_IP_STEP(gt, IP_VER(12, 71), STEP_B0, STEP_FOREVER) || |
| 2893 | IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 74), IP_VER(12, 74))) | ||
| 2885 | /* Wa_14017856879 */ | 2894 | /* Wa_14017856879 */ |
| 2886 | wa_mcr_masked_en(wal, GEN9_ROW_CHICKEN3, MTL_DISABLE_FIX_FOR_EOT_FLUSH); | 2895 | wa_mcr_masked_en(wal, GEN9_ROW_CHICKEN3, MTL_DISABLE_FIX_FOR_EOT_FLUSH); |
| 2887 | 2896 | ||
| @@ -62,12 +62,12 @@ int live_rc6_manual(void *arg) · 61 unmodified lines | |||
| 62 | 62 | ||
| 63 | dt = ktime_get(); | 63 | dt = ktime_get(); |
| 64 | rc0_power = librapl_energy_uJ(); | 64 | rc0_power = librapl_energy_uJ(); |
| 65 | msleep(250); | 65 | msleep(1000); |
| 66 | rc0_power = librapl_energy_uJ() - rc0_power; | 66 | rc0_power = librapl_energy_uJ() - rc0_power; |
| 67 | dt = ktime_sub(ktime_get(), dt); | 67 | dt = ktime_sub(ktime_get(), dt); |
| 68 | res[1] = rc6_residency(rc6); | 68 | res[1] = rc6_residency(rc6); |
| 69 | if ((res[1] - res[0]) >> 10) { | 69 | if ((res[1] - res[0]) >> 10) { |
| 70 | pr_err("RC6 residency increased by %lldus while disabled for 250ms!\n", | 70 | pr_err("RC6 residency increased by %lldus while disabled for 1000ms!\n", |
| 71 | (res[1] - res[0]) >> 10); | 71 | (res[1] - res[0]) >> 10); |
| 72 | err = -EINVAL; | 72 | err = -EINVAL; |
| 73 | goto out_unlock; | 73 | goto out_unlock; |
| @@ -377,8 +377,13 @@ static int guc_mmio_regset_init(struct temp_regset *regset, · 376 unmodified lines | |||
| 377 | CCS_MASK(engine->gt)) | 377 | CCS_MASK(engine->gt)) |
| 378 | ret |= GUC_MMIO_REG_ADD(gt, regset, GEN12_RCU_MODE, true); | 378 | ret |= GUC_MMIO_REG_ADD(gt, regset, GEN12_RCU_MODE, true); |
| 379 | 379 | ||
| 380 | /* | ||
| 381 | * some of the WA registers are MCR registers. As it is safe to | ||
| 382 | * use MCR form for non-MCR registers, for code simplicity, all | ||
| 383 | * WA registers are added with MCR form. | ||
| 384 | */ | ||
| 380 | for (i = 0, wa = wal->list; i < wal->count; i++, wa++) | 385 | for (i = 0, wa = wal->list; i < wal->count; i++, wa++) |
| 381 | ret |= GUC_MMIO_REG_ADD(gt, regset, wa->reg, wa->masked_reg); | 386 | ret |= GUC_MCR_REG_ADD(gt, regset, wa->mcr_reg, wa->masked_reg); |
| 382 | 387 | ||
| 383 | /* Be extra paranoid and include all whitelist registers. */ | 388 | /* Be extra paranoid and include all whitelist registers. */ |
| 384 | for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) | 389 | for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) |
| @@ -394,13 +399,13 @@ static int guc_mmio_regset_init(struct temp_regset *regset, · 9 unmodified lines | |||
| 394 | ret |= GUC_MMIO_REG_ADD(gt, regset, GEN9_LNCFCMOCS(i), false); | 399 | ret |= GUC_MMIO_REG_ADD(gt, regset, GEN9_LNCFCMOCS(i), false); |
| 395 | 400 | ||
| 396 | if (GRAPHICS_VER(engine->i915) >= 12) { | 401 | if (GRAPHICS_VER(engine->i915) >= 12) { |
| 397 | ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL0, false); | 402 | ret |= GUC_MCR_REG_ADD(gt, regset, MCR_REG(i915_mmio_reg_offset(EU_PERF_CNTL0)), false); |
| 398 | ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL1, false); | 403 | ret |= GUC_MCR_REG_ADD(gt, regset, MCR_REG(i915_mmio_reg_offset(EU_PERF_CNTL1)), false); |
| 399 | ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL2, false); | 404 | ret |= GUC_MCR_REG_ADD(gt, regset, MCR_REG(i915_mmio_reg_offset(EU_PERF_CNTL2)), false); |
| 400 | ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL3, false); | 405 | ret |= GUC_MCR_REG_ADD(gt, regset, MCR_REG(i915_mmio_reg_offset(EU_PERF_CNTL3)), false); |
| 401 | ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL4, false); | 406 | ret |= GUC_MCR_REG_ADD(gt, regset, MCR_REG(i915_mmio_reg_offset(EU_PERF_CNTL4)), false); |
| 402 | ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL5, false); | 407 | ret |= GUC_MCR_REG_ADD(gt, regset, MCR_REG(i915_mmio_reg_offset(EU_PERF_CNTL5)), false); |
| 403 | ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL6, false); | 408 | ret |= GUC_MCR_REG_ADD(gt, regset, MCR_REG(i915_mmio_reg_offset(EU_PERF_CNTL6)), false); |
| 404 | } | 409 | } |
| 405 | 410 | ||
| 406 | return ret ? -1 : 0; | 411 | return ret ? -1 : 0; |
| @@ -184,7 +184,7 @@ static int guc_wait_ucode(struct intel_guc *guc) · 183 unmodified lines | |||
| 184 | * in the seconds range. However, there is a limit on how long an | 184 | * in the seconds range. However, there is a limit on how long an |
| 185 | * individual wait_for() can wait. So wrap it in a loop. | 185 | * individual wait_for() can wait. So wrap it in a loop. |
| 186 | */ | 186 | */ |
| 187 | before_freq = intel_rps_read_actual_frequency(&uncore->gt->rps); | 187 | before_freq = intel_rps_read_actual_frequency(>->rps); |
| 188 | before = ktime_get(); | 188 | before = ktime_get(); |
| 189 | for (count = 0; count < GUC_LOAD_RETRY_LIMIT; count++) { | 189 | for (count = 0; count < GUC_LOAD_RETRY_LIMIT; count++) { |
| 190 | ret = wait_for(guc_load_done(uncore, &status, &success), 1000); | 190 | ret = wait_for(guc_load_done(uncore, &status, &success), 1000); |
| @@ -192,7 +192,7 @@ static int guc_wait_ucode(struct intel_guc *guc) · 1 unmodified line | |||
| 192 | break; | 192 | break; |
| 193 | 193 | ||
| 194 | guc_dbg(guc, "load still in progress, count = %d, freq = %dMHz, status = 0x%08X [0x%02X/%02X]\n", | 194 | guc_dbg(guc, "load still in progress, count = %d, freq = %dMHz, status = 0x%08X [0x%02X/%02X]\n", |
| 195 | count, intel_rps_read_actual_frequency(&uncore->gt->rps), status, | 195 | count, intel_rps_read_actual_frequency(>->rps), status, |
| 196 | REG_FIELD_GET(GS_BOOTROM_MASK, status), | 196 | REG_FIELD_GET(GS_BOOTROM_MASK, status), |
| 197 | REG_FIELD_GET(GS_UKERNEL_MASK, status)); | 197 | REG_FIELD_GET(GS_UKERNEL_MASK, status)); |
| 198 | } | 198 | } |
| @@ -204,7 +204,7 @@ static int guc_wait_ucode(struct intel_guc *guc) · 5 unmodified lines | |||
| 204 | u32 bootrom = REG_FIELD_GET(GS_BOOTROM_MASK, status); | 204 | u32 bootrom = REG_FIELD_GET(GS_BOOTROM_MASK, status); |
| 205 | 205 | ||
| 206 | guc_info(guc, "load failed: status = 0x%08X, time = %lldms, freq = %dMHz, ret = %d\n", | 206 | guc_info(guc, "load failed: status = 0x%08X, time = %lldms, freq = %dMHz, ret = %d\n", |
| 207 | status, delta_ms, intel_rps_read_actual_frequency(&uncore->gt->rps), ret); | 207 | status, delta_ms, intel_rps_read_actual_frequency(>->rps), ret); |
| 208 | guc_info(guc, "load failed: status: Reset = %d, BootROM = 0x%02X, UKernel = 0x%02X, MIA = 0x%02X, Auth = 0x%02X\n", | 208 | guc_info(guc, "load failed: status: Reset = %d, BootROM = 0x%02X, UKernel = 0x%02X, MIA = 0x%02X, Auth = 0x%02X\n", |
| 209 | REG_FIELD_GET(GS_MIA_IN_RESET, status), | 209 | REG_FIELD_GET(GS_MIA_IN_RESET, status), |
| 210 | bootrom, ukernel, | 210 | bootrom, ukernel, |
| @@ -254,11 +254,11 @@ static int guc_wait_ucode(struct intel_guc *guc) · 43 unmodified lines | |||
| 254 | guc_warn(guc, "excessive init time: %lldms! [status = 0x%08X, count = %d, ret = %d]\n", | 254 | guc_warn(guc, "excessive init time: %lldms! [status = 0x%08X, count = %d, ret = %d]\n", |
| 255 | delta_ms, status, count, ret); | 255 | delta_ms, status, count, ret); |
| 256 | guc_warn(guc, "excessive init time: [freq = %dMHz, before = %dMHz, perf_limit_reasons = 0x%08X]\n", | 256 | guc_warn(guc, "excessive init time: [freq = %dMHz, before = %dMHz, perf_limit_reasons = 0x%08X]\n", |
| 257 | intel_rps_read_actual_frequency(&uncore->gt->rps), before_freq, | 257 | intel_rps_read_actual_frequency(>->rps), before_freq, |
| 258 | intel_uncore_read(uncore, intel_gt_perf_limit_reasons_reg(gt))); | 258 | intel_uncore_read(uncore, intel_gt_perf_limit_reasons_reg(gt))); |
| 259 | } else { | 259 | } else { |
| 260 | guc_dbg(guc, "init took %lldms, freq = %dMHz, before = %dMHz, status = 0x%08X, count = %d, ret = %d\n", | 260 | guc_dbg(guc, "init took %lldms, freq = %dMHz, before = %dMHz, status = 0x%08X, count = %d, ret = %d\n", |
| 261 | delta_ms, intel_rps_read_actual_frequency(&uncore->gt->rps), | 261 | delta_ms, intel_rps_read_actual_frequency(>->rps), |
| 262 | before_freq, status, count, ret); | 262 | before_freq, status, count, ret); |
| 263 | } | 263 | } |
| 264 | 264 | ||
| @@ -236,6 +236,13 @@ set_context_destroyed(struct intel_context *ce) · 235 unmodified lines | |||
| 236 | ce->guc_state.sched_state |= SCHED_STATE_DESTROYED; | 236 | ce->guc_state.sched_state |= SCHED_STATE_DESTROYED; |
| 237 | } | 237 | } |
| 238 | 238 | ||
| 239 | static inline void | ||
| 240 | clr_context_destroyed(struct intel_context *ce) | ||
| 241 | { | ||
| 242 | lockdep_assert_held(&ce->guc_state.lock); | ||
| 243 | ce->guc_state.sched_state &= ~SCHED_STATE_DESTROYED; | ||
| 244 | } | ||
| 245 | |||
| 239 | static inline bool context_pending_disable(struct intel_context *ce) | 246 | static inline bool context_pending_disable(struct intel_context *ce) |
| 240 | { | 247 | { |
| 241 | return ce->guc_state.sched_state & SCHED_STATE_PENDING_DISABLE; | 248 | return ce->guc_state.sched_state & SCHED_STATE_PENDING_DISABLE; |
| @@ -613,6 +620,8 @@ static int guc_submission_send_busy_loop(struct intel_guc *guc, · 371 unmodified lines | |||
| 613 | u32 g2h_len_dw, | 620 | u32 g2h_len_dw, |
| 614 | bool loop) | 621 | bool loop) |
| 615 | { | 622 | { |
| 623 | int ret; | ||
| 624 | |||
| 616 | /* | 625 | /* |
| 617 | * We always loop when a send requires a reply (i.e. g2h_len_dw > 0), | 626 | * We always loop when a send requires a reply (i.e. g2h_len_dw > 0), |
| 618 | * so we don't handle the case where we don't get a reply because we | 627 | * so we don't handle the case where we don't get a reply because we |
| @@ -623,7 +632,11 @@ static int guc_submission_send_busy_loop(struct intel_guc *guc, · 4 unmodified lines | |||
| 623 | if (g2h_len_dw) | 632 | if (g2h_len_dw) |
| 624 | atomic_inc(&guc->outstanding_submission_g2h); | 633 | atomic_inc(&guc->outstanding_submission_g2h); |
| 625 | 634 | ||
| 626 | return intel_guc_send_busy_loop(guc, action, len, g2h_len_dw, loop); | 635 | ret = intel_guc_send_busy_loop(guc, action, len, g2h_len_dw, loop); |
| 636 | if (ret) | ||
| 637 | atomic_dec(&guc->outstanding_submission_g2h); | ||
| 638 | |||
| 639 | return ret; | ||
| 627 | } | 640 | } |
| 628 | 641 | ||
| 629 | int intel_guc_wait_for_pending_msg(struct intel_guc *guc, | 642 | int intel_guc_wait_for_pending_msg(struct intel_guc *guc, |
| @@ -1362,7 +1375,45 @@ static void guc_enable_busyness_worker(struct intel_guc *guc) · 732 unmodified lines | |||
| 1362 | 1375 | ||
| 1363 | static void guc_cancel_busyness_worker(struct intel_guc *guc) | 1376 | static void guc_cancel_busyness_worker(struct intel_guc *guc) |
| 1364 | { | 1377 | { |
| 1365 | cancel_delayed_work_sync(&guc->timestamp.work); | 1378 | /* |
| 1379 | * There are many different call stacks that can get here. Some of them | ||
| 1380 | * hold the reset mutex. The busyness worker also attempts to acquire the | ||
| 1381 | * reset mutex. Synchronously flushing a worker thread requires acquiring | ||
| 1382 | * the worker mutex. Lockdep sees this as a conflict. It thinks that the | ||
| 1383 | * flush can deadlock because it holds the worker mutex while waiting for | ||
| 1384 | * the reset mutex, but another thread is holding the reset mutex and might | ||
| 1385 | * attempt to use other worker functions. | ||
| 1386 | * | ||
| 1387 | * In practice, this scenario does not exist because the busyness worker | ||
| 1388 | * does not block waiting for the reset mutex. It does a try-lock on it and | ||
| 1389 | * immediately exits if the lock is already held. Unfortunately, the mutex | ||
| 1390 | * in question (I915_RESET_BACKOFF) is an i915 implementation which has lockdep | ||
| 1391 | * annotation but not to the extent of explaining the 'might lock' is also a | ||
| 1392 | * 'does not need to lock'. So one option would be to add more complex lockdep | ||
| 1393 | * annotations to ignore the issue (if at all possible). A simpler option is to | ||
| 1394 | * just not flush synchronously when a rest in progress. Given that the worker | ||
| 1395 | * will just early exit and re-schedule itself anyway, there is no advantage | ||
| 1396 | * to running it immediately. | ||
| 1397 | * | ||
| 1398 | * If a reset is not in progress, then the synchronous flush may be required. | ||
| 1399 | * As noted many call stacks lead here, some during suspend and driver unload | ||
| 1400 | * which do require a synchronous flush to make sure the worker is stopped | ||
| 1401 | * before memory is freed. | ||
| 1402 | * | ||
| 1403 | * Trying to pass a 'need_sync' or 'in_reset' flag all the way down through | ||
| 1404 | * every possible call stack is unfeasible. It would be too intrusive to many | ||
| 1405 | * areas that really don't care about the GuC backend. However, there is the | ||
| 1406 | * 'reset_in_progress' flag available, so just use that. | ||
| 1407 | * | ||
| 1408 | * And note that in the case of a reset occurring during driver unload | ||
| 1409 | * (wedge_on_fini), skipping the cancel in _prepare (when the reset flag is set | ||
| 1410 | * is fine because there is another cancel in _finish (when the reset flag is | ||
| 1411 | * not). | ||
| 1412 | */ | ||
| 1413 | if (guc_to_gt(guc)->uc.reset_in_progress) | ||
| 1414 | cancel_delayed_work(&guc->timestamp.work); | ||
| 1415 | else | ||
| 1416 | cancel_delayed_work_sync(&guc->timestamp.work); | ||
| 1366 | } | 1417 | } |
| 1367 | 1418 | ||
| 1368 | static void __reset_guc_busyness_stats(struct intel_guc *guc) | 1419 | static void __reset_guc_busyness_stats(struct intel_guc *guc) |
| @@ -1613,6 +1664,11 @@ static void guc_flush_submissions(struct intel_guc *guc) · 244 unmodified lines | |||
| 1613 | spin_unlock_irqrestore(&sched_engine->lock, flags); | 1664 | spin_unlock_irqrestore(&sched_engine->lock, flags); |
| 1614 | } | 1665 | } |
| 1615 | 1666 | ||
| 1667 | void intel_guc_submission_flush_work(struct intel_guc *guc) | ||
| 1668 | { | ||
| 1669 | flush_work(&guc->submission_state.destroyed_worker); | ||
| 1670 | } | ||
| 1671 | |||
| 1616 | static void guc_flush_destroyed_contexts(struct intel_guc *guc); | 1672 | static void guc_flush_destroyed_contexts(struct intel_guc *guc); |
| 1617 | 1673 | ||
| 1618 | void intel_guc_submission_reset_prepare(struct intel_guc *guc) | 1674 | void intel_guc_submission_reset_prepare(struct intel_guc *guc) |
| @@ -1948,8 +2004,16 @@ void intel_guc_submission_cancel_requests(struct intel_guc *guc) · 329 unmodified lines | |||
| 1948 | 2004 | ||
| 1949 | void intel_guc_submission_reset_finish(struct intel_guc *guc) | 2005 | void intel_guc_submission_reset_finish(struct intel_guc *guc) |
| 1950 | { | 2006 | { |
| 2007 | /* | ||
| 2008 | * Ensure the busyness worker gets cancelled even on a fatal wedge. | ||
| 2009 | * Note that reset_prepare is not allowed to because it confuses lockdep. | ||
| 2010 | */ | ||
| 2011 | if (guc_submission_initialized(guc)) | ||
| 2012 | guc_cancel_busyness_worker(guc); | ||
| 2013 | |||
| 1951 | /* Reset called during driver load or during wedge? */ | 2014 | /* Reset called during driver load or during wedge? */ |
| 1952 | if (unlikely(!guc_submission_initialized(guc) || | 2015 | if (unlikely(!guc_submission_initialized(guc) || |
| 2016 | !intel_guc_is_fw_running(guc) || | ||
| 1953 | intel_gt_is_wedged(guc_to_gt(guc)))) { | 2017 | intel_gt_is_wedged(guc_to_gt(guc)))) { |
| 1954 | return; | 2018 | return; |
| 1955 | } | 2019 | } |
| @@ -3283,12 +3347,13 @@ static void guc_context_close(struct intel_context *ce) · 1327 unmodified lines | |||
| 3283 | spin_unlock_irqrestore(&ce->guc_state.lock, flags); | 3347 | spin_unlock_irqrestore(&ce->guc_state.lock, flags); |
| 3284 | } | 3348 | } |
| 3285 | 3349 | ||
| 3286 | static inline void guc_lrc_desc_unpin(struct intel_context *ce) | 3350 | static inline int guc_lrc_desc_unpin(struct intel_context *ce) |
| 3287 | { | 3351 | { |
| 3288 | struct intel_guc *guc = ce_to_guc(ce); | 3352 | struct intel_guc *guc = ce_to_guc(ce); |
| 3289 | struct intel_gt *gt = guc_to_gt(guc); | 3353 | struct intel_gt *gt = guc_to_gt(guc); |
| 3290 | unsigned long flags; | 3354 | unsigned long flags; |
| 3291 | bool disabled; | 3355 | bool disabled; |
| 3356 | int ret; | ||
| 3292 | 3357 | ||
| 3293 | GEM_BUG_ON(!intel_gt_pm_is_awake(gt)); | 3358 | GEM_BUG_ON(!intel_gt_pm_is_awake(gt)); |
| 3294 | GEM_BUG_ON(!ctx_id_mapped(guc, ce->guc_id.id)); | 3359 | GEM_BUG_ON(!ctx_id_mapped(guc, ce->guc_id.id)); |
| @@ -3299,18 +3364,41 @@ static inline void guc_lrc_desc_unpin(struct intel_context *ce) · 4 unmodified lines | |||
| 3299 | spin_lock_irqsave(&ce->guc_state.lock, flags); | 3364 | spin_lock_irqsave(&ce->guc_state.lock, flags); |
| 3300 | disabled = submission_disabled(guc); | 3365 | disabled = submission_disabled(guc); |
| 3301 | if (likely(!disabled)) { | 3366 | if (likely(!disabled)) { |
| 3367 | /* | ||
| 3368 | * Take a gt-pm ref and change context state to be destroyed. | ||
| 3369 | * NOTE: a G2H IRQ that comes after will put this gt-pm ref back | ||
| 3370 | */ | ||
| 3302 | __intel_gt_pm_get(gt); | 3371 | __intel_gt_pm_get(gt); |
| 3303 | set_context_destroyed(ce); | 3372 | set_context_destroyed(ce); |
| 3304 | clr_context_registered(ce); | 3373 | clr_context_registered(ce); |
| 3305 | } | 3374 | } |
| 3306 | spin_unlock_irqrestore(&ce->guc_state.lock, flags); | 3375 | spin_unlock_irqrestore(&ce->guc_state.lock, flags); |
| 3376 | |||
| 3307 | if (unlikely(disabled)) { | 3377 | if (unlikely(disabled)) { |
| 3308 | release_guc_id(guc, ce); | 3378 | release_guc_id(guc, ce); |
| 3309 | __guc_context_destroy(ce); | 3379 | __guc_context_destroy(ce); |
| 3310 | return; | 3380 | return 0; |
| 3311 | } | 3381 | } |
| 3312 | 3382 | ||
| 3313 | deregister_context(ce, ce->guc_id.id); | 3383 | /* |
| 3384 | * GuC is active, lets destroy this context, but at this point we can still be racing | ||
| 3385 | * with suspend, so we undo everything if the H2G fails in deregister_context so | ||
| 3386 | * that GuC reset will find this context during clean up. | ||
| 3387 | */ | ||
| 3388 | ret = deregister_context(ce, ce->guc_id.id); | ||
| 3389 | if (ret) { | ||
| 3390 | spin_lock(&ce->guc_state.lock); | ||
| 3391 | set_context_registered(ce); | ||
| 3392 | clr_context_destroyed(ce); | ||
| 3393 | spin_unlock(&ce->guc_state.lock); | ||
| 3394 | /* | ||
| 3395 | * As gt-pm is awake at function entry, intel_wakeref_put_async merely decrements | ||
| 3396 | * the wakeref immediately but per function spec usage call this after unlock. | ||
| 3397 | */ | ||
| 3398 | intel_wakeref_put_async(>->wakeref); | ||
| 3399 | } | ||
| 3400 | |||
| 3401 | return ret; | ||
| 3314 | } | 3402 | } |
| 3315 | 3403 | ||
| 3316 | static void __guc_context_destroy(struct intel_context *ce) | 3404 | static void __guc_context_destroy(struct intel_context *ce) |
| @@ -3378,7 +3466,22 @@ static void deregister_destroyed_contexts(struct intel_guc *guc) · 61 unmodified lines | |||
| 3378 | if (!ce) | 3466 | if (!ce) |
| 3379 | break; | 3467 | break; |
| 3380 | 3468 | ||
| 3381 | guc_lrc_desc_unpin(ce); | 3469 | if (guc_lrc_desc_unpin(ce)) { |
| 3470 | /* | ||
| 3471 | * This means GuC's CT link severed mid-way which could happen | ||
| 3472 | * in suspend-resume corner cases. In this case, put the | ||
| 3473 | * context back into the destroyed_contexts list which will | ||
| 3474 | * get picked up on the next context deregistration event or | ||
| 3475 | * purged in a GuC sanitization event (reset/unload/wedged/...). | ||
| 3476 | */ | ||
| 3477 | spin_lock_irqsave(&guc->submission_state.lock, flags); | ||
| 3478 | list_add_tail(&ce->destroyed_link, | ||
| 3479 | &guc->submission_state.destroyed_contexts); | ||
| 3480 | spin_unlock_irqrestore(&guc->submission_state.lock, flags); | ||
| 3481 | /* Bail now since the list might never be emptied if h2gs fail */ | ||
| 3482 | break; | ||
| 3483 | } | ||
| 3484 | |||
| 3382 | } | 3485 | } |
| 3383 | } | 3486 | } |
| 3384 | 3487 | ||
| @@ -3389,6 +3492,17 @@ static void destroyed_worker_func(struct work_struct *w) · 4 unmodified lines | |||
| 3389 | struct intel_gt *gt = guc_to_gt(guc); | 3492 | struct intel_gt *gt = guc_to_gt(guc); |
| 3390 | intel_wakeref_t wakeref; | 3493 | intel_wakeref_t wakeref; |
| 3391 | 3494 | ||
| 3495 | /* | ||
| 3496 | * In rare cases we can get here via async context-free fence-signals that | ||
| 3497 | * come very late in suspend flow or very early in resume flows. In these | ||
| 3498 | * cases, GuC won't be ready but just skipping it here is fine as these | ||
| 3499 | * pending-destroy-contexts get destroyed totally at GuC reset time at the | ||
| 3500 | * end of suspend.. OR.. this worker can be picked up later on the next | ||
| 3501 | * context destruction trigger after resume-completes | ||
| 3502 | */ | ||
| 3503 | if (!intel_guc_is_ready(guc)) | ||
| 3504 | return; | ||
| 3505 | |||
| 3392 | with_intel_gt_pm(gt, wakeref) | 3506 | with_intel_gt_pm(gt, wakeref) |
| 3393 | deregister_destroyed_contexts(guc); | 3507 | deregister_destroyed_contexts(guc); |
| 3394 | } | 3508 | } |
| @@ -38,6 +38,8 @@ int intel_guc_wait_for_pending_msg(struct intel_guc *guc, · 37 unmodified lines | |||
| 38 | bool interruptible, | 38 | bool interruptible, |
| 39 | long timeout); | 39 | long timeout); |
| 40 | 40 | ||
| 41 | void intel_guc_submission_flush_work(struct intel_guc *guc); | ||
| 42 | |||
| 41 | static inline bool intel_guc_submission_is_supported(struct intel_guc *guc) | 43 | static inline bool intel_guc_submission_is_supported(struct intel_guc *guc) |
| 42 | { | 44 | { |
| 43 | return guc->submission_supported; | 45 | return guc->submission_supported; |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | |||
| 6 | #include <linux/types.h> | 6 | #include <linux/types.h> |
| 7 | 7 | ||
| 8 | #include "gt/intel_gt.h" | 8 | #include "gt/intel_gt.h" |
| 9 | #include "gt/intel_rps.h" | ||
| 9 | #include "intel_guc_reg.h" | 10 | #include "intel_guc_reg.h" |
| 10 | #include "intel_huc.h" | 11 | #include "intel_huc.h" |
| 11 | #include "intel_huc_print.h" | 12 | #include "intel_huc_print.h" |
| @@ -447,17 +448,68 @@ static const char *auth_mode_string(struct intel_huc *huc, · 435 unmodified lines | |||
| 447 | return partial ? "clear media" : "all workloads"; | 448 | return partial ? "clear media" : "all workloads"; |
| 448 | } | 449 | } |
| 449 | 450 | ||
| 451 | /* | ||
| 452 | * Use a longer timeout for debug builds so that problems can be detected | ||
| 453 | * and analysed. But a shorter timeout for releases so that user's don't | ||
| 454 | * wait forever to find out there is a problem. Note that the only reason | ||
| 455 | * an end user should hit the timeout is in case of extreme thermal throttling. | ||
| 456 | * And a system that is that hot during boot is probably dead anyway! | ||
| 457 | */ | ||
| 458 | #if defined(CONFIG_DRM_I915_DEBUG_GEM) | ||
| 459 | #define HUC_LOAD_RETRY_LIMIT 20 | ||
| 460 | #else | ||
| 461 | #define HUC_LOAD_RETRY_LIMIT 3 | ||
| 462 | #endif | ||
| 463 | |||
| 450 | int intel_huc_wait_for_auth_complete(struct intel_huc *huc, | 464 | int intel_huc_wait_for_auth_complete(struct intel_huc *huc, |
| 451 | enum intel_huc_authentication_type type) | 465 | enum intel_huc_authentication_type type) |
| 452 | { | 466 | { |
| 453 | struct intel_gt *gt = huc_to_gt(huc); | 467 | struct intel_gt *gt = huc_to_gt(huc); |
| 454 | int ret; | 468 | struct intel_uncore *uncore = gt->uncore; |
| 469 | ktime_t before, after, delta; | ||
| 470 | int ret, count; | ||
| 471 | u64 delta_ms; | ||
| 472 | u32 before_freq; | ||
| 455 | 473 | ||
| 456 | ret = __intel_wait_for_register(gt->uncore, | 474 | /* |
| 457 | huc->status[type].reg, | 475 | * The KMD requests maximum frequency during driver load, however thermal |
| 458 | huc->status[type].mask, | 476 | * throttling can force the frequency down to minimum (although the board |
| 459 | huc->status[type].value, | 477 | * really should never get that hot in real life!). IFWI issues have been |
| 460 | 2, 50, NULL); | 478 | * seen to cause sporadic failures to grant the higher frequency. And at |
| 479 | * minimum frequency, the authentication time can be in the seconds range. | ||
| 480 | * Note that there is a limit on how long an individual wait_for() can wait. | ||
| 481 | * So wrap it in a loop. | ||
| 482 | */ | ||
| 483 | before_freq = intel_rps_read_actual_frequency(>->rps); | ||
| 484 | before = ktime_get(); | ||
| 485 | for (count = 0; count < HUC_LOAD_RETRY_LIMIT; count++) { | ||
| 486 | ret = __intel_wait_for_register(gt->uncore, | ||
| 487 | huc->status[type].reg, | ||
| 488 | huc->status[type].mask, | ||
| 489 | huc->status[type].value, | ||
| 490 | 2, 1000, NULL); | ||
| 491 | if (!ret) | ||
| 492 | break; | ||
| 493 | |||
| 494 | huc_dbg(huc, "auth still in progress, count = %d, freq = %dMHz, status = 0x%08X\n", | ||
| 495 | count, intel_rps_read_actual_frequency(>->rps), | ||
| 496 | huc->status[type].reg.reg); | ||
| 497 | } | ||
| 498 | after = ktime_get(); | ||
| 499 | delta = ktime_sub(after, before); | ||
| 500 | delta_ms = ktime_to_ms(delta); | ||
| 501 | |||
| 502 | if (delta_ms > 50) { | ||
| 503 | huc_warn(huc, "excessive auth time: %lldms! [status = 0x%08X, count = %d, ret = %d]\n", | ||
| 504 | delta_ms, huc->status[type].reg.reg, count, ret); | ||
| 505 | huc_warn(huc, "excessive auth time: [freq = %dMHz, before = %dMHz, perf_limit_reasons = 0x%08X]\n", | ||
| 506 | intel_rps_read_actual_frequency(>->rps), before_freq, | ||
| 507 | intel_uncore_read(uncore, intel_gt_perf_limit_reasons_reg(gt))); | ||
| 508 | } else { | ||
| 509 | huc_dbg(huc, "auth took %lldms, freq = %dMHz, before = %dMHz, status = 0x%08X, count = %d, ret = %d\n", | ||
| 510 | delta_ms, intel_rps_read_actual_frequency(>->rps), | ||
| 511 | before_freq, huc->status[type].reg.reg, count, ret); | ||
| 512 | } | ||
| 461 | 513 | ||
| 462 | /* mark the load process as complete even if the wait failed */ | 514 | /* mark the load process as complete even if the wait failed */ |
| 463 | delayed_huc_load_complete(huc); | 515 | delayed_huc_load_complete(huc); |
| @@ -640,7 +640,7 @@ void intel_uc_reset_finish(struct intel_uc *uc) · 639 unmodified lines | |||
| 640 | uc->reset_in_progress = false; | 640 | uc->reset_in_progress = false; |
| 641 | 641 | ||
| 642 | /* Firmware expected to be running when this function is called */ | 642 | /* Firmware expected to be running when this function is called */ |
| 643 | if (intel_guc_is_fw_running(guc) && intel_uc_uses_guc_submission(uc)) | 643 | if (intel_uc_uses_guc_submission(uc)) |
| 644 | intel_guc_submission_reset_finish(guc); | 644 | intel_guc_submission_reset_finish(guc); |
| 645 | } | 645 | } |
| 646 | 646 | ||
| @@ -690,6 +690,8 @@ void intel_uc_suspend(struct intel_uc *uc) · 43 unmodified lines | |||
| 690 | return; | 690 | return; |
| 691 | } | 691 | } |
| 692 | 692 | ||
| 693 | intel_guc_submission_flush_work(guc); | ||
| 694 | |||
| 693 | with_intel_runtime_pm(&uc_to_gt(uc)->i915->runtime_pm, wakeref) { | 695 | with_intel_runtime_pm(&uc_to_gt(uc)->i915->runtime_pm, wakeref) { |
| 694 | err = intel_guc_suspend(guc); | 696 | err = intel_guc_suspend(guc); |
| 695 | if (err) | 697 | if (err) |
| @@ -147,7 +147,7 @@ static const char *i915_cache_level_str(struct drm_i915_gem_object *obj) · 146 unmodified lines | |||
| 147 | { | 147 | { |
| 148 | struct drm_i915_private *i915 = obj_to_i915(obj); | 148 | struct drm_i915_private *i915 = obj_to_i915(obj); |
| 149 | 149 | ||
| 150 | if (IS_GFX_GT_IP_RANGE(to_gt(i915), IP_VER(12, 70), IP_VER(12, 71))) { | 150 | if (IS_GFX_GT_IP_RANGE(to_gt(i915), IP_VER(12, 70), IP_VER(12, 74))) { |
| 151 | switch (obj->pat_index) { | 151 | switch (obj->pat_index) { |
| 152 | case 0: return " WB"; | 152 | case 0: return " WB"; |
| 153 | case 1: return " WT"; | 153 | case 1: return " WT"; |
| @@ -165,14 +165,6 @@ struct i915_gem_mm { · 164 unmodified lines | |||
| 165 | struct notifier_block vmap_notifier; | 165 | struct notifier_block vmap_notifier; |
| 166 | struct shrinker *shrinker; | 166 | struct shrinker *shrinker; |
| 167 | 167 | ||
| 168 | #ifdef CONFIG_MMU_NOTIFIER | ||
| 169 | /** | ||
| 170 | * notifier_lock for mmu notifiers, memory may not be allocated | ||
| 171 | * while holding this lock. | ||
| 172 | */ | ||
| 173 | rwlock_t notifier_lock; | ||
| 174 | #endif | ||
| 175 | |||
| 176 | /* shrinker accounting, also useful for userland debugging */ | 168 | /* shrinker accounting, also useful for userland debugging */ |
| 177 | u64 shrink_memory; | 169 | u64 shrink_memory; |
| 178 | u32 shrink_count; | 170 | u32 shrink_count; |
| @@ -48,7 +48,6 @@ · 47 unmodified lines | |||
| 48 | #include "gem/i915_gem_object_frontbuffer.h" | 48 | #include "gem/i915_gem_object_frontbuffer.h" |
| 49 | #include "gem/i915_gem_pm.h" | 49 | #include "gem/i915_gem_pm.h" |
| 50 | #include "gem/i915_gem_region.h" | 50 | #include "gem/i915_gem_region.h" |
| 51 | #include "gem/i915_gem_userptr.h" | ||
| 52 | #include "gt/intel_engine_user.h" | 51 | #include "gt/intel_engine_user.h" |
| 53 | #include "gt/intel_gt.h" | 52 | #include "gt/intel_gt.h" |
| 54 | #include "gt/intel_gt_pm.h" | 53 | #include "gt/intel_gt_pm.h" |
| @@ -1165,10 +1164,6 @@ int i915_gem_init(struct drm_i915_private *dev_priv) · 1110 unmodified lines | |||
| 1165 | if (intel_vgpu_active(dev_priv) && !intel_vgpu_has_huge_gtt(dev_priv)) | 1164 | if (intel_vgpu_active(dev_priv) && !intel_vgpu_has_huge_gtt(dev_priv)) |
| 1166 | RUNTIME_INFO(dev_priv)->page_sizes = I915_GTT_PAGE_SIZE_4K; | 1165 | RUNTIME_INFO(dev_priv)->page_sizes = I915_GTT_PAGE_SIZE_4K; |
| 1167 | 1166 | ||
| 1168 | ret = i915_gem_init_userptr(dev_priv); | ||
| 1169 | if (ret) | ||
| 1170 | return ret; | ||
| 1171 | |||
| 1172 | for_each_gt(gt, dev_priv, i) { | 1167 | for_each_gt(gt, dev_priv, i) { |
| 1173 | intel_uc_fetch_firmwares(>->uc); | 1168 | intel_uc_fetch_firmwares(>->uc); |
| 1174 | intel_wopcm_init(>->wopcm); | 1169 | intel_wopcm_init(>->wopcm); |
| @@ -3225,7 +3225,7 @@ u32 i915_perf_oa_timestamp_frequency(struct drm_i915_private *i915) · 3224 unmodified lines | |||
| 3225 | struct intel_gt *gt = to_gt(i915); | 3225 | struct intel_gt *gt = to_gt(i915); |
| 3226 | 3226 | ||
| 3227 | /* Wa_18013179988 */ | 3227 | /* Wa_18013179988 */ |
| 3228 | if (IS_DG2(i915) || IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) { | 3228 | if (IS_DG2(i915) || IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74))) { |
| 3229 | intel_wakeref_t wakeref; | 3229 | intel_wakeref_t wakeref; |
| 3230 | u32 reg, shift; | 3230 | u32 reg, shift; |
| 3231 | 3231 | ||
| @@ -551,6 +551,38 @@ static int query_hwconfig_blob(struct drm_i915_private *i915, · 550 unmodified lines | |||
| 551 | return hwconfig->size; | 551 | return hwconfig->size; |
| 552 | } | 552 | } |
| 553 | 553 | ||
| 554 | static int | ||
| 555 | query_guc_submission_version(struct drm_i915_private *i915, | ||
| 556 | struct drm_i915_query_item *query) | ||
| 557 | { | ||
| 558 | struct drm_i915_query_guc_submission_version __user *query_ptr = | ||
| 559 | u64_to_user_ptr(query->data_ptr); | ||
| 560 | struct drm_i915_query_guc_submission_version ver; | ||
| 561 | struct intel_guc *guc = &to_gt(i915)->uc.guc; | ||
| 562 | const size_t size = sizeof(ver); | ||
| 563 | int ret; | ||
| 564 | |||
| 565 | if (!intel_uc_uses_guc_submission(&to_gt(i915)->uc)) | ||
| 566 | return -ENODEV; | ||
| 567 | |||
| 568 | ret = copy_query_item(&ver, size, size, query); | ||
| 569 | if (ret != 0) | ||
| 570 | return ret; | ||
| 571 | |||
| 572 | if (ver.branch || ver.major || ver.minor || ver.patch) | ||
| 573 | return -EINVAL; | ||
| 574 | |||
| 575 | ver.branch = 0; | ||
| 576 | ver.major = guc->submission_version.major; | ||
| 577 | ver.minor = guc->submission_version.minor; | ||
| 578 | ver.patch = guc->submission_version.patch; | ||
| 579 | |||
| 580 | if (copy_to_user(query_ptr, &ver, size)) | ||
| 581 | return -EFAULT; | ||
| 582 | |||
| 583 | return 0; | ||
| 584 | } | ||
| 585 | |||
| 554 | static int (* const i915_query_funcs[])(struct drm_i915_private *dev_priv, | 586 | static int (* const i915_query_funcs[])(struct drm_i915_private *dev_priv, |
| 555 | struct drm_i915_query_item *query_item) = { | 587 | struct drm_i915_query_item *query_item) = { |
| 556 | query_topology_info, | 588 | query_topology_info, |
| @@ -559,6 +591,7 @@ static int (* const i915_query_funcs[])(struct drm_i915_private *dev_priv, · 2 unmodified lines | |||
| 559 | query_memregion_info, | 591 | query_memregion_info, |
| 560 | query_hwconfig_blob, | 592 | query_hwconfig_blob, |
| 561 | query_geometry_subslices, | 593 | query_geometry_subslices, |
| 594 | query_guc_submission_version, | ||
| 562 | }; | 595 | }; |
| 563 | 596 | ||
| 564 | int i915_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file) | 597 | int i915_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file) |
| @@ -75,13 +75,10 @@ struct i915_syncmap { · 74 unmodified lines | |||
| 75 | unsigned int height; | 75 | unsigned int height; |
| 76 | unsigned int bitmap; | 76 | unsigned int bitmap; |
| 77 | struct i915_syncmap *parent; | 77 | struct i915_syncmap *parent; |
| 78 | /* | 78 | union { |
| 79 | * Following this header is an array of either seqno or child pointers: | 79 | DECLARE_FLEX_ARRAY(u32, seqno); |
| 80 | * union { | 80 | DECLARE_FLEX_ARRAY(struct i915_syncmap *, child); |
| 81 | * u32 seqno[KSYNCMAP]; | 81 | }; |
| 82 | * struct i915_syncmap *child[KSYNCMAP]; | ||
| 83 | * }; | ||
| 84 | */ | ||
| 85 | }; | 82 | }; |
| 86 | 83 | ||
| 87 | /** | 84 | /** |
| @@ -99,13 +96,13 @@ void i915_syncmap_init(struct i915_syncmap **root) · 11 unmodified lines | |||
| 99 | static inline u32 *__sync_seqno(struct i915_syncmap *p) | 96 | static inline u32 *__sync_seqno(struct i915_syncmap *p) |
| 100 | { | 97 | { |
| 101 | GEM_BUG_ON(p->height); | 98 | GEM_BUG_ON(p->height); |
| 102 | return (u32 *)(p + 1); | 99 | return p->seqno; |
| 103 | } | 100 | } |
| 104 | 101 | ||
| 105 | static inline struct i915_syncmap **__sync_child(struct i915_syncmap *p) | 102 | static inline struct i915_syncmap **__sync_child(struct i915_syncmap *p) |
| 106 | { | 103 | { |
| 107 | GEM_BUG_ON(!p->height); | 104 | GEM_BUG_ON(!p->height); |
| 108 | return (struct i915_syncmap **)(p + 1); | 105 | return p->child; |
| 109 | } | 106 | } |
| 110 | 107 | ||
| 111 | static inline unsigned int | 108 | static inline unsigned int |
| @@ -200,7 +197,7 @@ __sync_alloc_leaf(struct i915_syncmap *parent, u64 id) · 88 unmodified lines | |||
| 200 | { | 197 | { |
| 201 | struct i915_syncmap *p; | 198 | struct i915_syncmap *p; |
| 202 | 199 | ||
| 203 | p = kmalloc(sizeof(*p) + KSYNCMAP * sizeof(u32), GFP_KERNEL); | 200 | p = kmalloc(struct_size(p, seqno, KSYNCMAP), GFP_KERNEL); |
| 204 | if (unlikely(!p)) | 201 | if (unlikely(!p)) |
| 205 | return NULL; | 202 | return NULL; |
| 206 | 203 | ||
| @@ -282,7 +279,7 @@ static noinline int __sync_set(struct i915_syncmap **root, u64 id, u32 seqno) · 75 unmodified lines | |||
| 282 | unsigned int above; | 279 | unsigned int above; |
| 283 | 280 | ||
| 284 | /* Insert a join above the current layer */ | 281 | /* Insert a join above the current layer */ |
| 285 | next = kzalloc(sizeof(*next) + KSYNCMAP * sizeof(next), | 282 | next = kzalloc(struct_size(next, child, KSYNCMAP), |
| 286 | GFP_KERNEL); | 283 | GFP_KERNEL); |
| 287 | if (unlikely(!next)) | 284 | if (unlikely(!next)) |
| 288 | return -ENOMEM; | 285 | return -ENOMEM; |
| @@ -1800,7 +1800,10 @@ static const struct intel_forcewake_range __mtl_fw_ranges[] = { · 1799 unmodified lines | |||
| 1800 | GEN_FW_RANGE(0x24000, 0x2ffff, 0), /* | 1800 | GEN_FW_RANGE(0x24000, 0x2ffff, 0), /* |
| 1801 | 0x24000 - 0x2407f: always on | 1801 | 0x24000 - 0x2407f: always on |
| 1802 | 0x24080 - 0x2ffff: reserved */ | 1802 | 0x24080 - 0x2ffff: reserved */ |
| 1803 | GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_GT) | 1803 | GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_GT), |
| 1804 | GEN_FW_RANGE(0x40000, 0x1901ef, 0), | ||
| 1805 | GEN_FW_RANGE(0x1901f0, 0x1901f3, FORCEWAKE_GT) | ||
| 1806 | /* FIXME: WA to wake GT while triggering H2G */ | ||
| 1804 | }; | 1807 | }; |
| 1805 | 1808 | ||
| 1806 | /* | 1809 | /* |
| @@ -3013,6 +3013,7 @@ struct drm_i915_query_item { · 3012 unmodified lines | |||
| 3013 | * - %DRM_I915_QUERY_MEMORY_REGIONS (see struct drm_i915_query_memory_regions) | 3013 | * - %DRM_I915_QUERY_MEMORY_REGIONS (see struct drm_i915_query_memory_regions) |
| 3014 | * - %DRM_I915_QUERY_HWCONFIG_BLOB (see `GuC HWCONFIG blob uAPI`) | 3014 | * - %DRM_I915_QUERY_HWCONFIG_BLOB (see `GuC HWCONFIG blob uAPI`) |
| 3015 | * - %DRM_I915_QUERY_GEOMETRY_SUBSLICES (see struct drm_i915_query_topology_info) | 3015 | * - %DRM_I915_QUERY_GEOMETRY_SUBSLICES (see struct drm_i915_query_topology_info) |
| 3016 | * - %DRM_I915_QUERY_GUC_SUBMISSION_VERSION (see struct drm_i915_query_guc_submission_version) | ||
| 3016 | */ | 3017 | */ |
| 3017 | __u64 query_id; | 3018 | __u64 query_id; |
| 3018 | #define DRM_I915_QUERY_TOPOLOGY_INFO 1 | 3019 | #define DRM_I915_QUERY_TOPOLOGY_INFO 1 |
| @@ -3021,6 +3022,7 @@ struct drm_i915_query_item { · 2 unmodified lines | |||
| 3021 | #define DRM_I915_QUERY_MEMORY_REGIONS 4 | 3022 | #define DRM_I915_QUERY_MEMORY_REGIONS 4 |
| 3022 | #define DRM_I915_QUERY_HWCONFIG_BLOB 5 | 3023 | #define DRM_I915_QUERY_HWCONFIG_BLOB 5 |
| 3023 | #define DRM_I915_QUERY_GEOMETRY_SUBSLICES 6 | 3024 | #define DRM_I915_QUERY_GEOMETRY_SUBSLICES 6 |
| 3025 | #define DRM_I915_QUERY_GUC_SUBMISSION_VERSION 7 | ||
| 3024 | /* Must be kept compact -- no holes and well documented */ | 3026 | /* Must be kept compact -- no holes and well documented */ |
| 3025 | 3027 | ||
| 3026 | /** | 3028 | /** |
| @@ -3566,6 +3568,16 @@ struct drm_i915_query_memory_regions { · 539 unmodified lines | |||
| 3566 | struct drm_i915_memory_region_info regions[]; | 3568 | struct drm_i915_memory_region_info regions[]; |
| 3567 | }; | 3569 | }; |
| 3568 | 3570 | ||
| 3571 | /** | ||
| 3572 | * struct drm_i915_query_guc_submission_version - query GuC submission interface version | ||
| 3573 | */ | ||
| 3574 | struct drm_i915_query_guc_submission_version { | ||
| 3575 | __u32 branch; | ||
| 3576 | __u32 major; | ||
| 3577 | __u32 minor; | ||
| 3578 | __u32 patch; | ||
| 3579 | }; | ||
| 3580 | |||
| 3569 | /** | 3581 | /** |
| 3570 | * DOC: GuC HWCONFIG blob uAPI | 3582 | * DOC: GuC HWCONFIG blob uAPI |
| 3571 | * | 3583 | * |