1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2020 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 #include "spdk/log.h" 8 #include "spdk/env.h" 9 #include "spdk/event.h" 10 #include "spdk/scheduler.h" 11 12 #include "spdk_internal/event.h" 13 14 #include <rte_power.h> 15 16 static uint32_t 17 _get_core_avail_freqs(uint32_t lcore_id, uint32_t *freqs, uint32_t num) 18 { 19 uint32_t rc; 20 21 rc = rte_power_freqs(lcore_id, freqs, num); 22 if (!rc) { 23 SPDK_ERRLOG("Unable to get current core frequency array for core %d\n.", lcore_id); 24 25 return 0; 26 } 27 28 return rc; 29 } 30 31 static uint32_t 32 _get_core_curr_freq(uint32_t lcore_id) 33 { 34 uint32_t freqs[SPDK_MAX_LCORE_FREQS]; 35 uint32_t freq_index; 36 int rc; 37 38 rc = rte_power_freqs(lcore_id, freqs, SPDK_MAX_LCORE_FREQS); 39 if (!rc) { 40 SPDK_ERRLOG("Unable to get current core frequency array for core %d\n.", lcore_id); 41 42 return 0; 43 } 44 freq_index = rte_power_get_freq(lcore_id); 45 if (freq_index >= SPDK_MAX_LCORE_FREQS) { 46 SPDK_ERRLOG("Unable to get current core frequency for core %d\n.", lcore_id); 47 48 return 0; 49 } 50 51 return freqs[freq_index]; 52 } 53 54 static int 55 _core_freq_up(uint32_t lcore_id) 56 { 57 return rte_power_freq_up(lcore_id); 58 } 59 60 static int 61 _core_freq_down(uint32_t lcore_id) 62 { 63 return rte_power_freq_down(lcore_id); 64 } 65 66 static int 67 _set_core_freq_max(uint32_t lcore_id) 68 { 69 return rte_power_freq_max(lcore_id); 70 } 71 72 static int 73 _set_core_freq_min(uint32_t lcore_id) 74 { 75 return rte_power_freq_min(lcore_id); 76 } 77 78 static int 79 _get_core_capabilities(uint32_t lcore_id, struct spdk_governor_capabilities *capabilities) 80 { 81 struct rte_power_core_capabilities caps; 82 int rc; 83 84 rc = rte_power_get_capabilities(lcore_id, &caps); 85 if (rc != 0) { 86 return rc; 87 } 88 89 capabilities->priority = caps.priority == 0 ? false : true; 90 91 return 0; 92 } 93 94 static int 95 _dump_info_json(struct spdk_json_write_ctx *w) 96 { 97 enum power_management_env env; 98 99 env = rte_power_get_env(); 100 101 if (env == PM_ENV_ACPI_CPUFREQ) { 102 spdk_json_write_named_string(w, "env", "acpi-cpufreq"); 103 } else if (env == PM_ENV_KVM_VM) { 104 spdk_json_write_named_string(w, "env", "kvm"); 105 } else if (env == PM_ENV_PSTATE_CPUFREQ) { 106 spdk_json_write_named_string(w, "env", "intel-pstate"); 107 } else if (env == PM_ENV_CPPC_CPUFREQ) { 108 spdk_json_write_named_string(w, "env", "cppc-cpufreq"); 109 } else if (env == PM_ENV_AMD_PSTATE_CPUFREQ) { 110 spdk_json_write_named_string(w, "env", "amd-pstate"); 111 } else { 112 spdk_json_write_named_string(w, "env", "unknown"); 113 return -EINVAL; 114 } 115 116 return 0; 117 } 118 119 static int 120 _init_core(uint32_t lcore_id) 121 { 122 struct rte_power_core_capabilities caps; 123 int rc; 124 125 rc = rte_power_init(lcore_id); 126 if (rc != 0) { 127 SPDK_ERRLOG("Failed to initialize on core%d\n", lcore_id); 128 return rc; 129 } 130 131 rc = rte_power_get_capabilities(lcore_id, &caps); 132 if (rc != 0) { 133 SPDK_ERRLOG("Failed retrieve capabilities of core%d\n", lcore_id); 134 return rc; 135 } 136 137 if (caps.turbo) { 138 rc = rte_power_freq_enable_turbo(lcore_id); 139 if (rc != 0) { 140 SPDK_ERRLOG("Failed to set turbo on core%d\n", lcore_id); 141 return rc; 142 } 143 } 144 145 return rc; 146 } 147 148 static int 149 _init(void) 150 { 151 uint32_t i, j; 152 int rc = 0; 153 154 SPDK_ENV_FOREACH_CORE(i) { 155 rc = _init_core(i); 156 if (rc != 0) { 157 SPDK_ERRLOG("Failed to initialize on core%d\n", i); 158 break; 159 } 160 } 161 162 if (rc == 0) { 163 return rc; 164 } 165 166 /* When initialization of a core failed, deinitialize prior cores. */ 167 SPDK_ENV_FOREACH_CORE(j) { 168 if (j >= i) { 169 break; 170 } 171 if (rte_power_exit(j) != 0) { 172 SPDK_ERRLOG("Failed to deinitialize on core%d\n", j); 173 } 174 } 175 return rc; 176 } 177 178 static void 179 _deinit(void) 180 { 181 uint32_t i; 182 183 SPDK_ENV_FOREACH_CORE(i) { 184 if (rte_power_exit(i) != 0) { 185 SPDK_ERRLOG("Failed to deinitialize on core%d\n", i); 186 } 187 } 188 } 189 190 static struct spdk_governor dpdk_governor = { 191 .name = "dpdk_governor", 192 .get_core_avail_freqs = _get_core_avail_freqs, 193 .get_core_curr_freq = _get_core_curr_freq, 194 .core_freq_up = _core_freq_up, 195 .core_freq_down = _core_freq_down, 196 .set_core_freq_max = _set_core_freq_max, 197 .set_core_freq_min = _set_core_freq_min, 198 .get_core_capabilities = _get_core_capabilities, 199 .dump_info_json = _dump_info_json, 200 .init = _init, 201 .deinit = _deinit, 202 }; 203 204 SPDK_GOVERNOR_REGISTER(dpdk_governor); 205