2 * Copyright © 2012 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * Ben Widawsky <ben@bwidawsk.net>
25 * Jeff McGee <jeff.mcgee@intel.com>
37 static bool verbose = false;
39 static const char sysfs_base_path[] = "/sys/class/drm/card%d/gt_%s_freq_mhz";
50 static int origfreqs[NUMFREQ];
57 { "cur", "r", NULL }, { "min", "rb+", NULL }, { "max", "rb+", NULL }, { "RP0", "r", NULL }, { "RP1", "r", NULL }, { "RPn", "r", NULL }, { NULL, NULL, NULL }
60 static int readval(FILE *filp)
66 scanned = fscanf(filp, "%d", &val);
67 igt_assert(scanned == 1);
72 static void read_freqs(int *freqs)
76 for (i = 0; i < NUMFREQ; i++)
77 freqs[i] = readval(stuff[i].filp);
80 static int do_writeval(FILE *filp, int val, int lerrno)
86 ret = fprintf(filp, "%d", val);
89 /* Expecting specific error */
90 igt_assert(ret == EOF && errno == lerrno);
91 igt_assert(readval(filp) == orig);
93 /* Expecting no error */
94 igt_assert(ret != EOF);
95 igt_assert(readval(filp) == val);
100 #define writeval(filp, val) do_writeval(filp, val, 0)
101 #define writeval_inval(filp, val) do_writeval(filp, val, EINVAL)
103 static void setfreq(int val)
105 if (val > readval(stuff[MAX].filp)) {
106 writeval(stuff[MAX].filp, val);
107 writeval(stuff[MIN].filp, val);
109 writeval(stuff[MIN].filp, val);
110 writeval(stuff[MAX].filp, val);
114 static void checkit(const int *freqs)
116 igt_assert(freqs[MIN] <= freqs[MAX]);
117 igt_assert(freqs[CUR] <= freqs[MAX]);
118 igt_assert(freqs[MIN] <= freqs[CUR]);
119 igt_assert(freqs[RPn] <= freqs[MIN]);
120 igt_assert(freqs[MAX] <= freqs[RP0]);
121 igt_assert(freqs[RP1] <= freqs[RP0]);
122 igt_assert(freqs[RPn] <= freqs[RP1]);
123 igt_assert(freqs[RP0] != 0);
124 igt_assert(freqs[RP1] != 0);
127 static void dumpit(const int *freqs)
131 for (i = 0; i < NUMFREQ; i++)
132 printf("gt frequency %s (MHz): %d\n", stuff[i].name, freqs[i]);
136 #define dump(x) if (verbose) dumpit(x)
137 #define log(...) if (verbose) printf(__VA_ARGS__)
139 static void min_max_config(void (*check)(void))
141 int fmid = (origfreqs[RPn] + origfreqs[RP0]) / 2;
143 log("Check original min and max...\n");
146 log("Set min=RPn and max=RP0...\n");
147 writeval(stuff[MIN].filp, origfreqs[RPn]);
148 writeval(stuff[MAX].filp, origfreqs[RP0]);
151 log("Increase min to midpoint...\n");
152 writeval(stuff[MIN].filp, fmid);
155 log("Increase min to RP0...\n");
156 writeval(stuff[MIN].filp, origfreqs[RP0]);
159 log("Increase min above RP0 (invalid)...\n");
160 writeval_inval(stuff[MIN].filp, origfreqs[RP0] + 1000);
163 log("Decrease max to RPn (invalid)...\n");
164 writeval_inval(stuff[MAX].filp, origfreqs[RPn]);
167 log("Decrease min to midpoint...\n");
168 writeval(stuff[MIN].filp, fmid);
171 log("Decrease min to RPn...\n");
172 writeval(stuff[MIN].filp, origfreqs[RPn]);
175 log("Decrease min below RPn (invalid)...\n");
176 writeval_inval(stuff[MIN].filp, 0);
179 log("Decrease max to midpoint...\n");
180 writeval(stuff[MAX].filp, fmid);
183 log("Decrease max to RPn...\n");
184 writeval(stuff[MAX].filp, origfreqs[RPn]);
187 log("Decrease max below RPn (invalid)...\n");
188 writeval_inval(stuff[MAX].filp, 0);
191 log("Increase min to RP0 (invalid)...\n");
192 writeval_inval(stuff[MIN].filp, origfreqs[RP0]);
195 log("Increase max to midpoint...\n");
196 writeval(stuff[MAX].filp, fmid);
199 log("Increase max to RP0...\n");
200 writeval(stuff[MAX].filp, origfreqs[RP0]);
203 log("Increase max above RP0 (invalid)...\n");
204 writeval_inval(stuff[MAX].filp, origfreqs[RP0] + 1000);
208 static void idle_check(void)
217 static void pm_rps_exit_handler(int sig)
219 if (origfreqs[MIN] > readval(stuff[MAX].filp)) {
220 writeval(stuff[MAX].filp, origfreqs[MAX]);
221 writeval(stuff[MIN].filp, origfreqs[MIN]);
223 writeval(stuff[MIN].filp, origfreqs[MIN]);
224 writeval(stuff[MAX].filp, origfreqs[MAX]);
228 static int opt_handler(int opt, int opt_index)
241 /* Mod of igt_subtest_init that adds our extra options */
242 static void subtest_init(int argc, char **argv)
244 struct option long_opts[] = {
245 {"verbose", 0, 0, 'v'}
247 const char *help_str = " -v, --verbose";
250 ret = igt_subtest_init_parse_opts(argc, argv, "v", long_opts,
251 help_str, opt_handler);
254 /* exit with no error for -h/--help */
255 exit(ret == -1 ? 0 : ret);
258 int main(int argc, char **argv)
260 subtest_init(argc, argv);
262 igt_skip_on_simulation();
265 const int device = drm_get_card();
266 struct junk *junk = stuff;
269 /* Use drm_open_any to verify device existence */
276 ret = asprintf(&path, sysfs_base_path, device, junk->name);
277 igt_assert(ret != -1);
278 junk->filp = fopen(path, junk->mode);
279 igt_require(junk->filp);
280 setbuf(junk->filp, NULL);
282 val = readval(junk->filp);
283 igt_assert(val >= 0);
285 } while(junk->name != NULL);
287 read_freqs(origfreqs);
289 igt_install_exit_handler(pm_rps_exit_handler);
292 igt_subtest("min-max-config-at-idle")
293 min_max_config(idle_check);