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 17static 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 27void 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 49int 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