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