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