pm_rps: Use unbuffered I/O on sysfs files
[platform/upstream/intel-gpu-tools.git] / tests / pm_rps.c
1 /*
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  *    Jeff McGee <jeff.mcgee@intel.com>
26  *
27  */
28
29 #define _GNU_SOURCE
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include "drmtest.h"
35
36 static bool verbose = false;
37 static int origmin, origmax;
38
39 #define restore_assert(COND) do { \
40         if (!(COND)) { \
41                 writeval(stuff[MIN].filp, origmin); \
42                 writeval(stuff[MAX].filp, origmax); \
43                 igt_assert(0); \
44         } \
45 } while (0);
46
47 static const char sysfs_base_path[] = "/sys/class/drm/card%d/gt_%s_freq_mhz";
48 enum {
49         CUR,
50         MIN,
51         MAX,
52         RP0,
53         RP1,
54         RPn
55 };
56
57 struct junk {
58         const char *name;
59         const char *mode;
60         FILE *filp;
61 } stuff[] = {
62         { "cur", "r", NULL }, { "min", "rb+", NULL }, { "max", "rb+", NULL }, { "RP0", "r", NULL }, { "RP1", "r", NULL }, { "RPn", "r", NULL }, { NULL, NULL, NULL }
63 };
64
65 static int readval(FILE *filp)
66 {
67         int val;
68         int scanned;
69
70         rewind(filp);
71         scanned = fscanf(filp, "%d", &val);
72         igt_assert(scanned == 1);
73
74         return val;
75 }
76
77 static int do_writeval(FILE *filp, int val, int lerrno)
78 {
79         int ret;
80         rewind(filp);
81         ret = fprintf(filp, "%d", val);
82         if (ret && lerrno)
83                 igt_assert(errno = lerrno);
84         return ret;
85 }
86 #define writeval(filp, val) do_writeval(filp, val, 0)
87
88 #define fcur (readval(stuff[CUR].filp))
89 #define fmin (readval(stuff[MIN].filp))
90 #define fmax (readval(stuff[MAX].filp))
91 #define frp0 (readval(stuff[RP0].filp))
92 #define frp1 (readval(stuff[RP1].filp))
93 #define frpn (readval(stuff[RPn].filp))
94
95 static void setfreq(int val)
96 {
97         writeval(stuff[MIN].filp, val);
98         writeval(stuff[MAX].filp, val);
99 }
100
101 static void checkit(void)
102 {
103         restore_assert(fmin <= fmax);
104         restore_assert(fcur <= fmax);
105         restore_assert(fmin <= fcur);
106         restore_assert(frpn <= fmin);
107         restore_assert(fmax <= frp0);
108         restore_assert(frp1 <= frp0);
109         restore_assert(frpn <= frp1);
110         restore_assert(frp0 != 0);
111         restore_assert(frp1 != 0);
112 }
113
114 static void dumpit(void)
115 {
116         struct junk *junk = stuff;
117         do {
118                 printf("gt frequency %s (MHz):  %d\n", junk->name, readval(junk->filp));
119                 junk++;
120         } while(junk->name != NULL);
121
122         printf("\n");
123 }
124
125
126 igt_simple_main
127 {
128         const int device = drm_get_card();
129         struct junk *junk = stuff;
130         int fd, ret;
131
132         igt_skip_on_simulation();
133
134         /* Use drm_open_any to verify device existence */
135         fd = drm_open_any();
136         close(fd);
137
138         do {
139                 int val = -1;
140                 char *path;
141                 ret = asprintf(&path, sysfs_base_path, device, junk->name);
142                 igt_assert(ret != -1);
143                 junk->filp = fopen(path, junk->mode);
144                 igt_require(junk->filp);
145                 setbuf(junk->filp, NULL);
146
147                 val = readval(junk->filp);
148                 igt_assert(val >= 0);
149                 junk++;
150         } while(junk->name != NULL);
151
152         origmin = fmin;
153         origmax = fmax;
154
155         if (verbose)
156                 printf("Original min = %d\nOriginal max = %d\n", origmin, origmax);
157
158         if (verbose)
159                 dumpit();
160
161         checkit();
162         setfreq(fmin);
163         if (verbose)
164                 dumpit();
165         restore_assert(fcur == fmin);
166         setfreq(fmax);
167         if (verbose)
168                 dumpit();
169         restore_assert(fcur == fmax);
170         checkit();
171
172         /* And some errors */
173         writeval(stuff[MIN].filp, frpn - 1);
174         writeval(stuff[MAX].filp, frp0 + 1000);
175         checkit();
176
177         writeval(stuff[MIN].filp, fmax + 1000);
178         writeval(stuff[MAX].filp, fmin - 1);
179         checkit();
180
181         do_writeval(stuff[MIN].filp, 0x11111110, EINVAL);
182         do_writeval(stuff[MAX].filp, 0, EINVAL);
183
184         writeval(stuff[MIN].filp, origmin);
185         writeval(stuff[MAX].filp, origmax);
186 }