1ac1edcb6SSivaprasad Tummala /* SPDX-License-Identifier: BSD-3-Clause 2ac1edcb6SSivaprasad Tummala * Copyright(c) 2010-2014 Intel Corporation 3ac1edcb6SSivaprasad Tummala * Copyright(c) 2023 AMD Corporation 4ac1edcb6SSivaprasad Tummala */ 5ac1edcb6SSivaprasad Tummala 6ac1edcb6SSivaprasad Tummala #include <rte_spinlock.h> 7*ebe99d35SSivaprasad Tummala #include <rte_debug.h> 8ac1edcb6SSivaprasad Tummala 9ac1edcb6SSivaprasad Tummala #include "rte_power_uncore.h" 10*ebe99d35SSivaprasad Tummala #include "power_common.h" 11ac1edcb6SSivaprasad Tummala 12*ebe99d35SSivaprasad Tummala static enum rte_uncore_power_mgmt_env global_uncore_env = RTE_UNCORE_PM_ENV_NOT_SET; 13*ebe99d35SSivaprasad Tummala static struct rte_power_uncore_ops *global_uncore_ops; 14ac1edcb6SSivaprasad Tummala 15ac1edcb6SSivaprasad Tummala static rte_spinlock_t global_env_cfg_lock = RTE_SPINLOCK_INITIALIZER; 16*ebe99d35SSivaprasad Tummala static RTE_TAILQ_HEAD(, rte_power_uncore_ops) uncore_ops_list = 17*ebe99d35SSivaprasad Tummala TAILQ_HEAD_INITIALIZER(uncore_ops_list); 18ac1edcb6SSivaprasad Tummala 19*ebe99d35SSivaprasad Tummala const char *uncore_env_str[] = { 20*ebe99d35SSivaprasad Tummala "not set", 21*ebe99d35SSivaprasad Tummala "auto-detect", 22*ebe99d35SSivaprasad Tummala "intel-uncore", 23*ebe99d35SSivaprasad Tummala "amd-hsmp" 24*ebe99d35SSivaprasad Tummala }; 25*ebe99d35SSivaprasad Tummala 26*ebe99d35SSivaprasad Tummala /* register the ops struct in rte_power_uncore_ops, return 0 on success. */ 27*ebe99d35SSivaprasad Tummala int 28*ebe99d35SSivaprasad Tummala rte_power_register_uncore_ops(struct rte_power_uncore_ops *driver_ops) 29ac1edcb6SSivaprasad Tummala { 30*ebe99d35SSivaprasad Tummala if (!driver_ops->init || !driver_ops->exit || !driver_ops->get_num_pkgs || 31*ebe99d35SSivaprasad Tummala !driver_ops->get_num_dies || !driver_ops->get_num_freqs || 32*ebe99d35SSivaprasad Tummala !driver_ops->get_avail_freqs || !driver_ops->get_freq || 33*ebe99d35SSivaprasad Tummala !driver_ops->set_freq || !driver_ops->freq_max || 34*ebe99d35SSivaprasad Tummala !driver_ops->freq_min) { 35*ebe99d35SSivaprasad Tummala POWER_LOG(ERR, "Missing callbacks while registering power ops"); 36*ebe99d35SSivaprasad Tummala return -1; 37ac1edcb6SSivaprasad Tummala } 38ac1edcb6SSivaprasad Tummala 39*ebe99d35SSivaprasad Tummala if (driver_ops->cb) 40*ebe99d35SSivaprasad Tummala driver_ops->cb(); 41*ebe99d35SSivaprasad Tummala 42*ebe99d35SSivaprasad Tummala TAILQ_INSERT_TAIL(&uncore_ops_list, driver_ops, next); 43*ebe99d35SSivaprasad Tummala 44ac1edcb6SSivaprasad Tummala return 0; 45ac1edcb6SSivaprasad Tummala } 46ac1edcb6SSivaprasad Tummala 47ac1edcb6SSivaprasad Tummala int 48ac1edcb6SSivaprasad Tummala rte_power_set_uncore_env(enum rte_uncore_power_mgmt_env env) 49ac1edcb6SSivaprasad Tummala { 50*ebe99d35SSivaprasad Tummala int ret = -1; 51*ebe99d35SSivaprasad Tummala struct rte_power_uncore_ops *ops; 52ac1edcb6SSivaprasad Tummala 53ac1edcb6SSivaprasad Tummala rte_spinlock_lock(&global_env_cfg_lock); 54ac1edcb6SSivaprasad Tummala 55*ebe99d35SSivaprasad Tummala if (global_uncore_env != RTE_UNCORE_PM_ENV_NOT_SET) { 56ae67895bSDavid Marchand POWER_LOG(ERR, "Uncore Power Management Env already set."); 57*ebe99d35SSivaprasad Tummala goto out; 58ac1edcb6SSivaprasad Tummala } 59ac1edcb6SSivaprasad Tummala 603b3af56dSSivaprasad Tummala if (env == RTE_UNCORE_PM_ENV_AUTO_DETECT) 613b3af56dSSivaprasad Tummala /* Currently only intel_uncore is supported. 623b3af56dSSivaprasad Tummala * This will be extended with auto-detection support 633b3af56dSSivaprasad Tummala * for multiple uncore implementations. 643b3af56dSSivaprasad Tummala */ 653b3af56dSSivaprasad Tummala env = RTE_UNCORE_PM_ENV_INTEL_UNCORE; 663b3af56dSSivaprasad Tummala 67*ebe99d35SSivaprasad Tummala if (env <= RTE_DIM(uncore_env_str)) { 68*ebe99d35SSivaprasad Tummala RTE_TAILQ_FOREACH(ops, &uncore_ops_list, next) 69*ebe99d35SSivaprasad Tummala if (strncmp(ops->name, uncore_env_str[env], 70*ebe99d35SSivaprasad Tummala RTE_POWER_UNCORE_DRIVER_NAMESZ) == 0) { 71*ebe99d35SSivaprasad Tummala global_uncore_env = env; 72*ebe99d35SSivaprasad Tummala global_uncore_ops = ops; 73ac1edcb6SSivaprasad Tummala ret = 0; 74ac1edcb6SSivaprasad Tummala goto out; 75ac1edcb6SSivaprasad Tummala } 76*ebe99d35SSivaprasad Tummala POWER_LOG(ERR, "Power Management (%s) not supported", 77*ebe99d35SSivaprasad Tummala uncore_env_str[env]); 78*ebe99d35SSivaprasad Tummala } else 79*ebe99d35SSivaprasad Tummala POWER_LOG(ERR, "Invalid Power Management Environment"); 80ac1edcb6SSivaprasad Tummala 81ac1edcb6SSivaprasad Tummala out: 82ac1edcb6SSivaprasad Tummala rte_spinlock_unlock(&global_env_cfg_lock); 83ac1edcb6SSivaprasad Tummala return ret; 84ac1edcb6SSivaprasad Tummala } 85ac1edcb6SSivaprasad Tummala 86ac1edcb6SSivaprasad Tummala void 87ac1edcb6SSivaprasad Tummala rte_power_unset_uncore_env(void) 88ac1edcb6SSivaprasad Tummala { 89ac1edcb6SSivaprasad Tummala rte_spinlock_lock(&global_env_cfg_lock); 90*ebe99d35SSivaprasad Tummala global_uncore_env = RTE_UNCORE_PM_ENV_NOT_SET; 91ac1edcb6SSivaprasad Tummala rte_spinlock_unlock(&global_env_cfg_lock); 92ac1edcb6SSivaprasad Tummala } 93ac1edcb6SSivaprasad Tummala 94ac1edcb6SSivaprasad Tummala enum rte_uncore_power_mgmt_env 95ac1edcb6SSivaprasad Tummala rte_power_get_uncore_env(void) 96ac1edcb6SSivaprasad Tummala { 97*ebe99d35SSivaprasad Tummala return global_uncore_env; 98ac1edcb6SSivaprasad Tummala } 99ac1edcb6SSivaprasad Tummala 100ac1edcb6SSivaprasad Tummala int 101ac1edcb6SSivaprasad Tummala rte_power_uncore_init(unsigned int pkg, unsigned int die) 102ac1edcb6SSivaprasad Tummala { 103ac1edcb6SSivaprasad Tummala int ret = -1; 104*ebe99d35SSivaprasad Tummala struct rte_power_uncore_ops *ops; 105*ebe99d35SSivaprasad Tummala uint8_t env; 106ac1edcb6SSivaprasad Tummala 107*ebe99d35SSivaprasad Tummala if ((global_uncore_env != RTE_UNCORE_PM_ENV_NOT_SET) && 108*ebe99d35SSivaprasad Tummala (global_uncore_env != RTE_UNCORE_PM_ENV_AUTO_DETECT)) 109*ebe99d35SSivaprasad Tummala return global_uncore_ops->init(pkg, die); 110ac1edcb6SSivaprasad Tummala 111*ebe99d35SSivaprasad Tummala /* Auto Detect Environment */ 112*ebe99d35SSivaprasad Tummala RTE_TAILQ_FOREACH(ops, &uncore_ops_list, next) 113*ebe99d35SSivaprasad Tummala if (ops) { 114*ebe99d35SSivaprasad Tummala POWER_LOG(INFO, 115*ebe99d35SSivaprasad Tummala "Attempting to initialise %s power management...", 116*ebe99d35SSivaprasad Tummala ops->name); 117*ebe99d35SSivaprasad Tummala ret = ops->init(pkg, die); 118ac1edcb6SSivaprasad Tummala if (ret == 0) { 119*ebe99d35SSivaprasad Tummala for (env = 0; env < RTE_DIM(uncore_env_str); env++) 120*ebe99d35SSivaprasad Tummala if (strncmp(ops->name, uncore_env_str[env], 121*ebe99d35SSivaprasad Tummala RTE_POWER_UNCORE_DRIVER_NAMESZ) == 0) { 122*ebe99d35SSivaprasad Tummala rte_power_set_uncore_env(env); 123ac1edcb6SSivaprasad Tummala goto out; 124ac1edcb6SSivaprasad Tummala } 125*ebe99d35SSivaprasad Tummala } 126ac1edcb6SSivaprasad Tummala } 127ac1edcb6SSivaprasad Tummala out: 128ac1edcb6SSivaprasad Tummala return ret; 129ac1edcb6SSivaprasad Tummala } 130ac1edcb6SSivaprasad Tummala 131ac1edcb6SSivaprasad Tummala int 132ac1edcb6SSivaprasad Tummala rte_power_uncore_exit(unsigned int pkg, unsigned int die) 133ac1edcb6SSivaprasad Tummala { 134*ebe99d35SSivaprasad Tummala if ((global_uncore_env != RTE_UNCORE_PM_ENV_NOT_SET) && 135*ebe99d35SSivaprasad Tummala global_uncore_ops) 136*ebe99d35SSivaprasad Tummala return global_uncore_ops->exit(pkg, die); 137*ebe99d35SSivaprasad Tummala 138*ebe99d35SSivaprasad Tummala POWER_LOG(ERR, 139*ebe99d35SSivaprasad Tummala "Uncore Env has not been set, unable to exit gracefully"); 140*ebe99d35SSivaprasad Tummala 141ac1edcb6SSivaprasad Tummala return -1; 142ac1edcb6SSivaprasad Tummala } 143*ebe99d35SSivaprasad Tummala 144*ebe99d35SSivaprasad Tummala uint32_t 145*ebe99d35SSivaprasad Tummala rte_power_get_uncore_freq(unsigned int pkg, unsigned int die) 146*ebe99d35SSivaprasad Tummala { 147*ebe99d35SSivaprasad Tummala RTE_ASSERT(global_uncore_ops != NULL); 148*ebe99d35SSivaprasad Tummala return global_uncore_ops->get_freq(pkg, die); 149*ebe99d35SSivaprasad Tummala } 150*ebe99d35SSivaprasad Tummala 151*ebe99d35SSivaprasad Tummala int 152*ebe99d35SSivaprasad Tummala rte_power_set_uncore_freq(unsigned int pkg, unsigned int die, uint32_t index) 153*ebe99d35SSivaprasad Tummala { 154*ebe99d35SSivaprasad Tummala RTE_ASSERT(global_uncore_ops != NULL); 155*ebe99d35SSivaprasad Tummala return global_uncore_ops->set_freq(pkg, die, index); 156*ebe99d35SSivaprasad Tummala } 157*ebe99d35SSivaprasad Tummala 158*ebe99d35SSivaprasad Tummala int 159*ebe99d35SSivaprasad Tummala rte_power_uncore_freq_max(unsigned int pkg, unsigned int die) 160*ebe99d35SSivaprasad Tummala { 161*ebe99d35SSivaprasad Tummala RTE_ASSERT(global_uncore_ops != NULL); 162*ebe99d35SSivaprasad Tummala return global_uncore_ops->freq_max(pkg, die); 163*ebe99d35SSivaprasad Tummala } 164*ebe99d35SSivaprasad Tummala 165*ebe99d35SSivaprasad Tummala int 166*ebe99d35SSivaprasad Tummala rte_power_uncore_freq_min(unsigned int pkg, unsigned int die) 167*ebe99d35SSivaprasad Tummala { 168*ebe99d35SSivaprasad Tummala RTE_ASSERT(global_uncore_ops != NULL); 169*ebe99d35SSivaprasad Tummala return global_uncore_ops->freq_min(pkg, die); 170*ebe99d35SSivaprasad Tummala } 171*ebe99d35SSivaprasad Tummala 172*ebe99d35SSivaprasad Tummala int 173*ebe99d35SSivaprasad Tummala rte_power_uncore_freqs(unsigned int pkg, unsigned int die, 174*ebe99d35SSivaprasad Tummala uint32_t *freqs, uint32_t num) 175*ebe99d35SSivaprasad Tummala { 176*ebe99d35SSivaprasad Tummala RTE_ASSERT(global_uncore_ops != NULL); 177*ebe99d35SSivaprasad Tummala return global_uncore_ops->get_avail_freqs(pkg, die, freqs, num); 178*ebe99d35SSivaprasad Tummala } 179*ebe99d35SSivaprasad Tummala 180*ebe99d35SSivaprasad Tummala int 181*ebe99d35SSivaprasad Tummala rte_power_uncore_get_num_freqs(unsigned int pkg, unsigned int die) 182*ebe99d35SSivaprasad Tummala { 183*ebe99d35SSivaprasad Tummala RTE_ASSERT(global_uncore_ops != NULL); 184*ebe99d35SSivaprasad Tummala return global_uncore_ops->get_num_freqs(pkg, die); 185*ebe99d35SSivaprasad Tummala } 186*ebe99d35SSivaprasad Tummala 187*ebe99d35SSivaprasad Tummala unsigned int 188*ebe99d35SSivaprasad Tummala rte_power_uncore_get_num_pkgs(void) 189*ebe99d35SSivaprasad Tummala { 190*ebe99d35SSivaprasad Tummala RTE_ASSERT(global_uncore_ops != NULL); 191*ebe99d35SSivaprasad Tummala return global_uncore_ops->get_num_pkgs(); 192*ebe99d35SSivaprasad Tummala } 193*ebe99d35SSivaprasad Tummala 194*ebe99d35SSivaprasad Tummala unsigned int 195*ebe99d35SSivaprasad Tummala rte_power_uncore_get_num_dies(unsigned int pkg) 196*ebe99d35SSivaprasad Tummala { 197*ebe99d35SSivaprasad Tummala RTE_ASSERT(global_uncore_ops != NULL); 198*ebe99d35SSivaprasad Tummala return global_uncore_ops->get_num_dies(pkg); 199*ebe99d35SSivaprasad Tummala } 200