tests/pm_pc8: Fix invalid pointer-to-integer casting
[platform/upstream/intel-gpu-tools.git] / tests / pm_pc8.c
1 /*
2  * Copyright © 2013 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  * Authors:
24  *    Paulo Zanoni <paulo.r.zanoni@intel.com>
25  *
26  */
27
28 #include <stdio.h>
29 #include <stdint.h>
30 #include <stdbool.h>
31 #include <string.h>
32
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <dirent.h>
36 #include <sys/ioctl.h>
37 #include <sys/mman.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <linux/i2c.h>
41 #include <linux/i2c-dev.h>
42
43 #include "drm.h"
44 #include "drmtest.h"
45 #include "intel_batchbuffer.h"
46 #include "intel_gpu_tools.h"
47 #include "i915_drm.h"
48 #include "igt_kms.h"
49
50 #define MSR_PC8_RES     0x630
51 #define MSR_PC9_RES     0x631
52 #define MSR_PC10_RES    0x632
53
54 #define MAX_CONNECTORS  32
55 #define MAX_ENCODERS    32
56 #define MAX_CRTCS       16
57
58 enum screen_type {
59         SCREEN_TYPE_LPSP,
60         SCREEN_TYPE_NON_LPSP,
61         SCREEN_TYPE_ANY,
62 };
63
64 enum residency_wait {
65         WAIT,
66         DONT_WAIT,
67 };
68
69 int drm_fd, msr_fd;
70 struct mode_set_data ms_data;
71
72 /* Stuff used when creating FBs and mode setting. */
73 struct mode_set_data {
74         drmModeResPtr res;
75         drmModeConnectorPtr connectors[MAX_CONNECTORS];
76         drmModePropertyBlobPtr edids[MAX_CONNECTORS];
77
78         uint32_t devid;
79 };
80
81 /* Stuff we query at different times so we can compare. */
82 struct compare_data {
83         drmModeResPtr res;
84         drmModeEncoderPtr encoders[MAX_ENCODERS];
85         drmModeConnectorPtr connectors[MAX_CONNECTORS];
86         drmModeCrtcPtr crtcs[MAX_CRTCS];
87         drmModePropertyBlobPtr edids[MAX_CONNECTORS];
88 };
89
90 struct compare_registers {
91         /* We know these are lost */
92         uint32_t arb_mode;
93         uint32_t tilectl;
94
95         /* Stuff touched at init_clock_gating, so we can make sure we
96          * don't need to call it when reiniting. */
97         uint32_t gen6_ucgctl2;
98         uint32_t gen7_l3cntlreg1;
99         uint32_t transa_chicken1;
100
101         uint32_t deier;
102         uint32_t gtier;
103
104         uint32_t ddi_buf_trans_a_1;
105         uint32_t ddi_buf_trans_b_5;
106         uint32_t ddi_buf_trans_c_10;
107         uint32_t ddi_buf_trans_d_15;
108         uint32_t ddi_buf_trans_e_20;
109 };
110
111 /* If the read fails, then the machine doesn't support PC8+ residencies. */
112 static bool supports_pc8_plus_residencies(void)
113 {
114         int rc;
115         uint64_t val;
116
117         rc = pread(msr_fd, &val, sizeof(uint64_t), MSR_PC8_RES);
118         if (rc != sizeof(val))
119                 return false;
120         rc = pread(msr_fd, &val, sizeof(uint64_t), MSR_PC9_RES);
121         if (rc != sizeof(val))
122                 return false;
123         rc = pread(msr_fd, &val, sizeof(uint64_t), MSR_PC10_RES);
124         if (rc != sizeof(val))
125                 return false;
126
127         return true;
128 }
129
130 static uint64_t get_residency(uint32_t type)
131 {
132         int rc;
133         uint64_t ret;
134
135         rc = pread(msr_fd, &ret, sizeof(uint64_t), type);
136         igt_assert(rc == sizeof(ret));
137
138         return ret;
139 }
140
141 static bool pc8_plus_residency_changed(unsigned int timeout_sec)
142 {
143         unsigned int i;
144         uint64_t res_pc8, res_pc9, res_pc10;
145         int to_sleep = 100 * 1000;
146
147         res_pc8 = get_residency(MSR_PC8_RES);
148         res_pc9 = get_residency(MSR_PC9_RES);
149         res_pc10 = get_residency(MSR_PC10_RES);
150
151         for (i = 0; i < timeout_sec * 1000 * 1000; i += to_sleep) {
152                 if (res_pc8 != get_residency(MSR_PC8_RES) ||
153                     res_pc9 != get_residency(MSR_PC9_RES) ||
154                     res_pc10 != get_residency(MSR_PC10_RES)) {
155                         return true;
156                 }
157                 usleep(to_sleep);
158         }
159
160         return false;
161 }
162
163 /* Checks not only if PC8+ is allowed, but also if we're reaching it.
164  * We call this when we expect this function to return quickly since PC8 is
165  * actually enabled, so the 30s timeout we use shouldn't matter. */
166 static bool pc8_plus_enabled(void)
167 {
168         return pc8_plus_residency_changed(30);
169 }
170
171 /* We call this when we expect PC8+ to be actually disabled, so we should not
172  * return until the 5s timeout expires. In other words: in the "happy case",
173  * every time we call this function the program will take 5s more to finish. */
174 static bool pc8_plus_disabled(void)
175 {
176         return !pc8_plus_residency_changed(5);
177 }
178
179 static void disable_all_screens(struct mode_set_data *data)
180 {
181         int i, rc;
182
183         for (i = 0; i < data->res->count_crtcs; i++) {
184                 rc = drmModeSetCrtc(drm_fd, data->res->crtcs[i], -1, 0, 0,
185                                     NULL, 0, NULL);
186                 igt_assert(rc == 0);
187         }
188 }
189
190 static uint32_t create_fb(struct mode_set_data *data, int width, int height)
191 {
192         struct kmstest_fb fb;
193         cairo_t *cr;
194         uint32_t buffer_id;
195
196         buffer_id = kmstest_create_fb(drm_fd, width, height, 32, 24, false,
197                                       &fb);
198         cr = kmstest_get_cairo_ctx(drm_fd, &fb);
199         kmstest_paint_test_pattern(cr, width, height);
200         return buffer_id;
201 }
202
203 static bool enable_one_screen_with_type(struct mode_set_data *data,
204                                         enum screen_type type)
205 {
206         uint32_t crtc_id = 0, buffer_id = 0, connector_id = 0;
207         drmModeModeInfoPtr mode = NULL;
208         int i, rc;
209
210         for (i = 0; i < data->res->count_connectors; i++) {
211                 drmModeConnectorPtr c = data->connectors[i];
212
213                 if (type == SCREEN_TYPE_LPSP &&
214                     c->connector_type != DRM_MODE_CONNECTOR_eDP)
215                         continue;
216
217                 if (type == SCREEN_TYPE_NON_LPSP &&
218                     c->connector_type == DRM_MODE_CONNECTOR_eDP)
219                         continue;
220
221                 if (c->connection == DRM_MODE_CONNECTED && c->count_modes) {
222                         connector_id = c->connector_id;
223                         mode = &c->modes[0];
224                         break;
225                 }
226         }
227
228         if (connector_id == 0)
229                 return false;
230
231         crtc_id = data->res->crtcs[0];
232         buffer_id = create_fb(data, mode->hdisplay, mode->vdisplay);
233
234         igt_assert(crtc_id);
235         igt_assert(buffer_id);
236         igt_assert(connector_id);
237         igt_assert(mode);
238
239         rc = drmModeSetCrtc(drm_fd, crtc_id, buffer_id, 0, 0, &connector_id,
240                             1, mode);
241         igt_assert(rc == 0);
242
243         return true;
244 }
245
246 static void enable_one_screen(struct mode_set_data *data)
247 {
248         igt_assert(enable_one_screen_with_type(data, SCREEN_TYPE_ANY));
249 }
250
251 static drmModePropertyBlobPtr get_connector_edid(drmModeConnectorPtr connector,
252                                                  int index)
253 {
254         unsigned int i;
255         drmModeObjectPropertiesPtr props;
256         drmModePropertyBlobPtr ret = NULL;
257
258         props = drmModeObjectGetProperties(drm_fd, connector->connector_id,
259                                            DRM_MODE_OBJECT_CONNECTOR);
260
261         for (i = 0; i < props->count_props; i++) {
262                 drmModePropertyPtr prop = drmModeGetProperty(drm_fd,
263                                                              props->props[i]);
264
265                 if (strcmp(prop->name, "EDID") == 0) {
266                         igt_assert(prop->flags & DRM_MODE_PROP_BLOB);
267                         igt_assert(prop->count_blobs == 0);
268                         ret = drmModeGetPropertyBlob(drm_fd,
269                                                      props->prop_values[i]);
270                 }
271
272                 drmModeFreeProperty(prop);
273         }
274
275         drmModeFreeObjectProperties(props);
276         return ret;
277 }
278
279 static void init_mode_set_data(struct mode_set_data *data)
280 {
281         int i;
282
283         data->res = drmModeGetResources(drm_fd);
284         igt_assert(data->res);
285         igt_assert(data->res->count_connectors <= MAX_CONNECTORS);
286
287         for (i = 0; i < data->res->count_connectors; i++) {
288                 data->connectors[i] = drmModeGetConnector(drm_fd,
289                                                 data->res->connectors[i]);
290                 data->edids[i] = get_connector_edid(data->connectors[i], i);
291         }
292
293         data->devid = intel_get_drm_devid(drm_fd);
294
295         igt_set_vt_graphics_mode();
296 }
297
298 static void fini_mode_set_data(struct mode_set_data *data)
299 {
300         int i;
301
302         for (i = 0; i < data->res->count_connectors; i++) {
303                 drmModeFreeConnector(data->connectors[i]);
304                 drmModeFreePropertyBlob(data->edids[i]);
305         }
306         drmModeFreeResources(data->res);
307 }
308
309 static void get_drm_info(struct compare_data *data)
310 {
311         int i;
312
313         data->res = drmModeGetResources(drm_fd);
314         igt_assert(data->res);
315
316         igt_assert(data->res->count_connectors <= MAX_CONNECTORS);
317         igt_assert(data->res->count_encoders <= MAX_ENCODERS);
318         igt_assert(data->res->count_crtcs <= MAX_CRTCS);
319
320         for (i = 0; i < data->res->count_connectors; i++) {
321                 data->connectors[i] = drmModeGetConnector(drm_fd,
322                                                 data->res->connectors[i]);
323                 data->edids[i] = get_connector_edid(data->connectors[i], i);
324         }
325         for (i = 0; i < data->res->count_encoders; i++)
326                 data->encoders[i] = drmModeGetEncoder(drm_fd,
327                                                 data->res->encoders[i]);
328         for (i = 0; i < data->res->count_crtcs; i++)
329                 data->crtcs[i] = drmModeGetCrtc(drm_fd, data->res->crtcs[i]);
330 }
331
332 static void get_registers(struct compare_registers *data)
333 {
334         intel_register_access_init(intel_get_pci_device(), 0);
335         data->arb_mode = INREG(0x4030);
336         data->tilectl = INREG(0x101000);
337         data->gen6_ucgctl2 = INREG(0x9404);
338         data->gen7_l3cntlreg1 = INREG(0xB0C1);
339         data->transa_chicken1 = INREG(0xF0060);
340         data->deier = INREG(0x4400C);
341         data->gtier = INREG(0x4401C);
342         data->ddi_buf_trans_a_1 = INREG(0x64E00);
343         data->ddi_buf_trans_b_5 = INREG(0x64E70);
344         data->ddi_buf_trans_c_10 = INREG(0x64EE0);
345         data->ddi_buf_trans_d_15 = INREG(0x64F58);
346         data->ddi_buf_trans_e_20 = INREG(0x64FCC);
347         intel_register_access_fini();
348 }
349
350 static void free_drm_info(struct compare_data *data)
351 {
352         int i;
353
354         for (i = 0; i < data->res->count_connectors; i++) {
355                 drmModeFreeConnector(data->connectors[i]);
356                 drmModeFreePropertyBlob(data->edids[i]);
357         }
358         for (i = 0; i < data->res->count_encoders; i++)
359                 drmModeFreeEncoder(data->encoders[i]);
360         for (i = 0; i < data->res->count_crtcs; i++)
361                 drmModeFreeCrtc(data->crtcs[i]);
362
363         drmModeFreeResources(data->res);
364 }
365
366 #define COMPARE(d1, d2, data) igt_assert(d1->data == d2->data)
367 #define COMPARE_ARRAY(d1, d2, size, data) do { \
368         for (i = 0; i < size; i++) \
369                 igt_assert(d1->data[i] == d2->data[i]); \
370 } while (0)
371
372 static void assert_drm_resources_equal(struct compare_data *d1,
373                                        struct compare_data *d2)
374 {
375         COMPARE(d1, d2, res->count_connectors);
376         COMPARE(d1, d2, res->count_encoders);
377         COMPARE(d1, d2, res->count_crtcs);
378         COMPARE(d1, d2, res->min_width);
379         COMPARE(d1, d2, res->max_width);
380         COMPARE(d1, d2, res->min_height);
381         COMPARE(d1, d2, res->max_height);
382 }
383
384 static void assert_modes_equal(drmModeModeInfoPtr m1, drmModeModeInfoPtr m2)
385 {
386         COMPARE(m1, m2, clock);
387         COMPARE(m1, m2, hdisplay);
388         COMPARE(m1, m2, hsync_start);
389         COMPARE(m1, m2, hsync_end);
390         COMPARE(m1, m2, htotal);
391         COMPARE(m1, m2, hskew);
392         COMPARE(m1, m2, vdisplay);
393         COMPARE(m1, m2, vsync_start);
394         COMPARE(m1, m2, vsync_end);
395         COMPARE(m1, m2, vtotal);
396         COMPARE(m1, m2, vscan);
397         COMPARE(m1, m2, vrefresh);
398         COMPARE(m1, m2, flags);
399         COMPARE(m1, m2, type);
400         igt_assert(strcmp(m1->name, m2->name) == 0);
401 }
402
403 static void assert_drm_connectors_equal(drmModeConnectorPtr c1,
404                                         drmModeConnectorPtr c2)
405 {
406         int i;
407
408         COMPARE(c1, c2, connector_id);
409         COMPARE(c1, c2, connector_type);
410         COMPARE(c1, c2, connector_type_id);
411         COMPARE(c1, c2, mmWidth);
412         COMPARE(c1, c2, mmHeight);
413         COMPARE(c1, c2, count_modes);
414         COMPARE(c1, c2, count_props);
415         COMPARE(c1, c2, count_encoders);
416         COMPARE_ARRAY(c1, c2, c1->count_props, props);
417         COMPARE_ARRAY(c1, c2, c1->count_encoders, encoders);
418
419         for (i = 0; i < c1->count_modes; i++)
420                 assert_modes_equal(&c1->modes[0], &c2->modes[0]);
421 }
422
423 static void assert_drm_encoders_equal(drmModeEncoderPtr e1,
424                                       drmModeEncoderPtr e2)
425 {
426         COMPARE(e1, e2, encoder_id);
427         COMPARE(e1, e2, encoder_type);
428         COMPARE(e1, e2, possible_crtcs);
429         COMPARE(e1, e2, possible_clones);
430 }
431
432 static void assert_drm_crtcs_equal(drmModeCrtcPtr c1, drmModeCrtcPtr c2)
433 {
434         COMPARE(c1, c2, crtc_id);
435 }
436
437 static void assert_drm_edids_equal(drmModePropertyBlobPtr e1,
438                                    drmModePropertyBlobPtr e2)
439 {
440         if (!e1 && !e2)
441                 return;
442         igt_assert(e1 && e2);
443
444         COMPARE(e1, e2, id);
445         COMPARE(e1, e2, length);
446
447         igt_assert(memcmp(e1->data, e2->data, e1->length) == 0);
448 }
449
450 static void compare_registers(struct compare_registers *d1,
451                               struct compare_registers *d2)
452 {
453         COMPARE(d1, d2, gen6_ucgctl2);
454         COMPARE(d1, d2, gen7_l3cntlreg1);
455         COMPARE(d1, d2, transa_chicken1);
456         COMPARE(d1, d2, arb_mode);
457         COMPARE(d1, d2, tilectl);
458         COMPARE(d1, d2, arb_mode);
459         COMPARE(d1, d2, tilectl);
460         COMPARE(d1, d2, gtier);
461         COMPARE(d1, d2, ddi_buf_trans_a_1);
462         COMPARE(d1, d2, ddi_buf_trans_b_5);
463         COMPARE(d1, d2, ddi_buf_trans_c_10);
464         COMPARE(d1, d2, ddi_buf_trans_d_15);
465         COMPARE(d1, d2, ddi_buf_trans_e_20);
466 }
467
468 static void assert_drm_infos_equal(struct compare_data *d1,
469                                    struct compare_data *d2)
470 {
471         int i;
472
473         assert_drm_resources_equal(d1, d2);
474
475         for (i = 0; i < d1->res->count_connectors; i++) {
476                 assert_drm_connectors_equal(d1->connectors[i],
477                                             d2->connectors[i]);
478                 assert_drm_edids_equal(d1->edids[i], d2->edids[i]);
479         }
480
481         for (i = 0; i < d1->res->count_encoders; i++)
482                 assert_drm_encoders_equal(d1->encoders[i], d2->encoders[i]);
483
484         for (i = 0; i < d1->res->count_crtcs; i++)
485                 assert_drm_crtcs_equal(d1->crtcs[i], d2->crtcs[i]);
486 }
487
488 /* We could check the checksum too, but just the header is probably enough. */
489 static bool edid_is_valid(const unsigned char *edid)
490 {
491         char edid_header[] = {
492                 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0,
493         };
494
495         return (memcmp(edid, edid_header, sizeof(edid_header)) == 0);
496 }
497
498 static int count_drm_valid_edids(struct mode_set_data *data)
499 {
500         int i, ret = 0;
501
502         for (i = 0; i < data->res->count_connectors; i++)
503                 if (data->edids[i] && edid_is_valid(data->edids[i]->data))
504                         ret++;
505         return ret;
506 }
507
508 static bool i2c_edid_is_valid(int fd)
509 {
510         int rc;
511         unsigned char edid[128] = {};
512         struct i2c_msg msgs[] = {
513                 { /* Start at 0. */
514                         .addr = 0x50,
515                         .flags = 0,
516                         .len = 1,
517                         .buf = edid,
518                 }, { /* Now read the EDID. */
519                         .addr = 0x50,
520                         .flags = I2C_M_RD,
521                         .len = 128,
522                         .buf = edid,
523                 }
524         };
525         struct i2c_rdwr_ioctl_data msgset = {
526                 .msgs = msgs,
527                 .nmsgs = 2,
528         };
529
530         rc = ioctl(fd, I2C_RDWR, &msgset);
531         return (rc >= 0) ? edid_is_valid(edid) : false;
532 }
533
534 static int count_i2c_valid_edids(void)
535 {
536         int fd, ret = 0;
537         DIR *dir;
538
539         struct dirent *dirent;
540         char full_name[32];
541
542         dir = opendir("/dev/");
543         igt_assert(dir);
544
545         while ((dirent = readdir(dir))) {
546                 if (strncmp(dirent->d_name, "i2c-", 4) == 0) {
547                         snprintf(full_name, 32, "/dev/%s", dirent->d_name);
548                         fd = open(full_name, O_RDWR);
549                         igt_assert(fd != -1);
550                         if (i2c_edid_is_valid(fd))
551                                 ret++;
552                         close(fd);
553                 }
554         }
555
556         closedir(dir);
557
558         return ret;
559 }
560
561 static void test_i2c(struct mode_set_data *data)
562 {
563         int i2c_edids = count_i2c_valid_edids();
564         int drm_edids = count_drm_valid_edids(data);
565
566         igt_assert(i2c_edids == drm_edids);
567 }
568
569 static void setup_environment(void)
570 {
571         drm_fd = drm_open_any();
572         igt_assert(drm_fd >= 0);
573
574         init_mode_set_data(&ms_data);
575
576         /* Only Haswell supports the PC8 feature. */
577         igt_require_f(IS_HASWELL(ms_data.devid),
578                       "PC8+ feature only supported on Haswell.\n");
579
580         /* Make sure our Kernel supports MSR and the module is loaded. */
581         msr_fd = open("/dev/cpu/0/msr", O_RDONLY);
582         igt_assert_f(msr_fd >= 0,
583                      "Can't open /dev/cpu/0/msr.\n");
584
585         /* Non-ULT machines don't support PC8+. */
586         igt_require_f(supports_pc8_plus_residencies(),
587                       "Machine doesn't support PC8+ residencies.\n");
588 }
589
590 static void teardown_environment(void)
591 {
592         fini_mode_set_data(&ms_data);
593         drmClose(drm_fd);
594         close(msr_fd);
595 }
596
597 static void basic_subtest(void)
598 {
599         /* Make sure PC8+ residencies move! */
600         disable_all_screens(&ms_data);
601         igt_assert_f(pc8_plus_enabled(),
602                      "Machine is not reaching PC8+ states, please check its "
603                      "configuration.\n");
604
605         /* Make sure PC8+ residencies stop! */
606         enable_one_screen(&ms_data);
607         igt_assert_f(pc8_plus_disabled(),
608                      "PC8+ residency didn't stop with screen enabled.\n");
609 }
610
611 static void modeset_subtest(enum screen_type type, int rounds,
612                             enum residency_wait wait)
613 {
614         int i;
615
616         for (i = 0; i < rounds; i++) {
617                 disable_all_screens(&ms_data);
618                 if (wait == WAIT)
619                         igt_assert(pc8_plus_enabled());
620
621                 /* If we skip this line it's because the type of screen we want
622                  * is not connected. */
623                 igt_require(enable_one_screen_with_type(&ms_data, type));
624                 if (wait == WAIT)
625                         igt_assert(pc8_plus_disabled());
626         }
627 }
628
629 /* Test of the DRM resources reported by the IOCTLs are still the same. This
630  * ensures we still see the monitors with the same eyes. We get the EDIDs and
631  * compare them, which ensures we use DP AUX or GMBUS depending on what's
632  * connected. */
633 static void drm_resources_equal_subtest(void)
634 {
635         struct compare_data pre_pc8, during_pc8, post_pc8;
636
637         enable_one_screen(&ms_data);
638         igt_assert(pc8_plus_disabled());
639         get_drm_info(&pre_pc8);
640         igt_assert(pc8_plus_disabled());
641
642         disable_all_screens(&ms_data);
643         igt_assert(pc8_plus_enabled());
644         get_drm_info(&during_pc8);
645         igt_assert(pc8_plus_enabled());
646
647         enable_one_screen(&ms_data);
648         igt_assert(pc8_plus_disabled());
649         get_drm_info(&post_pc8);
650         igt_assert(pc8_plus_disabled());
651
652         assert_drm_infos_equal(&pre_pc8, &during_pc8);
653         assert_drm_infos_equal(&pre_pc8, &post_pc8);
654
655         free_drm_info(&pre_pc8);
656         free_drm_info(&during_pc8);
657         free_drm_info(&post_pc8);
658 }
659
660 static void i2c_subtest_check_environment(void)
661 {
662         int i2c_dev_files = 0;
663         DIR *dev_dir;
664         struct dirent *dirent;
665
666         /* Make sure the /dev/i2c-* files exist. */
667         dev_dir = opendir("/dev");
668         igt_assert(dev_dir);
669         while ((dirent = readdir(dev_dir))) {
670                 if (strncmp(dirent->d_name, "i2c-", 4) == 0)
671                         i2c_dev_files++;
672         }
673         closedir(dev_dir);
674         igt_require(i2c_dev_files);
675 }
676
677 /* Try to use raw I2C, which also needs interrupts. */
678 static void i2c_subtest(void)
679 {
680         i2c_subtest_check_environment();
681
682         enable_one_screen(&ms_data);
683         igt_assert(pc8_plus_disabled());
684
685         disable_all_screens(&ms_data);
686         igt_assert(pc8_plus_enabled());
687         test_i2c(&ms_data);
688         igt_assert(pc8_plus_enabled());
689
690         enable_one_screen(&ms_data);
691 }
692
693 /* Just reading/writing registers from outside the Kernel is not really a safe
694  * thing to do on Haswell, so don't do this test on the default case. */
695 static void register_compare_subtest(void)
696 {
697         struct compare_registers pre_pc8, post_pc8;
698
699         enable_one_screen(&ms_data);
700         igt_assert(pc8_plus_disabled());
701         get_registers(&pre_pc8);
702         igt_assert(pc8_plus_disabled());
703
704         disable_all_screens(&ms_data);
705         igt_assert(pc8_plus_enabled());
706         enable_one_screen(&ms_data);
707         igt_assert(pc8_plus_disabled());
708         /* Wait for the registers to be restored. */
709         sleep(1);
710         get_registers(&post_pc8);
711         igt_assert(pc8_plus_disabled());
712
713         compare_registers(&pre_pc8, &post_pc8);
714 }
715
716 static void read_full_file(const char *name)
717 {
718         int rc, fd;
719         char buf[128];
720
721         igt_assert_f(pc8_plus_enabled(), "File: %s\n", name);
722
723         fd = open(name, O_RDONLY);
724         if (fd < 0)
725                 return;
726
727         do {
728                 rc = read(fd, buf, ARRAY_SIZE(buf));
729         } while (rc == ARRAY_SIZE(buf));
730
731         rc = close(fd);
732         igt_assert(rc == 0);
733
734         igt_assert_f(pc8_plus_enabled(), "File: %s\n", name);
735 }
736
737 static void read_files_from_dir(const char *name, int level)
738 {
739         DIR *dir;
740         struct dirent *dirent;
741         char *full_name;
742         int rc;
743
744         dir = opendir(name);
745         igt_assert(dir);
746
747         full_name = malloc(PATH_MAX);
748
749         igt_assert(level < 128);
750
751         while ((dirent = readdir(dir))) {
752                 struct stat stat_buf;
753
754                 if (strcmp(dirent->d_name, ".") == 0)
755                         continue;
756                 if (strcmp(dirent->d_name, "..") == 0)
757                         continue;
758
759                 snprintf(full_name, PATH_MAX, "%s/%s", name, dirent->d_name);
760
761                 rc = lstat(full_name, &stat_buf);
762                 igt_assert(rc == 0);
763
764                 if (S_ISDIR(stat_buf.st_mode))
765                         read_files_from_dir(full_name, level + 1);
766
767                 if (S_ISREG(stat_buf.st_mode))
768                         read_full_file(full_name);
769         }
770
771         free(full_name);
772         closedir(dir);
773 }
774
775 /* This test will probably pass, with a small chance of hanging the machine in
776  * case of bugs. Many of the bugs exercised by this patch just result in dmesg
777  * errors, so a "pass" here should be confirmed by a check on dmesg. */
778 static void debugfs_read_subtest(void)
779 {
780         const char *path = "/sys/kernel/debug/dri/0";
781         DIR *dir;
782
783         dir = opendir(path);
784         igt_require_f(dir, "Can't open the debugfs directory\n");
785         closedir(dir);
786
787         disable_all_screens(&ms_data);
788         igt_assert(pc8_plus_enabled());
789
790         read_files_from_dir(path, 0);
791 }
792
793 /* Read the comment on debugfs_read_subtest(). */
794 static void sysfs_read_subtest(void)
795 {
796         const char *path = "/sys/devices/pci0000:00/0000:00:02.0";
797         DIR *dir;
798
799         dir = opendir(path);
800         igt_require_f(dir, "Can't open the sysfs directory\n");
801         closedir(dir);
802
803         disable_all_screens(&ms_data);
804         igt_assert(pc8_plus_enabled());
805
806         read_files_from_dir(path, 0);
807 }
808
809 /* Make sure we don't suspend when we have the i915_forcewake_user file open. */
810 static void debugfs_forcewake_user_subtest(void)
811 {
812         int fd, rc;
813
814         igt_require(!(IS_GEN2(ms_data.devid) || IS_GEN3(ms_data.devid) ||
815                       IS_GEN4(ms_data.devid) || IS_GEN5(ms_data.devid)));
816
817         disable_all_screens(&ms_data);
818         igt_assert(pc8_plus_enabled());
819
820         fd = open("/sys/kernel/debug/dri/0/i915_forcewake_user", O_RDONLY);
821         igt_require(fd);
822
823         igt_assert(pc8_plus_disabled());
824
825         rc = close(fd);
826         igt_assert(rc == 0);
827
828         igt_assert(pc8_plus_enabled());
829 }
830
831 static void gem_mmap_subtest(bool gtt_mmap)
832 {
833         int i;
834         uint32_t handle;
835         int buf_size = 8192;
836         uint8_t *gem_buf;
837
838         /* Create, map and set data while the device is active. */
839         enable_one_screen(&ms_data);
840         igt_assert(pc8_plus_disabled());
841
842         handle = gem_create(drm_fd, buf_size);
843
844         if (gtt_mmap)
845                 gem_buf = gem_mmap__gtt(drm_fd, handle, buf_size,
846                                         PROT_READ | PROT_WRITE);
847         else
848                 gem_buf = gem_mmap__cpu(drm_fd, handle, buf_size, 0);
849
850
851         for (i = 0; i < buf_size; i++)
852                 gem_buf[i] = i & 0xFF;
853
854         for (i = 0; i < buf_size; i++)
855                 igt_assert(gem_buf[i] == (i & 0xFF));
856
857         /* Now suspend, read and modify. */
858         disable_all_screens(&ms_data);
859         igt_assert(pc8_plus_enabled());
860
861         for (i = 0; i < buf_size; i++)
862                 igt_assert(gem_buf[i] == (i & 0xFF));
863         igt_assert(pc8_plus_enabled());
864
865         for (i = 0; i < buf_size; i++)
866                 gem_buf[i] = (~i & 0xFF);
867         igt_assert(pc8_plus_enabled());
868
869         /* Now resume and see if it's still there. */
870         enable_one_screen(&ms_data);
871         igt_assert(pc8_plus_disabled());
872         for (i = 0; i < buf_size; i++)
873                 igt_assert(gem_buf[i] == (~i & 0xFF));
874
875         igt_assert(munmap(gem_buf, buf_size) == 0);
876
877         /* Now the opposite: suspend, and try to create the mmap while
878          * suspended. */
879         disable_all_screens(&ms_data);
880         igt_assert(pc8_plus_enabled());
881
882         if (gtt_mmap)
883                 gem_buf = gem_mmap__gtt(drm_fd, handle, buf_size,
884                                         PROT_READ | PROT_WRITE);
885         else
886                 gem_buf = gem_mmap__cpu(drm_fd, handle, buf_size, 0);
887
888         igt_assert(pc8_plus_enabled());
889
890         for (i = 0; i < buf_size; i++)
891                 gem_buf[i] = i & 0xFF;
892
893         for (i = 0; i < buf_size; i++)
894                 igt_assert(gem_buf[i] == (i & 0xFF));
895
896         igt_assert(pc8_plus_enabled());
897
898         /* Resume and check if it's still there. */
899         enable_one_screen(&ms_data);
900         igt_assert(pc8_plus_disabled());
901         for (i = 0; i < buf_size; i++)
902                 igt_assert(gem_buf[i] == (i & 0xFF));
903
904         igt_assert(munmap(gem_buf, buf_size) == 0);
905         gem_close(drm_fd, handle);
906 }
907
908 static void gem_pread_subtest(void)
909 {
910         int i;
911         uint32_t handle;
912         int buf_size = 8192;
913         uint8_t *cpu_buf, *read_buf;
914
915         cpu_buf = malloc(buf_size);
916         read_buf = malloc(buf_size);
917         igt_assert(cpu_buf);
918         igt_assert(read_buf);
919         memset(cpu_buf, 0, buf_size);
920         memset(read_buf, 0, buf_size);
921
922         /* Create and set data while the device is active. */
923         enable_one_screen(&ms_data);
924         igt_assert(pc8_plus_disabled());
925
926         handle = gem_create(drm_fd, buf_size);
927
928         for (i = 0; i < buf_size; i++)
929                 cpu_buf[i] = i & 0xFF;
930
931         gem_write(drm_fd, handle, 0, cpu_buf, buf_size);
932
933         gem_read(drm_fd, handle, 0, read_buf, buf_size);
934
935         for (i = 0; i < buf_size; i++)
936                 igt_assert(cpu_buf[i] == read_buf[i]);
937
938         /* Now suspend, read and modify. */
939         disable_all_screens(&ms_data);
940         igt_assert(pc8_plus_enabled());
941
942         memset(read_buf, 0, buf_size);
943         gem_read(drm_fd, handle, 0, read_buf, buf_size);
944
945         for (i = 0; i < buf_size; i++)
946                 igt_assert(cpu_buf[i] == read_buf[i]);
947         igt_assert(pc8_plus_enabled());
948
949         for (i = 0; i < buf_size; i++)
950                 cpu_buf[i] = (~i & 0xFF);
951         gem_write(drm_fd, handle, 0, cpu_buf, buf_size);
952         igt_assert(pc8_plus_enabled());
953
954         /* Now resume and see if it's still there. */
955         enable_one_screen(&ms_data);
956         igt_assert(pc8_plus_disabled());
957
958         memset(read_buf, 0, buf_size);
959         gem_read(drm_fd, handle, 0, read_buf, buf_size);
960
961         for (i = 0; i < buf_size; i++)
962                 igt_assert(cpu_buf[i] == read_buf[i]);
963
964         gem_close(drm_fd, handle);
965
966         free(cpu_buf);
967         free(read_buf);
968 }
969
970 /* Paints a square of color $color, size $width x $height, at position $x x $y
971  * of $dst_handle, which contains pitch $pitch. */
972 static void submit_blt_cmd(uint32_t dst_handle, uint32_t x, uint32_t y,
973                            uint32_t width, uint32_t height, uint32_t pitch,
974                            uint32_t color, uint32_t *presumed_dst_offset)
975 {
976         int i, reloc_pos;
977         int bpp = 4;
978         uint32_t batch_handle;
979         int batch_size = 8 * sizeof(uint32_t);
980         uint32_t batch_buf[batch_size];
981         uint32_t offset_in_dst = (pitch * y) + (x * bpp);
982         struct drm_i915_gem_execbuffer2 execbuf = {};
983         struct drm_i915_gem_exec_object2 objs[2] = {{}, {}};
984         struct drm_i915_gem_relocation_entry relocs[1] = {{}};
985         struct drm_i915_gem_wait gem_wait;
986
987         i = 0;
988
989         batch_buf[i++] = COLOR_BLT_CMD | COLOR_BLT_WRITE_ALPHA |
990                          COLOR_BLT_WRITE_RGB;
991         batch_buf[i++] = (3 << 24) | (0xF0 << 16) | pitch;
992         batch_buf[i++] = (height << 16) | width * bpp;
993         reloc_pos = i;
994         batch_buf[i++] = *presumed_dst_offset + offset_in_dst;
995         batch_buf[i++] = color;
996
997         batch_buf[i++] = MI_NOOP;
998         batch_buf[i++] = MI_BATCH_BUFFER_END;
999         batch_buf[i++] = MI_NOOP;
1000
1001         igt_assert(i * sizeof(uint32_t) == batch_size);
1002
1003         batch_handle = gem_create(drm_fd, batch_size);
1004         gem_write(drm_fd, batch_handle, 0, batch_buf, batch_size);
1005
1006         relocs[0].target_handle = dst_handle;
1007         relocs[0].delta = offset_in_dst;
1008         relocs[0].offset = reloc_pos * sizeof(uint32_t);
1009         relocs[0].presumed_offset = *presumed_dst_offset;
1010         relocs[0].read_domains = 0;
1011         relocs[0].write_domain = I915_GEM_DOMAIN_RENDER;
1012
1013         objs[0].handle = dst_handle;
1014         objs[0].alignment = 64;
1015
1016         objs[1].handle = batch_handle;
1017         objs[1].relocation_count = 1;
1018         objs[1].relocs_ptr = (uintptr_t)relocs;
1019
1020         execbuf.buffers_ptr = (uintptr_t)objs;
1021         execbuf.buffer_count = 2;
1022         execbuf.batch_len = batch_size;
1023         execbuf.flags = I915_EXEC_BLT;
1024         i915_execbuffer2_set_context_id(execbuf, 0);
1025
1026         do_ioctl(drm_fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf);
1027
1028         *presumed_dst_offset = relocs[0].presumed_offset;
1029
1030         gem_wait.flags = 0;
1031         gem_wait.timeout_ns = 10000000000LL; /* 10s */
1032
1033         gem_wait.bo_handle = batch_handle;
1034         do_ioctl(drm_fd, DRM_IOCTL_I915_GEM_WAIT, &gem_wait);
1035
1036         gem_wait.bo_handle = dst_handle;
1037         do_ioctl(drm_fd, DRM_IOCTL_I915_GEM_WAIT, &gem_wait);
1038
1039         gem_close(drm_fd, batch_handle);
1040 }
1041
1042 /* Make sure we can submit a batch buffer and verify its result. */
1043 static void gem_execbuf_subtest(void)
1044 {
1045         int x, y;
1046         uint32_t handle;
1047         int bpp = 4;
1048         int pitch = 128 * bpp;
1049         int dst_size = 128 * 128 * bpp; /* 128x128 square */
1050         uint32_t *cpu_buf;
1051         uint32_t presumed_offset = 0;
1052         int sq_x = 5, sq_y = 10, sq_w = 15, sq_h = 20;
1053         uint32_t color;
1054
1055         /* Create and set data while the device is active. */
1056         enable_one_screen(&ms_data);
1057         igt_assert(pc8_plus_disabled());
1058
1059         handle = gem_create(drm_fd, dst_size);
1060
1061         cpu_buf = malloc(dst_size);
1062         igt_assert(cpu_buf);
1063         memset(cpu_buf, 0, dst_size);
1064         gem_write(drm_fd, handle, 0, cpu_buf, dst_size);
1065
1066         /* Now suspend and try it. */
1067         disable_all_screens(&ms_data);
1068         igt_assert(pc8_plus_enabled());
1069
1070         color = 0x12345678;
1071         submit_blt_cmd(handle, sq_x, sq_y, sq_w, sq_h, pitch, color,
1072                        &presumed_offset);
1073         igt_assert(pc8_plus_enabled());
1074
1075         gem_read(drm_fd, handle, 0, cpu_buf, dst_size);
1076         igt_assert(pc8_plus_enabled());
1077         for (y = 0; y < 128; y++) {
1078                 for (x = 0; x < 128; x++) {
1079                         uint32_t px = cpu_buf[y * 128 + x];
1080
1081                         if (y >= sq_y && y < (sq_y + sq_h) &&
1082                             x >= sq_x && x < (sq_x + sq_w))
1083                                 igt_assert(px == color);
1084                         else
1085                                 igt_assert(px == 0);
1086                 }
1087         }
1088
1089         /* Now resume and check for it again. */
1090         enable_one_screen(&ms_data);
1091         igt_assert(pc8_plus_disabled());
1092
1093         memset(cpu_buf, 0, dst_size);
1094         gem_read(drm_fd, handle, 0, cpu_buf, dst_size);
1095         for (y = 0; y < 128; y++) {
1096                 for (x = 0; x < 128; x++) {
1097                         uint32_t px = cpu_buf[y * 128 + x];
1098
1099                         if (y >= sq_y && y < (sq_y + sq_h) &&
1100                             x >= sq_x && x < (sq_x + sq_w))
1101                                 igt_assert(px == color);
1102                         else
1103                                 igt_assert(px == 0);
1104                 }
1105         }
1106
1107         /* Now we'll do the opposite: do the blt while active, then read while
1108          * suspended. We use the same spot, but a different color. As a bonus,
1109          * we're testing the presumed_offset from the previous command. */
1110         color = 0x87654321;
1111         submit_blt_cmd(handle, sq_x, sq_y, sq_w, sq_h, pitch, color,
1112                        &presumed_offset);
1113
1114         disable_all_screens(&ms_data);
1115         igt_assert(pc8_plus_enabled());
1116
1117         memset(cpu_buf, 0, dst_size);
1118         gem_read(drm_fd, handle, 0, cpu_buf, dst_size);
1119         for (y = 0; y < 128; y++) {
1120                 for (x = 0; x < 128; x++) {
1121                         uint32_t px = cpu_buf[y * 128 + x];
1122
1123                         if (y >= sq_y && y < (sq_y + sq_h) &&
1124                             x >= sq_x && x < (sq_x + sq_w))
1125                                 igt_assert(px == color);
1126                         else
1127                                 igt_assert(px == 0);
1128                 }
1129         }
1130
1131         gem_close(drm_fd, handle);
1132
1133         free(cpu_buf);
1134 }
1135
1136 /* Assuming execbuf already works, let's see what happens when we force many
1137  * suspend/resume cycles with commands. */
1138 static void gem_execbuf_stress_subtest(void)
1139 {
1140         int i;
1141         int max = 50;
1142         int batch_size = 4 * sizeof(uint32_t);
1143         uint32_t batch_buf[batch_size];
1144         uint32_t handle;
1145         struct drm_i915_gem_execbuffer2 execbuf = {};
1146         struct drm_i915_gem_exec_object2 objs[1] = {{}};
1147
1148         i = 0;
1149         batch_buf[i++] = MI_NOOP;
1150         batch_buf[i++] = MI_NOOP;
1151         batch_buf[i++] = MI_BATCH_BUFFER_END;
1152         batch_buf[i++] = MI_NOOP;
1153         igt_assert(i * sizeof(uint32_t) == batch_size);
1154
1155         disable_all_screens(&ms_data);
1156         igt_assert(pc8_plus_enabled());
1157
1158         handle = gem_create(drm_fd, batch_size);
1159         gem_write(drm_fd, handle, 0, batch_buf, batch_size);
1160
1161         objs[0].handle = handle;
1162
1163         execbuf.buffers_ptr = (uintptr_t)objs;
1164         execbuf.buffer_count = 1;
1165         execbuf.batch_len = batch_size;
1166         execbuf.flags = I915_EXEC_RENDER;
1167         i915_execbuffer2_set_context_id(execbuf, 0);
1168
1169         for (i = 0; i < max; i++) {
1170                 do_ioctl(drm_fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf);
1171                 igt_assert(pc8_plus_enabled());
1172         }
1173
1174         gem_close(drm_fd, handle);
1175 }
1176
1177 int main(int argc, char *argv[])
1178 {
1179         bool do_register_compare = false;
1180
1181         if (argc > 1 && strcmp(argv[1], "--do-register-compare") == 0)
1182                 do_register_compare = true;
1183
1184         igt_subtest_init(argc, argv);
1185
1186         /* Skip instead of failing in case the machine is not prepared to reach
1187          * PC8+. We don't want bug reports from cases where the machine is just
1188          * not properly configured. */
1189         igt_fixture
1190                 setup_environment();
1191
1192         /* Essential things */
1193         igt_subtest("rte")
1194                 basic_subtest();
1195         igt_subtest("drm-resources-equal")
1196                 drm_resources_equal_subtest();
1197
1198         /* Basic modeset */
1199         igt_subtest("modeset-lpsp")
1200                 modeset_subtest(SCREEN_TYPE_LPSP, 1, WAIT);
1201         igt_subtest("modeset-non-lpsp")
1202                 modeset_subtest(SCREEN_TYPE_NON_LPSP, 1, WAIT);
1203
1204         /* GEM */
1205         igt_subtest("gem-mmap-cpu")
1206                 gem_mmap_subtest(false);
1207         igt_subtest("gem-mmap-gtt")
1208                 gem_mmap_subtest(true);
1209         igt_subtest("gem-pread")
1210                 gem_pread_subtest();
1211         igt_subtest("gem-execbuf")
1212                 gem_execbuf_subtest();
1213
1214         /* Misc */
1215         igt_subtest("i2c")
1216                 i2c_subtest();
1217         igt_subtest("debugfs-read")
1218                 debugfs_read_subtest();
1219         igt_subtest("debugfs-forcewake-user")
1220                 debugfs_forcewake_user_subtest();
1221         igt_subtest("sysfs-read")
1222                 sysfs_read_subtest();
1223
1224         /* Modeset stress */
1225         igt_subtest("modeset-lpsp-stress")
1226                 modeset_subtest(SCREEN_TYPE_LPSP, 50, WAIT);
1227         igt_subtest("modeset-non-lpsp-stress")
1228                 modeset_subtest(SCREEN_TYPE_NON_LPSP, 50, WAIT);
1229         igt_subtest("modeset-lpsp-stress-no-wait")
1230                 modeset_subtest(SCREEN_TYPE_LPSP, 50, DONT_WAIT);
1231         igt_subtest("modeset-non-lpsp-stress-no-wait")
1232                 modeset_subtest(SCREEN_TYPE_NON_LPSP, 50, DONT_WAIT);
1233
1234         /* GEM stress */
1235         igt_subtest("gem-execbuf-stress")
1236                 gem_execbuf_stress_subtest();
1237
1238         /* Optional */
1239         igt_subtest("register-compare") {
1240                 igt_require(do_register_compare);
1241                 register_compare_subtest();
1242         }
1243
1244         igt_fixture
1245                 teardown_environment();
1246
1247         igt_exit();
1248 }