e60600d14937c96294c2bd0fba76e4edbe1d8ac6
[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         mutex_lock(&rps->lock);
43         GEM_BUG_ON(!rps->active);
44         intel_rps_set(rps, rps->min_freq);
45         mutex_unlock(&rps->lock);
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         return 0;
109 }
110
111 static int __rps_down_interrupt(struct intel_rps *rps,
112                                 struct intel_engine_cs *engine)
113 {
114         struct intel_uncore *uncore = engine->uncore;
115         u32 timeout;
116
117         mutex_lock(&rps->lock);
118         GEM_BUG_ON(!rps->active);
119         intel_rps_set(rps, rps->max_freq);
120         mutex_unlock(&rps->lock);
121
122         if (!(rps->pm_events & GEN6_PM_RP_DOWN_THRESHOLD)) {
123                 pr_err("%s: RPS did not register DOWN interrupt\n",
124                        engine->name);
125                 return -EINVAL;
126         }
127
128         if (rps->last_freq != rps->max_freq) {
129                 pr_err("%s: RPS did not program max frequency\n",
130                        engine->name);
131                 return -EINVAL;
132         }
133
134         timeout = intel_uncore_read(uncore, GEN6_RP_DOWN_EI);
135         timeout = GT_PM_INTERVAL_TO_US(engine->i915, timeout);
136
137         sleep_for_ei(rps, timeout);
138
139         if (rps->cur_freq != rps->max_freq) {
140                 pr_err("%s: Frequency unexpectedly changed [down], now %d!\n",
141                        engine->name,
142                        intel_rps_read_actual_frequency(rps));
143                 return -EINVAL;
144         }
145
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));
155                 return -EINVAL;
156         }
157
158         return 0;
159 }
160
161 int live_rps_interrupt(void *arg)
162 {
163         struct intel_gt *gt = arg;
164         struct intel_rps *rps = &gt->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;
169         u32 pm_events;
170         int err = 0;
171
172         /*
173          * First, let's check whether or not we are receiving interrupts.
174          */
175
176         if (!rps->enabled || rps->max_freq <= rps->min_freq)
177                 return 0;
178
179         intel_gt_pm_get(gt);
180         pm_events = rps->pm_events;
181         intel_gt_pm_put(gt);
182         if (!pm_events) {
183                 pr_err("No RPS PM events registered, but RPS is enabled?\n");
184                 return -ENODEV;
185         }
186
187         if (igt_spinner_init(&spin, gt))
188                 return -ENOMEM;
189
190         intel_gt_pm_wait_for_idle(gt);
191         saved_work = rps->work.func;
192         rps->work.func = dummy_rps_work;
193
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);
199
200                         intel_engine_pm_get(engine);
201                         err = __rps_up_interrupt(rps, engine, &spin);
202                         intel_engine_pm_put(engine);
203                         if (err)
204                                 goto out;
205
206                         intel_gt_pm_wait_for_idle(engine->gt);
207                 }
208
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(&gt->rc6);
213
214                         err = __rps_down_interrupt(rps, engine);
215
216                         intel_rc6_enable(&gt->rc6);
217                         intel_engine_pm_put(engine);
218                         if (err)
219                                 goto out;
220                 }
221         }
222
223 out:
224         if (igt_flush_test(gt->i915))
225                 err = -EIO;
226
227         igt_spinner_fini(&spin);
228
229         intel_gt_pm_wait_for_idle(gt);
230         rps->work.func = saved_work;
231
232         return err;
233 }