blob: 8ba541c406fe2846196a4016995f96cd01b0efe9 [file] [log] [blame]
Ben Widawsky0cedccc2012-09-07 18:12:07 -07001/*
2 * Copyright © 2012 Intel Corporation
3 *
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:
10 *
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
13 * Software.
14 *
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
21 * IN THE SOFTWARE.
22 *
23 * Authors:
24 * Ben Widawsky <ben@bwidawsk.net>
25 *
26 */
27
28#define _GNU_SOURCE
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <unistd.h>
33#include "drmtest.h"
34
35static bool verbose = false;
36static int origmin, origmax;
37
38#define restore_assert(COND) do { \
39 if (!(COND)) { \
40 writeval(stuff[MIN].filp, origmin); \
41 writeval(stuff[MAX].filp, origmax); \
42 assert(0); \
43 } \
44} while (0);
45
46static const char sysfs_base_path[] = "/sys/class/drm/card%d/gt_%s_freq_mhz";
47enum {
48 CUR,
49 MIN,
50 MAX,
51 RP0,
52 RP1,
53 RPn
54};
55
56struct junk {
57 const char *name;
58 const char *mode;
59 FILE *filp;
60} stuff[] = {
61 { "cur", "r", NULL }, { "min", "rb+", NULL }, { "max", "rb+", NULL }, { "RP0", "r", NULL }, { "RP1", "r", NULL }, { "RPn", "r", NULL }, { NULL, NULL, NULL }
62};
63
64static int readval(FILE *filp)
65{
66 int val;
Imre Deak3a622b92012-10-10 16:04:42 +030067 int scanned;
68
Ben Widawsky0cedccc2012-09-07 18:12:07 -070069 fflush(filp);
70 rewind(filp);
Imre Deak3a622b92012-10-10 16:04:42 +030071 scanned = fscanf(filp, "%d", &val);
72 assert(scanned == 1);
73
Ben Widawsky0cedccc2012-09-07 18:12:07 -070074 return val;
75}
76
Ben Widawskydc3ac002012-10-15 10:05:56 -070077static int do_writeval(FILE *filp, int val, int lerrno)
Ben Widawsky0cedccc2012-09-07 18:12:07 -070078{
Ben Widawskydc3ac002012-10-15 10:05:56 -070079 /* Must write twice to sysfs since the first one simply calculates the size and won't return the error */
80 int ret;
Ben Widawsky0cedccc2012-09-07 18:12:07 -070081 rewind(filp);
Ben Widawskydc3ac002012-10-15 10:05:56 -070082 ret = fprintf(filp, "%d", val);
83 rewind(filp);
84 ret = fprintf(filp, "%d", val);
85 if (ret && lerrno)
86 assert(errno = lerrno);
Ben Widawsky0cedccc2012-09-07 18:12:07 -070087 fflush(filp);
Ben Widawskydc3ac002012-10-15 10:05:56 -070088 return ret;
Ben Widawsky0cedccc2012-09-07 18:12:07 -070089}
Ben Widawskydc3ac002012-10-15 10:05:56 -070090#define writeval(filp, val) do_writeval(filp, val, 0)
Ben Widawsky0cedccc2012-09-07 18:12:07 -070091
92#define fcur (readval(stuff[CUR].filp))
93#define fmin (readval(stuff[MIN].filp))
94#define fmax (readval(stuff[MAX].filp))
95#define frp0 (readval(stuff[RP0].filp))
96#define frp1 (readval(stuff[RP1].filp))
97#define frpn (readval(stuff[RPn].filp))
98
99static void setfreq(int val)
100{
101 writeval(stuff[MIN].filp, val);
102 writeval(stuff[MAX].filp, val);
103}
104
105static void checkit(void)
106{
107 restore_assert(fmin <= fmax);
108 restore_assert(fcur <= fmax);
109 restore_assert(fmin <= fcur);
110 restore_assert(frpn <= fmin);
111 restore_assert(fmax <= frp0);
112 restore_assert(frp1 <= frp0);
113 restore_assert(frpn <= frp1);
114 restore_assert(frp0 != 0);
115 restore_assert(frp1 != 0);
116}
117
118static void dumpit(void)
119{
120 struct junk *junk = stuff;
121 do {
122 printf("gt frequency %s (MHz): %d\n", junk->name, readval(junk->filp));
123 junk++;
124 } while(junk->name != NULL);
125
126 printf("\n");
127}
128
129
130int main(int argc, char *argv[])
131{
132 const int device = drm_get_card(0);
133 struct junk *junk = stuff;
134 int fd, ret;
135
136 if (argc > 1)
137 verbose++;
138
139 /* Use drm_open_any to verify device existence */
140 fd = drm_open_any();
141 close(fd);
142
143 do {
144 int val = -1;
145 char *path;
146 ret = asprintf(&path, sysfs_base_path, device, junk->name);
147 assert(ret != -1);
148 junk->filp = fopen(path, junk->mode);
149 if (junk->filp == NULL) {
Daniel Vetter021909e2012-11-27 20:04:15 +0100150 printf("Kernel is too old. GTFO\n");
Ben Widawsky0cedccc2012-09-07 18:12:07 -0700151 exit(77);
152 }
153 val = readval(junk->filp);
154 assert(val >= 0);
155 junk++;
156 } while(junk->name != NULL);
157
158 origmin = fmin;
159 origmax = fmax;
160
161 if (verbose)
162 printf("Original min = %d\nOriginal max = %d\n", origmin, origmax);
163
164 if (verbose)
165 dumpit();
166
167 checkit();
168 setfreq(fmin);
169 if (verbose)
170 dumpit();
171 restore_assert(fcur == fmin);
172 setfreq(fmax);
173 if (verbose)
174 dumpit();
175 restore_assert(fcur == fmax);
176 checkit();
177
178 /* And some errors */
179 writeval(stuff[MIN].filp, frpn - 1);
180 writeval(stuff[MAX].filp, frp0 + 1000);
181 checkit();
182
183 writeval(stuff[MIN].filp, fmax + 1000);
184 writeval(stuff[MAX].filp, fmin - 1);
185 checkit();
186
Ben Widawskydc3ac002012-10-15 10:05:56 -0700187 do_writeval(stuff[MIN].filp, 0x11111110, EINVAL);
188 do_writeval(stuff[MAX].filp, 0, EINVAL);
189
Ben Widawsky0cedccc2012-09-07 18:12:07 -0700190 writeval(stuff[MIN].filp, origmin);
191 writeval(stuff[MAX].filp, origmax);
192
193 exit(EXIT_SUCCESS);
194}