17fd786dfSSrinivas Pandruvada // SPDX-License-Identifier: GPL-2.0 27fd786dfSSrinivas Pandruvada /* 37fd786dfSSrinivas Pandruvada * Intel Speed Select -- Allow speed select to daemonize 47fd786dfSSrinivas Pandruvada * Copyright (c) 2022 Intel Corporation. 57fd786dfSSrinivas Pandruvada */ 67fd786dfSSrinivas Pandruvada 77fd786dfSSrinivas Pandruvada #include <stdio.h> 87fd786dfSSrinivas Pandruvada #include <stdlib.h> 97fd786dfSSrinivas Pandruvada #include <stdarg.h> 107fd786dfSSrinivas Pandruvada #include <string.h> 117fd786dfSSrinivas Pandruvada #include <unistd.h> 127fd786dfSSrinivas Pandruvada #include <fcntl.h> 137fd786dfSSrinivas Pandruvada #include <sys/file.h> 147fd786dfSSrinivas Pandruvada #include <sys/types.h> 157fd786dfSSrinivas Pandruvada #include <sys/stat.h> 167fd786dfSSrinivas Pandruvada #include <errno.h> 177fd786dfSSrinivas Pandruvada #include <getopt.h> 187fd786dfSSrinivas Pandruvada #include <signal.h> 197fd786dfSSrinivas Pandruvada #include <time.h> 207fd786dfSSrinivas Pandruvada 217fd786dfSSrinivas Pandruvada #include "isst.h" 227fd786dfSSrinivas Pandruvada 237fd786dfSSrinivas Pandruvada static int per_package_levels_info[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE]; 247fd786dfSSrinivas Pandruvada static time_t per_package_levels_tm[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE]; 257fd786dfSSrinivas Pandruvada 267fd786dfSSrinivas Pandruvada static void init_levels(void) 277fd786dfSSrinivas Pandruvada { 287fd786dfSSrinivas Pandruvada int i, j; 297fd786dfSSrinivas Pandruvada 307fd786dfSSrinivas Pandruvada for (i = 0; i < MAX_PACKAGE_COUNT; ++i) 317fd786dfSSrinivas Pandruvada for (j = 0; j < MAX_DIE_PER_PACKAGE; ++j) 327fd786dfSSrinivas Pandruvada per_package_levels_info[i][j] = -1; 337fd786dfSSrinivas Pandruvada } 347fd786dfSSrinivas Pandruvada 35*850337ecSZhang Rui void process_level_change(struct isst_id *id) 367fd786dfSSrinivas Pandruvada { 377fd786dfSSrinivas Pandruvada struct isst_pkg_ctdp_level_info ctdp_level; 38*850337ecSZhang Rui int pkg_id = get_physical_package_id(id->cpu); 39*850337ecSZhang Rui int die_id = get_physical_die_id(id->cpu); 407fd786dfSSrinivas Pandruvada struct isst_pkg_ctdp pkg_dev; 417fd786dfSSrinivas Pandruvada time_t tm; 427fd786dfSSrinivas Pandruvada int ret; 437fd786dfSSrinivas Pandruvada 44d9f74d98SDan Carpenter if (pkg_id >= MAX_PACKAGE_COUNT || die_id >= MAX_DIE_PER_PACKAGE) { 45*850337ecSZhang Rui debug_printf("Invalid package/die info for cpu:%d\n", id->cpu); 467fd786dfSSrinivas Pandruvada return; 477fd786dfSSrinivas Pandruvada } 487fd786dfSSrinivas Pandruvada 497fd786dfSSrinivas Pandruvada tm = time(NULL); 507fd786dfSSrinivas Pandruvada if (tm - per_package_levels_tm[pkg_id][die_id] < 2 ) 517fd786dfSSrinivas Pandruvada return; 527fd786dfSSrinivas Pandruvada 537fd786dfSSrinivas Pandruvada per_package_levels_tm[pkg_id][die_id] = tm; 547fd786dfSSrinivas Pandruvada 55*850337ecSZhang Rui ret = isst_get_ctdp_levels(id, &pkg_dev); 567fd786dfSSrinivas Pandruvada if (ret) { 57*850337ecSZhang Rui debug_printf("Can't get tdp levels for cpu:%d\n", id->cpu); 587fd786dfSSrinivas Pandruvada return; 597fd786dfSSrinivas Pandruvada } 607fd786dfSSrinivas Pandruvada 61*850337ecSZhang Rui debug_printf("Get Config level %d pkg:%d die:%d current_level:%d\n", id->cpu, 627fd786dfSSrinivas Pandruvada pkg_id, die_id, pkg_dev.current_level); 637fd786dfSSrinivas Pandruvada 647fd786dfSSrinivas Pandruvada if (pkg_dev.locked) { 657fd786dfSSrinivas Pandruvada debug_printf("config TDP s locked \n"); 667fd786dfSSrinivas Pandruvada return; 677fd786dfSSrinivas Pandruvada } 687fd786dfSSrinivas Pandruvada 697fd786dfSSrinivas Pandruvada if (per_package_levels_info[pkg_id][die_id] == pkg_dev.current_level) 707fd786dfSSrinivas Pandruvada return; 717fd786dfSSrinivas Pandruvada 727fd786dfSSrinivas Pandruvada debug_printf("**Config level change for cpu:%d pkg:%d die:%d from %d to %d\n", 73*850337ecSZhang Rui id->cpu, pkg_id, die_id, per_package_levels_info[pkg_id][die_id], 747fd786dfSSrinivas Pandruvada pkg_dev.current_level); 757fd786dfSSrinivas Pandruvada 767fd786dfSSrinivas Pandruvada per_package_levels_info[pkg_id][die_id] = pkg_dev.current_level; 777fd786dfSSrinivas Pandruvada 787fd786dfSSrinivas Pandruvada ctdp_level.core_cpumask_size = 797fd786dfSSrinivas Pandruvada alloc_cpu_set(&ctdp_level.core_cpumask); 80*850337ecSZhang Rui ret = isst_get_coremask_info(id, pkg_dev.current_level, &ctdp_level); 817fd786dfSSrinivas Pandruvada if (ret) { 827fd786dfSSrinivas Pandruvada free_cpu_set(ctdp_level.core_cpumask); 83*850337ecSZhang Rui debug_printf("Can't get core_mask:%d\n", id->cpu); 847fd786dfSSrinivas Pandruvada return; 857fd786dfSSrinivas Pandruvada } 867fd786dfSSrinivas Pandruvada 877fd786dfSSrinivas Pandruvada if (ctdp_level.cpu_count) { 887fd786dfSSrinivas Pandruvada int i, max_cpus = get_topo_max_cpus(); 897fd786dfSSrinivas Pandruvada for (i = 0; i < max_cpus; ++i) { 907fd786dfSSrinivas Pandruvada if (pkg_id != get_physical_package_id(i) || die_id != get_physical_die_id(i)) 917fd786dfSSrinivas Pandruvada continue; 927fd786dfSSrinivas Pandruvada if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) { 937fd786dfSSrinivas Pandruvada fprintf(stderr, "online cpu %d\n", i); 947fd786dfSSrinivas Pandruvada set_cpu_online_offline(i, 1); 957fd786dfSSrinivas Pandruvada } else { 967fd786dfSSrinivas Pandruvada fprintf(stderr, "offline cpu %d\n", i); 977fd786dfSSrinivas Pandruvada set_cpu_online_offline(i, 0); 987fd786dfSSrinivas Pandruvada } 997fd786dfSSrinivas Pandruvada } 1007fd786dfSSrinivas Pandruvada } 1017fd786dfSSrinivas Pandruvada 1027fd786dfSSrinivas Pandruvada free_cpu_set(ctdp_level.core_cpumask); 1037fd786dfSSrinivas Pandruvada } 1047fd786dfSSrinivas Pandruvada 105*850337ecSZhang Rui static void _poll_for_config_change(struct isst_id *id, void *arg1, void *arg2, 1067fd786dfSSrinivas Pandruvada void *arg3, void *arg4) 1077fd786dfSSrinivas Pandruvada { 108*850337ecSZhang Rui process_level_change(id); 1097fd786dfSSrinivas Pandruvada } 1107fd786dfSSrinivas Pandruvada 1117fd786dfSSrinivas Pandruvada static void poll_for_config_change(void) 1127fd786dfSSrinivas Pandruvada { 1137fd786dfSSrinivas Pandruvada for_each_online_package_in_set(_poll_for_config_change, NULL, NULL, 1147fd786dfSSrinivas Pandruvada NULL, NULL); 1157fd786dfSSrinivas Pandruvada } 1167fd786dfSSrinivas Pandruvada 1177fd786dfSSrinivas Pandruvada static int done = 0; 1187fd786dfSSrinivas Pandruvada static int pid_file_handle; 1197fd786dfSSrinivas Pandruvada 1207fd786dfSSrinivas Pandruvada static void signal_handler(int sig) 1217fd786dfSSrinivas Pandruvada { 1227fd786dfSSrinivas Pandruvada switch (sig) { 1237fd786dfSSrinivas Pandruvada case SIGINT: 1247fd786dfSSrinivas Pandruvada case SIGTERM: 1257fd786dfSSrinivas Pandruvada done = 1; 1267d440da0SSrinivas Pandruvada hfi_exit(); 1277fd786dfSSrinivas Pandruvada exit(0); 1287fd786dfSSrinivas Pandruvada break; 1297fd786dfSSrinivas Pandruvada default: 1307fd786dfSSrinivas Pandruvada break; 1317fd786dfSSrinivas Pandruvada } 1327fd786dfSSrinivas Pandruvada } 1337fd786dfSSrinivas Pandruvada 1347fd786dfSSrinivas Pandruvada static void daemonize(char *rundir, char *pidfile) 1357fd786dfSSrinivas Pandruvada { 1367fd786dfSSrinivas Pandruvada int pid, sid, i; 1377fd786dfSSrinivas Pandruvada char str[10]; 1387fd786dfSSrinivas Pandruvada struct sigaction sig_actions; 1397fd786dfSSrinivas Pandruvada sigset_t sig_set; 1407fd786dfSSrinivas Pandruvada int ret; 1417fd786dfSSrinivas Pandruvada 1427fd786dfSSrinivas Pandruvada if (getppid() == 1) 1437fd786dfSSrinivas Pandruvada return; 1447fd786dfSSrinivas Pandruvada 1457fd786dfSSrinivas Pandruvada sigemptyset(&sig_set); 1467fd786dfSSrinivas Pandruvada sigaddset(&sig_set, SIGCHLD); 1477fd786dfSSrinivas Pandruvada sigaddset(&sig_set, SIGTSTP); 1487fd786dfSSrinivas Pandruvada sigaddset(&sig_set, SIGTTOU); 1497fd786dfSSrinivas Pandruvada sigaddset(&sig_set, SIGTTIN); 1507fd786dfSSrinivas Pandruvada sigprocmask(SIG_BLOCK, &sig_set, NULL); 1517fd786dfSSrinivas Pandruvada 1527fd786dfSSrinivas Pandruvada sig_actions.sa_handler = signal_handler; 1537fd786dfSSrinivas Pandruvada sigemptyset(&sig_actions.sa_mask); 1547fd786dfSSrinivas Pandruvada sig_actions.sa_flags = 0; 1557fd786dfSSrinivas Pandruvada 1567fd786dfSSrinivas Pandruvada sigaction(SIGHUP, &sig_actions, NULL); 1577fd786dfSSrinivas Pandruvada sigaction(SIGTERM, &sig_actions, NULL); 1587fd786dfSSrinivas Pandruvada sigaction(SIGINT, &sig_actions, NULL); 1597fd786dfSSrinivas Pandruvada 1607fd786dfSSrinivas Pandruvada pid = fork(); 1617fd786dfSSrinivas Pandruvada if (pid < 0) { 1627fd786dfSSrinivas Pandruvada /* Could not fork */ 1637fd786dfSSrinivas Pandruvada exit(EXIT_FAILURE); 1647fd786dfSSrinivas Pandruvada } 1657fd786dfSSrinivas Pandruvada if (pid > 0) 1667fd786dfSSrinivas Pandruvada exit(EXIT_SUCCESS); 1677fd786dfSSrinivas Pandruvada 1687fd786dfSSrinivas Pandruvada umask(027); 1697fd786dfSSrinivas Pandruvada 1707fd786dfSSrinivas Pandruvada sid = setsid(); 1717fd786dfSSrinivas Pandruvada if (sid < 0) 1727fd786dfSSrinivas Pandruvada exit(EXIT_FAILURE); 1737fd786dfSSrinivas Pandruvada 1747fd786dfSSrinivas Pandruvada /* close all descriptors */ 1757fd786dfSSrinivas Pandruvada for (i = getdtablesize(); i >= 0; --i) 1767fd786dfSSrinivas Pandruvada close(i); 1777fd786dfSSrinivas Pandruvada 1787fd786dfSSrinivas Pandruvada i = open("/dev/null", O_RDWR); 1797fd786dfSSrinivas Pandruvada ret = dup(i); 1807fd786dfSSrinivas Pandruvada if (ret == -1) 1817fd786dfSSrinivas Pandruvada exit(EXIT_FAILURE); 1827fd786dfSSrinivas Pandruvada 1837fd786dfSSrinivas Pandruvada ret = dup(i); 1847fd786dfSSrinivas Pandruvada if (ret == -1) 1857fd786dfSSrinivas Pandruvada exit(EXIT_FAILURE); 1867fd786dfSSrinivas Pandruvada 1877fd786dfSSrinivas Pandruvada ret = chdir(rundir); 1887fd786dfSSrinivas Pandruvada if (ret == -1) 1897fd786dfSSrinivas Pandruvada exit(EXIT_FAILURE); 1907fd786dfSSrinivas Pandruvada 1917fd786dfSSrinivas Pandruvada pid_file_handle = open(pidfile, O_RDWR | O_CREAT, 0600); 1927fd786dfSSrinivas Pandruvada if (pid_file_handle == -1) { 1937fd786dfSSrinivas Pandruvada /* Couldn't open lock file */ 1947fd786dfSSrinivas Pandruvada exit(1); 1957fd786dfSSrinivas Pandruvada } 1967fd786dfSSrinivas Pandruvada /* Try to lock file */ 1977fd786dfSSrinivas Pandruvada #ifdef LOCKF_SUPPORT 1987fd786dfSSrinivas Pandruvada if (lockf(pid_file_handle, F_TLOCK, 0) == -1) { 1997fd786dfSSrinivas Pandruvada #else 2007fd786dfSSrinivas Pandruvada if (flock(pid_file_handle, LOCK_EX|LOCK_NB) < 0) { 2017fd786dfSSrinivas Pandruvada #endif 2027fd786dfSSrinivas Pandruvada /* Couldn't get lock on lock file */ 2037fd786dfSSrinivas Pandruvada fprintf(stderr, "Couldn't get lock file %d\n", getpid()); 2047fd786dfSSrinivas Pandruvada exit(1); 2057fd786dfSSrinivas Pandruvada } 2067fd786dfSSrinivas Pandruvada snprintf(str, sizeof(str), "%d\n", getpid()); 2077fd786dfSSrinivas Pandruvada ret = write(pid_file_handle, str, strlen(str)); 2087fd786dfSSrinivas Pandruvada if (ret == -1) 2097fd786dfSSrinivas Pandruvada exit(EXIT_FAILURE); 2107fd786dfSSrinivas Pandruvada 2117fd786dfSSrinivas Pandruvada close(i); 2127fd786dfSSrinivas Pandruvada } 2137fd786dfSSrinivas Pandruvada 2147fd786dfSSrinivas Pandruvada int isst_daemon(int debug_mode, int poll_interval, int no_daemon) 2157fd786dfSSrinivas Pandruvada { 2167fd786dfSSrinivas Pandruvada int ret; 2177fd786dfSSrinivas Pandruvada 2187fd786dfSSrinivas Pandruvada if (!no_daemon && poll_interval < 0 && !debug_mode) { 2197fd786dfSSrinivas Pandruvada fprintf(stderr, "OOB mode is enabled and will run as daemon\n"); 2207fd786dfSSrinivas Pandruvada daemonize((char *) "/tmp/", 2217fd786dfSSrinivas Pandruvada (char *)"/tmp/hfi-events.pid"); 2227fd786dfSSrinivas Pandruvada } else { 2237fd786dfSSrinivas Pandruvada signal(SIGINT, signal_handler); 2247fd786dfSSrinivas Pandruvada } 2257fd786dfSSrinivas Pandruvada 2267fd786dfSSrinivas Pandruvada init_levels(); 2277fd786dfSSrinivas Pandruvada 2287fd786dfSSrinivas Pandruvada if (poll_interval < 0) { 2297d440da0SSrinivas Pandruvada ret = hfi_main(); 2307d440da0SSrinivas Pandruvada if (ret) { 2317d440da0SSrinivas Pandruvada fprintf(stderr, "HFI initialization failed\n"); 2327d440da0SSrinivas Pandruvada } 2337fd786dfSSrinivas Pandruvada fprintf(stderr, "Must specify poll-interval\n"); 2347fd786dfSSrinivas Pandruvada return ret; 2357fd786dfSSrinivas Pandruvada } 2367fd786dfSSrinivas Pandruvada 2377fd786dfSSrinivas Pandruvada debug_printf("Starting loop\n"); 2387fd786dfSSrinivas Pandruvada while (!done) { 2397fd786dfSSrinivas Pandruvada sleep(poll_interval); 2407fd786dfSSrinivas Pandruvada poll_for_config_change(); 2417fd786dfSSrinivas Pandruvada } 2427fd786dfSSrinivas Pandruvada 2437fd786dfSSrinivas Pandruvada return 0; 2447fd786dfSSrinivas Pandruvada } 245