1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker * Copyright 2012 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker * Jesse Barnes <[email protected]>
4*d83cc019SAndroid Build Coastguard Worker *
5*d83cc019SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
6*d83cc019SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
7*d83cc019SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
8*d83cc019SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*d83cc019SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
10*d83cc019SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
11*d83cc019SAndroid Build Coastguard Worker *
12*d83cc019SAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included in
13*d83cc019SAndroid Build Coastguard Worker * all copies or substantial portions of the 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 THE
18*d83cc019SAndroid Build Coastguard Worker * 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
24*d83cc019SAndroid Build Coastguard Worker #include "config.h"
25*d83cc019SAndroid Build Coastguard Worker
26*d83cc019SAndroid Build Coastguard Worker #include "igt.h"
27*d83cc019SAndroid Build Coastguard Worker
28*d83cc019SAndroid Build Coastguard Worker #if defined(USE_CAIRO_PIXMAN)
29*d83cc019SAndroid Build Coastguard Worker #include <cairo.h>
30*d83cc019SAndroid Build Coastguard Worker #endif
31*d83cc019SAndroid Build Coastguard Worker #include <errno.h>
32*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
33*d83cc019SAndroid Build Coastguard Worker #include <math.h>
34*d83cc019SAndroid Build Coastguard Worker #include <stdint.h>
35*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
36*d83cc019SAndroid Build Coastguard Worker #include <sys/poll.h>
37*d83cc019SAndroid Build Coastguard Worker #include <sys/time.h>
38*d83cc019SAndroid Build Coastguard Worker #include <sys/ioctl.h>
39*d83cc019SAndroid Build Coastguard Worker #ifdef HAVE_LINUX_KD_H
40*d83cc019SAndroid Build Coastguard Worker #include <linux/kd.h>
41*d83cc019SAndroid Build Coastguard Worker #elif HAVE_SYS_KD_H
42*d83cc019SAndroid Build Coastguard Worker #include <sys/kd.h>
43*d83cc019SAndroid Build Coastguard Worker #endif
44*d83cc019SAndroid Build Coastguard Worker #include <time.h>
45*d83cc019SAndroid Build Coastguard Worker #include <pthread.h>
46*d83cc019SAndroid Build Coastguard Worker
47*d83cc019SAndroid Build Coastguard Worker #include "igt_stats.h"
48*d83cc019SAndroid Build Coastguard Worker
49*d83cc019SAndroid Build Coastguard Worker #define TEST_DPMS (1 << 0)
50*d83cc019SAndroid Build Coastguard Worker
51*d83cc019SAndroid Build Coastguard Worker #define TEST_PAN (1 << 3)
52*d83cc019SAndroid Build Coastguard Worker #define TEST_MODESET (1 << 4)
53*d83cc019SAndroid Build Coastguard Worker #define TEST_CHECK_TS (1 << 5)
54*d83cc019SAndroid Build Coastguard Worker #define TEST_EBUSY (1 << 6)
55*d83cc019SAndroid Build Coastguard Worker #define TEST_EINVAL (1 << 7)
56*d83cc019SAndroid Build Coastguard Worker #define TEST_FLIP (1 << 8)
57*d83cc019SAndroid Build Coastguard Worker #define TEST_VBLANK (1 << 9)
58*d83cc019SAndroid Build Coastguard Worker #define TEST_VBLANK_BLOCK (1 << 10)
59*d83cc019SAndroid Build Coastguard Worker #define TEST_VBLANK_ABSOLUTE (1 << 11)
60*d83cc019SAndroid Build Coastguard Worker #define TEST_VBLANK_EXPIRED_SEQ (1 << 12)
61*d83cc019SAndroid Build Coastguard Worker #define TEST_FB_RECREATE (1 << 13)
62*d83cc019SAndroid Build Coastguard Worker #define TEST_RMFB (1 << 14)
63*d83cc019SAndroid Build Coastguard Worker #define TEST_HANG (1 << 15)
64*d83cc019SAndroid Build Coastguard Worker #define TEST_NOEVENT (1 << 16)
65*d83cc019SAndroid Build Coastguard Worker
66*d83cc019SAndroid Build Coastguard Worker #define TEST_SINGLE_BUFFER (1 << 18)
67*d83cc019SAndroid Build Coastguard Worker #define TEST_DPMS_OFF (1 << 19)
68*d83cc019SAndroid Build Coastguard Worker #define TEST_NO_2X_OUTPUT (1 << 20)
69*d83cc019SAndroid Build Coastguard Worker #define TEST_DPMS_OFF_OTHERS (1 << 21)
70*d83cc019SAndroid Build Coastguard Worker #define TEST_ENOENT (1 << 22)
71*d83cc019SAndroid Build Coastguard Worker #define TEST_FENCE_STRESS (1 << 23)
72*d83cc019SAndroid Build Coastguard Worker #define TEST_VBLANK_RACE (1 << 24)
73*d83cc019SAndroid Build Coastguard Worker #define TEST_SUSPEND (1 << 26)
74*d83cc019SAndroid Build Coastguard Worker #define TEST_BO_TOOBIG (1 << 28)
75*d83cc019SAndroid Build Coastguard Worker
76*d83cc019SAndroid Build Coastguard Worker #define TEST_NO_VBLANK (1 << 29)
77*d83cc019SAndroid Build Coastguard Worker #define TEST_BASIC (1 << 30)
78*d83cc019SAndroid Build Coastguard Worker
79*d83cc019SAndroid Build Coastguard Worker #define EVENT_FLIP (1 << 0)
80*d83cc019SAndroid Build Coastguard Worker #define EVENT_VBLANK (1 << 1)
81*d83cc019SAndroid Build Coastguard Worker
82*d83cc019SAndroid Build Coastguard Worker #define RUN_TEST 1
83*d83cc019SAndroid Build Coastguard Worker #define RUN_PAIR 2
84*d83cc019SAndroid Build Coastguard Worker
85*d83cc019SAndroid Build Coastguard Worker #ifndef DRM_CAP_TIMESTAMP_MONOTONIC
86*d83cc019SAndroid Build Coastguard Worker #define DRM_CAP_TIMESTAMP_MONOTONIC 6
87*d83cc019SAndroid Build Coastguard Worker #endif
88*d83cc019SAndroid Build Coastguard Worker
89*d83cc019SAndroid Build Coastguard Worker drmModeRes *resources;
90*d83cc019SAndroid Build Coastguard Worker int drm_fd;
91*d83cc019SAndroid Build Coastguard Worker static drm_intel_bufmgr *bufmgr;
92*d83cc019SAndroid Build Coastguard Worker struct intel_batchbuffer *batch;
93*d83cc019SAndroid Build Coastguard Worker uint32_t devid;
94*d83cc019SAndroid Build Coastguard Worker int test_time = 3;
95*d83cc019SAndroid Build Coastguard Worker static bool monotonic_timestamp;
96*d83cc019SAndroid Build Coastguard Worker static pthread_t vblank_wait_thread;
97*d83cc019SAndroid Build Coastguard Worker
98*d83cc019SAndroid Build Coastguard Worker static drmModeConnector *last_connector;
99*d83cc019SAndroid Build Coastguard Worker
100*d83cc019SAndroid Build Coastguard Worker uint32_t *fb_ptr;
101*d83cc019SAndroid Build Coastguard Worker
102*d83cc019SAndroid Build Coastguard Worker struct type_name {
103*d83cc019SAndroid Build Coastguard Worker int type;
104*d83cc019SAndroid Build Coastguard Worker const char *name;
105*d83cc019SAndroid Build Coastguard Worker };
106*d83cc019SAndroid Build Coastguard Worker
107*d83cc019SAndroid Build Coastguard Worker struct event_state {
108*d83cc019SAndroid Build Coastguard Worker const char *name;
109*d83cc019SAndroid Build Coastguard Worker
110*d83cc019SAndroid Build Coastguard Worker /*
111*d83cc019SAndroid Build Coastguard Worker * Event data for the last event that has already passed our check.
112*d83cc019SAndroid Build Coastguard Worker * Updated using the below current_* vars in update_state().
113*d83cc019SAndroid Build Coastguard Worker */
114*d83cc019SAndroid Build Coastguard Worker struct timeval last_ts; /* kernel reported timestamp */
115*d83cc019SAndroid Build Coastguard Worker struct timeval last_received_ts; /* the moment we received it */
116*d83cc019SAndroid Build Coastguard Worker unsigned int last_seq; /* kernel reported seq. num */
117*d83cc019SAndroid Build Coastguard Worker
118*d83cc019SAndroid Build Coastguard Worker /*
119*d83cc019SAndroid Build Coastguard Worker * Event data for for the current event that we just received and
120*d83cc019SAndroid Build Coastguard Worker * going to check for validity. Set in event_handler().
121*d83cc019SAndroid Build Coastguard Worker */
122*d83cc019SAndroid Build Coastguard Worker struct timeval current_ts; /* kernel reported timestamp */
123*d83cc019SAndroid Build Coastguard Worker struct timeval current_received_ts; /* the moment we received it */
124*d83cc019SAndroid Build Coastguard Worker unsigned int current_seq; /* kernel reported seq. num */
125*d83cc019SAndroid Build Coastguard Worker
126*d83cc019SAndroid Build Coastguard Worker int count; /* # of events of this type */
127*d83cc019SAndroid Build Coastguard Worker
128*d83cc019SAndroid Build Coastguard Worker /* Step between the current and next 'target' sequence number. */
129*d83cc019SAndroid Build Coastguard Worker int seq_step;
130*d83cc019SAndroid Build Coastguard Worker };
131*d83cc019SAndroid Build Coastguard Worker
vblank_dependence(int flags)132*d83cc019SAndroid Build Coastguard Worker static bool vblank_dependence(int flags)
133*d83cc019SAndroid Build Coastguard Worker {
134*d83cc019SAndroid Build Coastguard Worker int vblank_flags = TEST_VBLANK | TEST_VBLANK_BLOCK |
135*d83cc019SAndroid Build Coastguard Worker TEST_VBLANK_ABSOLUTE | TEST_VBLANK_EXPIRED_SEQ |
136*d83cc019SAndroid Build Coastguard Worker TEST_CHECK_TS | TEST_VBLANK_RACE | TEST_EBUSY;
137*d83cc019SAndroid Build Coastguard Worker
138*d83cc019SAndroid Build Coastguard Worker if (flags & vblank_flags)
139*d83cc019SAndroid Build Coastguard Worker return true;
140*d83cc019SAndroid Build Coastguard Worker
141*d83cc019SAndroid Build Coastguard Worker return false;
142*d83cc019SAndroid Build Coastguard Worker }
143*d83cc019SAndroid Build Coastguard Worker
timeval_float(const struct timeval * tv)144*d83cc019SAndroid Build Coastguard Worker static float timeval_float(const struct timeval *tv)
145*d83cc019SAndroid Build Coastguard Worker {
146*d83cc019SAndroid Build Coastguard Worker return tv->tv_sec + tv->tv_usec / 1000000.0f;
147*d83cc019SAndroid Build Coastguard Worker }
148*d83cc019SAndroid Build Coastguard Worker
dump_event_state(const struct event_state * es)149*d83cc019SAndroid Build Coastguard Worker static void dump_event_state(const struct event_state *es)
150*d83cc019SAndroid Build Coastguard Worker {
151*d83cc019SAndroid Build Coastguard Worker igt_debug("name = %s\n"
152*d83cc019SAndroid Build Coastguard Worker "last_ts = %.06f\n"
153*d83cc019SAndroid Build Coastguard Worker "last_received_ts = %.06f\n"
154*d83cc019SAndroid Build Coastguard Worker "last_seq = %u\n"
155*d83cc019SAndroid Build Coastguard Worker "current_ts = %.06f\n"
156*d83cc019SAndroid Build Coastguard Worker "current_received_ts = %.06f\n"
157*d83cc019SAndroid Build Coastguard Worker "current_seq = %u\n"
158*d83cc019SAndroid Build Coastguard Worker "count = %u\n"
159*d83cc019SAndroid Build Coastguard Worker "seq_step = %d\n",
160*d83cc019SAndroid Build Coastguard Worker es->name,
161*d83cc019SAndroid Build Coastguard Worker timeval_float(&es->last_ts),
162*d83cc019SAndroid Build Coastguard Worker timeval_float(&es->last_received_ts),
163*d83cc019SAndroid Build Coastguard Worker es->last_seq,
164*d83cc019SAndroid Build Coastguard Worker timeval_float(&es->current_ts),
165*d83cc019SAndroid Build Coastguard Worker timeval_float(&es->current_received_ts),
166*d83cc019SAndroid Build Coastguard Worker es->current_seq,
167*d83cc019SAndroid Build Coastguard Worker es->count,
168*d83cc019SAndroid Build Coastguard Worker es->seq_step);
169*d83cc019SAndroid Build Coastguard Worker }
170*d83cc019SAndroid Build Coastguard Worker
171*d83cc019SAndroid Build Coastguard Worker struct test_output {
172*d83cc019SAndroid Build Coastguard Worker int mode_valid;
173*d83cc019SAndroid Build Coastguard Worker drmModeModeInfo kmode[4];
174*d83cc019SAndroid Build Coastguard Worker drmModeEncoder *kencoder[4];
175*d83cc019SAndroid Build Coastguard Worker drmModeConnector *kconnector[4];
176*d83cc019SAndroid Build Coastguard Worker uint32_t _connector[4];
177*d83cc019SAndroid Build Coastguard Worker uint32_t _crtc[4];
178*d83cc019SAndroid Build Coastguard Worker int _pipe[4];
179*d83cc019SAndroid Build Coastguard Worker int count; /* 1:1 mapping between crtc:connector */
180*d83cc019SAndroid Build Coastguard Worker int flags;
181*d83cc019SAndroid Build Coastguard Worker int pipe; /* primary pipe for vblank */
182*d83cc019SAndroid Build Coastguard Worker unsigned int current_fb_id;
183*d83cc019SAndroid Build Coastguard Worker unsigned int fb_width;
184*d83cc019SAndroid Build Coastguard Worker unsigned int fb_height;
185*d83cc019SAndroid Build Coastguard Worker unsigned int fb_ids[3];
186*d83cc019SAndroid Build Coastguard Worker int bpp, depth;
187*d83cc019SAndroid Build Coastguard Worker struct igt_fb fb_info[3];
188*d83cc019SAndroid Build Coastguard Worker
189*d83cc019SAndroid Build Coastguard Worker struct event_state flip_state;
190*d83cc019SAndroid Build Coastguard Worker struct event_state vblank_state;
191*d83cc019SAndroid Build Coastguard Worker /* Overall step between each round */
192*d83cc019SAndroid Build Coastguard Worker int seq_step;
193*d83cc019SAndroid Build Coastguard Worker unsigned int pending_events;
194*d83cc019SAndroid Build Coastguard Worker int flip_count;
195*d83cc019SAndroid Build Coastguard Worker
196*d83cc019SAndroid Build Coastguard Worker double vblank_interval;
197*d83cc019SAndroid Build Coastguard Worker };
198*d83cc019SAndroid Build Coastguard Worker
199*d83cc019SAndroid Build Coastguard Worker
gettime_us(void)200*d83cc019SAndroid Build Coastguard Worker static unsigned long gettime_us(void)
201*d83cc019SAndroid Build Coastguard Worker {
202*d83cc019SAndroid Build Coastguard Worker struct timespec ts;
203*d83cc019SAndroid Build Coastguard Worker
204*d83cc019SAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC, &ts);
205*d83cc019SAndroid Build Coastguard Worker
206*d83cc019SAndroid Build Coastguard Worker return ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
207*d83cc019SAndroid Build Coastguard Worker }
208*d83cc019SAndroid Build Coastguard Worker
emit_fence_stress(struct test_output * o)209*d83cc019SAndroid Build Coastguard Worker static void emit_fence_stress(struct test_output *o)
210*d83cc019SAndroid Build Coastguard Worker {
211*d83cc019SAndroid Build Coastguard Worker const int num_fences = gem_available_fences(drm_fd);
212*d83cc019SAndroid Build Coastguard Worker struct igt_fb *fb_info = &o->fb_info[o->current_fb_id];
213*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_execbuffer2 execbuf;
214*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_exec_object2 *exec;
215*d83cc019SAndroid Build Coastguard Worker uint32_t buf[2] = { MI_BATCH_BUFFER_END, 0 };
216*d83cc019SAndroid Build Coastguard Worker drm_intel_bo **bo;
217*d83cc019SAndroid Build Coastguard Worker int i;
218*d83cc019SAndroid Build Coastguard Worker
219*d83cc019SAndroid Build Coastguard Worker igt_require(bufmgr);
220*d83cc019SAndroid Build Coastguard Worker
221*d83cc019SAndroid Build Coastguard Worker bo = calloc(sizeof(*bo), num_fences);
222*d83cc019SAndroid Build Coastguard Worker exec = calloc(sizeof(*exec), num_fences+1);
223*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < num_fences - 1; i++) {
224*d83cc019SAndroid Build Coastguard Worker uint32_t tiling = I915_TILING_X;
225*d83cc019SAndroid Build Coastguard Worker unsigned long pitch = 0;
226*d83cc019SAndroid Build Coastguard Worker bo[i] = drm_intel_bo_alloc_tiled(bufmgr,
227*d83cc019SAndroid Build Coastguard Worker "X tiled bo", 1024, 1024, 4,
228*d83cc019SAndroid Build Coastguard Worker &tiling, &pitch, 0);
229*d83cc019SAndroid Build Coastguard Worker exec[i].handle = bo[i]->handle;
230*d83cc019SAndroid Build Coastguard Worker exec[i].flags = EXEC_OBJECT_NEEDS_FENCE;
231*d83cc019SAndroid Build Coastguard Worker }
232*d83cc019SAndroid Build Coastguard Worker exec[i].handle = fb_info->gem_handle;
233*d83cc019SAndroid Build Coastguard Worker exec[i].flags = EXEC_OBJECT_NEEDS_FENCE;
234*d83cc019SAndroid Build Coastguard Worker exec[++i].handle = gem_create(drm_fd, 4096);
235*d83cc019SAndroid Build Coastguard Worker gem_write(drm_fd, exec[i].handle, 0, buf, sizeof(buf));
236*d83cc019SAndroid Build Coastguard Worker
237*d83cc019SAndroid Build Coastguard Worker memset(&execbuf, 0, sizeof(execbuf));
238*d83cc019SAndroid Build Coastguard Worker execbuf.buffers_ptr = (uintptr_t)exec;
239*d83cc019SAndroid Build Coastguard Worker execbuf.buffer_count = i + 1;
240*d83cc019SAndroid Build Coastguard Worker execbuf.batch_len = sizeof(buf);
241*d83cc019SAndroid Build Coastguard Worker if (HAS_BLT_RING(intel_get_drm_devid(drm_fd)))
242*d83cc019SAndroid Build Coastguard Worker execbuf.flags = I915_EXEC_BLT;
243*d83cc019SAndroid Build Coastguard Worker
244*d83cc019SAndroid Build Coastguard Worker gem_execbuf(drm_fd, &execbuf);
245*d83cc019SAndroid Build Coastguard Worker
246*d83cc019SAndroid Build Coastguard Worker gem_close(drm_fd, exec[i].handle);
247*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < num_fences - 1; i++)
248*d83cc019SAndroid Build Coastguard Worker drm_intel_bo_unreference(bo[i]);
249*d83cc019SAndroid Build Coastguard Worker free(bo);
250*d83cc019SAndroid Build Coastguard Worker free(exec);
251*d83cc019SAndroid Build Coastguard Worker }
252*d83cc019SAndroid Build Coastguard Worker
dpms_off_other_outputs(struct test_output * o)253*d83cc019SAndroid Build Coastguard Worker static void dpms_off_other_outputs(struct test_output *o)
254*d83cc019SAndroid Build Coastguard Worker {
255*d83cc019SAndroid Build Coastguard Worker int i, n;
256*d83cc019SAndroid Build Coastguard Worker drmModeConnector *connector;
257*d83cc019SAndroid Build Coastguard Worker uint32_t connector_id;
258*d83cc019SAndroid Build Coastguard Worker
259*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < resources->count_connectors; i++) {
260*d83cc019SAndroid Build Coastguard Worker connector_id = resources->connectors[i];
261*d83cc019SAndroid Build Coastguard Worker
262*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < o->count; n++) {
263*d83cc019SAndroid Build Coastguard Worker if (connector_id == o->kconnector[n]->connector_id)
264*d83cc019SAndroid Build Coastguard Worker goto next;
265*d83cc019SAndroid Build Coastguard Worker }
266*d83cc019SAndroid Build Coastguard Worker
267*d83cc019SAndroid Build Coastguard Worker connector = drmModeGetConnectorCurrent(drm_fd, connector_id);
268*d83cc019SAndroid Build Coastguard Worker
269*d83cc019SAndroid Build Coastguard Worker kmstest_set_connector_dpms(drm_fd, connector, DRM_MODE_DPMS_ON);
270*d83cc019SAndroid Build Coastguard Worker kmstest_set_connector_dpms(drm_fd, connector, DRM_MODE_DPMS_OFF);
271*d83cc019SAndroid Build Coastguard Worker
272*d83cc019SAndroid Build Coastguard Worker drmModeFreeConnector(connector);
273*d83cc019SAndroid Build Coastguard Worker next:
274*d83cc019SAndroid Build Coastguard Worker ;
275*d83cc019SAndroid Build Coastguard Worker }
276*d83cc019SAndroid Build Coastguard Worker }
277*d83cc019SAndroid Build Coastguard Worker
set_dpms(struct test_output * o,int mode)278*d83cc019SAndroid Build Coastguard Worker static void set_dpms(struct test_output *o, int mode)
279*d83cc019SAndroid Build Coastguard Worker {
280*d83cc019SAndroid Build Coastguard Worker for (int n = 0; n < o->count; n++)
281*d83cc019SAndroid Build Coastguard Worker kmstest_set_connector_dpms(drm_fd, o->kconnector[n], mode);
282*d83cc019SAndroid Build Coastguard Worker }
283*d83cc019SAndroid Build Coastguard Worker
set_flag(unsigned int * v,unsigned int flag)284*d83cc019SAndroid Build Coastguard Worker static void set_flag(unsigned int *v, unsigned int flag)
285*d83cc019SAndroid Build Coastguard Worker {
286*d83cc019SAndroid Build Coastguard Worker igt_assert(!(*v & flag));
287*d83cc019SAndroid Build Coastguard Worker *v |= flag;
288*d83cc019SAndroid Build Coastguard Worker }
289*d83cc019SAndroid Build Coastguard Worker
clear_flag(unsigned int * v,unsigned int flag)290*d83cc019SAndroid Build Coastguard Worker static void clear_flag(unsigned int *v, unsigned int flag)
291*d83cc019SAndroid Build Coastguard Worker {
292*d83cc019SAndroid Build Coastguard Worker igt_assert(*v & flag);
293*d83cc019SAndroid Build Coastguard Worker *v &= ~flag;
294*d83cc019SAndroid Build Coastguard Worker }
295*d83cc019SAndroid Build Coastguard Worker
do_page_flip(struct test_output * o,uint32_t fb_id,bool event)296*d83cc019SAndroid Build Coastguard Worker static int do_page_flip(struct test_output *o, uint32_t fb_id, bool event)
297*d83cc019SAndroid Build Coastguard Worker {
298*d83cc019SAndroid Build Coastguard Worker int n, ret = 0;
299*d83cc019SAndroid Build Coastguard Worker
300*d83cc019SAndroid Build Coastguard Worker o->flip_count = 0;
301*d83cc019SAndroid Build Coastguard Worker
302*d83cc019SAndroid Build Coastguard Worker for (n = 0; ret == 0 && n < o->count; n++)
303*d83cc019SAndroid Build Coastguard Worker ret = drmModePageFlip(drm_fd, o->_crtc[n], fb_id,
304*d83cc019SAndroid Build Coastguard Worker event ? DRM_MODE_PAGE_FLIP_EVENT : 0,
305*d83cc019SAndroid Build Coastguard Worker event ? (void *)((unsigned long)o | (n==0)) : NULL);
306*d83cc019SAndroid Build Coastguard Worker
307*d83cc019SAndroid Build Coastguard Worker if (ret == 0 && event)
308*d83cc019SAndroid Build Coastguard Worker set_flag(&o->pending_events, EVENT_FLIP);
309*d83cc019SAndroid Build Coastguard Worker
310*d83cc019SAndroid Build Coastguard Worker return ret;
311*d83cc019SAndroid Build Coastguard Worker }
312*d83cc019SAndroid Build Coastguard Worker
313*d83cc019SAndroid Build Coastguard Worker struct vblank_reply {
314*d83cc019SAndroid Build Coastguard Worker unsigned int sequence;
315*d83cc019SAndroid Build Coastguard Worker struct timeval ts;
316*d83cc019SAndroid Build Coastguard Worker };
317*d83cc019SAndroid Build Coastguard Worker
__wait_for_vblank(unsigned int flags,int crtc_idx,int target_seq,unsigned long ret_data,struct vblank_reply * reply)318*d83cc019SAndroid Build Coastguard Worker static int __wait_for_vblank(unsigned int flags, int crtc_idx,
319*d83cc019SAndroid Build Coastguard Worker int target_seq, unsigned long ret_data,
320*d83cc019SAndroid Build Coastguard Worker struct vblank_reply *reply)
321*d83cc019SAndroid Build Coastguard Worker {
322*d83cc019SAndroid Build Coastguard Worker drmVBlank wait_vbl;
323*d83cc019SAndroid Build Coastguard Worker int ret;
324*d83cc019SAndroid Build Coastguard Worker uint32_t pipe_id_flag;
325*d83cc019SAndroid Build Coastguard Worker bool event = !(flags & TEST_VBLANK_BLOCK);
326*d83cc019SAndroid Build Coastguard Worker
327*d83cc019SAndroid Build Coastguard Worker memset(&wait_vbl, 0, sizeof(wait_vbl));
328*d83cc019SAndroid Build Coastguard Worker pipe_id_flag = kmstest_get_vbl_flag(crtc_idx);
329*d83cc019SAndroid Build Coastguard Worker
330*d83cc019SAndroid Build Coastguard Worker wait_vbl.request.type = pipe_id_flag;
331*d83cc019SAndroid Build Coastguard Worker if (flags & TEST_VBLANK_ABSOLUTE)
332*d83cc019SAndroid Build Coastguard Worker wait_vbl.request.type |= DRM_VBLANK_ABSOLUTE;
333*d83cc019SAndroid Build Coastguard Worker else
334*d83cc019SAndroid Build Coastguard Worker wait_vbl.request.type |= DRM_VBLANK_RELATIVE;
335*d83cc019SAndroid Build Coastguard Worker if (event) {
336*d83cc019SAndroid Build Coastguard Worker wait_vbl.request.type |= DRM_VBLANK_EVENT;
337*d83cc019SAndroid Build Coastguard Worker wait_vbl.request.signal = ret_data;
338*d83cc019SAndroid Build Coastguard Worker }
339*d83cc019SAndroid Build Coastguard Worker wait_vbl.request.sequence = target_seq;
340*d83cc019SAndroid Build Coastguard Worker
341*d83cc019SAndroid Build Coastguard Worker ret = drmWaitVBlank(drm_fd, &wait_vbl);
342*d83cc019SAndroid Build Coastguard Worker
343*d83cc019SAndroid Build Coastguard Worker if (ret == 0) {
344*d83cc019SAndroid Build Coastguard Worker reply->ts.tv_sec = wait_vbl.reply.tval_sec;
345*d83cc019SAndroid Build Coastguard Worker reply->ts.tv_usec = wait_vbl.reply.tval_usec;
346*d83cc019SAndroid Build Coastguard Worker reply->sequence = wait_vbl.reply.sequence;
347*d83cc019SAndroid Build Coastguard Worker } else
348*d83cc019SAndroid Build Coastguard Worker ret = -errno;
349*d83cc019SAndroid Build Coastguard Worker
350*d83cc019SAndroid Build Coastguard Worker return ret;
351*d83cc019SAndroid Build Coastguard Worker }
352*d83cc019SAndroid Build Coastguard Worker
do_wait_for_vblank(struct test_output * o,int pipe_id,int target_seq,struct vblank_reply * reply)353*d83cc019SAndroid Build Coastguard Worker static int do_wait_for_vblank(struct test_output *o, int pipe_id,
354*d83cc019SAndroid Build Coastguard Worker int target_seq, struct vblank_reply *reply)
355*d83cc019SAndroid Build Coastguard Worker {
356*d83cc019SAndroid Build Coastguard Worker int ret;
357*d83cc019SAndroid Build Coastguard Worker unsigned flags = o->flags;
358*d83cc019SAndroid Build Coastguard Worker
359*d83cc019SAndroid Build Coastguard Worker /* Absolute waits only works once we have a frame counter. */
360*d83cc019SAndroid Build Coastguard Worker if (!(o->vblank_state.count > 0))
361*d83cc019SAndroid Build Coastguard Worker flags &= ~TEST_VBLANK_ABSOLUTE;
362*d83cc019SAndroid Build Coastguard Worker
363*d83cc019SAndroid Build Coastguard Worker ret = __wait_for_vblank(flags, pipe_id, target_seq, (unsigned long)o,
364*d83cc019SAndroid Build Coastguard Worker reply);
365*d83cc019SAndroid Build Coastguard Worker if (ret == 0 && !(o->flags & TEST_VBLANK_BLOCK))
366*d83cc019SAndroid Build Coastguard Worker set_flag(&o->pending_events, EVENT_VBLANK);
367*d83cc019SAndroid Build Coastguard Worker
368*d83cc019SAndroid Build Coastguard Worker return ret;
369*d83cc019SAndroid Build Coastguard Worker }
370*d83cc019SAndroid Build Coastguard Worker
371*d83cc019SAndroid Build Coastguard Worker static bool
analog_tv_connector(const struct test_output * o)372*d83cc019SAndroid Build Coastguard Worker analog_tv_connector(const struct test_output *o)
373*d83cc019SAndroid Build Coastguard Worker {
374*d83cc019SAndroid Build Coastguard Worker uint32_t connector_type = o->kconnector[0]->connector_type;
375*d83cc019SAndroid Build Coastguard Worker
376*d83cc019SAndroid Build Coastguard Worker return connector_type == DRM_MODE_CONNECTOR_TV ||
377*d83cc019SAndroid Build Coastguard Worker connector_type == DRM_MODE_CONNECTOR_9PinDIN ||
378*d83cc019SAndroid Build Coastguard Worker connector_type == DRM_MODE_CONNECTOR_SVIDEO ||
379*d83cc019SAndroid Build Coastguard Worker connector_type == DRM_MODE_CONNECTOR_Composite;
380*d83cc019SAndroid Build Coastguard Worker }
381*d83cc019SAndroid Build Coastguard Worker
event_handler(struct event_state * es,unsigned int frame,unsigned int sec,unsigned int usec)382*d83cc019SAndroid Build Coastguard Worker static void event_handler(struct event_state *es, unsigned int frame,
383*d83cc019SAndroid Build Coastguard Worker unsigned int sec, unsigned int usec)
384*d83cc019SAndroid Build Coastguard Worker {
385*d83cc019SAndroid Build Coastguard Worker struct timeval now;
386*d83cc019SAndroid Build Coastguard Worker
387*d83cc019SAndroid Build Coastguard Worker if (monotonic_timestamp) {
388*d83cc019SAndroid Build Coastguard Worker struct timespec ts;
389*d83cc019SAndroid Build Coastguard Worker
390*d83cc019SAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC, &ts);
391*d83cc019SAndroid Build Coastguard Worker now.tv_sec = ts.tv_sec;
392*d83cc019SAndroid Build Coastguard Worker now.tv_usec = ts.tv_nsec / 1000;
393*d83cc019SAndroid Build Coastguard Worker } else {
394*d83cc019SAndroid Build Coastguard Worker gettimeofday(&now, NULL);
395*d83cc019SAndroid Build Coastguard Worker }
396*d83cc019SAndroid Build Coastguard Worker es->current_received_ts = now;
397*d83cc019SAndroid Build Coastguard Worker
398*d83cc019SAndroid Build Coastguard Worker es->current_ts.tv_sec = sec;
399*d83cc019SAndroid Build Coastguard Worker es->current_ts.tv_usec = usec;
400*d83cc019SAndroid Build Coastguard Worker es->current_seq = frame;
401*d83cc019SAndroid Build Coastguard Worker }
402*d83cc019SAndroid Build Coastguard Worker
page_flip_handler(int fd,unsigned int frame,unsigned int sec,unsigned int usec,void * data)403*d83cc019SAndroid Build Coastguard Worker static void page_flip_handler(int fd, unsigned int frame, unsigned int sec,
404*d83cc019SAndroid Build Coastguard Worker unsigned int usec, void *data)
405*d83cc019SAndroid Build Coastguard Worker {
406*d83cc019SAndroid Build Coastguard Worker int primary = (unsigned long)data & 1;
407*d83cc019SAndroid Build Coastguard Worker struct test_output *o = (void *)((unsigned long)data & ~ 1);
408*d83cc019SAndroid Build Coastguard Worker
409*d83cc019SAndroid Build Coastguard Worker if (++o->flip_count == o->count)
410*d83cc019SAndroid Build Coastguard Worker clear_flag(&o->pending_events, EVENT_FLIP);
411*d83cc019SAndroid Build Coastguard Worker if (primary)
412*d83cc019SAndroid Build Coastguard Worker event_handler(&o->flip_state, frame, sec, usec);
413*d83cc019SAndroid Build Coastguard Worker }
414*d83cc019SAndroid Build Coastguard Worker
mode_frame_time(const struct test_output * o)415*d83cc019SAndroid Build Coastguard Worker static double mode_frame_time(const struct test_output *o)
416*d83cc019SAndroid Build Coastguard Worker {
417*d83cc019SAndroid Build Coastguard Worker return 1000.0 * o->kmode[0].htotal * o->kmode[0].vtotal / o->kmode[0].clock;
418*d83cc019SAndroid Build Coastguard Worker }
419*d83cc019SAndroid Build Coastguard Worker
actual_frame_time(const struct test_output * o)420*d83cc019SAndroid Build Coastguard Worker static double actual_frame_time(const struct test_output *o)
421*d83cc019SAndroid Build Coastguard Worker {
422*d83cc019SAndroid Build Coastguard Worker igt_assert(o->flags & TEST_CHECK_TS);
423*d83cc019SAndroid Build Coastguard Worker return o->vblank_interval;
424*d83cc019SAndroid Build Coastguard Worker }
425*d83cc019SAndroid Build Coastguard Worker
vblank_wait_thread_func(void * data)426*d83cc019SAndroid Build Coastguard Worker static void *vblank_wait_thread_func(void *data)
427*d83cc019SAndroid Build Coastguard Worker {
428*d83cc019SAndroid Build Coastguard Worker struct test_output *o = data;
429*d83cc019SAndroid Build Coastguard Worker struct vblank_reply reply;
430*d83cc019SAndroid Build Coastguard Worker int i;
431*d83cc019SAndroid Build Coastguard Worker
432*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < 32; i++) {
433*d83cc019SAndroid Build Coastguard Worker unsigned long start = gettime_us();
434*d83cc019SAndroid Build Coastguard Worker __wait_for_vblank(TEST_VBLANK_BLOCK, o->pipe, 20, (unsigned long)o, &reply);
435*d83cc019SAndroid Build Coastguard Worker if (gettime_us() - start > 2 * mode_frame_time(o))
436*d83cc019SAndroid Build Coastguard Worker return (void*)1;
437*d83cc019SAndroid Build Coastguard Worker }
438*d83cc019SAndroid Build Coastguard Worker
439*d83cc019SAndroid Build Coastguard Worker return 0;
440*d83cc019SAndroid Build Coastguard Worker }
441*d83cc019SAndroid Build Coastguard Worker
spawn_vblank_wait_thread(struct test_output * o)442*d83cc019SAndroid Build Coastguard Worker static void spawn_vblank_wait_thread(struct test_output *o)
443*d83cc019SAndroid Build Coastguard Worker {
444*d83cc019SAndroid Build Coastguard Worker igt_assert(pthread_create(&vblank_wait_thread, NULL,
445*d83cc019SAndroid Build Coastguard Worker vblank_wait_thread_func, o) == 0);
446*d83cc019SAndroid Build Coastguard Worker }
447*d83cc019SAndroid Build Coastguard Worker
join_vblank_wait_thread(void)448*d83cc019SAndroid Build Coastguard Worker static void join_vblank_wait_thread(void)
449*d83cc019SAndroid Build Coastguard Worker {
450*d83cc019SAndroid Build Coastguard Worker igt_assert(pthread_join(vblank_wait_thread, NULL) == 0);
451*d83cc019SAndroid Build Coastguard Worker }
452*d83cc019SAndroid Build Coastguard Worker
fixup_premature_vblank_ts(struct test_output * o,struct event_state * es)453*d83cc019SAndroid Build Coastguard Worker static void fixup_premature_vblank_ts(struct test_output *o,
454*d83cc019SAndroid Build Coastguard Worker struct event_state *es)
455*d83cc019SAndroid Build Coastguard Worker {
456*d83cc019SAndroid Build Coastguard Worker /*
457*d83cc019SAndroid Build Coastguard Worker * In case a power off event preempts the completion of a
458*d83cc019SAndroid Build Coastguard Worker * wait-for-vblank event the kernel will return a wf-vblank event with
459*d83cc019SAndroid Build Coastguard Worker * a zeroed-out timestamp. In order that check_state() doesn't
460*d83cc019SAndroid Build Coastguard Worker * complain replace this ts with a valid ts. As we can't calculate the
461*d83cc019SAndroid Build Coastguard Worker * exact timestamp, just use the time we received the event.
462*d83cc019SAndroid Build Coastguard Worker */
463*d83cc019SAndroid Build Coastguard Worker struct timeval tv;
464*d83cc019SAndroid Build Coastguard Worker
465*d83cc019SAndroid Build Coastguard Worker if (!(o->flags & (TEST_DPMS | TEST_MODESET)))
466*d83cc019SAndroid Build Coastguard Worker return;
467*d83cc019SAndroid Build Coastguard Worker
468*d83cc019SAndroid Build Coastguard Worker if (o->vblank_state.current_ts.tv_sec != 0 ||
469*d83cc019SAndroid Build Coastguard Worker o->vblank_state.current_ts.tv_usec != 0)
470*d83cc019SAndroid Build Coastguard Worker return;
471*d83cc019SAndroid Build Coastguard Worker
472*d83cc019SAndroid Build Coastguard Worker tv.tv_sec = 0;
473*d83cc019SAndroid Build Coastguard Worker tv.tv_usec = 1;
474*d83cc019SAndroid Build Coastguard Worker timersub(&es->current_received_ts, &tv, &es->current_ts);
475*d83cc019SAndroid Build Coastguard Worker }
476*d83cc019SAndroid Build Coastguard Worker
vblank_handler(int fd,unsigned int frame,unsigned int sec,unsigned int usec,void * data)477*d83cc019SAndroid Build Coastguard Worker static void vblank_handler(int fd, unsigned int frame, unsigned int sec,
478*d83cc019SAndroid Build Coastguard Worker unsigned int usec, void *data)
479*d83cc019SAndroid Build Coastguard Worker {
480*d83cc019SAndroid Build Coastguard Worker struct test_output *o = data;
481*d83cc019SAndroid Build Coastguard Worker
482*d83cc019SAndroid Build Coastguard Worker clear_flag(&o->pending_events, EVENT_VBLANK);
483*d83cc019SAndroid Build Coastguard Worker event_handler(&o->vblank_state, frame, sec, usec);
484*d83cc019SAndroid Build Coastguard Worker fixup_premature_vblank_ts(o, &o->vblank_state);
485*d83cc019SAndroid Build Coastguard Worker }
486*d83cc019SAndroid Build Coastguard Worker
check_state(const struct test_output * o,const struct event_state * es)487*d83cc019SAndroid Build Coastguard Worker static void check_state(const struct test_output *o, const struct event_state *es)
488*d83cc019SAndroid Build Coastguard Worker {
489*d83cc019SAndroid Build Coastguard Worker struct timeval diff;
490*d83cc019SAndroid Build Coastguard Worker
491*d83cc019SAndroid Build Coastguard Worker dump_event_state(es);
492*d83cc019SAndroid Build Coastguard Worker
493*d83cc019SAndroid Build Coastguard Worker timersub(&es->current_ts, &es->current_received_ts, &diff);
494*d83cc019SAndroid Build Coastguard Worker if (!analog_tv_connector(o)) {
495*d83cc019SAndroid Build Coastguard Worker igt_assert_f(diff.tv_sec < 0 || (diff.tv_sec == 0 && diff.tv_usec <= 2000),
496*d83cc019SAndroid Build Coastguard Worker "%s ts delayed for too long: %.06f\n",
497*d83cc019SAndroid Build Coastguard Worker es->name, timeval_float(&diff));
498*d83cc019SAndroid Build Coastguard Worker }
499*d83cc019SAndroid Build Coastguard Worker
500*d83cc019SAndroid Build Coastguard Worker if (es->count == 0)
501*d83cc019SAndroid Build Coastguard Worker return;
502*d83cc019SAndroid Build Coastguard Worker
503*d83cc019SAndroid Build Coastguard Worker timersub(&es->current_ts, &es->last_received_ts, &diff);
504*d83cc019SAndroid Build Coastguard Worker igt_assert_f(timercmp(&es->last_received_ts, &es->current_ts, <),
505*d83cc019SAndroid Build Coastguard Worker "%s ts before the %s was issued!\n"
506*d83cc019SAndroid Build Coastguard Worker "timerdiff %.06f\n",
507*d83cc019SAndroid Build Coastguard Worker es->name, es->name, timeval_float(&diff));
508*d83cc019SAndroid Build Coastguard Worker
509*d83cc019SAndroid Build Coastguard Worker /* check only valid if no modeset happens in between, that increments by
510*d83cc019SAndroid Build Coastguard Worker * (1 << 23) on each step. This bounding matches the one in
511*d83cc019SAndroid Build Coastguard Worker * DRM_IOCTL_WAIT_VBLANK. */
512*d83cc019SAndroid Build Coastguard Worker if (!(o->flags & (TEST_DPMS | TEST_MODESET | TEST_NO_VBLANK)))
513*d83cc019SAndroid Build Coastguard Worker igt_assert_f(es->current_seq - (es->last_seq + o->seq_step) <= 1UL << 23,
514*d83cc019SAndroid Build Coastguard Worker "unexpected %s seq %u, should be >= %u\n",
515*d83cc019SAndroid Build Coastguard Worker es->name, es->current_seq, es->last_seq + o->seq_step);
516*d83cc019SAndroid Build Coastguard Worker
517*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_CHECK_TS) {
518*d83cc019SAndroid Build Coastguard Worker double elapsed, expected;
519*d83cc019SAndroid Build Coastguard Worker
520*d83cc019SAndroid Build Coastguard Worker timersub(&es->current_ts, &es->last_ts, &diff);
521*d83cc019SAndroid Build Coastguard Worker elapsed = 1e6*diff.tv_sec + diff.tv_usec;
522*d83cc019SAndroid Build Coastguard Worker expected = (es->current_seq - es->last_seq) * actual_frame_time(o);
523*d83cc019SAndroid Build Coastguard Worker
524*d83cc019SAndroid Build Coastguard Worker igt_debug("%s ts/seq: last %.06f/%u, current %.06f/%u: elapsed=%.1fus expected=%.1fus +- %.1fus, error %.1f%%\n",
525*d83cc019SAndroid Build Coastguard Worker es->name, timeval_float(&es->last_ts), es->last_seq,
526*d83cc019SAndroid Build Coastguard Worker timeval_float(&es->current_ts), es->current_seq,
527*d83cc019SAndroid Build Coastguard Worker elapsed, expected, expected * 0.005,
528*d83cc019SAndroid Build Coastguard Worker fabs((elapsed - expected) / expected) * 100);
529*d83cc019SAndroid Build Coastguard Worker
530*d83cc019SAndroid Build Coastguard Worker igt_assert_f(fabs((elapsed - expected) / expected) <= 0.005,
531*d83cc019SAndroid Build Coastguard Worker "inconsistent %s ts/seq: last %.06f/%u, current %.06f/%u: elapsed=%.1fus expected=%.1fus\n",
532*d83cc019SAndroid Build Coastguard Worker es->name, timeval_float(&es->last_ts), es->last_seq,
533*d83cc019SAndroid Build Coastguard Worker timeval_float(&es->current_ts), es->current_seq,
534*d83cc019SAndroid Build Coastguard Worker elapsed, expected);
535*d83cc019SAndroid Build Coastguard Worker
536*d83cc019SAndroid Build Coastguard Worker igt_assert_f(es->current_seq == es->last_seq + o->seq_step,
537*d83cc019SAndroid Build Coastguard Worker "unexpected %s seq %u, expected %u\n",
538*d83cc019SAndroid Build Coastguard Worker es->name, es->current_seq,
539*d83cc019SAndroid Build Coastguard Worker es->last_seq + o->seq_step);
540*d83cc019SAndroid Build Coastguard Worker }
541*d83cc019SAndroid Build Coastguard Worker }
542*d83cc019SAndroid Build Coastguard Worker
check_state_correlation(struct test_output * o,struct event_state * es1,struct event_state * es2)543*d83cc019SAndroid Build Coastguard Worker static void check_state_correlation(struct test_output *o,
544*d83cc019SAndroid Build Coastguard Worker struct event_state *es1,
545*d83cc019SAndroid Build Coastguard Worker struct event_state *es2)
546*d83cc019SAndroid Build Coastguard Worker {
547*d83cc019SAndroid Build Coastguard Worker struct timeval tv_diff;
548*d83cc019SAndroid Build Coastguard Worker double ftime;
549*d83cc019SAndroid Build Coastguard Worker double usec_diff;
550*d83cc019SAndroid Build Coastguard Worker int seq_diff;
551*d83cc019SAndroid Build Coastguard Worker
552*d83cc019SAndroid Build Coastguard Worker if (es1->count == 0 || es2->count == 0)
553*d83cc019SAndroid Build Coastguard Worker return;
554*d83cc019SAndroid Build Coastguard Worker
555*d83cc019SAndroid Build Coastguard Worker timersub(&es2->current_ts, &es1->current_ts, &tv_diff);
556*d83cc019SAndroid Build Coastguard Worker usec_diff = tv_diff.tv_sec * USEC_PER_SEC + tv_diff.tv_usec;
557*d83cc019SAndroid Build Coastguard Worker
558*d83cc019SAndroid Build Coastguard Worker seq_diff = es2->current_seq - es1->current_seq;
559*d83cc019SAndroid Build Coastguard Worker ftime = mode_frame_time(o);
560*d83cc019SAndroid Build Coastguard Worker usec_diff -= seq_diff * ftime;
561*d83cc019SAndroid Build Coastguard Worker
562*d83cc019SAndroid Build Coastguard Worker igt_assert_f(fabs(usec_diff) / ftime <= 0.005,
563*d83cc019SAndroid Build Coastguard Worker "timestamp mismatch between %s and %s (diff %.6f sec)\n",
564*d83cc019SAndroid Build Coastguard Worker es1->name, es2->name, usec_diff / USEC_PER_SEC);
565*d83cc019SAndroid Build Coastguard Worker }
566*d83cc019SAndroid Build Coastguard Worker
check_all_state(struct test_output * o,unsigned int completed_events)567*d83cc019SAndroid Build Coastguard Worker static void check_all_state(struct test_output *o,
568*d83cc019SAndroid Build Coastguard Worker unsigned int completed_events)
569*d83cc019SAndroid Build Coastguard Worker {
570*d83cc019SAndroid Build Coastguard Worker bool flip, vblank;
571*d83cc019SAndroid Build Coastguard Worker
572*d83cc019SAndroid Build Coastguard Worker flip = completed_events & EVENT_FLIP;
573*d83cc019SAndroid Build Coastguard Worker vblank = completed_events & EVENT_VBLANK;
574*d83cc019SAndroid Build Coastguard Worker
575*d83cc019SAndroid Build Coastguard Worker if (flip)
576*d83cc019SAndroid Build Coastguard Worker check_state(o, &o->flip_state);
577*d83cc019SAndroid Build Coastguard Worker if (vblank)
578*d83cc019SAndroid Build Coastguard Worker check_state(o, &o->vblank_state);
579*d83cc019SAndroid Build Coastguard Worker
580*d83cc019SAndroid Build Coastguard Worker /* FIXME: Correlation check is broken. */
581*d83cc019SAndroid Build Coastguard Worker if (flip && vblank && 0)
582*d83cc019SAndroid Build Coastguard Worker check_state_correlation(o, &o->flip_state, &o->vblank_state);
583*d83cc019SAndroid Build Coastguard Worker }
584*d83cc019SAndroid Build Coastguard Worker
recreate_fb(struct test_output * o)585*d83cc019SAndroid Build Coastguard Worker static void recreate_fb(struct test_output *o)
586*d83cc019SAndroid Build Coastguard Worker {
587*d83cc019SAndroid Build Coastguard Worker drmModeFBPtr r;
588*d83cc019SAndroid Build Coastguard Worker struct igt_fb *fb_info = &o->fb_info[o->current_fb_id];
589*d83cc019SAndroid Build Coastguard Worker uint32_t new_fb_id;
590*d83cc019SAndroid Build Coastguard Worker
591*d83cc019SAndroid Build Coastguard Worker /* Call rmfb/getfb/addfb to ensure those don't introduce stalls */
592*d83cc019SAndroid Build Coastguard Worker r = drmModeGetFB(drm_fd, fb_info->fb_id);
593*d83cc019SAndroid Build Coastguard Worker igt_assert(r);
594*d83cc019SAndroid Build Coastguard Worker
595*d83cc019SAndroid Build Coastguard Worker do_or_die(drmModeAddFB(drm_fd, o->fb_width, o->fb_height, o->depth,
596*d83cc019SAndroid Build Coastguard Worker o->bpp, fb_info->strides[0],
597*d83cc019SAndroid Build Coastguard Worker r->handle, &new_fb_id));
598*d83cc019SAndroid Build Coastguard Worker
599*d83cc019SAndroid Build Coastguard Worker gem_close(drm_fd, r->handle);
600*d83cc019SAndroid Build Coastguard Worker drmFree(r);
601*d83cc019SAndroid Build Coastguard Worker do_or_die(drmModeRmFB(drm_fd, fb_info->fb_id));
602*d83cc019SAndroid Build Coastguard Worker
603*d83cc019SAndroid Build Coastguard Worker o->fb_ids[o->current_fb_id] = new_fb_id;
604*d83cc019SAndroid Build Coastguard Worker o->fb_info[o->current_fb_id].fb_id = new_fb_id;
605*d83cc019SAndroid Build Coastguard Worker }
606*d83cc019SAndroid Build Coastguard Worker
hang_gpu(int fd)607*d83cc019SAndroid Build Coastguard Worker static igt_hang_t hang_gpu(int fd)
608*d83cc019SAndroid Build Coastguard Worker {
609*d83cc019SAndroid Build Coastguard Worker #if defined(USE_INTEL)
610*d83cc019SAndroid Build Coastguard Worker return igt_hang_ring(fd, I915_EXEC_DEFAULT);
611*d83cc019SAndroid Build Coastguard Worker #else
612*d83cc019SAndroid Build Coastguard Worker igt_hang_t ret = {};
613*d83cc019SAndroid Build Coastguard Worker return ret;
614*d83cc019SAndroid Build Coastguard Worker #endif
615*d83cc019SAndroid Build Coastguard Worker }
616*d83cc019SAndroid Build Coastguard Worker
unhang_gpu(int fd,igt_hang_t hang)617*d83cc019SAndroid Build Coastguard Worker static void unhang_gpu(int fd, igt_hang_t hang)
618*d83cc019SAndroid Build Coastguard Worker {
619*d83cc019SAndroid Build Coastguard Worker #if defined(USE_INTEL)
620*d83cc019SAndroid Build Coastguard Worker igt_post_hang_ring(fd, hang);
621*d83cc019SAndroid Build Coastguard Worker #endif
622*d83cc019SAndroid Build Coastguard Worker }
623*d83cc019SAndroid Build Coastguard Worker
is_wedged(int fd)624*d83cc019SAndroid Build Coastguard Worker static bool is_wedged(int fd)
625*d83cc019SAndroid Build Coastguard Worker {
626*d83cc019SAndroid Build Coastguard Worker if (drmIoctl(fd, DRM_IOCTL_I915_GEM_THROTTLE, 0) == 0)
627*d83cc019SAndroid Build Coastguard Worker return false;
628*d83cc019SAndroid Build Coastguard Worker
629*d83cc019SAndroid Build Coastguard Worker return errno == EIO;
630*d83cc019SAndroid Build Coastguard Worker }
631*d83cc019SAndroid Build Coastguard Worker
set_mode(struct test_output * o,uint32_t fb,int x,int y)632*d83cc019SAndroid Build Coastguard Worker static int set_mode(struct test_output *o, uint32_t fb, int x, int y)
633*d83cc019SAndroid Build Coastguard Worker {
634*d83cc019SAndroid Build Coastguard Worker int n, ret;
635*d83cc019SAndroid Build Coastguard Worker
636*d83cc019SAndroid Build Coastguard Worker for (n = o->count - 1; n >= 0; n--) {
637*d83cc019SAndroid Build Coastguard Worker uint32_t buffer_id = fb, x_crtc = x, y_crtc = y;
638*d83cc019SAndroid Build Coastguard Worker uint32_t *conn = &o->_connector[n];
639*d83cc019SAndroid Build Coastguard Worker int count = 1;
640*d83cc019SAndroid Build Coastguard Worker drmModeModeInfoPtr mode = &o->kmode[n];
641*d83cc019SAndroid Build Coastguard Worker
642*d83cc019SAndroid Build Coastguard Worker if (fb == 0) {
643*d83cc019SAndroid Build Coastguard Worker buffer_id = x_crtc = y_crtc = count = 0;
644*d83cc019SAndroid Build Coastguard Worker conn = NULL; mode = NULL;
645*d83cc019SAndroid Build Coastguard Worker }
646*d83cc019SAndroid Build Coastguard Worker
647*d83cc019SAndroid Build Coastguard Worker ret = drmModeSetCrtc(drm_fd, o->_crtc[n],
648*d83cc019SAndroid Build Coastguard Worker buffer_id, x_crtc, y_crtc,
649*d83cc019SAndroid Build Coastguard Worker conn, count, mode);
650*d83cc019SAndroid Build Coastguard Worker if (ret)
651*d83cc019SAndroid Build Coastguard Worker return ret;
652*d83cc019SAndroid Build Coastguard Worker }
653*d83cc019SAndroid Build Coastguard Worker
654*d83cc019SAndroid Build Coastguard Worker return 0;
655*d83cc019SAndroid Build Coastguard Worker }
656*d83cc019SAndroid Build Coastguard Worker
657*d83cc019SAndroid Build Coastguard Worker /* Return mask of completed events. */
run_test_step(struct test_output * o)658*d83cc019SAndroid Build Coastguard Worker static unsigned int run_test_step(struct test_output *o)
659*d83cc019SAndroid Build Coastguard Worker {
660*d83cc019SAndroid Build Coastguard Worker unsigned int new_fb_id;
661*d83cc019SAndroid Build Coastguard Worker /* for funny reasons page_flip returns -EBUSY on disabled crtcs ... */
662*d83cc019SAndroid Build Coastguard Worker int expected_einval = o->flags & TEST_MODESET ? -EBUSY : -EINVAL;
663*d83cc019SAndroid Build Coastguard Worker unsigned int completed_events = 0;
664*d83cc019SAndroid Build Coastguard Worker bool do_flip;
665*d83cc019SAndroid Build Coastguard Worker bool do_vblank;
666*d83cc019SAndroid Build Coastguard Worker struct vblank_reply vbl_reply;
667*d83cc019SAndroid Build Coastguard Worker unsigned int target_seq;
668*d83cc019SAndroid Build Coastguard Worker igt_hang_t hang;
669*d83cc019SAndroid Build Coastguard Worker
670*d83cc019SAndroid Build Coastguard Worker target_seq = o->vblank_state.seq_step;
671*d83cc019SAndroid Build Coastguard Worker /* Absolute waits only works once we have a frame counter. */
672*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_VBLANK_ABSOLUTE && o->vblank_state.count > 0)
673*d83cc019SAndroid Build Coastguard Worker target_seq += o->vblank_state.last_seq;
674*d83cc019SAndroid Build Coastguard Worker
675*d83cc019SAndroid Build Coastguard Worker /*
676*d83cc019SAndroid Build Coastguard Worker * It's possible that we don't have a pending flip here, in case both
677*d83cc019SAndroid Build Coastguard Worker * wf-vblank and flip were scheduled and the wf-vblank event was
678*d83cc019SAndroid Build Coastguard Worker * delivered earlier. The same applies to vblank events w.r.t flip.
679*d83cc019SAndroid Build Coastguard Worker */
680*d83cc019SAndroid Build Coastguard Worker do_flip = (o->flags & TEST_FLIP) && !(o->pending_events & EVENT_FLIP);
681*d83cc019SAndroid Build Coastguard Worker do_vblank = (o->flags & TEST_VBLANK) &&
682*d83cc019SAndroid Build Coastguard Worker !(o->pending_events & EVENT_VBLANK);
683*d83cc019SAndroid Build Coastguard Worker
684*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_DPMS_OFF_OTHERS)
685*d83cc019SAndroid Build Coastguard Worker dpms_off_other_outputs(o);
686*d83cc019SAndroid Build Coastguard Worker
687*d83cc019SAndroid Build Coastguard Worker if (!(o->flags & TEST_SINGLE_BUFFER))
688*d83cc019SAndroid Build Coastguard Worker o->current_fb_id = !o->current_fb_id;
689*d83cc019SAndroid Build Coastguard Worker
690*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_FB_RECREATE)
691*d83cc019SAndroid Build Coastguard Worker recreate_fb(o);
692*d83cc019SAndroid Build Coastguard Worker new_fb_id = o->fb_ids[o->current_fb_id];
693*d83cc019SAndroid Build Coastguard Worker
694*d83cc019SAndroid Build Coastguard Worker if ((o->flags & TEST_VBLANK_EXPIRED_SEQ) &&
695*d83cc019SAndroid Build Coastguard Worker !(o->pending_events & EVENT_VBLANK) && o->flip_state.count > 0) {
696*d83cc019SAndroid Build Coastguard Worker struct vblank_reply reply;
697*d83cc019SAndroid Build Coastguard Worker unsigned int exp_seq;
698*d83cc019SAndroid Build Coastguard Worker unsigned long start, end;
699*d83cc019SAndroid Build Coastguard Worker
700*d83cc019SAndroid Build Coastguard Worker exp_seq = o->flip_state.current_seq;
701*d83cc019SAndroid Build Coastguard Worker start = gettime_us();
702*d83cc019SAndroid Build Coastguard Worker do_or_die(__wait_for_vblank(TEST_VBLANK_ABSOLUTE |
703*d83cc019SAndroid Build Coastguard Worker TEST_VBLANK_BLOCK, o->pipe, exp_seq,
704*d83cc019SAndroid Build Coastguard Worker 0, &reply));
705*d83cc019SAndroid Build Coastguard Worker end = gettime_us();
706*d83cc019SAndroid Build Coastguard Worker igt_debug("Vblank took %luus\n", end - start);
707*d83cc019SAndroid Build Coastguard Worker igt_assert(end - start < 500);
708*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(reply.sequence, exp_seq);
709*d83cc019SAndroid Build Coastguard Worker igt_assert(timercmp(&reply.ts, &o->flip_state.last_ts, ==));
710*d83cc019SAndroid Build Coastguard Worker }
711*d83cc019SAndroid Build Coastguard Worker
712*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_ENOENT) {
713*d83cc019SAndroid Build Coastguard Worker /* hope that fb 0xfffffff0 does not exist */
714*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(do_page_flip(o, 0xfffffff0, false), -ENOENT);
715*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(set_mode(o, 0xfffffff0, 0, 0), -ENOENT);
716*d83cc019SAndroid Build Coastguard Worker }
717*d83cc019SAndroid Build Coastguard Worker
718*d83cc019SAndroid Build Coastguard Worker if (do_flip && (o->flags & TEST_EINVAL) && o->flip_state.count > 0)
719*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(do_page_flip(o, new_fb_id, false), expected_einval);
720*d83cc019SAndroid Build Coastguard Worker
721*d83cc019SAndroid Build Coastguard Worker if (do_vblank && (o->flags & TEST_EINVAL) && o->vblank_state.count > 0)
722*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(do_wait_for_vblank(o, o->pipe, target_seq, &vbl_reply), -EINVAL);
723*d83cc019SAndroid Build Coastguard Worker
724*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_VBLANK_RACE) {
725*d83cc019SAndroid Build Coastguard Worker spawn_vblank_wait_thread(o);
726*d83cc019SAndroid Build Coastguard Worker
727*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_MODESET)
728*d83cc019SAndroid Build Coastguard Worker igt_assert_f(set_mode(o, 0 /* no fb */, 0, 0) == 0,
729*d83cc019SAndroid Build Coastguard Worker "failed to disable output: %s\n",
730*d83cc019SAndroid Build Coastguard Worker strerror(errno));
731*d83cc019SAndroid Build Coastguard Worker }
732*d83cc019SAndroid Build Coastguard Worker
733*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_DPMS_OFF)
734*d83cc019SAndroid Build Coastguard Worker set_dpms(o, DRM_MODE_DPMS_OFF);
735*d83cc019SAndroid Build Coastguard Worker
736*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_MODESET)
737*d83cc019SAndroid Build Coastguard Worker igt_assert(set_mode(o, o->fb_ids[o->current_fb_id], 0, 0) == 0);
738*d83cc019SAndroid Build Coastguard Worker
739*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_DPMS)
740*d83cc019SAndroid Build Coastguard Worker set_dpms(o, DRM_MODE_DPMS_ON);
741*d83cc019SAndroid Build Coastguard Worker
742*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_VBLANK_RACE) {
743*d83cc019SAndroid Build Coastguard Worker struct vblank_reply reply;
744*d83cc019SAndroid Build Coastguard Worker unsigned long start, end;
745*d83cc019SAndroid Build Coastguard Worker
746*d83cc019SAndroid Build Coastguard Worker /* modeset/DPMS is done, vblank wait should work normally now */
747*d83cc019SAndroid Build Coastguard Worker start = gettime_us();
748*d83cc019SAndroid Build Coastguard Worker igt_assert(__wait_for_vblank(TEST_VBLANK_BLOCK, o->pipe, 2, 0, &reply) == 0);
749*d83cc019SAndroid Build Coastguard Worker end = gettime_us();
750*d83cc019SAndroid Build Coastguard Worker /*
751*d83cc019SAndroid Build Coastguard Worker * we waited for two vblanks, so verify that
752*d83cc019SAndroid Build Coastguard Worker * we were blocked for ~1-2 frames.
753*d83cc019SAndroid Build Coastguard Worker */
754*d83cc019SAndroid Build Coastguard Worker igt_assert_f(end - start > 0.9 * mode_frame_time(o) &&
755*d83cc019SAndroid Build Coastguard Worker end - start < 2.1 * mode_frame_time(o),
756*d83cc019SAndroid Build Coastguard Worker "wait for two vblanks took %lu usec (frame time %f usec)\n",
757*d83cc019SAndroid Build Coastguard Worker end - start, mode_frame_time(o));
758*d83cc019SAndroid Build Coastguard Worker join_vblank_wait_thread();
759*d83cc019SAndroid Build Coastguard Worker }
760*d83cc019SAndroid Build Coastguard Worker
761*d83cc019SAndroid Build Coastguard Worker igt_print_activity();
762*d83cc019SAndroid Build Coastguard Worker
763*d83cc019SAndroid Build Coastguard Worker memset(&hang, 0, sizeof(hang));
764*d83cc019SAndroid Build Coastguard Worker if (do_flip && (o->flags & TEST_HANG))
765*d83cc019SAndroid Build Coastguard Worker hang = hang_gpu(drm_fd);
766*d83cc019SAndroid Build Coastguard Worker
767*d83cc019SAndroid Build Coastguard Worker /* try to make sure we can issue two flips during the same frame */
768*d83cc019SAndroid Build Coastguard Worker if (do_flip && (o->flags & TEST_EBUSY)) {
769*d83cc019SAndroid Build Coastguard Worker struct vblank_reply reply;
770*d83cc019SAndroid Build Coastguard Worker igt_assert(__wait_for_vblank(TEST_VBLANK_BLOCK, o->pipe, 1, 0, &reply) == 0);
771*d83cc019SAndroid Build Coastguard Worker }
772*d83cc019SAndroid Build Coastguard Worker
773*d83cc019SAndroid Build Coastguard Worker if (do_flip)
774*d83cc019SAndroid Build Coastguard Worker do_or_die(do_page_flip(o, new_fb_id, !(o->flags & TEST_NOEVENT)));
775*d83cc019SAndroid Build Coastguard Worker
776*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_FENCE_STRESS)
777*d83cc019SAndroid Build Coastguard Worker emit_fence_stress(o);
778*d83cc019SAndroid Build Coastguard Worker
779*d83cc019SAndroid Build Coastguard Worker if (do_vblank) {
780*d83cc019SAndroid Build Coastguard Worker do_or_die(do_wait_for_vblank(o, o->pipe, target_seq,
781*d83cc019SAndroid Build Coastguard Worker &vbl_reply));
782*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_VBLANK_BLOCK) {
783*d83cc019SAndroid Build Coastguard Worker event_handler(&o->vblank_state, vbl_reply.sequence,
784*d83cc019SAndroid Build Coastguard Worker vbl_reply.ts.tv_sec,
785*d83cc019SAndroid Build Coastguard Worker vbl_reply.ts.tv_usec);
786*d83cc019SAndroid Build Coastguard Worker completed_events = EVENT_VBLANK;
787*d83cc019SAndroid Build Coastguard Worker }
788*d83cc019SAndroid Build Coastguard Worker }
789*d83cc019SAndroid Build Coastguard Worker
790*d83cc019SAndroid Build Coastguard Worker if (do_flip && (o->flags & TEST_EBUSY))
791*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(do_page_flip(o, new_fb_id, false), -EBUSY);
792*d83cc019SAndroid Build Coastguard Worker
793*d83cc019SAndroid Build Coastguard Worker if (do_flip && (o->flags & TEST_RMFB))
794*d83cc019SAndroid Build Coastguard Worker recreate_fb(o);
795*d83cc019SAndroid Build Coastguard Worker
796*d83cc019SAndroid Build Coastguard Worker /* pan before the flip completes */
797*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_PAN) {
798*d83cc019SAndroid Build Coastguard Worker int count = do_flip ?
799*d83cc019SAndroid Build Coastguard Worker o->flip_state.count : o->vblank_state.count;
800*d83cc019SAndroid Build Coastguard Worker int width = o->fb_width - o->kmode[0].hdisplay;
801*d83cc019SAndroid Build Coastguard Worker int x_ofs = count * 10 % (2 * width);
802*d83cc019SAndroid Build Coastguard Worker if (x_ofs >= width)
803*d83cc019SAndroid Build Coastguard Worker x_ofs = 2 * width - x_ofs;
804*d83cc019SAndroid Build Coastguard Worker
805*d83cc019SAndroid Build Coastguard Worker /* Make sure DSPSURF changes value */
806*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_HANG)
807*d83cc019SAndroid Build Coastguard Worker o->current_fb_id = !o->current_fb_id;
808*d83cc019SAndroid Build Coastguard Worker
809*d83cc019SAndroid Build Coastguard Worker igt_assert_f(set_mode(o, o->fb_ids[o->current_fb_id], x_ofs, 0) == 0,
810*d83cc019SAndroid Build Coastguard Worker "failed to pan (%dx%d@%dHz)+%d: %s\n",
811*d83cc019SAndroid Build Coastguard Worker o->kmode[0].hdisplay, o->kmode[0].vdisplay, o->kmode[0].vrefresh,
812*d83cc019SAndroid Build Coastguard Worker x_ofs, strerror(errno));
813*d83cc019SAndroid Build Coastguard Worker }
814*d83cc019SAndroid Build Coastguard Worker
815*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_DPMS)
816*d83cc019SAndroid Build Coastguard Worker set_dpms(o, DRM_MODE_DPMS_OFF);
817*d83cc019SAndroid Build Coastguard Worker
818*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_MODESET && !(o->flags & TEST_RMFB) && !(o->flags & TEST_VBLANK_RACE))
819*d83cc019SAndroid Build Coastguard Worker igt_assert_f(set_mode(o, 0 /* no fb */, 0, 0) == 0,
820*d83cc019SAndroid Build Coastguard Worker "failed to disable output: %s\n",
821*d83cc019SAndroid Build Coastguard Worker strerror(errno));
822*d83cc019SAndroid Build Coastguard Worker
823*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_SUSPEND)
824*d83cc019SAndroid Build Coastguard Worker igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
825*d83cc019SAndroid Build Coastguard Worker SUSPEND_TEST_NONE);
826*d83cc019SAndroid Build Coastguard Worker
827*d83cc019SAndroid Build Coastguard Worker if (do_vblank && (o->flags & TEST_EINVAL) && o->vblank_state.count > 0)
828*d83cc019SAndroid Build Coastguard Worker igt_assert(do_wait_for_vblank(o, o->pipe, target_seq, &vbl_reply)
829*d83cc019SAndroid Build Coastguard Worker == -EINVAL);
830*d83cc019SAndroid Build Coastguard Worker
831*d83cc019SAndroid Build Coastguard Worker if (do_flip && (o->flags & TEST_EINVAL))
832*d83cc019SAndroid Build Coastguard Worker igt_assert(do_page_flip(o, new_fb_id, false) == expected_einval);
833*d83cc019SAndroid Build Coastguard Worker
834*d83cc019SAndroid Build Coastguard Worker unhang_gpu(drm_fd, hang);
835*d83cc019SAndroid Build Coastguard Worker
836*d83cc019SAndroid Build Coastguard Worker return completed_events;
837*d83cc019SAndroid Build Coastguard Worker }
838*d83cc019SAndroid Build Coastguard Worker
update_state(struct event_state * es)839*d83cc019SAndroid Build Coastguard Worker static void update_state(struct event_state *es)
840*d83cc019SAndroid Build Coastguard Worker {
841*d83cc019SAndroid Build Coastguard Worker es->last_received_ts = es->current_received_ts;
842*d83cc019SAndroid Build Coastguard Worker es->last_ts = es->current_ts;
843*d83cc019SAndroid Build Coastguard Worker es->last_seq = es->current_seq;
844*d83cc019SAndroid Build Coastguard Worker es->count++;
845*d83cc019SAndroid Build Coastguard Worker }
846*d83cc019SAndroid Build Coastguard Worker
update_all_state(struct test_output * o,unsigned int completed_events)847*d83cc019SAndroid Build Coastguard Worker static void update_all_state(struct test_output *o,
848*d83cc019SAndroid Build Coastguard Worker unsigned int completed_events)
849*d83cc019SAndroid Build Coastguard Worker {
850*d83cc019SAndroid Build Coastguard Worker if (completed_events & EVENT_FLIP)
851*d83cc019SAndroid Build Coastguard Worker update_state(&o->flip_state);
852*d83cc019SAndroid Build Coastguard Worker
853*d83cc019SAndroid Build Coastguard Worker if (completed_events & EVENT_VBLANK)
854*d83cc019SAndroid Build Coastguard Worker update_state(&o->vblank_state);
855*d83cc019SAndroid Build Coastguard Worker }
856*d83cc019SAndroid Build Coastguard Worker
connector_find_preferred_mode(uint32_t connector_id,int crtc_idx,struct test_output * o)857*d83cc019SAndroid Build Coastguard Worker static void connector_find_preferred_mode(uint32_t connector_id, int crtc_idx,
858*d83cc019SAndroid Build Coastguard Worker struct test_output *o)
859*d83cc019SAndroid Build Coastguard Worker {
860*d83cc019SAndroid Build Coastguard Worker struct kmstest_connector_config config;
861*d83cc019SAndroid Build Coastguard Worker
862*d83cc019SAndroid Build Coastguard Worker if (!kmstest_get_connector_config(drm_fd, connector_id, 1 << crtc_idx,
863*d83cc019SAndroid Build Coastguard Worker &config)) {
864*d83cc019SAndroid Build Coastguard Worker o->mode_valid = 0;
865*d83cc019SAndroid Build Coastguard Worker return;
866*d83cc019SAndroid Build Coastguard Worker }
867*d83cc019SAndroid Build Coastguard Worker
868*d83cc019SAndroid Build Coastguard Worker o->pipe = config.pipe;
869*d83cc019SAndroid Build Coastguard Worker o->kconnector[0] = config.connector;
870*d83cc019SAndroid Build Coastguard Worker o->kencoder[0] = config.encoder;
871*d83cc019SAndroid Build Coastguard Worker o->_crtc[0] = config.crtc->crtc_id;
872*d83cc019SAndroid Build Coastguard Worker o->_pipe[0] = config.pipe;
873*d83cc019SAndroid Build Coastguard Worker o->kmode[0] = config.default_mode;
874*d83cc019SAndroid Build Coastguard Worker o->mode_valid = 1;
875*d83cc019SAndroid Build Coastguard Worker
876*d83cc019SAndroid Build Coastguard Worker o->fb_width = o->kmode[0].hdisplay;
877*d83cc019SAndroid Build Coastguard Worker o->fb_height = o->kmode[0].vdisplay;
878*d83cc019SAndroid Build Coastguard Worker
879*d83cc019SAndroid Build Coastguard Worker drmModeFreeCrtc(config.crtc);
880*d83cc019SAndroid Build Coastguard Worker }
881*d83cc019SAndroid Build Coastguard Worker
mode_compatible(const drmModeModeInfo * a,const drmModeModeInfo * b)882*d83cc019SAndroid Build Coastguard Worker static bool mode_compatible(const drmModeModeInfo *a, const drmModeModeInfo *b)
883*d83cc019SAndroid Build Coastguard Worker {
884*d83cc019SAndroid Build Coastguard Worker int d_refresh;
885*d83cc019SAndroid Build Coastguard Worker
886*d83cc019SAndroid Build Coastguard Worker if (a->hdisplay != b->hdisplay)
887*d83cc019SAndroid Build Coastguard Worker return false;
888*d83cc019SAndroid Build Coastguard Worker
889*d83cc019SAndroid Build Coastguard Worker if (a->vdisplay != b->vdisplay)
890*d83cc019SAndroid Build Coastguard Worker return false;
891*d83cc019SAndroid Build Coastguard Worker
892*d83cc019SAndroid Build Coastguard Worker d_refresh = a->vrefresh - b->vrefresh;
893*d83cc019SAndroid Build Coastguard Worker if (d_refresh < -1 || d_refresh > 1)
894*d83cc019SAndroid Build Coastguard Worker return false;
895*d83cc019SAndroid Build Coastguard Worker
896*d83cc019SAndroid Build Coastguard Worker return true;
897*d83cc019SAndroid Build Coastguard Worker }
898*d83cc019SAndroid Build Coastguard Worker
connector_find_compatible_mode(int crtc_idx0,int crtc_idx1,struct test_output * o)899*d83cc019SAndroid Build Coastguard Worker static void connector_find_compatible_mode(int crtc_idx0, int crtc_idx1,
900*d83cc019SAndroid Build Coastguard Worker struct test_output *o)
901*d83cc019SAndroid Build Coastguard Worker {
902*d83cc019SAndroid Build Coastguard Worker struct kmstest_connector_config config[2];
903*d83cc019SAndroid Build Coastguard Worker drmModeModeInfo *mode[2];
904*d83cc019SAndroid Build Coastguard Worker int n, m;
905*d83cc019SAndroid Build Coastguard Worker
906*d83cc019SAndroid Build Coastguard Worker if (!kmstest_get_connector_config(drm_fd, o->_connector[0],
907*d83cc019SAndroid Build Coastguard Worker 1 << crtc_idx0, &config[0]))
908*d83cc019SAndroid Build Coastguard Worker return;
909*d83cc019SAndroid Build Coastguard Worker
910*d83cc019SAndroid Build Coastguard Worker if (!kmstest_get_connector_config(drm_fd, o->_connector[1],
911*d83cc019SAndroid Build Coastguard Worker 1 << crtc_idx1, &config[1])) {
912*d83cc019SAndroid Build Coastguard Worker kmstest_free_connector_config(&config[0]);
913*d83cc019SAndroid Build Coastguard Worker return;
914*d83cc019SAndroid Build Coastguard Worker }
915*d83cc019SAndroid Build Coastguard Worker
916*d83cc019SAndroid Build Coastguard Worker mode[0] = &config[0].default_mode;
917*d83cc019SAndroid Build Coastguard Worker mode[1] = &config[1].default_mode;
918*d83cc019SAndroid Build Coastguard Worker if (!mode_compatible(mode[0], mode[1])) {
919*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < config[0].connector->count_modes; n++) {
920*d83cc019SAndroid Build Coastguard Worker mode[0] = &config[0].connector->modes[n];
921*d83cc019SAndroid Build Coastguard Worker for (m = 0; m < config[1].connector->count_modes; m++) {
922*d83cc019SAndroid Build Coastguard Worker mode[1] = &config[1].connector->modes[m];
923*d83cc019SAndroid Build Coastguard Worker if (mode_compatible(mode[0], mode[1]))
924*d83cc019SAndroid Build Coastguard Worker goto found;
925*d83cc019SAndroid Build Coastguard Worker }
926*d83cc019SAndroid Build Coastguard Worker }
927*d83cc019SAndroid Build Coastguard Worker
928*d83cc019SAndroid Build Coastguard Worker /* hope for the best! */
929*d83cc019SAndroid Build Coastguard Worker mode[1] = mode[0] = &config[0].default_mode;
930*d83cc019SAndroid Build Coastguard Worker }
931*d83cc019SAndroid Build Coastguard Worker
932*d83cc019SAndroid Build Coastguard Worker found:
933*d83cc019SAndroid Build Coastguard Worker o->pipe = config[0].pipe;
934*d83cc019SAndroid Build Coastguard Worker o->fb_width = mode[0]->hdisplay;
935*d83cc019SAndroid Build Coastguard Worker o->fb_height = mode[0]->vdisplay;
936*d83cc019SAndroid Build Coastguard Worker o->mode_valid = 1;
937*d83cc019SAndroid Build Coastguard Worker
938*d83cc019SAndroid Build Coastguard Worker o->kconnector[0] = config[0].connector;
939*d83cc019SAndroid Build Coastguard Worker o->kencoder[0] = config[0].encoder;
940*d83cc019SAndroid Build Coastguard Worker o->_crtc[0] = config[0].crtc->crtc_id;
941*d83cc019SAndroid Build Coastguard Worker o->_pipe[0] = config[0].pipe;
942*d83cc019SAndroid Build Coastguard Worker o->kmode[0] = *mode[0];
943*d83cc019SAndroid Build Coastguard Worker
944*d83cc019SAndroid Build Coastguard Worker o->kconnector[1] = config[1].connector;
945*d83cc019SAndroid Build Coastguard Worker o->kencoder[1] = config[1].encoder;
946*d83cc019SAndroid Build Coastguard Worker o->_crtc[1] = config[1].crtc->crtc_id;
947*d83cc019SAndroid Build Coastguard Worker o->_pipe[1] = config[1].pipe;
948*d83cc019SAndroid Build Coastguard Worker o->kmode[1] = *mode[1];
949*d83cc019SAndroid Build Coastguard Worker
950*d83cc019SAndroid Build Coastguard Worker drmModeFreeCrtc(config[0].crtc);
951*d83cc019SAndroid Build Coastguard Worker drmModeFreeCrtc(config[1].crtc);
952*d83cc019SAndroid Build Coastguard Worker }
953*d83cc019SAndroid Build Coastguard Worker
paint_flip_mode(struct igt_fb * fb,bool odd_frame)954*d83cc019SAndroid Build Coastguard Worker static void paint_flip_mode(struct igt_fb *fb, bool odd_frame)
955*d83cc019SAndroid Build Coastguard Worker {
956*d83cc019SAndroid Build Coastguard Worker /* TODO (b/145293089) resolve Cairo/Pixman dependencies */
957*d83cc019SAndroid Build Coastguard Worker #if defined(USE_CAIRO_PIXMAN)
958*d83cc019SAndroid Build Coastguard Worker cairo_t *cr = igt_get_cairo_ctx(drm_fd, fb);
959*d83cc019SAndroid Build Coastguard Worker int width = fb->width;
960*d83cc019SAndroid Build Coastguard Worker int height = fb->height;
961*d83cc019SAndroid Build Coastguard Worker
962*d83cc019SAndroid Build Coastguard Worker igt_paint_test_pattern(cr, width, height);
963*d83cc019SAndroid Build Coastguard Worker
964*d83cc019SAndroid Build Coastguard Worker if (odd_frame)
965*d83cc019SAndroid Build Coastguard Worker cairo_rectangle(cr, width/4, height/2, width/4, height/8);
966*d83cc019SAndroid Build Coastguard Worker else
967*d83cc019SAndroid Build Coastguard Worker cairo_rectangle(cr, width/2, height/2, width/4, height/8);
968*d83cc019SAndroid Build Coastguard Worker
969*d83cc019SAndroid Build Coastguard Worker cairo_set_source_rgb(cr, 1, 1, 1);
970*d83cc019SAndroid Build Coastguard Worker cairo_fill(cr);
971*d83cc019SAndroid Build Coastguard Worker
972*d83cc019SAndroid Build Coastguard Worker igt_put_cairo_ctx(drm_fd, fb, cr);
973*d83cc019SAndroid Build Coastguard Worker #endif
974*d83cc019SAndroid Build Coastguard Worker }
975*d83cc019SAndroid Build Coastguard Worker
fb_is_bound(struct test_output * o,int fb)976*d83cc019SAndroid Build Coastguard Worker static bool fb_is_bound(struct test_output *o, int fb)
977*d83cc019SAndroid Build Coastguard Worker {
978*d83cc019SAndroid Build Coastguard Worker int n;
979*d83cc019SAndroid Build Coastguard Worker
980*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < o->count; n++) {
981*d83cc019SAndroid Build Coastguard Worker struct drm_mode_crtc mode = {
982*d83cc019SAndroid Build Coastguard Worker .crtc_id = o->_crtc[n]
983*d83cc019SAndroid Build Coastguard Worker };
984*d83cc019SAndroid Build Coastguard Worker
985*d83cc019SAndroid Build Coastguard Worker if (drmIoctl(drm_fd, DRM_IOCTL_MODE_GETCRTC, &mode))
986*d83cc019SAndroid Build Coastguard Worker return false;
987*d83cc019SAndroid Build Coastguard Worker
988*d83cc019SAndroid Build Coastguard Worker if (!mode.mode_valid || mode.fb_id != fb)
989*d83cc019SAndroid Build Coastguard Worker return false;
990*d83cc019SAndroid Build Coastguard Worker }
991*d83cc019SAndroid Build Coastguard Worker
992*d83cc019SAndroid Build Coastguard Worker return true;
993*d83cc019SAndroid Build Coastguard Worker }
994*d83cc019SAndroid Build Coastguard Worker
check_final_state(const struct test_output * o,const struct event_state * es,unsigned int elapsed)995*d83cc019SAndroid Build Coastguard Worker static void check_final_state(const struct test_output *o,
996*d83cc019SAndroid Build Coastguard Worker const struct event_state *es,
997*d83cc019SAndroid Build Coastguard Worker unsigned int elapsed)
998*d83cc019SAndroid Build Coastguard Worker {
999*d83cc019SAndroid Build Coastguard Worker igt_assert_f(es->count > 0,
1000*d83cc019SAndroid Build Coastguard Worker "no %s event received\n", es->name);
1001*d83cc019SAndroid Build Coastguard Worker
1002*d83cc019SAndroid Build Coastguard Worker /* Verify we drop no frames, but only if it's not a TV encoder, since
1003*d83cc019SAndroid Build Coastguard Worker * those use some funny fake timings behind userspace's back. */
1004*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_CHECK_TS) {
1005*d83cc019SAndroid Build Coastguard Worker int count = es->count * o->seq_step;
1006*d83cc019SAndroid Build Coastguard Worker unsigned int min = actual_frame_time(o) * (count - 1);
1007*d83cc019SAndroid Build Coastguard Worker unsigned int max = actual_frame_time(o) * (count + 1);
1008*d83cc019SAndroid Build Coastguard Worker
1009*d83cc019SAndroid Build Coastguard Worker igt_debug("expected %d, counted %d, encoder type %d\n",
1010*d83cc019SAndroid Build Coastguard Worker (int)(elapsed / actual_frame_time(o)), count,
1011*d83cc019SAndroid Build Coastguard Worker o->kencoder[0]->encoder_type);
1012*d83cc019SAndroid Build Coastguard Worker igt_assert_f(elapsed >= min && elapsed <= max,
1013*d83cc019SAndroid Build Coastguard Worker "dropped frames, expected %d, counted %d, encoder type %d\n",
1014*d83cc019SAndroid Build Coastguard Worker (int)(elapsed / actual_frame_time(o)), count,
1015*d83cc019SAndroid Build Coastguard Worker o->kencoder[0]->encoder_type);
1016*d83cc019SAndroid Build Coastguard Worker }
1017*d83cc019SAndroid Build Coastguard Worker }
1018*d83cc019SAndroid Build Coastguard Worker
1019*d83cc019SAndroid Build Coastguard Worker /*
1020*d83cc019SAndroid Build Coastguard Worker * Wait until at least one pending event completes. Return mask of completed
1021*d83cc019SAndroid Build Coastguard Worker * events.
1022*d83cc019SAndroid Build Coastguard Worker */
wait_for_events(struct test_output * o)1023*d83cc019SAndroid Build Coastguard Worker static unsigned int wait_for_events(struct test_output *o)
1024*d83cc019SAndroid Build Coastguard Worker {
1025*d83cc019SAndroid Build Coastguard Worker drmEventContext evctx;
1026*d83cc019SAndroid Build Coastguard Worker struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
1027*d83cc019SAndroid Build Coastguard Worker fd_set fds;
1028*d83cc019SAndroid Build Coastguard Worker unsigned int event_mask;
1029*d83cc019SAndroid Build Coastguard Worker int ret;
1030*d83cc019SAndroid Build Coastguard Worker
1031*d83cc019SAndroid Build Coastguard Worker event_mask = o->pending_events;
1032*d83cc019SAndroid Build Coastguard Worker igt_assert(event_mask);
1033*d83cc019SAndroid Build Coastguard Worker
1034*d83cc019SAndroid Build Coastguard Worker memset(&evctx, 0, sizeof evctx);
1035*d83cc019SAndroid Build Coastguard Worker evctx.version = 2;
1036*d83cc019SAndroid Build Coastguard Worker evctx.vblank_handler = vblank_handler;
1037*d83cc019SAndroid Build Coastguard Worker evctx.page_flip_handler = page_flip_handler;
1038*d83cc019SAndroid Build Coastguard Worker
1039*d83cc019SAndroid Build Coastguard Worker FD_ZERO(&fds);
1040*d83cc019SAndroid Build Coastguard Worker FD_SET(drm_fd, &fds);
1041*d83cc019SAndroid Build Coastguard Worker do {
1042*d83cc019SAndroid Build Coastguard Worker do {
1043*d83cc019SAndroid Build Coastguard Worker ret = select(drm_fd + 1, &fds, NULL, NULL, &timeout);
1044*d83cc019SAndroid Build Coastguard Worker } while (ret < 0 && errno == EINTR);
1045*d83cc019SAndroid Build Coastguard Worker
1046*d83cc019SAndroid Build Coastguard Worker igt_assert_f(ret >= 0,
1047*d83cc019SAndroid Build Coastguard Worker "select error (errno %i)\n", errno);
1048*d83cc019SAndroid Build Coastguard Worker igt_assert_f(ret > 0,
1049*d83cc019SAndroid Build Coastguard Worker "select timed out or error (ret %d)\n", ret);
1050*d83cc019SAndroid Build Coastguard Worker igt_assert_f(!FD_ISSET(0, &fds),
1051*d83cc019SAndroid Build Coastguard Worker "no fds active, breaking\n");
1052*d83cc019SAndroid Build Coastguard Worker
1053*d83cc019SAndroid Build Coastguard Worker do_or_die(drmHandleEvent(drm_fd, &evctx));
1054*d83cc019SAndroid Build Coastguard Worker } while (o->pending_events);
1055*d83cc019SAndroid Build Coastguard Worker
1056*d83cc019SAndroid Build Coastguard Worker event_mask ^= o->pending_events;
1057*d83cc019SAndroid Build Coastguard Worker igt_assert(event_mask);
1058*d83cc019SAndroid Build Coastguard Worker
1059*d83cc019SAndroid Build Coastguard Worker return event_mask;
1060*d83cc019SAndroid Build Coastguard Worker }
1061*d83cc019SAndroid Build Coastguard Worker
1062*d83cc019SAndroid Build Coastguard Worker /* Returned the elapsed time in us */
event_loop(struct test_output * o,unsigned duration_ms)1063*d83cc019SAndroid Build Coastguard Worker static unsigned event_loop(struct test_output *o, unsigned duration_ms)
1064*d83cc019SAndroid Build Coastguard Worker {
1065*d83cc019SAndroid Build Coastguard Worker unsigned long start, end;
1066*d83cc019SAndroid Build Coastguard Worker int count = 0;
1067*d83cc019SAndroid Build Coastguard Worker
1068*d83cc019SAndroid Build Coastguard Worker start = gettime_us();
1069*d83cc019SAndroid Build Coastguard Worker
1070*d83cc019SAndroid Build Coastguard Worker while (1) {
1071*d83cc019SAndroid Build Coastguard Worker unsigned int completed_events;
1072*d83cc019SAndroid Build Coastguard Worker
1073*d83cc019SAndroid Build Coastguard Worker completed_events = run_test_step(o);
1074*d83cc019SAndroid Build Coastguard Worker if (o->pending_events)
1075*d83cc019SAndroid Build Coastguard Worker completed_events |= wait_for_events(o);
1076*d83cc019SAndroid Build Coastguard Worker check_all_state(o, completed_events);
1077*d83cc019SAndroid Build Coastguard Worker update_all_state(o, completed_events);
1078*d83cc019SAndroid Build Coastguard Worker
1079*d83cc019SAndroid Build Coastguard Worker if (count && (gettime_us() - start) / 1000 >= duration_ms)
1080*d83cc019SAndroid Build Coastguard Worker break;
1081*d83cc019SAndroid Build Coastguard Worker
1082*d83cc019SAndroid Build Coastguard Worker count++;
1083*d83cc019SAndroid Build Coastguard Worker }
1084*d83cc019SAndroid Build Coastguard Worker
1085*d83cc019SAndroid Build Coastguard Worker end = gettime_us();
1086*d83cc019SAndroid Build Coastguard Worker
1087*d83cc019SAndroid Build Coastguard Worker /* Flush any remaining events */
1088*d83cc019SAndroid Build Coastguard Worker if (o->pending_events)
1089*d83cc019SAndroid Build Coastguard Worker wait_for_events(o);
1090*d83cc019SAndroid Build Coastguard Worker
1091*d83cc019SAndroid Build Coastguard Worker return end - start;
1092*d83cc019SAndroid Build Coastguard Worker }
1093*d83cc019SAndroid Build Coastguard Worker
free_test_output(struct test_output * o)1094*d83cc019SAndroid Build Coastguard Worker static void free_test_output(struct test_output *o)
1095*d83cc019SAndroid Build Coastguard Worker {
1096*d83cc019SAndroid Build Coastguard Worker int i;
1097*d83cc019SAndroid Build Coastguard Worker
1098*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < o->count; i++) {
1099*d83cc019SAndroid Build Coastguard Worker drmModeFreeEncoder(o->kencoder[i]);
1100*d83cc019SAndroid Build Coastguard Worker drmModeFreeConnector(o->kconnector[i]);
1101*d83cc019SAndroid Build Coastguard Worker }
1102*d83cc019SAndroid Build Coastguard Worker }
1103*d83cc019SAndroid Build Coastguard Worker
calibrate_ts(struct test_output * o,int crtc_idx)1104*d83cc019SAndroid Build Coastguard Worker static void calibrate_ts(struct test_output *o, int crtc_idx)
1105*d83cc019SAndroid Build Coastguard Worker {
1106*d83cc019SAndroid Build Coastguard Worker #define CALIBRATE_TS_STEPS 16
1107*d83cc019SAndroid Build Coastguard Worker drmVBlank wait;
1108*d83cc019SAndroid Build Coastguard Worker igt_stats_t stats;
1109*d83cc019SAndroid Build Coastguard Worker uint32_t last_seq;
1110*d83cc019SAndroid Build Coastguard Worker uint64_t last_timestamp;
1111*d83cc019SAndroid Build Coastguard Worker double expected;
1112*d83cc019SAndroid Build Coastguard Worker double mean;
1113*d83cc019SAndroid Build Coastguard Worker double stddev;
1114*d83cc019SAndroid Build Coastguard Worker int n;
1115*d83cc019SAndroid Build Coastguard Worker
1116*d83cc019SAndroid Build Coastguard Worker memset(&wait, 0, sizeof(wait));
1117*d83cc019SAndroid Build Coastguard Worker wait.request.type = kmstest_get_vbl_flag(crtc_idx);
1118*d83cc019SAndroid Build Coastguard Worker wait.request.type |= DRM_VBLANK_RELATIVE | DRM_VBLANK_NEXTONMISS;
1119*d83cc019SAndroid Build Coastguard Worker do_or_die(drmWaitVBlank(drm_fd, &wait));
1120*d83cc019SAndroid Build Coastguard Worker
1121*d83cc019SAndroid Build Coastguard Worker last_seq = wait.reply.sequence;
1122*d83cc019SAndroid Build Coastguard Worker last_timestamp = wait.reply.tval_sec;
1123*d83cc019SAndroid Build Coastguard Worker last_timestamp *= 1000000;
1124*d83cc019SAndroid Build Coastguard Worker last_timestamp += wait.reply.tval_usec;
1125*d83cc019SAndroid Build Coastguard Worker
1126*d83cc019SAndroid Build Coastguard Worker memset(&wait, 0, sizeof(wait));
1127*d83cc019SAndroid Build Coastguard Worker wait.request.type = kmstest_get_vbl_flag(crtc_idx);
1128*d83cc019SAndroid Build Coastguard Worker wait.request.type |= DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
1129*d83cc019SAndroid Build Coastguard Worker wait.request.sequence = last_seq;
1130*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < CALIBRATE_TS_STEPS; n++) {
1131*d83cc019SAndroid Build Coastguard Worker drmVBlank check = {};
1132*d83cc019SAndroid Build Coastguard Worker
1133*d83cc019SAndroid Build Coastguard Worker ++wait.request.sequence;
1134*d83cc019SAndroid Build Coastguard Worker do_or_die(drmWaitVBlank(drm_fd, &wait));
1135*d83cc019SAndroid Build Coastguard Worker
1136*d83cc019SAndroid Build Coastguard Worker /* Double check that haven't already missed the vblank */
1137*d83cc019SAndroid Build Coastguard Worker check.request.type = kmstest_get_vbl_flag(crtc_idx);
1138*d83cc019SAndroid Build Coastguard Worker check.request.type |= DRM_VBLANK_RELATIVE;
1139*d83cc019SAndroid Build Coastguard Worker do_or_die(drmWaitVBlank(drm_fd, &check));
1140*d83cc019SAndroid Build Coastguard Worker
1141*d83cc019SAndroid Build Coastguard Worker igt_assert(!igt_vblank_after(check.reply.sequence, wait.request.sequence));
1142*d83cc019SAndroid Build Coastguard Worker }
1143*d83cc019SAndroid Build Coastguard Worker
1144*d83cc019SAndroid Build Coastguard Worker igt_stats_init_with_size(&stats, CALIBRATE_TS_STEPS);
1145*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < CALIBRATE_TS_STEPS; n++) {
1146*d83cc019SAndroid Build Coastguard Worker struct drm_event_vblank ev;
1147*d83cc019SAndroid Build Coastguard Worker uint64_t now;
1148*d83cc019SAndroid Build Coastguard Worker int poll_ret;
1149*d83cc019SAndroid Build Coastguard Worker
1150*d83cc019SAndroid Build Coastguard Worker while (1) {
1151*d83cc019SAndroid Build Coastguard Worker /*
1152*d83cc019SAndroid Build Coastguard Worker * In case of the interruptible tests, this poll may
1153*d83cc019SAndroid Build Coastguard Worker * be interrupted with -EINTR, handle this by restarting
1154*d83cc019SAndroid Build Coastguard Worker * until we poll timeout or success.
1155*d83cc019SAndroid Build Coastguard Worker */
1156*d83cc019SAndroid Build Coastguard Worker poll_ret = poll(&(struct pollfd){drm_fd, POLLIN}, 1, 1000);
1157*d83cc019SAndroid Build Coastguard Worker
1158*d83cc019SAndroid Build Coastguard Worker if (poll_ret == 1)
1159*d83cc019SAndroid Build Coastguard Worker break;
1160*d83cc019SAndroid Build Coastguard Worker
1161*d83cc019SAndroid Build Coastguard Worker igt_assert_neq(poll_ret, 0);
1162*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(errno, EINTR);
1163*d83cc019SAndroid Build Coastguard Worker }
1164*d83cc019SAndroid Build Coastguard Worker igt_assert(read(drm_fd, &ev, sizeof(ev)) == sizeof(ev));
1165*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(ev.sequence, last_seq + 1);
1166*d83cc019SAndroid Build Coastguard Worker
1167*d83cc019SAndroid Build Coastguard Worker now = ev.tv_sec;
1168*d83cc019SAndroid Build Coastguard Worker now *= 1000000;
1169*d83cc019SAndroid Build Coastguard Worker now += ev.tv_usec;
1170*d83cc019SAndroid Build Coastguard Worker
1171*d83cc019SAndroid Build Coastguard Worker igt_stats_push(&stats, now - last_timestamp);
1172*d83cc019SAndroid Build Coastguard Worker
1173*d83cc019SAndroid Build Coastguard Worker last_timestamp = now;
1174*d83cc019SAndroid Build Coastguard Worker last_seq = ev.sequence;
1175*d83cc019SAndroid Build Coastguard Worker }
1176*d83cc019SAndroid Build Coastguard Worker
1177*d83cc019SAndroid Build Coastguard Worker expected = mode_frame_time(o);
1178*d83cc019SAndroid Build Coastguard Worker
1179*d83cc019SAndroid Build Coastguard Worker mean = igt_stats_get_mean(&stats);
1180*d83cc019SAndroid Build Coastguard Worker stddev = igt_stats_get_std_deviation(&stats);
1181*d83cc019SAndroid Build Coastguard Worker
1182*d83cc019SAndroid Build Coastguard Worker igt_info("Expected frametime: %.0fus; measured %.1fus +- %.3fus accuracy %.2f%%\n",
1183*d83cc019SAndroid Build Coastguard Worker expected, mean, stddev, 100 * 3 * stddev / mean);
1184*d83cc019SAndroid Build Coastguard Worker /* 99.7% samples within 0.5% of the mean */
1185*d83cc019SAndroid Build Coastguard Worker /* Removing the check as this level of accuracy is hard to acheive.
1186*d83cc019SAndroid Build Coastguard Worker * The test fails on many current devices.
1187*d83cc019SAndroid Build Coastguard Worker */
1188*d83cc019SAndroid Build Coastguard Worker // igt_assert(3 * stddev / mean < 0.005);
1189*d83cc019SAndroid Build Coastguard Worker igt_warn_on_f(!(3 * stddev / mean < 0.005),
1190*d83cc019SAndroid Build Coastguard Worker "VBlank intervals do not form a normal distribution.\n");
1191*d83cc019SAndroid Build Coastguard Worker /* 84% samples within 0.5% of the expected value.
1192*d83cc019SAndroid Build Coastguard Worker * See comments in check_timings() in kms_setmode.c
1193*d83cc019SAndroid Build Coastguard Worker */
1194*d83cc019SAndroid Build Coastguard Worker if (fabs(mean - expected) > 2*stddev) {
1195*d83cc019SAndroid Build Coastguard Worker igt_info("vblank interval differs from modeline! expected %.1fus, measured %1.fus +- %.3fus, difference %.1fus (%.1f sigma)\n",
1196*d83cc019SAndroid Build Coastguard Worker expected, mean, stddev,
1197*d83cc019SAndroid Build Coastguard Worker fabs(mean - expected), fabs(mean - expected) / stddev);
1198*d83cc019SAndroid Build Coastguard Worker }
1199*d83cc019SAndroid Build Coastguard Worker
1200*d83cc019SAndroid Build Coastguard Worker o->vblank_interval = mean;
1201*d83cc019SAndroid Build Coastguard Worker }
1202*d83cc019SAndroid Build Coastguard Worker
run_test_on_crtc_set(struct test_output * o,int * crtc_idxs,int crtc_count,int duration_ms)1203*d83cc019SAndroid Build Coastguard Worker static void run_test_on_crtc_set(struct test_output *o, int *crtc_idxs,
1204*d83cc019SAndroid Build Coastguard Worker int crtc_count, int duration_ms)
1205*d83cc019SAndroid Build Coastguard Worker {
1206*d83cc019SAndroid Build Coastguard Worker char test_name[128];
1207*d83cc019SAndroid Build Coastguard Worker unsigned elapsed;
1208*d83cc019SAndroid Build Coastguard Worker unsigned bo_size = 0;
1209*d83cc019SAndroid Build Coastguard Worker uint64_t tiling;
1210*d83cc019SAndroid Build Coastguard Worker int i;
1211*d83cc019SAndroid Build Coastguard Worker bool vblank = true;
1212*d83cc019SAndroid Build Coastguard Worker
1213*d83cc019SAndroid Build Coastguard Worker switch (crtc_count) {
1214*d83cc019SAndroid Build Coastguard Worker case RUN_TEST:
1215*d83cc019SAndroid Build Coastguard Worker connector_find_preferred_mode(o->_connector[0], crtc_idxs[0], o);
1216*d83cc019SAndroid Build Coastguard Worker if (!o->mode_valid)
1217*d83cc019SAndroid Build Coastguard Worker return;
1218*d83cc019SAndroid Build Coastguard Worker snprintf(test_name, sizeof(test_name),
1219*d83cc019SAndroid Build Coastguard Worker "%s on pipe %s, connector %s-%d",
1220*d83cc019SAndroid Build Coastguard Worker igt_subtest_name(),
1221*d83cc019SAndroid Build Coastguard Worker kmstest_pipe_name(o->_pipe[0]),
1222*d83cc019SAndroid Build Coastguard Worker kmstest_connector_type_str(o->kconnector[0]->connector_type),
1223*d83cc019SAndroid Build Coastguard Worker o->kconnector[0]->connector_type_id);
1224*d83cc019SAndroid Build Coastguard Worker break;
1225*d83cc019SAndroid Build Coastguard Worker case RUN_PAIR:
1226*d83cc019SAndroid Build Coastguard Worker connector_find_compatible_mode(crtc_idxs[0], crtc_idxs[1], o);
1227*d83cc019SAndroid Build Coastguard Worker if (!o->mode_valid)
1228*d83cc019SAndroid Build Coastguard Worker return;
1229*d83cc019SAndroid Build Coastguard Worker snprintf(test_name, sizeof(test_name),
1230*d83cc019SAndroid Build Coastguard Worker "%s on pipe %s:%s, connector %s-%d:%s-%d",
1231*d83cc019SAndroid Build Coastguard Worker igt_subtest_name(),
1232*d83cc019SAndroid Build Coastguard Worker kmstest_pipe_name(o->_pipe[0]),
1233*d83cc019SAndroid Build Coastguard Worker kmstest_pipe_name(o->_pipe[1]),
1234*d83cc019SAndroid Build Coastguard Worker kmstest_connector_type_str(o->kconnector[0]->connector_type),
1235*d83cc019SAndroid Build Coastguard Worker o->kconnector[0]->connector_type_id,
1236*d83cc019SAndroid Build Coastguard Worker kmstest_connector_type_str(o->kconnector[1]->connector_type),
1237*d83cc019SAndroid Build Coastguard Worker o->kconnector[1]->connector_type_id);
1238*d83cc019SAndroid Build Coastguard Worker break;
1239*d83cc019SAndroid Build Coastguard Worker default:
1240*d83cc019SAndroid Build Coastguard Worker igt_assert(0);
1241*d83cc019SAndroid Build Coastguard Worker }
1242*d83cc019SAndroid Build Coastguard Worker
1243*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(o->count, crtc_count);
1244*d83cc019SAndroid Build Coastguard Worker
1245*d83cc019SAndroid Build Coastguard Worker last_connector = o->kconnector[0];
1246*d83cc019SAndroid Build Coastguard Worker
1247*d83cc019SAndroid Build Coastguard Worker igt_info("Beginning %s\n", test_name);
1248*d83cc019SAndroid Build Coastguard Worker
1249*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_PAN)
1250*d83cc019SAndroid Build Coastguard Worker o->fb_width *= 2;
1251*d83cc019SAndroid Build Coastguard Worker
1252*d83cc019SAndroid Build Coastguard Worker tiling = LOCAL_DRM_FORMAT_MOD_NONE;
1253*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_FENCE_STRESS) {
1254*d83cc019SAndroid Build Coastguard Worker #if defined(USE_INTEL)
1255*d83cc019SAndroid Build Coastguard Worker tiling = LOCAL_I915_FORMAT_MOD_X_TILED;
1256*d83cc019SAndroid Build Coastguard Worker #else
1257*d83cc019SAndroid Build Coastguard Worker igt_skip("Requires an intel device.\n");
1258*d83cc019SAndroid Build Coastguard Worker #endif
1259*d83cc019SAndroid Build Coastguard Worker }
1260*d83cc019SAndroid Build Coastguard Worker
1261*d83cc019SAndroid Build Coastguard Worker /* 256 MB is usually the maximum mappable aperture,
1262*d83cc019SAndroid Build Coastguard Worker * (make it 4x times that to ensure failure) */
1263*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_BO_TOOBIG) {
1264*d83cc019SAndroid Build Coastguard Worker bo_size = 4*gem_mappable_aperture_size();
1265*d83cc019SAndroid Build Coastguard Worker #if defined(USE_INTEL)
1266*d83cc019SAndroid Build Coastguard Worker igt_require(bo_size < gem_global_aperture_size(drm_fd));
1267*d83cc019SAndroid Build Coastguard Worker #endif
1268*d83cc019SAndroid Build Coastguard Worker }
1269*d83cc019SAndroid Build Coastguard Worker
1270*d83cc019SAndroid Build Coastguard Worker o->fb_ids[0] = igt_create_fb(drm_fd, o->fb_width, o->fb_height,
1271*d83cc019SAndroid Build Coastguard Worker igt_bpp_depth_to_drm_format(o->bpp, o->depth),
1272*d83cc019SAndroid Build Coastguard Worker tiling, &o->fb_info[0]);
1273*d83cc019SAndroid Build Coastguard Worker o->fb_ids[1] = igt_create_fb_with_bo_size(drm_fd, o->fb_width, o->fb_height,
1274*d83cc019SAndroid Build Coastguard Worker igt_bpp_depth_to_drm_format(o->bpp, o->depth),
1275*d83cc019SAndroid Build Coastguard Worker tiling, IGT_COLOR_YCBCR_BT709,
1276*d83cc019SAndroid Build Coastguard Worker IGT_COLOR_YCBCR_LIMITED_RANGE,
1277*d83cc019SAndroid Build Coastguard Worker &o->fb_info[1], bo_size, 0);
1278*d83cc019SAndroid Build Coastguard Worker
1279*d83cc019SAndroid Build Coastguard Worker igt_assert(o->fb_ids[0]);
1280*d83cc019SAndroid Build Coastguard Worker igt_assert(o->fb_ids[1]);
1281*d83cc019SAndroid Build Coastguard Worker
1282*d83cc019SAndroid Build Coastguard Worker paint_flip_mode(&o->fb_info[0], false);
1283*d83cc019SAndroid Build Coastguard Worker if (!(o->flags & TEST_BO_TOOBIG))
1284*d83cc019SAndroid Build Coastguard Worker paint_flip_mode(&o->fb_info[1], true);
1285*d83cc019SAndroid Build Coastguard Worker if (o->fb_ids[2])
1286*d83cc019SAndroid Build Coastguard Worker paint_flip_mode(&o->fb_info[2], true);
1287*d83cc019SAndroid Build Coastguard Worker
1288*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < o->count; i++)
1289*d83cc019SAndroid Build Coastguard Worker kmstest_dump_mode(&o->kmode[i]);
1290*d83cc019SAndroid Build Coastguard Worker
1291*d83cc019SAndroid Build Coastguard Worker kmstest_unset_all_crtcs(drm_fd, resources);
1292*d83cc019SAndroid Build Coastguard Worker
1293*d83cc019SAndroid Build Coastguard Worker if (set_mode(o, o->fb_ids[0], 0, 0)) {
1294*d83cc019SAndroid Build Coastguard Worker /* We may fail to apply the mode if there are hidden
1295*d83cc019SAndroid Build Coastguard Worker * constraints, such as bandwidth on the third pipe.
1296*d83cc019SAndroid Build Coastguard Worker */
1297*d83cc019SAndroid Build Coastguard Worker igt_assert_f(crtc_count > 1 || crtc_idxs[0] < 2,
1298*d83cc019SAndroid Build Coastguard Worker "set_mode may only fail on the 3rd pipe or in multiple crtc tests\n");
1299*d83cc019SAndroid Build Coastguard Worker igt_info("\n%s: SKIPPED\n\n", test_name);
1300*d83cc019SAndroid Build Coastguard Worker goto out;
1301*d83cc019SAndroid Build Coastguard Worker }
1302*d83cc019SAndroid Build Coastguard Worker igt_assert(fb_is_bound(o, o->fb_ids[0]));
1303*d83cc019SAndroid Build Coastguard Worker
1304*d83cc019SAndroid Build Coastguard Worker vblank = kms_has_vblank(drm_fd);
1305*d83cc019SAndroid Build Coastguard Worker if (!vblank) {
1306*d83cc019SAndroid Build Coastguard Worker if (vblank_dependence(o->flags))
1307*d83cc019SAndroid Build Coastguard Worker igt_require_f(vblank, "There is no VBlank\n");
1308*d83cc019SAndroid Build Coastguard Worker else
1309*d83cc019SAndroid Build Coastguard Worker o->flags |= TEST_NO_VBLANK;
1310*d83cc019SAndroid Build Coastguard Worker }
1311*d83cc019SAndroid Build Coastguard Worker
1312*d83cc019SAndroid Build Coastguard Worker /* quiescent the hw a bit so ensure we don't miss a single frame */
1313*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_CHECK_TS)
1314*d83cc019SAndroid Build Coastguard Worker calibrate_ts(o, crtc_idxs[0]);
1315*d83cc019SAndroid Build Coastguard Worker
1316*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_BO_TOOBIG) {
1317*d83cc019SAndroid Build Coastguard Worker int err = do_page_flip(o, o->fb_ids[1], true);
1318*d83cc019SAndroid Build Coastguard Worker igt_assert(err == 0 || err == -E2BIG);
1319*d83cc019SAndroid Build Coastguard Worker if (err)
1320*d83cc019SAndroid Build Coastguard Worker goto out;
1321*d83cc019SAndroid Build Coastguard Worker } else {
1322*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(do_page_flip(o, o->fb_ids[1], true), 0);
1323*d83cc019SAndroid Build Coastguard Worker }
1324*d83cc019SAndroid Build Coastguard Worker wait_for_events(o);
1325*d83cc019SAndroid Build Coastguard Worker
1326*d83cc019SAndroid Build Coastguard Worker o->current_fb_id = 1;
1327*d83cc019SAndroid Build Coastguard Worker
1328*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_FLIP)
1329*d83cc019SAndroid Build Coastguard Worker o->flip_state.seq_step = 1;
1330*d83cc019SAndroid Build Coastguard Worker else
1331*d83cc019SAndroid Build Coastguard Worker o->flip_state.seq_step = 0;
1332*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_VBLANK)
1333*d83cc019SAndroid Build Coastguard Worker o->vblank_state.seq_step = 10;
1334*d83cc019SAndroid Build Coastguard Worker else
1335*d83cc019SAndroid Build Coastguard Worker o->vblank_state.seq_step = 0;
1336*d83cc019SAndroid Build Coastguard Worker
1337*d83cc019SAndroid Build Coastguard Worker /* We run the vblank and flip actions in parallel by default. */
1338*d83cc019SAndroid Build Coastguard Worker o->seq_step = max(o->vblank_state.seq_step, o->flip_state.seq_step);
1339*d83cc019SAndroid Build Coastguard Worker
1340*d83cc019SAndroid Build Coastguard Worker elapsed = event_loop(o, duration_ms);
1341*d83cc019SAndroid Build Coastguard Worker
1342*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_FLIP && !(o->flags & TEST_NOEVENT))
1343*d83cc019SAndroid Build Coastguard Worker check_final_state(o, &o->flip_state, elapsed);
1344*d83cc019SAndroid Build Coastguard Worker if (o->flags & TEST_VBLANK)
1345*d83cc019SAndroid Build Coastguard Worker check_final_state(o, &o->vblank_state, elapsed);
1346*d83cc019SAndroid Build Coastguard Worker
1347*d83cc019SAndroid Build Coastguard Worker igt_info("\n%s: PASSED\n\n", test_name);
1348*d83cc019SAndroid Build Coastguard Worker
1349*d83cc019SAndroid Build Coastguard Worker out:
1350*d83cc019SAndroid Build Coastguard Worker igt_remove_fb(drm_fd, &o->fb_info[2]);
1351*d83cc019SAndroid Build Coastguard Worker igt_remove_fb(drm_fd, &o->fb_info[1]);
1352*d83cc019SAndroid Build Coastguard Worker igt_remove_fb(drm_fd, &o->fb_info[0]);
1353*d83cc019SAndroid Build Coastguard Worker
1354*d83cc019SAndroid Build Coastguard Worker last_connector = NULL;
1355*d83cc019SAndroid Build Coastguard Worker
1356*d83cc019SAndroid Build Coastguard Worker free_test_output(o);
1357*d83cc019SAndroid Build Coastguard Worker }
1358*d83cc019SAndroid Build Coastguard Worker
run_test(int duration,int flags)1359*d83cc019SAndroid Build Coastguard Worker static int run_test(int duration, int flags)
1360*d83cc019SAndroid Build Coastguard Worker {
1361*d83cc019SAndroid Build Coastguard Worker struct test_output o;
1362*d83cc019SAndroid Build Coastguard Worker int i, n, modes = 0;
1363*d83cc019SAndroid Build Coastguard Worker
1364*d83cc019SAndroid Build Coastguard Worker igt_require((flags & TEST_HANG) == 0 || !is_wedged(drm_fd));
1365*d83cc019SAndroid Build Coastguard Worker
1366*d83cc019SAndroid Build Coastguard Worker resources = drmModeGetResources(drm_fd);
1367*d83cc019SAndroid Build Coastguard Worker igt_require(resources);
1368*d83cc019SAndroid Build Coastguard Worker
1369*d83cc019SAndroid Build Coastguard Worker /* Count output configurations to scale test runtime. */
1370*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < resources->count_connectors; i++) {
1371*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < resources->count_crtcs; n++) {
1372*d83cc019SAndroid Build Coastguard Worker memset(&o, 0, sizeof(o));
1373*d83cc019SAndroid Build Coastguard Worker o.count = 1;
1374*d83cc019SAndroid Build Coastguard Worker o._connector[0] = resources->connectors[i];
1375*d83cc019SAndroid Build Coastguard Worker o.flags = flags;
1376*d83cc019SAndroid Build Coastguard Worker o.flip_state.name = "flip";
1377*d83cc019SAndroid Build Coastguard Worker o.vblank_state.name = "vblank";
1378*d83cc019SAndroid Build Coastguard Worker o.bpp = 32;
1379*d83cc019SAndroid Build Coastguard Worker o.depth = 24;
1380*d83cc019SAndroid Build Coastguard Worker
1381*d83cc019SAndroid Build Coastguard Worker connector_find_preferred_mode(o._connector[0], n, &o);
1382*d83cc019SAndroid Build Coastguard Worker if (o.mode_valid)
1383*d83cc019SAndroid Build Coastguard Worker modes++;
1384*d83cc019SAndroid Build Coastguard Worker
1385*d83cc019SAndroid Build Coastguard Worker free_test_output(&o);
1386*d83cc019SAndroid Build Coastguard Worker }
1387*d83cc019SAndroid Build Coastguard Worker }
1388*d83cc019SAndroid Build Coastguard Worker
1389*d83cc019SAndroid Build Coastguard Worker igt_require(modes);
1390*d83cc019SAndroid Build Coastguard Worker duration = duration * 1000 / modes;
1391*d83cc019SAndroid Build Coastguard Worker duration = max(500, duration);
1392*d83cc019SAndroid Build Coastguard Worker
1393*d83cc019SAndroid Build Coastguard Worker /* Find any connected displays */
1394*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < resources->count_connectors; i++) {
1395*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < resources->count_crtcs; n++) {
1396*d83cc019SAndroid Build Coastguard Worker int crtc_idx;
1397*d83cc019SAndroid Build Coastguard Worker
1398*d83cc019SAndroid Build Coastguard Worker memset(&o, 0, sizeof(o));
1399*d83cc019SAndroid Build Coastguard Worker o.count = 1;
1400*d83cc019SAndroid Build Coastguard Worker o._connector[0] = resources->connectors[i];
1401*d83cc019SAndroid Build Coastguard Worker o.flags = flags;
1402*d83cc019SAndroid Build Coastguard Worker o.flip_state.name = "flip";
1403*d83cc019SAndroid Build Coastguard Worker o.vblank_state.name = "vblank";
1404*d83cc019SAndroid Build Coastguard Worker o.bpp = 32;
1405*d83cc019SAndroid Build Coastguard Worker o.depth = 24;
1406*d83cc019SAndroid Build Coastguard Worker
1407*d83cc019SAndroid Build Coastguard Worker crtc_idx = n;
1408*d83cc019SAndroid Build Coastguard Worker run_test_on_crtc_set(&o, &crtc_idx, RUN_TEST, duration);
1409*d83cc019SAndroid Build Coastguard Worker }
1410*d83cc019SAndroid Build Coastguard Worker }
1411*d83cc019SAndroid Build Coastguard Worker
1412*d83cc019SAndroid Build Coastguard Worker drmModeFreeResources(resources);
1413*d83cc019SAndroid Build Coastguard Worker return 1;
1414*d83cc019SAndroid Build Coastguard Worker }
1415*d83cc019SAndroid Build Coastguard Worker
run_pair(int duration,int flags)1416*d83cc019SAndroid Build Coastguard Worker static int run_pair(int duration, int flags)
1417*d83cc019SAndroid Build Coastguard Worker {
1418*d83cc019SAndroid Build Coastguard Worker struct test_output o;
1419*d83cc019SAndroid Build Coastguard Worker int i, j, m, n, modes = 0;
1420*d83cc019SAndroid Build Coastguard Worker
1421*d83cc019SAndroid Build Coastguard Worker igt_require((flags & TEST_HANG) == 0 || !is_wedged(drm_fd));
1422*d83cc019SAndroid Build Coastguard Worker
1423*d83cc019SAndroid Build Coastguard Worker resources = drmModeGetResources(drm_fd);
1424*d83cc019SAndroid Build Coastguard Worker igt_require(resources);
1425*d83cc019SAndroid Build Coastguard Worker
1426*d83cc019SAndroid Build Coastguard Worker /* Find a pair of connected displays */
1427*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < resources->count_connectors; i++) {
1428*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < resources->count_crtcs; n++) {
1429*d83cc019SAndroid Build Coastguard Worker for (j = i + 1; j < resources->count_connectors; j++) {
1430*d83cc019SAndroid Build Coastguard Worker for (m = n + 1; m < resources->count_crtcs; m++) {
1431*d83cc019SAndroid Build Coastguard Worker memset(&o, 0, sizeof(o));
1432*d83cc019SAndroid Build Coastguard Worker o.count = 2;
1433*d83cc019SAndroid Build Coastguard Worker o._connector[0] = resources->connectors[i];
1434*d83cc019SAndroid Build Coastguard Worker o._connector[1] = resources->connectors[j];
1435*d83cc019SAndroid Build Coastguard Worker o.flags = flags;
1436*d83cc019SAndroid Build Coastguard Worker o.flip_state.name = "flip";
1437*d83cc019SAndroid Build Coastguard Worker o.vblank_state.name = "vblank";
1438*d83cc019SAndroid Build Coastguard Worker o.bpp = 32;
1439*d83cc019SAndroid Build Coastguard Worker o.depth = 24;
1440*d83cc019SAndroid Build Coastguard Worker
1441*d83cc019SAndroid Build Coastguard Worker connector_find_compatible_mode(n, m, &o);
1442*d83cc019SAndroid Build Coastguard Worker if (o.mode_valid)
1443*d83cc019SAndroid Build Coastguard Worker modes++;
1444*d83cc019SAndroid Build Coastguard Worker
1445*d83cc019SAndroid Build Coastguard Worker free_test_output(&o);
1446*d83cc019SAndroid Build Coastguard Worker }
1447*d83cc019SAndroid Build Coastguard Worker }
1448*d83cc019SAndroid Build Coastguard Worker }
1449*d83cc019SAndroid Build Coastguard Worker }
1450*d83cc019SAndroid Build Coastguard Worker
1451*d83cc019SAndroid Build Coastguard Worker /* If we have fewer than 2 connected outputs then we won't have any
1452*d83cc019SAndroid Build Coastguard Worker * configuration at all. So skip in that case. */
1453*d83cc019SAndroid Build Coastguard Worker igt_require_f(modes, "At least two displays required\n");
1454*d83cc019SAndroid Build Coastguard Worker duration = duration * 1000 / modes;
1455*d83cc019SAndroid Build Coastguard Worker duration = max(duration, 500);
1456*d83cc019SAndroid Build Coastguard Worker
1457*d83cc019SAndroid Build Coastguard Worker /* Find a pair of connected displays */
1458*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < resources->count_connectors; i++) {
1459*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < resources->count_crtcs; n++) {
1460*d83cc019SAndroid Build Coastguard Worker for (j = i + 1; j < resources->count_connectors; j++) {
1461*d83cc019SAndroid Build Coastguard Worker for (m = n + 1; m < resources->count_crtcs; m++) {
1462*d83cc019SAndroid Build Coastguard Worker int crtc_idxs[2];
1463*d83cc019SAndroid Build Coastguard Worker
1464*d83cc019SAndroid Build Coastguard Worker memset(&o, 0, sizeof(o));
1465*d83cc019SAndroid Build Coastguard Worker o.count = 2;
1466*d83cc019SAndroid Build Coastguard Worker o._connector[0] = resources->connectors[i];
1467*d83cc019SAndroid Build Coastguard Worker o._connector[1] = resources->connectors[j];
1468*d83cc019SAndroid Build Coastguard Worker o.flags = flags;
1469*d83cc019SAndroid Build Coastguard Worker o.flip_state.name = "flip";
1470*d83cc019SAndroid Build Coastguard Worker o.vblank_state.name = "vblank";
1471*d83cc019SAndroid Build Coastguard Worker o.bpp = 32;
1472*d83cc019SAndroid Build Coastguard Worker o.depth = 24;
1473*d83cc019SAndroid Build Coastguard Worker
1474*d83cc019SAndroid Build Coastguard Worker crtc_idxs[0] = n;
1475*d83cc019SAndroid Build Coastguard Worker crtc_idxs[1] = m;
1476*d83cc019SAndroid Build Coastguard Worker
1477*d83cc019SAndroid Build Coastguard Worker run_test_on_crtc_set(&o, crtc_idxs,
1478*d83cc019SAndroid Build Coastguard Worker RUN_PAIR,
1479*d83cc019SAndroid Build Coastguard Worker duration);
1480*d83cc019SAndroid Build Coastguard Worker }
1481*d83cc019SAndroid Build Coastguard Worker }
1482*d83cc019SAndroid Build Coastguard Worker }
1483*d83cc019SAndroid Build Coastguard Worker }
1484*d83cc019SAndroid Build Coastguard Worker
1485*d83cc019SAndroid Build Coastguard Worker drmModeFreeResources(resources);
1486*d83cc019SAndroid Build Coastguard Worker return 1;
1487*d83cc019SAndroid Build Coastguard Worker }
1488*d83cc019SAndroid Build Coastguard Worker
get_timestamp_format(void)1489*d83cc019SAndroid Build Coastguard Worker static void get_timestamp_format(void)
1490*d83cc019SAndroid Build Coastguard Worker {
1491*d83cc019SAndroid Build Coastguard Worker uint64_t cap_mono;
1492*d83cc019SAndroid Build Coastguard Worker int ret;
1493*d83cc019SAndroid Build Coastguard Worker
1494*d83cc019SAndroid Build Coastguard Worker ret = drmGetCap(drm_fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap_mono);
1495*d83cc019SAndroid Build Coastguard Worker igt_assert(ret == 0 || errno == EINVAL);
1496*d83cc019SAndroid Build Coastguard Worker monotonic_timestamp = ret == 0 && cap_mono == 1;
1497*d83cc019SAndroid Build Coastguard Worker igt_info("Using %s timestamps\n",
1498*d83cc019SAndroid Build Coastguard Worker monotonic_timestamp ? "monotonic" : "real");
1499*d83cc019SAndroid Build Coastguard Worker }
1500*d83cc019SAndroid Build Coastguard Worker
kms_flip_exit_handler(int sig)1501*d83cc019SAndroid Build Coastguard Worker static void kms_flip_exit_handler(int sig)
1502*d83cc019SAndroid Build Coastguard Worker {
1503*d83cc019SAndroid Build Coastguard Worker igt_fixture {
1504*d83cc019SAndroid Build Coastguard Worker if (last_connector)
1505*d83cc019SAndroid Build Coastguard Worker kmstest_set_connector_dpms(drm_fd, last_connector, DRM_MODE_DPMS_ON);
1506*d83cc019SAndroid Build Coastguard Worker }
1507*d83cc019SAndroid Build Coastguard Worker }
1508*d83cc019SAndroid Build Coastguard Worker
test_nonblocking_read(int in)1509*d83cc019SAndroid Build Coastguard Worker static void test_nonblocking_read(int in)
1510*d83cc019SAndroid Build Coastguard Worker {
1511*d83cc019SAndroid Build Coastguard Worker char buffer[1024];
1512*d83cc019SAndroid Build Coastguard Worker int fd = dup(in);
1513*d83cc019SAndroid Build Coastguard Worker int ret;
1514*d83cc019SAndroid Build Coastguard Worker
1515*d83cc019SAndroid Build Coastguard Worker ret = -1;
1516*d83cc019SAndroid Build Coastguard Worker if (fd != -1)
1517*d83cc019SAndroid Build Coastguard Worker ret = fcntl(fd, F_GETFL);
1518*d83cc019SAndroid Build Coastguard Worker if (ret != -1) {
1519*d83cc019SAndroid Build Coastguard Worker ret |= O_NONBLOCK;
1520*d83cc019SAndroid Build Coastguard Worker ret = fcntl(fd, F_SETFL, ret);
1521*d83cc019SAndroid Build Coastguard Worker }
1522*d83cc019SAndroid Build Coastguard Worker igt_require(ret != -1);
1523*d83cc019SAndroid Build Coastguard Worker
1524*d83cc019SAndroid Build Coastguard Worker igt_set_timeout(5, "Nonblocking DRM fd reading");
1525*d83cc019SAndroid Build Coastguard Worker ret = read(fd, buffer, sizeof(buffer));
1526*d83cc019SAndroid Build Coastguard Worker igt_reset_timeout();
1527*d83cc019SAndroid Build Coastguard Worker
1528*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(ret, -1);
1529*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(errno, EAGAIN);
1530*d83cc019SAndroid Build Coastguard Worker
1531*d83cc019SAndroid Build Coastguard Worker close(fd);
1532*d83cc019SAndroid Build Coastguard Worker }
1533*d83cc019SAndroid Build Coastguard Worker
1534*d83cc019SAndroid Build Coastguard Worker igt_main
1535*d83cc019SAndroid Build Coastguard Worker {
1536*d83cc019SAndroid Build Coastguard Worker struct {
1537*d83cc019SAndroid Build Coastguard Worker int duration;
1538*d83cc019SAndroid Build Coastguard Worker int flags;
1539*d83cc019SAndroid Build Coastguard Worker const char *name;
1540*d83cc019SAndroid Build Coastguard Worker } tests[] = {
1541*d83cc019SAndroid Build Coastguard Worker { 30, TEST_VBLANK | TEST_CHECK_TS, "wf_vblank-ts-check" },
1542*d83cc019SAndroid Build Coastguard Worker { 30, TEST_VBLANK | TEST_VBLANK_BLOCK | TEST_CHECK_TS,
1543*d83cc019SAndroid Build Coastguard Worker "blocking-wf_vblank" },
1544*d83cc019SAndroid Build Coastguard Worker { 30, TEST_VBLANK | TEST_VBLANK_ABSOLUTE,
1545*d83cc019SAndroid Build Coastguard Worker "absolute-wf_vblank" },
1546*d83cc019SAndroid Build Coastguard Worker { 30, TEST_VBLANK | TEST_VBLANK_BLOCK | TEST_VBLANK_ABSOLUTE,
1547*d83cc019SAndroid Build Coastguard Worker "blocking-absolute-wf_vblank" },
1548*d83cc019SAndroid Build Coastguard Worker { 10, TEST_FLIP | TEST_BASIC, "plain-flip" },
1549*d83cc019SAndroid Build Coastguard Worker { 1, TEST_FLIP | TEST_EBUSY, "busy-flip" },
1550*d83cc019SAndroid Build Coastguard Worker { 30, TEST_FLIP | TEST_FENCE_STRESS , "flip-vs-fences" },
1551*d83cc019SAndroid Build Coastguard Worker { 30, TEST_FLIP | TEST_CHECK_TS, "plain-flip-ts-check" },
1552*d83cc019SAndroid Build Coastguard Worker { 30, TEST_FLIP | TEST_CHECK_TS | TEST_FB_RECREATE,
1553*d83cc019SAndroid Build Coastguard Worker "plain-flip-fb-recreate" },
1554*d83cc019SAndroid Build Coastguard Worker { 30, TEST_FLIP | TEST_RMFB | TEST_MODESET , "flip-vs-rmfb" },
1555*d83cc019SAndroid Build Coastguard Worker { 20, TEST_FLIP | TEST_DPMS | TEST_EINVAL | TEST_BASIC, "flip-vs-dpms" },
1556*d83cc019SAndroid Build Coastguard Worker { 30, TEST_FLIP | TEST_PAN, "flip-vs-panning" },
1557*d83cc019SAndroid Build Coastguard Worker { 20, TEST_FLIP | TEST_MODESET | TEST_EINVAL | TEST_BASIC, "flip-vs-modeset" },
1558*d83cc019SAndroid Build Coastguard Worker { 30, TEST_FLIP | TEST_VBLANK_EXPIRED_SEQ,
1559*d83cc019SAndroid Build Coastguard Worker "flip-vs-expired-vblank" },
1560*d83cc019SAndroid Build Coastguard Worker
1561*d83cc019SAndroid Build Coastguard Worker { 30, TEST_FLIP | TEST_VBLANK | TEST_VBLANK_ABSOLUTE |
1562*d83cc019SAndroid Build Coastguard Worker TEST_CHECK_TS, "flip-vs-absolute-wf_vblank" },
1563*d83cc019SAndroid Build Coastguard Worker { 10, TEST_FLIP | TEST_VBLANK | TEST_CHECK_TS | TEST_BASIC,
1564*d83cc019SAndroid Build Coastguard Worker "flip-vs-wf_vblank" },
1565*d83cc019SAndroid Build Coastguard Worker { 30, TEST_FLIP | TEST_VBLANK | TEST_VBLANK_BLOCK |
1566*d83cc019SAndroid Build Coastguard Worker TEST_CHECK_TS, "flip-vs-blocking-wf-vblank" },
1567*d83cc019SAndroid Build Coastguard Worker { 30, TEST_FLIP | TEST_MODESET | TEST_HANG | TEST_NOEVENT, "flip-vs-modeset-vs-hang" },
1568*d83cc019SAndroid Build Coastguard Worker { 30, TEST_FLIP | TEST_PAN | TEST_HANG, "flip-vs-panning-vs-hang" },
1569*d83cc019SAndroid Build Coastguard Worker
1570*d83cc019SAndroid Build Coastguard Worker { 1, TEST_DPMS_OFF | TEST_MODESET | TEST_FLIP,
1571*d83cc019SAndroid Build Coastguard Worker "flip-vs-dpms-off-vs-modeset" },
1572*d83cc019SAndroid Build Coastguard Worker { 1, TEST_DPMS_OFF | TEST_MODESET | TEST_FLIP | TEST_SINGLE_BUFFER,
1573*d83cc019SAndroid Build Coastguard Worker "single-buffer-flip-vs-dpms-off-vs-modeset" },
1574*d83cc019SAndroid Build Coastguard Worker { 30, TEST_FLIP | TEST_NO_2X_OUTPUT | TEST_DPMS_OFF_OTHERS , "dpms-off-confusion" },
1575*d83cc019SAndroid Build Coastguard Worker { 0, TEST_ENOENT | TEST_NOEVENT, "nonexisting-fb" },
1576*d83cc019SAndroid Build Coastguard Worker { 10, TEST_DPMS_OFF | TEST_DPMS | TEST_VBLANK_RACE, "dpms-vs-vblank-race" },
1577*d83cc019SAndroid Build Coastguard Worker { 10, TEST_MODESET | TEST_VBLANK_RACE, "modeset-vs-vblank-race" },
1578*d83cc019SAndroid Build Coastguard Worker { 0, TEST_BO_TOOBIG | TEST_NO_2X_OUTPUT, "bo-too-big" },
1579*d83cc019SAndroid Build Coastguard Worker { 10, TEST_FLIP | TEST_SUSPEND, "flip-vs-suspend" },
1580*d83cc019SAndroid Build Coastguard Worker };
1581*d83cc019SAndroid Build Coastguard Worker int i;
1582*d83cc019SAndroid Build Coastguard Worker
1583*d83cc019SAndroid Build Coastguard Worker igt_fixture {
1584*d83cc019SAndroid Build Coastguard Worker drm_fd = drm_open_driver_master(DRIVER_ANY);
1585*d83cc019SAndroid Build Coastguard Worker
1586*d83cc019SAndroid Build Coastguard Worker igt_enable_connectors(drm_fd);
1587*d83cc019SAndroid Build Coastguard Worker
1588*d83cc019SAndroid Build Coastguard Worker kmstest_set_vt_graphics_mode();
1589*d83cc019SAndroid Build Coastguard Worker igt_install_exit_handler(kms_flip_exit_handler);
1590*d83cc019SAndroid Build Coastguard Worker get_timestamp_format();
1591*d83cc019SAndroid Build Coastguard Worker
1592*d83cc019SAndroid Build Coastguard Worker #if defined(USE_INTEL)
1593*d83cc019SAndroid Build Coastguard Worker if (is_i915_device(drm_fd)) {
1594*d83cc019SAndroid Build Coastguard Worker bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 4096);
1595*d83cc019SAndroid Build Coastguard Worker if (bufmgr) {
1596*d83cc019SAndroid Build Coastguard Worker devid = intel_get_drm_devid(drm_fd);
1597*d83cc019SAndroid Build Coastguard Worker batch = intel_batchbuffer_alloc(bufmgr, devid);
1598*d83cc019SAndroid Build Coastguard Worker }
1599*d83cc019SAndroid Build Coastguard Worker }
1600*d83cc019SAndroid Build Coastguard Worker #endif
1601*d83cc019SAndroid Build Coastguard Worker }
1602*d83cc019SAndroid Build Coastguard Worker
1603*d83cc019SAndroid Build Coastguard Worker igt_subtest("nonblocking-read")
1604*d83cc019SAndroid Build Coastguard Worker test_nonblocking_read(drm_fd);
1605*d83cc019SAndroid Build Coastguard Worker
1606*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < sizeof(tests) / sizeof (tests[0]); i++) {
1607*d83cc019SAndroid Build Coastguard Worker igt_subtest_f("%s%s",
1608*d83cc019SAndroid Build Coastguard Worker tests[i].flags & TEST_BASIC ? "basic-" : "",
1609*d83cc019SAndroid Build Coastguard Worker tests[i].name)
1610*d83cc019SAndroid Build Coastguard Worker run_test(tests[i].duration, tests[i].flags);
1611*d83cc019SAndroid Build Coastguard Worker
1612*d83cc019SAndroid Build Coastguard Worker if (tests[i].flags & TEST_NO_2X_OUTPUT)
1613*d83cc019SAndroid Build Coastguard Worker continue;
1614*d83cc019SAndroid Build Coastguard Worker
1615*d83cc019SAndroid Build Coastguard Worker igt_subtest_f( "2x-%s", tests[i].name)
1616*d83cc019SAndroid Build Coastguard Worker run_pair(tests[i].duration, tests[i].flags);
1617*d83cc019SAndroid Build Coastguard Worker }
1618*d83cc019SAndroid Build Coastguard Worker
1619*d83cc019SAndroid Build Coastguard Worker igt_fork_signal_helper();
1620*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < sizeof(tests) / sizeof (tests[0]); i++) {
1621*d83cc019SAndroid Build Coastguard Worker /* relative blocking vblank waits that get constantly interrupt
1622*d83cc019SAndroid Build Coastguard Worker * take forver. So don't do them. */
1623*d83cc019SAndroid Build Coastguard Worker if ((tests[i].flags & TEST_VBLANK_BLOCK) &&
1624*d83cc019SAndroid Build Coastguard Worker !(tests[i].flags & TEST_VBLANK_ABSOLUTE))
1625*d83cc019SAndroid Build Coastguard Worker continue;
1626*d83cc019SAndroid Build Coastguard Worker
1627*d83cc019SAndroid Build Coastguard Worker /*
1628*d83cc019SAndroid Build Coastguard Worker * -EBUSY needs to complete in a single vblank, skip them for
1629*d83cc019SAndroid Build Coastguard Worker * interruptible tests
1630*d83cc019SAndroid Build Coastguard Worker */
1631*d83cc019SAndroid Build Coastguard Worker if (tests[i].flags & TEST_EBUSY)
1632*d83cc019SAndroid Build Coastguard Worker continue;
1633*d83cc019SAndroid Build Coastguard Worker
1634*d83cc019SAndroid Build Coastguard Worker igt_subtest_f( "%s-interruptible", tests[i].name)
1635*d83cc019SAndroid Build Coastguard Worker run_test(tests[i].duration, tests[i].flags);
1636*d83cc019SAndroid Build Coastguard Worker
1637*d83cc019SAndroid Build Coastguard Worker if (tests[i].flags & TEST_NO_2X_OUTPUT)
1638*d83cc019SAndroid Build Coastguard Worker continue;
1639*d83cc019SAndroid Build Coastguard Worker
1640*d83cc019SAndroid Build Coastguard Worker igt_subtest_f( "2x-%s-interruptible", tests[i].name)
1641*d83cc019SAndroid Build Coastguard Worker run_pair(tests[i].duration, tests[i].flags);
1642*d83cc019SAndroid Build Coastguard Worker }
1643*d83cc019SAndroid Build Coastguard Worker igt_stop_signal_helper();
1644*d83cc019SAndroid Build Coastguard Worker }
1645