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 intel_gt_pm_wait_for_idle(engine->gt);
43 GEM_BUG_ON(rps->active);
45 rps->cur_freq = rps->min_freq;
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));
108 intel_gt_pm_wait_for_idle(engine->gt);
112 static int __rps_down_interrupt(struct intel_rps *rps,
113 struct intel_engine_cs *engine)
115 struct intel_uncore *uncore = engine->uncore;
118 mutex_lock(&rps->lock);
119 GEM_BUG_ON(!rps->active);
120 intel_rps_set(rps, rps->max_freq);
121 mutex_unlock(&rps->lock);
123 if (!(rps->pm_events & GEN6_PM_RP_DOWN_THRESHOLD)) {
124 pr_err("%s: RPS did not register DOWN interrupt\n",
129 if (rps->last_freq != rps->max_freq) {
130 pr_err("%s: RPS did not program max frequency\n",
135 timeout = intel_uncore_read(uncore, GEN6_RP_DOWN_EI);
136 timeout = GT_PM_INTERVAL_TO_US(engine->i915, timeout);
138 sleep_for_ei(rps, timeout);
140 if (rps->cur_freq != rps->max_freq) {
141 pr_err("%s: Frequency unexpectedly changed [down], now %d!\n",
143 intel_rps_read_actual_frequency(rps));
147 if (!(rps->pm_iir & (GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT))) {
148 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",
149 engine->name, rps->pm_iir,
150 intel_uncore_read(uncore, GEN6_RP_PREV_DOWN),
151 intel_uncore_read(uncore, GEN6_RP_DOWN_THRESHOLD),
152 intel_uncore_read(uncore, GEN6_RP_DOWN_EI),
153 intel_uncore_read(uncore, GEN6_RP_PREV_UP),
154 intel_uncore_read(uncore, GEN6_RP_UP_THRESHOLD),
155 intel_uncore_read(uncore, GEN6_RP_UP_EI));
162 int live_rps_interrupt(void *arg)
164 struct intel_gt *gt = arg;
165 struct intel_rps *rps = >->rps;
166 void (*saved_work)(struct work_struct *wrk);
167 struct intel_engine_cs *engine;
168 enum intel_engine_id id;
169 struct igt_spinner spin;
174 * First, let's check whether or not we are receiving interrupts.
177 if (!rps->enabled || rps->max_freq <= rps->min_freq)
181 pm_events = rps->pm_events;
184 pr_err("No RPS PM events registered, but RPS is enabled?\n");
188 if (igt_spinner_init(&spin, gt))
191 intel_gt_pm_wait_for_idle(gt);
192 saved_work = rps->work.func;
193 rps->work.func = dummy_rps_work;
195 for_each_engine(engine, gt, id) {
196 /* Keep the engine busy with a spinner; expect an UP! */
197 if (pm_events & GEN6_PM_RP_UP_THRESHOLD) {
198 err = __rps_up_interrupt(rps, engine, &spin);
203 /* Keep the engine awake but idle and check for DOWN */
204 if (pm_events & GEN6_PM_RP_DOWN_THRESHOLD) {
205 intel_engine_pm_get(engine);
206 intel_rc6_disable(>->rc6);
208 err = __rps_down_interrupt(rps, engine);
210 intel_rc6_enable(>->rc6);
211 intel_engine_pm_put(engine);
218 if (igt_flush_test(gt->i915))
221 igt_spinner_fini(&spin);
223 intel_gt_pm_wait_for_idle(gt);
224 rps->work.func = saved_work;