1*dd6fd75bSHuisong Li /* SPDX-License-Identifier: BSD-3-Clause 2*dd6fd75bSHuisong Li * Copyright(c) 2024 HiSilicon Limited 3*dd6fd75bSHuisong Li */ 4*dd6fd75bSHuisong Li 5*dd6fd75bSHuisong Li #include <errno.h> 6*dd6fd75bSHuisong Li #include <stdlib.h> 7*dd6fd75bSHuisong Li #include <string.h> 8*dd6fd75bSHuisong Li 9*dd6fd75bSHuisong Li #include <rte_lcore.h> 10*dd6fd75bSHuisong Li #include <rte_log.h> 11*dd6fd75bSHuisong Li 12*dd6fd75bSHuisong Li #include "power_common.h" 13*dd6fd75bSHuisong Li #include "rte_power_qos.h" 14*dd6fd75bSHuisong Li 15*dd6fd75bSHuisong Li #define PM_QOS_SYSFILE_RESUME_LATENCY_US \ 16*dd6fd75bSHuisong Li "/sys/devices/system/cpu/cpu%u/power/pm_qos_resume_latency_us" 17*dd6fd75bSHuisong Li 18*dd6fd75bSHuisong Li #define PM_QOS_CPU_RESUME_LATENCY_BUF_LEN 32 19*dd6fd75bSHuisong Li 20*dd6fd75bSHuisong Li int 21*dd6fd75bSHuisong Li rte_power_qos_set_cpu_resume_latency(uint16_t lcore_id, int latency) 22*dd6fd75bSHuisong Li { 23*dd6fd75bSHuisong Li char buf[PM_QOS_CPU_RESUME_LATENCY_BUF_LEN]; 24*dd6fd75bSHuisong Li uint32_t cpu_id; 25*dd6fd75bSHuisong Li FILE *f; 26*dd6fd75bSHuisong Li int ret; 27*dd6fd75bSHuisong Li 28*dd6fd75bSHuisong Li if (!rte_lcore_is_enabled(lcore_id)) { 29*dd6fd75bSHuisong Li POWER_LOG(ERR, "lcore id %u is not enabled", lcore_id); 30*dd6fd75bSHuisong Li return -EINVAL; 31*dd6fd75bSHuisong Li } 32*dd6fd75bSHuisong Li ret = power_get_lcore_mapped_cpu_id(lcore_id, &cpu_id); 33*dd6fd75bSHuisong Li if (ret != 0) 34*dd6fd75bSHuisong Li return ret; 35*dd6fd75bSHuisong Li 36*dd6fd75bSHuisong Li if (latency < 0) { 37*dd6fd75bSHuisong Li POWER_LOG(ERR, "latency should be greater than and equal to 0"); 38*dd6fd75bSHuisong Li return -EINVAL; 39*dd6fd75bSHuisong Li } 40*dd6fd75bSHuisong Li 41*dd6fd75bSHuisong Li ret = open_core_sysfs_file(&f, "w", PM_QOS_SYSFILE_RESUME_LATENCY_US, cpu_id); 42*dd6fd75bSHuisong Li if (ret != 0) { 43*dd6fd75bSHuisong Li POWER_LOG(ERR, "Failed to open "PM_QOS_SYSFILE_RESUME_LATENCY_US" : %s", 44*dd6fd75bSHuisong Li cpu_id, strerror(errno)); 45*dd6fd75bSHuisong Li return ret; 46*dd6fd75bSHuisong Li } 47*dd6fd75bSHuisong Li 48*dd6fd75bSHuisong Li /* 49*dd6fd75bSHuisong Li * Based on the sysfs interface pm_qos_resume_latency_us under 50*dd6fd75bSHuisong Li * @PM_QOS_SYSFILE_RESUME_LATENCY_US directory in kernel, their meaning 51*dd6fd75bSHuisong Li * is as follows for different input string. 52*dd6fd75bSHuisong Li * 1> the resume latency is 0 if the input is "n/a". 53*dd6fd75bSHuisong Li * 2> the resume latency is no constraint if the input is "0". 54*dd6fd75bSHuisong Li * 3> the resume latency is the actual value to be set. 55*dd6fd75bSHuisong Li */ 56*dd6fd75bSHuisong Li if (latency == RTE_POWER_QOS_STRICT_LATENCY_VALUE) 57*dd6fd75bSHuisong Li snprintf(buf, sizeof(buf), "%s", "n/a"); 58*dd6fd75bSHuisong Li else if (latency == RTE_POWER_QOS_RESUME_LATENCY_NO_CONSTRAINT) 59*dd6fd75bSHuisong Li snprintf(buf, sizeof(buf), "%u", 0); 60*dd6fd75bSHuisong Li else 61*dd6fd75bSHuisong Li snprintf(buf, sizeof(buf), "%u", latency); 62*dd6fd75bSHuisong Li 63*dd6fd75bSHuisong Li ret = write_core_sysfs_s(f, buf); 64*dd6fd75bSHuisong Li if (ret != 0) 65*dd6fd75bSHuisong Li POWER_LOG(ERR, "Failed to write "PM_QOS_SYSFILE_RESUME_LATENCY_US" : %s", 66*dd6fd75bSHuisong Li cpu_id, strerror(errno)); 67*dd6fd75bSHuisong Li 68*dd6fd75bSHuisong Li fclose(f); 69*dd6fd75bSHuisong Li 70*dd6fd75bSHuisong Li return ret; 71*dd6fd75bSHuisong Li } 72*dd6fd75bSHuisong Li 73*dd6fd75bSHuisong Li int 74*dd6fd75bSHuisong Li rte_power_qos_get_cpu_resume_latency(uint16_t lcore_id) 75*dd6fd75bSHuisong Li { 76*dd6fd75bSHuisong Li char buf[PM_QOS_CPU_RESUME_LATENCY_BUF_LEN]; 77*dd6fd75bSHuisong Li int latency = -1; 78*dd6fd75bSHuisong Li uint32_t cpu_id; 79*dd6fd75bSHuisong Li FILE *f; 80*dd6fd75bSHuisong Li int ret; 81*dd6fd75bSHuisong Li 82*dd6fd75bSHuisong Li if (!rte_lcore_is_enabled(lcore_id)) { 83*dd6fd75bSHuisong Li POWER_LOG(ERR, "lcore id %u is not enabled", lcore_id); 84*dd6fd75bSHuisong Li return -EINVAL; 85*dd6fd75bSHuisong Li } 86*dd6fd75bSHuisong Li ret = power_get_lcore_mapped_cpu_id(lcore_id, &cpu_id); 87*dd6fd75bSHuisong Li if (ret != 0) 88*dd6fd75bSHuisong Li return ret; 89*dd6fd75bSHuisong Li 90*dd6fd75bSHuisong Li ret = open_core_sysfs_file(&f, "r", PM_QOS_SYSFILE_RESUME_LATENCY_US, cpu_id); 91*dd6fd75bSHuisong Li if (ret != 0) { 92*dd6fd75bSHuisong Li POWER_LOG(ERR, "Failed to open "PM_QOS_SYSFILE_RESUME_LATENCY_US" : %s", 93*dd6fd75bSHuisong Li cpu_id, strerror(errno)); 94*dd6fd75bSHuisong Li return ret; 95*dd6fd75bSHuisong Li } 96*dd6fd75bSHuisong Li 97*dd6fd75bSHuisong Li ret = read_core_sysfs_s(f, buf, sizeof(buf)); 98*dd6fd75bSHuisong Li if (ret != 0) { 99*dd6fd75bSHuisong Li POWER_LOG(ERR, "Failed to read "PM_QOS_SYSFILE_RESUME_LATENCY_US" : %s", 100*dd6fd75bSHuisong Li cpu_id, strerror(errno)); 101*dd6fd75bSHuisong Li goto out; 102*dd6fd75bSHuisong Li } 103*dd6fd75bSHuisong Li 104*dd6fd75bSHuisong Li /* 105*dd6fd75bSHuisong Li * Based on the sysfs interface pm_qos_resume_latency_us under 106*dd6fd75bSHuisong Li * @PM_QOS_SYSFILE_RESUME_LATENCY_US directory in kernel, their meaning 107*dd6fd75bSHuisong Li * is as follows for different output string. 108*dd6fd75bSHuisong Li * 1> the resume latency is 0 if the output is "n/a". 109*dd6fd75bSHuisong Li * 2> the resume latency is no constraint if the output is "0". 110*dd6fd75bSHuisong Li * 3> the resume latency is the actual value in used for other string. 111*dd6fd75bSHuisong Li */ 112*dd6fd75bSHuisong Li if (strcmp(buf, "n/a") == 0) 113*dd6fd75bSHuisong Li latency = RTE_POWER_QOS_STRICT_LATENCY_VALUE; 114*dd6fd75bSHuisong Li else { 115*dd6fd75bSHuisong Li latency = strtoul(buf, NULL, 10); 116*dd6fd75bSHuisong Li latency = latency == 0 ? RTE_POWER_QOS_RESUME_LATENCY_NO_CONSTRAINT : latency; 117*dd6fd75bSHuisong Li } 118*dd6fd75bSHuisong Li 119*dd6fd75bSHuisong Li out: 120*dd6fd75bSHuisong Li fclose(f); 121*dd6fd75bSHuisong Li 122*dd6fd75bSHuisong Li return latency != -1 ? latency : ret; 123*dd6fd75bSHuisong Li } 124