Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'drm-intel-gt-next-2023-12-08' of git://anongit.freedesktop.org/drm/drm-intel into drm-next

UAPI Changes:

- drm/i915: Implement fdinfo memory stats printing

Use the newly added drm_print_memory_stats helper to show memory
utilisation of our objects in drm/driver specific fdinfo output.

To collect the stats we walk the per memory regions object lists
and accumulate object size into the respective drm_memory_stats
categories.

Cross-subsystem Changes:

- Backmerge of drm-next (to bring drm-intel-next for PXP changes)

Driver Changes:

- Wa_18028616096 now applies to all DG2 (Matt R)
- Drop Wa_22014600077 on all DG2 (Matt R)
- Add new ATS-M device ID (Haridhar)
- More Meteorlake (MTL) workarounds (Matt R, Dnyaneshwar, Jonathan,
Gustavo, Radhakrishna)
- PMU WARN_ON cleanup on driver unbind (Umesh)
- Limit GGTT WC flushing workaround to pre BXT/ICL platforms
- Complement implementation for Wa_16018031267 / Wa_16018063123
(Andrzej, Jonathan, Nirmoy, Chris)

- Properly print internal GSC engine in trace logs (Tvrtko)
- Track gt pm wakerefs (Andrzej)
- Fix null deref bugs on perf code when perf is disabled (Harshit,
Tvrtko)
- Fix __i915_request_create memory leak on driver unbind (Andrzej)
- Remove spurious unsupported HuC message on MTL (Daniele)
- Read a shadowed mmio register for ggtt flush (Vinay)
- Add missing new-line to GT_TRACE (Andrzej)
- Add drm_dbgs for critical PXP events (Alan)
- Skip pxp init if gt is wedged (Zhanjun)

- Replace custom intel runtime_pm tracker with ref_tracker library
(Andrzej)
- Compiler warning/static checker/coding style cleanups (Arnd, Nirmoy,
Soumya, Gilbert, Dorcas, Kunwu, Sam, Tvrtko)
- Code structure and helper cleanups (Jani, Tvrtko, Andi)
- Selftest improvements (John, Tvrtko, Andrzej)

Signed-off-by: Dave Airlie <airlied@redhat.com>

# Conflicts:
# drivers/gpu/drm/i915/gt/intel_gt_mcr.c
From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/ZXNBcsSwJEVsq9On@jlahtine-mobl.ger.corp.intel.com

