|
| 1 | +/* |
| 2 | + * Copyright (C) 2023 Intel Corporation |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: MIT |
| 5 | + * |
| 6 | + */ |
| 7 | + |
| 8 | +#include "level_zero/sysman/source/performance/linux/os_performance_imp_prelim.h" |
| 9 | + |
| 10 | +#include "shared/source/debug_settings/debug_settings_manager.h" |
| 11 | +#include "shared/source/device/device.h" |
| 12 | +#include "shared/source/helpers/hw_info.h" |
| 13 | + |
| 14 | +#include "level_zero/sysman/source/sysman_const.h" |
| 15 | + |
| 16 | +#include <cmath> |
| 17 | + |
| 18 | +namespace L0 { |
| 19 | +namespace Sysman { |
| 20 | + |
| 21 | +const std::string LinuxPerformanceImp::sysPwrBalance("sys_pwr_balance"); |
| 22 | + |
| 23 | +ze_result_t LinuxPerformanceImp::osPerformanceGetProperties(zes_perf_properties_t &pProperties) { |
| 24 | + pProperties.onSubdevice = isSubdevice; |
| 25 | + pProperties.subdeviceId = subdeviceId; |
| 26 | + pProperties.engines = domain; |
| 27 | + return ZE_RESULT_SUCCESS; |
| 28 | +} |
| 29 | + |
| 30 | +ze_result_t LinuxPerformanceImp::getBaseScaleFactor() { |
| 31 | + auto result = pSysfsAccess->read(baseScale, baseScaleReading); |
| 32 | + if (ZE_RESULT_SUCCESS != result) { |
| 33 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): SysfsAccess->read() failed to read %s and returning error:0x%x \n", __FUNCTION__, baseScale.c_str(), getErrorCode(result)); |
| 34 | + return getErrorCode(result); |
| 35 | + } |
| 36 | + return ZE_RESULT_SUCCESS; |
| 37 | +} |
| 38 | + |
| 39 | +ze_result_t LinuxPerformanceImp::getMediaScaleFactor() { |
| 40 | + auto result = pSysfsAccess->read(mediaScale, mediaScaleReading); |
| 41 | + if (ZE_RESULT_SUCCESS != result) { |
| 42 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): SysfsAccess->read() failed to read %s and returning error:0x%x \n", __FUNCTION__, mediaScale.c_str(), getErrorCode(result)); |
| 43 | + return getErrorCode(result); |
| 44 | + } |
| 45 | + return ZE_RESULT_SUCCESS; |
| 46 | +} |
| 47 | + |
| 48 | +ze_result_t LinuxPerformanceImp::osPerformanceGetConfig(double *pFactor) { |
| 49 | + ze_result_t result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; |
| 50 | + double baseFactorReading = 0; |
| 51 | + double mediaFactorReading = 0; |
| 52 | + double sysPwrBalanceReading = 0; |
| 53 | + double multiplier = 0; |
| 54 | + switch (domain) { |
| 55 | + case ZES_ENGINE_TYPE_FLAG_OTHER: |
| 56 | + result = pSysfsAccess->read(sysPwrBalance, sysPwrBalanceReading); |
| 57 | + if (ZE_RESULT_SUCCESS != result) { |
| 58 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): SysfsAccess->read() failed to read %s and returning error:0x%x \n", __FUNCTION__, sysPwrBalance.c_str(), getErrorCode(result)); |
| 59 | + return getErrorCode(result); |
| 60 | + } |
| 61 | + if (sysPwrBalanceReading >= 0 && sysPwrBalanceReading <= 16.0) { |
| 62 | + *pFactor = 50.0 + std::round((16.0 - sysPwrBalanceReading) * 50.0 / 16.0); |
| 63 | + } else if (sysPwrBalanceReading > 16.0 && sysPwrBalanceReading <= 63.0) { |
| 64 | + *pFactor = std::round((63.0 - sysPwrBalanceReading) * 50.0 / (63.0 - 16.0)); |
| 65 | + } else { |
| 66 | + result = ZE_RESULT_ERROR_UNKNOWN; |
| 67 | + } |
| 68 | + break; |
| 69 | + case ZES_ENGINE_TYPE_FLAG_MEDIA: |
| 70 | + result = pSysfsAccess->read(mediaFreqFactor, mediaFactorReading); |
| 71 | + if (ZE_RESULT_SUCCESS != result) { |
| 72 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): SysfsAccess->read() failed to read %s and returning error:0x%x \n", __FUNCTION__, mediaFreqFactor.c_str(), getErrorCode(result)); |
| 73 | + return getErrorCode(result); |
| 74 | + } |
| 75 | + multiplier = (mediaFactorReading * mediaScaleReading); // Value retrieved from media_freq_factor file is in U(fixed point decimal) format convert it into decimal by multiplication with scale factor |
| 76 | + if (multiplier == 1) { |
| 77 | + *pFactor = maxPerformanceFactor; |
| 78 | + } else if (multiplier == 0.5) { |
| 79 | + *pFactor = halfOfMaxPerformanceFactor; |
| 80 | + } else if (multiplier == 0) { |
| 81 | + *pFactor = minPerformanceFactor; |
| 82 | + } else { |
| 83 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): multiplier for MEDIA is not matching with given presets and returning UNKNOWN ERROR \n", __FUNCTION__); |
| 84 | + result = ZE_RESULT_ERROR_UNKNOWN; |
| 85 | + } |
| 86 | + break; |
| 87 | + case ZES_ENGINE_TYPE_FLAG_COMPUTE: |
| 88 | + result = pSysfsAccess->read(baseFreqFactor, baseFactorReading); |
| 89 | + if (ZE_RESULT_SUCCESS != result) { |
| 90 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): SysfsAccess->read() failed to read %s and returning error:0x%x \n", __FUNCTION__, baseFreqFactor.c_str(), getErrorCode(result)); |
| 91 | + return getErrorCode(result); |
| 92 | + } |
| 93 | + multiplier = (baseFactorReading * baseScaleReading); // Value retrieved from base_freq_factor file is in U(fixed point decimal) format convert it into decimal by multiplication with scale factor |
| 94 | + if (multiplier >= 0.5 && multiplier <= 1) { |
| 95 | + *pFactor = (1 - multiplier) * 100 + 50; |
| 96 | + } else if (multiplier > 1 && multiplier <= 2) { |
| 97 | + *pFactor = (2 - multiplier) * 50; |
| 98 | + } else { |
| 99 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): multiplier for COMPUTE is not matching with given presets and returning UNKNOWN ERROR\n", __FUNCTION__); |
| 100 | + result = ZE_RESULT_ERROR_UNKNOWN; |
| 101 | + } |
| 102 | + break; |
| 103 | + default: |
| 104 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s() returning UNSUPPORTED_FEATURE \n", __FUNCTION__); |
| 105 | + result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; |
| 106 | + break; |
| 107 | + } |
| 108 | + return result; |
| 109 | +} |
| 110 | + |
| 111 | +ze_result_t LinuxPerformanceImp::osPerformanceSetConfig(double pFactor) { |
| 112 | + double multiplier = 0; |
| 113 | + ze_result_t result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; |
| 114 | + if (pFactor < minPerformanceFactor || pFactor > maxPerformanceFactor) { |
| 115 | + return ZE_RESULT_ERROR_INVALID_ARGUMENT; |
| 116 | + } |
| 117 | + |
| 118 | + switch (domain) { |
| 119 | + case ZES_ENGINE_TYPE_FLAG_OTHER: |
| 120 | + if (pFactor <= halfOfMaxPerformanceFactor) { |
| 121 | + multiplier = 63.0 - std::round(pFactor * (47.0) / 50.0); // multiplier = 63 - ROUND(pFactor * (63.0 - 16.0) / 50.0) |
| 122 | + } else { |
| 123 | + multiplier = 16.0 - std::round((pFactor - 50.0) * 16.0 / 50.0); |
| 124 | + } |
| 125 | + result = pSysfsAccess->write(sysPwrBalance, multiplier); |
| 126 | + break; |
| 127 | + case ZES_ENGINE_TYPE_FLAG_MEDIA: |
| 128 | + if (productFamily == IGFX_PVC) { |
| 129 | + if (pFactor > halfOfMaxPerformanceFactor) { |
| 130 | + multiplier = 1; |
| 131 | + } else { |
| 132 | + multiplier = 0.5; |
| 133 | + } |
| 134 | + } else { |
| 135 | + if (pFactor > halfOfMaxPerformanceFactor) { |
| 136 | + multiplier = 1; |
| 137 | + } else if (pFactor > minPerformanceFactor) { |
| 138 | + multiplier = 0.5; |
| 139 | + } else { |
| 140 | + multiplier = 0; // dynamic control mode is not supported on PVC |
| 141 | + } |
| 142 | + } |
| 143 | + multiplier = multiplier / mediaScaleReading; // Divide by scale factor and then round off to convert from decimal to U format |
| 144 | + multiplier = std::round(multiplier); |
| 145 | + result = pSysfsAccess->write(mediaFreqFactor, multiplier); |
| 146 | + break; |
| 147 | + case ZES_ENGINE_TYPE_FLAG_COMPUTE: |
| 148 | + if (pFactor < halfOfMaxPerformanceFactor) { |
| 149 | + multiplier = 2 - (pFactor / 50.0); |
| 150 | + } else { |
| 151 | + multiplier = 1 - ((pFactor - 50) / 100.0); |
| 152 | + } |
| 153 | + multiplier = multiplier / baseScaleReading; // Divide by scale factor and then round off to convert from decimal to U format |
| 154 | + multiplier = std::round(multiplier); |
| 155 | + result = pSysfsAccess->write(baseFreqFactor, multiplier); |
| 156 | + break; |
| 157 | + default: |
| 158 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s() returning UNSUPPORTED_FEATURE \n", __FUNCTION__); |
| 159 | + result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; |
| 160 | + break; |
| 161 | + } |
| 162 | + |
| 163 | + return result; |
| 164 | +} |
| 165 | + |
| 166 | +bool LinuxPerformanceImp::isPerformanceSupported(void) { |
| 167 | + switch (domain) { |
| 168 | + case ZES_ENGINE_TYPE_FLAG_OTHER: |
| 169 | + if (pSysfsAccess->canRead(sysPwrBalance) != ZE_RESULT_SUCCESS) { |
| 170 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): ZES_ENGINE_TYPE_FLAG_OTHER returns false \n", __FUNCTION__); |
| 171 | + return false; |
| 172 | + } |
| 173 | + break; |
| 174 | + case ZES_ENGINE_TYPE_FLAG_MEDIA: |
| 175 | + if (pSysfsAccess->canRead(mediaFreqFactor) != ZE_RESULT_SUCCESS) { |
| 176 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): ZES_ENGINE_TYPE_FLAG_MEDIA returns false \n", __FUNCTION__); |
| 177 | + return false; |
| 178 | + } |
| 179 | + if (getMediaScaleFactor() != ZE_RESULT_SUCCESS) { |
| 180 | + return false; |
| 181 | + } |
| 182 | + break; |
| 183 | + case ZES_ENGINE_TYPE_FLAG_COMPUTE: |
| 184 | + if (pSysfsAccess->canRead(baseFreqFactor) != ZE_RESULT_SUCCESS) { |
| 185 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): ZES_ENGINE_TYPE_FLAG_COMPUTE returns false \n", __FUNCTION__); |
| 186 | + return false; |
| 187 | + } |
| 188 | + if (getBaseScaleFactor() != ZE_RESULT_SUCCESS) { |
| 189 | + return false; |
| 190 | + } |
| 191 | + break; |
| 192 | + default: |
| 193 | + return false; |
| 194 | + break; |
| 195 | + } |
| 196 | + return true; |
| 197 | +} |
| 198 | + |
| 199 | +void LinuxPerformanceImp::init() { |
| 200 | + const std::string baseDir = "gt/gt" + std::to_string(subdeviceId) + "/"; |
| 201 | + baseFreqFactor = baseDir + "base_freq_factor"; |
| 202 | + mediaFreqFactor = baseDir + "media_freq_factor"; |
| 203 | + baseScale = baseDir + "base_freq_factor.scale"; |
| 204 | + mediaScale = baseDir + "media_freq_factor.scale"; |
| 205 | +} |
| 206 | + |
| 207 | +LinuxPerformanceImp::LinuxPerformanceImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, |
| 208 | + zes_engine_type_flag_t domain) : domain(domain), subdeviceId(subdeviceId), isSubdevice(onSubdevice) { |
| 209 | + LinuxSysmanImp *pLinuxSysmanImp = static_cast<LinuxSysmanImp *>(pOsSysman); |
| 210 | + pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess(); |
| 211 | + productFamily = pLinuxSysmanImp->getProductFamily(); |
| 212 | + init(); |
| 213 | +} |
| 214 | + |
| 215 | +OsPerformance *OsPerformance::create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_engine_type_flag_t domain) { |
| 216 | + LinuxPerformanceImp *pLinuxPerformanceImp = new LinuxPerformanceImp(pOsSysman, onSubdevice, subdeviceId, domain); |
| 217 | + return static_cast<OsPerformance *>(pLinuxPerformanceImp); |
| 218 | +} |
| 219 | + |
| 220 | +} // namespace Sysman |
| 221 | +} // namespace L0 |
0 commit comments