From 27801542b2b815dad2759b7b1f85858627671a3b Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 28 Aug 2023 17:23:46 -0700 Subject: selftests/thermel/intel: Add test to read workload hint Some SoCs have in built firmware support to classify current running workload and pass to OS for making power management decisions. This test program waits for notification of workload type change and prints. This program can be used to test this feature and also allows other user space programs to use as a reference. Signed-off-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- tools/testing/selftests/Makefile | 1 + .../selftests/thermal/intel/workload_hint/Makefile | 12 ++ .../intel/workload_hint/workload_hint_test.c | 157 +++++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 tools/testing/selftests/thermal/intel/workload_hint/Makefile create mode 100644 tools/testing/selftests/thermal/intel/workload_hint/workload_hint_test.c (limited to 'tools') diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 42806add0114..725ce59e4637 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -85,6 +85,7 @@ TARGETS += syscall_user_dispatch TARGETS += sysctl TARGETS += tc-testing TARGETS += tdx +TARGETS += thermal/intel/workload_hint TARGETS += timens ifneq (1, $(quicktest)) TARGETS += timers diff --git a/tools/testing/selftests/thermal/intel/workload_hint/Makefile b/tools/testing/selftests/thermal/intel/workload_hint/Makefile new file mode 100644 index 000000000000..37ff3286283b --- /dev/null +++ b/tools/testing/selftests/thermal/intel/workload_hint/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +ifndef CROSS_COMPILE +uname_M := $(shell uname -m 2>/dev/null || echo not) +ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) + +ifeq ($(ARCH),x86) +TEST_GEN_PROGS := workload_hint_test + +include ../../../lib.mk + +endif +endif diff --git a/tools/testing/selftests/thermal/intel/workload_hint/workload_hint_test.c b/tools/testing/selftests/thermal/intel/workload_hint/workload_hint_test.c new file mode 100644 index 000000000000..217c3a641c53 --- /dev/null +++ b/tools/testing/selftests/thermal/intel/workload_hint/workload_hint_test.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#define WORKLOAD_NOTIFICATION_DELAY_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/notification_delay_ms" +#define WORKLOAD_ENABLE_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/workload_hint_enable" +#define WORKLOAD_TYPE_INDEX_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/workload_type_index" + +static const char * const workload_types[] = { + "idle", + "battery_life", + "sustained", + "bursty", + NULL +}; + +#define WORKLOAD_TYPE_MAX_INDEX 3 + +void workload_hint_exit(int signum) +{ + int fd; + + /* Disable feature via sysfs knob */ + + fd = open(WORKLOAD_ENABLE_ATTRIBUTE, O_RDWR); + if (fd < 0) { + perror("Unable to open workload type feature enable file\n"); + exit(1); + } + + if (write(fd, "0\n", 2) < 0) { + perror("Can' disable workload hints\n"); + exit(1); + } + + printf("Disabled workload type prediction\n"); + + close(fd); +} + +int main(int argc, char **argv) +{ + struct pollfd ufd; + char index_str[4]; + int fd, ret, index; + char delay_str[64]; + int delay = 0; + + printf("Usage: workload_hint_test [notification delay in milli seconds]\n"); + + if (argc > 1) { + ret = sscanf(argv[1], "%d", &delay); + if (ret < 0) { + printf("Invalid delay\n"); + exit(1); + } + + printf("Setting notification delay to %d ms\n", delay); + if (delay < 0) + exit(1); + + sprintf(delay_str, "%s\n", argv[1]); + + sprintf(delay_str, "%s\n", argv[1]); + fd = open(WORKLOAD_NOTIFICATION_DELAY_ATTRIBUTE, O_RDWR); + if (fd < 0) { + perror("Unable to open workload notification delay\n"); + exit(1); + } + + if (write(fd, delay_str, strlen(delay_str)) < 0) { + perror("Can't set delay\n"); + exit(1); + } + + close(fd); + } + + if (signal(SIGINT, workload_hint_exit) == SIG_IGN) + signal(SIGINT, SIG_IGN); + if (signal(SIGHUP, workload_hint_exit) == SIG_IGN) + signal(SIGHUP, SIG_IGN); + if (signal(SIGTERM, workload_hint_exit) == SIG_IGN) + signal(SIGTERM, SIG_IGN); + + /* Enable feature via sysfs knob */ + fd = open(WORKLOAD_ENABLE_ATTRIBUTE, O_RDWR); + if (fd < 0) { + perror("Unable to open workload type feature enable file\n"); + exit(1); + } + + if (write(fd, "1\n", 2) < 0) { + perror("Can' enable workload hints\n"); + exit(1); + } + + close(fd); + + printf("Enabled workload type prediction\n"); + + while (1) { + fd = open(WORKLOAD_TYPE_INDEX_ATTRIBUTE, O_RDONLY); + if (fd < 0) { + perror("Unable to open workload type file\n"); + exit(1); + } + + if ((lseek(fd, 0L, SEEK_SET)) < 0) { + fprintf(stderr, "Failed to set pointer to beginning\n"); + exit(1); + } + + if (read(fd, index_str, sizeof(index_str)) < 0) { + fprintf(stderr, "Failed to read from:%s\n", + WORKLOAD_TYPE_INDEX_ATTRIBUTE); + exit(1); + } + + ufd.fd = fd; + ufd.events = POLLPRI; + + ret = poll(&ufd, 1, -1); + if (ret < 0) { + perror("poll error"); + exit(1); + } else if (ret == 0) { + printf("Poll Timeout\n"); + } else { + if ((lseek(fd, 0L, SEEK_SET)) < 0) { + fprintf(stderr, "Failed to set pointer to beginning\n"); + exit(1); + } + + if (read(fd, index_str, sizeof(index_str)) < 0) + exit(0); + + ret = sscanf(index_str, "%d", &index); + if (ret < 0) + break; + if (index > WORKLOAD_TYPE_MAX_INDEX) + printf("Invalid workload type index\n"); + else + printf("workload type:%s\n", workload_types[index]); + } + + close(fd); + } +} -- cgit v1.2.3 From d4d27e5a1a88f433a4fabf748e00d626be48cd75 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 9 Oct 2023 12:05:38 -0700 Subject: selftests/thermel/intel: Add test to read power floor status Some SoCs have firmware support to notify, if the system can't lower power limit to a value requested from user space via RAPL constraints. This test program waits for notification of power floor and prints. This program can be used to test this feature and also allows other user space programs to use as a reference. Signed-off-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- tools/testing/selftests/Makefile | 1 + .../selftests/thermal/intel/power_floor/Makefile | 12 +++ .../thermal/intel/power_floor/power_floor_test.c | 108 +++++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 tools/testing/selftests/thermal/intel/power_floor/Makefile create mode 100644 tools/testing/selftests/thermal/intel/power_floor/power_floor_test.c (limited to 'tools') diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 725ce59e4637..c99de76fb20d 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -85,6 +85,7 @@ TARGETS += syscall_user_dispatch TARGETS += sysctl TARGETS += tc-testing TARGETS += tdx +TARGETS += thermal/intel/power_floor TARGETS += thermal/intel/workload_hint TARGETS += timens ifneq (1, $(quicktest)) diff --git a/tools/testing/selftests/thermal/intel/power_floor/Makefile b/tools/testing/selftests/thermal/intel/power_floor/Makefile new file mode 100644 index 000000000000..9b88e57dbba5 --- /dev/null +++ b/tools/testing/selftests/thermal/intel/power_floor/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +ifndef CROSS_COMPILE +uname_M := $(shell uname -m 2>/dev/null || echo not) +ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) + +ifeq ($(ARCH),x86) +TEST_GEN_PROGS := power_floor_test + +include ../../../lib.mk + +endif +endif diff --git a/tools/testing/selftests/thermal/intel/power_floor/power_floor_test.c b/tools/testing/selftests/thermal/intel/power_floor/power_floor_test.c new file mode 100644 index 000000000000..0326b39a11b9 --- /dev/null +++ b/tools/testing/selftests/thermal/intel/power_floor/power_floor_test.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#define POWER_FLOOR_ENABLE_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/power_limits/power_floor_enable" +#define POWER_FLOOR_STATUS_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/power_limits/power_floor_status" + +void power_floor_exit(int signum) +{ + int fd; + + /* Disable feature via sysfs knob */ + + fd = open(POWER_FLOOR_ENABLE_ATTRIBUTE, O_RDWR); + if (fd < 0) { + perror("Unable to open power floor enable file\n"); + exit(1); + } + + if (write(fd, "0\n", 2) < 0) { + perror("Can' disable power floor notifications\n"); + exit(1); + } + + printf("Disabled power floor notifications\n"); + + close(fd); +} + +int main(int argc, char **argv) +{ + struct pollfd ufd; + char status_str[3]; + int fd, ret; + + if (signal(SIGINT, power_floor_exit) == SIG_IGN) + signal(SIGINT, SIG_IGN); + if (signal(SIGHUP, power_floor_exit) == SIG_IGN) + signal(SIGHUP, SIG_IGN); + if (signal(SIGTERM, power_floor_exit) == SIG_IGN) + signal(SIGTERM, SIG_IGN); + + /* Enable feature via sysfs knob */ + fd = open(POWER_FLOOR_ENABLE_ATTRIBUTE, O_RDWR); + if (fd < 0) { + perror("Unable to open power floor enable file\n"); + exit(1); + } + + if (write(fd, "1\n", 2) < 0) { + perror("Can' enable power floor notifications\n"); + exit(1); + } + + close(fd); + + printf("Enabled power floor notifications\n"); + + while (1) { + fd = open(POWER_FLOOR_STATUS_ATTRIBUTE, O_RDONLY); + if (fd < 0) { + perror("Unable to power floor status file\n"); + exit(1); + } + + if ((lseek(fd, 0L, SEEK_SET)) < 0) { + fprintf(stderr, "Failed to set pointer to beginning\n"); + exit(1); + } + + if (read(fd, status_str, sizeof(status_str)) < 0) { + fprintf(stderr, "Failed to read from:%s\n", + POWER_FLOOR_STATUS_ATTRIBUTE); + exit(1); + } + + ufd.fd = fd; + ufd.events = POLLPRI; + + ret = poll(&ufd, 1, -1); + if (ret < 0) { + perror("poll error"); + exit(1); + } else if (ret == 0) { + printf("Poll Timeout\n"); + } else { + if ((lseek(fd, 0L, SEEK_SET)) < 0) { + fprintf(stderr, "Failed to set pointer to beginning\n"); + exit(1); + } + + if (read(fd, status_str, sizeof(status_str)) < 0) + exit(0); + + printf("power floor status: %s\n", status_str); + } + + close(fd); + } +} -- cgit v1.2.3 From de84da588f35423c5c2e6a46f2bc8a07f8eaf793 Mon Sep 17 00:00:00 2001 From: Kuan-Wei Chiu Date: Wed, 27 Sep 2023 01:37:36 +0800 Subject: tools/thermal: Remove unused 'mds' and 'nrhandler' variables In the previous code, the 'mds' and 'nrhandler' variables were not utilized in the codebase. Additionally, there was a potential NULL pointer dereference and memory leak due to improper handling of memory reallocation failure. This patch removes the unused 'mds' and 'nrhandler' variables along with the associated code, addressing the unused variable issue, NULL pointer dereference issue and the memory leak issue. Signed-off-by: Kuan-Wei Chiu Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230926173736.1142420-1-visitorckw@gmail.com --- tools/thermal/lib/mainloop.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'tools') diff --git a/tools/thermal/lib/mainloop.c b/tools/thermal/lib/mainloop.c index 94cbbcbd1c14..bf4c1b730d7b 100644 --- a/tools/thermal/lib/mainloop.c +++ b/tools/thermal/lib/mainloop.c @@ -9,7 +9,6 @@ #include "log.h" static int epfd = -1; -static unsigned short nrhandler; static sig_atomic_t exit_mainloop; struct mainloop_data { @@ -18,8 +17,6 @@ struct mainloop_data { int fd; }; -static struct mainloop_data **mds; - #define MAX_EVENTS 10 int mainloop(unsigned int timeout) @@ -61,13 +58,6 @@ int mainloop_add(int fd, mainloop_callback_t cb, void *data) struct mainloop_data *md; - if (fd >= nrhandler) { - mds = realloc(mds, sizeof(*mds) * (fd + 1)); - if (!mds) - return -1; - nrhandler = fd + 1; - } - md = malloc(sizeof(*md)); if (!md) return -1; @@ -76,7 +66,6 @@ int mainloop_add(int fd, mainloop_callback_t cb, void *data) md->cb = cb; md->fd = fd; - mds[fd] = md; ev.data.ptr = md; if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0) { @@ -89,14 +78,9 @@ int mainloop_add(int fd, mainloop_callback_t cb, void *data) int mainloop_del(int fd) { - if (fd >= nrhandler) - return -1; - if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) < 0) return -1; - free(mds[fd]); - return 0; } -- cgit v1.2.3