1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 * Copyright(c) 2023 AMD Corporation 4 */ 5 6 #include <errno.h> 7 8 #include <rte_errno.h> 9 #include <rte_spinlock.h> 10 11 #include "power_common.h" 12 #include "rte_power_uncore.h" 13 #include "power_intel_uncore.h" 14 15 enum rte_uncore_power_mgmt_env default_uncore_env = RTE_UNCORE_PM_ENV_NOT_SET; 16 17 static rte_spinlock_t global_env_cfg_lock = RTE_SPINLOCK_INITIALIZER; 18 19 static uint32_t 20 power_get_dummy_uncore_freq(unsigned int pkg __rte_unused, 21 unsigned int die __rte_unused) 22 { 23 return 0; 24 } 25 26 static int 27 power_set_dummy_uncore_freq(unsigned int pkg __rte_unused, 28 unsigned int die __rte_unused, uint32_t index __rte_unused) 29 { 30 return 0; 31 } 32 33 static int 34 power_dummy_uncore_freq_max(unsigned int pkg __rte_unused, 35 unsigned int die __rte_unused) 36 { 37 return 0; 38 } 39 40 static int 41 power_dummy_uncore_freq_min(unsigned int pkg __rte_unused, 42 unsigned int die __rte_unused) 43 { 44 return 0; 45 } 46 47 static int 48 power_dummy_uncore_freqs(unsigned int pkg __rte_unused, unsigned int die __rte_unused, 49 uint32_t *freqs __rte_unused, uint32_t num __rte_unused) 50 { 51 return 0; 52 } 53 54 static int 55 power_dummy_uncore_get_num_freqs(unsigned int pkg __rte_unused, 56 unsigned int die __rte_unused) 57 { 58 return 0; 59 } 60 61 static unsigned int 62 power_dummy_uncore_get_num_pkgs(void) 63 { 64 return 0; 65 } 66 67 static unsigned int 68 power_dummy_uncore_get_num_dies(unsigned int pkg __rte_unused) 69 { 70 return 0; 71 } 72 73 /* function pointers */ 74 rte_power_get_uncore_freq_t rte_power_get_uncore_freq = power_get_dummy_uncore_freq; 75 rte_power_set_uncore_freq_t rte_power_set_uncore_freq = power_set_dummy_uncore_freq; 76 rte_power_uncore_freq_change_t rte_power_uncore_freq_max = power_dummy_uncore_freq_max; 77 rte_power_uncore_freq_change_t rte_power_uncore_freq_min = power_dummy_uncore_freq_min; 78 rte_power_uncore_freqs_t rte_power_uncore_freqs = power_dummy_uncore_freqs; 79 rte_power_uncore_get_num_freqs_t rte_power_uncore_get_num_freqs = power_dummy_uncore_get_num_freqs; 80 rte_power_uncore_get_num_pkgs_t rte_power_uncore_get_num_pkgs = power_dummy_uncore_get_num_pkgs; 81 rte_power_uncore_get_num_dies_t rte_power_uncore_get_num_dies = power_dummy_uncore_get_num_dies; 82 83 static void 84 reset_power_uncore_function_ptrs(void) 85 { 86 rte_power_get_uncore_freq = power_get_dummy_uncore_freq; 87 rte_power_set_uncore_freq = power_set_dummy_uncore_freq; 88 rte_power_uncore_freq_max = power_dummy_uncore_freq_max; 89 rte_power_uncore_freq_min = power_dummy_uncore_freq_min; 90 rte_power_uncore_freqs = power_dummy_uncore_freqs; 91 rte_power_uncore_get_num_freqs = power_dummy_uncore_get_num_freqs; 92 rte_power_uncore_get_num_pkgs = power_dummy_uncore_get_num_pkgs; 93 rte_power_uncore_get_num_dies = power_dummy_uncore_get_num_dies; 94 } 95 96 int 97 rte_power_set_uncore_env(enum rte_uncore_power_mgmt_env env) 98 { 99 int ret; 100 101 rte_spinlock_lock(&global_env_cfg_lock); 102 103 if (default_uncore_env != RTE_UNCORE_PM_ENV_NOT_SET) { 104 POWER_LOG(ERR, "Uncore Power Management Env already set."); 105 rte_spinlock_unlock(&global_env_cfg_lock); 106 return -1; 107 } 108 109 if (env == RTE_UNCORE_PM_ENV_AUTO_DETECT) 110 /* Currently only intel_uncore is supported. 111 * This will be extended with auto-detection support 112 * for multiple uncore implementations. 113 */ 114 env = RTE_UNCORE_PM_ENV_INTEL_UNCORE; 115 116 ret = 0; 117 if (env == RTE_UNCORE_PM_ENV_INTEL_UNCORE) { 118 rte_power_get_uncore_freq = power_get_intel_uncore_freq; 119 rte_power_set_uncore_freq = power_set_intel_uncore_freq; 120 rte_power_uncore_freq_min = power_intel_uncore_freq_min; 121 rte_power_uncore_freq_max = power_intel_uncore_freq_max; 122 rte_power_uncore_freqs = power_intel_uncore_freqs; 123 rte_power_uncore_get_num_freqs = power_intel_uncore_get_num_freqs; 124 rte_power_uncore_get_num_pkgs = power_intel_uncore_get_num_pkgs; 125 rte_power_uncore_get_num_dies = power_intel_uncore_get_num_dies; 126 } else { 127 POWER_LOG(ERR, "Invalid Power Management Environment(%d) set", env); 128 ret = -1; 129 goto out; 130 } 131 132 default_uncore_env = env; 133 out: 134 rte_spinlock_unlock(&global_env_cfg_lock); 135 return ret; 136 } 137 138 void 139 rte_power_unset_uncore_env(void) 140 { 141 rte_spinlock_lock(&global_env_cfg_lock); 142 default_uncore_env = RTE_UNCORE_PM_ENV_NOT_SET; 143 reset_power_uncore_function_ptrs(); 144 rte_spinlock_unlock(&global_env_cfg_lock); 145 } 146 147 enum rte_uncore_power_mgmt_env 148 rte_power_get_uncore_env(void) 149 { 150 return default_uncore_env; 151 } 152 153 int 154 rte_power_uncore_init(unsigned int pkg, unsigned int die) 155 { 156 int ret = -1; 157 158 switch (default_uncore_env) { 159 case RTE_UNCORE_PM_ENV_INTEL_UNCORE: 160 return power_intel_uncore_init(pkg, die); 161 default: 162 POWER_LOG(INFO, "Uncore Env isn't set yet!"); 163 break; 164 } 165 166 /* Auto detect Environment */ 167 POWER_LOG(INFO, "Attempting to initialise Intel Uncore power mgmt..."); 168 ret = power_intel_uncore_init(pkg, die); 169 if (ret == 0) { 170 rte_power_set_uncore_env(RTE_UNCORE_PM_ENV_INTEL_UNCORE); 171 goto out; 172 } 173 174 if (default_uncore_env == RTE_UNCORE_PM_ENV_NOT_SET) { 175 POWER_LOG(ERR, "Unable to set Power Management Environment " 176 "for package %u Die %u", pkg, die); 177 ret = 0; 178 } 179 out: 180 return ret; 181 } 182 183 int 184 rte_power_uncore_exit(unsigned int pkg, unsigned int die) 185 { 186 switch (default_uncore_env) { 187 case RTE_UNCORE_PM_ENV_INTEL_UNCORE: 188 return power_intel_uncore_exit(pkg, die); 189 default: 190 POWER_LOG(ERR, "Uncore Env has not been set, unable to exit gracefully"); 191 break; 192 } 193 return -1; 194 } 195