199d608aa7638394aab83e8615e2ac32734d7a84
[linux-2.6-microblaze.git] / drivers / gpu / drm / i915 / gt / selftest_rps.c
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2020 Intel Corporation
4  */
5
6 #include "intel_engine_pm.h"
7 #include "intel_gt_pm.h"
8 #include "intel_rc6.h"
9 #include "selftest_rps.h"
10 #include "selftests/igt_flush_test.h"
11 #include "selftests/igt_spinner.h"
12
13 static void dummy_rps_work(struct work_struct *wrk)
14 {
15 }
16
17 static void sleep_for_ei(struct intel_rps *rps, int timeout_us)
18 {
19         /* Flush any previous EI */
20         usleep_range(timeout_us, 2 * timeout_us);
21
22         /* Reset the interrupt status */
23         rps_disable_interrupts(rps);
24         GEM_BUG_ON(rps->pm_iir);
25         rps_enable_interrupts(rps);
26
27         /* And then wait for the timeout, for real this time */
28         usleep_range(2 * timeout_us, 3 * timeout_us);
29 }
30
31 static int __rps_up_interrupt(struct intel_rps *rps,
32                               struct intel_engine_cs *engine,
33                               struct igt_spinner *spin)
34 {
35         struct intel_uncore *uncore = engine->uncore;
36         struct i915_request *rq;
37         u32 timeout;
38
39         if (!intel_engine_can_store_dword(engine))
40                 return 0;
41
42         intel_gt_pm_wait_for_idle(engine->gt);
43         GEM_BUG_ON(rps->active);
44
45         rps->cur_freq = rps->min_freq;
46
47         rq = igt_spinner_create_request(spin, engine->kernel_context, MI_NOOP);
48         if (IS_ERR(rq))
49                 return PTR_ERR(rq);
50
51         i915_request_get(rq);
52         i915_request_add(rq);
53
54         if (!igt_wait_for_spinner(spin, rq)) {
55                 pr_err("%s: RPS spinner did not start\n",
56                        engine->name);
57                 i915_request_put(rq);
58                 intel_gt_set_wedged(engine->gt);
59                 return -EIO;
60         }
61
62         if (!rps->active) {
63                 pr_err("%s: RPS not enabled on starting spinner\n",
64                        engine->name);
65                 igt_spinner_end(spin);
66                 i915_request_put(rq);
67                 return -EINVAL;
68         }
69
70         if (!(rps->pm_events & GEN6_PM_RP_UP_THRESHOLD)) {
71                 pr_err("%s: RPS did not register UP interrupt\n",
72                        engine->name);
73                 i915_request_put(rq);
74                 return -EINVAL;
75         }
76
77         if (rps->last_freq != rps->min_freq) {
78                 pr_err("%s: RPS did not program min frequency\n",
79                        engine->name);
80                 i915_request_put(rq);
81                 return -EINVAL;
82         }
83
84         timeout = intel_uncore_read(uncore, GEN6_RP_UP_EI);
85         timeout = GT_PM_INTERVAL_TO_US(engine->i915, timeout);
86
87         sleep_for_ei(rps, timeout);
88         GEM_BUG_ON(i915_request_completed(rq));
89
90         igt_spinner_end(spin);
91         i915_request_put(rq);
92
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));
96                 return -EINVAL;
97         }
98
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));
105                 return -EINVAL;
106         }
107
108         intel_gt_pm_wait_for_idle(engine->gt);
109         return 0;
110 }
111
112 static int __rps_down_interrupt(struct intel_rps *rps,
113                                 struct intel_engine_cs *engine)
114 {
115         struct intel_uncore *uncore = engine->uncore;
116         u32 timeout;
117
118         mutex_lock(&rps->lock);
119         GEM_BUG_ON(!rps->active);
120         intel_rps_set(rps, rps->max_freq);
121         mutex_unlock(&rps->lock);
122
123         if (!(rps->pm_events & GEN6_PM_RP_DOWN_THRESHOLD)) {
124                 pr_err("%s: RPS did not register DOWN interrupt\n",
125                        engine->name);
126                 return -EINVAL;
127         }
128
129         if (rps->last_freq != rps->max_freq) {
130                 pr_err("%s: RPS did not program max frequency\n",
131                        engine->name);
132                 return -EINVAL;
133         }
134
135         timeout = intel_uncore_read(uncore, GEN6_RP_DOWN_EI);
136         timeout = GT_PM_INTERVAL_TO_US(engine->i915, timeout);
137
138         sleep_for_ei(rps, timeout);
139
140         if (rps->cur_freq != rps->max_freq) {
141                 pr_err("%s: Frequency unexpectedly changed [down], now %d!\n",
142                        engine->name,
143                        intel_rps_read_actual_frequency(rps));
144                 return -EINVAL;
145         }
146
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));
156                 return -EINVAL;
157         }
158
159         return 0;
160 }
161
162 int live_rps_interrupt(void *arg)
163 {
164         struct intel_gt *gt = arg;
165         struct intel_rps *rps = &gt->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;
170         u32 pm_events;
171         int err = 0;
172
173         /*
174          * First, let's check whether or not we are receiving interrupts.
175          */
176
177         if (!rps->enabled || rps->max_freq <= rps->min_freq)
178                 return 0;
179
180         intel_gt_pm_get(gt);
181         pm_events = rps->pm_events;
182         intel_gt_pm_put(gt);
183         if (!pm_events) {
184                 pr_err("No RPS PM events registered, but RPS is enabled?\n");
185                 return -ENODEV;
186         }
187
188         if (igt_spinner_init(&spin, gt))
189                 return -ENOMEM;
190
191         intel_gt_pm_wait_for_idle(gt);
192         saved_work = rps->work.func;
193         rps->work.func = dummy_rps_work;
194
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);
199                         if (err)
200                                 goto out;
201                 }
202
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(&gt->rc6);
207
208                         err = __rps_down_interrupt(rps, engine);
209
210                         intel_rc6_enable(&gt->rc6);
211                         intel_engine_pm_put(engine);
212                         if (err)
213                                 goto out;
214                 }
215         }
216
217 out:
218         if (igt_flush_test(gt->i915))
219                 err = -EIO;
220
221         igt_spinner_fini(&spin);
222
223         intel_gt_pm_wait_for_idle(gt);
224         rps->work.func = saved_work;
225
226         return err;
227 }