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 POWER_FLOOR_ENABLE_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/power_limits/power_floor_enable"
14 #define POWER_FLOOR_STATUS_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/power_limits/power_floor_status"
15
power_floor_exit(int signum)16 void power_floor_exit(int signum)
17 {
18 int fd;
19
20 /* Disable feature via sysfs knob */
21
22 fd = open(POWER_FLOOR_ENABLE_ATTRIBUTE, O_RDWR);
23 if (fd < 0) {
24 perror("Unable to open power floor enable file\n");
25 exit(1);
26 }
27
28 if (write(fd, "0\n", 2) < 0) {
29 perror("Can' disable power floor notifications\n");
30 exit(1);
31 }
32
33 printf("Disabled power floor notifications\n");
34
35 close(fd);
36 }
37
main(int argc,char ** argv)38 int main(int argc, char **argv)
39 {
40 struct pollfd ufd;
41 char status_str[3];
42 int fd, ret;
43
44 if (signal(SIGINT, power_floor_exit) == SIG_IGN)
45 signal(SIGINT, SIG_IGN);
46 if (signal(SIGHUP, power_floor_exit) == SIG_IGN)
47 signal(SIGHUP, SIG_IGN);
48 if (signal(SIGTERM, power_floor_exit) == SIG_IGN)
49 signal(SIGTERM, SIG_IGN);
50
51 /* Enable feature via sysfs knob */
52 fd = open(POWER_FLOOR_ENABLE_ATTRIBUTE, O_RDWR);
53 if (fd < 0) {
54 perror("Unable to open power floor enable file\n");
55 exit(1);
56 }
57
58 if (write(fd, "1\n", 2) < 0) {
59 perror("Can' enable power floor notifications\n");
60 exit(1);
61 }
62
63 close(fd);
64
65 printf("Enabled power floor notifications\n");
66
67 while (1) {
68 fd = open(POWER_FLOOR_STATUS_ATTRIBUTE, O_RDONLY);
69 if (fd < 0) {
70 perror("Unable to power floor status file\n");
71 exit(1);
72 }
73
74 if ((lseek(fd, 0L, SEEK_SET)) < 0) {
75 fprintf(stderr, "Failed to set pointer to beginning\n");
76 exit(1);
77 }
78
79 if (read(fd, status_str, sizeof(status_str)) < 0) {
80 fprintf(stderr, "Failed to read from:%s\n",
81 POWER_FLOOR_STATUS_ATTRIBUTE);
82 exit(1);
83 }
84
85 ufd.fd = fd;
86 ufd.events = POLLPRI;
87
88 ret = poll(&ufd, 1, -1);
89 if (ret < 0) {
90 perror("poll error");
91 exit(1);
92 } else if (ret == 0) {
93 printf("Poll Timeout\n");
94 } else {
95 if ((lseek(fd, 0L, SEEK_SET)) < 0) {
96 fprintf(stderr, "Failed to set pointer to beginning\n");
97 exit(1);
98 }
99
100 if (read(fd, status_str, sizeof(status_str)) < 0)
101 exit(0);
102
103 printf("power floor status: %s\n", status_str);
104 }
105
106 close(fd);
107 }
108 }
109