1*d83cc019SAndroid Build Coastguard Worker #include <ctype.h>
2*d83cc019SAndroid Build Coastguard Worker #include <errno.h>
3*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
4*d83cc019SAndroid Build Coastguard Worker #include <locale.h>
5*d83cc019SAndroid Build Coastguard Worker #include <math.h>
6*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
7*d83cc019SAndroid Build Coastguard Worker #include <inttypes.h>
8*d83cc019SAndroid Build Coastguard Worker
9*d83cc019SAndroid Build Coastguard Worker #include "igt_gpu_power.h"
10*d83cc019SAndroid Build Coastguard Worker #include "igt_perf.h"
11*d83cc019SAndroid Build Coastguard Worker #include "igt_sysfs.h"
12*d83cc019SAndroid Build Coastguard Worker
13*d83cc019SAndroid Build Coastguard Worker struct rapl {
14*d83cc019SAndroid Build Coastguard Worker uint64_t power, type;
15*d83cc019SAndroid Build Coastguard Worker double scale;
16*d83cc019SAndroid Build Coastguard Worker };
17*d83cc019SAndroid Build Coastguard Worker
rapl_parse(struct rapl * r)18*d83cc019SAndroid Build Coastguard Worker static int rapl_parse(struct rapl *r)
19*d83cc019SAndroid Build Coastguard Worker {
20*d83cc019SAndroid Build Coastguard Worker locale_t locale, oldlocale;
21*d83cc019SAndroid Build Coastguard Worker bool result;
22*d83cc019SAndroid Build Coastguard Worker int dir;
23*d83cc019SAndroid Build Coastguard Worker
24*d83cc019SAndroid Build Coastguard Worker memset(r, 0, sizeof(*r));
25*d83cc019SAndroid Build Coastguard Worker
26*d83cc019SAndroid Build Coastguard Worker dir = open("/sys/devices/power", O_RDONLY);
27*d83cc019SAndroid Build Coastguard Worker if (dir < 0)
28*d83cc019SAndroid Build Coastguard Worker return -errno;
29*d83cc019SAndroid Build Coastguard Worker
30*d83cc019SAndroid Build Coastguard Worker /* Replace user environment with plain C to match kernel format */
31*d83cc019SAndroid Build Coastguard Worker locale = newlocale(LC_ALL, "C", 0);
32*d83cc019SAndroid Build Coastguard Worker oldlocale = uselocale(locale);
33*d83cc019SAndroid Build Coastguard Worker
34*d83cc019SAndroid Build Coastguard Worker result = true;
35*d83cc019SAndroid Build Coastguard Worker result &= igt_sysfs_scanf(dir, "type",
36*d83cc019SAndroid Build Coastguard Worker "%"PRIu64, &r->type) == 1;
37*d83cc019SAndroid Build Coastguard Worker result &= igt_sysfs_scanf(dir, "events/energy-gpu",
38*d83cc019SAndroid Build Coastguard Worker "event=%"PRIx64, &r->power) == 1;
39*d83cc019SAndroid Build Coastguard Worker result &= igt_sysfs_scanf(dir, "events/energy-gpu.scale",
40*d83cc019SAndroid Build Coastguard Worker "%lf", &r->scale) == 1;
41*d83cc019SAndroid Build Coastguard Worker
42*d83cc019SAndroid Build Coastguard Worker uselocale(oldlocale);
43*d83cc019SAndroid Build Coastguard Worker freelocale(locale);
44*d83cc019SAndroid Build Coastguard Worker
45*d83cc019SAndroid Build Coastguard Worker close(dir);
46*d83cc019SAndroid Build Coastguard Worker
47*d83cc019SAndroid Build Coastguard Worker if (!result)
48*d83cc019SAndroid Build Coastguard Worker return -EINVAL;
49*d83cc019SAndroid Build Coastguard Worker
50*d83cc019SAndroid Build Coastguard Worker if (isnan(r->scale) || !r->scale)
51*d83cc019SAndroid Build Coastguard Worker return -ERANGE;
52*d83cc019SAndroid Build Coastguard Worker
53*d83cc019SAndroid Build Coastguard Worker return 0;
54*d83cc019SAndroid Build Coastguard Worker }
55*d83cc019SAndroid Build Coastguard Worker
gpu_power_open(struct gpu_power * power)56*d83cc019SAndroid Build Coastguard Worker int gpu_power_open(struct gpu_power *power)
57*d83cc019SAndroid Build Coastguard Worker {
58*d83cc019SAndroid Build Coastguard Worker struct rapl r;
59*d83cc019SAndroid Build Coastguard Worker
60*d83cc019SAndroid Build Coastguard Worker power->fd = rapl_parse(&r);
61*d83cc019SAndroid Build Coastguard Worker if (power->fd < 0)
62*d83cc019SAndroid Build Coastguard Worker goto err;
63*d83cc019SAndroid Build Coastguard Worker
64*d83cc019SAndroid Build Coastguard Worker power->fd = igt_perf_open(r.type, r.power);
65*d83cc019SAndroid Build Coastguard Worker if (power->fd < 0) {
66*d83cc019SAndroid Build Coastguard Worker power->fd = -errno;
67*d83cc019SAndroid Build Coastguard Worker goto err;
68*d83cc019SAndroid Build Coastguard Worker }
69*d83cc019SAndroid Build Coastguard Worker
70*d83cc019SAndroid Build Coastguard Worker power->scale = r.scale;
71*d83cc019SAndroid Build Coastguard Worker
72*d83cc019SAndroid Build Coastguard Worker return 0;
73*d83cc019SAndroid Build Coastguard Worker
74*d83cc019SAndroid Build Coastguard Worker err:
75*d83cc019SAndroid Build Coastguard Worker errno = 0;
76*d83cc019SAndroid Build Coastguard Worker return power->fd;
77*d83cc019SAndroid Build Coastguard Worker }
78*d83cc019SAndroid Build Coastguard Worker
gpu_power_read(struct gpu_power * power,struct gpu_power_sample * s)79*d83cc019SAndroid Build Coastguard Worker bool gpu_power_read(struct gpu_power *power, struct gpu_power_sample *s)
80*d83cc019SAndroid Build Coastguard Worker {
81*d83cc019SAndroid Build Coastguard Worker return read(power->fd, s, sizeof(*s)) == sizeof(*s);
82*d83cc019SAndroid Build Coastguard Worker }
83*d83cc019SAndroid Build Coastguard Worker
gpu_power_close(struct gpu_power * power)84*d83cc019SAndroid Build Coastguard Worker void gpu_power_close(struct gpu_power *power)
85*d83cc019SAndroid Build Coastguard Worker {
86*d83cc019SAndroid Build Coastguard Worker close(power->fd);
87*d83cc019SAndroid Build Coastguard Worker }
88