diff --git a/level_zero/tools/source/sysman/power/linux/CMakeLists.txt b/level_zero/tools/source/sysman/power/linux/CMakeLists.txt index 0e16954cfd..0e9e93de61 100644 --- a/level_zero/tools/source/sysman/power/linux/CMakeLists.txt +++ b/level_zero/tools/source/sysman/power/linux/CMakeLists.txt @@ -8,6 +8,7 @@ set(L0_SRCS_TOOLS_SYSMAN_POWER_LINUX ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/os_power_imp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/os_power_imp.h + ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/os_power_helper.cpp ) if(UNIX) diff --git a/level_zero/tools/source/sysman/power/linux/os_power_helper.cpp b/level_zero/tools/source/sysman/power/linux/os_power_helper.cpp new file mode 100644 index 0000000000..685c8da2a0 --- /dev/null +++ b/level_zero/tools/source/sysman/power/linux/os_power_helper.cpp @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/tools/source/sysman/power/linux/os_power_imp.h" + +namespace L0 { + +bool LinuxPowerImp::isEnergyHwmonDir(std::string name) { + if (isSubdevice == false && (name == i915)) { + return true; + } + return false; +} + +} // namespace L0 diff --git a/level_zero/tools/source/sysman/power/linux/os_power_imp.cpp b/level_zero/tools/source/sysman/power/linux/os_power_imp.cpp index 8d7129d306..77a680c1b2 100644 --- a/level_zero/tools/source/sysman/power/linux/os_power_imp.cpp +++ b/level_zero/tools/source/sysman/power/linux/os_power_imp.cpp @@ -32,8 +32,8 @@ void powerGetTimestamp(uint64_t ×tamp) { } ze_result_t LinuxPowerImp::getProperties(zes_power_properties_t *pProperties) { - pProperties->onSubdevice = false; - pProperties->subdeviceId = 0; + pProperties->onSubdevice = isSubdevice; + pProperties->subdeviceId = subdeviceId; pProperties->canControl = canControl; pProperties->isEnergyThresholdSupported = false; pProperties->defaultLimit = -1; @@ -58,16 +58,25 @@ ze_result_t LinuxPowerImp::getProperties(zes_power_properties_t *pProperties) { return ZE_RESULT_SUCCESS; } +ze_result_t LinuxPowerImp::getPmtEnergyCounter(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 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; + return result; +} ze_result_t LinuxPowerImp::getEnergyCounter(zes_power_energy_counter_t *pEnergy) { - 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); + ze_result_t result = pSysfsAccess->read(energyHwmonDir + "/" + energyCounterNode, pEnergy->energy); + if (result != ZE_RESULT_SUCCESS) { + if (pPmt != nullptr) { + return getPmtEnergyCounter(pEnergy); + } + } + if (result != ZE_RESULT_SUCCESS) { + return getErrorCode(result); + } return result; } @@ -131,6 +140,13 @@ ze_result_t LinuxPowerImp::setLimits(const zes_power_sustained_limit_t *pSustain if (ZE_RESULT_SUCCESS != result) { return getErrorCode(result); } + if (isSustainedPowerLimitEnabled != static_cast(pSustained->enabled)) { + result = pSysfsAccess->write(i915HwmonDir + "/" + sustainedPowerLimitEnabled, static_cast(pSustained->enabled)); + if (ZE_RESULT_SUCCESS != result) { + return getErrorCode(result); + } + isSustainedPowerLimitEnabled = static_cast(pSustained->enabled); + } if (isSustainedPowerLimitEnabled) { val = static_cast(pSustained->power) * milliFactor; // Convert milliWatts to microwatts @@ -144,6 +160,7 @@ ze_result_t LinuxPowerImp::setLimits(const zes_power_sustained_limit_t *pSustain return getErrorCode(result); } } + result = ZE_RESULT_SUCCESS; } if (pBurst != nullptr) { result = pSysfsAccess->write(i915HwmonDir + "/" + burstPowerLimitEnabled, static_cast(pBurst->enabled)); @@ -159,7 +176,6 @@ ze_result_t LinuxPowerImp::setLimits(const zes_power_sustained_limit_t *pSustain } } } - return result; } @@ -187,7 +203,9 @@ bool LinuxPowerImp::isPowerModuleSupported() { i915HwmonDir = hwmonDir + "/" + tempHwmonDirEntry; hwmonDirExists = true; canControl = true; - break; + } + if (isEnergyHwmonDir(name) == true) { + energyHwmonDir = hwmonDir + "/" + tempHwmonDirEntry; } } if (hwmonDirExists == false) { @@ -196,16 +214,14 @@ bool LinuxPowerImp::isPowerModuleSupported() { return true; } -LinuxPowerImp::LinuxPowerImp(OsSysman *pOsSysman) { +LinuxPowerImp::LinuxPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId) : isSubdevice(onSubdevice), subdeviceId(subdeviceId) { LinuxSysmanImp *pLinuxSysmanImp = static_cast(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); + pPmt = pLinuxSysmanImp->getPlatformMonitoringTechAccess(subdeviceId); pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess(); } -OsPower *OsPower::create(OsSysman *pOsSysman) { - LinuxPowerImp *pLinuxPowerImp = new LinuxPowerImp(pOsSysman); +OsPower *OsPower::create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId) { + LinuxPowerImp *pLinuxPowerImp = new LinuxPowerImp(pOsSysman, onSubdevice, subdeviceId); return static_cast(pLinuxPowerImp); } diff --git a/level_zero/tools/source/sysman/power/linux/os_power_imp.h b/level_zero/tools/source/sysman/power/linux/os_power_imp.h index ab8ca2352c..45b6c45c37 100644 --- a/level_zero/tools/source/sysman/power/linux/os_power_imp.h +++ b/level_zero/tools/source/sysman/power/linux/os_power_imp.h @@ -27,7 +27,9 @@ class LinuxPowerImp : public OsPower, NEO::NonCopyableOrMovableClass { ze_result_t setEnergyThreshold(double threshold) override; bool isPowerModuleSupported() override; - LinuxPowerImp(OsSysman *pOsSysman); + bool isEnergyHwmonDir(std::string name); + ze_result_t getPmtEnergyCounter(zes_power_energy_counter_t *pEnergy); + LinuxPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId); LinuxPowerImp() = default; ~LinuxPowerImp() override = default; @@ -37,6 +39,7 @@ class LinuxPowerImp : public OsPower, NEO::NonCopyableOrMovableClass { private: std::string i915HwmonDir; + std::string energyHwmonDir; static const std::string hwmonDir; static const std::string i915; static const std::string sustainedPowerLimitEnabled; @@ -49,6 +52,8 @@ class LinuxPowerImp : public OsPower, NEO::NonCopyableOrMovableClass { static const std::string minPowerLimit; static const std::string maxPowerLimit; bool canControl = false; + bool isSubdevice = false; + uint32_t subdeviceId = 0; ze_result_t getErrorCode(ze_result_t result) { if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) { diff --git a/level_zero/tools/source/sysman/power/os_power.h b/level_zero/tools/source/sysman/power/os_power.h index 36b4377249..9d75ca2b77 100644 --- a/level_zero/tools/source/sysman/power/os_power.h +++ b/level_zero/tools/source/sysman/power/os_power.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -22,7 +22,7 @@ class OsPower { virtual ze_result_t setEnergyThreshold(double threshold) = 0; virtual bool isPowerModuleSupported() = 0; - static OsPower *create(OsSysman *pOsSysman); + static OsPower *create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId); virtual ~OsPower() = default; }; diff --git a/level_zero/tools/source/sysman/power/power.cpp b/level_zero/tools/source/sysman/power/power.cpp index 0d707a2a7a..0af2d31892 100644 --- a/level_zero/tools/source/sysman/power/power.cpp +++ b/level_zero/tools/source/sysman/power/power.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -19,14 +19,20 @@ PowerHandleContext::~PowerHandleContext() { } } -void PowerHandleContext::init() { - Power *pPower = new PowerImp(pOsSysman); +void PowerHandleContext::createHandle(ze_device_handle_t deviceHandle) { + Power *pPower = new PowerImp(pOsSysman, deviceHandle); if (pPower->initSuccess == true) { handleList.push_back(pPower); } else { delete pPower; } } +ze_result_t PowerHandleContext::init(std::vector &deviceHandles) { + for (const auto &deviceHandle : deviceHandles) { + createHandle(deviceHandle); + } + return ZE_RESULT_SUCCESS; +} ze_result_t PowerHandleContext::powerGet(uint32_t *pCount, zes_pwr_handle_t *phPower) { uint32_t handleListSize = static_cast(handleList.size()); diff --git a/level_zero/tools/source/sysman/power/power.h b/level_zero/tools/source/sysman/power/power.h index c4adb0ce21..b2c724918d 100644 --- a/level_zero/tools/source/sysman/power/power.h +++ b/level_zero/tools/source/sysman/power/power.h @@ -1,11 +1,12 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * */ #pragma once +#include "level_zero/core/source/device/device.h" #include #include @@ -41,12 +42,14 @@ struct PowerHandleContext { PowerHandleContext(OsSysman *pOsSysman) : pOsSysman(pOsSysman){}; ~PowerHandleContext(); - void init(); - + ze_result_t init(std::vector &deviceHandles); ze_result_t powerGet(uint32_t *pCount, zes_pwr_handle_t *phPower); OsSysman *pOsSysman = nullptr; std::vector handleList = {}; + + private: + void createHandle(ze_device_handle_t deviceHandle); }; } // namespace L0 \ No newline at end of file diff --git a/level_zero/tools/source/sysman/power/power_imp.cpp b/level_zero/tools/source/sysman/power/power_imp.cpp index 90a811b2e5..e21a6cf176 100644 --- a/level_zero/tools/source/sysman/power/power_imp.cpp +++ b/level_zero/tools/source/sysman/power/power_imp.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -35,10 +35,11 @@ ze_result_t PowerImp::powerSetEnergyThreshold(double threshold) { return pOsPower->setEnergyThreshold(threshold); } -PowerImp::PowerImp(OsSysman *pOsSysman) { - pOsPower = OsPower::create(pOsSysman); +PowerImp::PowerImp(OsSysman *pOsSysman, ze_device_handle_t handle) : deviceHandle(handle) { + ze_device_properties_t deviceProperties = {}; + Device::fromHandle(deviceHandle)->getProperties(&deviceProperties); + pOsPower = OsPower::create(pOsSysman, deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, deviceProperties.subdeviceId); UNRECOVERABLE_IF(nullptr == pOsPower); - init(); } diff --git a/level_zero/tools/source/sysman/power/power_imp.h b/level_zero/tools/source/sysman/power/power_imp.h index 31d126bce2..5d06c8dadd 100644 --- a/level_zero/tools/source/sysman/power/power_imp.h +++ b/level_zero/tools/source/sysman/power/power_imp.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -23,10 +23,13 @@ class PowerImp : public Power, NEO::NonCopyableOrMovableClass { ze_result_t powerSetEnergyThreshold(double threshold) override; PowerImp() = default; - PowerImp(OsSysman *pOsSysman); + PowerImp(OsSysman *pOsSysman, ze_device_handle_t device); ~PowerImp() override; OsPower *pOsPower = nullptr; void init(); + + private: + ze_device_handle_t deviceHandle = {}; }; } // namespace L0 diff --git a/level_zero/tools/source/sysman/power/windows/os_power_imp.cpp b/level_zero/tools/source/sysman/power/windows/os_power_imp.cpp index fec12ec55c..26c3e1669d 100644 --- a/level_zero/tools/source/sysman/power/windows/os_power_imp.cpp +++ b/level_zero/tools/source/sysman/power/windows/os_power_imp.cpp @@ -330,13 +330,13 @@ bool WddmPowerImp::isPowerModuleSupported() { return ((status == ZE_RESULT_SUCCESS) && (enabled)); } -WddmPowerImp::WddmPowerImp(OsSysman *pOsSysman) { +WddmPowerImp::WddmPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId) { WddmSysmanImp *pWddmSysmanImp = static_cast(pOsSysman); pKmdSysManager = &pWddmSysmanImp->getKmdSysManager(); } -OsPower *OsPower::create(OsSysman *pOsSysman) { - WddmPowerImp *pWddmPowerImp = new WddmPowerImp(pOsSysman); +OsPower *OsPower::create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId) { + WddmPowerImp *pWddmPowerImp = new WddmPowerImp(pOsSysman, onSubdevice, subdeviceId); return static_cast(pWddmPowerImp); } diff --git a/level_zero/tools/source/sysman/power/windows/os_power_imp.h b/level_zero/tools/source/sysman/power/windows/os_power_imp.h index 6571836cf4..3acce90fc7 100644 --- a/level_zero/tools/source/sysman/power/windows/os_power_imp.h +++ b/level_zero/tools/source/sysman/power/windows/os_power_imp.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -23,7 +23,7 @@ class WddmPowerImp : public OsPower, NEO::NonCopyableOrMovableClass { ze_result_t setEnergyThreshold(double threshold) override; bool isPowerModuleSupported() override; - WddmPowerImp(OsSysman *pOsSysman); + WddmPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId); WddmPowerImp() = default; ~WddmPowerImp() override = default; diff --git a/level_zero/tools/source/sysman/sysman_imp.cpp b/level_zero/tools/source/sysman/sysman_imp.cpp index 6ca1818131..8205b25e52 100644 --- a/level_zero/tools/source/sysman/sysman_imp.cpp +++ b/level_zero/tools/source/sysman/sysman_imp.cpp @@ -76,7 +76,7 @@ ze_result_t SysmanDeviceImp::init() { return result; } if (pPowerHandleContext) { - pPowerHandleContext->init(); + pPowerHandleContext->init(deviceHandles); } if (pFrequencyHandleContext) { pFrequencyHandleContext->init(deviceHandles); diff --git a/level_zero/tools/test/unit_tests/sources/sysman/power/linux/CMakeLists.txt b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/CMakeLists.txt index bd6f28d594..2db63117be 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/power/linux/CMakeLists.txt +++ b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/CMakeLists.txt @@ -8,6 +8,8 @@ set(L0_TESTS_TOOLS_SYSMAN_POWER_LINUX ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/test_zes_power.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mock_sysfs_power.h + ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/mock_sysfs_power_helper.h + ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/test_zes_power_helper.cpp ) if(UNIX) diff --git a/level_zero/tools/test/unit_tests/sources/sysman/power/linux/mock_sysfs_power.h b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/mock_sysfs_power.h index 362ab5cfc7..7b837dc857 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/power/linux/mock_sysfs_power.h +++ b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/mock_sysfs_power.h @@ -10,11 +10,16 @@ #include "level_zero/core/test/unit_tests/mock.h" #include "level_zero/tools/source/sysman/power/linux/os_power_imp.h" +#include "level_zero/tools/test/unit_tests/sources/sysman/linux/mock_sysman_fixture.h" #include "sysman/linux/pmt/pmt.h" #include "sysman/power/power_imp.h" #include "sysman/sysman_imp.h" +using ::testing::DoDefault; +using ::testing::Matcher; +using ::testing::Return; + namespace L0 { namespace ult { constexpr uint64_t setEnergyCounter = (83456u * 1048576u); @@ -23,9 +28,9 @@ constexpr uint64_t mappedLength = 2048; const std::string deviceName("device"); const std::string baseTelemSysFS("/sys/class/intel_pmt"); const std::string hwmonDir("device/hwmon"); -const std::string i915HwmonDir("device/hwmon/hwmon4"); +const std::string i915HwmonDir("device/hwmon/hwmon2"); const std::string nonI915HwmonDir("device/hwmon/hwmon1"); -const std::vector listOfMockedHwmonDirs = {"hwmon1", "hwmon2", "hwmon3", "hwmon4"}; +const std::vector listOfMockedHwmonDirs = {"hwmon0", "hwmon1", "hwmon2", "hwmon3", "hwmon4"}; const std::string sustainedPowerLimitEnabled("power1_max_enable"); const std::string sustainedPowerLimit("power1_max"); const std::string sustainedPowerLimitInterval("power1_max_interval"); @@ -39,11 +44,18 @@ constexpr uint64_t expectedEnergyCounter = 123456785u; constexpr uint32_t mockDefaultPowerLimitVal = 300000000; constexpr uint32_t mockMaxPowerLimitVal = 490000000; constexpr uint32_t mockMinPowerLimitVal = 10; +const std::map deviceKeyOffsetMapPower = { + {"PACKAGE_ENERGY", 0x400}, + {"COMPUTE_TEMPERATURES", 0x68}, + {"SOC_TEMPERATURES", 0x60}, + {"CORE_TEMPERATURES", 0x6c}}; + class PowerSysfsAccess : public SysfsAccess {}; template <> struct Mock : public PowerSysfsAccess { + ze_result_t getValStringHelper(const std::string file, std::string &val); ze_result_t getValString(const std::string file, std::string &val) { ze_result_t result = ZE_RESULT_ERROR_UNKNOWN; if (file.compare(i915HwmonDir + "/" + "name") == 0) { @@ -65,17 +77,14 @@ struct Mock : public PowerSysfsAccess { uint64_t burstPowerLimitVal = 0; uint64_t energyCounterNodeVal = expectedEnergyCounter; - ze_result_t getValUnsignedLongReturnErrorForEnergyCounter(const std::string file, uint64_t &val) { - if (file.compare(i915HwmonDir + "/" + energyCounterNode) == 0) { - return ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS; - } - return ZE_RESULT_SUCCESS; - } - ze_result_t getValUnsignedLongReturnErrorForBurstPowerLimit(const std::string file, uint64_t &val) { if (file.compare(i915HwmonDir + "/" + burstPowerLimitEnabled) == 0) { val = burstPowerLimitEnabledVal; } + if (file.compare(i915HwmonDir + "/" + burstPowerLimit) == 0) { + + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } return ZE_RESULT_SUCCESS; } @@ -122,10 +131,6 @@ struct Mock : public PowerSysfsAccess { return ZE_RESULT_SUCCESS; } - ze_result_t getValUnsignedLongReturnErrorUnknown(const std::string file, uint64_t &val) { - return ZE_RESULT_ERROR_UNKNOWN; - } - ze_result_t setValUnsignedLongReturnErrorForBurstPowerLimit(const std::string file, const int val) { if (file.compare(i915HwmonDir + "/" + burstPowerLimit) == 0) { return ZE_RESULT_ERROR_NOT_AVAILABLE; @@ -140,6 +145,20 @@ struct Mock : public PowerSysfsAccess { return ZE_RESULT_SUCCESS; } + ze_result_t setValUnsignedLongReturnErrorForSustainedPowerLimitEnabled(const std::string file, const int val) { + if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitEnabled) == 0) { + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + return ZE_RESULT_SUCCESS; + } + + ze_result_t setValUnsignedLongReturnInsufficientForSustainedPowerLimitEnabled(const std::string file, const int val) { + if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitEnabled) == 0) { + return ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS; + } + return ZE_RESULT_SUCCESS; + } + ze_result_t setValReturnErrorForSustainedPower(const std::string file, const int val) { if (file.compare(i915HwmonDir + "/" + sustainedPowerLimit) == 0) { return ZE_RESULT_ERROR_NOT_AVAILABLE; @@ -154,6 +173,7 @@ struct Mock : public PowerSysfsAccess { return ZE_RESULT_SUCCESS; } + ze_result_t getValUnsignedLongHelper(const std::string file, uint64_t &val); ze_result_t getValUnsignedLong(const std::string file, uint64_t &val) { ze_result_t result = ZE_RESULT_SUCCESS; if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitEnabled) == 0) { @@ -201,7 +221,9 @@ struct Mock : public PowerSysfsAccess { ze_result_t setVal(const std::string file, const int val) { ze_result_t result = ZE_RESULT_SUCCESS; - if (file.compare(i915HwmonDir + "/" + sustainedPowerLimit) == 0) { + if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitEnabled) == 0) { + sustainedPowerLimitEnabledVal = static_cast(val); + } else if (file.compare(i915HwmonDir + "/" + sustainedPowerLimit) == 0) { sustainedPowerLimitVal = static_cast(val); } else if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitInterval) == 0) { sustainedPowerLimitIntervalVal = static_cast(val); @@ -222,9 +244,6 @@ struct Mock : public PowerSysfsAccess { } return ZE_RESULT_ERROR_NOT_AVAILABLE; } - ze_result_t getscanDirEntriesStatusReturnError(const std::string file, std::vector &listOfEntries) { - return ZE_RESULT_ERROR_NOT_AVAILABLE; - } Mock() = default; @@ -316,8 +335,141 @@ struct Mock : public PowerFsAccess { class PublicLinuxPowerImp : public L0::LinuxPowerImp { public: - PublicLinuxPowerImp(OsSysman *pOsSysman) : LinuxPowerImp(pOsSysman) {} + PublicLinuxPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId) : LinuxPowerImp(pOsSysman, onSubdevice, subdeviceId) {} using LinuxPowerImp::pPmt; }; + +class SysmanDevicePowerFixture : public SysmanDeviceFixture { + protected: + std::unique_ptr pPublicLinuxPowerImp; + std::unique_ptr> pPmt; + std::unique_ptr> pFsAccess; + std::unique_ptr> pSysfsAccess; + SysfsAccess *pSysfsAccessOld = nullptr; + FsAccess *pFsAccessOriginal = nullptr; + OsPower *pOsPowerOriginal = nullptr; + std::vector deviceHandles; + void SetUp() override { + SysmanDeviceFixture::SetUp(); + pFsAccess = std::make_unique>>(); + pFsAccessOriginal = pLinuxSysmanImp->pFsAccess; + pLinuxSysmanImp->pFsAccess = pFsAccess.get(); + pSysfsAccessOld = pLinuxSysmanImp->pSysfsAccess; + pSysfsAccess = std::make_unique>>(); + pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get(); + ON_CALL(*pFsAccess.get(), listDirectory(_, _)) + .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock::listDirectorySuccess)); + ON_CALL(*pFsAccess.get(), getRealPath(_, _)) + .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock::getRealPathSuccess)); + ON_CALL(*pSysfsAccess.get(), read(_, Matcher(_))) + .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getValString)); + ON_CALL(*pSysfsAccess.get(), read(_, Matcher(_))) + .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getValUnsignedLong)); + ON_CALL(*pSysfsAccess.get(), read(_, Matcher(_))) + .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getValUnsignedInt)); + ON_CALL(*pSysfsAccess.get(), write(_, _)) + .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::setVal)); + ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) + .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getscanDirEntries)); + uint32_t subDeviceCount = 0; + Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, nullptr); + if (subDeviceCount == 0) { + deviceHandles.resize(1, device->toHandle()); + } else { + deviceHandles.resize(subDeviceCount, nullptr); + Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, deviceHandles.data()); + } + + for (auto &deviceHandle : deviceHandles) { + ze_device_properties_t deviceProperties = {ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES}; + Device::fromHandle(deviceHandle)->getProperties(&deviceProperties); + auto pPmt = new NiceMock>(pFsAccess.get(), deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, + deviceProperties.subdeviceId); + pPmt->mockedInit(pFsAccess.get()); + pPmt->keyOffsetMap = deviceKeyOffsetMapPower; + pLinuxSysmanImp->mapOfSubDeviceIdToPmtObject.emplace(deviceProperties.subdeviceId, pPmt); + } + + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); + } + void TearDown() override { + SysmanDeviceFixture::TearDown(); + pLinuxSysmanImp->pFsAccess = pFsAccessOriginal; + pLinuxSysmanImp->pSysfsAccess = pSysfsAccessOld; + } + + std::vector getPowerHandles(uint32_t count) { + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumPowerDomains(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + return handles; + } +}; + +class SysmanDevicePowerMultiDeviceFixture : public SysmanMultiDeviceFixture { + protected: + std::unique_ptr pPublicLinuxPowerImp; + std::unique_ptr> pPmt; + std::unique_ptr> pFsAccess; + std::unique_ptr> pSysfsAccess; + SysfsAccess *pSysfsAccessOld = nullptr; + FsAccess *pFsAccessOriginal = nullptr; + OsPower *pOsPowerOriginal = nullptr; + std::vector deviceHandles; + void SetUp() override { + SysmanMultiDeviceFixture::SetUp(); + pFsAccess = std::make_unique>>(); + pFsAccessOriginal = pLinuxSysmanImp->pFsAccess; + pLinuxSysmanImp->pFsAccess = pFsAccess.get(); + pSysfsAccessOld = pLinuxSysmanImp->pSysfsAccess; + pSysfsAccess = std::make_unique>>(); + pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get(); + ON_CALL(*pFsAccess.get(), listDirectory(_, _)) + .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock::listDirectorySuccess)); + ON_CALL(*pFsAccess.get(), getRealPath(_, _)) + .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock::getRealPathSuccess)); + ON_CALL(*pSysfsAccess.get(), read(_, Matcher(_))) + .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getValString)); + ON_CALL(*pSysfsAccess.get(), read(_, Matcher(_))) + .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getValUnsignedLong)); + ON_CALL(*pSysfsAccess.get(), read(_, Matcher(_))) + .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getValUnsignedInt)); + ON_CALL(*pSysfsAccess.get(), write(_, _)) + .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::setVal)); + ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) + .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getscanDirEntries)); + uint32_t subDeviceCount = 0; + Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, nullptr); + if (subDeviceCount == 0) { + deviceHandles.resize(1, device->toHandle()); + } else { + deviceHandles.resize(subDeviceCount, nullptr); + Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, deviceHandles.data()); + } + + for (auto &deviceHandle : deviceHandles) { + ze_device_properties_t deviceProperties = {ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES}; + Device::fromHandle(deviceHandle)->getProperties(&deviceProperties); + auto pPmt = new NiceMock>(pFsAccess.get(), deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, + deviceProperties.subdeviceId); + pPmt->mockedInit(pFsAccess.get()); + pPmt->keyOffsetMap = deviceKeyOffsetMapPower; + pLinuxSysmanImp->mapOfSubDeviceIdToPmtObject.emplace(deviceProperties.subdeviceId, pPmt); + } + + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); + } + void TearDown() override { + SysmanMultiDeviceFixture::TearDown(); + pLinuxSysmanImp->pFsAccess = pFsAccessOriginal; + pLinuxSysmanImp->pSysfsAccess = pSysfsAccessOld; + } + + std::vector getPowerHandles(uint32_t count) { + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumPowerDomains(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + return handles; + } +}; + } // namespace ult } // namespace L0 diff --git a/level_zero/tools/test/unit_tests/sources/sysman/power/linux/mock_sysfs_power_helper.h b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/mock_sysfs_power_helper.h new file mode 100644 index 0000000000..af3c51cc00 --- /dev/null +++ b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/mock_sysfs_power_helper.h @@ -0,0 +1,6 @@ +/* + * Copyright (C) 2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ diff --git a/level_zero/tools/test/unit_tests/sources/sysman/power/linux/test_zes_power.cpp b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/test_zes_power.cpp index 7fbd3f8a0d..bfc6ed9542 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/power/linux/test_zes_power.cpp +++ b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/test_zes_power.cpp @@ -6,94 +6,13 @@ */ #include "level_zero/tools/source/sysman/power/linux/os_power_imp.h" -#include "level_zero/tools/test/unit_tests/sources/sysman/linux/mock_sysman_fixture.h" - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "mock_sysfs_power.h" -#include "sysman/power/power_imp.h" - -using ::testing::DoDefault; -using ::testing::Matcher; -using ::testing::Return; +#include "level_zero/tools/test/unit_tests/sources/sysman/power/linux/mock_sysfs_power.h" namespace L0 { namespace ult { constexpr uint64_t convertJouleToMicroJoule = 1000000u; constexpr uint32_t powerHandleComponentCount = 1u; -const std::map deviceKeyOffsetMapPower = { - {"PACKAGE_ENERGY", 0x400}, - {"COMPUTE_TEMPERATURES", 0x68}, - {"SOC_TEMPERATURES", 0x60}, - {"CORE_TEMPERATURES", 0x6c}}; - -class SysmanDevicePowerFixture : public SysmanDeviceFixture { - protected: - std::unique_ptr pPublicLinuxPowerImp; - std::unique_ptr> pPmt; - std::unique_ptr> pFsAccess; - std::unique_ptr> pSysfsAccess; - SysfsAccess *pSysfsAccessOld = nullptr; - FsAccess *pFsAccessOriginal = nullptr; - OsPower *pOsPowerOriginal = nullptr; - std::vector deviceHandles; - void SetUp() override { - SysmanDeviceFixture::SetUp(); - pFsAccess = std::make_unique>>(); - pFsAccessOriginal = pLinuxSysmanImp->pFsAccess; - pLinuxSysmanImp->pFsAccess = pFsAccess.get(); - pSysfsAccessOld = pLinuxSysmanImp->pSysfsAccess; - pSysfsAccess = std::make_unique>>(); - pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get(); - ON_CALL(*pFsAccess.get(), listDirectory(_, _)) - .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock::listDirectorySuccess)); - ON_CALL(*pFsAccess.get(), getRealPath(_, _)) - .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock::getRealPathSuccess)); - ON_CALL(*pSysfsAccess.get(), read(_, Matcher(_))) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getValString)); - ON_CALL(*pSysfsAccess.get(), read(_, Matcher(_))) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getValUnsignedLong)); - ON_CALL(*pSysfsAccess.get(), read(_, Matcher(_))) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getValUnsignedInt)); - ON_CALL(*pSysfsAccess.get(), write(_, _)) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::setVal)); - ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getscanDirEntries)); - - uint32_t subDeviceCount = 0; - Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, nullptr); - if (subDeviceCount == 0) { - deviceHandles.resize(1, device->toHandle()); - } else { - deviceHandles.resize(subDeviceCount, nullptr); - Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, deviceHandles.data()); - } - - for (auto &deviceHandle : deviceHandles) { - ze_device_properties_t deviceProperties = {ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES}; - Device::fromHandle(deviceHandle)->getProperties(&deviceProperties); - auto pPmt = new NiceMock>(pFsAccess.get(), deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, - deviceProperties.subdeviceId); - pPmt->mockedInit(pFsAccess.get()); - pPmt->keyOffsetMap = deviceKeyOffsetMapPower; - pLinuxSysmanImp->mapOfSubDeviceIdToPmtObject.emplace(deviceProperties.subdeviceId, pPmt); - } - - pSysmanDeviceImp->pPowerHandleContext->init(); - } - void TearDown() override { - SysmanDeviceFixture::TearDown(); - pLinuxSysmanImp->pFsAccess = pFsAccessOriginal; - pLinuxSysmanImp->pSysfsAccess = pSysfsAccessOld; - } - - std::vector getPowerHandles(uint32_t count) { - std::vector handles(count, nullptr); - EXPECT_EQ(zesDeviceEnumPowerDomains(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); - return handles; - } -}; TEST_F(SysmanDevicePowerFixture, GivenComponentCountZeroWhenEnumeratingPowerDomainsWhenhwmonInterfaceExistsThenValidCountIsReturnedAndVerifySysmanPowerGetCallSucceeds) { uint32_t count = 0; @@ -147,7 +66,7 @@ TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerProperties delete handle; } pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); - pSysmanDeviceImp->pPowerHandleContext->init(); + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); auto handles = getPowerHandles(powerHandleComponentCount); for (auto handle : handles) { zes_power_properties_t properties; @@ -171,7 +90,7 @@ TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerProperties delete handle; } pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); - pSysmanDeviceImp->pPowerHandleContext->init(); + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); auto handles = getPowerHandles(powerHandleComponentCount); for (auto handle : handles) { zes_power_properties_t properties; @@ -194,7 +113,7 @@ TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerProperties delete handle; } pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); - pSysmanDeviceImp->pPowerHandleContext->init(); + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); auto handles = getPowerHandles(powerHandleComponentCount); for (auto handle : handles) { zes_power_properties_t properties; @@ -207,21 +126,11 @@ TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerProperties } } -TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerEnergyCounterWhenHwmonInterfaceExistThenValidPowerReadingsRetrieved) { - auto handles = getPowerHandles(powerHandleComponentCount); - - for (auto handle : handles) { - zes_power_energy_counter_t energyCounter = {}; - ASSERT_EQ(ZE_RESULT_SUCCESS, zesPowerGetEnergyCounter(handle, &energyCounter)); - EXPECT_EQ(energyCounter.energy, expectedEnergyCounter); - } -} - TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerEnergyCounterFailedWhenHwmonInterfaceExistThenValidErrorCodeReturned) { auto handles = getPowerHandles(powerHandleComponentCount); - ON_CALL(*pSysfsAccess.get(), read(_, Matcher(_))) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getValUnsignedLongReturnErrorForEnergyCounter)); + EXPECT_CALL(*pSysfsAccess.get(), read(_, Matcher(_))) + .WillRepeatedly(Return(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS)); for (auto handle : handles) { zes_power_energy_counter_t energyCounter = {}; uint64_t expectedEnergyCounter = convertJouleToMicroJoule * (setEnergyCounter / 1048576); @@ -235,6 +144,7 @@ TEST_F(SysmanDevicePowerFixture, GivenSetPowerLimitsWhenGettingPowerLimitsWhenHw for (auto handle : handles) { zes_power_sustained_limit_t sustainedSet = {}; zes_power_sustained_limit_t sustainedGet = {}; + sustainedSet.enabled = 1; sustainedSet.interval = 10; sustainedSet.power = 300000; EXPECT_EQ(ZE_RESULT_SUCCESS, zesPowerSetLimits(handle, &sustainedSet, nullptr, nullptr)); @@ -285,8 +195,8 @@ TEST_F(SysmanDevicePowerFixture, GivenGetPowerLimitsReturnErrorWhenGettingPowerL TEST_F(SysmanDevicePowerFixture, GivenGetPowerLimitsReturnErrorWhenGettingPowerLimitsWhenHwmonInterfaceExistForBurstPowerLimitThenProperErrorCodesIsReturned) { auto handles = getPowerHandles(powerHandleComponentCount); - ON_CALL(*pSysfsAccess.get(), read(_, Matcher(_))) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getValUnsignedLongReturnErrorUnknown)); + EXPECT_CALL(*pSysfsAccess.get(), read(_, Matcher(_))) + .WillRepeatedly(Return(ZE_RESULT_ERROR_UNKNOWN)); for (auto handle : handles) { zes_power_burst_limit_t burstSet = {}; @@ -374,6 +284,7 @@ TEST_F(SysmanDevicePowerFixture, GivenwritingSustainedPowerNodeReturnErrorWhenSe .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::setValReturnErrorForSustainedPower)); zes_power_sustained_limit_t sustainedSet = {}; + sustainedSet.enabled = 1; sustainedSet.interval = 10; sustainedSet.power = 300000; EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesPowerSetLimits(handles[0], &sustainedSet, nullptr, nullptr)); @@ -386,11 +297,39 @@ TEST_F(SysmanDevicePowerFixture, GivenwritingSustainedPowerIntervalNodeReturnErr .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::setValReturnErrorForSustainedPowerInterval)); zes_power_sustained_limit_t sustainedSet = {}; + sustainedSet.enabled = 1; sustainedSet.interval = 10; sustainedSet.power = 300000; EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesPowerSetLimits(handles[0], &sustainedSet, nullptr, nullptr)); } +TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenWritingToSustainedPowerEnableNodeWithoutPermissionsThenValidErrorIsReturned) { + auto handles = getPowerHandles(powerHandleComponentCount); + + ON_CALL(*pSysfsAccess.get(), write(_, _)) + .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::setValUnsignedLongReturnInsufficientForSustainedPowerLimitEnabled)); + + zes_power_sustained_limit_t sustainedSet = {}; + sustainedSet.enabled = 0; + EXPECT_EQ(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS, zesPowerSetLimits(handles[0], &sustainedSet, nullptr, nullptr)); +} + +TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleAndPermissionsThenFirstDisableSustainedPowerLimitAndThenEnableItAndCheckSuccesIsReturned) { + auto handles = getPowerHandles(powerHandleComponentCount); + zes_power_sustained_limit_t sustainedSet = {}; + zes_power_sustained_limit_t sustainedGet = {}; + sustainedSet.enabled = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPowerSetLimits(handles[0], &sustainedSet, nullptr, nullptr)); + sustainedSet.enabled = 1; + sustainedSet.interval = 10; + sustainedSet.power = 300000; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPowerSetLimits(handles[0], &sustainedSet, nullptr, nullptr)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPowerGetLimits(handles[0], &sustainedGet, nullptr, nullptr)); + EXPECT_EQ(sustainedGet.enabled, sustainedSet.enabled); + EXPECT_EQ(sustainedGet.power, sustainedSet.power); + EXPECT_EQ(sustainedGet.interval, sustainedSet.interval); +} + TEST_F(SysmanDevicePowerFixture, GivenGetPowerLimitsWhenPowerLimitsAreDisabledWhenHwmonInterfaceExistThenAllPowerValuesAreIgnored) { auto handles = getPowerHandles(powerHandleComponentCount); @@ -413,35 +352,37 @@ TEST_F(SysmanDevicePowerFixture, GivenGetPowerLimitsWhenPowerLimitsAreDisabledWh } TEST_F(SysmanDevicePowerFixture, GivenScanDiectoriesFailAndPmtIsNotNullPointerThenPowerModuleIsSupported) { - ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getscanDirEntriesStatusReturnError)); - pSysmanDeviceImp->pPowerHandleContext->init(); - PublicLinuxPowerImp *pPowerImp = new PublicLinuxPowerImp(pOsSysman); + EXPECT_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) + .WillRepeatedly(Return(ZE_RESULT_ERROR_NOT_AVAILABLE)); + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); + ze_device_properties_t deviceProperties = {ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES}; + Device::fromHandle(device)->getProperties(&deviceProperties); + PublicLinuxPowerImp *pPowerImp = new PublicLinuxPowerImp(pOsSysman, deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, deviceProperties.subdeviceId); EXPECT_TRUE(pPowerImp->isPowerModuleSupported()); delete pPowerImp; } TEST_F(SysmanDevicePowerFixture, GivenComponentCountZeroWhenEnumeratingPowerDomainsThenValidCountIsReturnedAndVerifySysmanPowerGetCallSucceeds) { - ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getscanDirEntriesStatusReturnError)); + EXPECT_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) + .WillRepeatedly(Return(ZE_RESULT_ERROR_NOT_AVAILABLE)); for (const auto &handle : pSysmanDeviceImp->pPowerHandleContext->handleList) { delete handle; } pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); - pSysmanDeviceImp->pPowerHandleContext->init(); + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); uint32_t count = 0; EXPECT_EQ(zesDeviceEnumPowerDomains(device->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); EXPECT_EQ(count, powerHandleComponentCount); } TEST_F(SysmanDevicePowerFixture, GivenInvalidComponentCountWhenEnumeratingPowerDomainsThenValidCountIsReturnedAndVerifySysmanPowerGetCallSucceeds) { - ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getscanDirEntriesStatusReturnError)); + EXPECT_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) + .WillRepeatedly(Return(ZE_RESULT_ERROR_NOT_AVAILABLE)); for (const auto &handle : pSysmanDeviceImp->pPowerHandleContext->handleList) { delete handle; } pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); - pSysmanDeviceImp->pPowerHandleContext->init(); + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); uint32_t count = 0; EXPECT_EQ(zesDeviceEnumPowerDomains(device->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); EXPECT_EQ(count, powerHandleComponentCount); @@ -452,13 +393,13 @@ TEST_F(SysmanDevicePowerFixture, GivenInvalidComponentCountWhenEnumeratingPowerD } TEST_F(SysmanDevicePowerFixture, GivenComponentCountZeroWhenEnumeratingPowerDomainsThenValidPowerHandlesIsReturned) { - ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getscanDirEntriesStatusReturnError)); + EXPECT_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) + .WillRepeatedly(Return(ZE_RESULT_ERROR_NOT_AVAILABLE)); for (const auto &handle : pSysmanDeviceImp->pPowerHandleContext->handleList) { delete handle; } pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); - pSysmanDeviceImp->pPowerHandleContext->init(); + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); uint32_t count = 0; EXPECT_EQ(zesDeviceEnumPowerDomains(device->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); EXPECT_EQ(count, powerHandleComponentCount); @@ -471,13 +412,13 @@ TEST_F(SysmanDevicePowerFixture, GivenComponentCountZeroWhenEnumeratingPowerDoma } TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerPropertiesThenCallSucceeds) { - ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getscanDirEntriesStatusReturnError)); + EXPECT_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) + .WillRepeatedly(Return(ZE_RESULT_ERROR_NOT_AVAILABLE)); for (const auto &handle : pSysmanDeviceImp->pPowerHandleContext->handleList) { delete handle; } pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); - pSysmanDeviceImp->pPowerHandleContext->init(); + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); auto handles = getPowerHandles(powerHandleComponentCount); for (auto handle : handles) { @@ -489,13 +430,13 @@ TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerProperties } TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerEnergyCounterThenValidPowerReadingsRetrieved) { - ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getscanDirEntriesStatusReturnError)); + EXPECT_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) + .WillRepeatedly(Return(ZE_RESULT_ERROR_NOT_AVAILABLE)); for (const auto &handle : pSysmanDeviceImp->pPowerHandleContext->handleList) { delete handle; } pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); - pSysmanDeviceImp->pPowerHandleContext->init(); + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); auto handles = getPowerHandles(powerHandleComponentCount); for (auto handle : handles) { @@ -506,14 +447,39 @@ TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerEnergyCoun } } +TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerEnergyCounterWhenEnergyHwmonFileReturnsErrorAndPmtFailsThenFailureIsReturned) { + EXPECT_CALL(*pSysfsAccess.get(), read(_, Matcher(_))) + .WillRepeatedly(Return(ZE_RESULT_ERROR_NOT_AVAILABLE)); + for (const auto &handle : pSysmanDeviceImp->pPowerHandleContext->handleList) { + delete handle; + } + for (auto &subDeviceIdToPmtEntry : pLinuxSysmanImp->mapOfSubDeviceIdToPmtObject) { + delete subDeviceIdToPmtEntry.second; + } + pLinuxSysmanImp->mapOfSubDeviceIdToPmtObject.clear(); + for (auto &deviceHandle : deviceHandles) { + ze_device_properties_t deviceProperties = {ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES}; + Device::fromHandle(deviceHandle)->getProperties(&deviceProperties); + pLinuxSysmanImp->mapOfSubDeviceIdToPmtObject.emplace(deviceProperties.subdeviceId, nullptr); + } + pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); + auto handles = getPowerHandles(powerHandleComponentCount); + + for (auto handle : handles) { + zes_power_energy_counter_t energyCounter = {}; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesPowerGetEnergyCounter(handle, &energyCounter)); + } +} + TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerEnergyThresholdThenUnsupportedFeatureErrorIsReturned) { - ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getscanDirEntriesStatusReturnError)); + EXPECT_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) + .WillRepeatedly(Return(ZE_RESULT_ERROR_NOT_AVAILABLE)); for (const auto &handle : pSysmanDeviceImp->pPowerHandleContext->handleList) { delete handle; } pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); - pSysmanDeviceImp->pPowerHandleContext->init(); + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); zes_energy_threshold_t threshold; auto handles = getPowerHandles(powerHandleComponentCount); for (auto handle : handles) { @@ -522,13 +488,13 @@ TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerEnergyThre } TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenSettingPowerEnergyThresholdThenUnsupportedFeatureErrorIsReturned) { - ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getscanDirEntriesStatusReturnError)); + EXPECT_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) + .WillRepeatedly(Return(ZE_RESULT_ERROR_NOT_AVAILABLE)); for (const auto &handle : pSysmanDeviceImp->pPowerHandleContext->handleList) { delete handle; } pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); - pSysmanDeviceImp->pPowerHandleContext->init(); + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); double threshold = 0; auto handles = getPowerHandles(powerHandleComponentCount); for (auto handle : handles) { @@ -537,13 +503,13 @@ TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenSettingPowerEnergyThre } TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerLimitsThenUnsupportedFeatureErrorIsReturned) { - ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getscanDirEntriesStatusReturnError)); + EXPECT_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) + .WillRepeatedly(Return(ZE_RESULT_ERROR_NOT_AVAILABLE)); for (const auto &handle : pSysmanDeviceImp->pPowerHandleContext->handleList) { delete handle; } pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); - pSysmanDeviceImp->pPowerHandleContext->init(); + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); auto handles = getPowerHandles(powerHandleComponentCount); for (auto handle : handles) { zes_power_sustained_limit_t sustained; @@ -554,13 +520,13 @@ TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerLimitsThen } TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenSettingPowerLimitsThenUnsupportedFeatureErrorIsReturned) { - ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getscanDirEntriesStatusReturnError)); + EXPECT_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) + .WillRepeatedly(Return(ZE_RESULT_ERROR_NOT_AVAILABLE)); for (const auto &handle : pSysmanDeviceImp->pPowerHandleContext->handleList) { delete handle; } pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); - pSysmanDeviceImp->pPowerHandleContext->init(); + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); auto handles = getPowerHandles(powerHandleComponentCount); for (auto handle : handles) { zes_power_sustained_limit_t sustained; @@ -570,5 +536,23 @@ TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenSettingPowerLimitsThen } } +TEST_F(SysmanDevicePowerMultiDeviceFixture, GivenValidPowerHandleWhenGettingPowerEnergyCounterWhenEnergyHwmonFailsThenValidPowerReadingsRetrievedFromPmt) { + EXPECT_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) + .WillRepeatedly(Return(ZE_RESULT_ERROR_NOT_AVAILABLE)); + for (const auto &handle : pSysmanDeviceImp->pPowerHandleContext->handleList) { + delete handle; + } + pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); + auto handles = getPowerHandles(powerHandleComponentCount); + + for (auto handle : handles) { + zes_power_energy_counter_t energyCounter; + uint64_t expectedEnergyCounter = convertJouleToMicroJoule * (setEnergyCounter / 1048576); + ASSERT_EQ(ZE_RESULT_SUCCESS, zesPowerGetEnergyCounter(handle, &energyCounter)); + EXPECT_EQ(energyCounter.energy, expectedEnergyCounter); + } +} + } // namespace ult } // namespace L0 diff --git a/level_zero/tools/test/unit_tests/sources/sysman/power/linux/test_zes_power_helper.cpp b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/test_zes_power_helper.cpp new file mode 100644 index 0000000000..21f6c5be56 --- /dev/null +++ b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/test_zes_power_helper.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/tools/source/sysman/power/linux/os_power_imp.h" +#include "level_zero/tools/test/unit_tests/sources/sysman/power/linux/mock_sysfs_power.h" + +namespace L0 { +namespace ult { + +constexpr uint32_t powerHandleComponentCount = 1u; +using SysmanDevicePowerFixtureHelper = SysmanDevicePowerFixture; + +TEST_F(SysmanDevicePowerFixtureHelper, GivenValidPowerHandleWhenGettingPowerEnergyCounterThenValidPowerReadingsRetrieved) { + auto handles = getPowerHandles(powerHandleComponentCount); + for (auto handle : handles) { + zes_power_energy_counter_t energyCounter = {}; + ASSERT_EQ(ZE_RESULT_SUCCESS, zesPowerGetEnergyCounter(handle, &energyCounter)); + EXPECT_EQ(energyCounter.energy, expectedEnergyCounter); + } +} + +using SysmanDevicePowerMultiDeviceFixtureHelper = SysmanDevicePowerMultiDeviceFixture; + +TEST_F(SysmanDevicePowerMultiDeviceFixtureHelper, GivenValidDeviceHandlesAndHwmonInterfaceExistThenSuccessIsReturned) { + for (auto &deviceHandle : deviceHandles) { + ze_device_properties_t deviceProperties = {ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES}; + Device::fromHandle(deviceHandle)->getProperties(&deviceProperties); + PublicLinuxPowerImp *pPowerImp = new PublicLinuxPowerImp(pOsSysman, deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, deviceProperties.subdeviceId); + EXPECT_TRUE(pPowerImp->isPowerModuleSupported()); + delete pPowerImp; + } +} + +} // namespace ult +} // namespace L0 \ No newline at end of file diff --git a/level_zero/tools/test/unit_tests/sources/sysman/power/windows/test_zes_sysman_power.cpp b/level_zero/tools/test/unit_tests/sources/sysman/power/windows/test_zes_sysman_power.cpp index a2404ecb46..f1e8a85ea2 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/power/windows/test_zes_sysman_power.cpp +++ b/level_zero/tools/test/unit_tests/sources/sysman/power/windows/test_zes_sysman_power.cpp @@ -38,7 +38,16 @@ class SysmanDevicePowerFixture : public SysmanDeviceFixture { } pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); - pSysmanDeviceImp->pPowerHandleContext->init(); + uint32_t subDeviceCount = 0; + std::vector deviceHandles; + Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, nullptr); + if (subDeviceCount == 0) { + deviceHandles.resize(1, device->toHandle()); + } else { + deviceHandles.resize(subDeviceCount, nullptr); + Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, deviceHandles.data()); + } + pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles); } void TearDown() override { SysmanDeviceFixture::TearDown();