xref: /aosp_15_r20/external/igt-gpu-tools/tools/intel_residency.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2016 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker  *
4*d83cc019SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker  *
11*d83cc019SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker  * Software.
14*d83cc019SAndroid Build Coastguard Worker  *
15*d83cc019SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker  *
23*d83cc019SAndroid Build Coastguard Worker  * Authors: Paulo Zanoni <[email protected]>
24*d83cc019SAndroid Build Coastguard Worker  *
25*d83cc019SAndroid Build Coastguard Worker  */
26*d83cc019SAndroid Build Coastguard Worker 
27*d83cc019SAndroid Build Coastguard Worker #include <sys/time.h>
28*d83cc019SAndroid Build Coastguard Worker #include <sys/types.h>
29*d83cc019SAndroid Build Coastguard Worker #include <sys/stat.h>
30*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
31*d83cc019SAndroid Build Coastguard Worker #include <inttypes.h>
32*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
33*d83cc019SAndroid Build Coastguard Worker #include <signal.h>
34*d83cc019SAndroid Build Coastguard Worker #include <time.h>
35*d83cc019SAndroid Build Coastguard Worker #include <getopt.h>
36*d83cc019SAndroid Build Coastguard Worker #include "igt.h"
37*d83cc019SAndroid Build Coastguard Worker 
38*d83cc019SAndroid Build Coastguard Worker #define IA32_TIME_STAMP_COUNTER		0x10
39*d83cc019SAndroid Build Coastguard Worker 
40*d83cc019SAndroid Build Coastguard Worker #define MSR_PKG_CST_CONFIG_CONTROL	0xE2
41*d83cc019SAndroid Build Coastguard Worker #define  PKG_CST_LIMIT_MASK		0x7
42*d83cc019SAndroid Build Coastguard Worker #define  PKG_CST_LIMIT_C0		0x0
43*d83cc019SAndroid Build Coastguard Worker #define  PKG_CST_LIMIT_C2		0x1
44*d83cc019SAndroid Build Coastguard Worker #define  PKG_CST_LIMIT_C3		0x2
45*d83cc019SAndroid Build Coastguard Worker #define  PKG_CST_LIMIT_C6		0x3
46*d83cc019SAndroid Build Coastguard Worker #define  PKG_CST_LIMIT_C7		0x4
47*d83cc019SAndroid Build Coastguard Worker #define  PKG_CST_LIMIT_C7s		0x5
48*d83cc019SAndroid Build Coastguard Worker #define  PKG_CST_NO_LIMIT		0x7
49*d83cc019SAndroid Build Coastguard Worker 
50*d83cc019SAndroid Build Coastguard Worker #define MSR_PKG_C2_RESIDENCY		0x60D
51*d83cc019SAndroid Build Coastguard Worker #define MSR_PKG_C3_RESIDENCY		0x3F8
52*d83cc019SAndroid Build Coastguard Worker #define MSR_PKG_C6_RESIDENCY		0x3F9
53*d83cc019SAndroid Build Coastguard Worker #define MSR_PKG_C7_RESIDENCY		0x3FA
54*d83cc019SAndroid Build Coastguard Worker #define MSR_PKG_C8_RESIDENCY		0x630
55*d83cc019SAndroid Build Coastguard Worker #define MSR_PKG_C9_RESIDENCY		0x631
56*d83cc019SAndroid Build Coastguard Worker #define MSR_PKG_C10_RESIDENCY		0x632
57*d83cc019SAndroid Build Coastguard Worker 
58*d83cc019SAndroid Build Coastguard Worker #define NUM_PC_STATES 7
59*d83cc019SAndroid Build Coastguard Worker 
60*d83cc019SAndroid Build Coastguard Worker const char *res_msr_names[] = {
61*d83cc019SAndroid Build Coastguard Worker 	"PC2", "PC3", "PC6", "PC7", "PC8", "PC9", "PC10"
62*d83cc019SAndroid Build Coastguard Worker };
63*d83cc019SAndroid Build Coastguard Worker 
64*d83cc019SAndroid Build Coastguard Worker const uint32_t res_msr_addrs[] = {
65*d83cc019SAndroid Build Coastguard Worker 	MSR_PKG_C2_RESIDENCY,
66*d83cc019SAndroid Build Coastguard Worker 	MSR_PKG_C3_RESIDENCY,
67*d83cc019SAndroid Build Coastguard Worker 	MSR_PKG_C6_RESIDENCY,
68*d83cc019SAndroid Build Coastguard Worker 	MSR_PKG_C7_RESIDENCY,
69*d83cc019SAndroid Build Coastguard Worker 	MSR_PKG_C8_RESIDENCY,
70*d83cc019SAndroid Build Coastguard Worker 	MSR_PKG_C9_RESIDENCY,
71*d83cc019SAndroid Build Coastguard Worker 	MSR_PKG_C10_RESIDENCY,
72*d83cc019SAndroid Build Coastguard Worker };
73*d83cc019SAndroid Build Coastguard Worker 
74*d83cc019SAndroid Build Coastguard Worker int msr_fd;
75*d83cc019SAndroid Build Coastguard Worker 
76*d83cc019SAndroid Build Coastguard Worker uint32_t deepest_pc_state;
77*d83cc019SAndroid Build Coastguard Worker uint64_t idle_res;
78*d83cc019SAndroid Build Coastguard Worker 
79*d83cc019SAndroid Build Coastguard Worker #define MAX_CONNECTORS 32
80*d83cc019SAndroid Build Coastguard Worker #define MAX_PLANES 32
81*d83cc019SAndroid Build Coastguard Worker struct {
82*d83cc019SAndroid Build Coastguard Worker 	int fd;
83*d83cc019SAndroid Build Coastguard Worker 	drmModeResPtr res;
84*d83cc019SAndroid Build Coastguard Worker 	drmModeConnectorPtr connectors[MAX_CONNECTORS];
85*d83cc019SAndroid Build Coastguard Worker 	drm_intel_bufmgr *bufmgr;
86*d83cc019SAndroid Build Coastguard Worker } drm;
87*d83cc019SAndroid Build Coastguard Worker 
88*d83cc019SAndroid Build Coastguard Worker struct {
89*d83cc019SAndroid Build Coastguard Worker 	uint32_t crtc_id;
90*d83cc019SAndroid Build Coastguard Worker 	uint32_t connector_id;
91*d83cc019SAndroid Build Coastguard Worker 	drmModeModeInfoPtr mode;
92*d83cc019SAndroid Build Coastguard Worker } modeset;
93*d83cc019SAndroid Build Coastguard Worker 
94*d83cc019SAndroid Build Coastguard Worker int vblank_interval_us;
95*d83cc019SAndroid Build Coastguard Worker struct igt_fb fbs[2], cursor, *front_fb, *back_fb;
96*d83cc019SAndroid Build Coastguard Worker 
97*d83cc019SAndroid Build Coastguard Worker struct {
98*d83cc019SAndroid Build Coastguard Worker 	int draw_size;
99*d83cc019SAndroid Build Coastguard Worker 	bool do_page_flip;
100*d83cc019SAndroid Build Coastguard Worker 	bool do_draw;
101*d83cc019SAndroid Build Coastguard Worker 	bool do_draw_and_flip;
102*d83cc019SAndroid Build Coastguard Worker 	int res_warm_time;
103*d83cc019SAndroid Build Coastguard Worker 	int res_calc_time;
104*d83cc019SAndroid Build Coastguard Worker 	int loop_inc;
105*d83cc019SAndroid Build Coastguard Worker 	char *test_name;
106*d83cc019SAndroid Build Coastguard Worker } opts = {
107*d83cc019SAndroid Build Coastguard Worker 	.draw_size = 0,
108*d83cc019SAndroid Build Coastguard Worker 	.do_page_flip = true,
109*d83cc019SAndroid Build Coastguard Worker 	.do_draw = true,
110*d83cc019SAndroid Build Coastguard Worker 	.do_draw_and_flip = true,
111*d83cc019SAndroid Build Coastguard Worker 	.res_warm_time = 1,
112*d83cc019SAndroid Build Coastguard Worker 	.res_calc_time = 4,
113*d83cc019SAndroid Build Coastguard Worker 	.loop_inc = 2,
114*d83cc019SAndroid Build Coastguard Worker 	.test_name = NULL,
115*d83cc019SAndroid Build Coastguard Worker };
116*d83cc019SAndroid Build Coastguard Worker 
msr_read(uint32_t addr)117*d83cc019SAndroid Build Coastguard Worker static uint64_t msr_read(uint32_t addr)
118*d83cc019SAndroid Build Coastguard Worker {
119*d83cc019SAndroid Build Coastguard Worker 	int rc;
120*d83cc019SAndroid Build Coastguard Worker 	uint64_t ret;
121*d83cc019SAndroid Build Coastguard Worker 
122*d83cc019SAndroid Build Coastguard Worker 	rc = pread(msr_fd, &ret, sizeof(uint64_t), addr);
123*d83cc019SAndroid Build Coastguard Worker 	igt_assert(rc == sizeof(ret));
124*d83cc019SAndroid Build Coastguard Worker 
125*d83cc019SAndroid Build Coastguard Worker 	return ret;
126*d83cc019SAndroid Build Coastguard Worker }
127*d83cc019SAndroid Build Coastguard Worker 
setup_msr(void)128*d83cc019SAndroid Build Coastguard Worker static void setup_msr(void)
129*d83cc019SAndroid Build Coastguard Worker {
130*d83cc019SAndroid Build Coastguard Worker #if 0
131*d83cc019SAndroid Build Coastguard Worker 	uint64_t control;
132*d83cc019SAndroid Build Coastguard Worker 	const char *limit;
133*d83cc019SAndroid Build Coastguard Worker #endif
134*d83cc019SAndroid Build Coastguard Worker 
135*d83cc019SAndroid Build Coastguard Worker 	/* Make sure our Kernel supports MSR and the module is loaded. */
136*d83cc019SAndroid Build Coastguard Worker 	igt_assert(system("modprobe -q msr > /dev/null 2>&1") != -1);
137*d83cc019SAndroid Build Coastguard Worker 
138*d83cc019SAndroid Build Coastguard Worker 	msr_fd = open("/dev/cpu/0/msr", O_RDONLY);
139*d83cc019SAndroid Build Coastguard Worker 	igt_assert_f(msr_fd >= 0,
140*d83cc019SAndroid Build Coastguard Worker 		     "Can't open /dev/cpu/0/msr.\n");
141*d83cc019SAndroid Build Coastguard Worker 
142*d83cc019SAndroid Build Coastguard Worker #if 0
143*d83cc019SAndroid Build Coastguard Worker 	/* FIXME: why is this code not printing the truth? */
144*d83cc019SAndroid Build Coastguard Worker 	control = msr_read(MSR_PKG_CST_CONFIG_CONTROL);
145*d83cc019SAndroid Build Coastguard Worker 	printf("Control: 0x016%" PRIx64 "\n", control);
146*d83cc019SAndroid Build Coastguard Worker 	switch (control & PKG_CST_LIMIT_MASK) {
147*d83cc019SAndroid Build Coastguard Worker 	case PKG_CST_LIMIT_C0:
148*d83cc019SAndroid Build Coastguard Worker 		limit = "C0";
149*d83cc019SAndroid Build Coastguard Worker 		break;
150*d83cc019SAndroid Build Coastguard Worker 	case PKG_CST_LIMIT_C2:
151*d83cc019SAndroid Build Coastguard Worker 		limit = "C2";
152*d83cc019SAndroid Build Coastguard Worker 		break;
153*d83cc019SAndroid Build Coastguard Worker 	case PKG_CST_LIMIT_C3:
154*d83cc019SAndroid Build Coastguard Worker 		limit = "C3";
155*d83cc019SAndroid Build Coastguard Worker 		break;
156*d83cc019SAndroid Build Coastguard Worker 	case PKG_CST_LIMIT_C6:
157*d83cc019SAndroid Build Coastguard Worker 		limit = "C6";
158*d83cc019SAndroid Build Coastguard Worker 		break;
159*d83cc019SAndroid Build Coastguard Worker 	case PKG_CST_LIMIT_C7:
160*d83cc019SAndroid Build Coastguard Worker 		limit = "C7";
161*d83cc019SAndroid Build Coastguard Worker 		break;
162*d83cc019SAndroid Build Coastguard Worker 	case PKG_CST_LIMIT_C7s:
163*d83cc019SAndroid Build Coastguard Worker 		limit = "C7s";
164*d83cc019SAndroid Build Coastguard Worker 		break;
165*d83cc019SAndroid Build Coastguard Worker 	case PKG_CST_NO_LIMIT:
166*d83cc019SAndroid Build Coastguard Worker 		limit = "no limit";
167*d83cc019SAndroid Build Coastguard Worker 		break;
168*d83cc019SAndroid Build Coastguard Worker 	default:
169*d83cc019SAndroid Build Coastguard Worker 		limit = "unknown";
170*d83cc019SAndroid Build Coastguard Worker 		break;
171*d83cc019SAndroid Build Coastguard Worker 	}
172*d83cc019SAndroid Build Coastguard Worker 	printf("Package C state limit: %s\n", limit);
173*d83cc019SAndroid Build Coastguard Worker #endif
174*d83cc019SAndroid Build Coastguard Worker }
175*d83cc019SAndroid Build Coastguard Worker 
teardown_msr(void)176*d83cc019SAndroid Build Coastguard Worker static void teardown_msr(void)
177*d83cc019SAndroid Build Coastguard Worker {
178*d83cc019SAndroid Build Coastguard Worker 	close(msr_fd);
179*d83cc019SAndroid Build Coastguard Worker }
180*d83cc019SAndroid Build Coastguard Worker 
setup_drm(void)181*d83cc019SAndroid Build Coastguard Worker static void setup_drm(void)
182*d83cc019SAndroid Build Coastguard Worker {
183*d83cc019SAndroid Build Coastguard Worker 	int i;
184*d83cc019SAndroid Build Coastguard Worker 
185*d83cc019SAndroid Build Coastguard Worker 	drm.fd = drm_open_driver_master(DRIVER_INTEL);
186*d83cc019SAndroid Build Coastguard Worker 
187*d83cc019SAndroid Build Coastguard Worker 	drm.res = drmModeGetResources(drm.fd);
188*d83cc019SAndroid Build Coastguard Worker 	igt_assert(drm.res->count_connectors <= MAX_CONNECTORS);
189*d83cc019SAndroid Build Coastguard Worker 
190*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < drm.res->count_connectors; i++)
191*d83cc019SAndroid Build Coastguard Worker 		drm.connectors[i] = drmModeGetConnector(drm.fd,
192*d83cc019SAndroid Build Coastguard Worker 						drm.res->connectors[i]);
193*d83cc019SAndroid Build Coastguard Worker 
194*d83cc019SAndroid Build Coastguard Worker 	drm.bufmgr = drm_intel_bufmgr_gem_init(drm.fd, 4096);
195*d83cc019SAndroid Build Coastguard Worker 	igt_assert(drm.bufmgr);
196*d83cc019SAndroid Build Coastguard Worker 	drm_intel_bufmgr_gem_enable_reuse(drm.bufmgr);
197*d83cc019SAndroid Build Coastguard Worker }
198*d83cc019SAndroid Build Coastguard Worker 
teardown_drm(void)199*d83cc019SAndroid Build Coastguard Worker static void teardown_drm(void)
200*d83cc019SAndroid Build Coastguard Worker {
201*d83cc019SAndroid Build Coastguard Worker 	int i;
202*d83cc019SAndroid Build Coastguard Worker 
203*d83cc019SAndroid Build Coastguard Worker 	drm_intel_bufmgr_destroy(drm.bufmgr);
204*d83cc019SAndroid Build Coastguard Worker 
205*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < drm.res->count_connectors; i++)
206*d83cc019SAndroid Build Coastguard Worker 		drmModeFreeConnector(drm.connectors[i]);
207*d83cc019SAndroid Build Coastguard Worker 
208*d83cc019SAndroid Build Coastguard Worker 	drmModeFreeResources(drm.res);
209*d83cc019SAndroid Build Coastguard Worker 	close(drm.fd);
210*d83cc019SAndroid Build Coastguard Worker }
211*d83cc019SAndroid Build Coastguard Worker 
draw_rect(struct igt_fb * fb,enum igt_draw_method method,uint32_t color)212*d83cc019SAndroid Build Coastguard Worker static void draw_rect(struct igt_fb *fb, enum igt_draw_method method,
213*d83cc019SAndroid Build Coastguard Worker 		      uint32_t color)
214*d83cc019SAndroid Build Coastguard Worker {
215*d83cc019SAndroid Build Coastguard Worker 	drmModeClip clip;
216*d83cc019SAndroid Build Coastguard Worker 	int rc;
217*d83cc019SAndroid Build Coastguard Worker 
218*d83cc019SAndroid Build Coastguard Worker 	switch (opts.draw_size) {
219*d83cc019SAndroid Build Coastguard Worker 	case 0:
220*d83cc019SAndroid Build Coastguard Worker 		clip.x1 = fb->width / 2 - 32;
221*d83cc019SAndroid Build Coastguard Worker 		clip.x2 = fb->width / 2 + 32;
222*d83cc019SAndroid Build Coastguard Worker 		clip.y1 = fb->height / 2 - 32;
223*d83cc019SAndroid Build Coastguard Worker 		clip.y2 = fb->height / 2 + 32;
224*d83cc019SAndroid Build Coastguard Worker 		break;
225*d83cc019SAndroid Build Coastguard Worker 	case 1:
226*d83cc019SAndroid Build Coastguard Worker 		clip.x1 = fb->width / 4;
227*d83cc019SAndroid Build Coastguard Worker 		clip.x2 = fb->width / 4 + fb->width / 2;
228*d83cc019SAndroid Build Coastguard Worker 		clip.y1 = fb->height / 4;
229*d83cc019SAndroid Build Coastguard Worker 		clip.y2 = fb->height / 4 + fb->height / 2;
230*d83cc019SAndroid Build Coastguard Worker 		break;
231*d83cc019SAndroid Build Coastguard Worker 	case 2:
232*d83cc019SAndroid Build Coastguard Worker 		clip.x1 = 0;
233*d83cc019SAndroid Build Coastguard Worker 		clip.x2 = fb->width;
234*d83cc019SAndroid Build Coastguard Worker 		clip.y1 = 0;
235*d83cc019SAndroid Build Coastguard Worker 		clip.y2 = fb->height;
236*d83cc019SAndroid Build Coastguard Worker 		break;
237*d83cc019SAndroid Build Coastguard Worker 	default:
238*d83cc019SAndroid Build Coastguard Worker 		igt_assert(false);
239*d83cc019SAndroid Build Coastguard Worker 	}
240*d83cc019SAndroid Build Coastguard Worker 
241*d83cc019SAndroid Build Coastguard Worker 	igt_draw_rect_fb(drm.fd, drm.bufmgr, NULL, fb, method, clip.x1, clip.y1,
242*d83cc019SAndroid Build Coastguard Worker 			 clip.x2 - clip.x1, clip.y2 - clip.y1, color);
243*d83cc019SAndroid Build Coastguard Worker 
244*d83cc019SAndroid Build Coastguard Worker 	if (method == IGT_DRAW_MMAP_WC) {
245*d83cc019SAndroid Build Coastguard Worker 		rc = drmModeDirtyFB(drm.fd, fb->fb_id, &clip, 1);
246*d83cc019SAndroid Build Coastguard Worker 		igt_assert(rc == 0 || rc == -ENOSYS);
247*d83cc019SAndroid Build Coastguard Worker 	}
248*d83cc019SAndroid Build Coastguard Worker }
249*d83cc019SAndroid Build Coastguard Worker 
setup_modeset(void)250*d83cc019SAndroid Build Coastguard Worker static void setup_modeset(void)
251*d83cc019SAndroid Build Coastguard Worker {
252*d83cc019SAndroid Build Coastguard Worker 	int i;
253*d83cc019SAndroid Build Coastguard Worker 	drmModeConnectorPtr connector;
254*d83cc019SAndroid Build Coastguard Worker 
255*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < drm.res->count_connectors; i++) {
256*d83cc019SAndroid Build Coastguard Worker 		connector = drm.connectors[i];
257*d83cc019SAndroid Build Coastguard Worker 
258*d83cc019SAndroid Build Coastguard Worker 		if (connector->connection == DRM_MODE_CONNECTED &&
259*d83cc019SAndroid Build Coastguard Worker 		    connector->count_modes > 0)
260*d83cc019SAndroid Build Coastguard Worker 			break;
261*d83cc019SAndroid Build Coastguard Worker 	}
262*d83cc019SAndroid Build Coastguard Worker 	igt_assert(i < drm.res->count_connectors);
263*d83cc019SAndroid Build Coastguard Worker 
264*d83cc019SAndroid Build Coastguard Worker 	modeset.connector_id = connector->connector_id;
265*d83cc019SAndroid Build Coastguard Worker 	modeset.mode = &connector->modes[0];
266*d83cc019SAndroid Build Coastguard Worker 	modeset.crtc_id = kmstest_find_crtc_for_connector(drm.fd, drm.res,
267*d83cc019SAndroid Build Coastguard Worker 							  connector, 0);
268*d83cc019SAndroid Build Coastguard Worker 
269*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < 2; i++) {
270*d83cc019SAndroid Build Coastguard Worker 		igt_create_fb(drm.fd, modeset.mode->hdisplay,
271*d83cc019SAndroid Build Coastguard Worker 			      modeset.mode->vdisplay,  DRM_FORMAT_XRGB8888,
272*d83cc019SAndroid Build Coastguard Worker 			      LOCAL_I915_FORMAT_MOD_X_TILED, &fbs[i]);
273*d83cc019SAndroid Build Coastguard Worker 		igt_draw_fill_fb(drm.fd, &fbs[i], 0x80);
274*d83cc019SAndroid Build Coastguard Worker 	}
275*d83cc019SAndroid Build Coastguard Worker 	draw_rect(&fbs[1], IGT_DRAW_BLT, 0x800000);
276*d83cc019SAndroid Build Coastguard Worker 
277*d83cc019SAndroid Build Coastguard Worker 	igt_create_fb(drm.fd, 64, 64, DRM_FORMAT_ARGB8888,
278*d83cc019SAndroid Build Coastguard Worker 		     LOCAL_DRM_FORMAT_MOD_NONE, &cursor);
279*d83cc019SAndroid Build Coastguard Worker 	igt_draw_fill_fb(drm.fd, &cursor, 0xFF008000);
280*d83cc019SAndroid Build Coastguard Worker }
281*d83cc019SAndroid Build Coastguard Worker 
teardown_modeset(void)282*d83cc019SAndroid Build Coastguard Worker static void teardown_modeset(void)
283*d83cc019SAndroid Build Coastguard Worker {
284*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(drm.fd, &fbs[0]);
285*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(drm.fd, &fbs[1]);
286*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(drm.fd, &cursor);
287*d83cc019SAndroid Build Coastguard Worker }
288*d83cc019SAndroid Build Coastguard Worker 
setup_vblank_interval(void)289*d83cc019SAndroid Build Coastguard Worker static void setup_vblank_interval(void)
290*d83cc019SAndroid Build Coastguard Worker {
291*d83cc019SAndroid Build Coastguard Worker 	uint64_t vrefresh, interval;
292*d83cc019SAndroid Build Coastguard Worker 
293*d83cc019SAndroid Build Coastguard Worker 	vrefresh = ((uint64_t) modeset.mode->clock * 1000 * 1000) /
294*d83cc019SAndroid Build Coastguard Worker 		   (modeset.mode->htotal * modeset.mode->vtotal);
295*d83cc019SAndroid Build Coastguard Worker 	interval = 1000000000 / vrefresh;
296*d83cc019SAndroid Build Coastguard Worker 
297*d83cc019SAndroid Build Coastguard Worker 	vblank_interval_us = interval;
298*d83cc019SAndroid Build Coastguard Worker 
299*d83cc019SAndroid Build Coastguard Worker 	printf("Interval between vblanks:\t%dus\n", vblank_interval_us);
300*d83cc019SAndroid Build Coastguard Worker }
301*d83cc019SAndroid Build Coastguard Worker 
302*d83cc019SAndroid Build Coastguard Worker bool alarm_received;
alarm_handler(int signal)303*d83cc019SAndroid Build Coastguard Worker static void alarm_handler(int signal)
304*d83cc019SAndroid Build Coastguard Worker {
305*d83cc019SAndroid Build Coastguard Worker 	alarm_received = true;
306*d83cc019SAndroid Build Coastguard Worker }
307*d83cc019SAndroid Build Coastguard Worker 
setup_alarm(void)308*d83cc019SAndroid Build Coastguard Worker static void setup_alarm(void)
309*d83cc019SAndroid Build Coastguard Worker {
310*d83cc019SAndroid Build Coastguard Worker 	struct sigaction sa;
311*d83cc019SAndroid Build Coastguard Worker 
312*d83cc019SAndroid Build Coastguard Worker 	sa.sa_handler = alarm_handler;
313*d83cc019SAndroid Build Coastguard Worker 	sigemptyset(&sa.sa_mask);
314*d83cc019SAndroid Build Coastguard Worker 	sa.sa_flags = 0;
315*d83cc019SAndroid Build Coastguard Worker 	sigaction(SIGALRM, &sa, NULL);
316*d83cc019SAndroid Build Coastguard Worker }
317*d83cc019SAndroid Build Coastguard Worker 
set_alarm(time_t sec,suseconds_t usec)318*d83cc019SAndroid Build Coastguard Worker static void set_alarm(time_t sec, suseconds_t usec)
319*d83cc019SAndroid Build Coastguard Worker {
320*d83cc019SAndroid Build Coastguard Worker 	struct itimerval timerval = {{0, 0}, {sec, usec}};
321*d83cc019SAndroid Build Coastguard Worker 
322*d83cc019SAndroid Build Coastguard Worker 	alarm_received = false;
323*d83cc019SAndroid Build Coastguard Worker 	igt_assert(setitimer(ITIMER_REAL, &timerval, NULL) == 0);
324*d83cc019SAndroid Build Coastguard Worker }
325*d83cc019SAndroid Build Coastguard Worker 
unset_mode(void)326*d83cc019SAndroid Build Coastguard Worker static void unset_mode(void)
327*d83cc019SAndroid Build Coastguard Worker {
328*d83cc019SAndroid Build Coastguard Worker 	int rc;
329*d83cc019SAndroid Build Coastguard Worker 
330*d83cc019SAndroid Build Coastguard Worker 	kmstest_unset_all_crtcs(drm.fd, drm.res);
331*d83cc019SAndroid Build Coastguard Worker 	rc = drmModeSetCursor(drm.fd, modeset.crtc_id, 0, 0, 0);
332*d83cc019SAndroid Build Coastguard Worker 	igt_assert(rc == 0);
333*d83cc019SAndroid Build Coastguard Worker }
334*d83cc019SAndroid Build Coastguard Worker 
set_mode(void)335*d83cc019SAndroid Build Coastguard Worker static void set_mode(void)
336*d83cc019SAndroid Build Coastguard Worker {
337*d83cc019SAndroid Build Coastguard Worker 	int rc;
338*d83cc019SAndroid Build Coastguard Worker 
339*d83cc019SAndroid Build Coastguard Worker 	front_fb = &fbs[0];
340*d83cc019SAndroid Build Coastguard Worker 	back_fb = &fbs[1];
341*d83cc019SAndroid Build Coastguard Worker 	rc = drmModeSetCrtc(drm.fd, modeset.crtc_id, front_fb->fb_id, 0, 0,
342*d83cc019SAndroid Build Coastguard Worker 			    &modeset.connector_id, 1, modeset.mode);
343*d83cc019SAndroid Build Coastguard Worker 	igt_assert(rc == 0);
344*d83cc019SAndroid Build Coastguard Worker 
345*d83cc019SAndroid Build Coastguard Worker 	/* TODO: it seems we need a cursor in order to reach PC7 on BDW. Why? */
346*d83cc019SAndroid Build Coastguard Worker 	rc = drmModeMoveCursor(drm.fd, modeset.crtc_id, 0, 0);
347*d83cc019SAndroid Build Coastguard Worker 	igt_assert(rc == 0);
348*d83cc019SAndroid Build Coastguard Worker 
349*d83cc019SAndroid Build Coastguard Worker 	rc = drmModeSetCursor(drm.fd, modeset.crtc_id, cursor.gem_handle,
350*d83cc019SAndroid Build Coastguard Worker 			      cursor.width, cursor.height);
351*d83cc019SAndroid Build Coastguard Worker 	igt_assert(rc == 0);
352*d83cc019SAndroid Build Coastguard Worker }
353*d83cc019SAndroid Build Coastguard Worker 
wait_vblanks(int n_vblanks)354*d83cc019SAndroid Build Coastguard Worker static void wait_vblanks(int n_vblanks)
355*d83cc019SAndroid Build Coastguard Worker {
356*d83cc019SAndroid Build Coastguard Worker 	drmVBlank vblank;
357*d83cc019SAndroid Build Coastguard Worker 
358*d83cc019SAndroid Build Coastguard Worker 	if (!n_vblanks)
359*d83cc019SAndroid Build Coastguard Worker 		return;
360*d83cc019SAndroid Build Coastguard Worker 
361*d83cc019SAndroid Build Coastguard Worker 	vblank.request.type = DRM_VBLANK_RELATIVE;
362*d83cc019SAndroid Build Coastguard Worker 	vblank.request.sequence = n_vblanks;
363*d83cc019SAndroid Build Coastguard Worker 	vblank.request.signal = 0;
364*d83cc019SAndroid Build Coastguard Worker 	drmWaitVBlank(drm.fd, &vblank);
365*d83cc019SAndroid Build Coastguard Worker }
366*d83cc019SAndroid Build Coastguard Worker 
page_flip(void)367*d83cc019SAndroid Build Coastguard Worker static void page_flip(void)
368*d83cc019SAndroid Build Coastguard Worker {
369*d83cc019SAndroid Build Coastguard Worker 	struct igt_fb *tmp_fb;
370*d83cc019SAndroid Build Coastguard Worker 	int rc;
371*d83cc019SAndroid Build Coastguard Worker 
372*d83cc019SAndroid Build Coastguard Worker 	rc = drmModePageFlip(drm.fd, modeset.crtc_id, back_fb->fb_id, 0, NULL);
373*d83cc019SAndroid Build Coastguard Worker 	igt_assert(rc == 0);
374*d83cc019SAndroid Build Coastguard Worker 
375*d83cc019SAndroid Build Coastguard Worker 	tmp_fb = front_fb;
376*d83cc019SAndroid Build Coastguard Worker 	front_fb = back_fb;
377*d83cc019SAndroid Build Coastguard Worker 	back_fb = tmp_fb;
378*d83cc019SAndroid Build Coastguard Worker }
379*d83cc019SAndroid Build Coastguard Worker 
wait_until_idle(void)380*d83cc019SAndroid Build Coastguard Worker static void wait_until_idle(void)
381*d83cc019SAndroid Build Coastguard Worker {
382*d83cc019SAndroid Build Coastguard Worker 	uint64_t tsc, pc, res;
383*d83cc019SAndroid Build Coastguard Worker 
384*d83cc019SAndroid Build Coastguard Worker 	do {
385*d83cc019SAndroid Build Coastguard Worker 		set_alarm(0, 500 * 1000);
386*d83cc019SAndroid Build Coastguard Worker 
387*d83cc019SAndroid Build Coastguard Worker 		tsc = msr_read(IA32_TIME_STAMP_COUNTER);
388*d83cc019SAndroid Build Coastguard Worker 		pc = msr_read(deepest_pc_state);
389*d83cc019SAndroid Build Coastguard Worker 
390*d83cc019SAndroid Build Coastguard Worker 		while (!alarm_received)
391*d83cc019SAndroid Build Coastguard Worker 			pause();
392*d83cc019SAndroid Build Coastguard Worker 
393*d83cc019SAndroid Build Coastguard Worker 		pc = msr_read(deepest_pc_state) - pc;
394*d83cc019SAndroid Build Coastguard Worker 		tsc = msr_read(IA32_TIME_STAMP_COUNTER) - tsc;
395*d83cc019SAndroid Build Coastguard Worker 
396*d83cc019SAndroid Build Coastguard Worker 		res = pc * 100 / tsc;
397*d83cc019SAndroid Build Coastguard Worker 
398*d83cc019SAndroid Build Coastguard Worker 		/*printf("res:%02"PRIu64"\n", res);*/
399*d83cc019SAndroid Build Coastguard Worker 	} while (res < idle_res && idle_res - res > 3);
400*d83cc019SAndroid Build Coastguard Worker 
401*d83cc019SAndroid Build Coastguard Worker 	if (res > idle_res && res - idle_res > 3)
402*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "The calculated idle residency may be too low "
403*d83cc019SAndroid Build Coastguard Worker 			"(got %02"PRIu64"%%)\n", res);
404*d83cc019SAndroid Build Coastguard Worker }
405*d83cc019SAndroid Build Coastguard Worker 
do_measurement(void (* callback)(void * ptr),void * ptr)406*d83cc019SAndroid Build Coastguard Worker static uint64_t do_measurement(void (*callback)(void *ptr), void *ptr)
407*d83cc019SAndroid Build Coastguard Worker {
408*d83cc019SAndroid Build Coastguard Worker 	uint64_t tsc, pc;
409*d83cc019SAndroid Build Coastguard Worker 
410*d83cc019SAndroid Build Coastguard Worker 	wait_until_idle();
411*d83cc019SAndroid Build Coastguard Worker 
412*d83cc019SAndroid Build Coastguard Worker 	set_alarm(opts.res_warm_time, 0);
413*d83cc019SAndroid Build Coastguard Worker 	callback(ptr);
414*d83cc019SAndroid Build Coastguard Worker 
415*d83cc019SAndroid Build Coastguard Worker 	set_alarm(opts.res_calc_time, 0);
416*d83cc019SAndroid Build Coastguard Worker 
417*d83cc019SAndroid Build Coastguard Worker 	tsc = msr_read(IA32_TIME_STAMP_COUNTER);
418*d83cc019SAndroid Build Coastguard Worker 	pc = msr_read(deepest_pc_state);
419*d83cc019SAndroid Build Coastguard Worker 
420*d83cc019SAndroid Build Coastguard Worker 	callback(ptr);
421*d83cc019SAndroid Build Coastguard Worker 
422*d83cc019SAndroid Build Coastguard Worker 	pc = msr_read(deepest_pc_state) - pc;
423*d83cc019SAndroid Build Coastguard Worker 	tsc = msr_read(IA32_TIME_STAMP_COUNTER) - tsc;
424*d83cc019SAndroid Build Coastguard Worker 
425*d83cc019SAndroid Build Coastguard Worker 	return pc * 100 / tsc;
426*d83cc019SAndroid Build Coastguard Worker }
427*d83cc019SAndroid Build Coastguard Worker 
setup_idle(void)428*d83cc019SAndroid Build Coastguard Worker static void setup_idle(void)
429*d83cc019SAndroid Build Coastguard Worker {
430*d83cc019SAndroid Build Coastguard Worker 	uint64_t tsc, pc[NUM_PC_STATES], res, best_res;
431*d83cc019SAndroid Build Coastguard Worker 	int pc_i, best_pc_i = 0, retries, consecutive_not_best;
432*d83cc019SAndroid Build Coastguard Worker 
433*d83cc019SAndroid Build Coastguard Worker 	for (retries = 0; ; retries++) {
434*d83cc019SAndroid Build Coastguard Worker 
435*d83cc019SAndroid Build Coastguard Worker 		set_alarm(opts.res_warm_time, 0);
436*d83cc019SAndroid Build Coastguard Worker 		while (!alarm_received)
437*d83cc019SAndroid Build Coastguard Worker 			pause();
438*d83cc019SAndroid Build Coastguard Worker 
439*d83cc019SAndroid Build Coastguard Worker 		set_alarm(opts.res_calc_time, 0);
440*d83cc019SAndroid Build Coastguard Worker 
441*d83cc019SAndroid Build Coastguard Worker 		tsc = msr_read(IA32_TIME_STAMP_COUNTER);
442*d83cc019SAndroid Build Coastguard Worker 		for (pc_i = best_pc_i; pc_i < NUM_PC_STATES; pc_i++)
443*d83cc019SAndroid Build Coastguard Worker 			pc[pc_i] = msr_read(res_msr_addrs[pc_i]);
444*d83cc019SAndroid Build Coastguard Worker 
445*d83cc019SAndroid Build Coastguard Worker 		while (!alarm_received)
446*d83cc019SAndroid Build Coastguard Worker 			pause();
447*d83cc019SAndroid Build Coastguard Worker 
448*d83cc019SAndroid Build Coastguard Worker 		for (pc_i = best_pc_i; pc_i < NUM_PC_STATES; pc_i++)
449*d83cc019SAndroid Build Coastguard Worker 			pc[pc_i] = msr_read(res_msr_addrs[pc_i]) - pc[pc_i];
450*d83cc019SAndroid Build Coastguard Worker 		tsc = msr_read(IA32_TIME_STAMP_COUNTER) - tsc;
451*d83cc019SAndroid Build Coastguard Worker 
452*d83cc019SAndroid Build Coastguard Worker 		for (pc_i = NUM_PC_STATES -1; pc_i >= best_pc_i; pc_i--)
453*d83cc019SAndroid Build Coastguard Worker 			if (pc[pc_i] != 0)
454*d83cc019SAndroid Build Coastguard Worker 				break;
455*d83cc019SAndroid Build Coastguard Worker 		igt_require_f(pc_i >= 0, "We're not reaching any PC states!\n");
456*d83cc019SAndroid Build Coastguard Worker 
457*d83cc019SAndroid Build Coastguard Worker 		res = pc[pc_i] * 100 / tsc;
458*d83cc019SAndroid Build Coastguard Worker 
459*d83cc019SAndroid Build Coastguard Worker 		if (retries == 0 || pc_i > best_pc_i || res > best_res) {
460*d83cc019SAndroid Build Coastguard Worker 			best_pc_i = pc_i;
461*d83cc019SAndroid Build Coastguard Worker 			best_res = res;
462*d83cc019SAndroid Build Coastguard Worker 			consecutive_not_best = 0;
463*d83cc019SAndroid Build Coastguard Worker 		} else {
464*d83cc019SAndroid Build Coastguard Worker 			consecutive_not_best++;
465*d83cc019SAndroid Build Coastguard Worker 			if (consecutive_not_best > 2)
466*d83cc019SAndroid Build Coastguard Worker 				break;
467*d83cc019SAndroid Build Coastguard Worker 		}
468*d83cc019SAndroid Build Coastguard Worker 	}
469*d83cc019SAndroid Build Coastguard Worker 
470*d83cc019SAndroid Build Coastguard Worker 	deepest_pc_state = res_msr_addrs[best_pc_i];
471*d83cc019SAndroid Build Coastguard Worker 	idle_res = best_res;
472*d83cc019SAndroid Build Coastguard Worker 
473*d83cc019SAndroid Build Coastguard Worker 	printf("Stable idle residency retries:\t%d\n", retries);
474*d83cc019SAndroid Build Coastguard Worker 	printf("Deepest PC state reached when idle:\t%s\n",
475*d83cc019SAndroid Build Coastguard Worker 	       res_msr_names[best_pc_i]);
476*d83cc019SAndroid Build Coastguard Worker 	printf("Idle residency for this state:\t%02"PRIu64"%%\n", idle_res);
477*d83cc019SAndroid Build Coastguard Worker }
478*d83cc019SAndroid Build Coastguard Worker 
print_result(int ops,int vblanks,uint64_t res)479*d83cc019SAndroid Build Coastguard Worker static void print_result(int ops, int vblanks, uint64_t res)
480*d83cc019SAndroid Build Coastguard Worker {
481*d83cc019SAndroid Build Coastguard Worker 	printf("- %02d ops every %02d vblanks:\t%02"PRIu64"%%\n",
482*d83cc019SAndroid Build Coastguard Worker 	       ops, vblanks, res);
483*d83cc019SAndroid Build Coastguard Worker 	fflush(stdout);
484*d83cc019SAndroid Build Coastguard Worker }
485*d83cc019SAndroid Build Coastguard Worker 
486*d83cc019SAndroid Build Coastguard Worker struct page_flip_data {
487*d83cc019SAndroid Build Coastguard Worker 	int n_vblanks;
488*d83cc019SAndroid Build Coastguard Worker };
489*d83cc019SAndroid Build Coastguard Worker 
page_flip_cb(void * ptr)490*d83cc019SAndroid Build Coastguard Worker static void page_flip_cb(void *ptr)
491*d83cc019SAndroid Build Coastguard Worker {
492*d83cc019SAndroid Build Coastguard Worker 	struct page_flip_data *data = ptr;
493*d83cc019SAndroid Build Coastguard Worker 
494*d83cc019SAndroid Build Coastguard Worker 	while (!alarm_received) {
495*d83cc019SAndroid Build Coastguard Worker 		page_flip();
496*d83cc019SAndroid Build Coastguard Worker 		wait_vblanks(data->n_vblanks);
497*d83cc019SAndroid Build Coastguard Worker 	}
498*d83cc019SAndroid Build Coastguard Worker }
499*d83cc019SAndroid Build Coastguard Worker 
page_flip_test(void)500*d83cc019SAndroid Build Coastguard Worker static void page_flip_test(void)
501*d83cc019SAndroid Build Coastguard Worker {
502*d83cc019SAndroid Build Coastguard Worker 	struct page_flip_data data;
503*d83cc019SAndroid Build Coastguard Worker 	int n_vblanks;
504*d83cc019SAndroid Build Coastguard Worker 	uint64_t res;
505*d83cc019SAndroid Build Coastguard Worker 
506*d83cc019SAndroid Build Coastguard Worker 	printf("\nPage flip test:\n");
507*d83cc019SAndroid Build Coastguard Worker 
508*d83cc019SAndroid Build Coastguard Worker 	for (n_vblanks = 1; n_vblanks <= 64; n_vblanks *= opts.loop_inc) {
509*d83cc019SAndroid Build Coastguard Worker 		data.n_vblanks = n_vblanks;
510*d83cc019SAndroid Build Coastguard Worker 		res = do_measurement(page_flip_cb, &data);
511*d83cc019SAndroid Build Coastguard Worker 		print_result(1, n_vblanks, res);
512*d83cc019SAndroid Build Coastguard Worker 	}
513*d83cc019SAndroid Build Coastguard Worker }
514*d83cc019SAndroid Build Coastguard Worker 
515*d83cc019SAndroid Build Coastguard Worker struct draw_data {
516*d83cc019SAndroid Build Coastguard Worker 	enum igt_draw_method method;
517*d83cc019SAndroid Build Coastguard Worker 	int n_vblanks;
518*d83cc019SAndroid Build Coastguard Worker 	int ops_per_vblank;
519*d83cc019SAndroid Build Coastguard Worker };
520*d83cc019SAndroid Build Coastguard Worker 
draw_cb(void * ptr)521*d83cc019SAndroid Build Coastguard Worker static void draw_cb(void *ptr)
522*d83cc019SAndroid Build Coastguard Worker {
523*d83cc019SAndroid Build Coastguard Worker 	struct draw_data *data = ptr;
524*d83cc019SAndroid Build Coastguard Worker 	struct timespec req;
525*d83cc019SAndroid Build Coastguard Worker 	int i, ops;
526*d83cc019SAndroid Build Coastguard Worker 
527*d83cc019SAndroid Build Coastguard Worker 	req.tv_sec = 0;
528*d83cc019SAndroid Build Coastguard Worker 	req.tv_nsec = vblank_interval_us * 1000 / data->ops_per_vblank;
529*d83cc019SAndroid Build Coastguard Worker 
530*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; !alarm_received; i++) {
531*d83cc019SAndroid Build Coastguard Worker 		for (ops = 0; ops < data->ops_per_vblank; ops++) {
532*d83cc019SAndroid Build Coastguard Worker 			draw_rect(front_fb, data->method, i << 8);
533*d83cc019SAndroid Build Coastguard Worker 
534*d83cc019SAndroid Build Coastguard Worker 			/* The code that stops the callbacks relies on SIGALRM,
535*d83cc019SAndroid Build Coastguard Worker 			 * so we have to use nanosleep since it doesn't use
536*d83cc019SAndroid Build Coastguard Worker 			 * signals. */
537*d83cc019SAndroid Build Coastguard Worker 			if (data->ops_per_vblank > 1)
538*d83cc019SAndroid Build Coastguard Worker 				nanosleep(&req, NULL);
539*d83cc019SAndroid Build Coastguard Worker 		}
540*d83cc019SAndroid Build Coastguard Worker 
541*d83cc019SAndroid Build Coastguard Worker 		if (data->n_vblanks)
542*d83cc019SAndroid Build Coastguard Worker 			wait_vblanks(data->n_vblanks);
543*d83cc019SAndroid Build Coastguard Worker 	}
544*d83cc019SAndroid Build Coastguard Worker }
545*d83cc019SAndroid Build Coastguard Worker 
draw_test(void)546*d83cc019SAndroid Build Coastguard Worker static void draw_test(void)
547*d83cc019SAndroid Build Coastguard Worker {
548*d83cc019SAndroid Build Coastguard Worker 	struct draw_data data;
549*d83cc019SAndroid Build Coastguard Worker 	enum igt_draw_method method;
550*d83cc019SAndroid Build Coastguard Worker 	int i;
551*d83cc019SAndroid Build Coastguard Worker 	uint64_t res;
552*d83cc019SAndroid Build Coastguard Worker 
553*d83cc019SAndroid Build Coastguard Worker 	for (method = 0; method < IGT_DRAW_METHOD_COUNT; method++) {
554*d83cc019SAndroid Build Coastguard Worker 		data.method = method;
555*d83cc019SAndroid Build Coastguard Worker 
556*d83cc019SAndroid Build Coastguard Worker 		printf("\nDraw %s test:\n",
557*d83cc019SAndroid Build Coastguard Worker 		       igt_draw_get_method_name(method));
558*d83cc019SAndroid Build Coastguard Worker 
559*d83cc019SAndroid Build Coastguard Worker 		data.n_vblanks = 0;
560*d83cc019SAndroid Build Coastguard Worker 		for (i = 32; i >= 2; i /= opts.loop_inc) {
561*d83cc019SAndroid Build Coastguard Worker 			data.ops_per_vblank = i;
562*d83cc019SAndroid Build Coastguard Worker 			res = do_measurement(draw_cb, &data);
563*d83cc019SAndroid Build Coastguard Worker 			print_result(i, 1, res);
564*d83cc019SAndroid Build Coastguard Worker 		}
565*d83cc019SAndroid Build Coastguard Worker 
566*d83cc019SAndroid Build Coastguard Worker 		data.ops_per_vblank = 1;
567*d83cc019SAndroid Build Coastguard Worker 		for (i = 1; i <= 64; i *= opts.loop_inc) {
568*d83cc019SAndroid Build Coastguard Worker 			data.n_vblanks = i ;
569*d83cc019SAndroid Build Coastguard Worker 			res = do_measurement(draw_cb, &data);
570*d83cc019SAndroid Build Coastguard Worker 			print_result(1, i, res);
571*d83cc019SAndroid Build Coastguard Worker 		}
572*d83cc019SAndroid Build Coastguard Worker 	}
573*d83cc019SAndroid Build Coastguard Worker }
574*d83cc019SAndroid Build Coastguard Worker 
draw_and_flip_cb(void * ptr)575*d83cc019SAndroid Build Coastguard Worker static void draw_and_flip_cb(void *ptr)
576*d83cc019SAndroid Build Coastguard Worker {
577*d83cc019SAndroid Build Coastguard Worker 	struct draw_data *data = ptr;
578*d83cc019SAndroid Build Coastguard Worker 	int i, ops;
579*d83cc019SAndroid Build Coastguard Worker 
580*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; !alarm_received; i++) {
581*d83cc019SAndroid Build Coastguard Worker 		for (ops = 0; ops < data->ops_per_vblank; ops++)
582*d83cc019SAndroid Build Coastguard Worker 			draw_rect(back_fb, data->method, i << 8);
583*d83cc019SAndroid Build Coastguard Worker 
584*d83cc019SAndroid Build Coastguard Worker 		page_flip();
585*d83cc019SAndroid Build Coastguard Worker 		wait_vblanks(1);
586*d83cc019SAndroid Build Coastguard Worker 	}
587*d83cc019SAndroid Build Coastguard Worker }
588*d83cc019SAndroid Build Coastguard Worker 
draw_and_flip_test(void)589*d83cc019SAndroid Build Coastguard Worker static void draw_and_flip_test(void)
590*d83cc019SAndroid Build Coastguard Worker {
591*d83cc019SAndroid Build Coastguard Worker 	struct draw_data data;
592*d83cc019SAndroid Build Coastguard Worker 	enum igt_draw_method method;
593*d83cc019SAndroid Build Coastguard Worker 	int i;
594*d83cc019SAndroid Build Coastguard Worker 	uint64_t res;
595*d83cc019SAndroid Build Coastguard Worker 
596*d83cc019SAndroid Build Coastguard Worker 	for (method = 0; method < IGT_DRAW_METHOD_COUNT; method++) {
597*d83cc019SAndroid Build Coastguard Worker 		data.method = method;
598*d83cc019SAndroid Build Coastguard Worker 
599*d83cc019SAndroid Build Coastguard Worker 		/* Doing everything consumes too much time! */
600*d83cc019SAndroid Build Coastguard Worker 		if (method != IGT_DRAW_MMAP_CPU && method != IGT_DRAW_BLT)
601*d83cc019SAndroid Build Coastguard Worker 			continue;
602*d83cc019SAndroid Build Coastguard Worker 
603*d83cc019SAndroid Build Coastguard Worker 		printf("\nDraw and flip %s test:\n",
604*d83cc019SAndroid Build Coastguard Worker 		       igt_draw_get_method_name(method));
605*d83cc019SAndroid Build Coastguard Worker 
606*d83cc019SAndroid Build Coastguard Worker 		for (i = 16; i >= 1; i /= opts.loop_inc) {
607*d83cc019SAndroid Build Coastguard Worker 			data.ops_per_vblank = 1;
608*d83cc019SAndroid Build Coastguard Worker 			res = do_measurement(draw_and_flip_cb, &data);
609*d83cc019SAndroid Build Coastguard Worker 			print_result(i, 1, res);
610*d83cc019SAndroid Build Coastguard Worker 		}
611*d83cc019SAndroid Build Coastguard Worker 	}
612*d83cc019SAndroid Build Coastguard Worker }
613*d83cc019SAndroid Build Coastguard Worker 
parse_opts(int argc,char * argv[])614*d83cc019SAndroid Build Coastguard Worker static void parse_opts(int argc, char *argv[])
615*d83cc019SAndroid Build Coastguard Worker {
616*d83cc019SAndroid Build Coastguard Worker 	int opt;
617*d83cc019SAndroid Build Coastguard Worker 	char short_opts[] = "d:lrbw:c:i:fsn:";
618*d83cc019SAndroid Build Coastguard Worker 	struct option long_opts[] = {
619*d83cc019SAndroid Build Coastguard Worker 		{ "draw-size",        required_argument, NULL, 'd'},
620*d83cc019SAndroid Build Coastguard Worker 		{ "no-flip",          no_argument,       NULL, 'l'},
621*d83cc019SAndroid Build Coastguard Worker 		{ "no-draw",          no_argument,       NULL, 'r'},
622*d83cc019SAndroid Build Coastguard Worker 		{ "no-draw-and-flip", no_argument,       NULL, 'b'},
623*d83cc019SAndroid Build Coastguard Worker 		{ "warm-time",        required_argument, NULL, 'w'},
624*d83cc019SAndroid Build Coastguard Worker 		{ "calc-time",        required_argument, NULL, 'c'},
625*d83cc019SAndroid Build Coastguard Worker 		{ "loop-increment",   required_argument, NULL, 'i'},
626*d83cc019SAndroid Build Coastguard Worker 		{ "fast",             no_argument,       NULL, 'f'},
627*d83cc019SAndroid Build Coastguard Worker 		{ "slow",             no_argument,       NULL, 's'},
628*d83cc019SAndroid Build Coastguard Worker 		{ "name",             required_argument, NULL, 'n'},
629*d83cc019SAndroid Build Coastguard Worker 		{ 0 },
630*d83cc019SAndroid Build Coastguard Worker 	};
631*d83cc019SAndroid Build Coastguard Worker 
632*d83cc019SAndroid Build Coastguard Worker 	while (1) {
633*d83cc019SAndroid Build Coastguard Worker 		opt = getopt_long(argc, argv, short_opts, long_opts, NULL);
634*d83cc019SAndroid Build Coastguard Worker 
635*d83cc019SAndroid Build Coastguard Worker 		switch (opt) {
636*d83cc019SAndroid Build Coastguard Worker 		case 'd':
637*d83cc019SAndroid Build Coastguard Worker 			if (strcmp(optarg, "s") == 0)
638*d83cc019SAndroid Build Coastguard Worker 				opts.draw_size = 0;
639*d83cc019SAndroid Build Coastguard Worker 			else if (strcmp(optarg, "m") == 0)
640*d83cc019SAndroid Build Coastguard Worker 				opts.draw_size = 1;
641*d83cc019SAndroid Build Coastguard Worker 			else if (strcmp(optarg, "l") == 0)
642*d83cc019SAndroid Build Coastguard Worker 				opts.draw_size = 2;
643*d83cc019SAndroid Build Coastguard Worker 			else
644*d83cc019SAndroid Build Coastguard Worker 				igt_assert(false);
645*d83cc019SAndroid Build Coastguard Worker 			break;
646*d83cc019SAndroid Build Coastguard Worker 		case 'l':
647*d83cc019SAndroid Build Coastguard Worker 			opts.do_page_flip = false;
648*d83cc019SAndroid Build Coastguard Worker 			break;
649*d83cc019SAndroid Build Coastguard Worker 		case 'r':
650*d83cc019SAndroid Build Coastguard Worker 			opts.do_draw = false;
651*d83cc019SAndroid Build Coastguard Worker 			break;
652*d83cc019SAndroid Build Coastguard Worker 		case 'b':
653*d83cc019SAndroid Build Coastguard Worker 			opts.do_draw_and_flip = false;
654*d83cc019SAndroid Build Coastguard Worker 			break;
655*d83cc019SAndroid Build Coastguard Worker 		case 'w':
656*d83cc019SAndroid Build Coastguard Worker 			opts.res_warm_time = atoi(optarg);
657*d83cc019SAndroid Build Coastguard Worker 			break;
658*d83cc019SAndroid Build Coastguard Worker 		case 'c':
659*d83cc019SAndroid Build Coastguard Worker 			opts.res_calc_time = atoi(optarg);
660*d83cc019SAndroid Build Coastguard Worker 			break;
661*d83cc019SAndroid Build Coastguard Worker 		case 'i':
662*d83cc019SAndroid Build Coastguard Worker 			opts.loop_inc = atoi(optarg);
663*d83cc019SAndroid Build Coastguard Worker 			break;
664*d83cc019SAndroid Build Coastguard Worker 		case 'f':
665*d83cc019SAndroid Build Coastguard Worker 			opts.res_warm_time = 1;
666*d83cc019SAndroid Build Coastguard Worker 			opts.res_calc_time = 2;
667*d83cc019SAndroid Build Coastguard Worker 			opts.loop_inc = 4;
668*d83cc019SAndroid Build Coastguard Worker 			break;
669*d83cc019SAndroid Build Coastguard Worker 		case 's':
670*d83cc019SAndroid Build Coastguard Worker 			opts.res_warm_time = 2;
671*d83cc019SAndroid Build Coastguard Worker 			opts.res_calc_time = 6;
672*d83cc019SAndroid Build Coastguard Worker 			opts.loop_inc = 2;
673*d83cc019SAndroid Build Coastguard Worker 			break;
674*d83cc019SAndroid Build Coastguard Worker 		case 'n':
675*d83cc019SAndroid Build Coastguard Worker 			opts.test_name = optarg;
676*d83cc019SAndroid Build Coastguard Worker 			break;
677*d83cc019SAndroid Build Coastguard Worker 		case -1:
678*d83cc019SAndroid Build Coastguard Worker 			return;
679*d83cc019SAndroid Build Coastguard Worker 		default:
680*d83cc019SAndroid Build Coastguard Worker 			igt_assert(false);
681*d83cc019SAndroid Build Coastguard Worker 		}
682*d83cc019SAndroid Build Coastguard Worker 	}
683*d83cc019SAndroid Build Coastguard Worker }
684*d83cc019SAndroid Build Coastguard Worker 
main(int argc,char * argv[])685*d83cc019SAndroid Build Coastguard Worker int main(int argc, char *argv[])
686*d83cc019SAndroid Build Coastguard Worker {
687*d83cc019SAndroid Build Coastguard Worker 	parse_opts(argc, argv);
688*d83cc019SAndroid Build Coastguard Worker 
689*d83cc019SAndroid Build Coastguard Worker 	setup_msr();
690*d83cc019SAndroid Build Coastguard Worker 	setup_drm();
691*d83cc019SAndroid Build Coastguard Worker 	setup_modeset();
692*d83cc019SAndroid Build Coastguard Worker 	setup_vblank_interval();
693*d83cc019SAndroid Build Coastguard Worker 	setup_alarm();
694*d83cc019SAndroid Build Coastguard Worker 
695*d83cc019SAndroid Build Coastguard Worker 	printf("Test name:\t%s\n", opts.test_name);
696*d83cc019SAndroid Build Coastguard Worker 
697*d83cc019SAndroid Build Coastguard Worker 	unset_mode();
698*d83cc019SAndroid Build Coastguard Worker 	set_mode();
699*d83cc019SAndroid Build Coastguard Worker 
700*d83cc019SAndroid Build Coastguard Worker 	setup_idle();
701*d83cc019SAndroid Build Coastguard Worker 
702*d83cc019SAndroid Build Coastguard Worker 	if (opts.do_page_flip)
703*d83cc019SAndroid Build Coastguard Worker 		page_flip_test();
704*d83cc019SAndroid Build Coastguard Worker 
705*d83cc019SAndroid Build Coastguard Worker 	if (opts.do_draw)
706*d83cc019SAndroid Build Coastguard Worker 		draw_test();
707*d83cc019SAndroid Build Coastguard Worker 
708*d83cc019SAndroid Build Coastguard Worker 	if (opts.do_draw_and_flip)
709*d83cc019SAndroid Build Coastguard Worker 		draw_and_flip_test();
710*d83cc019SAndroid Build Coastguard Worker 
711*d83cc019SAndroid Build Coastguard Worker 	teardown_modeset();
712*d83cc019SAndroid Build Coastguard Worker 	teardown_drm();
713*d83cc019SAndroid Build Coastguard Worker 	teardown_msr();
714*d83cc019SAndroid Build Coastguard Worker 	return 0;
715*d83cc019SAndroid Build Coastguard Worker }
716