98eaba9154552327f3d8902ccc591d26d8c74db0
[dpdk.git] / lib / power / rte_power.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #include <rte_errno.h>
6 #include <rte_spinlock.h>
7
8 #include "rte_power.h"
9 #include "power_acpi_cpufreq.h"
10 #include "power_kvm_vm.h"
11 #include "power_pstate_cpufreq.h"
12 #include "power_common.h"
13
14 enum power_management_env global_default_env = PM_ENV_NOT_SET;
15
16 static rte_spinlock_t global_env_cfg_lock = RTE_SPINLOCK_INITIALIZER;
17
18 /* function pointers */
19 rte_power_freqs_t rte_power_freqs  = NULL;
20 rte_power_get_freq_t rte_power_get_freq = NULL;
21 rte_power_set_freq_t rte_power_set_freq = NULL;
22 rte_power_freq_change_t rte_power_freq_up = NULL;
23 rte_power_freq_change_t rte_power_freq_down = NULL;
24 rte_power_freq_change_t rte_power_freq_max = NULL;
25 rte_power_freq_change_t rte_power_freq_min = NULL;
26 rte_power_freq_change_t rte_power_turbo_status;
27 rte_power_freq_change_t rte_power_freq_enable_turbo;
28 rte_power_freq_change_t rte_power_freq_disable_turbo;
29 rte_power_get_capabilities_t rte_power_get_capabilities;
30
31 static void
32 reset_power_function_ptrs(void)
33 {
34         rte_power_freqs  = NULL;
35         rte_power_get_freq = NULL;
36         rte_power_set_freq = NULL;
37         rte_power_freq_up = NULL;
38         rte_power_freq_down = NULL;
39         rte_power_freq_max = NULL;
40         rte_power_freq_min = NULL;
41         rte_power_turbo_status = NULL;
42         rte_power_freq_enable_turbo = NULL;
43         rte_power_freq_disable_turbo = NULL;
44         rte_power_get_capabilities = NULL;
45 }
46
47 int
48 rte_power_check_env_supported(enum power_management_env env)
49 {
50         switch (env) {
51         case PM_ENV_ACPI_CPUFREQ:
52                 return power_acpi_cpufreq_check_supported();
53         case PM_ENV_PSTATE_CPUFREQ:
54                 return power_pstate_cpufreq_check_supported();
55         case PM_ENV_KVM_VM:
56                 return power_kvm_vm_check_supported();
57         default:
58                 rte_errno = EINVAL;
59                 return -1;
60         }
61 }
62
63 int
64 rte_power_set_env(enum power_management_env env)
65 {
66         rte_spinlock_lock(&global_env_cfg_lock);
67
68         if (global_default_env != PM_ENV_NOT_SET) {
69                 RTE_LOG(ERR, POWER, "Power Management Environment already set.\n");
70                 rte_spinlock_unlock(&global_env_cfg_lock);
71                 return -1;
72         }
73
74         int ret = 0;
75
76         if (env == PM_ENV_ACPI_CPUFREQ) {
77                 rte_power_freqs = power_acpi_cpufreq_freqs;
78                 rte_power_get_freq = power_acpi_cpufreq_get_freq;
79                 rte_power_set_freq = power_acpi_cpufreq_set_freq;
80                 rte_power_freq_up = power_acpi_cpufreq_freq_up;
81                 rte_power_freq_down = power_acpi_cpufreq_freq_down;
82                 rte_power_freq_min = power_acpi_cpufreq_freq_min;
83                 rte_power_freq_max = power_acpi_cpufreq_freq_max;
84                 rte_power_turbo_status = power_acpi_turbo_status;
85                 rte_power_freq_enable_turbo = power_acpi_enable_turbo;
86                 rte_power_freq_disable_turbo = power_acpi_disable_turbo;
87                 rte_power_get_capabilities = power_acpi_get_capabilities;
88         } else if (env == PM_ENV_KVM_VM) {
89                 rte_power_freqs = power_kvm_vm_freqs;
90                 rte_power_get_freq = power_kvm_vm_get_freq;
91                 rte_power_set_freq = power_kvm_vm_set_freq;
92                 rte_power_freq_up = power_kvm_vm_freq_up;
93                 rte_power_freq_down = power_kvm_vm_freq_down;
94                 rte_power_freq_min = power_kvm_vm_freq_min;
95                 rte_power_freq_max = power_kvm_vm_freq_max;
96                 rte_power_turbo_status = power_kvm_vm_turbo_status;
97                 rte_power_freq_enable_turbo = power_kvm_vm_enable_turbo;
98                 rte_power_freq_disable_turbo = power_kvm_vm_disable_turbo;
99                 rte_power_get_capabilities = power_kvm_vm_get_capabilities;
100         } else if (env == PM_ENV_PSTATE_CPUFREQ) {
101                 rte_power_freqs = power_pstate_cpufreq_freqs;
102                 rte_power_get_freq = power_pstate_cpufreq_get_freq;
103                 rte_power_set_freq = power_pstate_cpufreq_set_freq;
104                 rte_power_freq_up = power_pstate_cpufreq_freq_up;
105                 rte_power_freq_down = power_pstate_cpufreq_freq_down;
106                 rte_power_freq_min = power_pstate_cpufreq_freq_min;
107                 rte_power_freq_max = power_pstate_cpufreq_freq_max;
108                 rte_power_turbo_status = power_pstate_turbo_status;
109                 rte_power_freq_enable_turbo = power_pstate_enable_turbo;
110                 rte_power_freq_disable_turbo = power_pstate_disable_turbo;
111                 rte_power_get_capabilities = power_pstate_get_capabilities;
112
113         } else {
114                 RTE_LOG(ERR, POWER, "Invalid Power Management Environment(%d) set\n",
115                                 env);
116                 ret = -1;
117         }
118
119         if (ret == 0)
120                 global_default_env = env;
121         else {
122                 global_default_env = PM_ENV_NOT_SET;
123                 reset_power_function_ptrs();
124         }
125
126         rte_spinlock_unlock(&global_env_cfg_lock);
127         return ret;
128 }
129
130 void
131 rte_power_unset_env(void)
132 {
133         rte_spinlock_lock(&global_env_cfg_lock);
134         global_default_env = PM_ENV_NOT_SET;
135         reset_power_function_ptrs();
136         rte_spinlock_unlock(&global_env_cfg_lock);
137 }
138
139 enum power_management_env
140 rte_power_get_env(void) {
141         return global_default_env;
142 }
143
144 int
145 rte_power_init(unsigned int lcore_id)
146 {
147         int ret = -1;
148
149         switch (global_default_env) {
150         case PM_ENV_ACPI_CPUFREQ:
151                 return power_acpi_cpufreq_init(lcore_id);
152         case PM_ENV_KVM_VM:
153                 return power_kvm_vm_init(lcore_id);
154         case PM_ENV_PSTATE_CPUFREQ:
155                 return power_pstate_cpufreq_init(lcore_id);
156         default:
157                 RTE_LOG(INFO, POWER, "Env isn't set yet!\n");
158         }
159
160         /* Auto detect Environment */
161         RTE_LOG(INFO, POWER, "Attempting to initialise ACPI cpufreq power management...\n");
162         ret = power_acpi_cpufreq_init(lcore_id);
163         if (ret == 0) {
164                 rte_power_set_env(PM_ENV_ACPI_CPUFREQ);
165                 goto out;
166         }
167
168         RTE_LOG(INFO, POWER, "Attempting to initialise PSTAT power management...\n");
169         ret = power_pstate_cpufreq_init(lcore_id);
170         if (ret == 0) {
171                 rte_power_set_env(PM_ENV_PSTATE_CPUFREQ);
172                 goto out;
173         }
174
175         RTE_LOG(INFO, POWER, "Attempting to initialise VM power management...\n");
176         ret = power_kvm_vm_init(lcore_id);
177         if (ret == 0) {
178                 rte_power_set_env(PM_ENV_KVM_VM);
179                 goto out;
180         }
181         RTE_LOG(ERR, POWER, "Unable to set Power Management Environment for lcore "
182                         "%u\n", lcore_id);
183 out:
184         return ret;
185 }
186
187 int
188 rte_power_exit(unsigned int lcore_id)
189 {
190         switch (global_default_env) {
191         case PM_ENV_ACPI_CPUFREQ:
192                 return power_acpi_cpufreq_exit(lcore_id);
193         case PM_ENV_KVM_VM:
194                 return power_kvm_vm_exit(lcore_id);
195         case PM_ENV_PSTATE_CPUFREQ:
196                 return power_pstate_cpufreq_exit(lcore_id);
197         default:
198                 RTE_LOG(ERR, POWER, "Environment has not been set, unable to exit gracefully\n");
199
200         }
201         return -1;
202
203 }