+1232 -635
+18
drivers/gpu/drm/i915/Kconfig.debug
··· 24 24 select DEBUG_FS 25 25 select PREEMPT_COUNT 26 26 select I2C_CHARDEV 27 + select REF_TRACKER 27 28 select STACKDEPOT 29 + select STACKTRACE 28 30 select DRM_DP_AUX_CHARDEV 29 31 select X86_MSR # used by igt/pm_rpm 30 32 select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks) ··· 40 38 select DRM_I915_DEBUG_GEM_ONCE 41 39 select DRM_I915_DEBUG_MMIO 42 40 select DRM_I915_DEBUG_RUNTIME_PM 41 + select DRM_I915_DEBUG_WAKEREF 43 42 select DRM_I915_SW_FENCE_DEBUG_OBJECTS 44 43 select DRM_I915_SELFTEST 45 44 default n ··· 234 231 bool "Enable extra state checking for runtime PM" 235 232 depends on DRM_I915 236 233 default n 234 + select REF_TRACKER 237 235 select STACKDEPOT 236 + select STACKTRACE 238 237 help 239 238 Choose this option to turn on extra state checking for the 240 239 runtime PM functionality. This may introduce overhead during 241 240 driver loading, suspend and resume operations. 242 241 243 242 Recommended for driver developers only. 243 + 244 + If in doubt, say "N" 245 + 246 + config DRM_I915_DEBUG_WAKEREF 247 + bool "Enable extra tracking for wakerefs" 248 + depends on DRM_I915 249 + select REF_TRACKER 250 + select STACKDEPOT 251 + select STACKTRACE 252 + help 253 + Choose this option to turn on extra state checking and usage 254 + tracking for the wakerefPM functionality. This may introduce 255 + overhead during driver runtime. 244 256 245 257 If in doubt, say "N"
+1 -1
drivers/gpu/drm/i915/display/intel_display_power.c
··· 405 405 struct drm_i915_private, 406 406 display.power.domains); 407 407 408 - drm_dbg(&i915->drm, "async_put_wakeref %u\n", 408 + drm_dbg(&i915->drm, "async_put_wakeref %lu\n", 409 409 power_domains->async_put_wakeref); 410 410 411 411 print_power_domains(power_domains, "async_put_domains[0]",
+8 -3
drivers/gpu/drm/i915/gem/i915_gem_context.c
··· 279 279 } 280 280 281 281 static struct i915_gem_proto_context * 282 - proto_context_create(struct drm_i915_private *i915, unsigned int flags) 282 + proto_context_create(struct drm_i915_file_private *fpriv, 283 + struct drm_i915_private *i915, unsigned int flags) 283 284 { 284 285 struct i915_gem_proto_context *pc, *err; 285 286 ··· 288 287 if (!pc) 289 288 return ERR_PTR(-ENOMEM); 290 289 290 + pc->fpriv = fpriv; 291 291 pc->num_user_engines = -1; 292 292 pc->user_engines = NULL; 293 293 pc->user_flags = BIT(UCONTEXT_BANNABLE) | ··· 1624 1622 err = PTR_ERR(ppgtt); 1625 1623 goto err_ctx; 1626 1624 } 1625 + ppgtt->vm.fpriv = pc->fpriv; 1627 1626 vm = &ppgtt->vm; 1628 1627 } 1629 1628 if (vm) ··· 1744 1741 /* 0 reserved for invalid/unassigned ppgtt */ 1745 1742 xa_init_flags(&file_priv->vm_xa, XA_FLAGS_ALLOC1); 1746 1743 1747 - pc = proto_context_create(i915, 0); 1744 + pc = proto_context_create(file_priv, i915, 0); 1748 1745 if (IS_ERR(pc)) { 1749 1746 err = PTR_ERR(pc); 1750 1747 goto err; ··· 1826 1823 1827 1824 GEM_BUG_ON(id == 0); /* reserved for invalid/unassigned ppgtt */ 1828 1825 args->vm_id = id; 1826 + ppgtt->vm.fpriv = file_priv; 1829 1827 return 0; 1830 1828 1831 1829 err_put: ··· 2289 2285 return -EIO; 2290 2286 } 2291 2287 2292 - ext_data.pc = proto_context_create(i915, args->flags); 2288 + ext_data.pc = proto_context_create(file->driver_priv, i915, 2289 + args->flags); 2293 2290 if (IS_ERR(ext_data.pc)) 2294 2291 return PTR_ERR(ext_data.pc); 2295 2292
+3
drivers/gpu/drm/i915/gem/i915_gem_context_types.h
··· 188 188 * CONTEXT_CREATE_SET_PARAM during GEM_CONTEXT_CREATE. 189 189 */ 190 190 struct i915_gem_proto_context { 191 + /** @fpriv: Client which creates the context */ 192 + struct drm_i915_file_private *fpriv; 193 + 191 194 /** @vm: See &i915_gem_context.vm */ 192 195 struct i915_address_space *vm; 193 196
+9 -7
drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
··· 254 254 struct intel_gt *gt; /* gt for the execbuf */ 255 255 struct intel_context *context; /* logical state for the request */ 256 256 struct i915_gem_context *gem_context; /** caller's context */ 257 + intel_wakeref_t wakeref; 258 + intel_wakeref_t wakeref_gt0; 257 259 258 260 /** our requests to build */ 259 261 struct i915_request *requests[MAX_ENGINE_INSTANCE + 1]; ··· 1681 1679 urelocs = u64_to_user_ptr(eb->exec[i].relocs_ptr); 1682 1680 size = nreloc * sizeof(*relocs); 1683 1681 1684 - relocs = kvmalloc_array(size, 1, GFP_KERNEL); 1682 + relocs = kvmalloc_array(1, size, GFP_KERNEL); 1685 1683 if (!relocs) { 1686 1684 err = -ENOMEM; 1687 1685 goto err; ··· 2722 2720 2723 2721 for_each_child(ce, child) 2724 2722 intel_context_get(child); 2725 - intel_gt_pm_get(gt); 2723 + eb->wakeref = intel_gt_pm_get(ce->engine->gt); 2726 2724 /* 2727 2725 * Keep GT0 active on MTL so that i915_vma_parked() doesn't 2728 2726 * free VMAs while execbuf ioctl is validating VMAs. 2729 2727 */ 2730 2728 if (gt->info.id) 2731 - intel_gt_pm_get(to_gt(gt->i915)); 2729 + eb->wakeref_gt0 = intel_gt_pm_get(to_gt(gt->i915)); 2732 2730 2733 2731 if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) { 2734 2732 err = intel_context_alloc_state(ce); ··· 2768 2766 2769 2767 err: 2770 2768 if (gt->info.id) 2771 - intel_gt_pm_put(to_gt(gt->i915)); 2769 + intel_gt_pm_put(to_gt(gt->i915), eb->wakeref_gt0); 2772 2770 2773 - intel_gt_pm_put(gt); 2771 + intel_gt_pm_put(ce->engine->gt, eb->wakeref); 2774 2772 for_each_child(ce, child) 2775 2773 intel_context_put(child); 2776 2774 intel_context_put(ce); ··· 2788 2786 * i915_vma_parked() from interfering while execbuf validates vmas. 2789 2787 */ 2790 2788 if (eb->gt->info.id) 2791 - intel_gt_pm_put(to_gt(eb->gt->i915)); 2792 - intel_gt_pm_put(eb->gt); 2789 + intel_gt_pm_put(to_gt(eb->gt->i915), eb->wakeref_gt0); 2790 + intel_gt_pm_put(eb->context->engine->gt, eb->wakeref); 2793 2791 for_each_child(eb->context, child) 2794 2792 intel_context_put(child); 2795 2793 intel_context_put(eb->context);
+10 -3
drivers/gpu/drm/i915/gem/i915_gem_object.c
··· 106 106 107 107 INIT_LIST_HEAD(&obj->mm.link); 108 108 109 + #ifdef CONFIG_PROC_FS 110 + INIT_LIST_HEAD(&obj->client_link); 111 + #endif 112 + 109 113 INIT_LIST_HEAD(&obj->lut_list); 110 114 spin_lock_init(&obj->lut_lock); 111 115 ··· 297 293 container_of(head, typeof(*obj), rcu); 298 294 struct drm_i915_private *i915 = to_i915(obj->base.dev); 299 295 296 + /* We need to keep this alive for RCU read access from fdinfo. */ 297 + if (obj->mm.n_placements > 1) 298 + kfree(obj->mm.placements); 299 + 300 300 i915_gem_object_free(obj); 301 301 302 302 GEM_BUG_ON(!atomic_read(&i915->mm.free_count)); ··· 397 389 if (obj->ops->release) 398 390 obj->ops->release(obj); 399 391 400 - if (obj->mm.n_placements > 1) 401 - kfree(obj->mm.placements); 402 - 403 392 if (obj->shares_resv_from) 404 393 i915_vm_resv_put(obj->shares_resv_from); 405 394 ··· 446 441 struct drm_i915_private *i915 = to_i915(obj->base.dev); 447 442 448 443 GEM_BUG_ON(i915_gem_object_is_framebuffer(obj)); 444 + 445 + i915_drm_client_remove_object(obj); 449 446 450 447 /* 451 448 * Before we free the object, make sure any pure RCU-only
+12
drivers/gpu/drm/i915/gem/i915_gem_object_types.h
··· 302 302 */ 303 303 struct i915_address_space *shares_resv_from; 304 304 305 + #ifdef CONFIG_PROC_FS 306 + /** 307 + * @client: @i915_drm_client which created the object 308 + */ 309 + struct i915_drm_client *client; 310 + 311 + /** 312 + * @client_link: Link into @i915_drm_client.objects_list 313 + */ 314 + struct list_head client_link; 315 + #endif 316 + 305 317 union { 306 318 struct rcu_head rcu; 307 319 struct llist_node freed;
+21
drivers/gpu/drm/i915/gem/i915_gem_stolen.c
··· 386 386 387 387 drm_dbg(&i915->drm, "GEN6_STOLEN_RESERVED = 0x%016llx\n", reg_val); 388 388 389 + /* Wa_14019821291 */ 390 + if (MEDIA_VER_FULL(i915) == IP_VER(13, 0)) { 391 + /* 392 + * This workaround is primarily implemented by the BIOS. We 393 + * just need to figure out whether the BIOS has applied the 394 + * workaround (meaning the programmed address falls within 395 + * the DSM) and, if so, reserve that part of the DSM to 396 + * prevent accidental reuse. The DSM location should be just 397 + * below the WOPCM. 398 + */ 399 + u64 gscpsmi_base = intel_uncore_read64_2x32(uncore, 400 + MTL_GSCPSMI_BASEADDR_LSB, 401 + MTL_GSCPSMI_BASEADDR_MSB); 402 + if (gscpsmi_base >= i915->dsm.stolen.start && 403 + gscpsmi_base < i915->dsm.stolen.end) { 404 + *base = gscpsmi_base; 405 + *size = i915->dsm.stolen.end - gscpsmi_base; 406 + return; 407 + } 408 + } 409 + 389 410 switch (reg_val & GEN8_STOLEN_RESERVED_SIZE_MASK) { 390 411 case GEN8_STOLEN_RESERVED_1M: 391 412 *size = 1024 * 1024;
+6 -4
drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c
··· 85 85 86 86 static int gtt_set(struct context *ctx, unsigned long offset, u32 v) 87 87 { 88 + intel_wakeref_t wakeref; 88 89 struct i915_vma *vma; 89 90 u32 __iomem *map; 90 91 int err = 0; ··· 100 99 if (IS_ERR(vma)) 101 100 return PTR_ERR(vma); 102 101 103 - intel_gt_pm_get(vma->vm->gt); 102 + wakeref = intel_gt_pm_get(vma->vm->gt); 104 103 105 104 map = i915_vma_pin_iomap(vma); 106 105 i915_vma_unpin(vma); ··· 113 112 i915_vma_unpin_iomap(vma); 114 113 115 114 out_rpm: 116 - intel_gt_pm_put(vma->vm->gt); 115 + intel_gt_pm_put(vma->vm->gt, wakeref); 117 116 return err; 118 117 } 119 118 120 119 static int gtt_get(struct context *ctx, unsigned long offset, u32 *v) 121 120 { 121 + intel_wakeref_t wakeref; 122 122 struct i915_vma *vma; 123 123 u32 __iomem *map; 124 124 int err = 0; ··· 134 132 if (IS_ERR(vma)) 135 133 return PTR_ERR(vma); 136 134 137 - intel_gt_pm_get(vma->vm->gt); 135 + wakeref = intel_gt_pm_get(vma->vm->gt); 138 136 139 137 map = i915_vma_pin_iomap(vma); 140 138 i915_vma_unpin(vma); ··· 147 145 i915_vma_unpin_iomap(vma); 148 146 149 147 out_rpm: 150 - intel_gt_pm_put(vma->vm->gt); 148 + intel_gt_pm_put(vma->vm->gt, wakeref); 151 149 return err; 152 150 } 153 151
+8 -6
drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
··· 630 630 static void disable_retire_worker(struct drm_i915_private *i915) 631 631 { 632 632 i915_gem_driver_unregister__shrinker(i915); 633 - intel_gt_pm_get(to_gt(i915)); 633 + intel_gt_pm_get_untracked(to_gt(i915)); 634 634 cancel_delayed_work_sync(&to_gt(i915)->requests.retire_work); 635 635 } 636 636 637 637 static void restore_retire_worker(struct drm_i915_private *i915) 638 638 { 639 639 igt_flush_test(i915); 640 - intel_gt_pm_put(to_gt(i915)); 640 + intel_gt_pm_put_untracked(to_gt(i915)); 641 641 i915_gem_driver_register__shrinker(i915); 642 642 } 643 643 ··· 778 778 779 779 static int gtt_set(struct drm_i915_gem_object *obj) 780 780 { 781 + intel_wakeref_t wakeref; 781 782 struct i915_vma *vma; 782 783 void __iomem *map; 783 784 int err = 0; ··· 787 786 if (IS_ERR(vma)) 788 787 return PTR_ERR(vma); 789 788 790 - intel_gt_pm_get(vma->vm->gt); 789 + wakeref = intel_gt_pm_get(vma->vm->gt); 791 790 map = i915_vma_pin_iomap(vma); 792 791 i915_vma_unpin(vma); 793 792 if (IS_ERR(map)) { ··· 799 798 i915_vma_unpin_iomap(vma); 800 799 801 800 out: 802 - intel_gt_pm_put(vma->vm->gt); 801 + intel_gt_pm_put(vma->vm->gt, wakeref); 803 802 return err; 804 803 } 805 804 806 805 static int gtt_check(struct drm_i915_gem_object *obj) 807 806 { 807 + intel_wakeref_t wakeref; 808 808 struct i915_vma *vma; 809 809 void __iomem *map; 810 810 int err = 0; ··· 814 812 if (IS_ERR(vma)) 815 813 return PTR_ERR(vma); 816 814 817 - intel_gt_pm_get(vma->vm->gt); 815 + wakeref = intel_gt_pm_get(vma->vm->gt); 818 816 map = i915_vma_pin_iomap(vma); 819 817 i915_vma_unpin(vma); 820 818 if (IS_ERR(map)) { ··· 830 828 i915_vma_unpin_iomap(vma); 831 829 832 830 out: 833 - intel_gt_pm_put(vma->vm->gt); 831 + intel_gt_pm_put(vma->vm->gt, wakeref); 834 832 return err; 835 833 } 836 834
+2 -2
drivers/gpu/drm/i915/gem/selftests/mock_context.c
··· 83 83 int err; 84 84 u32 id; 85 85 86 - pc = proto_context_create(i915, 0); 86 + pc = proto_context_create(fpriv, i915, 0); 87 87 if (IS_ERR(pc)) 88 88 return ERR_CAST(pc); 89 89 ··· 152 152 struct i915_gem_context *ctx; 153 153 struct i915_gem_proto_context *pc; 154 154 155 - pc = proto_context_create(i915, 0); 155 + pc = proto_context_create(NULL, i915, 0); 156 156 if (IS_ERR(pc)) 157 157 return ERR_CAST(pc); 158 158
+43
drivers/gpu/drm/i915/gt/gen8_ppgtt.c
··· 5 5 6 6 #include <linux/log2.h> 7 7 8 + #include "gem/i915_gem_internal.h" 8 9 #include "gem/i915_gem_lmem.h" 9 10 10 11 #include "gen8_ppgtt.h" ··· 222 221 static void gen8_ppgtt_cleanup(struct i915_address_space *vm) 223 222 { 224 223 struct i915_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); 224 + 225 + if (vm->rsvd.obj) 226 + i915_gem_object_put(vm->rsvd.obj); 225 227 226 228 if (intel_vgpu_active(vm->i915)) 227 229 gen8_ppgtt_notify_vgt(ppgtt, false); ··· 954 950 return ERR_PTR(err); 955 951 } 956 952 953 + static int gen8_init_rsvd(struct i915_address_space *vm) 954 + { 955 + struct drm_i915_private *i915 = vm->i915; 956 + struct drm_i915_gem_object *obj; 957 + struct i915_vma *vma; 958 + int ret; 959 + 960 + /* The memory will be used only by GPU. */ 961 + obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 962 + I915_BO_ALLOC_VOLATILE | 963 + I915_BO_ALLOC_GPU_ONLY); 964 + if (IS_ERR(obj)) 965 + obj = i915_gem_object_create_internal(i915, PAGE_SIZE); 966 + if (IS_ERR(obj)) 967 + return PTR_ERR(obj); 968 + 969 + vma = i915_vma_instance(obj, vm, NULL); 970 + if (IS_ERR(vma)) { 971 + ret = PTR_ERR(vma); 972 + goto unref; 973 + } 974 + 975 + ret = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_HIGH); 976 + if (ret) 977 + goto unref; 978 + 979 + vm->rsvd.vma = i915_vma_make_unshrinkable(vma); 980 + vm->rsvd.obj = obj; 981 + vm->total -= vma->node.size; 982 + return 0; 983 + unref: 984 + i915_gem_object_put(obj); 985 + return ret; 986 + } 987 + 957 988 /* 958 989 * GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers 959 990 * with a net effect resembling a 2-level page table in normal x86 terms. Each ··· 1069 1030 1070 1031 if (intel_vgpu_active(gt->i915)) 1071 1032 gen8_ppgtt_notify_vgt(ppgtt, true); 1033 + 1034 + err = gen8_init_rsvd(&ppgtt->vm); 1035 + if (err) 1036 + goto err_put; 1072 1037 1073 1038 return ppgtt; 1074 1039
+9 -4
drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
··· 28 28 29 29 static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) 30 30 { 31 + intel_wakeref_t wakeref; 32 + 31 33 /* 32 34 * Since we are waiting on a request, the GPU should be busy 33 35 * and should have its own rpm reference. 34 36 */ 35 - if (GEM_WARN_ON(!intel_gt_pm_get_if_awake(b->irq_engine->gt))) 37 + wakeref = intel_gt_pm_get_if_awake(b->irq_engine->gt); 38 + if (GEM_WARN_ON(!wakeref)) 36 39 return; 37 40 38 41 /* ··· 44 41 * which we can add a new waiter and avoid the cost of re-enabling 45 42 * the irq. 46 43 */ 47 - WRITE_ONCE(b->irq_armed, true); 44 + WRITE_ONCE(b->irq_armed, wakeref); 48 45 49 46 /* Requests may have completed before we could enable the interrupt. */ 50 47 if (!b->irq_enabled++ && b->irq_enable(b)) ··· 64 61 65 62 static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b) 66 63 { 64 + intel_wakeref_t wakeref = b->irq_armed; 65 + 67 66 GEM_BUG_ON(!b->irq_enabled); 68 67 if (!--b->irq_enabled) 69 68 b->irq_disable(b); 70 69 71 - WRITE_ONCE(b->irq_armed, false); 72 - intel_gt_pm_put_async(b->irq_engine->gt); 70 + WRITE_ONCE(b->irq_armed, 0); 71 + intel_gt_pm_put_async(b->irq_engine->gt, wakeref); 73 72 } 74 73 75 74 static void intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b)
+2 -1
drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h
··· 13 13 #include <linux/types.h> 14 14 15 15 #include "intel_engine_types.h" 16 + #include "intel_wakeref.h" 16 17 17 18 /* 18 19 * Rather than have every client wait upon all user interrupts, ··· 44 43 spinlock_t irq_lock; /* protects the interrupt from hardirq context */ 45 44 struct irq_work irq_work; /* for use from inside irq_lock */ 46 45 unsigned int irq_enabled; 47 - bool irq_armed; 46 + intel_wakeref_t irq_armed; 48 47 49 48 /* Not all breadcrumbs are attached to physical HW */ 50 49 intel_engine_mask_t engine_mask;
+14
drivers/gpu/drm/i915/gt/intel_context.c
··· 6 6 #include "gem/i915_gem_context.h" 7 7 #include "gem/i915_gem_pm.h" 8 8 9 + #include "i915_drm_client.h" 9 10 #include "i915_drv.h" 10 11 #include "i915_trace.h" 11 12 ··· 51 50 52 51 int intel_context_alloc_state(struct intel_context *ce) 53 52 { 53 + struct i915_gem_context *ctx; 54 54 int err = 0; 55 55 56 56 if (mutex_lock_interruptible(&ce->pin_mutex)) ··· 68 66 goto unlock; 69 67 70 68 set_bit(CONTEXT_ALLOC_BIT, &ce->flags); 69 + 70 + rcu_read_lock(); 71 + ctx = rcu_dereference(ce->gem_context); 72 + if (ctx && !kref_get_unless_zero(&ctx->ref)) 73 + ctx = NULL; 74 + rcu_read_unlock(); 75 + if (ctx) { 76 + if (ctx->client) 77 + i915_drm_client_add_context_objects(ctx->client, 78 + ce); 79 + i915_gem_context_put(ctx); 80 + } 71 81 } 72 82 73 83 unlock:
+2 -2
drivers/gpu/drm/i915/gt/intel_context.h
··· 212 212 return; 213 213 214 214 ce->ops->enter(ce); 215 - intel_gt_pm_get(ce->vm->gt); 215 + ce->wakeref = intel_gt_pm_get(ce->vm->gt); 216 216 } 217 217 218 218 static inline void intel_context_mark_active(struct intel_context *ce) ··· 229 229 if (--ce->active_count) 230 230 return; 231 231 232 - intel_gt_pm_put_async(ce->vm->gt); 232 + intel_gt_pm_put_async(ce->vm->gt, ce->wakeref); 233 233 ce->ops->exit(ce); 234 234 } 235 235
+2
drivers/gpu/drm/i915/gt/intel_context_types.h
··· 17 17 #include "i915_utils.h" 18 18 #include "intel_engine_types.h" 19 19 #include "intel_sseu.h" 20 + #include "intel_wakeref.h" 20 21 21 22 #include "uc/intel_guc_fwif.h" 22 23 ··· 113 112 u32 ring_size; 114 113 struct intel_ring *ring; 115 114 struct intel_timeline *timeline; 115 + intel_wakeref_t wakeref; 116 116 117 117 unsigned long flags; 118 118 #define CONTEXT_BARRIER_BIT 0
+1 -1
drivers/gpu/drm/i915/gt/intel_engine_cs.c
··· 47 47 #define GEN9_LR_CONTEXT_RENDER_SIZE (22 * PAGE_SIZE) 48 48 #define GEN11_LR_CONTEXT_RENDER_SIZE (14 * PAGE_SIZE) 49 49 50 - #define GEN8_LR_CONTEXT_OTHER_SIZE ( 2 * PAGE_SIZE) 50 + #define GEN8_LR_CONTEXT_OTHER_SIZE (2 * PAGE_SIZE) 51 51 52 52 #define MAX_MMIO_BASES 3 53 53 struct engine_info {
+1 -1
drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
··· 188 188 * low latency and no jitter] the chance to naturally 189 189 * complete before being preempted. 190 190 */ 191 - attr.priority = 0; 191 + attr.priority = I915_PRIORITY_NORMAL; 192 192 if (rq->sched.attr.priority >= attr.priority) 193 193 attr.priority = I915_PRIORITY_HEARTBEAT; 194 194 if (rq->sched.attr.priority >= attr.priority)
+4 -3
drivers/gpu/drm/i915/gt/intel_engine_pm.c
··· 63 63 64 64 ENGINE_TRACE(engine, "\n"); 65 65 66 - intel_gt_pm_get(engine->gt); 66 + engine->wakeref_track = intel_gt_pm_get(engine->gt); 67 67 68 68 /* Discard stale context state from across idling */ 69 69 ce = engine->kernel_context; ··· 122 122 */ 123 123 GEM_BUG_ON(rq->context->active_count != 1); 124 124 __intel_gt_pm_get(engine->gt); 125 + rq->context->wakeref = intel_wakeref_track(&engine->gt->wakeref); 125 126 126 127 /* 127 128 * We have to serialise all potential retirement paths with our ··· 286 285 engine->park(engine); 287 286 288 287 /* While gt calls i915_vma_parked(), we have to break the lock cycle */ 289 - intel_gt_pm_put_async(engine->gt); 288 + intel_gt_pm_put_async(engine->gt, engine->wakeref_track); 290 289 return 0; 291 290 } 292 291 ··· 297 296 298 297 void intel_engine_init__pm(struct intel_engine_cs *engine) 299 298 { 300 - intel_wakeref_init(&engine->wakeref, engine->i915, &wf_ops); 299 + intel_wakeref_init(&engine->wakeref, engine->i915, &wf_ops, engine->name); 301 300 intel_engine_init_heartbeat(engine); 302 301 303 302 intel_gsc_idle_msg_enable(engine);
+8
drivers/gpu/drm/i915/gt/intel_engine_regs.h
··· 118 118 #define CCID_EXTENDED_STATE_RESTORE BIT(2) 119 119 #define CCID_EXTENDED_STATE_SAVE BIT(3) 120 120 #define RING_BB_PER_CTX_PTR(base) _MMIO((base) + 0x1c0) /* gen8+ */ 121 + #define PER_CTX_BB_FORCE BIT(2) 122 + #define PER_CTX_BB_VALID BIT(0) 123 + 121 124 #define RING_INDIRECT_CTX(base) _MMIO((base) + 0x1c4) /* gen8+ */ 122 125 #define RING_INDIRECT_CTX_OFFSET(base) _MMIO((base) + 0x1c8) /* gen8+ */ 123 126 #define ECOSKPD(base) _MMIO((base) + 0x1d0) 127 + #define XEHP_BLITTER_SCHEDULING_MODE_MASK REG_GENMASK(12, 11) 128 + #define XEHP_BLITTER_ROUND_ROBIN_MODE \ 129 + REG_FIELD_PREP(XEHP_BLITTER_SCHEDULING_MODE_MASK, 1) 124 130 #define ECO_CONSTANT_BUFFER_SR_DISABLE REG_BIT(4) 125 131 #define ECO_GATING_CX_ONLY REG_BIT(3) 126 132 #define GEN6_BLITTER_FBC_NOTIFY REG_BIT(3) ··· 263 257 #define VDBOX_CGCTL3F18(base) _MMIO((base) + 0x3f18) 264 258 #define ALNUNIT_CLKGATE_DIS REG_BIT(13) 265 259 260 + #define VDBOX_CGCTL3F1C(base) _MMIO((base) + 0x3f1c) 261 + #define MFXPIPE_CLKGATE_DIS REG_BIT(3) 266 262 267 263 #endif /* __INTEL_ENGINE_REGS__ */
+2
drivers/gpu/drm/i915/gt/intel_engine_types.h
··· 446 446 unsigned long serial; 447 447 448 448 unsigned long wakeref_serial; 449 + intel_wakeref_t wakeref_track; 449 450 struct intel_wakeref wakeref; 451 + 450 452 struct file *default_state; 451 453 452 454 struct {
+1 -1
drivers/gpu/drm/i915/gt/intel_execlists_submission.c
··· 630 630 execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT); 631 631 if (engine->fw_domain && !--engine->fw_active) 632 632 intel_uncore_forcewake_put(engine->uncore, engine->fw_domain); 633 - intel_gt_pm_put_async(engine->gt); 633 + intel_gt_pm_put_async_untracked(engine->gt); 634 634 635 635 /* 636 636 * If this is part of a virtual engine, its next request may
+12 -11
drivers/gpu/drm/i915/gt/intel_ggtt.c
··· 245 245 gen8_ggtt_invalidate(ggtt); 246 246 247 247 list_for_each_entry(gt, &ggtt->gt_list, ggtt_link) { 248 - if (intel_guc_tlb_invalidation_is_available(&gt->uc.guc)) { 248 + if (intel_guc_tlb_invalidation_is_available(&gt->uc.guc)) 249 249 guc_ggtt_ct_invalidate(gt); 250 - } else if (GRAPHICS_VER(i915) >= 12) { 250 + else if (GRAPHICS_VER(i915) >= 12) 251 251 intel_uncore_write_fw(gt->uncore, 252 252 GEN12_GUC_TLB_INV_CR, 253 253 GEN12_GUC_TLB_INV_CR_INVALIDATE); 254 - } else { 254 + else 255 255 intel_uncore_write_fw(gt->uncore, 256 256 GEN8_GTCR, GEN8_GTCR_INVALIDATE); 257 - } 258 257 } 259 258 } 260 259 ··· 296 297 return intel_gt_is_bind_context_ready(gt); 297 298 } 298 299 299 - static struct intel_context *gen8_ggtt_bind_get_ce(struct i915_ggtt *ggtt) 300 + static struct intel_context *gen8_ggtt_bind_get_ce(struct i915_ggtt *ggtt, intel_wakeref_t *wakeref) 300 301 { 301 302 struct intel_context *ce; 302 303 struct intel_gt *gt = ggtt->vm.gt; ··· 313 314 * would conflict with fs_reclaim trying to allocate memory while 314 315 * doing rpm_resume(). 315 316 */ 316 - if (!intel_gt_pm_get_if_awake(gt)) 317 + *wakeref = intel_gt_pm_get_if_awake(gt); 318 + if (!*wakeref) 317 319 return NULL; 318 320 319 321 intel_engine_pm_get(ce->engine); ··· 322 322 return ce; 323 323 } 324 324 325 - static void gen8_ggtt_bind_put_ce(struct intel_context *ce) 325 + static void gen8_ggtt_bind_put_ce(struct intel_context *ce, intel_wakeref_t wakeref) 326 326 { 327 327 intel_engine_pm_put(ce->engine); 328 - intel_gt_pm_put(ce->engine->gt); 328 + intel_gt_pm_put(ce->engine->gt, wakeref); 329 329 } 330 330 331 331 static bool gen8_ggtt_bind_ptes(struct i915_ggtt *ggtt, u32 offset, ··· 338 338 struct sgt_iter iter; 339 339 struct i915_request *rq; 340 340 struct intel_context *ce; 341 + intel_wakeref_t wakeref; 341 342 u32 *cs; 342 343 343 344 if (!num_entries) 344 345 return true; 345 346 346 - ce = gen8_ggtt_bind_get_ce(ggtt); 347 + ce = gen8_ggtt_bind_get_ce(ggtt, &wakeref); 347 348 if (!ce) 348 349 return false; 349 350 ··· 420 419 offset += n_ptes; 421 420 } 422 421 423 - gen8_ggtt_bind_put_ce(ce); 422 + gen8_ggtt_bind_put_ce(ce, wakeref); 424 423 return true; 425 424 426 425 err_rq: 427 426 i915_request_put(rq); 428 427 put_ce: 429 - gen8_ggtt_bind_put_ce(ce); 428 + gen8_ggtt_bind_put_ce(ce, wakeref); 430 429 return false; 431 430 } 432 431
+1 -1
drivers/gpu/drm/i915/gt/intel_gt.c
··· 451 451 452 452 spin_lock_irqsave(&uncore->lock, flags); 453 453 intel_uncore_posting_read_fw(uncore, 454 - RING_HEAD(RENDER_RING_BASE)); 454 + RING_TAIL(RENDER_RING_BASE)); 455 455 spin_unlock_irqrestore(&uncore->lock, flags); 456 456 } 457 457 }
+9
drivers/gpu/drm/i915/gt/intel_gt.h
··· 82 82 ##__VA_ARGS__); \ 83 83 } while (0) 84 84 85 + #define NEEDS_FASTCOLOR_BLT_WABB(engine) ( \ 86 + IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 55), IP_VER(12, 71)) && \ 87 + engine->class == COPY_ENGINE_CLASS && engine->instance == 0) 88 + 85 89 static inline bool gt_is_root(struct intel_gt *gt) 86 90 { 87 91 return !gt->info.id; ··· 116 112 static inline struct intel_gt *gsc_to_gt(struct intel_gsc *gsc) 117 113 { 118 114 return container_of(gsc, struct intel_gt, gsc); 115 + } 116 + 117 + static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) 118 + { 119 + return guc_to_gt(guc)->i915; 119 120 } 120 121 121 122 void intel_gt_common_init_early(struct intel_gt *gt);
+1 -2
drivers/gpu/drm/i915/gt/intel_gt_mcr.c
··· 388 388 * registers. This wakeref will be released in the unlock 389 389 * routine. 390 390 * 391 - * This is expected to become a formally documented/numbered 392 - * workaround soon. 391 + * Wa_22018931422 393 392 */ 394 393 intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_GT); 395 394
+8 -6
drivers/gpu/drm/i915/gt/intel_gt_pm.c
··· 28 28 static void user_forcewake(struct intel_gt *gt, bool suspend) 29 29 { 30 30 int count = atomic_read(&gt->user_wakeref); 31 + intel_wakeref_t wakeref; 31 32 32 33 /* Inside suspend/resume so single threaded, no races to worry about. */ 33 34 if (likely(!count)) 34 35 return; 35 36 36 - intel_gt_pm_get(gt); 37 + wakeref = intel_gt_pm_get(gt); 37 38 if (suspend) { 38 39 GEM_BUG_ON(count > atomic_read(&gt->wakeref.count)); 39 40 atomic_sub(count, &gt->wakeref.count); 40 41 } else { 41 42 atomic_add(count, &gt->wakeref.count); 42 43 } 43 - intel_gt_pm_put(gt); 44 + intel_gt_pm_put(gt, wakeref); 44 45 } 45 46 46 47 static void runtime_begin(struct intel_gt *gt) ··· 139 138 * runtime_pm is per-device rather than per-tile, so this is still the 140 139 * correct structure. 141 140 */ 142 - intel_wakeref_init(&gt->wakeref, gt->i915, &wf_ops); 141 + intel_wakeref_init(&gt->wakeref, gt->i915, &wf_ops, "GT"); 143 142 seqcount_mutex_init(&gt->stats.lock, &gt->wakeref.mutex); 144 143 } 145 144 ··· 168 167 enum intel_engine_id id; 169 168 intel_wakeref_t wakeref; 170 169 171 - GT_TRACE(gt, "force:%s", str_yes_no(force)); 170 + GT_TRACE(gt, "force:%s\n", str_yes_no(force)); 172 171 173 172 /* Use a raw wakeref to avoid calling intel_display_power_get early */ 174 173 wakeref = intel_runtime_pm_get(gt->uncore->rpm); ··· 237 236 { 238 237 struct intel_engine_cs *engine; 239 238 enum intel_engine_id id; 239 + intel_wakeref_t wakeref; 240 240 int err; 241 241 242 242 err = intel_gt_has_unrecoverable_error(gt); ··· 254 252 */ 255 253 gt_sanitize(gt, true); 256 254 257 - intel_gt_pm_get(gt); 255 + wakeref = intel_gt_pm_get(gt); 258 256 259 257 intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL); 260 258 intel_rc6_sanitize(&gt->rc6); ··· 297 295 298 296 out_fw: 299 297 intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); 300 - intel_gt_pm_put(gt); 298 + intel_gt_pm_put(gt, wakeref); 301 299 intel_gt_bind_context_set_ready(gt); 302 300 return err; 303 301
+29 -9
drivers/gpu/drm/i915/gt/intel_gt_pm.h
··· 16 16 return intel_wakeref_is_active(&gt->wakeref); 17 17 } 18 18 19 - static inline void intel_gt_pm_get(struct intel_gt *gt) 19 + static inline void intel_gt_pm_get_untracked(struct intel_gt *gt) 20 20 { 21 21 intel_wakeref_get(&gt->wakeref); 22 + } 23 + 24 + static inline intel_wakeref_t intel_gt_pm_get(struct intel_gt *gt) 25 + { 26 + intel_gt_pm_get_untracked(gt); 27 + return intel_wakeref_track(&gt->wakeref); 22 28 } 23 29 24 30 static inline void __intel_gt_pm_get(struct intel_gt *gt) ··· 32 26 __intel_wakeref_get(&gt->wakeref); 33 27 } 34 28 35 - static inline bool intel_gt_pm_get_if_awake(struct intel_gt *gt) 29 + static inline intel_wakeref_t intel_gt_pm_get_if_awake(struct intel_gt *gt) 36 30 { 37 - return intel_wakeref_get_if_active(&gt->wakeref); 31 + if (!intel_wakeref_get_if_active(&gt->wakeref)) 32 + return 0; 33 + 34 + return intel_wakeref_track(&gt->wakeref); 38 35 } 39 36 40 37 static inline void intel_gt_pm_might_get(struct intel_gt *gt) ··· 45 36 intel_wakeref_might_get(&gt->wakeref); 46 37 } 47 38 48 - static inline void intel_gt_pm_put(struct intel_gt *gt) 39 + static inline void intel_gt_pm_put_untracked(struct intel_gt *gt) 49 40 { 50 41 intel_wakeref_put(&gt->wakeref); 51 42 } 52 43 53 - static inline void intel_gt_pm_put_async(struct intel_gt *gt) 44 + static inline void intel_gt_pm_put(struct intel_gt *gt, intel_wakeref_t handle) 45 + { 46 + intel_wakeref_untrack(&gt->wakeref, handle); 47 + intel_gt_pm_put_untracked(gt); 48 + } 49 + 50 + static inline void intel_gt_pm_put_async_untracked(struct intel_gt *gt) 54 51 { 55 52 intel_wakeref_put_async(&gt->wakeref); 56 53 } ··· 66 51 intel_wakeref_might_put(&gt->wakeref); 67 52 } 68 53 69 - #define with_intel_gt_pm(gt, tmp) \ 70 - for (tmp = 1, intel_gt_pm_get(gt); tmp; \ 71 - intel_gt_pm_put(gt), tmp = 0) 54 + static inline void intel_gt_pm_put_async(struct intel_gt *gt, intel_wakeref_t handle) 55 + { 56 + intel_wakeref_untrack(&gt->wakeref, handle); 57 + intel_gt_pm_put_async_untracked(gt); 58 + } 59 + 60 + #define with_intel_gt_pm(gt, wf) \ 61 + for (wf = intel_gt_pm_get(gt); wf; intel_gt_pm_put(gt, wf), wf = 0) 72 62 73 63 /** 74 64 * with_intel_gt_pm_if_awake - if GT is PM awake, get a reference to prevent ··· 84 64 * @wf: pointer to a temporary wakeref. 85 65 */ 86 66 #define with_intel_gt_pm_if_awake(gt, wf) \ 87 - for (wf = intel_gt_pm_get_if_awake(gt); wf; intel_gt_pm_put_async(gt), wf = 0) 67 + for (wf = intel_gt_pm_get_if_awake(gt); wf; intel_gt_pm_put_async(gt, wf), wf = 0) 88 68 89 69 static inline int intel_gt_pm_wait_for_idle(struct intel_gt *gt) 90 70 {
+2 -2
drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c
··· 27 27 void intel_gt_pm_debugfs_forcewake_user_open(struct intel_gt *gt) 28 28 { 29 29 atomic_inc(&gt->user_wakeref); 30 - intel_gt_pm_get(gt); 30 + intel_gt_pm_get_untracked(gt); 31 31 if (GRAPHICS_VER(gt->i915) >= 6) 32 32 intel_uncore_forcewake_user_get(gt->uncore); 33 33 } ··· 36 36 { 37 37 if (GRAPHICS_VER(gt->i915) >= 6) 38 38 intel_uncore_forcewake_user_put(gt->uncore); 39 - intel_gt_pm_put(gt); 39 + intel_gt_pm_put_untracked(gt); 40 40 atomic_dec(&gt->user_wakeref); 41 41 } 42 42
+3
drivers/gpu/drm/i915/gt/intel_gt_regs.h
··· 537 537 #define XEHP_SQCM MCR_REG(0x8724) 538 538 #define EN_32B_ACCESS REG_BIT(30) 539 539 540 + #define MTL_GSCPSMI_BASEADDR_LSB _MMIO(0x880c) 541 + #define MTL_GSCPSMI_BASEADDR_MSB _MMIO(0x8810) 542 + 540 543 #define HSW_IDICR _MMIO(0x9008) 541 544 #define IDIHASHMSK(x) (((x) & 0x3f) << 16) 542 545
+26
drivers/gpu/drm/i915/gt/intel_gtt.c
··· 63 63 if (!IS_ERR(obj)) { 64 64 obj->base.resv = i915_vm_resv_get(vm); 65 65 obj->shares_resv_from = vm; 66 + 67 + if (vm->fpriv) 68 + i915_drm_client_add_object(vm->fpriv->client, obj); 66 69 } 67 70 68 71 return obj; ··· 87 84 if (!IS_ERR(obj)) { 88 85 obj->base.resv = i915_vm_resv_get(vm); 89 86 obj->shares_resv_from = vm; 87 + 88 + if (vm->fpriv) 89 + i915_drm_client_add_object(vm->fpriv->client, obj); 90 90 } 91 91 92 92 return obj; ··· 101 95 void *vaddr; 102 96 103 97 type = intel_gt_coherent_map_type(vm->gt, obj, true); 98 + /* 99 + * FIXME: It is suspected that some Address Translation Service (ATS) 100 + * issue on IOMMU is causing CAT errors to occur on some MTL workloads. 101 + * Applying a write barrier to the ppgtt set entry functions appeared 102 + * to have no effect, so we must temporarily use I915_MAP_WC here on 103 + * MTL until a proper ATS solution is found. 104 + */ 105 + if (IS_METEORLAKE(vm->i915)) 106 + type = I915_MAP_WC; 107 + 104 108 vaddr = i915_gem_object_pin_map_unlocked(obj, type); 105 109 if (IS_ERR(vaddr)) 106 110 return PTR_ERR(vaddr); ··· 125 109 void *vaddr; 126 110 127 111 type = intel_gt_coherent_map_type(vm->gt, obj, true); 112 + /* 113 + * FIXME: It is suspected that some Address Translation Service (ATS) 114 + * issue on IOMMU is causing CAT errors to occur on some MTL workloads. 115 + * Applying a write barrier to the ppgtt set entry functions appeared 116 + * to have no effect, so we must temporarily use I915_MAP_WC here on 117 + * MTL until a proper ATS solution is found. 118 + */ 119 + if (IS_METEORLAKE(vm->i915)) 120 + type = I915_MAP_WC; 121 + 128 122 vaddr = i915_gem_object_pin_map(obj, type); 129 123 if (IS_ERR(vaddr)) 130 124 return PTR_ERR(vaddr);
+5
drivers/gpu/drm/i915/gt/intel_gtt.h
··· 249 249 struct work_struct release_work; 250 250 251 251 struct drm_mm mm; 252 + struct { 253 + struct drm_i915_gem_object *obj; 254 + struct i915_vma *vma; 255 + } rsvd; 252 256 struct intel_gt *gt; 253 257 struct drm_i915_private *i915; 258 + struct drm_i915_file_private *fpriv; 254 259 struct device *dma; 255 260 u64 total; /* size addr space maps (ex. 2GB for ggtt) */ 256 261 u64 reserved; /* size addr space reserved */
+97 -3
drivers/gpu/drm/i915/gt/intel_lrc.c
··· 829 829 } 830 830 831 831 static void 832 + lrc_setup_bb_per_ctx(u32 *regs, 833 + const struct intel_engine_cs *engine, 834 + u32 ctx_bb_ggtt_addr) 835 + { 836 + GEM_BUG_ON(lrc_ring_wa_bb_per_ctx(engine) == -1); 837 + regs[lrc_ring_wa_bb_per_ctx(engine) + 1] = 838 + ctx_bb_ggtt_addr | 839 + PER_CTX_BB_FORCE | 840 + PER_CTX_BB_VALID; 841 + } 842 + 843 + static void 832 844 lrc_setup_indirect_ctx(u32 *regs, 833 845 const struct intel_engine_cs *engine, 834 846 u32 ctx_bb_ggtt_addr, ··· 1032 1020 return PAGE_SIZE * ce->wa_bb_page; 1033 1021 } 1034 1022 1035 - static u32 *context_indirect_bb(const struct intel_context *ce) 1023 + /* 1024 + * per_ctx below determines which WABB section is used. 1025 + * When true, the function returns the location of the 1026 + * PER_CTX_BB. When false, the function returns the 1027 + * location of the INDIRECT_CTX. 1028 + */ 1029 + static u32 *context_wabb(const struct intel_context *ce, bool per_ctx) 1036 1030 { 1037 1031 void *ptr; 1038 1032 ··· 1047 1029 ptr = ce->lrc_reg_state; 1048 1030 ptr -= LRC_STATE_OFFSET; /* back to start of context image */ 1049 1031 ptr += context_wa_bb_offset(ce); 1032 + ptr += per_ctx ? PAGE_SIZE : 0; 1050 1033 1051 1034 return ptr; 1052 1035 } ··· 1124 1105 1125 1106 if (GRAPHICS_VER(engine->i915) >= 12) { 1126 1107 ce->wa_bb_page = context_size / PAGE_SIZE; 1127 - context_size += PAGE_SIZE; 1108 + /* INDIRECT_CTX and PER_CTX_BB need separate pages. */ 1109 + context_size += PAGE_SIZE * 2; 1128 1110 } 1129 1111 1130 1112 if (intel_context_is_parent(ce) && intel_engine_uses_guc(engine)) { ··· 1427 1407 return gen12_emit_aux_table_inv(ce->engine, cs); 1428 1408 } 1429 1409 1410 + static u32 *xehp_emit_fastcolor_blt_wabb(const struct intel_context *ce, u32 *cs) 1411 + { 1412 + struct intel_gt *gt = ce->engine->gt; 1413 + int mocs = gt->mocs.uc_index << 1; 1414 + 1415 + /** 1416 + * Wa_16018031267 / Wa_16018063123 requires that SW forces the 1417 + * main copy engine arbitration into round robin mode. We 1418 + * additionally need to submit the following WABB blt command 1419 + * to produce 4 subblits with each subblit generating 0 byte 1420 + * write requests as WABB: 1421 + * 1422 + * XY_FASTCOLOR_BLT 1423 + * BG0 -> 5100000E 1424 + * BG1 -> 0000003F (Dest pitch) 1425 + * BG2 -> 00000000 (X1, Y1) = (0, 0) 1426 + * BG3 -> 00040001 (X2, Y2) = (1, 4) 1427 + * BG4 -> scratch 1428 + * BG5 -> scratch 1429 + * BG6-12 -> 00000000 1430 + * BG13 -> 20004004 (Surf. Width= 2,Surf. Height = 5 ) 1431 + * BG14 -> 00000010 (Qpitch = 4) 1432 + * BG15 -> 00000000 1433 + */ 1434 + *cs++ = XY_FAST_COLOR_BLT_CMD | (16 - 2); 1435 + *cs++ = FIELD_PREP(XY_FAST_COLOR_BLT_MOCS_MASK, mocs) | 0x3f; 1436 + *cs++ = 0; 1437 + *cs++ = 4 << 16 | 1; 1438 + *cs++ = lower_32_bits(i915_vma_offset(ce->vm->rsvd.vma)); 1439 + *cs++ = upper_32_bits(i915_vma_offset(ce->vm->rsvd.vma)); 1440 + *cs++ = 0; 1441 + *cs++ = 0; 1442 + *cs++ = 0; 1443 + *cs++ = 0; 1444 + *cs++ = 0; 1445 + *cs++ = 0; 1446 + *cs++ = 0; 1447 + *cs++ = 0x20004004; 1448 + *cs++ = 0x10; 1449 + *cs++ = 0; 1450 + 1451 + return cs; 1452 + } 1453 + 1454 + static u32 * 1455 + xehp_emit_per_ctx_bb(const struct intel_context *ce, u32 *cs) 1456 + { 1457 + /* Wa_16018031267, Wa_16018063123 */ 1458 + if (NEEDS_FASTCOLOR_BLT_WABB(ce->engine)) 1459 + cs = xehp_emit_fastcolor_blt_wabb(ce, cs); 1460 + 1461 + return cs; 1462 + } 1463 + 1464 + static void 1465 + setup_per_ctx_bb(const struct intel_context *ce, 1466 + const struct intel_engine_cs *engine, 1467 + u32 *(*emit)(const struct intel_context *, u32 *)) 1468 + { 1469 + /* Place PER_CTX_BB on next page after INDIRECT_CTX */ 1470 + u32 * const start = context_wabb(ce, true); 1471 + u32 *cs; 1472 + 1473 + cs = emit(ce, start); 1474 + 1475 + /* PER_CTX_BB must manually terminate */ 1476 + *cs++ = MI_BATCH_BUFFER_END; 1477 + 1478 + GEM_BUG_ON(cs - start > I915_GTT_PAGE_SIZE / sizeof(*cs)); 1479 + lrc_setup_bb_per_ctx(ce->lrc_reg_state, engine, 1480 + lrc_indirect_bb(ce) + PAGE_SIZE); 1481 + } 1482 + 1430 1483 static void 1431 1484 setup_indirect_ctx_bb(const struct intel_context *ce, 1432 1485 const struct intel_engine_cs *engine, 1433 1486 u32 *(*emit)(const struct intel_context *, u32 *)) 1434 1487 { 1435 - u32 * const start = context_indirect_bb(ce); 1488 + u32 * const start = context_wabb(ce, false); 1436 1489 u32 *cs; 1437 1490 1438 1491 cs = emit(ce, start); ··· 1604 1511 /* Mutually exclusive wrt to global indirect bb */ 1605 1512 GEM_BUG_ON(engine->wa_ctx.indirect_ctx.size); 1606 1513 setup_indirect_ctx_bb(ce, engine, fn); 1514 + setup_per_ctx_bb(ce, engine, xehp_emit_per_ctx_bb); 1607 1515 } 1608 1516 1609 1517 return lrc_descriptor(ce) | CTX_DESC_FORCE_RESTORE;
+1 -1
drivers/gpu/drm/i915/gt/intel_reset.c
··· 1293 1293 if (msg) 1294 1294 drm_notice(&engine->i915->drm, 1295 1295 "Resetting %s for %s\n", engine->name, msg); 1296 - atomic_inc(&engine->i915->gpu_error.reset_engine_count[engine->uabi_class]); 1296 + i915_increase_reset_engine_count(&engine->i915->gpu_error, engine); 1297 1297 1298 1298 ret = intel_gt_reset_engine(engine); 1299 1299 if (ret) {
+3 -4
drivers/gpu/drm/i915/gt/intel_sseu.c
··· 849 849 const struct sseu_dev_info *sseu, 850 850 struct drm_printer *p) 851 851 { 852 - if (sseu->max_slices == 0) { 852 + if (sseu->max_slices == 0) 853 853 drm_printf(p, "Unavailable\n"); 854 - } else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) { 854 + else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) 855 855 sseu_print_xehp_topology(sseu, p); 856 - } else { 856 + else 857 857 sseu_print_hsw_topology(sseu, p); 858 - } 859 858 } 860 859 861 860 void intel_sseu_print_ss_info(const char *type,
+25 -13
drivers/gpu/drm/i915/gt/intel_workarounds.c
··· 1663 1663 } 1664 1664 1665 1665 static void 1666 + wa_16021867713(struct intel_gt *gt, struct i915_wa_list *wal) 1667 + { 1668 + struct intel_engine_cs *engine; 1669 + int id; 1670 + 1671 + for_each_engine(engine, gt, id) 1672 + if (engine->class == VIDEO_DECODE_CLASS) 1673 + wa_write_or(wal, VDBOX_CGCTL3F1C(engine->mmio_base), 1674 + MFXPIPE_CLKGATE_DIS); 1675 + } 1676 + 1677 + static void 1666 1678 xelpmp_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) 1667 1679 { 1680 + wa_16021867713(gt, wal); 1681 + 1668 1682 /* 1669 1683 * Wa_14018778641 1670 1684 * Wa_18018781329 ··· 1687 1673 * GT, the media GT's versions are regular singleton registers. 1688 1674 */ 1689 1675 wa_write_or(wal, XELPMP_GSC_MOD_CTRL, FORCE_MISS_FTLB); 1676 + 1677 + /* Wa_22016670082 */ 1678 + wa_write_or(wal, GEN12_SQCNT1, GEN12_STRICT_RAR_ENABLE); 1690 1679 1691 1680 debug_dump_steering(gt); 1692 1681 } ··· 2357 2340 0, true); 2358 2341 } 2359 2342 2360 - if (IS_DG2_G11(i915) || IS_DG2_G10(i915)) { 2361 - /* Wa_22014600077:dg2 */ 2362 - wa_mcr_add(wal, GEN10_CACHE_MODE_SS, 0, 2363 - _MASKED_BIT_ENABLE(ENABLE_EU_COUNT_FOR_TDL_FLUSH), 2364 - 0 /* Wa_14012342262 write-only reg, so skip verification */, 2365 - true); 2366 - } 2367 - 2368 2343 if (IS_DG2(i915) || IS_ALDERLAKE_P(i915) || IS_ALDERLAKE_S(i915) || 2369 2344 IS_DG1(i915) || IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915)) { 2370 2345 /* ··· 2791 2782 RING_SEMA_WAIT_POLL(engine->mmio_base), 2792 2783 1); 2793 2784 } 2785 + /* Wa_16018031267, Wa_16018063123 */ 2786 + if (NEEDS_FASTCOLOR_BLT_WABB(engine)) 2787 + wa_masked_field_set(wal, ECOSKPD(engine->mmio_base), 2788 + XEHP_BLITTER_SCHEDULING_MODE_MASK, 2789 + XEHP_BLITTER_ROUND_ROBIN_MODE); 2794 2790 } 2795 2791 2796 2792 static void ··· 2929 2915 * Wa_22015475538:dg2 2930 2916 */ 2931 2917 wa_mcr_write_or(wal, LSC_CHICKEN_BIT_0_UDW, DIS_CHAIN_2XSIMD8); 2918 + 2919 + /* Wa_18028616096 */ 2920 + wa_mcr_write_or(wal, LSC_CHICKEN_BIT_0_UDW, UGM_FRAGMENT_THRESHOLD_TO_3); 2932 2921 } 2933 2922 2934 2923 if (IS_DG2_G11(i915)) { ··· 2958 2941 _MASKED_BIT_ENABLE(ENABLE_PREFETCH_INTO_IC), 2959 2942 0 /* write-only, so skip validation */, 2960 2943 true); 2961 - } 2962 - 2963 - if (IS_DG2_G10(i915) || IS_DG2_G12(i915)) { 2964 - /* Wa_18028616096 */ 2965 - wa_mcr_write_or(wal, LSC_CHICKEN_BIT_0_UDW, UGM_FRAGMENT_THRESHOLD_TO_3); 2966 2944 } 2967 2945 2968 2946 if (IS_XEHPSDV(i915)) {
+12 -8
drivers/gpu/drm/i915/gt/selftest_engine_cs.c
··· 21 21 return *a - *b; 22 22 } 23 23 24 - static void perf_begin(struct intel_gt *gt) 24 + static intel_wakeref_t perf_begin(struct intel_gt *gt) 25 25 { 26 - intel_gt_pm_get(gt); 26 + intel_wakeref_t wakeref = intel_gt_pm_get(gt); 27 27 28 28 /* Boost gpufreq to max [waitboost] and keep it fixed */ 29 29 atomic_inc(&gt->rps.num_waiters); 30 30 queue_work(gt->i915->unordered_wq, &gt->rps.work); 31 31 flush_work(&gt->rps.work); 32 + 33 + return wakeref; 32 34 } 33 35 34 - static int perf_end(struct intel_gt *gt) 36 + static int perf_end(struct intel_gt *gt, intel_wakeref_t wakeref) 35 37 { 36 38 atomic_dec(&gt->rps.num_waiters); 37 - intel_gt_pm_put(gt); 39 + intel_gt_pm_put(gt, wakeref); 38 40 39 41 return igt_flush_test(gt->i915); 40 42 } ··· 135 133 struct intel_gt *gt = arg; 136 134 struct intel_engine_cs *engine; 137 135 enum intel_engine_id id; 136 + intel_wakeref_t wakeref; 138 137 int err = 0; 139 138 140 139 if (GRAPHICS_VER(gt->i915) < 4) /* Any CS_TIMESTAMP? */ 141 140 return 0; 142 141 143 - perf_begin(gt); 142 + wakeref = perf_begin(gt); 144 143 for_each_engine(engine, gt, id) { 145 144 struct intel_context *ce = engine->kernel_context; 146 145 struct i915_vma *batch; ··· 210 207 pr_info("%s: MI_BB_START cycles: %u\n", 211 208 engine->name, trifilter(cycles)); 212 209 } 213 - if (perf_end(gt)) 210 + if (perf_end(gt, wakeref)) 214 211 err = -EIO; 215 212 216 213 return err; ··· 263 260 struct intel_gt *gt = arg; 264 261 struct intel_engine_cs *engine; 265 262 enum intel_engine_id id; 263 + intel_wakeref_t wakeref; 266 264 int err = 0; 267 265 268 266 if (GRAPHICS_VER(gt->i915) < 4) /* Any CS_TIMESTAMP? */ 269 267 return 0; 270 268 271 - perf_begin(gt); 269 + wakeref = perf_begin(gt); 272 270 for_each_engine(engine, gt, id) { 273 271 struct intel_context *ce = engine->kernel_context; 274 272 struct i915_vma *base, *nop; ··· 368 364 pr_info("%s: 16K MI_NOOP cycles: %u\n", 369 365 engine->name, trifilter(cycles)); 370 366 } 371 - if (perf_end(gt)) 367 + if (perf_end(gt, wakeref)) 372 368 err = -EIO; 373 369 374 370 return err;
+1 -1
drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c
··· 84 84 85 85 static void pulse_unlock_wait(struct pulse *p) 86 86 { 87 - i915_active_unlock_wait(&p->active); 87 + wait_var_event_timeout(&p->active, i915_active_is_idle(&p->active), HZ); 88 88 } 89 89 90 90 static int __live_idle_pulse(struct intel_engine_cs *engine,
+3 -2
drivers/gpu/drm/i915/gt/selftest_gt_pm.c
··· 81 81 struct intel_gt *gt = arg; 82 82 struct intel_engine_cs *engine; 83 83 enum intel_engine_id id; 84 + intel_wakeref_t wakeref; 84 85 int err = 0; 85 86 86 87 if (!gt->clock_frequency) { /* unknown */ ··· 92 91 if (GRAPHICS_VER(gt->i915) < 4) /* Any CS_TIMESTAMP? */ 93 92 return 0; 94 93 95 - intel_gt_pm_get(gt); 94 + wakeref = intel_gt_pm_get(gt); 96 95 intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL); 97 96 98 97 for_each_engine(engine, gt, id) { ··· 129 128 } 130 129 131 130 intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); 132 - intel_gt_pm_put(gt); 131 + intel_gt_pm_put(gt, wakeref); 133 132 134 133 return err; 135 134 }
+48 -19
drivers/gpu/drm/i915/gt/selftest_lrc.c
··· 1555 1555 return err; 1556 1556 } 1557 1557 1558 - static int indirect_ctx_submit_req(struct intel_context *ce) 1558 + static int wabb_ctx_submit_req(struct intel_context *ce) 1559 1559 { 1560 1560 struct i915_request *rq; 1561 1561 int err = 0; ··· 1579 1579 #define CTX_BB_CANARY_INDEX (CTX_BB_CANARY_OFFSET / sizeof(u32)) 1580 1580 1581 1581 static u32 * 1582 - emit_indirect_ctx_bb_canary(const struct intel_context *ce, u32 *cs) 1582 + emit_wabb_ctx_canary(const struct intel_context *ce, 1583 + u32 *cs, bool per_ctx) 1583 1584 { 1584 1585 *cs++ = MI_STORE_REGISTER_MEM_GEN8 | 1585 1586 MI_SRM_LRM_GLOBAL_GTT | ··· 1588 1587 *cs++ = i915_mmio_reg_offset(RING_START(0)); 1589 1588 *cs++ = i915_ggtt_offset(ce->state) + 1590 1589 context_wa_bb_offset(ce) + 1591 - CTX_BB_CANARY_OFFSET; 1590 + CTX_BB_CANARY_OFFSET + 1591 + (per_ctx ? PAGE_SIZE : 0); 1592 1592 *cs++ = 0; 1593 1593 1594 1594 return cs; 1595 1595 } 1596 1596 1597 - static void 1598 - indirect_ctx_bb_setup(struct intel_context *ce) 1597 + static u32 * 1598 + emit_indirect_ctx_bb_canary(const struct intel_context *ce, u32 *cs) 1599 1599 { 1600 - u32 *cs = context_indirect_bb(ce); 1600 + return emit_wabb_ctx_canary(ce, cs, false); 1601 + } 1602 + 1603 + static u32 * 1604 + emit_per_ctx_bb_canary(const struct intel_context *ce, u32 *cs) 1605 + { 1606 + return emit_wabb_ctx_canary(ce, cs, true); 1607 + } 1608 + 1609 + static void 1610 + wabb_ctx_setup(struct intel_context *ce, bool per_ctx) 1611 + { 1612 + u32 *cs = context_wabb(ce, per_ctx); 1601 1613 1602 1614 cs[CTX_BB_CANARY_INDEX] = 0xdeadf00d; 1603 1615 1604 - setup_indirect_ctx_bb(ce, ce->engine, emit_indirect_ctx_bb_canary); 1616 + if (per_ctx) 1617 + setup_per_ctx_bb(ce, ce->engine, emit_per_ctx_bb_canary); 1618 + else 1619 + setup_indirect_ctx_bb(ce, ce->engine, emit_indirect_ctx_bb_canary); 1605 1620 } 1606 1621 1607 - static bool check_ring_start(struct intel_context *ce) 1622 + static bool check_ring_start(struct intel_context *ce, bool per_ctx) 1608 1623 { 1609 1624 const u32 * const ctx_bb = (void *)(ce->lrc_reg_state) - 1610 - LRC_STATE_OFFSET + context_wa_bb_offset(ce); 1625 + LRC_STATE_OFFSET + context_wa_bb_offset(ce) + 1626 + (per_ctx ? PAGE_SIZE : 0); 1611 1627 1612 1628 if (ctx_bb[CTX_BB_CANARY_INDEX] == ce->lrc_reg_state[CTX_RING_START]) 1613 1629 return true; ··· 1636 1618 return false; 1637 1619 } 1638 1620 1639 - static int indirect_ctx_bb_check(struct intel_context *ce) 1621 + static int wabb_ctx_check(struct intel_context *ce, bool per_ctx) 1640 1622 { 1641 1623 int err; 1642 1624 1643 - err = indirect_ctx_submit_req(ce); 1625 + err = wabb_ctx_submit_req(ce); 1644 1626 if (err) 1645 1627 return err; 1646 1628 1647 - if (!check_ring_start(ce)) 1629 + if (!check_ring_start(ce, per_ctx)) 1648 1630 return -EINVAL; 1649 1631 1650 1632 return 0; 1651 1633 } 1652 1634 1653 - static int __live_lrc_indirect_ctx_bb(struct intel_engine_cs *engine) 1635 + static int __lrc_wabb_ctx(struct intel_engine_cs *engine, bool per_ctx) 1654 1636 { 1655 1637 struct intel_context *a, *b; 1656 1638 int err; ··· 1685 1667 * As ring start is restored apriori of starting the indirect ctx bb and 1686 1668 * as it will be different for each context, it fits to this purpose. 1687 1669 */ 1688 - indirect_ctx_bb_setup(a); 1689 - indirect_ctx_bb_setup(b); 1670 + wabb_ctx_setup(a, per_ctx); 1671 + wabb_ctx_setup(b, per_ctx); 1690 1672 1691 - err = indirect_ctx_bb_check(a); 1673 + err = wabb_ctx_check(a, per_ctx); 1692 1674 if (err) 1693 1675 goto unpin_b; 1694 1676 1695 - err = indirect_ctx_bb_check(b); 1677 + err = wabb_ctx_check(b, per_ctx); 1696 1678 1697 1679 unpin_b: 1698 1680 intel_context_unpin(b); ··· 1706 1688 return err; 1707 1689 } 1708 1690 1709 - static int live_lrc_indirect_ctx_bb(void *arg) 1691 + static int lrc_wabb_ctx(void *arg, bool per_ctx) 1710 1692 { 1711 1693 struct intel_gt *gt = arg; 1712 1694 struct intel_engine_cs *engine; ··· 1715 1697 1716 1698 for_each_engine(engine, gt, id) { 1717 1699 intel_engine_pm_get(engine); 1718 - err = __live_lrc_indirect_ctx_bb(engine); 1700 + err = __lrc_wabb_ctx(engine, per_ctx); 1719 1701 intel_engine_pm_put(engine); 1720 1702 1721 1703 if (igt_flush_test(gt->i915)) ··· 1726 1708 } 1727 1709 1728 1710 return err; 1711 + } 1712 + 1713 + static int live_lrc_indirect_ctx_bb(void *arg) 1714 + { 1715 + return lrc_wabb_ctx(arg, false); 1716 + } 1717 + 1718 + static int live_lrc_per_ctx_bb(void *arg) 1719 + { 1720 + return lrc_wabb_ctx(arg, true); 1729 1721 } 1730 1722 1731 1723 static void garbage_reset(struct intel_engine_cs *engine, ··· 1975 1947 SUBTEST(live_lrc_garbage), 1976 1948 SUBTEST(live_pphwsp_runtime), 1977 1949 SUBTEST(live_lrc_indirect_ctx_bb), 1950 + SUBTEST(live_lrc_per_ctx_bb), 1978 1951 }; 1979 1952 1980 1953 if (!HAS_LOGICAL_RING_CONTEXTS(i915))
+6 -4
drivers/gpu/drm/i915/gt/selftest_reset.c
··· 261 261 { 262 262 struct intel_gt *gt = arg; 263 263 const typeof(*igt_atomic_phases) *p; 264 + intel_wakeref_t wakeref; 264 265 int err = 0; 265 266 266 267 /* Check that the resets are usable from atomic context */ 267 268 268 - intel_gt_pm_get(gt); 269 + wakeref = intel_gt_pm_get(gt); 269 270 igt_global_reset_lock(gt); 270 271 271 272 /* Flush any requests before we get started and check basics */ ··· 297 296 298 297 unlock: 299 298 igt_global_reset_unlock(gt); 300 - intel_gt_pm_put(gt); 299 + intel_gt_pm_put(gt, wakeref); 301 300 302 301 return err; 303 302 } ··· 308 307 const typeof(*igt_atomic_phases) *p; 309 308 struct intel_engine_cs *engine; 310 309 enum intel_engine_id id; 310 + intel_wakeref_t wakeref; 311 311 int err = 0; 312 312 313 313 /* Check that the resets are usable from atomic context */ ··· 319 317 if (intel_uc_uses_guc_submission(&gt->uc)) 320 318 return 0; 321 319 322 - intel_gt_pm_get(gt); 320 + wakeref = intel_gt_pm_get(gt); 323 321 igt_global_reset_lock(gt); 324 322 325 323 /* Flush any requests before we get started and check basics */ ··· 367 365 368 366 out_unlock: 369 367 igt_global_reset_unlock(gt); 370 - intel_gt_pm_put(gt); 368 + intel_gt_pm_put(gt, wakeref); 371 369 372 370 return err; 373 371 }
+10 -7
drivers/gpu/drm/i915/gt/selftest_rps.c
··· 224 224 struct intel_engine_cs *engine; 225 225 enum intel_engine_id id; 226 226 struct igt_spinner spin; 227 + intel_wakeref_t wakeref; 227 228 int err = 0; 228 229 229 230 if (!intel_rps_is_enabled(rps) || GRAPHICS_VER(gt->i915) < 6) ··· 237 236 saved_work = rps->work.func; 238 237 rps->work.func = dummy_rps_work; 239 238 240 - intel_gt_pm_get(gt); 239 + wakeref = intel_gt_pm_get(gt); 241 240 intel_rps_disable(&gt->rps); 242 241 243 242 intel_gt_check_clock_frequency(gt); ··· 356 355 } 357 356 358 357 intel_rps_enable(&gt->rps); 359 - intel_gt_pm_put(gt); 358 + intel_gt_pm_put(gt, wakeref); 360 359 361 360 igt_spinner_fini(&spin); 362 361 ··· 377 376 struct intel_engine_cs *engine; 378 377 enum intel_engine_id id; 379 378 struct igt_spinner spin; 379 + intel_wakeref_t wakeref; 380 380 int err = 0; 381 381 382 382 /* ··· 400 398 saved_work = rps->work.func; 401 399 rps->work.func = dummy_rps_work; 402 400 403 - intel_gt_pm_get(gt); 401 + wakeref = intel_gt_pm_get(gt); 404 402 for_each_engine(engine, gt, id) { 405 403 struct i915_request *rq; 406 404 ktime_t min_dt, max_dt; ··· 490 488 break; 491 489 } 492 490 } 493 - intel_gt_pm_put(gt); 491 + intel_gt_pm_put(gt, wakeref); 494 492 495 493 igt_spinner_fini(&spin); 496 494 ··· 1025 1023 struct intel_engine_cs *engine; 1026 1024 enum intel_engine_id id; 1027 1025 struct igt_spinner spin; 1026 + intel_wakeref_t wakeref; 1028 1027 u32 pm_events; 1029 1028 int err = 0; 1030 1029 ··· 1036 1033 if (!intel_rps_has_interrupts(rps) || GRAPHICS_VER(gt->i915) < 6) 1037 1034 return 0; 1038 1035 1039 - intel_gt_pm_get(gt); 1040 - pm_events = rps->pm_events; 1041 - intel_gt_pm_put(gt); 1036 + pm_events = 0; 1037 + with_intel_gt_pm(gt, wakeref) 1038 + pm_events = rps->pm_events; 1042 1039 if (!pm_events) { 1043 1040 pr_err("No RPS PM events registered, but RPS is enabled?\n"); 1044 1041 return -ENODEV;
+3 -2
drivers/gpu/drm/i915/gt/selftest_slpc.c
··· 266 266 struct intel_rps *rps = &gt->rps; 267 267 struct intel_engine_cs *engine; 268 268 enum intel_engine_id id; 269 + intel_wakeref_t wakeref; 269 270 struct igt_spinner spin; 270 271 u32 slpc_min_freq, slpc_max_freq; 271 272 int err = 0; ··· 312 311 } 313 312 314 313 intel_gt_pm_wait_for_idle(gt); 315 - intel_gt_pm_get(gt); 314 + wakeref = intel_gt_pm_get(gt); 316 315 for_each_engine(engine, gt, id) { 317 316 struct i915_request *rq; 318 317 u32 max_act_freq; ··· 398 397 if (igt_flush_test(gt->i915)) 399 398 err = -EIO; 400 399 401 - intel_gt_pm_put(gt); 400 + intel_gt_pm_put(gt, wakeref); 402 401 igt_spinner_fini(&spin); 403 402 intel_gt_pm_wait_for_idle(gt); 404 403
+2
drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c
··· 322 322 gsc->proxy.component = data; 323 323 gsc->proxy.component->mei_dev = mei_kdev; 324 324 mutex_unlock(&gsc->proxy.mutex); 325 + gt_dbg(gt, "GSC proxy mei component bound\n"); 325 326 326 327 return 0; 327 328 } ··· 343 342 with_intel_runtime_pm(&i915->runtime_pm, wakeref) 344 343 intel_uncore_rmw(gt->uncore, HECI_H_CSR(MTL_GSC_HECI2_BASE), 345 344 HECI_H_CSR_IE | HECI_H_CSR_RST, 0); 345 + gt_dbg(gt, "GSC proxy mei component unbound\n"); 346 346 } 347 347 348 348 static const struct component_ops i915_gsc_proxy_component_ops = {
+1 -1
drivers/gpu/drm/i915/gt/uc/intel_guc.c
··· 330 330 331 331 static u32 guc_ctl_devid(struct intel_guc *guc) 332 332 { 333 - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; 333 + struct drm_i915_private *i915 = guc_to_i915(guc); 334 334 335 335 return (INTEL_DEVID(i915) << 16) | INTEL_REVID(i915); 336 336 }
+4
drivers/gpu/drm/i915/gt/uc/intel_guc.h
··· 297 297 * @number_guc_id_stolen: The number of guc_ids that have been stolen 298 298 */ 299 299 int number_guc_id_stolen; 300 + /** 301 + * @fast_response_selftest: Backdoor to CT handler for fast response selftest 302 + */ 303 + u32 fast_response_selftest; 300 304 #endif 301 305 }; 302 306
+1 -1
drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
··· 355 355 static const struct __guc_mmio_reg_descr_group * 356 356 guc_capture_get_device_reglist(struct intel_guc *guc) 357 357 { 358 - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; 358 + struct drm_i915_private *i915 = guc_to_i915(guc); 359 359 const struct __guc_mmio_reg_descr_group *lists; 360 360 361 361 if (GRAPHICS_VER(i915) >= 12)
+10 -1
drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
··· 265 265 u32 *cmds; 266 266 int err; 267 267 268 - err = i915_inject_probe_error(guc_to_gt(guc)->i915, -ENXIO); 268 + err = i915_inject_probe_error(guc_to_i915(guc), -ENXIO); 269 269 if (err) 270 270 return err; 271 271 ··· 1076 1076 found = true; 1077 1077 break; 1078 1078 } 1079 + 1080 + #ifdef CONFIG_DRM_I915_SELFTEST 1081 + if (!found && ct_to_guc(ct)->fast_response_selftest) { 1082 + CT_DEBUG(ct, "Assuming unsolicited response due to FAST_REQUEST selftest\n"); 1083 + ct_to_guc(ct)->fast_response_selftest++; 1084 + found = true; 1085 + } 1086 + #endif 1087 + 1079 1088 if (!found) { 1080 1089 CT_ERROR(ct, "Unsolicited response message: len %u, data %#x (fence %u, last %u)\n", 1081 1090 len, hxg[0], fence, ct->requests.last_fence);
+5 -5
drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
··· 520 520 static int guc_log_relay_create(struct intel_guc_log *log) 521 521 { 522 522 struct intel_guc *guc = log_to_guc(log); 523 - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; 523 + struct drm_i915_private *i915 = guc_to_i915(guc); 524 524 struct rchan *guc_log_relay_chan; 525 525 size_t n_subbufs, subbuf_size; 526 526 int ret; ··· 573 573 static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) 574 574 { 575 575 struct intel_guc *guc = log_to_guc(log); 576 - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; 576 + struct drm_i915_private *i915 = guc_to_i915(guc); 577 577 intel_wakeref_t wakeref; 578 578 579 579 _guc_log_copy_debuglogs_for_relay(log); ··· 589 589 static u32 __get_default_log_level(struct intel_guc_log *log) 590 590 { 591 591 struct intel_guc *guc = log_to_guc(log); 592 - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; 592 + struct drm_i915_private *i915 = guc_to_i915(guc); 593 593 594 594 /* A negative value means "use platform/config default" */ 595 595 if (i915->params.guc_log_level < 0) { ··· 664 664 int intel_guc_log_set_level(struct intel_guc_log *log, u32 level) 665 665 { 666 666 struct intel_guc *guc = log_to_guc(log); 667 - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; 667 + struct drm_i915_private *i915 = guc_to_i915(guc); 668 668 intel_wakeref_t wakeref; 669 669 int ret = 0; 670 670 ··· 796 796 static void guc_log_relay_stop(struct intel_guc_log *log) 797 797 { 798 798 struct intel_guc *guc = log_to_guc(log); 799 - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; 799 + struct drm_i915_private *i915 = guc_to_i915(guc); 800 800 801 801 if (!log->relay.started) 802 802 return;
+1 -1
drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
··· 14 14 { 15 15 /* GuC RC is unavailable for pre-Gen12 */ 16 16 return guc->submission_supported && 17 - GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12; 17 + GRAPHICS_VER(guc_to_i915(guc)) >= 12; 18 18 } 19 19 20 20 static bool __guc_rc_selected(struct intel_guc *guc)
+1 -1
drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
··· 34 34 { 35 35 /* GuC SLPC is unavailable for pre-Gen12 */ 36 36 return guc->submission_supported && 37 - GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12; 37 + GRAPHICS_VER(guc_to_i915(guc)) >= 12; 38 38 } 39 39 40 40 static bool __guc_slpc_selected(struct intel_guc *guc)
+13 -10
drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
··· 1107 1107 if (deregister) 1108 1108 guc_signal_context_fence(ce); 1109 1109 if (destroyed) { 1110 - intel_gt_pm_put_async(guc_to_gt(guc)); 1110 + intel_gt_pm_put_async_untracked(guc_to_gt(guc)); 1111 1111 release_guc_id(guc, ce); 1112 1112 __guc_context_destroy(ce); 1113 1113 } ··· 1303 1303 unsigned long flags; 1304 1304 u32 reset_count; 1305 1305 bool in_reset; 1306 + intel_wakeref_t wakeref; 1306 1307 1307 1308 spin_lock_irqsave(&guc->timestamp.lock, flags); 1308 1309 ··· 1326 1325 * start_gt_clk is derived from GuC state. To get a consistent 1327 1326 * view of activity, we query the GuC state only if gt is awake. 1328 1327 */ 1329 - if (!in_reset && intel_gt_pm_get_if_awake(gt)) { 1328 + wakeref = in_reset ? 0 : intel_gt_pm_get_if_awake(gt); 1329 + if (wakeref) { 1330 1330 stats_saved = *stats; 1331 1331 gt_stamp_saved = guc->timestamp.gt_stamp; 1332 1332 /* ··· 1336 1334 */ 1337 1335 guc_update_engine_gt_clks(engine); 1338 1336 guc_update_pm_timestamp(guc, now); 1339 - intel_gt_pm_put_async(gt); 1337 + intel_gt_pm_put_async(gt, wakeref); 1340 1338 if (i915_reset_count(gpu_error) != reset_count) { 1341 1339 *stats = stats_saved; 1342 1340 guc->timestamp.gt_stamp = gt_stamp_saved; ··· 3387 3385 struct intel_guc *guc = container_of(w, struct intel_guc, 3388 3386 submission_state.destroyed_worker); 3389 3387 struct intel_gt *gt = guc_to_gt(guc); 3390 - int tmp; 3388 + intel_wakeref_t wakeref; 3391 3389 3392 - with_intel_gt_pm(gt, tmp) 3390 + with_intel_gt_pm(gt, wakeref) 3393 3391 deregister_destroyed_contexts(guc); 3394 3392 } 3395 3393 ··· 4626 4624 { 4627 4625 /* GuC submission is unavailable for pre-Gen11 */ 4628 4626 return intel_guc_is_supported(guc) && 4629 - GRAPHICS_VER(guc_to_gt(guc)->i915) >= 11; 4627 + GRAPHICS_VER(guc_to_i915(guc)) >= 11; 4630 4628 } 4631 4629 4632 4630 static bool __guc_submission_selected(struct intel_guc *guc) 4633 4631 { 4634 - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; 4632 + struct drm_i915_private *i915 = guc_to_i915(guc); 4635 4633 4636 4634 if (!intel_guc_submission_is_supported(guc)) 4637 4635 return false; ··· 4896 4894 intel_context_put(ce); 4897 4895 } else if (context_destroyed(ce)) { 4898 4896 /* Context has been destroyed */ 4899 - intel_gt_pm_put_async(guc_to_gt(guc)); 4897 + intel_gt_pm_put_async_untracked(guc_to_gt(guc)); 4900 4898 release_guc_id(guc, ce); 4901 4899 __guc_context_destroy(ce); 4902 4900 } ··· 5003 5001 if (match) { 5004 5002 intel_engine_set_hung_context(e, ce); 5005 5003 engine_mask |= e->mask; 5006 - atomic_inc(&i915->gpu_error.reset_engine_count[e->uabi_class]); 5004 + i915_increase_reset_engine_count(&i915->gpu_error, 5005 + e); 5007 5006 } 5008 5007 } 5009 5008 ··· 5016 5013 } else { 5017 5014 intel_engine_set_hung_context(ce->engine, ce); 5018 5015 engine_mask = ce->engine->mask; 5019 - atomic_inc(&i915->gpu_error.reset_engine_count[ce->engine->uabi_class]); 5016 + i915_increase_reset_engine_count(&i915->gpu_error, ce->engine); 5020 5017 } 5021 5018 5022 5019 with_intel_runtime_pm(&i915->runtime_pm, wakeref)
-5
drivers/gpu/drm/i915/gt/uc/intel_uc.c
··· 106 106 gt_info(gt, "Incompatible option enable_guc=%d - %s\n", 107 107 i915->params.enable_guc, "GuC is not supported!"); 108 108 109 - if (i915->params.enable_guc & ENABLE_GUC_LOAD_HUC && 110 - !intel_uc_supports_huc(uc)) 111 - gt_info(gt, "Incompatible option enable_guc=%d - %s\n", 112 - i915->params.enable_guc, "HuC is not supported!"); 113 - 114 109 if (i915->params.enable_guc & ENABLE_GUC_SUBMISSION && 115 110 !intel_uc_supports_guc_submission(uc)) 116 111 gt_info(gt, "Incompatible option enable_guc=%d - %s\n",
+115
drivers/gpu/drm/i915/gt/uc/selftest_guc.c
··· 286 286 return ret; 287 287 } 288 288 289 + /* 290 + * Send a context schedule H2G message with an invalid context id. 291 + * This should generate a GUC_RESULT_INVALID_CONTEXT response. 292 + */ 293 + static int bad_h2g(struct intel_guc *guc) 294 + { 295 + u32 action[] = { 296 + INTEL_GUC_ACTION_SCHED_CONTEXT, 297 + 0x12345678, 298 + }; 299 + 300 + return intel_guc_send_nb(guc, action, ARRAY_SIZE(action), 0); 301 + } 302 + 303 + /* 304 + * Set a spinner running to make sure the system is alive and active, 305 + * then send a bad but asynchronous H2G command and wait to see if an 306 + * error response is returned. If no response is received or if the 307 + * spinner dies then the test will fail. 308 + */ 309 + #define FAST_RESPONSE_TIMEOUT_MS 1000 310 + static int intel_guc_fast_request(void *arg) 311 + { 312 + struct intel_gt *gt = arg; 313 + struct intel_context *ce; 314 + struct igt_spinner spin; 315 + struct i915_request *rq; 316 + intel_wakeref_t wakeref; 317 + struct intel_engine_cs *engine = intel_selftest_find_any_engine(gt); 318 + bool spinning = false; 319 + int ret = 0; 320 + 321 + if (!engine) 322 + return 0; 323 + 324 + wakeref = intel_runtime_pm_get(gt->uncore->rpm); 325 + 326 + ce = intel_context_create(engine); 327 + if (IS_ERR(ce)) { 328 + ret = PTR_ERR(ce); 329 + gt_err(gt, "Failed to create spinner request: %pe\n", ce); 330 + goto err_pm; 331 + } 332 + 333 + ret = igt_spinner_init(&spin, engine->gt); 334 + if (ret) { 335 + gt_err(gt, "Failed to create spinner: %pe\n", ERR_PTR(ret)); 336 + goto err_pm; 337 + } 338 + spinning = true; 339 + 340 + rq = igt_spinner_create_request(&spin, ce, MI_ARB_CHECK); 341 + intel_context_put(ce); 342 + if (IS_ERR(rq)) { 343 + ret = PTR_ERR(rq); 344 + gt_err(gt, "Failed to create spinner request: %pe\n", rq); 345 + goto err_spin; 346 + } 347 + 348 + ret = request_add_spin(rq, &spin); 349 + if (ret) { 350 + gt_err(gt, "Failed to add Spinner request: %pe\n", ERR_PTR(ret)); 351 + goto err_rq; 352 + } 353 + 354 + gt->uc.guc.fast_response_selftest = 1; 355 + 356 + ret = bad_h2g(&gt->uc.guc); 357 + if (ret) { 358 + gt_err(gt, "Failed to send H2G: %pe\n", ERR_PTR(ret)); 359 + goto err_rq; 360 + } 361 + 362 + ret = wait_for(gt->uc.guc.fast_response_selftest != 1 || i915_request_completed(rq), 363 + FAST_RESPONSE_TIMEOUT_MS); 364 + if (ret) { 365 + gt_err(gt, "Request wait failed: %pe\n", ERR_PTR(ret)); 366 + goto err_rq; 367 + } 368 + 369 + if (i915_request_completed(rq)) { 370 + gt_err(gt, "Spinner died waiting for fast request error!\n"); 371 + ret = -EIO; 372 + goto err_rq; 373 + } 374 + 375 + if (gt->uc.guc.fast_response_selftest != 2) { 376 + gt_err(gt, "Unexpected fast response count: %d\n", 377 + gt->uc.guc.fast_response_selftest); 378 + goto err_rq; 379 + } 380 + 381 + igt_spinner_end(&spin); 382 + spinning = false; 383 + 384 + ret = intel_selftest_wait_for_rq(rq); 385 + if (ret) { 386 + gt_err(gt, "Request failed to complete: %pe\n", ERR_PTR(ret)); 387 + goto err_rq; 388 + } 389 + 390 + err_rq: 391 + i915_request_put(rq); 392 + 393 + err_spin: 394 + if (spinning) 395 + igt_spinner_end(&spin); 396 + igt_spinner_fini(&spin); 397 + 398 + err_pm: 399 + intel_runtime_pm_put(gt->uncore->rpm, wakeref); 400 + return ret; 401 + } 402 + 289 403 int intel_guc_live_selftests(struct drm_i915_private *i915) 290 404 { 291 405 static const struct i915_subtest tests[] = { 292 406 SUBTEST(intel_guc_scrub_ctbs), 293 407 SUBTEST(intel_guc_steal_guc_ids), 408 + SUBTEST(intel_guc_fast_request), 294 409 }; 295 410 struct intel_gt *gt = to_gt(i915); 296 411
+1 -1
drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c
··· 74 74 goto err; 75 75 } 76 76 77 - rq = igt_spinner_create_request(&spin, ce, MI_NOOP); 77 + rq = igt_spinner_create_request(&spin, ce, MI_ARB_CHECK); 78 78 intel_context_put(ce); 79 79 if (IS_ERR(rq)) { 80 80 ret = PTR_ERR(rq);
+3 -105
drivers/gpu/drm/i915/i915_debugfs.c
··· 51 51 #include "i915_debugfs.h" 52 52 #include "i915_debugfs_params.h" 53 53 #include "i915_driver.h" 54 + #include "i915_gpu_error.h" 54 55 #include "i915_irq.h" 55 56 #include "i915_reg.h" 56 57 #include "i915_scheduler.h" ··· 299 298 300 299 return 0; 301 300 } 302 - 303 - #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) 304 - static ssize_t gpu_state_read(struct file *file, char __user *ubuf, 305 - size_t count, loff_t *pos) 306 - { 307 - struct i915_gpu_coredump *error; 308 - ssize_t ret; 309 - void *buf; 310 - 311 - error = file->private_data; 312 - if (!error) 313 - return 0; 314 - 315 - /* Bounce buffer required because of kernfs __user API convenience. */ 316 - buf = kmalloc(count, GFP_KERNEL); 317 - if (!buf) 318 - return -ENOMEM; 319 - 320 - ret = i915_gpu_coredump_copy_to_buffer(error, buf, *pos, count); 321 - if (ret <= 0) 322 - goto out; 323 - 324 - if (!copy_to_user(ubuf, buf, ret)) 325 - *pos += ret; 326 - else 327 - ret = -EFAULT; 328 - 329 - out: 330 - kfree(buf); 331 - return ret; 332 - } 333 - 334 - static int gpu_state_release(struct inode *inode, struct file *file) 335 - { 336 - i915_gpu_coredump_put(file->private_data); 337 - return 0; 338 - } 339 - 340 - static int i915_gpu_info_open(struct inode *inode, struct file *file) 341 - { 342 - struct drm_i915_private *i915 = inode->i_private; 343 - struct i915_gpu_coredump *gpu; 344 - intel_wakeref_t wakeref; 345 - 346 - gpu = NULL; 347 - with_intel_runtime_pm(&i915->runtime_pm, wakeref) 348 - gpu = i915_gpu_coredump(to_gt(i915), ALL_ENGINES, CORE_DUMP_FLAG_NONE); 349 - 350 - if (IS_ERR(gpu)) 351 - return PTR_ERR(gpu); 352 - 353 - file->private_data = gpu; 354 - return 0; 355 - } 356 - 357 - static const struct file_operations i915_gpu_info_fops = { 358 - .owner = THIS_MODULE, 359 - .open = i915_gpu_info_open, 360 - .read = gpu_state_read, 361 - .llseek = default_llseek, 362 - .release = gpu_state_release, 363 - }; 364 - 365 - static ssize_t 366 - i915_error_state_write(struct file *filp, 367 - const char __user *ubuf, 368 - size_t cnt, 369 - loff_t *ppos) 370 - { 371 - struct i915_gpu_coredump *error = filp->private_data; 372 - 373 - if (!error) 374 - return 0; 375 - 376 - drm_dbg(&error->i915->drm, "Resetting error state\n"); 377 - i915_reset_error_state(error->i915); 378 - 379 - return cnt; 380 - } 381 - 382 - static int i915_error_state_open(struct inode *inode, struct file *file) 383 - { 384 - struct i915_gpu_coredump *error; 385 - 386 - error = i915_first_error_state(inode->i_private); 387 - if (IS_ERR(error)) 388 - return PTR_ERR(error); 389 - 390 - file->private_data = error; 391 - return 0; 392 - } 393 - 394 - static const struct file_operations i915_error_state_fops = { 395 - .owner = THIS_MODULE, 396 - .open = i915_error_state_open, 397 - .read = gpu_state_read, 398 - .write = i915_error_state_write, 399 - .llseek = default_llseek, 400 - .release = gpu_state_release, 401 - }; 402 - #endif 403 301 404 302 static int i915_frequency_info(struct seq_file *m, void *unused) 405 303 { ··· 739 839 {"i915_perf_noa_delay", &i915_perf_noa_delay_fops}, 740 840 {"i915_wedged", &i915_wedged_fops}, 741 841 {"i915_gem_drop_caches", &i915_drop_caches_fops}, 742 - #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) 743 - {"i915_error_state", &i915_error_state_fops}, 744 - {"i915_gpu_info", &i915_gpu_info_fops}, 745 - #endif 746 842 }; 747 843 748 844 void i915_debugfs_register(struct drm_i915_private *dev_priv) ··· 761 865 drm_debugfs_create_files(i915_debugfs_list, 762 866 ARRAY_SIZE(i915_debugfs_list), 763 867 minor->debugfs_root, minor); 868 + 869 + i915_gpu_error_debugfs_register(dev_priv); 764 870 }
+4 -2
drivers/gpu/drm/i915/i915_driver.c
··· 798 798 if (ret) 799 799 goto out_cleanup_modeset2; 800 800 801 - intel_pxp_init(i915); 801 + ret = intel_pxp_init(i915); 802 + if (ret != -ENODEV) 803 + drm_dbg(&i915->drm, "pxp init failed with %d\n", ret); 802 804 803 805 ret = intel_display_driver_probe(i915); 804 806 if (ret) ··· 1035 1033 intel_power_domains_driver_remove(i915); 1036 1034 enable_rpm_wakeref_asserts(&i915->runtime_pm); 1037 1035 1038 - intel_runtime_pm_driver_release(&i915->runtime_pm); 1036 + intel_runtime_pm_driver_last_release(&i915->runtime_pm); 1039 1037 } 1040 1038 1041 1039 static bool suspend_to_idle(struct drm_i915_private *dev_priv)
+108
drivers/gpu/drm/i915/i915_drm_client.c
··· 28 28 kref_init(&client->kref); 29 29 spin_lock_init(&client->ctx_lock); 30 30 INIT_LIST_HEAD(&client->ctx_list); 31 + #ifdef CONFIG_PROC_FS 32 + spin_lock_init(&client->objects_lock); 33 + INIT_LIST_HEAD(&client->objects_list); 34 + #endif 31 35 32 36 return client; 33 37 } ··· 45 41 } 46 42 47 43 #ifdef CONFIG_PROC_FS 44 + static void 45 + obj_meminfo(struct drm_i915_gem_object *obj, 46 + struct drm_memory_stats stats[INTEL_REGION_UNKNOWN]) 47 + { 48 + const enum intel_region_id id = obj->mm.region ? 49 + obj->mm.region->id : INTEL_REGION_SMEM; 50 + const u64 sz = obj->base.size; 51 + 52 + if (obj->base.handle_count > 1) 53 + stats[id].shared += sz; 54 + else 55 + stats[id].private += sz; 56 + 57 + if (i915_gem_object_has_pages(obj)) { 58 + stats[id].resident += sz; 59 + 60 + if (!dma_resv_test_signaled(obj->base.resv, 61 + DMA_RESV_USAGE_BOOKKEEP)) 62 + stats[id].active += sz; 63 + else if (i915_gem_object_is_shrinkable(obj) && 64 + obj->mm.madv == I915_MADV_DONTNEED) 65 + stats[id].purgeable += sz; 66 + } 67 + } 68 + 69 + static void show_meminfo(struct drm_printer *p, struct drm_file *file) 70 + { 71 + struct drm_memory_stats stats[INTEL_REGION_UNKNOWN] = {}; 72 + struct drm_i915_file_private *fpriv = file->driver_priv; 73 + struct i915_drm_client *client = fpriv->client; 74 + struct drm_i915_private *i915 = fpriv->i915; 75 + struct drm_i915_gem_object *obj; 76 + struct intel_memory_region *mr; 77 + struct list_head __rcu *pos; 78 + unsigned int id; 79 + 80 + /* Public objects. */ 81 + spin_lock(&file->table_lock); 82 + idr_for_each_entry(&file->object_idr, obj, id) 83 + obj_meminfo(obj, stats); 84 + spin_unlock(&file->table_lock); 85 + 86 + /* Internal objects. */ 87 + rcu_read_lock(); 88 + list_for_each_rcu(pos, &client->objects_list) { 89 + obj = i915_gem_object_get_rcu(list_entry(pos, typeof(*obj), 90 + client_link)); 91 + if (!obj) 92 + continue; 93 + obj_meminfo(obj, stats); 94 + i915_gem_object_put(obj); 95 + } 96 + rcu_read_unlock(); 97 + 98 + for_each_memory_region(mr, i915, id) 99 + drm_print_memory_stats(p, 100 + &stats[id], 101 + DRM_GEM_OBJECT_RESIDENT | 102 + DRM_GEM_OBJECT_PURGEABLE, 103 + mr->uabi_name); 104 + } 105 + 48 106 static const char * const uabi_class_names[] = { 49 107 [I915_ENGINE_CLASS_RENDER] = "render", 50 108 [I915_ENGINE_CLASS_COPY] = "copy", ··· 168 102 * ****************************************************************** 169 103 */ 170 104 105 + show_meminfo(p, file); 106 + 171 107 if (GRAPHICS_VER(i915) < 8) 172 108 return; 173 109 174 110 for (i = 0; i < ARRAY_SIZE(uabi_class_names); i++) 175 111 show_client_class(p, i915, file_priv->client, i); 112 + } 113 + 114 + void i915_drm_client_add_object(struct i915_drm_client *client, 115 + struct drm_i915_gem_object *obj) 116 + { 117 + unsigned long flags; 118 + 119 + GEM_WARN_ON(obj->client); 120 + GEM_WARN_ON(!list_empty(&obj->client_link)); 121 + 122 + spin_lock_irqsave(&client->objects_lock, flags); 123 + obj->client = i915_drm_client_get(client); 124 + list_add_tail_rcu(&obj->client_link, &client->objects_list); 125 + spin_unlock_irqrestore(&client->objects_lock, flags); 126 + } 127 + 128 + void i915_drm_client_remove_object(struct drm_i915_gem_object *obj) 129 + { 130 + struct i915_drm_client *client = fetch_and_zero(&obj->client); 131 + unsigned long flags; 132 + 133 + /* Object may not be associated with a client. */ 134 + if (!client) 135 + return; 136 + 137 + spin_lock_irqsave(&client->objects_lock, flags); 138 + list_del_rcu(&obj->client_link); 139 + spin_unlock_irqrestore(&client->objects_lock, flags); 140 + 141 + i915_drm_client_put(client); 142 + } 143 + 144 + void i915_drm_client_add_context_objects(struct i915_drm_client *client, 145 + struct intel_context *ce) 146 + { 147 + if (ce->state) 148 + i915_drm_client_add_object(client, ce->state->obj); 149 + 150 + if (ce->ring != ce->engine->legacy.ring && ce->ring->vma) 151 + i915_drm_client_add_object(client, ce->ring->vma->obj); 176 152 } 177 153 #endif
+42
drivers/gpu/drm/i915/i915_drm_client.h
··· 12 12 13 13 #include <uapi/drm/i915_drm.h> 14 14 15 + #include "i915_file_private.h" 16 + #include "gem/i915_gem_object_types.h" 17 + #include "gt/intel_context_types.h" 18 + 15 19 #define I915_LAST_UABI_ENGINE_CLASS I915_ENGINE_CLASS_COMPUTE 16 20 17 21 struct drm_file; ··· 28 24 29 25 spinlock_t ctx_lock; /* For add/remove from ctx_list. */ 30 26 struct list_head ctx_list; /* List of contexts belonging to client. */ 27 + 28 + #ifdef CONFIG_PROC_FS 29 + /** 30 + * @objects_lock: lock protecting @objects_list 31 + */ 32 + spinlock_t objects_lock; 33 + 34 + /** 35 + * @objects_list: list of objects created by this client 36 + * 37 + * Protected by @objects_lock. 38 + */ 39 + struct list_head objects_list; 40 + #endif 31 41 32 42 /** 33 43 * @past_runtime: Accumulation of pphwsp runtimes from closed contexts. ··· 66 48 struct i915_drm_client *i915_drm_client_alloc(void); 67 49 68 50 void i915_drm_client_fdinfo(struct drm_printer *p, struct drm_file *file); 51 + 52 + #ifdef CONFIG_PROC_FS 53 + void i915_drm_client_add_object(struct i915_drm_client *client, 54 + struct drm_i915_gem_object *obj); 55 + void i915_drm_client_remove_object(struct drm_i915_gem_object *obj); 56 + void i915_drm_client_add_context_objects(struct i915_drm_client *client, 57 + struct intel_context *ce); 58 + #else 59 + static inline void i915_drm_client_add_object(struct i915_drm_client *client, 60 + struct drm_i915_gem_object *obj) 61 + { 62 + } 63 + 64 + static inline void 65 + i915_drm_client_remove_object(struct drm_i915_gem_object *obj) 66 + { 67 + } 68 + 69 + static inline void 70 + i915_drm_client_add_context_objects(struct i915_drm_client *client, 71 + struct intel_context *ce) 72 + { 73 + } 74 + #endif 69 75 70 76 #endif /* !__I915_DRM_CLIENT_H__ */
+188 -6
drivers/gpu/drm/i915/i915_gpu_error.c
··· 57 57 #include "i915_memcpy.h" 58 58 #include "i915_reg.h" 59 59 #include "i915_scatterlist.h" 60 + #include "i915_sysfs.h" 60 61 #include "i915_utils.h" 61 62 62 63 #define ALLOW_FAIL (__GFP_KSWAPD_RECLAIM | __GFP_RETRY_MAYFAIL | __GFP_NOWARN) ··· 521 520 return NULL; 522 521 } 523 522 524 - struct i915_vma_coredump * 523 + static struct i915_vma_coredump * 525 524 intel_gpu_error_find_batch(const struct intel_engine_coredump *ee) 526 525 { 527 526 return __find_vma(ee->vma, "batch"); ··· 610 609 va_end(args); 611 610 } 612 611 613 - void intel_gpu_error_print_vma(struct drm_i915_error_state_buf *m, 614 - const struct intel_engine_cs *engine, 615 - const struct i915_vma_coredump *vma) 612 + static void intel_gpu_error_print_vma(struct drm_i915_error_state_buf *m, 613 + const struct intel_engine_cs *engine, 614 + const struct i915_vma_coredump *vma) 616 615 { 617 616 char out[ASCII85_BUFSZ]; 618 617 struct page *page; ··· 2141 2140 return error; 2142 2141 } 2143 2142 2144 - struct i915_gpu_coredump * 2143 + static struct i915_gpu_coredump * 2145 2144 i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 dump_flags) 2146 2145 { 2147 2146 static DEFINE_MUTEX(capture_mutex); ··· 2212 2211 i915_gpu_coredump_put(error); 2213 2212 } 2214 2213 2215 - struct i915_gpu_coredump * 2214 + static struct i915_gpu_coredump * 2216 2215 i915_first_error_state(struct drm_i915_private *i915) 2217 2216 { 2218 2217 struct i915_gpu_coredump *error; ··· 2379 2378 drm_info(&i915->drm, "[Capture/%d.%d] Dumped %zd bytes\n", l_count, line++, pos_err); 2380 2379 } 2381 2380 #endif 2381 + 2382 + static ssize_t gpu_state_read(struct file *file, char __user *ubuf, 2383 + size_t count, loff_t *pos) 2384 + { 2385 + struct i915_gpu_coredump *error; 2386 + ssize_t ret; 2387 + void *buf; 2388 + 2389 + error = file->private_data; 2390 + if (!error) 2391 + return 0; 2392 + 2393 + /* Bounce buffer required because of kernfs __user API convenience. */ 2394 + buf = kmalloc(count, GFP_KERNEL); 2395 + if (!buf) 2396 + return -ENOMEM; 2397 + 2398 + ret = i915_gpu_coredump_copy_to_buffer(error, buf, *pos, count); 2399 + if (ret <= 0) 2400 + goto out; 2401 + 2402 + if (!copy_to_user(ubuf, buf, ret)) 2403 + *pos += ret; 2404 + else 2405 + ret = -EFAULT; 2406 + 2407 + out: 2408 + kfree(buf); 2409 + return ret; 2410 + } 2411 + 2412 + static int gpu_state_release(struct inode *inode, struct file *file) 2413 + { 2414 + i915_gpu_coredump_put(file->private_data); 2415 + return 0; 2416 + } 2417 + 2418 + static int i915_gpu_info_open(struct inode *inode, struct file *file) 2419 + { 2420 + struct drm_i915_private *i915 = inode->i_private; 2421 + struct i915_gpu_coredump *gpu; 2422 + intel_wakeref_t wakeref; 2423 + 2424 + gpu = NULL; 2425 + with_intel_runtime_pm(&i915->runtime_pm, wakeref) 2426 + gpu = i915_gpu_coredump(to_gt(i915), ALL_ENGINES, CORE_DUMP_FLAG_NONE); 2427 + 2428 + if (IS_ERR(gpu)) 2429 + return PTR_ERR(gpu); 2430 + 2431 + file->private_data = gpu; 2432 + return 0; 2433 + } 2434 + 2435 + static const struct file_operations i915_gpu_info_fops = { 2436 + .owner = THIS_MODULE, 2437 + .open = i915_gpu_info_open, 2438 + .read = gpu_state_read, 2439 + .llseek = default_llseek, 2440 + .release = gpu_state_release, 2441 + }; 2442 + 2443 + static ssize_t 2444 + i915_error_state_write(struct file *filp, 2445 + const char __user *ubuf, 2446 + size_t cnt, 2447 + loff_t *ppos) 2448 + { 2449 + struct i915_gpu_coredump *error = filp->private_data; 2450 + 2451 + if (!error) 2452 + return 0; 2453 + 2454 + drm_dbg(&error->i915->drm, "Resetting error state\n"); 2455 + i915_reset_error_state(error->i915); 2456 + 2457 + return cnt; 2458 + } 2459 + 2460 + static int i915_error_state_open(struct inode *inode, struct file *file) 2461 + { 2462 + struct i915_gpu_coredump *error; 2463 + 2464 + error = i915_first_error_state(inode->i_private); 2465 + if (IS_ERR(error)) 2466 + return PTR_ERR(error); 2467 + 2468 + file->private_data = error; 2469 + return 0; 2470 + } 2471 + 2472 + static const struct file_operations i915_error_state_fops = { 2473 + .owner = THIS_MODULE, 2474 + .open = i915_error_state_open, 2475 + .read = gpu_state_read, 2476 + .write = i915_error_state_write, 2477 + .llseek = default_llseek, 2478 + .release = gpu_state_release, 2479 + }; 2480 + 2481 + void i915_gpu_error_debugfs_register(struct drm_i915_private *i915) 2482 + { 2483 + struct drm_minor *minor = i915->drm.primary; 2484 + 2485 + debugfs_create_file("i915_error_state", 0644, minor->debugfs_root, i915, 2486 + &i915_error_state_fops); 2487 + debugfs_create_file("i915_gpu_info", 0644, minor->debugfs_root, i915, 2488 + &i915_gpu_info_fops); 2489 + } 2490 + 2491 + static ssize_t error_state_read(struct file *filp, struct kobject *kobj, 2492 + struct bin_attribute *attr, char *buf, 2493 + loff_t off, size_t count) 2494 + { 2495 + 2496 + struct device *kdev = kobj_to_dev(kobj); 2497 + struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); 2498 + struct i915_gpu_coredump *gpu; 2499 + ssize_t ret = 0; 2500 + 2501 + /* 2502 + * FIXME: Concurrent clients triggering resets and reading + clearing 2503 + * dumps can cause inconsistent sysfs reads when a user calls in with a 2504 + * non-zero offset to complete a prior partial read but the 2505 + * gpu_coredump has been cleared or replaced. 2506 + */ 2507 + 2508 + gpu = i915_first_error_state(i915); 2509 + if (IS_ERR(gpu)) { 2510 + ret = PTR_ERR(gpu); 2511 + } else if (gpu) { 2512 + ret = i915_gpu_coredump_copy_to_buffer(gpu, buf, off, count); 2513 + i915_gpu_coredump_put(gpu); 2514 + } else { 2515 + const char *str = "No error state collected\n"; 2516 + size_t len = strlen(str); 2517 + 2518 + if (off < len) { 2519 + ret = min_t(size_t, count, len - off); 2520 + memcpy(buf, str + off, ret); 2521 + } 2522 + } 2523 + 2524 + return ret; 2525 + } 2526 + 2527 + static ssize_t error_state_write(struct file *file, struct kobject *kobj, 2528 + struct bin_attribute *attr, char *buf, 2529 + loff_t off, size_t count) 2530 + { 2531 + struct device *kdev = kobj_to_dev(kobj); 2532 + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); 2533 + 2534 + drm_dbg(&dev_priv->drm, "Resetting error state\n"); 2535 + i915_reset_error_state(dev_priv); 2536 + 2537 + return count; 2538 + } 2539 + 2540 + static const struct bin_attribute error_state_attr = { 2541 + .attr.name = "error", 2542 + .attr.mode = S_IRUSR | S_IWUSR, 2543 + .size = 0, 2544 + .read = error_state_read, 2545 + .write = error_state_write, 2546 + }; 2547 + 2548 + void i915_gpu_error_sysfs_setup(struct drm_i915_private *i915) 2549 + { 2550 + struct device *kdev = i915->drm.primary->kdev; 2551 + 2552 + if (sysfs_create_bin_file(&kdev->kobj, &error_state_attr)) 2553 + drm_err(&i915->drm, "error_state sysfs setup failed\n"); 2554 + } 2555 + 2556 + void i915_gpu_error_sysfs_teardown(struct drm_i915_private *i915) 2557 + { 2558 + struct device *kdev = i915->drm.primary->kdev; 2559 + 2560 + sysfs_remove_bin_file(&kdev->kobj, &error_state_attr); 2561 + }
+26 -16
drivers/gpu/drm/i915/i915_gpu_error.h
··· 17 17 #include "display/intel_display_device.h" 18 18 #include "display/intel_display_params.h" 19 19 #include "gt/intel_engine.h" 20 + #include "gt/intel_engine_types.h" 20 21 #include "gt/intel_gt_types.h" 21 22 #include "gt/uc/intel_uc_fw.h" 22 23 ··· 235 234 atomic_t reset_count; 236 235 237 236 /** Number of times an engine has been reset */ 238 - atomic_t reset_engine_count[I915_NUM_ENGINES]; 237 + atomic_t reset_engine_count[MAX_ENGINE_CLASS]; 239 238 }; 240 239 241 240 struct drm_i915_error_state_buf { ··· 258 257 static inline u32 i915_reset_engine_count(struct i915_gpu_error *error, 259 258 const struct intel_engine_cs *engine) 260 259 { 261 - return atomic_read(&error->reset_engine_count[engine->uabi_class]); 260 + return atomic_read(&error->reset_engine_count[engine->class]); 261 + } 262 + 263 + static inline void 264 + i915_increase_reset_engine_count(struct i915_gpu_error *error, 265 + const struct intel_engine_cs *engine) 266 + { 267 + atomic_inc(&error->reset_engine_count[engine->class]); 262 268 } 263 269 264 270 #define CORE_DUMP_FLAG_NONE 0x0 ··· 285 277 286 278 __printf(2, 3) 287 279 void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...); 288 - void intel_gpu_error_print_vma(struct drm_i915_error_state_buf *m, 289 - const struct intel_engine_cs *engine, 290 - const struct i915_vma_coredump *vma); 291 - struct i915_vma_coredump * 292 - intel_gpu_error_find_batch(const struct intel_engine_coredump *ee); 293 280 294 - struct i915_gpu_coredump *i915_gpu_coredump(struct intel_gt *gt, 295 - intel_engine_mask_t engine_mask, u32 dump_flags); 296 281 void i915_capture_error_state(struct intel_gt *gt, 297 282 intel_engine_mask_t engine_mask, u32 dump_flags); 298 283 ··· 333 332 kref_put(&gpu->ref, __i915_gpu_coredump_free); 334 333 } 335 334 336 - struct i915_gpu_coredump *i915_first_error_state(struct drm_i915_private *i915); 337 335 void i915_reset_error_state(struct drm_i915_private *i915); 338 336 void i915_disable_error_state(struct drm_i915_private *i915, int err); 337 + 338 + void i915_gpu_error_debugfs_register(struct drm_i915_private *i915); 339 + void i915_gpu_error_sysfs_setup(struct drm_i915_private *i915); 340 + void i915_gpu_error_sysfs_teardown(struct drm_i915_private *i915); 339 341 340 342 #else 341 343 ··· 407 403 { 408 404 } 409 405 410 - static inline struct i915_gpu_coredump * 411 - i915_first_error_state(struct drm_i915_private *i915) 412 - { 413 - return ERR_PTR(-ENODEV); 414 - } 415 - 416 406 static inline void i915_reset_error_state(struct drm_i915_private *i915) 417 407 { 418 408 } 419 409 420 410 static inline void i915_disable_error_state(struct drm_i915_private *i915, 421 411 int err) 412 + { 413 + } 414 + 415 + static inline void i915_gpu_error_debugfs_register(struct drm_i915_private *i915) 416 + { 417 + } 418 + 419 + static inline void i915_gpu_error_sysfs_setup(struct drm_i915_private *i915) 420 + { 421 + } 422 + 423 + static inline void i915_gpu_error_sysfs_teardown(struct drm_i915_private *i915) 422 424 { 423 425 } 424 426
+39 -38
drivers/gpu/drm/i915/i915_pmu.c
··· 31 31 static cpumask_t i915_pmu_cpumask; 32 32 static unsigned int i915_pmu_target_cpu = -1; 33 33 34 + static struct i915_pmu *event_to_pmu(struct perf_event *event) 35 + { 36 + return container_of(event->pmu, struct i915_pmu, base); 37 + } 38 + 39 + static struct drm_i915_private *pmu_to_i915(struct i915_pmu *pmu) 40 + { 41 + return container_of(pmu, struct drm_i915_private, pmu); 42 + } 43 + 34 44 static u8 engine_config_sample(u64 config) 35 45 { 36 46 return config & I915_PMU_SAMPLE_MASK; ··· 151 141 152 142 static bool pmu_needs_timer(struct i915_pmu *pmu) 153 143 { 154 - struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu); 144 + struct drm_i915_private *i915 = pmu_to_i915(pmu); 155 145 u32 enable; 156 146 157 147 /* ··· 223 213 struct drm_i915_private *i915 = gt->i915; 224 214 const unsigned int gt_id = gt->info.id; 225 215 struct i915_pmu *pmu = &i915->pmu; 216 + intel_wakeref_t wakeref; 226 217 unsigned long flags; 227 - bool awake = false; 228 218 u64 val; 229 219 230 - if (intel_gt_pm_get_if_awake(gt)) { 220 + wakeref = intel_gt_pm_get_if_awake(gt); 221 + if (wakeref) { 231 222 val = __get_rc6(gt); 232 - intel_gt_pm_put_async(gt); 233 - awake = true; 223 + intel_gt_pm_put_async(gt, wakeref); 234 224 } 235 225 236 226 spin_lock_irqsave(&pmu->lock, flags); 237 227 238 - if (awake) { 228 + if (wakeref) { 239 229 store_sample(pmu, gt_id, __I915_SAMPLE_RC6, val); 240 230 } else { 241 231 /* ··· 261 251 262 252 static void init_rc6(struct i915_pmu *pmu) 263 253 { 264 - struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu); 254 + struct drm_i915_private *i915 = pmu_to_i915(pmu); 265 255 struct intel_gt *gt; 266 256 unsigned int i; 267 257 ··· 439 429 const unsigned int gt_id = gt->info.id; 440 430 struct i915_pmu *pmu = &i915->pmu; 441 431 struct intel_rps *rps = &gt->rps; 432 + intel_wakeref_t wakeref; 442 433 443 434 if (!frequency_sampling_enabled(pmu, gt_id)) 444 435 return; 445 436 446 437 /* Report 0/0 (actual/requested) frequency while parked. */ 447 - if (!intel_gt_pm_get_if_awake(gt)) 438 + wakeref = intel_gt_pm_get_if_awake(gt); 439 + if (!wakeref) 448 440 return; 449 441 450 442 if (pmu->enable & config_mask(__I915_PMU_ACTUAL_FREQUENCY(gt_id))) { ··· 475 463 period_ns / 1000); 476 464 } 477 465 478 - intel_gt_pm_put_async(gt); 466 + intel_gt_pm_put_async(gt, wakeref); 479 467 } 480 468 481 469 static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer) 482 470 { 483 - struct drm_i915_private *i915 = 484 - container_of(hrtimer, struct drm_i915_private, pmu.timer); 485 - struct i915_pmu *pmu = &i915->pmu; 471 + struct i915_pmu *pmu = container_of(hrtimer, struct i915_pmu, timer); 472 + struct drm_i915_private *i915 = pmu_to_i915(pmu); 486 473 unsigned int period_ns; 487 474 struct intel_gt *gt; 488 475 unsigned int i; ··· 516 505 517 506 static void i915_pmu_event_destroy(struct perf_event *event) 518 507 { 519 - struct drm_i915_private *i915 = 520 - container_of(event->pmu, typeof(*i915), pmu.base); 508 + struct i915_pmu *pmu = event_to_pmu(event); 509 + struct drm_i915_private *i915 = pmu_to_i915(pmu); 521 510 522 511 drm_WARN_ON(&i915->drm, event->parent); 523 512 ··· 583 572 584 573 static int engine_event_init(struct perf_event *event) 585 574 { 586 - struct drm_i915_private *i915 = 587 - container_of(event->pmu, typeof(*i915), pmu.base); 575 + struct i915_pmu *pmu = event_to_pmu(event); 576 + struct drm_i915_private *i915 = pmu_to_i915(pmu); 588 577 struct intel_engine_cs *engine; 589 578 590 579 engine = intel_engine_lookup_user(i915, engine_event_class(event), ··· 597 586 598 587 static int i915_pmu_event_init(struct perf_event *event) 599 588 { 600 - struct drm_i915_private *i915 = 601 - container_of(event->pmu, typeof(*i915), pmu.base); 602 - struct i915_pmu *pmu = &i915->pmu; 589 + struct i915_pmu *pmu = event_to_pmu(event); 590 + struct drm_i915_private *i915 = pmu_to_i915(pmu); 603 591 int ret; 604 592 605 593 if (pmu->closed) ··· 638 628 639 629 static u64 __i915_pmu_event_read(struct perf_event *event) 640 630 { 641 - struct drm_i915_private *i915 = 642 - container_of(event->pmu, typeof(*i915), pmu.base); 643 - struct i915_pmu *pmu = &i915->pmu; 631 + struct i915_pmu *pmu = event_to_pmu(event); 632 + struct drm_i915_private *i915 = pmu_to_i915(pmu); 644 633 u64 val = 0; 645 634 646 635 if (is_engine_event(event)) { ··· 695 686 696 687 static void i915_pmu_event_read(struct perf_event *event) 697 688 { 698 - struct drm_i915_private *i915 = 699 - container_of(event->pmu, typeof(*i915), pmu.base); 689 + struct i915_pmu *pmu = event_to_pmu(event); 700 690 struct hw_perf_event *hwc = &event->hw; 701 - struct i915_pmu *pmu = &i915->pmu; 702 691 u64 prev, new; 703 692 704 693 if (pmu->closed) { ··· 714 707 715 708 static void i915_pmu_enable(struct perf_event *event) 716 709 { 717 - struct drm_i915_private *i915 = 718 - container_of(event->pmu, typeof(*i915), pmu.base); 710 + struct i915_pmu *pmu = event_to_pmu(event); 711 + struct drm_i915_private *i915 = pmu_to_i915(pmu); 719 712 const unsigned int bit = event_bit(event); 720 - struct i915_pmu *pmu = &i915->pmu; 721 713 unsigned long flags; 722 714 723 715 if (bit == -1) ··· 777 771 778 772 static void i915_pmu_disable(struct perf_event *event) 779 773 { 780 - struct drm_i915_private *i915 = 781 - container_of(event->pmu, typeof(*i915), pmu.base); 774 + struct i915_pmu *pmu = event_to_pmu(event); 775 + struct drm_i915_private *i915 = pmu_to_i915(pmu); 782 776 const unsigned int bit = event_bit(event); 783 - struct i915_pmu *pmu = &i915->pmu; 784 777 unsigned long flags; 785 778 786 779 if (bit == -1) ··· 823 818 824 819 static void i915_pmu_event_start(struct perf_event *event, int flags) 825 820 { 826 - struct drm_i915_private *i915 = 827 - container_of(event->pmu, typeof(*i915), pmu.base); 828 - struct i915_pmu *pmu = &i915->pmu; 821 + struct i915_pmu *pmu = event_to_pmu(event); 829 822 830 823 if (pmu->closed) 831 824 return; ··· 851 848 852 849 static int i915_pmu_event_add(struct perf_event *event, int flags) 853 850 { 854 - struct drm_i915_private *i915 = 855 - container_of(event->pmu, typeof(*i915), pmu.base); 856 - struct i915_pmu *pmu = &i915->pmu; 851 + struct i915_pmu *pmu = event_to_pmu(event); 857 852 858 853 if (pmu->closed) 859 854 return -ENODEV; ··· 983 982 static struct attribute ** 984 983 create_event_attributes(struct i915_pmu *pmu) 985 984 { 986 - struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu); 985 + struct drm_i915_private *i915 = pmu_to_i915(pmu); 987 986 static const struct { 988 987 unsigned int counter; 989 988 const char *name;
+2 -77
drivers/gpu/drm/i915/i915_sysfs.c
··· 155 155 .private = (void *)1 156 156 }; 157 157 158 - #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) 159 - 160 - static ssize_t error_state_read(struct file *filp, struct kobject *kobj, 161 - struct bin_attribute *attr, char *buf, 162 - loff_t off, size_t count) 163 - { 164 - 165 - struct device *kdev = kobj_to_dev(kobj); 166 - struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); 167 - struct i915_gpu_coredump *gpu; 168 - ssize_t ret = 0; 169 - 170 - /* 171 - * FIXME: Concurrent clients triggering resets and reading + clearing 172 - * dumps can cause inconsistent sysfs reads when a user calls in with a 173 - * non-zero offset to complete a prior partial read but the 174 - * gpu_coredump has been cleared or replaced. 175 - */ 176 - 177 - gpu = i915_first_error_state(i915); 178 - if (IS_ERR(gpu)) { 179 - ret = PTR_ERR(gpu); 180 - } else if (gpu) { 181 - ret = i915_gpu_coredump_copy_to_buffer(gpu, buf, off, count); 182 - i915_gpu_coredump_put(gpu); 183 - } else { 184 - const char *str = "No error state collected\n"; 185 - size_t len = strlen(str); 186 - 187 - if (off < len) { 188 - ret = min_t(size_t, count, len - off); 189 - memcpy(buf, str + off, ret); 190 - } 191 - } 192 - 193 - return ret; 194 - } 195 - 196 - static ssize_t error_state_write(struct file *file, struct kobject *kobj, 197 - struct bin_attribute *attr, char *buf, 198 - loff_t off, size_t count) 199 - { 200 - struct device *kdev = kobj_to_dev(kobj); 201 - struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); 202 - 203 - drm_dbg(&dev_priv->drm, "Resetting error state\n"); 204 - i915_reset_error_state(dev_priv); 205 - 206 - return count; 207 - } 208 - 209 - static const struct bin_attribute error_state_attr = { 210 - .attr.name = "error", 211 - .attr.mode = S_IRUSR | S_IWUSR, 212 - .size = 0, 213 - .read = error_state_read, 214 - .write = error_state_write, 215 - }; 216 - 217 - static void i915_setup_error_capture(struct device *kdev) 218 - { 219 - if (sysfs_create_bin_file(&kdev->kobj, &error_state_attr)) 220 - drm_err(&kdev_minor_to_i915(kdev)->drm, 221 - "error_state sysfs setup failed\n"); 222 - } 223 - 224 - static void i915_teardown_error_capture(struct device *kdev) 225 - { 226 - sysfs_remove_bin_file(&kdev->kobj, &error_state_attr); 227 - } 228 - #else 229 - static void i915_setup_error_capture(struct device *kdev) {} 230 - static void i915_teardown_error_capture(struct device *kdev) {} 231 - #endif 232 - 233 158 void i915_setup_sysfs(struct drm_i915_private *dev_priv) 234 159 { 235 160 struct device *kdev = dev_priv->drm.primary->kdev; ··· 180 255 drm_warn(&dev_priv->drm, 181 256 "failed to register GT sysfs directory\n"); 182 257 183 - i915_setup_error_capture(kdev); 258 + i915_gpu_error_sysfs_setup(dev_priv); 184 259 185 260 intel_engines_add_sysfs(dev_priv); 186 261 } ··· 189 264 { 190 265 struct device *kdev = dev_priv->drm.primary->kdev; 191 266 192 - i915_teardown_error_capture(kdev); 267 + i915_gpu_error_sysfs_teardown(dev_priv); 193 268 194 269 device_remove_bin_file(kdev, &dpf_attrs_1); 195 270 device_remove_bin_file(kdev, &dpf_attrs);
+19
drivers/gpu/drm/i915/intel_memory_region.c
··· 216 216 return err; 217 217 } 218 218 219 + static const char *region_type_str(u16 type) 220 + { 221 + switch (type) { 222 + case INTEL_MEMORY_SYSTEM: 223 + return "system"; 224 + case INTEL_MEMORY_LOCAL: 225 + return "local"; 226 + case INTEL_MEMORY_STOLEN_LOCAL: 227 + return "stolen-local"; 228 + case INTEL_MEMORY_STOLEN_SYSTEM: 229 + return "stolen-system"; 230 + default: 231 + return "unknown"; 232 + } 233 + } 234 + 219 235 struct intel_memory_region * 220 236 intel_memory_region_create(struct drm_i915_private *i915, 221 237 resource_size_t start, ··· 259 243 mem->total = size; 260 244 mem->type = type; 261 245 mem->instance = instance; 246 + 247 + snprintf(mem->uabi_name, sizeof(mem->uabi_name), "%s%u", 248 + region_type_str(type), instance); 262 249 263 250 mutex_init(&mem->objects.lock); 264 251 INIT_LIST_HEAD(&mem->objects.list);
+1
drivers/gpu/drm/i915/intel_memory_region.h
··· 80 80 u16 instance; 81 81 enum intel_region_id id; 82 82 char name[16]; 83 + char uabi_name[16]; 83 84 bool private; /* not for userspace */ 84 85 85 86 struct {
+17 -204
drivers/gpu/drm/i915/intel_runtime_pm.c
··· 57 57 58 58 #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) 59 59 60 - #include <linux/sort.h> 61 - 62 - #define STACKDEPTH 8 63 - 64 - static noinline depot_stack_handle_t __save_depot_stack(void) 65 - { 66 - unsigned long entries[STACKDEPTH]; 67 - unsigned int n; 68 - 69 - n = stack_trace_save(entries, ARRAY_SIZE(entries), 1); 70 - return stack_depot_save(entries, n, GFP_NOWAIT | __GFP_NOWARN); 71 - } 72 - 73 60 static void init_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm) 74 61 { 75 - spin_lock_init(&rpm->debug.lock); 76 - stack_depot_init(); 62 + ref_tracker_dir_init(&rpm->debug, INTEL_REFTRACK_DEAD_COUNT, dev_name(rpm->kdev)); 77 63 } 78 64 79 - static noinline depot_stack_handle_t 65 + static intel_wakeref_t 80 66 track_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm) 81 67 { 82 - depot_stack_handle_t stack, *stacks; 83 - unsigned long flags; 84 - 85 - if (rpm->no_wakeref_tracking) 68 + if (!rpm->available || rpm->no_wakeref_tracking) 86 69 return -1; 87 70 88 - stack = __save_depot_stack(); 89 - if (!stack) 90 - return -1; 91 - 92 - spin_lock_irqsave(&rpm->debug.lock, flags); 93 - 94 - if (!rpm->debug.count) 95 - rpm->debug.last_acquire = stack; 96 - 97 - stacks = krealloc(rpm->debug.owners, 98 - (rpm->debug.count + 1) * sizeof(*stacks), 99 - GFP_NOWAIT | __GFP_NOWARN); 100 - if (stacks) { 101 - stacks[rpm->debug.count++] = stack; 102 - rpm->debug.owners = stacks; 103 - } else { 104 - stack = -1; 105 - } 106 - 107 - spin_unlock_irqrestore(&rpm->debug.lock, flags); 108 - 109 - return stack; 71 + return intel_ref_tracker_alloc(&rpm->debug); 110 72 } 111 73 112 74 static void untrack_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm, 113 - depot_stack_handle_t stack) 75 + intel_wakeref_t wakeref) 114 76 { 115 - struct drm_i915_private *i915 = container_of(rpm, 116 - struct drm_i915_private, 117 - runtime_pm); 118 - unsigned long flags, n; 119 - bool found = false; 120 - 121 - if (unlikely(stack == -1)) 77 + if (!rpm->available || rpm->no_wakeref_tracking) 122 78 return; 123 79 124 - spin_lock_irqsave(&rpm->debug.lock, flags); 125 - for (n = rpm->debug.count; n--; ) { 126 - if (rpm->debug.owners[n] == stack) { 127 - memmove(rpm->debug.owners + n, 128 - rpm->debug.owners + n + 1, 129 - (--rpm->debug.count - n) * sizeof(stack)); 130 - found = true; 131 - break; 132 - } 133 - } 134 - spin_unlock_irqrestore(&rpm->debug.lock, flags); 135 - 136 - if (drm_WARN(&i915->drm, !found, 137 - "Unmatched wakeref (tracking %lu), count %u\n", 138 - rpm->debug.count, atomic_read(&rpm->wakeref_count))) { 139 - char *buf; 140 - 141 - buf = kmalloc(PAGE_SIZE, GFP_NOWAIT | __GFP_NOWARN); 142 - if (!buf) 143 - return; 144 - 145 - stack_depot_snprint(stack, buf, PAGE_SIZE, 2); 146 - DRM_DEBUG_DRIVER("wakeref %x from\n%s", stack, buf); 147 - 148 - stack = READ_ONCE(rpm->debug.last_release); 149 - if (stack) { 150 - stack_depot_snprint(stack, buf, PAGE_SIZE, 2); 151 - DRM_DEBUG_DRIVER("wakeref last released at\n%s", buf); 152 - } 153 - 154 - kfree(buf); 155 - } 80 + intel_ref_tracker_free(&rpm->debug, wakeref); 156 81 } 157 82 158 - static int cmphandle(const void *_a, const void *_b) 83 + static void untrack_all_intel_runtime_pm_wakerefs(struct intel_runtime_pm *rpm) 159 84 { 160 - const depot_stack_handle_t * const a = _a, * const b = _b; 161 - 162 - if (*a < *b) 163 - return -1; 164 - else if (*a > *b) 165 - return 1; 166 - else 167 - return 0; 168 - } 169 - 170 - static void 171 - __print_intel_runtime_pm_wakeref(struct drm_printer *p, 172 - const struct intel_runtime_pm_debug *dbg) 173 - { 174 - unsigned long i; 175 - char *buf; 176 - 177 - buf = kmalloc(PAGE_SIZE, GFP_NOWAIT | __GFP_NOWARN); 178 - if (!buf) 179 - return; 180 - 181 - if (dbg->last_acquire) { 182 - stack_depot_snprint(dbg->last_acquire, buf, PAGE_SIZE, 2); 183 - drm_printf(p, "Wakeref last acquired:\n%s", buf); 184 - } 185 - 186 - if (dbg->last_release) { 187 - stack_depot_snprint(dbg->last_release, buf, PAGE_SIZE, 2); 188 - drm_printf(p, "Wakeref last released:\n%s", buf); 189 - } 190 - 191 - drm_printf(p, "Wakeref count: %lu\n", dbg->count); 192 - 193 - sort(dbg->owners, dbg->count, sizeof(*dbg->owners), cmphandle, NULL); 194 - 195 - for (i = 0; i < dbg->count; i++) { 196 - depot_stack_handle_t stack = dbg->owners[i]; 197 - unsigned long rep; 198 - 199 - rep = 1; 200 - while (i + 1 < dbg->count && dbg->owners[i + 1] == stack) 201 - rep++, i++; 202 - stack_depot_snprint(stack, buf, PAGE_SIZE, 2); 203 - drm_printf(p, "Wakeref x%lu taken at:\n%s", rep, buf); 204 - } 205 - 206 - kfree(buf); 207 - } 208 - 209 - static noinline void 210 - __untrack_all_wakerefs(struct intel_runtime_pm_debug *debug, 211 - struct intel_runtime_pm_debug *saved) 212 - { 213 - *saved = *debug; 214 - 215 - debug->owners = NULL; 216 - debug->count = 0; 217 - debug->last_release = __save_depot_stack(); 218 - } 219 - 220 - static void 221 - dump_and_free_wakeref_tracking(struct intel_runtime_pm_debug *debug) 222 - { 223 - if (debug->count) { 224 - struct drm_printer p = drm_debug_printer("i915"); 225 - 226 - __print_intel_runtime_pm_wakeref(&p, debug); 227 - } 228 - 229 - kfree(debug->owners); 85 + ref_tracker_dir_exit(&rpm->debug); 230 86 } 231 87 232 88 static noinline void 233 89 __intel_wakeref_dec_and_check_tracking(struct intel_runtime_pm *rpm) 234 90 { 235 - struct intel_runtime_pm_debug dbg = {}; 236 91 unsigned long flags; 237 92 238 93 if (!atomic_dec_and_lock_irqsave(&rpm->wakeref_count, ··· 95 240 flags)) 96 241 return; 97 242 98 - __untrack_all_wakerefs(&rpm->debug, &dbg); 243 + ref_tracker_dir_print_locked(&rpm->debug, INTEL_REFTRACK_PRINT_LIMIT); 99 244 spin_unlock_irqrestore(&rpm->debug.lock, flags); 100 - 101 - dump_and_free_wakeref_tracking(&dbg); 102 - } 103 - 104 - static noinline void 105 - untrack_all_intel_runtime_pm_wakerefs(struct intel_runtime_pm *rpm) 106 - { 107 - struct intel_runtime_pm_debug dbg = {}; 108 - unsigned long flags; 109 - 110 - spin_lock_irqsave(&rpm->debug.lock, flags); 111 - __untrack_all_wakerefs(&rpm->debug, &dbg); 112 - spin_unlock_irqrestore(&rpm->debug.lock, flags); 113 - 114 - dump_and_free_wakeref_tracking(&dbg); 115 245 } 116 246 117 247 void print_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm, 118 248 struct drm_printer *p) 119 249 { 120 - struct intel_runtime_pm_debug dbg = {}; 121 - 122 - do { 123 - unsigned long alloc = dbg.count; 124 - depot_stack_handle_t *s; 125 - 126 - spin_lock_irq(&rpm->debug.lock); 127 - dbg.count = rpm->debug.count; 128 - if (dbg.count <= alloc) { 129 - memcpy(dbg.owners, 130 - rpm->debug.owners, 131 - dbg.count * sizeof(*s)); 132 - } 133 - dbg.last_acquire = rpm->debug.last_acquire; 134 - dbg.last_release = rpm->debug.last_release; 135 - spin_unlock_irq(&rpm->debug.lock); 136 - if (dbg.count <= alloc) 137 - break; 138 - 139 - s = krealloc(dbg.owners, 140 - dbg.count * sizeof(*s), 141 - GFP_NOWAIT | __GFP_NOWARN); 142 - if (!s) 143 - goto out; 144 - 145 - dbg.owners = s; 146 - } while (1); 147 - 148 - __print_intel_runtime_pm_wakeref(p, &dbg); 149 - 150 - out: 151 - kfree(dbg.owners); 250 + intel_ref_tracker_show(&rpm->debug, p); 152 251 } 153 252 154 253 #else ··· 111 302 { 112 303 } 113 304 114 - static depot_stack_handle_t 305 + static intel_wakeref_t 115 306 track_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm) 116 307 { 117 308 return -1; 118 309 } 119 310 120 311 static void untrack_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm, 121 - intel_wakeref_t wref) 312 + intel_wakeref_t wakeref) 122 313 { 123 314 } 124 315 ··· 445 636 "i915 raw-wakerefs=%d wakelocks=%d on cleanup\n", 446 637 intel_rpm_raw_wakeref_count(count), 447 638 intel_rpm_wakelock_count(count)); 639 + } 448 640 641 + void intel_runtime_pm_driver_last_release(struct intel_runtime_pm *rpm) 642 + { 643 + intel_runtime_pm_driver_release(rpm); 449 644 untrack_all_intel_runtime_pm_wakerefs(rpm); 450 645 } 451 646
+2 -9
drivers/gpu/drm/i915/intel_runtime_pm.h
··· 75 75 * paired rpm_put) we can remove corresponding pairs of and keep 76 76 * the array trimmed to active wakerefs. 77 77 */ 78 - struct intel_runtime_pm_debug { 79 - spinlock_t lock; 80 - 81 - depot_stack_handle_t last_acquire; 82 - depot_stack_handle_t last_release; 83 - 84 - depot_stack_handle_t *owners; 85 - unsigned long count; 86 - } debug; 78 + struct ref_tracker_dir debug; 87 79 #endif 88 80 }; 89 81 ··· 179 187 void intel_runtime_pm_enable(struct intel_runtime_pm *rpm); 180 188 void intel_runtime_pm_disable(struct intel_runtime_pm *rpm); 181 189 void intel_runtime_pm_driver_release(struct intel_runtime_pm *rpm); 190 + void intel_runtime_pm_driver_last_release(struct intel_runtime_pm *rpm); 182 191 183 192 intel_wakeref_t intel_runtime_pm_get(struct intel_runtime_pm *rpm); 184 193 intel_wakeref_t intel_runtime_pm_get_if_in_use(struct intel_runtime_pm *rpm);
+34 -1
drivers/gpu/drm/i915/intel_wakeref.c
··· 99 99 void __intel_wakeref_init(struct intel_wakeref *wf, 100 100 struct drm_i915_private *i915, 101 101 const struct intel_wakeref_ops *ops, 102 - struct intel_wakeref_lockclass *key) 102 + struct intel_wakeref_lockclass *key, 103 + const char *name) 103 104 { 104 105 wf->i915 = i915; 105 106 wf->ops = ops; ··· 112 111 INIT_DELAYED_WORK(&wf->work, __intel_wakeref_put_work); 113 112 lockdep_init_map(&wf->work.work.lockdep_map, 114 113 "wakeref.work", &key->work, 0); 114 + 115 + #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_WAKEREF) 116 + ref_tracker_dir_init(&wf->debug, INTEL_REFTRACK_DEAD_COUNT, name); 117 + #endif 115 118 } 116 119 117 120 int intel_wakeref_wait_for_idle(struct intel_wakeref *wf) ··· 195 190 { 196 191 intel_wakeref_auto(wf, 0); 197 192 INTEL_WAKEREF_BUG_ON(wf->wakeref); 193 + } 194 + 195 + void intel_ref_tracker_show(struct ref_tracker_dir *dir, 196 + struct drm_printer *p) 197 + { 198 + const size_t buf_size = PAGE_SIZE; 199 + char *buf, *sb, *se; 200 + size_t count; 201 + 202 + buf = kmalloc(buf_size, GFP_NOWAIT); 203 + if (!buf) 204 + return; 205 + 206 + count = ref_tracker_dir_snprint(dir, buf, buf_size); 207 + if (!count) 208 + goto free; 209 + /* printk does not like big buffers, so we split it */ 210 + for (sb = buf; *sb; sb = se + 1) { 211 + se = strchrnul(sb, '\n'); 212 + drm_printf(p, "%.*s", (int)(se - sb + 1), sb); 213 + if (!*se) 214 + break; 215 + } 216 + if (count >= buf_size) 217 + drm_printf(p, "\n...dropped %zd extra bytes of leak report.\n", 218 + count + 1 - buf_size); 219 + free: 220 + kfree(buf); 198 221 }
+68 -5
drivers/gpu/drm/i915/intel_wakeref.h
··· 7 7 #ifndef INTEL_WAKEREF_H 8 8 #define INTEL_WAKEREF_H 9 9 10 + #include <drm/drm_print.h> 11 + 10 12 #include <linux/atomic.h> 11 13 #include <linux/bitfield.h> 12 14 #include <linux/bits.h> 13 15 #include <linux/lockdep.h> 14 16 #include <linux/mutex.h> 15 17 #include <linux/refcount.h> 18 + #include <linux/ref_tracker.h> 19 + #include <linux/slab.h> 16 20 #include <linux/stackdepot.h> 17 21 #include <linux/timer.h> 18 22 #include <linux/workqueue.h> 23 + 24 + typedef unsigned long intel_wakeref_t; 25 + 26 + #define INTEL_REFTRACK_DEAD_COUNT 16 27 + #define INTEL_REFTRACK_PRINT_LIMIT 16 19 28 20 29 #if IS_ENABLED(CONFIG_DRM_I915_DEBUG) 21 30 #define INTEL_WAKEREF_BUG_ON(expr) BUG_ON(expr) ··· 34 25 35 26 struct intel_runtime_pm; 36 27 struct intel_wakeref; 37 - 38 - typedef depot_stack_handle_t intel_wakeref_t; 39 28 40 29 struct intel_wakeref_ops { 41 30 int (*get)(struct intel_wakeref *wf); ··· 50 43 const struct intel_wakeref_ops *ops; 51 44 52 45 struct delayed_work work; 46 + 47 + #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_WAKEREF) 48 + struct ref_tracker_dir debug; 49 + #endif 53 50 }; 54 51 55 52 struct intel_wakeref_lockclass { ··· 64 53 void __intel_wakeref_init(struct intel_wakeref *wf, 65 54 struct drm_i915_private *i915, 66 55 const struct intel_wakeref_ops *ops, 67 - struct intel_wakeref_lockclass *key); 68 - #define intel_wakeref_init(wf, i915, ops) do { \ 56 + struct intel_wakeref_lockclass *key, 57 + const char *name); 58 + #define intel_wakeref_init(wf, i915, ops, name) do { \ 69 59 static struct intel_wakeref_lockclass __key; \ 70 60 \ 71 - __intel_wakeref_init((wf), (i915), (ops), &__key); \ 61 + __intel_wakeref_init((wf), (i915), (ops), &__key, name); \ 72 62 } while (0) 73 63 74 64 int __intel_wakeref_get_first(struct intel_wakeref *wf); ··· 272 260 * Return: 0 on success, error code if killed. 273 261 */ 274 262 int intel_wakeref_wait_for_idle(struct intel_wakeref *wf); 263 + 264 + #define INTEL_WAKEREF_DEF ((intel_wakeref_t)(-1)) 265 + 266 + static inline intel_wakeref_t intel_ref_tracker_alloc(struct ref_tracker_dir *dir) 267 + { 268 + struct ref_tracker *user = NULL; 269 + 270 + ref_tracker_alloc(dir, &user, GFP_NOWAIT); 271 + 272 + return (intel_wakeref_t)user ?: INTEL_WAKEREF_DEF; 273 + } 274 + 275 + static inline void intel_ref_tracker_free(struct ref_tracker_dir *dir, 276 + intel_wakeref_t handle) 277 + { 278 + struct ref_tracker *user; 279 + 280 + user = (handle == INTEL_WAKEREF_DEF) ? NULL : (void *)handle; 281 + 282 + ref_tracker_free(dir, &user); 283 + } 284 + 285 + void intel_ref_tracker_show(struct ref_tracker_dir *dir, 286 + struct drm_printer *p); 287 + 288 + #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_WAKEREF) 289 + 290 + static inline intel_wakeref_t intel_wakeref_track(struct intel_wakeref *wf) 291 + { 292 + return intel_ref_tracker_alloc(&wf->debug); 293 + } 294 + 295 + static inline void intel_wakeref_untrack(struct intel_wakeref *wf, 296 + intel_wakeref_t handle) 297 + { 298 + intel_ref_tracker_free(&wf->debug, handle); 299 + } 300 + 301 + #else 302 + 303 + static inline intel_wakeref_t intel_wakeref_track(struct intel_wakeref *wf) 304 + { 305 + return -1; 306 + } 307 + 308 + static inline void intel_wakeref_untrack(struct intel_wakeref *wf, 309 + intel_wakeref_t handle) 310 + { 311 + } 312 + 313 + #endif 275 314 276 315 struct intel_wakeref_auto { 277 316 struct drm_i915_private *i915;
+15 -3
drivers/gpu/drm/i915/pxp/intel_pxp.c
··· 199 199 struct intel_gt *gt; 200 200 bool is_full_feature = false; 201 201 202 + if (intel_gt_is_wedged(to_gt(i915))) 203 + return -ENOTCONN; 204 + 202 205 /* 203 206 * NOTE: Get the ctrl_gt before checking intel_pxp_is_supported since 204 207 * we still need it if PXP's backend tee transport is needed. ··· 306 303 307 304 if (!pxp->arb_is_valid) 308 305 return 0; 306 + 307 + drm_dbg(&pxp->ctrl_gt->i915->drm, "PXP: teardown for suspend/fini"); 309 308 /* 310 309 * To ensure synchronous and coherent session teardown completion 311 310 * in response to suspend or shutdown triggers, don't use a worker. ··· 329 324 330 325 if (pxp->arb_is_valid) 331 326 return 0; 327 + 328 + drm_dbg(&pxp->ctrl_gt->i915->drm, "PXP: teardown for restart"); 332 329 /* 333 330 * The arb-session is currently inactive and we are doing a reset and restart 334 331 * due to a runtime event. Use the worker that was designed for this. ··· 339 332 340 333 timeout = intel_pxp_get_backend_timeout_ms(pxp); 341 334 342 - if (!wait_for_completion_timeout(&pxp->termination, msecs_to_jiffies(timeout))) 335 + if (!wait_for_completion_timeout(&pxp->termination, msecs_to_jiffies(timeout))) { 336 + drm_dbg(&pxp->ctrl_gt->i915->drm, "PXP: restart backend timed out (%d ms)", 337 + timeout); 343 338 return -ETIMEDOUT; 339 + } 344 340 345 341 return 0; 346 342 } ··· 424 414 int ret = 0; 425 415 426 416 ret = intel_pxp_get_readiness_status(pxp, PXP_READINESS_TIMEOUT); 427 - if (ret < 0) 417 + if (ret < 0) { 418 + drm_dbg(&pxp->ctrl_gt->i915->drm, "PXP: tried but not-avail (%d)", ret); 428 419 return ret; 429 - else if (ret > 1) 420 + } else if (ret > 1) { 430 421 return -EIO; /* per UAPI spec, user may retry later */ 422 + } 431 423 432 424 mutex_lock(&pxp->arb_mutex); 433 425
+3 -2
drivers/gpu/drm/i915/pxp/intel_pxp_irq.c
··· 40 40 GEN12_DISPLAY_APP_TERMINATED_PER_FW_REQ_INTERRUPT)) { 41 41 /* immediately mark PXP as inactive on termination */ 42 42 intel_pxp_mark_termination_in_progress(pxp); 43 - pxp->session_events |= PXP_TERMINATION_REQUEST | PXP_INVAL_REQUIRED; 43 + pxp->session_events |= PXP_TERMINATION_REQUEST | PXP_INVAL_REQUIRED | 44 + PXP_EVENT_TYPE_IRQ; 44 45 } 45 46 46 47 if (iir & GEN12_DISPLAY_STATE_RESET_COMPLETE_INTERRUPT) 47 - pxp->session_events |= PXP_TERMINATION_COMPLETE; 48 + pxp->session_events |= PXP_TERMINATION_COMPLETE | PXP_EVENT_TYPE_IRQ; 48 49 49 50 if (pxp->session_events) 50 51 queue_work(system_unbound_wq, &pxp->session_work);
+5 -1
drivers/gpu/drm/i915/pxp/intel_pxp_session.c
··· 137 137 static void pxp_terminate_complete(struct intel_pxp *pxp) 138 138 { 139 139 /* Re-create the arb session after teardown handle complete */ 140 - if (fetch_and_zero(&pxp->hw_state_invalidated)) 140 + if (fetch_and_zero(&pxp->hw_state_invalidated)) { 141 + drm_dbg(&pxp->ctrl_gt->i915->drm, "PXP: creating arb_session after invalidation"); 141 142 pxp_create_arb_session(pxp); 143 + } 142 144 143 145 complete_all(&pxp->termination); 144 146 } ··· 158 156 159 157 if (!events) 160 158 return; 159 + 160 + drm_dbg(&gt->i915->drm, "PXP: processing event-flags 0x%08x", events); 161 161 162 162 if (events & PXP_INVAL_REQUIRED) 163 163 intel_pxp_invalidate(pxp);
+1
drivers/gpu/drm/i915/pxp/intel_pxp_types.h
··· 124 124 #define PXP_TERMINATION_REQUEST BIT(0) 125 125 #define PXP_TERMINATION_COMPLETE BIT(1) 126 126 #define PXP_INVAL_REQUIRED BIT(2) 127 + #define PXP_EVENT_TYPE_IRQ BIT(3) 127 128 }; 128 129 129 130 #endif /* __INTEL_PXP_TYPES_H__ */
+5 -4
drivers/gpu/drm/i915/selftests/igt_live_test.c
··· 37 37 } 38 38 39 39 for_each_engine(engine, gt, id) 40 - t->reset_engine[id] = 41 - i915_reset_engine_count(&i915->gpu_error, engine); 40 + t->reset_engine[i][id] = 41 + i915_reset_engine_count(&i915->gpu_error, 42 + engine); 42 43 } 43 44 44 45 t->reset_global = i915_reset_count(&i915->gpu_error); ··· 67 66 68 67 for_each_gt(gt, i915, i) { 69 68 for_each_engine(engine, gt, id) { 70 - if (t->reset_engine[id] == 69 + if (t->reset_engine[i][id] == 71 70 i915_reset_engine_count(&i915->gpu_error, engine)) 72 71 continue; 73 72 74 73 gt_err(gt, "%s(%s): engine '%s' was reset %d times!\n", 75 74 t->func, t->name, engine->name, 76 75 i915_reset_engine_count(&i915->gpu_error, engine) - 77 - t->reset_engine[id]); 76 + t->reset_engine[i][id]); 78 77 return -EIO; 79 78 } 80 79 }
+2 -1
drivers/gpu/drm/i915/selftests/igt_live_test.h
··· 7 7 #ifndef IGT_LIVE_TEST_H 8 8 #define IGT_LIVE_TEST_H 9 9 10 + #include "gt/intel_gt_defines.h" /* for I915_MAX_GT */ 10 11 #include "gt/intel_engine.h" /* for I915_NUM_ENGINES */ 11 12 12 13 struct drm_i915_private; ··· 18 17 const char *name; 19 18 20 19 unsigned int reset_global; 21 - unsigned int reset_engine[I915_NUM_ENGINES]; 20 + unsigned int reset_engine[I915_MAX_GT][I915_NUM_ENGINES]; 22 21 }; 23 22 24 23 /*
+2 -1
include/drm/i915_pciids.h
··· 738 738 INTEL_DG2_G12_IDS(info) 739 739 740 740 #define INTEL_ATS_M150_IDS(info) \ 741 - INTEL_VGA_DEVICE(0x56C0, info) 741 + INTEL_VGA_DEVICE(0x56C0, info), \ 742 + INTEL_VGA_DEVICE(0x56C2, info) 742 743 743 744 #define INTEL_ATS_M75_IDS(info) \ 744 745 INTEL_VGA_DEVICE(0x56C1, info)