Add support for hwmon interface for sysman power

Signed-off-by: Mayank Raghuwanshi <mayank.raghuwanshi@intel.com>
This commit is contained in:
Mayank Raghuwanshi
2021-07-04 23:21:40 +05:30
committed by Compute-Runtime-Automation
parent 229ab9e30c
commit 0f2754e943
6 changed files with 786 additions and 23 deletions

View File

@@ -6,8 +6,8 @@
set(L0_SRCS_TOOLS_SYSMAN_POWER_LINUX
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/os_power_imp.cpp
${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/os_power_imp.h
${CMAKE_CURRENT_SOURCE_DIR}/os_power_imp.cpp
${CMAKE_CURRENT_SOURCE_DIR}/os_power_imp.h
)
if(UNIX)

View File

@@ -14,6 +14,18 @@
namespace L0 {
const std::string LinuxPowerImp::hwmonDir("device/hwmon");
const std::string LinuxPowerImp::i915("i915");
const std::string LinuxPowerImp::sustainedPowerLimitEnabled("power1_max_enable");
const std::string LinuxPowerImp::sustainedPowerLimit("power1_max");
const std::string LinuxPowerImp::sustainedPowerLimitInterval("power1_max_interval");
const std::string LinuxPowerImp::burstPowerLimitEnabled("power1_cap_enable");
const std::string LinuxPowerImp::burstPowerLimit("power1_cap");
const std::string LinuxPowerImp::energyCounterNode("energy1_input");
const std::string LinuxPowerImp::defaultPowerLimit("power_default_limit");
const std::string LinuxPowerImp::minPowerLimit("power_min_limit");
const std::string LinuxPowerImp::maxPowerLimit("power_max_limit");
void powerGetTimestamp(uint64_t &timestamp) {
std::chrono::time_point<std::chrono::steady_clock> ts = std::chrono::steady_clock::now();
timestamp = std::chrono::duration_cast<std::chrono::microseconds>(ts.time_since_epoch()).count();
@@ -22,27 +34,133 @@ void powerGetTimestamp(uint64_t &timestamp) {
ze_result_t LinuxPowerImp::getProperties(zes_power_properties_t *pProperties) {
pProperties->onSubdevice = false;
pProperties->subdeviceId = 0;
pProperties->canControl = canControl;
pProperties->isEnergyThresholdSupported = false;
pProperties->defaultLimit = -1;
pProperties->minLimit = -1;
pProperties->maxLimit = -1;
uint32_t val = 0;
auto result = pSysfsAccess->read(i915HwmonDir + "/" + defaultPowerLimit, val);
if (ZE_RESULT_SUCCESS == result) {
pProperties->defaultLimit = static_cast<int32_t>(val / milliFactor); // need to convert from microwatt to milliwatt
}
result = pSysfsAccess->read(i915HwmonDir + "/" + minPowerLimit, val);
if (ZE_RESULT_SUCCESS == result) {
pProperties->minLimit = static_cast<int32_t>(val / milliFactor); // need to convert from microwatt to milliwatt
}
result = pSysfsAccess->read(i915HwmonDir + "/" + maxPowerLimit, val);
if (ZE_RESULT_SUCCESS == result && val != std::numeric_limits<uint32_t>::max()) {
pProperties->maxLimit = static_cast<int32_t>(val / milliFactor); // need to convert from microwatt to milliwatt
}
return ZE_RESULT_SUCCESS;
}
ze_result_t LinuxPowerImp::getEnergyCounter(zes_power_energy_counter_t *pEnergy) {
const std::string key("PACKAGE_ENERGY");
uint64_t energy = 0;
ze_result_t result = pPmt->readValue(key, energy);
// PMT will return in joules and need to convert into microjoules
pEnergy->energy = energy * convertJouleToMicroJoule;
ze_result_t result = pSysfsAccess->read(i915HwmonDir + "/" + energyCounterNode, pEnergy->energy);
if (result != ZE_RESULT_SUCCESS) {
const std::string key("PACKAGE_ENERGY");
uint64_t energy = 0;
result = pPmt->readValue(key, energy);
// PMT will return energy counter in Q20 format(fixed point representation) where first 20 bits(from LSB) represent decimal part and remaining integral part which is converted into joule by division with 1048576(2^20) and then converted into microjoules
pEnergy->energy = (energy / 1048576) * convertJouleToMicroJoule;
}
powerGetTimestamp(pEnergy->timestamp);
return result;
}
ze_result_t LinuxPowerImp::getLimits(zes_power_sustained_limit_t *pSustained, zes_power_burst_limit_t *pBurst, zes_power_peak_limit_t *pPeak) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
ze_result_t result = ZE_RESULT_ERROR_UNKNOWN;
uint64_t val = 0;
if (pSustained != nullptr) {
result = pSysfsAccess->read(i915HwmonDir + "/" + sustainedPowerLimitEnabled, val);
if (ZE_RESULT_SUCCESS != result) {
return getErrorCode(result);
}
pSustained->enabled = static_cast<ze_bool_t>(val);
if (pSustained->enabled) {
val = 0;
result = pSysfsAccess->read(i915HwmonDir + "/" + sustainedPowerLimit, val);
if (ZE_RESULT_SUCCESS != result) {
return getErrorCode(result);
}
val /= milliFactor; // Convert microWatts to milliwatts
pSustained->power = static_cast<int32_t>(val);
val = 0;
result = pSysfsAccess->read(i915HwmonDir + "/" + sustainedPowerLimitInterval, val);
if (ZE_RESULT_SUCCESS != result) {
return getErrorCode(result);
}
pSustained->interval = static_cast<int32_t>(val);
}
}
if (pBurst != nullptr) {
result = pSysfsAccess->read(i915HwmonDir + "/" + burstPowerLimitEnabled, val);
if (ZE_RESULT_SUCCESS != result) {
return getErrorCode(result);
}
pBurst->enabled = static_cast<ze_bool_t>(val);
if (pBurst->enabled) {
result = pSysfsAccess->read(i915HwmonDir + "/" + burstPowerLimit, val);
if (ZE_RESULT_SUCCESS != result) {
return getErrorCode(result);
}
val /= milliFactor; // Convert microWatts to milliwatts
pBurst->power = static_cast<int32_t>(val);
}
}
if (pPeak != nullptr) {
pPeak->powerAC = -1;
pPeak->powerDC = -1;
result = ZE_RESULT_SUCCESS;
}
return result;
}
ze_result_t LinuxPowerImp::setLimits(const zes_power_sustained_limit_t *pSustained, const zes_power_burst_limit_t *pBurst, const zes_power_peak_limit_t *pPeak) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
ze_result_t result = ZE_RESULT_ERROR_UNKNOWN;
int32_t val = 0;
if (pSustained != nullptr) {
uint64_t isSustainedPowerLimitEnabled = 0;
result = pSysfsAccess->read(i915HwmonDir + "/" + sustainedPowerLimitEnabled, isSustainedPowerLimitEnabled);
if (ZE_RESULT_SUCCESS != result) {
return getErrorCode(result);
}
if (isSustainedPowerLimitEnabled) {
val = static_cast<uint32_t>(pSustained->power) * milliFactor; // Convert milliWatts to microwatts
result = pSysfsAccess->write(i915HwmonDir + "/" + sustainedPowerLimit, val);
if (ZE_RESULT_SUCCESS != result) {
return getErrorCode(result);
}
result = pSysfsAccess->write(i915HwmonDir + "/" + sustainedPowerLimitInterval, pSustained->interval);
if (ZE_RESULT_SUCCESS != result) {
return getErrorCode(result);
}
}
}
if (pBurst != nullptr) {
result = pSysfsAccess->write(i915HwmonDir + "/" + burstPowerLimitEnabled, static_cast<int>(pBurst->enabled));
if (ZE_RESULT_SUCCESS != result) {
return getErrorCode(result);
}
if (pBurst->enabled) {
val = static_cast<uint32_t>(pBurst->power) * milliFactor; // Convert milliWatts to microwatts
result = pSysfsAccess->write(i915HwmonDir + "/" + burstPowerLimit, val);
if (ZE_RESULT_SUCCESS != result) {
return getErrorCode(result);
}
}
}
return result;
}
ze_result_t LinuxPowerImp::getEnergyThreshold(zes_energy_threshold_t *pThreshold) {
@@ -54,13 +172,36 @@ ze_result_t LinuxPowerImp::setEnergyThreshold(double threshold) {
}
bool LinuxPowerImp::isPowerModuleSupported() {
return (pPmt != nullptr);
std::vector<std::string> listOfAllHwmonDirs = {};
bool hwmonDirExists = false;
if (ZE_RESULT_SUCCESS != pSysfsAccess->scanDirEntries(hwmonDir, listOfAllHwmonDirs)) {
hwmonDirExists = false;
}
for (const auto &tempHwmonDirEntry : listOfAllHwmonDirs) {
const std::string i915NameFile = hwmonDir + "/" + tempHwmonDirEntry + "/" + "name";
std::string name;
if (ZE_RESULT_SUCCESS != pSysfsAccess->read(i915NameFile, name)) {
continue;
}
if (name == i915) {
i915HwmonDir = hwmonDir + "/" + tempHwmonDirEntry;
hwmonDirExists = true;
canControl = true;
break;
}
}
if (hwmonDirExists == false) {
return (pPmt != nullptr);
}
return true;
}
LinuxPowerImp::LinuxPowerImp(OsSysman *pOsSysman) {
LinuxSysmanImp *pLinuxSysmanImp = static_cast<LinuxSysmanImp *>(pOsSysman);
// Lets hardcode subDeviceId to 0, as we are expecting this code to execute on device without subdevice
uint32_t subDeviceId = 0;
pPmt = pLinuxSysmanImp->getPlatformMonitoringTechAccess(subDeviceId);
pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess();
}
OsPower *OsPower::create(OsSysman *pOsSysman) {

View File

@@ -11,6 +11,7 @@
#include "level_zero/tools/source/sysman/power/os_power.h"
#include <memory>
#include <string>
namespace L0 {
@@ -32,5 +33,28 @@ class LinuxPowerImp : public OsPower, NEO::NonCopyableOrMovableClass {
protected:
PlatformMonitoringTech *pPmt = nullptr;
SysfsAccess *pSysfsAccess = nullptr;
private:
std::string i915HwmonDir;
static const std::string hwmonDir;
static const std::string i915;
static const std::string sustainedPowerLimitEnabled;
static const std::string sustainedPowerLimit;
static const std::string sustainedPowerLimitInterval;
static const std::string burstPowerLimitEnabled;
static const std::string burstPowerLimit;
static const std::string energyCounterNode;
static const std::string defaultPowerLimit;
static const std::string minPowerLimit;
static const std::string maxPowerLimit;
bool canControl = false;
ze_result_t getErrorCode(ze_result_t result) {
if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) {
result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
return result;
}
};
} // namespace L0