1 /*
2 * Copyright © 2013, 2015 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 * David Weinehall <david.weinehall@intel.com>
26 *
27 */
28 #include <fcntl.h>
29 #include <stdio.h>
30 #include <limits.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include <dirent.h>
37
38 #include "drmtest.h"
39 #include "igt_pm.h"
40 #include "igt_aux.h"
41
42 /**
43 * SECTION:igt_pm
44 * @short_description: Power Management related helpers
45 * @title: Power Management
46 * @include: igt.h
47 *
48 * This library provides various helpers to enable power management for,
49 * and in some cases subsequently allow restoring the old behaviour of,
50 * various external components that by default are set up in a way
51 * that interferes with the testing of our power management functionality.
52 */
53
54 enum {
55 POLICY_UNKNOWN = -1,
56 POLICY_MAX_PERFORMANCE = 0,
57 POLICY_MEDIUM_POWER = 1,
58 POLICY_MIN_POWER = 2
59 };
60
61 #define MAX_PERFORMANCE_STR "max_performance\n"
62 #define MEDIUM_POWER_STR "medium_power\n"
63 #define MIN_POWER_STR "min_power\n"
64 /* Remember to fix this if adding longer strings */
65 #define MAX_POLICY_STRLEN strlen(MAX_PERFORMANCE_STR)
66
67 static char __igt_pm_audio_runtime_power_save[64];
68 static char * __igt_pm_audio_runtime_control_path;
69 static char __igt_pm_audio_runtime_control[64];
70
__igt_pm_audio_restore_runtime_pm(void)71 static int __igt_pm_audio_restore_runtime_pm(void)
72 {
73 int fd;
74
75 if (!__igt_pm_audio_runtime_power_save[0])
76 return 0;
77
78 fd = open("/sys/module/snd_hda_intel/parameters/power_save", O_WRONLY);
79 if (fd < 0)
80 return errno;
81
82 if (write(fd, __igt_pm_audio_runtime_power_save,
83 strlen(__igt_pm_audio_runtime_power_save)) !=
84 strlen(__igt_pm_audio_runtime_power_save)) {
85 close(fd);
86 return errno;
87 }
88
89 close(fd);
90
91 fd = open(__igt_pm_audio_runtime_control_path, O_WRONLY);
92 if (fd < 0)
93 return errno;
94
95 if (write(fd, __igt_pm_audio_runtime_control,
96 strlen(__igt_pm_audio_runtime_control)) !=
97 strlen(__igt_pm_audio_runtime_control)) {
98 close(fd);
99 return errno;
100 }
101
102 close(fd);
103
104 memset(__igt_pm_audio_runtime_power_save, 0,
105 sizeof(__igt_pm_audio_runtime_power_save));
106
107 memset(__igt_pm_audio_runtime_control, 0,
108 sizeof(__igt_pm_audio_runtime_control));
109
110 free(__igt_pm_audio_runtime_control_path);
111 __igt_pm_audio_runtime_control_path = NULL;
112
113 return 0;
114 }
115
igt_pm_audio_restore_runtime_pm(void)116 static void igt_pm_audio_restore_runtime_pm(void)
117 {
118 int ret;
119
120 if (!__igt_pm_audio_runtime_power_save[0])
121 return;
122
123 igt_debug("Restoring audio power management to '%s' and '%s'\n",
124 __igt_pm_audio_runtime_power_save,
125 __igt_pm_audio_runtime_control);
126
127 ret = __igt_pm_audio_restore_runtime_pm();
128 if (ret)
129 igt_warn("Failed to restore runtime audio PM! (errno=%d)\n",
130 ret);
131 }
132
__igt_pm_audio_runtime_exit_handler(int sig)133 static void __igt_pm_audio_runtime_exit_handler(int sig)
134 {
135 __igt_pm_audio_restore_runtime_pm();
136 }
137
strchomp(char * str)138 static void strchomp(char *str)
139 {
140 int len = strlen(str);
141
142 if (len && str[len - 1] == '\n')
143 str[len - 1] = 0;
144 }
145
__igt_pm_enable_audio_runtime_pm(void)146 static int __igt_pm_enable_audio_runtime_pm(void)
147 {
148 char *path = NULL;
149 struct dirent *de;
150 DIR *dir;
151 int err;
152 int fd;
153
154 dir = opendir("/sys/class/sound");
155 if (!dir)
156 return 0;
157
158 /* Find PCI device claimed by snd_hda_intel and tied to i915. */
159 while ((de = readdir(dir))) {
160 const char *match = "hwC";
161 char buf[32] = { }; /* for Valgrind */
162 int loops = 500;
163 int base;
164 int ret;
165
166 if (de->d_type != DT_LNK ||
167 strncmp(de->d_name, match, strlen(match)))
168 continue;
169
170 base = openat(dirfd(dir), de->d_name, O_RDONLY);
171 igt_assert_fd(base);
172
173 do {
174 fd = openat(base, "vendor_name", O_RDONLY);
175 if (fd < 0) /* module is still loading? */
176 usleep(1000);
177 else
178 break;
179 } while (--loops);
180 close(base);
181 if (fd < 0)
182 continue;
183
184 ret = read(fd, buf, sizeof(buf) - 1);
185 close(fd);
186 igt_assert(ret > 0);
187 buf[ret] = '\0';
188 strchomp(buf);
189
190 /* Realtek and similar devices are not what we are after. */
191 if (strcmp(buf, "Intel"))
192 continue;
193
194 igt_assert(asprintf(&path,
195 "/sys/class/sound/%s/device/device/power/control",
196 de->d_name));
197
198 igt_debug("Audio device path is %s\n", path);
199 break;
200 }
201 closedir(dir);
202
203 fd = open("/sys/module/snd_hda_intel/parameters/power_save", O_RDWR);
204 if (fd < 0)
205 return 0;
206
207 /* snd_hda_intel loaded but no path found is an error. */
208 if (!path) {
209 close(fd);
210 err = -ESRCH;
211 goto err;
212 }
213
214 igt_assert(read(fd, __igt_pm_audio_runtime_power_save,
215 sizeof(__igt_pm_audio_runtime_power_save) - 1) > 0);
216 strchomp(__igt_pm_audio_runtime_power_save);
217 igt_install_exit_handler(__igt_pm_audio_runtime_exit_handler);
218 igt_assert_eq(write(fd, "1\n", 2), 2);
219 close(fd);
220
221 fd = open(path, O_RDWR);
222 if (fd < 0) {
223 err = -errno;
224 goto err;
225 }
226
227 igt_assert(read(fd, __igt_pm_audio_runtime_control,
228 sizeof(__igt_pm_audio_runtime_control) - 1) > 0);
229 strchomp(__igt_pm_audio_runtime_control);
230 igt_assert_eq(write(fd, "auto\n", 5), 5);
231 close(fd);
232
233 __igt_pm_audio_runtime_control_path = path;
234
235 igt_debug("Saved audio power management as '%s' and '%s'\n",
236 __igt_pm_audio_runtime_power_save,
237 __igt_pm_audio_runtime_control);
238
239 /* Give some time for it to react. */
240 sleep(1);
241 return 0;
242
243 err:
244 free(path);
245 return err;
246 }
247
248 /**
249 * igt_pm_enable_audio_runtime_pm:
250 *
251 * We know that if we don't enable audio runtime PM, snd_hda_intel will never
252 * release its power well refcount, and we'll never reach the LPSP state.
253 * There's no guarantee that it will release the power well if we enable
254 * runtime PM, but at least we can try.
255 *
256 * We don't have any assertions on open since the user may not even have
257 * snd_hda_intel loaded, which is not a problem.
258 */
igt_pm_enable_audio_runtime_pm(void)259 void igt_pm_enable_audio_runtime_pm(void)
260 {
261 int err;
262
263 /* Check if already enabled. */
264 if (__igt_pm_audio_runtime_power_save[0])
265 return;
266
267 for (int count = 0; count < 110; count++) {
268 if (!__igt_pm_enable_audio_runtime_pm())
269 return;
270
271 /* modprobe(sna-hda-intel) acts async so poll for sysfs */
272 if (count < 100)
273 usleep(10 * 1000); /* poll at 10ms for the first 1s */
274 else
275 sleep(1);
276 }
277
278 err = __igt_pm_enable_audio_runtime_pm();
279 if (err)
280 igt_debug("Failed to enable audio runtime PM! (%d)\n", -err);
281 }
282
283 /**
284 * igt_pm_enable_sata_link_power_management:
285 *
286 * Enable the min_power policy for SATA link power management.
287 * Without this we cannot reach deep runtime power states.
288 *
289 * We don't have any assertions on open since the system might not have
290 * a SATA host.
291 *
292 * Returns:
293 * An opaque pointer to the data needed to restore the default values
294 * after the test has terminated, or NULL if SATA link power management
295 * is not supported. This pointer should be freed when no longer used
296 * (typically after having called restore_sata_link_power_management()).
297 */
igt_pm_enable_sata_link_power_management(void)298 int8_t *igt_pm_enable_sata_link_power_management(void)
299 {
300 int fd, i;
301 ssize_t len;
302 char *buf;
303 char *file_name;
304 int8_t *link_pm_policies = NULL;
305
306 file_name = malloc(PATH_MAX);
307 buf = malloc(MAX_POLICY_STRLEN + 1);
308
309 for (i = 0; ; i++) {
310 int8_t policy;
311
312 snprintf(file_name, PATH_MAX,
313 "/sys/class/scsi_host/host%d/link_power_management_policy",
314 i);
315
316 fd = open(file_name, O_RDWR);
317 if (fd < 0)
318 break;
319
320 len = read(fd, buf, MAX_POLICY_STRLEN);
321 buf[len] = '\0';
322
323 if (!strncmp(MAX_PERFORMANCE_STR, buf,
324 strlen(MAX_PERFORMANCE_STR)))
325 policy = POLICY_MAX_PERFORMANCE;
326 else if (!strncmp(MEDIUM_POWER_STR, buf,
327 strlen(MEDIUM_POWER_STR)))
328 policy = POLICY_MEDIUM_POWER;
329 else if (!strncmp(MIN_POWER_STR, buf,
330 strlen(MIN_POWER_STR)))
331 policy = POLICY_MIN_POWER;
332 else
333 policy = POLICY_UNKNOWN;
334
335 if (!(i % 256))
336 link_pm_policies = realloc(link_pm_policies,
337 (i / 256 + 1) * 256 + 1);
338
339 link_pm_policies[i] = policy;
340 link_pm_policies[i + 1] = 0;
341
342 /* If the policy is something we don't know about,
343 * don't touch it, since we might potentially break things.
344 * And we obviously don't need to touch anything if the
345 * setting is already correct...
346 */
347 if (policy != POLICY_UNKNOWN &&
348 policy != POLICY_MIN_POWER) {
349 lseek(fd, 0, SEEK_SET);
350 igt_assert_eq(write(fd, MIN_POWER_STR,
351 strlen(MIN_POWER_STR)),
352 strlen(MIN_POWER_STR));
353 }
354 close(fd);
355 }
356 free(buf);
357 free(file_name);
358
359 return link_pm_policies;
360 }
361
362 /**
363 * igt_pm_restore_sata_link_power_management:
364 * @pm_data: An opaque pointer with saved link PM policies;
365 * If NULL is passed we force enable the "max_performance" policy.
366 *
367 * Restore the link power management policies to the values
368 * prior to enabling min_power.
369 *
370 * Caveat: If the system supports hotplugging and hotplugging takes
371 * place during our testing so that the hosts change numbers
372 * we might restore the settings to the wrong hosts.
373 */
igt_pm_restore_sata_link_power_management(int8_t * pm_data)374 void igt_pm_restore_sata_link_power_management(int8_t *pm_data)
375
376 {
377 int fd, i;
378 char *file_name;
379
380 /* Disk runtime PM policies. */
381 file_name = malloc(PATH_MAX);
382 for (i = 0; ; i++) {
383 int8_t policy;
384
385 if (!pm_data)
386 policy = POLICY_MAX_PERFORMANCE;
387 else if (pm_data[i] == POLICY_UNKNOWN)
388 continue;
389 else
390 policy = pm_data[i];
391
392 snprintf(file_name, PATH_MAX,
393 "/sys/class/scsi_host/host%d/link_power_management_policy",
394 i);
395
396 fd = open(file_name, O_WRONLY);
397 if (fd < 0)
398 break;
399
400 switch (policy) {
401 default:
402 case POLICY_MAX_PERFORMANCE:
403 igt_assert_eq(write(fd, MAX_PERFORMANCE_STR,
404 strlen(MAX_PERFORMANCE_STR)),
405 strlen(MAX_PERFORMANCE_STR));
406 break;
407
408 case POLICY_MEDIUM_POWER:
409 igt_assert_eq(write(fd, MEDIUM_POWER_STR,
410 strlen(MEDIUM_POWER_STR)),
411 strlen(MEDIUM_POWER_STR));
412 break;
413
414 case POLICY_MIN_POWER:
415 igt_assert_eq(write(fd, MIN_POWER_STR,
416 strlen(MIN_POWER_STR)),
417 strlen(MIN_POWER_STR));
418 break;
419 }
420
421 close(fd);
422 }
423 free(file_name);
424 }
425 #define POWER_DIR "/sys/devices/pci0000:00/0000:00:02.0/power"
426 /* We just leak this on exit ... */
427 int pm_status_fd = -1;
428
429 static char __igt_pm_runtime_autosuspend[64];
430 static char __igt_pm_runtime_control[64];
431
__igt_restore_runtime_pm(void)432 static int __igt_restore_runtime_pm(void)
433 {
434 int fd;
435
436 if (pm_status_fd < 0)
437 return 0;
438
439 fd = open(POWER_DIR "/autosuspend_delay_ms", O_WRONLY);
440 if (fd < 0)
441 return errno;
442
443 if (write(fd, __igt_pm_runtime_autosuspend,
444 strlen(__igt_pm_runtime_autosuspend)) !=
445 strlen(__igt_pm_runtime_autosuspend)) {
446 close(fd);
447 return errno;
448 }
449
450 close(fd);
451
452 fd = open(POWER_DIR "/control", O_WRONLY);
453 if (fd < 0)
454 return errno;
455
456 if (write(fd, __igt_pm_runtime_control,
457 strlen(__igt_pm_runtime_control)) !=
458 strlen(__igt_pm_runtime_control)) {
459 close(fd);
460 return errno;
461 }
462
463 close(fd);
464
465 close(pm_status_fd);
466 pm_status_fd = -1;
467
468 return 0;
469 }
470
471 /**
472 * igt_restore_runtime_pm:
473 *
474 * Restores the runtime PM configuration as it was before the call to
475 * igt_setup_runtime_pm.
476 */
igt_restore_runtime_pm(void)477 void igt_restore_runtime_pm(void)
478 {
479 int ret;
480
481 if (pm_status_fd < 0)
482 return;
483
484 igt_debug("Restoring runtime PM management to '%s' and '%s'\n",
485 __igt_pm_runtime_autosuspend,
486 __igt_pm_runtime_control);
487
488 ret = __igt_restore_runtime_pm();
489 if (ret)
490 igt_warn("Failed to restore runtime PM! (errno=%d)\n", ret);
491
492 igt_pm_audio_restore_runtime_pm();
493 }
494
__igt_pm_runtime_exit_handler(int sig)495 static void __igt_pm_runtime_exit_handler(int sig)
496 {
497 __igt_restore_runtime_pm();
498 }
499
500 /**
501 * igt_setup_runtime_pm:
502 *
503 * Sets up the runtime PM helper functions and enables runtime PM. To speed up
504 * tests the autosuspend delay is set to 0.
505 *
506 * Returns:
507 * True if runtime pm is available, false otherwise.
508 */
igt_setup_runtime_pm(void)509 bool igt_setup_runtime_pm(void)
510 {
511 int fd;
512 ssize_t size;
513 char buf[6];
514
515 if (pm_status_fd >= 0)
516 return true;
517
518 igt_pm_enable_audio_runtime_pm();
519
520 /*
521 * Our implementation uses autosuspend. Try to set it to 0ms so the
522 * test suite goes faster and we have a higher probability of
523 * triggering race conditions.
524 */
525 fd = open(POWER_DIR "/autosuspend_delay_ms", O_RDWR);
526 if (fd < 0) {
527 igt_pm_audio_restore_runtime_pm();
528 return false;
529 }
530
531 /*
532 * Save previous values to be able to install exit handler to restore
533 * them on test exit.
534 */
535 size = read(fd, __igt_pm_runtime_autosuspend,
536 sizeof(__igt_pm_runtime_autosuspend) - 1);
537
538 /*
539 * If we fail to read from the file, it means this system doesn't
540 * support runtime PM.
541 */
542 if (size <= 0) {
543 close(fd);
544 igt_pm_audio_restore_runtime_pm();
545 return false;
546 }
547
548 __igt_pm_runtime_autosuspend[size] = '\0';
549
550 strchomp(__igt_pm_runtime_autosuspend);
551 igt_install_exit_handler(__igt_pm_runtime_exit_handler);
552
553 size = write(fd, "0\n", 2);
554
555 close(fd);
556
557 if (size != 2)
558 return false;
559
560 /* We know we support runtime PM, let's try to enable it now. */
561 fd = open(POWER_DIR "/control", O_RDWR);
562 igt_assert_f(fd >= 0, "Can't open " POWER_DIR "/control\n");
563
564 igt_assert(read(fd, __igt_pm_runtime_control,
565 sizeof(__igt_pm_runtime_control) - 1) > 0);
566 strchomp(__igt_pm_runtime_control);
567
568 igt_debug("Saved runtime power management as '%s' and '%s'\n",
569 __igt_pm_runtime_autosuspend, __igt_pm_runtime_control);
570
571 size = write(fd, "auto\n", 5);
572 igt_assert(size == 5);
573
574 lseek(fd, 0, SEEK_SET);
575 size = read(fd, buf, ARRAY_SIZE(buf));
576 igt_assert(size == 5);
577 igt_assert(strncmp(buf, "auto\n", 5) == 0);
578
579 close(fd);
580
581 pm_status_fd = open(POWER_DIR "/runtime_status", O_RDONLY);
582 igt_assert_f(pm_status_fd >= 0,
583 "Can't open " POWER_DIR "/runtime_status\n");
584
585 return true;
586 }
587
588 /**
589 * igt_get_runtime_pm_status:
590 *
591 * Returns: The current runtime PM status.
592 */
igt_get_runtime_pm_status(void)593 enum igt_runtime_pm_status igt_get_runtime_pm_status(void)
594 {
595 ssize_t n_read;
596 char buf[32];
597
598 lseek(pm_status_fd, 0, SEEK_SET);
599 n_read = read(pm_status_fd, buf, ARRAY_SIZE(buf) - 1);
600 igt_assert(n_read >= 0);
601 buf[n_read] = '\0';
602
603 if (strncmp(buf, "suspended\n", n_read) == 0)
604 return IGT_RUNTIME_PM_STATUS_SUSPENDED;
605 else if (strncmp(buf, "active\n", n_read) == 0)
606 return IGT_RUNTIME_PM_STATUS_ACTIVE;
607 else if (strncmp(buf, "suspending\n", n_read) == 0)
608 return IGT_RUNTIME_PM_STATUS_SUSPENDING;
609 else if (strncmp(buf, "resuming\n", n_read) == 0)
610 return IGT_RUNTIME_PM_STATUS_RESUMING;
611
612 igt_assert_f(false, "Unknown status %s\n", buf);
613 return IGT_RUNTIME_PM_STATUS_UNKNOWN;
614 }
615
616 /**
617 * igt_wait_for_pm_status:
618 * @status: desired runtime PM status
619 *
620 * Waits until for the driver to switch to into the desired runtime PM status,
621 * with a 10 second timeout.
622 *
623 * Returns:
624 * True if the desired runtime PM status was attained, false if the operation
625 * timed out.
626 */
igt_wait_for_pm_status(enum igt_runtime_pm_status status)627 bool igt_wait_for_pm_status(enum igt_runtime_pm_status status)
628 {
629 return igt_wait(igt_get_runtime_pm_status() == status, 10000, 100);
630 }
631