1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2019 Intel Corporation 4 */ 5 6 #include <linux/sort.h> 7 8 #include "intel_engine_regs.h" 9 #include "intel_gt_clock_utils.h" 10 11 #include "selftest_llc.h" 12 #include "selftest_rc6.h" 13 #include "selftest_rps.h" 14 15 static int cmp_u64(const void *A, const void *B) 16 { 17 const u64 *a = A, *b = B; 18 19 if (a < b) 20 return -1; 21 else if (a > b) 22 return 1; 23 else 24 return 0; 25 } 26 27 static int cmp_u32(const void *A, const void *B) 28 { 29 const u32 *a = A, *b = B; 30 31 if (a < b) 32 return -1; 33 else if (a > b) 34 return 1; 35 else 36 return 0; 37 } 38 39 static u32 read_timestamp(struct intel_engine_cs *engine) 40 { 41 struct drm_i915_private *i915 = engine->i915; 42 43 /* On i965 the first read tends to give a stale value */ 44 ENGINE_READ_FW(engine, RING_TIMESTAMP); 45 46 if (GRAPHICS_VER(i915) == 5 || IS_G4X(i915)) 47 return ENGINE_READ_FW(engine, RING_TIMESTAMP_UDW); 48 else 49 return ENGINE_READ_FW(engine, RING_TIMESTAMP); 50 } 51 52 static void measure_clocks(struct intel_engine_cs *engine, 53 u32 *out_cycles, ktime_t *out_dt) 54 { 55 ktime_t dt[5]; 56 u32 cycles[5]; 57 int i; 58 59 for (i = 0; i < 5; i++) { 60 local_irq_disable(); 61 cycles[i] = -read_timestamp(engine); 62 dt[i] = ktime_get(); 63 64 udelay(1000); 65 66 cycles[i] += read_timestamp(engine); 67 dt[i] = ktime_sub(ktime_get(), dt[i]); 68 local_irq_enable(); 69 } 70 71 /* Use the median of both cycle/dt; close enough */ 72 sort(cycles, 5, sizeof(*cycles), cmp_u32, NULL); 73 *out_cycles = (cycles[1] + 2 * cycles[2] + cycles[3]) / 4; 74 75 sort(dt, 5, sizeof(*dt), cmp_u64, NULL); 76 *out_dt = div_u64(dt[1] + 2 * dt[2] + dt[3], 4); 77 } 78 79 static int live_gt_clocks(void *arg) 80 { 81 struct intel_gt *gt = arg; 82 struct intel_engine_cs *engine; 83 enum intel_engine_id id; 84 int err = 0; 85 86 if (!gt->clock_frequency) { /* unknown */ 87 pr_info("CS_TIMESTAMP frequency unknown\n"); 88 return 0; 89 } 90 91 if (GRAPHICS_VER(gt->i915) < 4) /* Any CS_TIMESTAMP? */ 92 return 0; 93 94 intel_gt_pm_get(gt); 95 intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL); 96 97 for_each_engine(engine, gt, id) { 98 u32 cycles; 99 u32 expected; 100 u64 time; 101 u64 dt; 102 103 if (GRAPHICS_VER(engine->i915) < 7 && engine->id != RCS0) 104 continue; 105 106 measure_clocks(engine, &cycles, &dt); 107 108 time = intel_gt_clock_interval_to_ns(engine->gt, cycles); 109 expected = intel_gt_ns_to_clock_interval(engine->gt, dt); 110 111 pr_info("%s: TIMESTAMP %d cycles [%lldns] in %lldns [%d cycles], using CS clock frequency of %uKHz\n", 112 engine->name, cycles, time, dt, expected, 113 engine->gt->clock_frequency / 1000); 114 115 if (9 * time < 8 * dt || 8 * time > 9 * dt) { 116 pr_err("%s: CS ticks did not match walltime!\n", 117 engine->name); 118 err = -EINVAL; 119 break; 120 } 121 122 if (9 * expected < 8 * cycles || 8 * expected > 9 * cycles) { 123 pr_err("%s: walltime did not match CS ticks!\n", 124 engine->name); 125 err = -EINVAL; 126 break; 127 } 128 } 129 130 intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); 131 intel_gt_pm_put(gt); 132 133 return err; 134 } 135 136 static int live_gt_resume(void *arg) 137 { 138 struct intel_gt *gt = arg; 139 IGT_TIMEOUT(end_time); 140 int err; 141 142 /* Do several suspend/resume cycles to check we don't explode! */ 143 do { 144 intel_gt_suspend_prepare(gt); 145 intel_gt_suspend_late(gt); 146 147 if (gt->rc6.enabled) { 148 pr_err("rc6 still enabled after suspend!\n"); 149 intel_gt_set_wedged_on_init(gt); 150 err = -EINVAL; 151 break; 152 } 153 154 err = intel_gt_resume(gt); 155 if (err) 156 break; 157 158 if (gt->rc6.supported && !gt->rc6.enabled) { 159 pr_err("rc6 not enabled upon resume!\n"); 160 intel_gt_set_wedged_on_init(gt); 161 err = -EINVAL; 162 break; 163 } 164 165 err = st_llc_verify(>->llc); 166 if (err) { 167 pr_err("llc state not restored upon resume!\n"); 168 intel_gt_set_wedged_on_init(gt); 169 break; 170 } 171 } while (!__igt_timeout(end_time, NULL)); 172 173 return err; 174 } 175 176 int intel_gt_pm_live_selftests(struct drm_i915_private *i915) 177 { 178 static const struct i915_subtest tests[] = { 179 SUBTEST(live_gt_clocks), 180 SUBTEST(live_rc6_manual), 181 SUBTEST(live_rps_clock_interval), 182 SUBTEST(live_rps_control), 183 SUBTEST(live_rps_frequency_cs), 184 SUBTEST(live_rps_frequency_srm), 185 SUBTEST(live_rps_power), 186 SUBTEST(live_rps_interrupt), 187 SUBTEST(live_rps_dynamic), 188 SUBTEST(live_gt_resume), 189 }; 190 191 if (intel_gt_is_wedged(to_gt(i915))) 192 return 0; 193 194 return intel_gt_live_subtests(tests, to_gt(i915)); 195 } 196 197 int intel_gt_pm_late_selftests(struct drm_i915_private *i915) 198 { 199 static const struct i915_subtest tests[] = { 200 /* 201 * These tests may leave the system in an undesirable state. 202 * They are intended to be run last in CI and the system 203 * rebooted afterwards. 204 */ 205 SUBTEST(live_rc6_ctx_wa), 206 }; 207 208 if (intel_gt_is_wedged(to_gt(i915))) 209 return 0; 210 211 return intel_gt_live_subtests(tests, to_gt(i915)); 212 } 213