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