xref: /dpdk/lib/power/rte_power_qos.c (revision dd6fd75bf662e89edf2cda8f34c37e762e79c274)
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