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_curr_freq(uint32_t lcore_id) 18 { 19 const uint32_t MAX_CORE_FREQ_NUM = 64; 20 uint32_t freqs[MAX_CORE_FREQ_NUM]; 21 uint32_t freq_index; 22 int rc; 23 24 rc = rte_power_freqs(lcore_id, freqs, MAX_CORE_FREQ_NUM); 25 if (!rc) { 26 SPDK_ERRLOG("Unable to get current core frequency array for core %d\n.", lcore_id); 27 28 return 0; 29 } 30 freq_index = rte_power_get_freq(lcore_id); 31 if (freq_index >= MAX_CORE_FREQ_NUM) { 32 SPDK_ERRLOG("Unable to get current core frequency for core %d\n.", lcore_id); 33 34 return 0; 35 } 36 37 return freqs[freq_index]; 38 } 39 40 static int 41 _core_freq_up(uint32_t lcore_id) 42 { 43 return rte_power_freq_up(lcore_id); 44 } 45 46 static int 47 _core_freq_down(uint32_t lcore_id) 48 { 49 return rte_power_freq_down(lcore_id); 50 } 51 52 static int 53 _set_core_freq_max(uint32_t lcore_id) 54 { 55 return rte_power_freq_max(lcore_id); 56 } 57 58 static int 59 _set_core_freq_min(uint32_t lcore_id) 60 { 61 return rte_power_freq_min(lcore_id); 62 } 63 64 static int 65 _get_core_capabilities(uint32_t lcore_id, struct spdk_governor_capabilities *capabilities) 66 { 67 struct rte_power_core_capabilities caps; 68 int rc; 69 70 rc = rte_power_get_capabilities(lcore_id, &caps); 71 if (rc != 0) { 72 return rc; 73 } 74 75 capabilities->priority = caps.priority == 0 ? false : true; 76 77 return 0; 78 } 79 80 static int 81 _init_core(uint32_t lcore_id) 82 { 83 struct rte_power_core_capabilities caps; 84 int rc; 85 86 rc = rte_power_init(lcore_id); 87 if (rc != 0) { 88 SPDK_ERRLOG("Failed to initialize on core%d\n", lcore_id); 89 return rc; 90 } 91 92 rc = rte_power_get_capabilities(lcore_id, &caps); 93 if (rc != 0) { 94 SPDK_ERRLOG("Failed retrieve capabilities of core%d\n", lcore_id); 95 return rc; 96 } 97 98 if (caps.turbo) { 99 rc = rte_power_freq_enable_turbo(lcore_id); 100 if (rc != 0) { 101 SPDK_ERRLOG("Failed to set turbo on core%d\n", lcore_id); 102 return rc; 103 } 104 } 105 106 return rc; 107 } 108 109 static int 110 _init(void) 111 { 112 uint32_t i, j; 113 int rc = 0; 114 115 SPDK_ENV_FOREACH_CORE(i) { 116 rc = _init_core(i); 117 if (rc != 0) { 118 SPDK_ERRLOG("Failed to initialize on core%d\n", i); 119 break; 120 } 121 } 122 123 if (rc == 0) { 124 return rc; 125 } 126 127 /* When initialization of a core failed, deinitialize prior cores. */ 128 SPDK_ENV_FOREACH_CORE(j) { 129 if (j >= i) { 130 break; 131 } 132 if (rte_power_exit(j) != 0) { 133 SPDK_ERRLOG("Failed to deinitialize on core%d\n", j); 134 } 135 } 136 return rc; 137 } 138 139 static void 140 _deinit(void) 141 { 142 uint32_t i; 143 144 SPDK_ENV_FOREACH_CORE(i) { 145 if (rte_power_exit(i) != 0) { 146 SPDK_ERRLOG("Failed to deinitialize on core%d\n", i); 147 } 148 } 149 } 150 151 static struct spdk_governor dpdk_governor = { 152 .name = "dpdk_governor", 153 .get_core_curr_freq = _get_core_curr_freq, 154 .core_freq_up = _core_freq_up, 155 .core_freq_down = _core_freq_down, 156 .set_core_freq_max = _set_core_freq_max, 157 .set_core_freq_min = _set_core_freq_min, 158 .get_core_capabilities = _get_core_capabilities, 159 .init = _init, 160 .deinit = _deinit, 161 }; 162 163 SPDK_GOVERNOR_REGISTER(dpdk_governor); 164