3 * SPDX-License-Identifier: MIT
5 * Copyright © 2019 Intel Corporation
8 #include <linux/sort.h>
10 #include "intel_gt_clock_utils.h"
12 #include "selftest_llc.h"
13 #include "selftest_rc6.h"
14 #include "selftest_rps.h"
16 static int cmp_u64(const void *A
, const void *B
)
18 const u64
*a
= A
, *b
= B
;
28 static int cmp_u32(const void *A
, const void *B
)
30 const u32
*a
= A
, *b
= B
;
40 static void measure_clocks(struct intel_engine_cs
*engine
,
41 u32
*out_cycles
, ktime_t
*out_dt
)
47 for (i
= 0; i
< 5; i
++) {
49 cycles
[i
] = -ENGINE_READ_FW(engine
, RING_TIMESTAMP
);
54 dt
[i
] = ktime_sub(ktime_get(), dt
[i
]);
55 cycles
[i
] += ENGINE_READ_FW(engine
, RING_TIMESTAMP
);
59 /* Use the median of both cycle/dt; close enough */
60 sort(cycles
, 5, sizeof(*cycles
), cmp_u32
, NULL
);
61 *out_cycles
= (cycles
[1] + 2 * cycles
[2] + cycles
[3]) / 4;
63 sort(dt
, 5, sizeof(*dt
), cmp_u64
, NULL
);
64 *out_dt
= div_u64(dt
[1] + 2 * dt
[2] + dt
[3], 4);
67 static int live_gt_clocks(void *arg
)
69 struct intel_gt
*gt
= arg
;
70 struct intel_engine_cs
*engine
;
71 enum intel_engine_id id
;
74 if (!RUNTIME_INFO(gt
->i915
)->cs_timestamp_frequency_hz
) { /* unknown */
75 pr_info("CS_TIMESTAMP frequency unknown\n");
79 if (INTEL_GEN(gt
->i915
) < 4) /* Any CS_TIMESTAMP? */
82 if (IS_GEN(gt
->i915
, 5))
84 * XXX CS_TIMESTAMP low dword is dysfunctional?
86 * Ville's experiments indicate the high dword still works,
87 * but at a correspondingly reduced frequency.
91 if (IS_GEN(gt
->i915
, 4))
93 * XXX CS_TIMESTAMP appears gibberish
95 * Ville's experiments indicate that it mostly appears 'stuck'
96 * in that we see the register report the same cycle count
97 * for a couple of reads.
102 intel_uncore_forcewake_get(gt
->uncore
, FORCEWAKE_ALL
);
104 for_each_engine(engine
, gt
, id
) {
110 if (INTEL_GEN(engine
->i915
) < 7 && engine
->id
!= RCS0
)
113 measure_clocks(engine
, &cycles
, &dt
);
115 time
= i915_cs_timestamp_ticks_to_ns(engine
->i915
, cycles
);
116 expected
= i915_cs_timestamp_ns_to_ticks(engine
->i915
, dt
);
118 pr_info("%s: TIMESTAMP %d cycles [%lldns] in %lldns [%d cycles], using CS clock frequency of %uKHz\n",
119 engine
->name
, cycles
, time
, dt
, expected
,
120 RUNTIME_INFO(engine
->i915
)->cs_timestamp_frequency_hz
/ 1000);
122 if (9 * time
< 8 * dt
|| 8 * time
> 9 * dt
) {
123 pr_err("%s: CS ticks did not match walltime!\n",
129 if (9 * expected
< 8 * cycles
|| 8 * expected
> 9 * cycles
) {
130 pr_err("%s: walltime did not match CS ticks!\n",
137 intel_uncore_forcewake_put(gt
->uncore
, FORCEWAKE_ALL
);
143 static int live_gt_resume(void *arg
)
145 struct intel_gt
*gt
= arg
;
146 IGT_TIMEOUT(end_time
);
149 /* Do several suspend/resume cycles to check we don't explode! */
151 intel_gt_suspend_prepare(gt
);
152 intel_gt_suspend_late(gt
);
154 if (gt
->rc6
.enabled
) {
155 pr_err("rc6 still enabled after suspend!\n");
156 intel_gt_set_wedged_on_init(gt
);
161 err
= intel_gt_resume(gt
);
165 if (gt
->rc6
.supported
&& !gt
->rc6
.enabled
) {
166 pr_err("rc6 not enabled upon resume!\n");
167 intel_gt_set_wedged_on_init(gt
);
172 err
= st_llc_verify(>
->llc
);
174 pr_err("llc state not restored upon resume!\n");
175 intel_gt_set_wedged_on_init(gt
);
178 } while (!__igt_timeout(end_time
, NULL
));
183 int intel_gt_pm_live_selftests(struct drm_i915_private
*i915
)
185 static const struct i915_subtest tests
[] = {
186 SUBTEST(live_gt_clocks
),
187 SUBTEST(live_rc6_manual
),
188 SUBTEST(live_rps_clock_interval
),
189 SUBTEST(live_rps_control
),
190 SUBTEST(live_rps_frequency_cs
),
191 SUBTEST(live_rps_frequency_srm
),
192 SUBTEST(live_rps_power
),
193 SUBTEST(live_rps_interrupt
),
194 SUBTEST(live_rps_dynamic
),
195 SUBTEST(live_gt_resume
),
198 if (intel_gt_is_wedged(&i915
->gt
))
201 return intel_gt_live_subtests(tests
, &i915
->gt
);
204 int intel_gt_pm_late_selftests(struct drm_i915_private
*i915
)
206 static const struct i915_subtest tests
[] = {
208 * These tests may leave the system in an undesirable state.
209 * They are intended to be run last in CI and the system
210 * rebooted afterwards.
212 SUBTEST(live_rc6_ctx_wa
),
215 if (intel_gt_is_wedged(&i915
->gt
))
218 return intel_gt_live_subtests(tests
, &i915
->gt
);