From e03b1581b91d5b5d7f27b7ffa3b95a529a6037f4 Mon Sep 17 00:00:00 2001 From: "Bari, Pratik" Date: Wed, 5 Apr 2023 08:28:11 +0000 Subject: [PATCH] Added support for the ECC APIs - Added support for the ECC APIs in the new sysman design. - Added ULTs for the ECC APIs in the new sysman design. Related-To: LOCI-4244 Signed-off-by: Bari, Pratik --- .../api/sysman/zes_sysman_api_entrypoints.h | 24 ++- level_zero/sysman/source/ecc/CMakeLists.txt | 15 ++ level_zero/sysman/source/ecc/ecc.h | 26 +++ level_zero/sysman/source/ecc/ecc_imp.cpp | 119 +++++++++++ level_zero/sysman/source/ecc/ecc_imp.h | 46 +++++ .../sysman/source/ecc/linux/CMakeLists.txt | 13 ++ level_zero/sysman/source/ecc/linux/os_ecc.cpp | 22 +++ .../sysman/source/ecc/windows/CMakeLists.txt | 13 ++ .../sysman/source/ecc/windows/os_ecc.cpp | 21 ++ level_zero/sysman/source/sysman_device.cpp | 20 ++ level_zero/sysman/source/sysman_device.h | 15 ++ .../sysman/source/sysman_device_imp.cpp | 15 ++ level_zero/sysman/source/sysman_device_imp.h | 5 + .../unit_tests/sources/ecc/CMakeLists.txt | 10 + .../sources/ecc/linux/CMakeLists.txt | 18 ++ .../unit_tests/sources/ecc/linux/mock_ecc.h | 67 +++++++ .../sources/ecc/linux/test_zes_ecc.cpp | 185 ++++++++++++++++++ 17 files changed, 630 insertions(+), 4 deletions(-) create mode 100644 level_zero/sysman/source/ecc/CMakeLists.txt create mode 100644 level_zero/sysman/source/ecc/ecc.h create mode 100644 level_zero/sysman/source/ecc/ecc_imp.cpp create mode 100644 level_zero/sysman/source/ecc/ecc_imp.h create mode 100644 level_zero/sysman/source/ecc/linux/CMakeLists.txt create mode 100644 level_zero/sysman/source/ecc/linux/os_ecc.cpp create mode 100755 level_zero/sysman/source/ecc/windows/CMakeLists.txt create mode 100644 level_zero/sysman/source/ecc/windows/os_ecc.cpp create mode 100644 level_zero/sysman/test/unit_tests/sources/ecc/CMakeLists.txt create mode 100644 level_zero/sysman/test/unit_tests/sources/ecc/linux/CMakeLists.txt create mode 100644 level_zero/sysman/test/unit_tests/sources/ecc/linux/mock_ecc.h create mode 100644 level_zero/sysman/test/unit_tests/sources/ecc/linux/test_zes_ecc.cpp diff --git a/level_zero/api/sysman/zes_sysman_api_entrypoints.h b/level_zero/api/sysman/zes_sysman_api_entrypoints.h index 3c1aa2abff..d2e5add975 100644 --- a/level_zero/api/sysman/zes_sysman_api_entrypoints.h +++ b/level_zero/api/sysman/zes_sysman_api_entrypoints.h @@ -938,26 +938,42 @@ ze_result_t zesPerformanceFactorSetConfig( ze_result_t zesDeviceEccAvailable( zes_device_handle_t hDevice, ze_bool_t *pAvailable) { - return L0::SysmanDevice::deviceEccAvailable(hDevice, pAvailable); + if (L0::sysmanInitFromCore) { + return L0::SysmanDevice::deviceEccAvailable(hDevice, pAvailable); + } else { + return L0::Sysman::SysmanDevice::deviceEccAvailable(hDevice, pAvailable); + } } ze_result_t zesDeviceEccConfigurable( zes_device_handle_t hDevice, ze_bool_t *pConfigurable) { - return L0::SysmanDevice::deviceEccConfigurable(hDevice, pConfigurable); + if (L0::sysmanInitFromCore) { + return L0::SysmanDevice::deviceEccConfigurable(hDevice, pConfigurable); + } else { + return L0::Sysman::SysmanDevice::deviceEccConfigurable(hDevice, pConfigurable); + } } ze_result_t zesDeviceGetEccState( zes_device_handle_t hDevice, zes_device_ecc_properties_t *pState) { - return L0::SysmanDevice::deviceGetEccState(hDevice, pState); + if (L0::sysmanInitFromCore) { + return L0::SysmanDevice::deviceGetEccState(hDevice, pState); + } else { + return L0::Sysman::SysmanDevice::deviceGetEccState(hDevice, pState); + } } ze_result_t zesDeviceSetEccState( zes_device_handle_t hDevice, const zes_device_ecc_desc_t *newState, zes_device_ecc_properties_t *pState) { - return L0::SysmanDevice::deviceSetEccState(hDevice, newState, pState); + if (L0::sysmanInitFromCore) { + return L0::SysmanDevice::deviceSetEccState(hDevice, newState, pState); + } else { + return L0::Sysman::SysmanDevice::deviceSetEccState(hDevice, newState, pState); + } } ze_result_t zesOverclockGetDomainProperties( diff --git a/level_zero/sysman/source/ecc/CMakeLists.txt b/level_zero/sysman/source/ecc/CMakeLists.txt new file mode 100644 index 0000000000..f68ef06be0 --- /dev/null +++ b/level_zero/sysman/source/ecc/CMakeLists.txt @@ -0,0 +1,15 @@ +# +# Copyright (C) 2023 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +target_sources(${L0_STATIC_LIB_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/ecc.h + ${CMAKE_CURRENT_SOURCE_DIR}/ecc_imp.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ecc_imp.h +) + +add_subdirectories() diff --git a/level_zero/sysman/source/ecc/ecc.h b/level_zero/sysman/source/ecc/ecc.h new file mode 100644 index 0000000000..ab2d3eabc1 --- /dev/null +++ b/level_zero/sysman/source/ecc/ecc.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include + +namespace L0 { +namespace Sysman { + +class Ecc { + public: + virtual ~Ecc() = default; + virtual ze_result_t deviceEccAvailable(ze_bool_t *pAvailable) = 0; + virtual ze_result_t deviceEccConfigurable(ze_bool_t *pConfigurable) = 0; + virtual ze_result_t getEccState(zes_device_ecc_properties_t *pState) = 0; + virtual ze_result_t setEccState(const zes_device_ecc_desc_t *newState, zes_device_ecc_properties_t *pState) = 0; + + virtual void init() = 0; +}; + +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/ecc/ecc_imp.cpp b/level_zero/sysman/source/ecc/ecc_imp.cpp new file mode 100644 index 0000000000..d0384c37b8 --- /dev/null +++ b/level_zero/sysman/source/ecc/ecc_imp.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/sysman/source/ecc/ecc_imp.h" + +#include "level_zero/sysman/source/firmware_util/firmware_util.h" + +namespace L0 { +namespace Sysman { +zes_device_ecc_state_t EccImp::getEccState(uint8_t state) { + switch (state) { + case eccStateEnable: + return ZES_DEVICE_ECC_STATE_ENABLED; + case eccStateDisable: + return ZES_DEVICE_ECC_STATE_DISABLED; + default: + return ZES_DEVICE_ECC_STATE_UNAVAILABLE; + } +} + +ze_result_t EccImp::getEccFwUtilInterface(FirmwareUtil *&pFwUtil) { + pFwUtil = getFirmwareUtilInterface(pOsSysman); + if (pFwUtil == nullptr) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + return ZE_RESULT_SUCCESS; +} + +ze_result_t EccImp::deviceEccAvailable(ze_bool_t *pAvailable) { + if (pFwInterface == nullptr) { + ze_result_t result = getEccFwUtilInterface(pFwInterface); + if (result != ZE_RESULT_SUCCESS) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + } + + *pAvailable = false; + uint8_t currentState = 0; + uint8_t pendingState = 0; + ze_result_t result = pFwInterface->fwGetEccConfig(¤tState, &pendingState); + if (ZE_RESULT_SUCCESS == result) { + if ((currentState != eccStateNone) && (pendingState != eccStateNone)) { + *pAvailable = true; + } + } + + return result; +} + +ze_result_t EccImp::deviceEccConfigurable(ze_bool_t *pConfigurable) { + return deviceEccAvailable(pConfigurable); +} + +ze_result_t EccImp::getEccState(zes_device_ecc_properties_t *pState) { + if (pFwInterface == nullptr) { + ze_result_t result = getEccFwUtilInterface(pFwInterface); + if (result != ZE_RESULT_SUCCESS) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + } + + uint8_t currentState = 0; + uint8_t pendingState = 0; + ze_result_t result = pFwInterface->fwGetEccConfig(¤tState, &pendingState); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + pState->currentState = getEccState(currentState); + pState->pendingState = getEccState(pendingState); + + pState->pendingAction = ZES_DEVICE_ACTION_WARM_CARD_RESET; + if (pState->currentState == pState->pendingState) { + pState->pendingAction = ZES_DEVICE_ACTION_NONE; + } + + return result; +} + +ze_result_t EccImp::setEccState(const zes_device_ecc_desc_t *newState, zes_device_ecc_properties_t *pState) { + if (pFwInterface == nullptr) { + ze_result_t result = getEccFwUtilInterface(pFwInterface); + if (result != ZE_RESULT_SUCCESS) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + } + + uint8_t state = 0; + uint8_t currentState = 0; + uint8_t pendingState = 0; + if (newState->state == ZES_DEVICE_ECC_STATE_ENABLED) { + state = eccStateEnable; + } else if (newState->state == ZES_DEVICE_ECC_STATE_DISABLED) { + state = eccStateDisable; + } else { + return ZE_RESULT_ERROR_INVALID_ENUMERATION; + } + + ze_result_t result = pFwInterface->fwSetEccConfig(state, ¤tState, &pendingState); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + + pState->currentState = getEccState(currentState); + pState->pendingState = getEccState(pendingState); + + pState->pendingAction = ZES_DEVICE_ACTION_WARM_CARD_RESET; + if (pState->currentState == pState->pendingState) { + pState->pendingAction = ZES_DEVICE_ACTION_NONE; + } + + return result; +} + +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/ecc/ecc_imp.h b/level_zero/sysman/source/ecc/ecc_imp.h new file mode 100644 index 0000000000..91662028af --- /dev/null +++ b/level_zero/sysman/source/ecc/ecc_imp.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "shared/source/helpers/non_copyable_or_moveable.h" + +#include "level_zero/sysman/source/ecc/ecc.h" +#include "level_zero/sysman/source/os_sysman.h" + +namespace L0 { +namespace Sysman { +class FirmwareUtil; +struct OsSysman; + +class EccImp : public Ecc, NEO::NonCopyableOrMovableClass { + public: + void init() override {} + ze_result_t deviceEccAvailable(ze_bool_t *pAvailable) override; + ze_result_t deviceEccConfigurable(ze_bool_t *pConfigurable) override; + ze_result_t getEccState(zes_device_ecc_properties_t *pState) override; + ze_result_t setEccState(const zes_device_ecc_desc_t *newState, zes_device_ecc_properties_t *pState) override; + + EccImp(OsSysman *pOsSysman) : pOsSysman(pOsSysman){}; + ~EccImp() override {} + + private: + OsSysman *pOsSysman = nullptr; + FirmwareUtil *pFwInterface = nullptr; + + enum eccState : uint8_t { + eccStateDisable = 0, + eccStateEnable = 1, + eccStateNone = 0xFF + }; + + zes_device_ecc_state_t getEccState(uint8_t state); + static FirmwareUtil *getFirmwareUtilInterface(OsSysman *pOsSysman); + ze_result_t getEccFwUtilInterface(FirmwareUtil *&pFwUtil); +}; + +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/ecc/linux/CMakeLists.txt b/level_zero/sysman/source/ecc/linux/CMakeLists.txt new file mode 100644 index 0000000000..1d87991f53 --- /dev/null +++ b/level_zero/sysman/source/ecc/linux/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Copyright (C) 2023 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +if(UNIX) + target_sources(${L0_STATIC_LIB_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/os_ecc.cpp + ) +endif() diff --git a/level_zero/sysman/source/ecc/linux/os_ecc.cpp b/level_zero/sysman/source/ecc/linux/os_ecc.cpp new file mode 100644 index 0000000000..59b2c9d82a --- /dev/null +++ b/level_zero/sysman/source/ecc/linux/os_ecc.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/sysman/source/ecc/ecc_imp.h" +#include "level_zero/sysman/source/linux/os_sysman_imp.h" + +namespace L0 { +namespace Sysman { +class LinuxSysmanImp; +class FirmwareUtil; + +FirmwareUtil *EccImp::getFirmwareUtilInterface(OsSysman *pOsSysman) { + LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); + return pLinuxSysmanImp->getFwUtilInterface(); +} + +} // namespace Sysman +} // namespace L0 \ No newline at end of file diff --git a/level_zero/sysman/source/ecc/windows/CMakeLists.txt b/level_zero/sysman/source/ecc/windows/CMakeLists.txt new file mode 100755 index 0000000000..db84959f2c --- /dev/null +++ b/level_zero/sysman/source/ecc/windows/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Copyright (C) 2023 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +if(WIN32) + target_sources(${L0_STATIC_LIB_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/os_ecc.cpp + ) +endif() diff --git a/level_zero/sysman/source/ecc/windows/os_ecc.cpp b/level_zero/sysman/source/ecc/windows/os_ecc.cpp new file mode 100644 index 0000000000..b0fbfc5fd4 --- /dev/null +++ b/level_zero/sysman/source/ecc/windows/os_ecc.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/sysman/source/ecc/ecc_imp.h" +#include "level_zero/sysman/source/windows/os_sysman_imp.h" + +namespace L0 { +namespace Sysman { +class WddmSysmanImp; +class FirmwareUtil; + +FirmwareUtil *EccImp::getFirmwareUtilInterface(OsSysman *pOsSysman) { + return nullptr; +} + +} // namespace Sysman +} // namespace L0 \ No newline at end of file diff --git a/level_zero/sysman/source/sysman_device.cpp b/level_zero/sysman/source/sysman_device.cpp index 0d74ea28ba..fde0be7d01 100644 --- a/level_zero/sysman/source/sysman_device.cpp +++ b/level_zero/sysman/source/sysman_device.cpp @@ -99,5 +99,25 @@ ze_result_t SysmanDevice::standbyGet(zes_device_handle_t hDevice, uint32_t *pCou return pSysmanDevice->standbyGet(pCount, phStandby); } +ze_result_t SysmanDevice::deviceEccAvailable(zes_device_handle_t hDevice, ze_bool_t *pAvailable) { + auto pSysmanDevice = L0::Sysman::SysmanDevice::fromHandle(hDevice); + return pSysmanDevice->deviceEccAvailable(pAvailable); +} + +ze_result_t SysmanDevice::deviceEccConfigurable(zes_device_handle_t hDevice, ze_bool_t *pConfigurable) { + auto pSysmanDevice = L0::Sysman::SysmanDevice::fromHandle(hDevice); + return pSysmanDevice->deviceEccConfigurable(pConfigurable); +} + +ze_result_t SysmanDevice::deviceGetEccState(zes_device_handle_t hDevice, zes_device_ecc_properties_t *pState) { + auto pSysmanDevice = L0::Sysman::SysmanDevice::fromHandle(hDevice); + return pSysmanDevice->deviceGetEccState(pState); +} + +ze_result_t SysmanDevice::deviceSetEccState(zes_device_handle_t hDevice, const zes_device_ecc_desc_t *newState, zes_device_ecc_properties_t *pState) { + auto pSysmanDevice = L0::Sysman::SysmanDevice::fromHandle(hDevice); + return pSysmanDevice->deviceSetEccState(newState, pState); +} + } // namespace Sysman } // namespace L0 diff --git a/level_zero/sysman/source/sysman_device.h b/level_zero/sysman/source/sysman_device.h index a0056f726a..9622cd0d91 100644 --- a/level_zero/sysman/source/sysman_device.h +++ b/level_zero/sysman/source/sysman_device.h @@ -10,6 +10,7 @@ #include "level_zero/core/source/device/device.h" #include "level_zero/sysman/source/diagnostics/diagnostics.h" +#include "level_zero/sysman/source/ecc/ecc.h" #include "level_zero/sysman/source/engine/engine.h" #include "level_zero/sysman/source/fabric_port/fabric_port.h" #include "level_zero/sysman/source/firmware/firmware.h" @@ -35,8 +36,10 @@ struct SysmanDevice : _ze_device_handle_t { static ze_result_t powerGet(zes_device_handle_t hDevice, uint32_t *pCount, zes_pwr_handle_t *phPower); virtual ze_result_t powerGet(uint32_t *pCount, zes_pwr_handle_t *phPower) = 0; + static ze_result_t powerGetCardDomain(zes_device_handle_t hDevice, zes_pwr_handle_t *phPower); virtual ze_result_t powerGetCardDomain(zes_pwr_handle_t *phPower) = 0; + static ze_result_t fabricPortGet(zes_device_handle_t hDevice, uint32_t *pCount, zes_fabric_port_handle_t *phPort); virtual ze_result_t fabricPortGet(uint32_t *pCount, zes_fabric_port_handle_t *phPort) = 0; @@ -75,6 +78,18 @@ struct SysmanDevice : _ze_device_handle_t { static ze_result_t standbyGet(zes_device_handle_t hDevice, uint32_t *pCount, zes_standby_handle_t *phStandby); virtual ze_result_t standbyGet(uint32_t *pCount, zes_standby_handle_t *phStandby) = 0; + + static ze_result_t deviceEccAvailable(zes_device_handle_t hDevice, ze_bool_t *pAvailable); + virtual ze_result_t deviceEccAvailable(ze_bool_t *pAvailable) = 0; + + static ze_result_t deviceEccConfigurable(zes_device_handle_t hDevice, ze_bool_t *pConfigurable); + virtual ze_result_t deviceEccConfigurable(ze_bool_t *pConfigurable) = 0; + + static ze_result_t deviceGetEccState(zes_device_handle_t hDevice, zes_device_ecc_properties_t *pState); + virtual ze_result_t deviceGetEccState(zes_device_ecc_properties_t *pState) = 0; + + static ze_result_t deviceSetEccState(zes_device_handle_t hDevice, const zes_device_ecc_desc_t *newState, zes_device_ecc_properties_t *pState); + virtual ze_result_t deviceSetEccState(const zes_device_ecc_desc_t *newState, zes_device_ecc_properties_t *pState) = 0; }; } // namespace Sysman diff --git a/level_zero/sysman/source/sysman_device_imp.cpp b/level_zero/sysman/source/sysman_device_imp.cpp index bb001bd125..74d05964c7 100644 --- a/level_zero/sysman/source/sysman_device_imp.cpp +++ b/level_zero/sysman/source/sysman_device_imp.cpp @@ -9,6 +9,7 @@ #include "shared/source/helpers/debug_helpers.h" +#include "level_zero/sysman/source/ecc/ecc_imp.h" #include "level_zero/sysman/source/global_operations/global_operations_imp.h" #include "level_zero/sysman/source/os_sysman.h" @@ -33,6 +34,7 @@ SysmanDeviceImp::SysmanDeviceImp(NEO::ExecutionEnvironment *executionEnvironment pDiagnosticsHandleContext = new DiagnosticsHandleContext(pOsSysman); pGlobalOperations = new GlobalOperationsImp(pOsSysman); pStandbyHandleContext = new StandbyHandleContext(pOsSysman); + pEcc = new EccImp(pOsSysman); } SysmanDeviceImp::~SysmanDeviceImp() { @@ -47,6 +49,7 @@ SysmanDeviceImp::~SysmanDeviceImp() { freeResource(pMemoryHandleContext); freeResource(pFabricPortHandleContext); freeResource(pStandbyHandleContext); + freeResource(pEcc); freeResource(pOsSysman); executionEnvironment->decRefInternal(); } @@ -114,6 +117,18 @@ ze_result_t SysmanDeviceImp::firmwareGet(uint32_t *pCount, zes_firmware_handle_t ze_result_t SysmanDeviceImp::diagnosticsGet(uint32_t *pCount, zes_diag_handle_t *phDiagnostics) { return pDiagnosticsHandleContext->diagnosticsGet(pCount, phDiagnostics); } +ze_result_t SysmanDeviceImp::deviceEccAvailable(ze_bool_t *pAvailable) { + return pEcc->deviceEccAvailable(pAvailable); +} +ze_result_t SysmanDeviceImp::deviceEccConfigurable(ze_bool_t *pConfigurable) { + return pEcc->deviceEccConfigurable(pConfigurable); +} +ze_result_t SysmanDeviceImp::deviceGetEccState(zes_device_ecc_properties_t *pState) { + return pEcc->getEccState(pState); +} +ze_result_t SysmanDeviceImp::deviceSetEccState(const zes_device_ecc_desc_t *newState, zes_device_ecc_properties_t *pState) { + return pEcc->setEccState(newState, pState); +} ze_result_t SysmanDeviceImp::standbyGet(uint32_t *pCount, zes_standby_handle_t *phStandby) { return pStandbyHandleContext->standbyGet(pCount, phStandby); diff --git a/level_zero/sysman/source/sysman_device_imp.h b/level_zero/sysman/source/sysman_device_imp.h index 3b553b9b8b..c6c943f6e5 100644 --- a/level_zero/sysman/source/sysman_device_imp.h +++ b/level_zero/sysman/source/sysman_device_imp.h @@ -48,6 +48,7 @@ struct SysmanDeviceImp : SysmanDevice, NEO::NonCopyableOrMovableClass { DiagnosticsHandleContext *pDiagnosticsHandleContext = nullptr; FrequencyHandleContext *pFrequencyHandleContext = nullptr; StandbyHandleContext *pStandbyHandleContext = nullptr; + Ecc *pEcc = nullptr; ze_result_t powerGet(uint32_t *pCount, zes_pwr_handle_t *phPower) override; ze_result_t powerGetCardDomain(zes_pwr_handle_t *phPower) override; @@ -64,6 +65,10 @@ struct SysmanDeviceImp : SysmanDevice, NEO::NonCopyableOrMovableClass { ze_result_t deviceReset(ze_bool_t force) override; ze_result_t deviceGetState(zes_device_state_t *pState) override; ze_result_t standbyGet(uint32_t *pCount, zes_standby_handle_t *phStandby) override; + ze_result_t deviceEccAvailable(ze_bool_t *pAvailable) override; + ze_result_t deviceEccConfigurable(ze_bool_t *pConfigurable) override; + ze_result_t deviceGetEccState(zes_device_ecc_properties_t *pState) override; + ze_result_t deviceSetEccState(const zes_device_ecc_desc_t *newState, zes_device_ecc_properties_t *pState) override; private: NEO::ExecutionEnvironment *executionEnvironment = nullptr; diff --git a/level_zero/sysman/test/unit_tests/sources/ecc/CMakeLists.txt b/level_zero/sysman/test/unit_tests/sources/ecc/CMakeLists.txt new file mode 100644 index 0000000000..9704dc6ade --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/ecc/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# Copyright (C) 2023 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +target_sources(${TARGET_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt +) +add_subdirectories() diff --git a/level_zero/sysman/test/unit_tests/sources/ecc/linux/CMakeLists.txt b/level_zero/sysman/test/unit_tests/sources/ecc/linux/CMakeLists.txt new file mode 100644 index 0000000000..fb0d763eeb --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/ecc/linux/CMakeLists.txt @@ -0,0 +1,18 @@ +# +# Copyright (C) 2023 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +set(L0_TESTS_SYSMAN_ECC_LINUX + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/test_zes_ecc.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/mock_ecc.h +) + +if(UNIX) + target_sources(${TARGET_NAME} + PRIVATE + ${L0_TESTS_SYSMAN_ECC_LINUX} + ) +endif() diff --git a/level_zero/sysman/test/unit_tests/sources/ecc/linux/mock_ecc.h b/level_zero/sysman/test/unit_tests/sources/ecc/linux/mock_ecc.h new file mode 100644 index 0000000000..ab79c0bc67 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/ecc/linux/mock_ecc.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "shared/test/common/test_macros/mock_method_macros.h" + +#include "level_zero/sysman/source/ecc/ecc_imp.h" +#include "level_zero/sysman/source/firmware_util/firmware_util.h" +#include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_fixture.h" + +namespace L0 { +namespace ult { + +struct MockEccFwInterface : public L0::Sysman::FirmwareUtil { + ze_result_t mockFwGetEccConfigResult = ZE_RESULT_SUCCESS; + ze_result_t mockFwSetEccConfigResult = ZE_RESULT_SUCCESS; + + ze_bool_t mockSetConfig = true; + uint8_t mockCurrentState = 0; + uint8_t mockPendingState = 0; + + ze_result_t fwGetEccConfig(uint8_t *currentState, uint8_t *pendingState) override { + if (mockFwGetEccConfigResult != ZE_RESULT_SUCCESS) { + return mockFwGetEccConfigResult; + } + + *currentState = mockCurrentState; + *pendingState = mockPendingState; + + return ZE_RESULT_SUCCESS; + } + + ze_result_t fwSetEccConfig(uint8_t newState, uint8_t *currentState, uint8_t *pendingState) override { + if (mockFwSetEccConfigResult != ZE_RESULT_SUCCESS) { + return mockFwSetEccConfigResult; + } + + if (mockSetConfig == true) { + mockPendingState = newState; + } + *currentState = mockCurrentState; + *pendingState = mockPendingState; + + return ZE_RESULT_SUCCESS; + } + + ADDMETHOD_NOBASE(getFirstDevice, ze_result_t, ZE_RESULT_SUCCESS, (igsc_device_info * info)); + ADDMETHOD_NOBASE(getFwVersion, ze_result_t, ZE_RESULT_SUCCESS, (std::string fwType, std::string &firmwareVersion)); + ADDMETHOD_NOBASE(flashFirmware, ze_result_t, ZE_RESULT_SUCCESS, (std::string fwType, void *pImage, uint32_t size)); + ADDMETHOD_NOBASE(fwIfrApplied, ze_result_t, ZE_RESULT_SUCCESS, (bool &ifrStatus)); + ADDMETHOD_NOBASE(fwSupportedDiagTests, ze_result_t, ZE_RESULT_SUCCESS, (std::vector & supportedDiagTests)); + ADDMETHOD_NOBASE(fwRunDiagTests, ze_result_t, ZE_RESULT_SUCCESS, (std::string & osDiagType, zes_diag_result_t *pResult)); + ADDMETHOD_NOBASE(fwDeviceInit, ze_result_t, ZE_RESULT_SUCCESS, ()); + ADDMETHOD_NOBASE(fwGetMemoryErrorCount, ze_result_t, ZE_RESULT_SUCCESS, (zes_ras_error_type_t category, uint32_t subDeviceCount, uint32_t subDeviceId, uint64_t &count)); + ADDMETHOD_NOBASE_VOIDRETURN(getDeviceSupportedFwTypes, (std::vector & fwTypes)); + ADDMETHOD_NOBASE_VOIDRETURN(fwGetMemoryHealthIndicator, (zes_mem_health_t * health)); + + MockEccFwInterface() = default; + ~MockEccFwInterface() override = default; +}; + +} // namespace ult +} // namespace L0 diff --git a/level_zero/sysman/test/unit_tests/sources/ecc/linux/test_zes_ecc.cpp b/level_zero/sysman/test/unit_tests/sources/ecc/linux/test_zes_ecc.cpp new file mode 100644 index 0000000000..db0468e00a --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/ecc/linux/test_zes_ecc.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/os_interface/driver_info.h" + +#include "level_zero/sysman/test/unit_tests/sources/ecc/linux/mock_ecc.h" + +namespace L0 { +namespace ult { + +enum eccState : uint8_t { + eccStateEnable = 1, + eccStateNone = 0xFF +}; + +class ZesEccFixture : public SysmanDeviceFixture { + protected: + L0::Sysman::SysmanDevice *device = nullptr; + std::unique_ptr pMockFwInterface; + L0::Sysman::FirmwareUtil *pFwUtilInterfaceOld = nullptr; + L0::Sysman::EccImp *pEccImp; + + void SetUp() override { + SysmanDeviceFixture::SetUp(); + device = pSysmanDevice; + pFwUtilInterfaceOld = pLinuxSysmanImp->pFwUtilInterface; + pMockFwInterface = std::make_unique(); + pLinuxSysmanImp->pFwUtilInterface = pMockFwInterface.get(); + + pEccImp = static_cast(pSysmanDeviceImp->pEcc); + } + + void TearDown() override { + pEccImp = nullptr; + + pLinuxSysmanImp->pFwUtilInterface = pFwUtilInterfaceOld; + SysmanDeviceFixture::TearDown(); + } +}; + +TEST_F(ZesEccFixture, GivenValidSysmanHandleAndFwInterfaceIsPresentWhenCallingzesDeviceEccAvailableThenVerifyApiCallSucceeds) { + ze_bool_t eccAvailable = false; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEccAvailable(device, &eccAvailable)); + EXPECT_EQ(true, eccAvailable); +} + +TEST_F(ZesEccFixture, GivenValidSysmanHandleAndFwInterfaceIsPresentWhenCallingzesDeviceEccConfigurableThenVerifyApiCallSucceeds) { + ze_bool_t eccConfigurable = false; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEccConfigurable(device, &eccConfigurable)); + EXPECT_EQ(true, eccConfigurable); +} + +TEST_F(ZesEccFixture, GivenValidSysmanHandleAndFwInterfaceIsAbsentWhenCallingEccApiThenVerifyApiCallReturnFailure) { + ze_bool_t eccConfigurable = true; + ze_bool_t eccAvailable = true; + L0::Sysman::EccImp *tempEccImp = new L0::Sysman::EccImp(pOsSysman); + pLinuxSysmanImp->pFwUtilInterface = nullptr; + tempEccImp->init(); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, tempEccImp->deviceEccAvailable(&eccAvailable)); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, tempEccImp->deviceEccConfigurable(&eccConfigurable)); + + zes_device_ecc_desc_t newState = {}; + zes_device_ecc_properties_t props = {}; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, tempEccImp->setEccState(&newState, &props)); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, tempEccImp->getEccState(&props)); + delete tempEccImp; +} + +TEST_F(ZesEccFixture, GivenValidSysmanHandleAndFwGetEccConfigFailsWhenCallingzesDeviceEccConfigurableAndAvailableThenVerifyApiCallReturnsFailure) { + ze_bool_t eccConfigurable = true; + ze_bool_t eccAvailable = true; + pMockFwInterface->mockFwGetEccConfigResult = ZE_RESULT_ERROR_UNINITIALIZED; + + EXPECT_EQ(ZE_RESULT_ERROR_UNINITIALIZED, zesDeviceEccAvailable(device, &eccAvailable)); + EXPECT_EQ(ZE_RESULT_ERROR_UNINITIALIZED, zesDeviceEccConfigurable(device, &eccConfigurable)); +} + +TEST_F(ZesEccFixture, GivenValidSysmanHandleAndCurrentStateIsNoneWhenCallingzesDeviceEccConfigurableAndAvailableThenNotSupportedEccIsReturned) { + ze_bool_t eccConfigurable = true; + ze_bool_t eccAvailable = true; + pMockFwInterface->mockCurrentState = eccStateNone; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEccAvailable(device, &eccAvailable)); + EXPECT_EQ(false, eccAvailable); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEccConfigurable(device, &eccConfigurable)); + EXPECT_EQ(false, eccConfigurable); +} + +TEST_F(ZesEccFixture, GivenValidSysmanHandleAndPendingStateIsNoneWhenCallingzesDeviceEccConfigurableAndAvailableThenNotSupportedEccIsReturned) { + ze_bool_t eccConfigurable = true; + ze_bool_t eccAvailable = true; + pMockFwInterface->mockPendingState = eccStateNone; + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEccAvailable(device, &eccAvailable)); + EXPECT_EQ(false, eccAvailable); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEccConfigurable(device, &eccConfigurable)); + EXPECT_EQ(false, eccConfigurable); +} + +TEST_F(ZesEccFixture, GivenValidSysmanHandleAndFwInterfaceIsPresentWhenCallingzesDeviceGetEccStateThenApiCallSucceeds) { + zes_device_ecc_properties_t props = {}; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceGetEccState(device, &props)); + EXPECT_EQ(ZES_DEVICE_ECC_STATE_DISABLED, props.currentState); + EXPECT_EQ(ZES_DEVICE_ECC_STATE_DISABLED, props.pendingState); + EXPECT_EQ(ZES_DEVICE_ACTION_NONE, props.pendingAction); +} + +TEST_F(ZesEccFixture, GivenValidSysmanHandleAndFwGetEccConfigFailsWhenCallingzesDeviceGetEccStateThenApiCallReturnFailure) { + zes_device_ecc_properties_t props = {}; + pMockFwInterface->mockFwGetEccConfigResult = ZE_RESULT_ERROR_UNINITIALIZED; + EXPECT_EQ(ZE_RESULT_ERROR_UNINITIALIZED, zesDeviceGetEccState(device, &props)); +} + +TEST_F(ZesEccFixture, GivenValidSysmanHandleAndFwInterfaceIsPresentWhenCallingzesDeviceSetEccStateThenApiCallSucceeds) { + zes_device_ecc_desc_t newState = {ZES_STRUCTURE_TYPE_DEVICE_STATE, nullptr, ZES_DEVICE_ECC_STATE_ENABLED}; + zes_device_ecc_properties_t props = {}; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceSetEccState(device, &newState, &props)); + + newState.state = ZES_DEVICE_ECC_STATE_DISABLED; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceSetEccState(device, &newState, &props)); +} + +TEST_F(ZesEccFixture, GivenValidSysmanHandleAndFwInterfaceIsPresentWhenCallingzesDeviceSetEccStateWithInvalidEnumThenFailureIsReturned) { + zes_device_ecc_desc_t newState = {ZES_STRUCTURE_TYPE_DEVICE_STATE, nullptr, ZES_DEVICE_ECC_STATE_UNAVAILABLE}; + zes_device_ecc_properties_t props = {}; + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ENUMERATION, zesDeviceSetEccState(device, &newState, &props)); +} + +TEST_F(ZesEccFixture, GivenValidSysmanHandleAndFwSetEccConfigFailsWhenCallingzesDeviceSetEccStateThenFailureIsReturned) { + zes_device_ecc_desc_t newState = {ZES_STRUCTURE_TYPE_DEVICE_STATE, nullptr, ZES_DEVICE_ECC_STATE_ENABLED}; + zes_device_ecc_properties_t props = {}; + pMockFwInterface->mockFwSetEccConfigResult = ZE_RESULT_ERROR_UNINITIALIZED; + EXPECT_EQ(ZE_RESULT_ERROR_UNINITIALIZED, zesDeviceSetEccState(device, &newState, &props)); +} + +TEST_F(ZesEccFixture, GivenValidSysmanHandleWhenCallingEccSetStateAndEccGetStateThenVerifyApiCallSuccedsAndValidStatesAreReturned) { + zes_device_ecc_desc_t newState = {ZES_STRUCTURE_TYPE_DEVICE_STATE, nullptr, ZES_DEVICE_ECC_STATE_ENABLED}; + zes_device_ecc_properties_t props = {}; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceSetEccState(device, &newState, &props)); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceGetEccState(device, &props)); + EXPECT_EQ(ZES_DEVICE_ECC_STATE_ENABLED, props.pendingState); + + newState.state = ZES_DEVICE_ECC_STATE_DISABLED; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceSetEccState(device, &newState, &props)); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceGetEccState(device, &props)); + EXPECT_EQ(ZES_DEVICE_ECC_STATE_DISABLED, props.pendingState); + + pMockFwInterface->mockSetConfig = false; + pMockFwInterface->mockCurrentState = eccStateNone; + pMockFwInterface->mockPendingState = eccStateNone; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceSetEccState(device, &newState, &props)); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceGetEccState(device, &props)); + EXPECT_EQ(ZES_DEVICE_ECC_STATE_UNAVAILABLE, props.pendingState); + EXPECT_EQ(ZES_DEVICE_ECC_STATE_UNAVAILABLE, props.currentState); +} + +TEST_F(ZesEccFixture, GivenValidSysmanHandleWhenCallingEccSetStateAndEccGetStateThenVerifyApiCallSuccedsAndValidActionIsReturned) { + zes_device_ecc_desc_t newState = {ZES_STRUCTURE_TYPE_DEVICE_STATE, nullptr, ZES_DEVICE_ECC_STATE_ENABLED}; + zes_device_ecc_properties_t props = {}; + pMockFwInterface->mockCurrentState = eccStateEnable; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceSetEccState(device, &newState, &props)); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceGetEccState(device, &props)); + EXPECT_EQ(ZES_DEVICE_ECC_STATE_ENABLED, props.pendingState); + EXPECT_EQ(ZES_DEVICE_ACTION_NONE, props.pendingAction); + + newState.state = ZES_DEVICE_ECC_STATE_DISABLED; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceSetEccState(device, &newState, &props)); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceGetEccState(device, &props)); + EXPECT_EQ(ZES_DEVICE_ECC_STATE_DISABLED, props.pendingState); + EXPECT_EQ(ZES_DEVICE_ACTION_WARM_CARD_RESET, props.pendingAction); +} + +} // namespace ult +} // namespace L0