1 // SPDX-License-Identifier: MIT
3 * Copyright © 2020 Intel Corporation
6 #include "intel_engine_pm.h"
7 #include "intel_gt_pm.h"
9 #include "selftest_rps.h"
10 #include "selftests/igt_flush_test.h"
11 #include "selftests/igt_spinner.h"
13 static void dummy_rps_work(struct work_struct *wrk)
17 static void sleep_for_ei(struct intel_rps *rps, int timeout_us)
19 /* Flush any previous EI */
20 usleep_range(timeout_us, 2 * timeout_us);
22 /* Reset the interrupt status */
23 rps_disable_interrupts(rps);
24 GEM_BUG_ON(rps->pm_iir);
25 rps_enable_interrupts(rps);
27 /* And then wait for the timeout, for real this time */
28 usleep_range(2 * timeout_us, 3 * timeout_us);
31 static int __rps_up_interrupt(struct intel_rps *rps,
32 struct intel_engine_cs *engine,
33 struct igt_spinner *spin)
35 struct intel_uncore *uncore = engine->uncore;
36 struct i915_request *rq;
39 if (!intel_engine_can_store_dword(engine))
42 mutex_lock(&rps->lock);
43 GEM_BUG_ON(!rps->active);
44 intel_rps_set(rps, rps->min_freq);
45 mutex_unlock(&rps->lock);
47 rq = igt_spinner_create_request(spin, engine->kernel_context, MI_NOOP);
54 if (!igt_wait_for_spinner(spin, rq)) {
55 pr_err("%s: RPS spinner did not start\n",
58 intel_gt_set_wedged(engine->gt);
63 pr_err("%s: RPS not enabled on starting spinner\n",
65 igt_spinner_end(spin);
70 if (!(rps->pm_events & GEN6_PM_RP_UP_THRESHOLD)) {
71 pr_err("%s: RPS did not register UP interrupt\n",
77 if (rps->last_freq != rps->min_freq) {
78 pr_err("%s: RPS did not program min frequency\n",
84 timeout = intel_uncore_read(uncore, GEN6_RP_UP_EI);
85 timeout = GT_PM_INTERVAL_TO_US(engine->i915, timeout);
87 sleep_for_ei(rps, timeout);
88 GEM_BUG_ON(i915_request_completed(rq));
90 igt_spinner_end(spin);
93 if (rps->cur_freq != rps->min_freq) {
94 pr_err("%s: Frequency unexpectedly changed [up], now %d!\n",
95 engine->name, intel_rps_read_actual_frequency(rps));
99 if (!(rps->pm_iir & GEN6_PM_RP_UP_THRESHOLD)) {
100 pr_err("%s: UP interrupt not recorded for spinner, pm_iir:%x, prev_up:%x, up_threshold:%x, up_ei:%x\n",
101 engine->name, rps->pm_iir,
102 intel_uncore_read(uncore, GEN6_RP_PREV_UP),
103 intel_uncore_read(uncore, GEN6_RP_UP_THRESHOLD),
104 intel_uncore_read(uncore, GEN6_RP_UP_EI));
111 static int __rps_down_interrupt(struct intel_rps *rps,
112 struct intel_engine_cs *engine)
114 struct intel_uncore *uncore = engine->uncore;
117 mutex_lock(&rps->lock);
118 GEM_BUG_ON(!rps->active);
119 intel_rps_set(rps, rps->max_freq);
120 mutex_unlock(&rps->lock);
122 if (!(rps->pm_events & GEN6_PM_RP_DOWN_THRESHOLD)) {
123 pr_err("%s: RPS did not register DOWN interrupt\n",
128 if (rps->last_freq != rps->max_freq) {
129 pr_err("%s: RPS did not program max frequency\n",
134 timeout = intel_uncore_read(uncore, GEN6_RP_DOWN_EI);
135 timeout = GT_PM_INTERVAL_TO_US(engine->i915, timeout);
137 sleep_for_ei(rps, timeout);
139 if (rps->cur_freq != rps->max_freq) {
140 pr_err("%s: Frequency unexpectedly changed [down], now %d!\n",
142 intel_rps_read_actual_frequency(rps));
146 if (!(rps->pm_iir & (GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT))) {
147 pr_err("%s: DOWN interrupt not recorded for idle, pm_iir:%x, prev_down:%x, down_threshold:%x, down_ei:%x [prev_up:%x, up_threshold:%x, up_ei:%x]\n",
148 engine->name, rps->pm_iir,
149 intel_uncore_read(uncore, GEN6_RP_PREV_DOWN),
150 intel_uncore_read(uncore, GEN6_RP_DOWN_THRESHOLD),
151 intel_uncore_read(uncore, GEN6_RP_DOWN_EI),
152 intel_uncore_read(uncore, GEN6_RP_PREV_UP),
153 intel_uncore_read(uncore, GEN6_RP_UP_THRESHOLD),
154 intel_uncore_read(uncore, GEN6_RP_UP_EI));
161 int live_rps_interrupt(void *arg)
163 struct intel_gt *gt = arg;
164 struct intel_rps *rps = >->rps;
165 void (*saved_work)(struct work_struct *wrk);
166 struct intel_engine_cs *engine;
167 enum intel_engine_id id;
168 struct igt_spinner spin;
173 * First, let's check whether or not we are receiving interrupts.
176 if (!rps->enabled || rps->max_freq <= rps->min_freq)
180 pm_events = rps->pm_events;
183 pr_err("No RPS PM events registered, but RPS is enabled?\n");
187 if (igt_spinner_init(&spin, gt))
190 intel_gt_pm_wait_for_idle(gt);
191 saved_work = rps->work.func;
192 rps->work.func = dummy_rps_work;
194 for_each_engine(engine, gt, id) {
195 /* Keep the engine busy with a spinner; expect an UP! */
196 if (pm_events & GEN6_PM_RP_UP_THRESHOLD) {
197 intel_gt_pm_wait_for_idle(engine->gt);
198 GEM_BUG_ON(rps->active);
200 intel_engine_pm_get(engine);
201 err = __rps_up_interrupt(rps, engine, &spin);
202 intel_engine_pm_put(engine);
206 intel_gt_pm_wait_for_idle(engine->gt);
209 /* Keep the engine awake but idle and check for DOWN */
210 if (pm_events & GEN6_PM_RP_DOWN_THRESHOLD) {
211 intel_engine_pm_get(engine);
212 intel_rc6_disable(>->rc6);
214 err = __rps_down_interrupt(rps, engine);
216 intel_rc6_enable(>->rc6);
217 intel_engine_pm_put(engine);
224 if (igt_flush_test(gt->i915))
227 igt_spinner_fini(&spin);
229 intel_gt_pm_wait_for_idle(gt);
230 rps->work.func = saved_work;