1 // SPDX-License-Identifier: MIT
3 * Copyright © 2023 Intel Corporation
7 #include "i915_perf_oa_regs.h"
8 #include "intel_engine_pm.h"
10 #include "intel_gt_mcr.h"
11 #include "intel_gt_pm.h"
12 #include "intel_gt_print.h"
13 #include "intel_gt_regs.h"
14 #include "intel_tlb.h"
17 * HW architecture suggest typical invalidation time at 40us,
18 * with pessimistic cases up to 100us and a recommendation to
19 * cap at 1ms. We go a bit higher just in case.
21 #define TLB_INVAL_TIMEOUT_US 100
22 #define TLB_INVAL_TIMEOUT_MS 4
25 * On Xe_HP the TLB invalidation registers are located at the same MMIO offsets
26 * but are now considered MCR registers. Since they exist within a GAM range,
27 * the primary instance of the register rolls up the status from each unit.
29 static int wait_for_invalidate(struct intel_engine_cs *engine)
31 if (engine->tlb_inv.mcr)
32 return intel_gt_mcr_wait_for_reg(engine->gt,
33 engine->tlb_inv.reg.mcr_reg,
37 TLB_INVAL_TIMEOUT_MS);
39 return __intel_wait_for_register_fw(engine->gt->uncore,
40 engine->tlb_inv.reg.reg,
48 static void mmio_invalidate_full(struct intel_gt *gt)
50 struct drm_i915_private *i915 = gt->i915;
51 struct intel_uncore *uncore = gt->uncore;
52 struct intel_engine_cs *engine;
53 intel_engine_mask_t awake, tmp;
54 enum intel_engine_id id;
57 if (GRAPHICS_VER(i915) < 8)
60 intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
62 intel_gt_mcr_lock(gt, &flags);
63 spin_lock(&uncore->lock); /* serialise invalidate with GT reset */
66 for_each_engine(engine, gt, id) {
67 if (!intel_engine_pm_is_awake(engine))
70 if (engine->tlb_inv.mcr)
71 intel_gt_mcr_multicast_write_fw(gt,
72 engine->tlb_inv.reg.mcr_reg,
73 engine->tlb_inv.request);
75 intel_uncore_write_fw(uncore,
76 engine->tlb_inv.reg.reg,
77 engine->tlb_inv.request);
79 awake |= engine->mask;
82 GT_TRACE(gt, "invalidated engines %08x\n", awake);
84 /* Wa_2207587034:tgl,dg1,rkl,adl-s,adl-p */
86 (IS_TIGERLAKE(i915) ||
88 IS_ROCKETLAKE(i915) ||
89 IS_ALDERLAKE_S(i915) ||
90 IS_ALDERLAKE_P(i915)))
91 intel_uncore_write_fw(uncore, GEN12_OA_TLB_INV_CR, 1);
93 spin_unlock(&uncore->lock);
94 intel_gt_mcr_unlock(gt, flags);
96 for_each_engine_masked(engine, gt, awake, tmp) {
97 if (wait_for_invalidate(engine))
98 gt_err_ratelimited(gt,
99 "%s TLB invalidation did not complete in %ums!\n",
100 engine->name, TLB_INVAL_TIMEOUT_MS);
104 * Use delayed put since a) we mostly expect a flurry of TLB
105 * invalidations so it is good to avoid paying the forcewake cost and
106 * b) it works around a bug in Icelake which cannot cope with too rapid
109 intel_uncore_forcewake_put_delayed(uncore, FORCEWAKE_ALL);
112 static bool tlb_seqno_passed(const struct intel_gt *gt, u32 seqno)
114 u32 cur = intel_gt_tlb_seqno(gt);
116 /* Only skip if a *full* TLB invalidate barrier has passed */
117 return (s32)(cur - ALIGN(seqno, 2)) > 0;
120 void intel_gt_invalidate_tlb_full(struct intel_gt *gt, u32 seqno)
122 intel_wakeref_t wakeref;
124 if (I915_SELFTEST_ONLY(gt->awake == -ENODEV))
127 if (intel_gt_is_wedged(gt))
130 if (tlb_seqno_passed(gt, seqno))
133 with_intel_gt_pm_if_awake(gt, wakeref) {
134 mutex_lock(>->tlb.invalidate_lock);
135 if (tlb_seqno_passed(gt, seqno))
138 mmio_invalidate_full(gt);
140 write_seqcount_invalidate(>->tlb.seqno);
142 mutex_unlock(>->tlb.invalidate_lock);
146 void intel_gt_init_tlb(struct intel_gt *gt)
148 mutex_init(>->tlb.invalidate_lock);
149 seqcount_mutex_init(>->tlb.seqno, >->tlb.invalidate_lock);
152 void intel_gt_fini_tlb(struct intel_gt *gt)
154 mutex_destroy(>->tlb.invalidate_lock);
157 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
158 #include "selftest_tlb.c"