1 // SPDX-License-Identifier: GPL-2.0
2
3 #define _GNU_SOURCE
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <fcntl.h>
10 #include <poll.h>
11 #include <signal.h>
12
13 #define WORKLOAD_NOTIFICATION_DELAY_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/notification_delay_ms"
14 #define WORKLOAD_ENABLE_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/workload_hint_enable"
15 #define WORKLOAD_TYPE_INDEX_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/workload_type_index"
16
17 static const char * const workload_types[] = {
18 "idle",
19 "battery_life",
20 "sustained",
21 "bursty",
22 NULL
23 };
24
25 #define WORKLOAD_TYPE_MAX_INDEX 3
26
workload_hint_exit(int signum)27 void workload_hint_exit(int signum)
28 {
29 int fd;
30
31 /* Disable feature via sysfs knob */
32
33 fd = open(WORKLOAD_ENABLE_ATTRIBUTE, O_RDWR);
34 if (fd < 0) {
35 perror("Unable to open workload type feature enable file\n");
36 exit(1);
37 }
38
39 if (write(fd, "0\n", 2) < 0) {
40 perror("Can' disable workload hints\n");
41 exit(1);
42 }
43
44 printf("Disabled workload type prediction\n");
45
46 close(fd);
47 }
48
main(int argc,char ** argv)49 int main(int argc, char **argv)
50 {
51 struct pollfd ufd;
52 char index_str[4];
53 int fd, ret, index;
54 char delay_str[64];
55 int delay = 0;
56
57 printf("Usage: workload_hint_test [notification delay in milli seconds]\n");
58
59 if (argc > 1) {
60 ret = sscanf(argv[1], "%d", &delay);
61 if (ret < 0) {
62 printf("Invalid delay\n");
63 exit(1);
64 }
65
66 printf("Setting notification delay to %d ms\n", delay);
67 if (delay < 0)
68 exit(1);
69
70 sprintf(delay_str, "%s\n", argv[1]);
71
72 sprintf(delay_str, "%s\n", argv[1]);
73 fd = open(WORKLOAD_NOTIFICATION_DELAY_ATTRIBUTE, O_RDWR);
74 if (fd < 0) {
75 perror("Unable to open workload notification delay\n");
76 exit(1);
77 }
78
79 if (write(fd, delay_str, strlen(delay_str)) < 0) {
80 perror("Can't set delay\n");
81 exit(1);
82 }
83
84 close(fd);
85 }
86
87 if (signal(SIGINT, workload_hint_exit) == SIG_IGN)
88 signal(SIGINT, SIG_IGN);
89 if (signal(SIGHUP, workload_hint_exit) == SIG_IGN)
90 signal(SIGHUP, SIG_IGN);
91 if (signal(SIGTERM, workload_hint_exit) == SIG_IGN)
92 signal(SIGTERM, SIG_IGN);
93
94 /* Enable feature via sysfs knob */
95 fd = open(WORKLOAD_ENABLE_ATTRIBUTE, O_RDWR);
96 if (fd < 0) {
97 perror("Unable to open workload type feature enable file\n");
98 exit(1);
99 }
100
101 if (write(fd, "1\n", 2) < 0) {
102 perror("Can' enable workload hints\n");
103 exit(1);
104 }
105
106 close(fd);
107
108 printf("Enabled workload type prediction\n");
109
110 while (1) {
111 fd = open(WORKLOAD_TYPE_INDEX_ATTRIBUTE, O_RDONLY);
112 if (fd < 0) {
113 perror("Unable to open workload type file\n");
114 exit(1);
115 }
116
117 if ((lseek(fd, 0L, SEEK_SET)) < 0) {
118 fprintf(stderr, "Failed to set pointer to beginning\n");
119 exit(1);
120 }
121
122 if (read(fd, index_str, sizeof(index_str)) < 0) {
123 fprintf(stderr, "Failed to read from:%s\n",
124 WORKLOAD_TYPE_INDEX_ATTRIBUTE);
125 exit(1);
126 }
127
128 ufd.fd = fd;
129 ufd.events = POLLPRI;
130
131 ret = poll(&ufd, 1, -1);
132 if (ret < 0) {
133 perror("poll error");
134 exit(1);
135 } else if (ret == 0) {
136 printf("Poll Timeout\n");
137 } else {
138 if ((lseek(fd, 0L, SEEK_SET)) < 0) {
139 fprintf(stderr, "Failed to set pointer to beginning\n");
140 exit(1);
141 }
142
143 if (read(fd, index_str, sizeof(index_str)) < 0)
144 exit(0);
145
146 ret = sscanf(index_str, "%d", &index);
147 if (ret < 0)
148 break;
149 if (index > WORKLOAD_TYPE_MAX_INDEX)
150 printf("Invalid workload type index\n");
151 else
152 printf("workload type:%s\n", workload_types[index]);
153 }
154
155 close(fd);
156 }
157 }
158