refactor: Merge Prelim and non-prelim files for scheduler

Related-To: NEO-11203

Signed-off-by: Bellekallu Rajkiran <bellekallu.rajkiran@intel.com>
This commit is contained in:
Bellekallu Rajkiran
2024-05-02 12:56:55 +00:00
committed by Compute-Runtime-Automation
parent e8afccd071
commit f18cb701d3
11 changed files with 99 additions and 2344 deletions

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2020-2023 Intel Corporation
# Copyright (C) 2020-2024 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
@@ -9,17 +9,6 @@ if(UNIX)
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/sysman_os_scheduler_imp.h
${CMAKE_CURRENT_SOURCE_DIR}/sysman_os_scheduler_imp.cpp
)
if(NEO_ENABLE_i915_PRELIM_DETECTION)
target_sources(${L0_STATIC_LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/sysman_os_scheduler_imp_prelim.cpp
)
else()
target_sources(${L0_STATIC_LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/sysman_os_scheduler_imp.cpp
)
endif()
endif()

View File

@@ -1,571 +0,0 @@
/*
* Copyright (C) 2022-2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/debug_settings/debug_settings_manager.h"
#include "shared/source/os_interface/linux/engine_info.h"
#include "shared/source/os_interface/linux/i915_prelim.h"
#include "level_zero/sysman/source/api/scheduler/linux/sysman_os_scheduler_imp.h"
#include "level_zero/sysman/source/shared/linux/sysman_fs_access_interface.h"
#include "level_zero/sysman/source/shared/linux/zes_os_sysman_imp.h"
#include "level_zero/sysman/source/sysman_const.h"
namespace L0 {
namespace Sysman {
const std::string LinuxSchedulerImp::preemptTimeoutMilliSecs("preempt_timeout_ms");
const std::string LinuxSchedulerImp::defaultPreemptTimeouttMilliSecs(".defaults/preempt_timeout_ms");
const std::string LinuxSchedulerImp::timesliceDurationMilliSecs("timeslice_duration_ms");
const std::string LinuxSchedulerImp::defaultTimesliceDurationMilliSecs(".defaults/timeslice_duration_ms");
const std::string LinuxSchedulerImp::heartbeatIntervalMilliSecs("heartbeat_interval_ms");
const std::string LinuxSchedulerImp::defaultHeartbeatIntervalMilliSecs(".defaults/heartbeat_interval_ms");
const std::string LinuxSchedulerImp::engineDir("engine");
const std::string LinuxSchedulerImp::enableEuDebug("prelim_enable_eu_debug");
constexpr uint16_t milliSecsToMicroSecs = 1000;
static const std::map<__u16, std::string> i915EngineClassToSysfsEngineMap = {
{drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER, "rcs"},
{static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_COMPUTE), "ccs"},
{drm_i915_gem_engine_class::I915_ENGINE_CLASS_COPY, "bcs"},
{drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO, "vcs"},
{drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO_ENHANCE, "vecs"}};
static const std::map<std::string, zes_engine_type_flag_t> sysfsEngineMapToLevel0EngineType = {
{"rcs", ZES_ENGINE_TYPE_FLAG_RENDER},
{"ccs", ZES_ENGINE_TYPE_FLAG_COMPUTE},
{"bcs", ZES_ENGINE_TYPE_FLAG_DMA},
{"vcs", ZES_ENGINE_TYPE_FLAG_MEDIA},
{"vecs", ZES_ENGINE_TYPE_FLAG_OTHER}};
static const std::multimap<zes_engine_type_flag_t, std::string> level0EngineTypeToSysfsEngineMap = {
{ZES_ENGINE_TYPE_FLAG_RENDER, "rcs"},
{ZES_ENGINE_TYPE_FLAG_COMPUTE, "ccs"},
{ZES_ENGINE_TYPE_FLAG_DMA, "bcs"},
{ZES_ENGINE_TYPE_FLAG_MEDIA, "vcs"},
{ZES_ENGINE_TYPE_FLAG_OTHER, "vecs"}};
static const std::map<std::string, __u16> sysfsEngineMapToi915EngineClass = {
{"rcs", drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER},
{"ccs", static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_COMPUTE)},
{"bcs", drm_i915_gem_engine_class::I915_ENGINE_CLASS_COPY},
{"vcs", drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO},
{"vecs", drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO_ENHANCE}};
ze_result_t LinuxSchedulerImp::getCurrentMode(zes_sched_mode_t *pMode) {
uint64_t timeout = 0;
uint64_t timeslice = 0;
uint64_t heartbeat = 0;
ze_result_t result = getPreemptTimeout(timeout, false);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to get preempt timeout and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
result = getTimesliceDuration(timeslice, false);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to get timeslice duration and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
result = getHeartbeatInterval(heartbeat, false);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to get heartbeat interval and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
if (timeslice > 0) {
*pMode = ZES_SCHED_MODE_TIMESLICE;
} else {
if (timeout > 0) {
*pMode = ZES_SCHED_MODE_TIMEOUT;
} else {
if (heartbeat == 0) {
// If we are here, it means heartbeat = 0, timeout = 0, timeslice = 0.
if (isComputeUnitDebugModeEnabled()) {
*pMode = ZES_SCHED_MODE_COMPUTE_UNIT_DEBUG;
} else {
*pMode = ZES_SCHED_MODE_EXCLUSIVE;
}
} else {
// If we are here it means heartbeat > 0, timeout = 0, timeslice = 0.
// And we dont know what that mode is.
*pMode = ZES_SCHED_MODE_FORCE_UINT32;
result = ZE_RESULT_ERROR_UNKNOWN;
}
}
}
return result;
}
ze_result_t LinuxSchedulerImp::setExclusiveModeImp() {
uint64_t timeslice = 0, timeout = 0, heartbeat = 0;
ze_result_t result = setPreemptTimeout(timeout);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to set preempt timeout and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
result = setTimesliceDuration(timeslice);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to set timeslice duration and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
result = setHeartbeatInterval(heartbeat);
return result;
}
ze_result_t LinuxSchedulerImp::setExclusiveMode(ze_bool_t *pNeedReload) {
*pNeedReload = false;
zes_sched_mode_t currMode;
ze_result_t result = getCurrentMode(&currMode);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to get current mode and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
if (currMode == ZES_SCHED_MODE_COMPUTE_UNIT_DEBUG) {
// Unset this mode
result = disableComputeUnitDebugMode(pNeedReload);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to diasble COMPUTE_UNIT_DEBUG mode and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
}
return setExclusiveModeImp();
}
ze_result_t LinuxSchedulerImp::getTimeoutModeProperties(ze_bool_t getDefaults, zes_sched_timeout_properties_t *pConfig) {
uint64_t heartbeat = 0;
ze_result_t result = getHeartbeatInterval(heartbeat, getDefaults);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to get heart beat interval and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
pConfig->watchdogTimeout = heartbeat;
return result;
}
ze_result_t LinuxSchedulerImp::getTimesliceModeProperties(ze_bool_t getDefaults, zes_sched_timeslice_properties_t *pConfig) {
uint64_t timeout = 0, timeslice = 0;
ze_result_t result = getPreemptTimeout(timeout, getDefaults);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to get preempt timeout and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
result = getTimesliceDuration(timeslice, getDefaults);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to get timeslice duration and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
pConfig->interval = timeslice;
pConfig->yieldTimeout = timeout;
return result;
}
ze_result_t LinuxSchedulerImp::setTimeoutMode(zes_sched_timeout_properties_t *pProperties, ze_bool_t *pNeedReload) {
*pNeedReload = false;
zes_sched_mode_t currMode;
ze_result_t result = getCurrentMode(&currMode);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to get current mode and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
if (pProperties->watchdogTimeout < minTimeoutModeHeartbeat) {
// watchdogTimeout(in usec) less than 5000 would be computed to
// 0 milli seconds preempt timeout, and then after returning from
// this method, we would end up in EXCLUSIVE mode
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
}
if (currMode == ZES_SCHED_MODE_COMPUTE_UNIT_DEBUG) {
// Unset this mode
result = disableComputeUnitDebugMode(pNeedReload);
if (result != ZE_RESULT_SUCCESS) {
// failed to disable compute unit debug mode
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to diasble COMPUTE_UNIT_DEBUG mode and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
}
result = setHeartbeatInterval(pProperties->watchdogTimeout);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to set heartbeat interval and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
uint64_t timeout = (pProperties->watchdogTimeout) / 5;
result = setPreemptTimeout(timeout);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to set preempt timeout and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
uint64_t timeslice = 0;
result = setTimesliceDuration(timeslice);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to set timeslice duration and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
return result;
}
ze_result_t LinuxSchedulerImp::setTimesliceMode(zes_sched_timeslice_properties_t *pProperties, ze_bool_t *pNeedReload) {
if (pProperties->interval < minTimeoutInMicroSeconds) {
// interval(in usec) less than 1000 would be computed to
// 0 milli seconds interval.
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
}
*pNeedReload = false;
zes_sched_mode_t currMode;
ze_result_t result = getCurrentMode(&currMode);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to get current mode and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
if (currMode == ZES_SCHED_MODE_COMPUTE_UNIT_DEBUG) {
// Unset this mode
result = disableComputeUnitDebugMode(pNeedReload);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to diasble COMPUTE_UNIT_DEBUG mode and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
}
result = setPreemptTimeout(pProperties->yieldTimeout);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to set preempt timeout and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
result = setTimesliceDuration(pProperties->interval);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to set timeslice duration and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
uint64_t heartbeat = 2500 * (pProperties->interval);
return setHeartbeatInterval(heartbeat);
}
ze_result_t LinuxSchedulerImp::getProperties(zes_sched_properties_t &schedProperties) {
schedProperties.onSubdevice = onSubdevice;
schedProperties.subdeviceId = subdeviceId;
schedProperties.canControl = canControlScheduler();
schedProperties.engines = this->engineType;
schedProperties.supportedModes = (1 << ZES_SCHED_MODE_TIMEOUT) | (1 << ZES_SCHED_MODE_TIMESLICE) | (1 << ZES_SCHED_MODE_EXCLUSIVE);
return ZE_RESULT_SUCCESS;
}
ze_result_t LinuxSchedulerImp::getPreemptTimeout(uint64_t &timeout, ze_bool_t getDefault) {
ze_result_t result = ZE_RESULT_ERROR_UNKNOWN;
uint32_t i = 0;
std::vector<uint64_t> timeoutVec = {};
std::string path = "";
timeoutVec.resize(listOfEngines.size());
for (const auto &engineName : listOfEngines) {
if (getDefault) {
path = engineDir + "/" + engineName + "/" + defaultPreemptTimeouttMilliSecs;
result = pSysfsAccess->read(path, timeout);
} else {
path = engineDir + "/" + engineName + "/" + preemptTimeoutMilliSecs;
result = pSysfsAccess->read(path, timeout);
}
if (result == ZE_RESULT_SUCCESS) {
timeout = timeout * milliSecsToMicroSecs;
timeoutVec[i] = timeout;
i++;
} else {
if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) {
result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to read preempt timeout from %s and returning error:0x%x \n", __FUNCTION__, path.c_str(), result);
return result;
}
}
if (engineType == ZES_ENGINE_TYPE_FLAG_COMPUTE) {
timeout = *std::max_element(timeoutVec.begin(), timeoutVec.end());
return result;
}
// check if all engines of the same type have the same scheduling param values
if (std::adjacent_find(timeoutVec.begin(), timeoutVec.end(), std::not_equal_to<>()) == timeoutVec.end()) {
timeout = timeoutVec[0];
return result;
} else {
return ZE_RESULT_ERROR_UNKNOWN;
}
}
ze_result_t LinuxSchedulerImp::getTimesliceDuration(uint64_t &timeslice, ze_bool_t getDefault) {
ze_result_t result = ZE_RESULT_ERROR_UNKNOWN;
uint32_t i = 0;
std::vector<uint64_t> timesliceVec = {};
std::string path = "";
timesliceVec.resize(listOfEngines.size());
for (const auto &engineName : listOfEngines) {
if (getDefault) {
path = engineDir + "/" + engineName + "/" + defaultTimesliceDurationMilliSecs;
result = pSysfsAccess->read(path, timeslice);
} else {
path = engineDir + "/" + engineName + "/" + timesliceDurationMilliSecs;
result = pSysfsAccess->read(path, timeslice);
}
if (result == ZE_RESULT_SUCCESS) {
timeslice = timeslice * milliSecsToMicroSecs;
timesliceVec[i] = timeslice;
i++;
} else {
if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) {
result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to read timeslice duration from %s and returning error:0x%x \n", __FUNCTION__, path.c_str(), result);
return result;
}
}
// check if all engines of the same type have the same scheduling param values
if (std::adjacent_find(timesliceVec.begin(), timesliceVec.end(), std::not_equal_to<>()) == timesliceVec.end()) {
timeslice = timesliceVec[0];
return result;
} else {
return ZE_RESULT_ERROR_UNKNOWN;
}
}
ze_result_t LinuxSchedulerImp::getHeartbeatInterval(uint64_t &heartbeat, ze_bool_t getDefault) {
ze_result_t result = ZE_RESULT_ERROR_UNKNOWN;
uint32_t i = 0;
std::vector<uint64_t> heartbeatVec = {};
std::string path = "";
heartbeatVec.resize(listOfEngines.size());
for (const auto &engineName : listOfEngines) {
if (getDefault) {
path = engineDir + "/" + engineName + "/" + defaultHeartbeatIntervalMilliSecs;
result = pSysfsAccess->read(path, heartbeat);
} else {
path = engineDir + "/" + engineName + "/" + heartbeatIntervalMilliSecs;
result = pSysfsAccess->read(path, heartbeat);
}
if (result == ZE_RESULT_SUCCESS) {
heartbeat = heartbeat * milliSecsToMicroSecs;
heartbeatVec[i] = heartbeat;
i++;
} else {
if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) {
result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to read heartbeat interval from %s and returning error:0x%x \n", __FUNCTION__, path.c_str(), result);
return result;
}
}
// check if all engines of the same type have the same scheduling param values
if (std::adjacent_find(heartbeatVec.begin(), heartbeatVec.end(), std::not_equal_to<>()) == heartbeatVec.end()) {
heartbeat = heartbeatVec[0];
return result;
} else {
return ZE_RESULT_ERROR_UNKNOWN;
}
}
ze_result_t LinuxSchedulerImp::setPreemptTimeout(uint64_t timeout) {
timeout = timeout / milliSecsToMicroSecs;
ze_result_t result = ZE_RESULT_ERROR_UNKNOWN;
for (const auto &engineName : listOfEngines) {
result = pSysfsAccess->write(engineDir + "/" + engineName + "/" + preemptTimeoutMilliSecs, timeout);
if (result != ZE_RESULT_SUCCESS) {
if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) {
result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to write Preempt timeout into engineDir/%s/preemptTimeoutMilliSecs and returning error:0x%x \n", __FUNCTION__, engineName.c_str(), result);
return result;
}
}
return result;
}
ze_result_t LinuxSchedulerImp::setTimesliceDuration(uint64_t timeslice) {
timeslice = timeslice / milliSecsToMicroSecs;
ze_result_t result = ZE_RESULT_ERROR_UNKNOWN;
for (const auto &engineName : listOfEngines) {
result = pSysfsAccess->write(engineDir + "/" + engineName + "/" + timesliceDurationMilliSecs, timeslice);
if (result != ZE_RESULT_SUCCESS) {
if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) {
result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to write Timeslice duration into engineDir/%s/timesliceDurationMilliSecs and returning error:0x%x \n", __FUNCTION__, engineName.c_str(), result);
return result;
}
}
return result;
}
ze_result_t LinuxSchedulerImp::setHeartbeatInterval(uint64_t heartbeat) {
heartbeat = heartbeat / milliSecsToMicroSecs;
ze_result_t result = ZE_RESULT_ERROR_UNKNOWN;
for (const auto &engineName : listOfEngines) {
result = pSysfsAccess->write(engineDir + "/" + engineName + "/" + heartbeatIntervalMilliSecs, heartbeat);
if (result != ZE_RESULT_SUCCESS) {
if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) {
result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to write Heartbeat interval into engineDir/%s/heartbeatIntervalMilliSecs and returning error:0x%x \n", __FUNCTION__, engineName.c_str(), result);
return result;
}
}
return result;
}
ze_bool_t LinuxSchedulerImp::canControlScheduler() {
return 1;
}
ze_result_t LinuxSchedulerImp::updateComputeUnitDebugNode(uint64_t val) {
// I915 will be reloaded if we toggle value of enableEuDebug
// Hence for gracefull handling close all i915 clients before toggling enableEuDebug
pLinuxSysmanImp->releaseSysmanDeviceResources();
ze_result_t result = pLinuxSysmanImp->gpuProcessCleanup(true);
if (ZE_RESULT_SUCCESS != result) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"updateComputeUnitDebugNode: gpuProcessCleanup() failed with error code: %ld\n", result);
return result;
}
result = pSysfsAccess->write(enableEuDebug, val);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"updateComputeUnitDebugNode: Write to sysfs node %s failed with error code: %ld\n", enableEuDebug.c_str(), result);
}
pLinuxSysmanImp->reInitSysmanDeviceResources();
return result;
}
ze_result_t LinuxSchedulerImp::setComputeUnitDebugMode(ze_bool_t *pNeedReload) {
auto result = setExclusiveModeImp();
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"setComputeUnitDebugMode: Exclusive mode set(precontiion to set Debug mode) failed. Error code: %ld\n", result);
return result;
}
*pNeedReload = false;
uint64_t val = 1;
auto ret = pSysfsAccess->canWrite(enableEuDebug);
if (ret != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"setComputeUnitDebugMode: sysfs node %s not writable. Error code: %ld\n", enableEuDebug.c_str(), result);
return ret;
}
return updateComputeUnitDebugNode(val);
}
bool LinuxSchedulerImp::isComputeUnitDebugModeEnabled() {
uint64_t val = 0;
auto result = pSysfsAccess->read(enableEuDebug, val);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"isComputeUnitDebugModeEnabled: Read from sysfs node %s failed with error code: %ld\n", enableEuDebug.c_str(), result);
return false;
}
return (val == 0) ? false : true;
}
ze_result_t LinuxSchedulerImp::disableComputeUnitDebugMode(ze_bool_t *pNeedReload) {
*pNeedReload = false;
uint64_t val = 0;
return updateComputeUnitDebugNode(val);
}
static ze_result_t getNumEngineTypeAndInstancesForSubDevices(std::map<zes_engine_type_flag_t, std::vector<std::string>> &mapOfEngines,
LinuxSysmanImp *pLinuxSysmanImp, uint32_t subdeviceId) {
auto pDrm = pLinuxSysmanImp->getDrm();
NEO::EngineInfo *engineInfo = nullptr;
{
auto hwDeviceId = pLinuxSysmanImp->getSysmanHwDeviceIdInstance();
engineInfo = pDrm->getEngineInfo();
}
if (engineInfo == nullptr) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
std::vector<NEO::EngineClassInstance> listOfEngines;
engineInfo->getListOfEnginesOnATile(subdeviceId, listOfEngines);
for (const auto &engine : listOfEngines) {
auto sysfEngineString = i915EngineClassToSysfsEngineMap.find(static_cast<drm_i915_gem_engine_class>(engine.engineClass));
if (sysfEngineString == i915EngineClassToSysfsEngineMap.end()) {
continue;
}
std::string sysfsEngineDirNode = sysfEngineString->second + std::to_string(engine.engineInstance);
auto level0EngineType = sysfsEngineMapToLevel0EngineType.find(sysfEngineString->second);
auto ret = mapOfEngines.find(level0EngineType->second);
if (ret != mapOfEngines.end()) {
ret->second.push_back(sysfsEngineDirNode);
} else {
std::vector<std::string> engineVec = {};
engineVec.push_back(sysfsEngineDirNode);
mapOfEngines.emplace(level0EngineType->second, engineVec);
}
}
return ZE_RESULT_SUCCESS;
}
static ze_result_t getNumEngineTypeAndInstancesForDevice(std::map<zes_engine_type_flag_t, std::vector<std::string>> &mapOfEngines, SysFsAccessInterface *pSysfsAccess) {
std::vector<std::string> localListOfAllEngines = {};
auto result = pSysfsAccess->scanDirEntries(LinuxSchedulerImp::engineDir, localListOfAllEngines);
if (ZE_RESULT_SUCCESS != result) {
if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) {
result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to scan directory entries to list all engines and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
for_each(localListOfAllEngines.begin(), localListOfAllEngines.end(),
[&](std::string &mappedEngine) {
for (auto itr = level0EngineTypeToSysfsEngineMap.begin(); itr != level0EngineTypeToSysfsEngineMap.end(); itr++) {
char digits[] = "0123456789";
auto mappedEngineName = mappedEngine.substr(0, mappedEngine.find_first_of(digits, 0));
if (0 == mappedEngineName.compare(itr->second.c_str())) {
auto ret = mapOfEngines.find(itr->first);
if (ret != mapOfEngines.end()) {
ret->second.push_back(mappedEngine);
} else {
std::vector<std::string> engineVec = {};
engineVec.push_back(mappedEngine);
mapOfEngines.emplace(itr->first, engineVec);
}
}
}
});
return result;
}
ze_result_t OsScheduler::getNumEngineTypeAndInstances(
std::map<zes_engine_type_flag_t, std::vector<std::string>> &mapOfEngines, OsSysman *pOsSysman, ze_bool_t onSubDevice, uint32_t subDeviceId) {
LinuxSysmanImp *pLinuxSysmanImp = static_cast<LinuxSysmanImp *>(pOsSysman);
auto pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess();
if (onSubDevice) {
return getNumEngineTypeAndInstancesForSubDevices(mapOfEngines, pLinuxSysmanImp, subDeviceId);
}
return getNumEngineTypeAndInstancesForDevice(mapOfEngines, pSysfsAccess);
}
LinuxSchedulerImp::LinuxSchedulerImp(
OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector<std::string> &listOfEngines, ze_bool_t isSubdevice,
uint32_t subdeviceId) : engineType(type), onSubdevice(isSubdevice), subdeviceId(subdeviceId) {
pLinuxSysmanImp = static_cast<LinuxSysmanImp *>(pOsSysman);
pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess();
this->listOfEngines = listOfEngines;
}
std::unique_ptr<OsScheduler> OsScheduler::create(
OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector<std::string> &listOfEngines, ze_bool_t isSubdevice, uint32_t subdeviceId) {
std::unique_ptr<LinuxSchedulerImp> pLinuxSchedulerImp = std::make_unique<LinuxSchedulerImp>(pOsSysman, type, listOfEngines, isSubdevice, subdeviceId);
return pLinuxSchedulerImp;
}
} // namespace Sysman
} // namespace L0

View File

@@ -36,6 +36,13 @@ static const std::multimap<zes_engine_type_flag_t, std::string> level0EngineType
{ZES_ENGINE_TYPE_FLAG_MEDIA, "vcs"},
{ZES_ENGINE_TYPE_FLAG_OTHER, "vecs"}};
static const std::map<std::string, zes_engine_type_flag_t> sysfsEngineMapToLevel0EngineType = {
{"rcs", ZES_ENGINE_TYPE_FLAG_RENDER},
{"ccs", ZES_ENGINE_TYPE_FLAG_COMPUTE},
{"bcs", ZES_ENGINE_TYPE_FLAG_DMA},
{"vcs", ZES_ENGINE_TYPE_FLAG_MEDIA},
{"vecs", ZES_ENGINE_TYPE_FLAG_OTHER}};
SysmanKmdInterface::SysmanKmdInterface() = default;
SysmanKmdInterface::~SysmanKmdInterface() = default;
@@ -87,6 +94,39 @@ SysFsAccessInterface *SysmanKmdInterface::getSysFsAccess() {
return pSysfsAccess.get();
}
ze_result_t SysmanKmdInterface::getNumEngineTypeAndInstancesForSubDevices(std::map<zes_engine_type_flag_t, std::vector<std::string>> &mapOfEngines,
NEO::Drm *pDrm,
uint32_t subdeviceId) {
NEO::EngineInfo *engineInfo = nullptr;
{
auto hwDeviceId = static_cast<SysmanHwDeviceIdDrm *>(pDrm->getHwDeviceId().get())->getSingleInstance();
engineInfo = pDrm->getEngineInfo();
}
if (engineInfo == nullptr) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
std::vector<NEO::EngineClassInstance> listOfEngines;
engineInfo->getListOfEnginesOnATile(subdeviceId, listOfEngines);
for (const auto &engine : listOfEngines) {
std::string sysfEngineString = getEngineClassString(engine.engineClass).value_or(" ");
if (sysfEngineString == " ") {
continue;
}
std::string sysfsEngineDirNode = sysfEngineString + std::to_string(engine.engineInstance);
auto level0EngineType = sysfsEngineMapToLevel0EngineType.find(sysfEngineString);
auto ret = mapOfEngines.find(level0EngineType->second);
if (ret != mapOfEngines.end()) {
ret->second.push_back(sysfsEngineDirNode);
} else {
std::vector<std::string> engineVec = {};
engineVec.push_back(sysfsEngineDirNode);
mapOfEngines.emplace(level0EngineType->second, engineVec);
}
}
return ZE_RESULT_SUCCESS;
}
ze_result_t SysmanKmdInterface::getNumEngineTypeAndInstancesForDevice(std::string engineDir, std::map<zes_engine_type_flag_t, std::vector<std::string>> &mapOfEngines,
SysFsAccessInterface *pSysfsAccess) {
std::vector<std::string> localListOfAllEngines = {};

View File

@@ -129,6 +129,9 @@ class SysmanKmdInterface {
uint32_t subdeviceId) = 0;
ze_result_t getNumEngineTypeAndInstancesForDevice(std::string engineDir, std::map<zes_engine_type_flag_t, std::vector<std::string>> &mapOfEngines,
SysFsAccessInterface *pSysfsAccess);
ze_result_t getNumEngineTypeAndInstancesForSubDevices(std::map<zes_engine_type_flag_t, std::vector<std::string>> &mapOfEngines,
NEO::Drm *pDrm,
uint32_t subdeviceId);
SysfsValueUnit getNativeUnit(const SysfsName sysfsName);
void convertSysfsValueUnit(const SysfsValueUnit dstUnit, const SysfsValueUnit srcUnit,
const uint64_t srcValue, uint64_t &dstValue) const;

View File

@@ -6,8 +6,10 @@
*/
#include "shared/source/helpers/debug_helpers.h"
#include "shared/source/os_interface/linux/i915_prelim.h"
#include "level_zero/sysman/source/shared/linux/sysman_kmd_interface.h"
#include "level_zero/sysman/source/shared/linux/zes_os_sysman_imp.h"
namespace L0 {
namespace Sysman {
@@ -18,6 +20,13 @@ SysmanKmdInterfaceI915Prelim::SysmanKmdInterfaceI915Prelim(const PRODUCT_FAMILY
SysmanKmdInterfaceI915Prelim::~SysmanKmdInterfaceI915Prelim() = default;
static const std::map<__u16, std::string> i915EngineClassToSysfsEngineMap = {
{drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER, "rcs"},
{static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_COMPUTE), "ccs"},
{drm_i915_gem_engine_class::I915_ENGINE_CLASS_COPY, "bcs"},
{drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO, "vcs"},
{drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO_ENHANCE, "vecs"}};
void SysmanKmdInterfaceI915Prelim::initSysfsNameToFileMap(const PRODUCT_FAMILY productFamily) {
sysfsNameToFileMap[SysfsName::sysfsNameMinFrequency] = std::make_pair("rps_min_freq_mhz", "gt_min_freq_mhz");
sysfsNameToFileMap[SysfsName::sysfsNameMaxFrequency] = std::make_pair("rps_max_freq_mhz", "gt_max_freq_mhz");
@@ -49,6 +58,9 @@ void SysmanKmdInterfaceI915Prelim::initSysfsNameToFileMap(const PRODUCT_FAMILY p
sysfsNameToFileMap[SysfsName::sysfsNamePerformanceMediaFrequencyFactor] = std::make_pair("media_freq_factor", "");
sysfsNameToFileMap[SysfsName::sysfsNamePerformanceMediaFrequencyFactorScale] = std::make_pair("media_freq_factor.scale", "");
sysfsNameToFileMap[SysfsName::sysfsNamePerformanceSystemPowerBalance] = std::make_pair("", "sys_pwr_balance");
sysfsNameToFileMap[SysfsName::sysfsNameSchedulerTimeout] = std::make_pair("", "preempt_timeout_ms");
sysfsNameToFileMap[SysfsName::sysfsNameSchedulerTimeslice] = std::make_pair("", "timeslice_duration_ms");
sysfsNameToFileMap[SysfsName::sysfsNameSchedulerWatchDogTimeout] = std::make_pair("", "heartbeat_interval_ms");
}
std::string SysmanKmdInterfaceI915Prelim::getBasePath(uint32_t subDeviceId) const {
@@ -80,7 +92,7 @@ std::string SysmanKmdInterfaceI915Prelim::getHwmonName(uint32_t subDeviceId, boo
}
std::string SysmanKmdInterfaceI915Prelim::getEngineBasePath(uint32_t subDeviceId) const {
return "";
return getEngineBasePathI915(subDeviceId);
}
ze_result_t SysmanKmdInterfaceI915Prelim::getNumEngineTypeAndInstances(std::map<zes_engine_type_flag_t, std::vector<std::string>> &mapOfEngines,
@@ -88,11 +100,20 @@ ze_result_t SysmanKmdInterfaceI915Prelim::getNumEngineTypeAndInstances(std::map<
SysFsAccessInterface *pSysfsAccess,
ze_bool_t onSubdevice,
uint32_t subdeviceId) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
if (onSubdevice) {
return getNumEngineTypeAndInstancesForSubDevices(mapOfEngines,
pLinuxSysmanImp->getDrm(), subdeviceId);
}
return getNumEngineTypeAndInstancesForDevice(getEngineBasePath(subdeviceId), mapOfEngines, pSysfsAccess);
}
std::optional<std::string> SysmanKmdInterfaceI915Prelim::getEngineClassString(uint16_t engineClass) {
return std::nullopt;
auto sysfEngineString = i915EngineClassToSysfsEngineMap.find(engineClass);
if (sysfEngineString == i915EngineClassToSysfsEngineMap.end()) {
DEBUG_BREAK_IF(true);
return {};
}
return sysfEngineString->second;
}
uint32_t SysmanKmdInterfaceI915Prelim::getEventType(const bool isIntegratedDevice) {

View File

@@ -24,47 +24,6 @@ static const std::map<__u16, std::string> xeEngineClassToSysfsEngineMap = {
{DRM_XE_ENGINE_CLASS_VIDEO_DECODE, "vcs"},
{DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE, "vecs"}};
static const std::map<std::string, zes_engine_type_flag_t> sysfsEngineMapToLevel0EngineType = {
{"rcs", ZES_ENGINE_TYPE_FLAG_RENDER},
{"ccs", ZES_ENGINE_TYPE_FLAG_COMPUTE},
{"bcs", ZES_ENGINE_TYPE_FLAG_DMA},
{"vcs", ZES_ENGINE_TYPE_FLAG_MEDIA},
{"vecs", ZES_ENGINE_TYPE_FLAG_OTHER}};
static ze_result_t getNumEngineTypeAndInstancesForSubDevices(std::map<zes_engine_type_flag_t, std::vector<std::string>> &mapOfEngines,
NEO::Drm *pDrm,
SysmanKmdInterface *pSysmanKmdInterface,
uint32_t subdeviceId) {
NEO::EngineInfo *engineInfo = nullptr;
{
auto hwDeviceId = static_cast<SysmanHwDeviceIdDrm *>(pDrm->getHwDeviceId().get())->getSingleInstance();
engineInfo = pDrm->getEngineInfo();
}
if (engineInfo == nullptr) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
std::vector<NEO::EngineClassInstance> listOfEngines;
engineInfo->getListOfEnginesOnATile(subdeviceId, listOfEngines);
for (const auto &engine : listOfEngines) {
std::string sysfEngineString = pSysmanKmdInterface->getEngineClassString(engine.engineClass).value_or(" ");
if (sysfEngineString == " ") {
continue;
}
std::string sysfsEngineDirNode = sysfEngineString + std::to_string(engine.engineInstance);
auto level0EngineType = sysfsEngineMapToLevel0EngineType.find(sysfEngineString);
auto ret = mapOfEngines.find(level0EngineType->second);
if (ret != mapOfEngines.end()) {
ret->second.push_back(sysfsEngineDirNode);
} else {
std::vector<std::string> engineVec = {};
engineVec.push_back(sysfsEngineDirNode);
mapOfEngines.emplace(level0EngineType->second, engineVec);
}
}
return ZE_RESULT_SUCCESS;
}
SysmanKmdInterfaceXe::SysmanKmdInterfaceXe(const PRODUCT_FAMILY productFamily) {
initSysfsNameToFileMap(productFamily);
}
@@ -151,7 +110,7 @@ ze_result_t SysmanKmdInterfaceXe::getNumEngineTypeAndInstances(std::map<zes_engi
uint32_t subdeviceId) {
if (onSubdevice) {
return getNumEngineTypeAndInstancesForSubDevices(mapOfEngines,
pLinuxSysmanImp->getDrm(), pLinuxSysmanImp->getSysmanKmdInterface(), subdeviceId);
pLinuxSysmanImp->getDrm(), subdeviceId);
}
return getNumEngineTypeAndInstancesForDevice(getEngineBasePath(subdeviceId), mapOfEngines, pSysfsAccess);
}

View File

@@ -1,26 +1,15 @@
#
# Copyright (C) 2020-2023 Intel Corporation
# Copyright (C) 2020-2024 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
set(L0_TESTS_TOOLS_SYSMAN_SCHEDULER_LINUX
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/test_zes_scheduler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mock_sysfs_scheduler.h
)
if(NEO_ENABLE_i915_PRELIM_DETECTION)
list(APPEND L0_TESTS_TOOLS_SYSMAN_SCHEDULER_LINUX
${CMAKE_CURRENT_SOURCE_DIR}/test_zes_scheduler_prelim.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mock_sysfs_scheduler_prelim.h
)
else()
list(APPEND L0_TESTS_TOOLS_SYSMAN_SCHEDULER_LINUX
${CMAKE_CURRENT_SOURCE_DIR}/test_zes_scheduler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mock_sysfs_scheduler.h
)
endif()
if(UNIX)
target_sources(${TARGET_NAME}
PRIVATE

View File

@@ -1,602 +0,0 @@
/*
* Copyright (C) 2020-2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/source/os_interface/linux/engine_info.h"
#include "shared/source/os_interface/linux/i915_prelim.h"
#include "shared/source/os_interface/linux/ioctl_helper.h"
#include "level_zero/sysman/source/api/scheduler/linux/sysman_os_scheduler_imp.h"
#include "level_zero/sysman/source/shared/linux/sysman_fs_access_interface.h"
#include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_hw_device_id.h"
namespace L0 {
namespace Sysman {
namespace ult {
const std::string preemptTimeoutMilliSecs("preempt_timeout_ms");
const std::string defaultPreemptTimeoutMilliSecs(".defaults/preempt_timeout_ms");
const std::string timesliceDurationMilliSecs("timeslice_duration_ms");
const std::string defaultTimesliceDurationMilliSecs(".defaults/timeslice_duration_ms");
const std::string heartbeatIntervalMilliSecs("heartbeat_interval_ms");
const std::string defaultHeartbeatIntervalMilliSecs(".defaults/heartbeat_interval_ms");
const std::string enableEuDebug("prelim_enable_eu_debug");
const std::string engineDir("engine");
const std::vector<std::string> listOfMockedEngines = {"rcs0", "bcs0", "vcs0", "vcs1", "vecs0", "ccs0"};
uint32_t tileCount = 2u;
uint32_t numberOfEnginesInSched = 34u;
struct MockSchedulerNeoDrm : public Drm {
using Drm::getEngineInfo;
using Drm::setupIoctlHelper;
const int mockFd = 0;
MockSchedulerNeoDrm(RootDeviceEnvironment &rootDeviceEnvironment) : Drm(std::make_unique<MockSysmanHwDeviceIdDrm>(mockFd, ""), rootDeviceEnvironment) {}
bool sysmanQueryEngineInfo() override {
uint16_t engineClassCopy = ioctlHelper->getDrmParamValue(DrmParam::engineClassCopy);
uint16_t engineClassCompute = ioctlHelper->getDrmParamValue(DrmParam::engineClassCompute);
uint16_t engineClassVideo = ioctlHelper->getDrmParamValue(DrmParam::engineClassVideo);
uint16_t engineClassVideoEnhance = ioctlHelper->getDrmParamValue(DrmParam::engineClassVideoEnhance);
uint16_t engineClassInvalid = ioctlHelper->getDrmParamValue(DrmParam::engineClassInvalid);
// Fill distanceInfos vector with dummy values
std::vector<NEO::DistanceInfo> distanceInfos = {
{{1, 0}, {engineClassCopy, 0}, 0},
{{1, 0}, {engineClassCopy, 1}, 1000},
{{1, 0}, {engineClassCompute, 0}, 0},
{{1, 0}, {engineClassCompute, 1}, 0},
{{1, 0}, {engineClassCompute, 2}, 0},
{{1, 0}, {engineClassCompute, 3}, 0},
{{1, 0}, {engineClassCompute, 4}, 1000},
{{1, 0}, {engineClassCompute, 5}, 1000},
{{1, 0}, {engineClassCompute, 6}, 1000},
{{1, 0}, {engineClassCompute, 7}, 1000},
{{1, 1}, {engineClassCopy, 0}, 1000},
{{1, 1}, {engineClassCopy, 1}, 0},
{{1, 1}, {engineClassCompute, 0}, 1000},
{{1, 1}, {engineClassCompute, 1}, 1000},
{{1, 1}, {engineClassCompute, 2}, 1000},
{{1, 1}, {engineClassCompute, 3}, 1000},
{{1, 1}, {engineClassCompute, 4}, 0},
{{1, 1}, {engineClassCompute, 5}, 0},
{{1, 1}, {engineClassCompute, 6}, 0},
{{1, 1}, {engineClassCompute, 7}, 0},
{{1, 1}, {engineClassInvalid, 7}, 0},
};
std::vector<QueryItem> queryItems{distanceInfos.size()};
for (auto i = 0u; i < distanceInfos.size(); i++) {
queryItems[i].queryId = PRELIM_DRM_I915_QUERY_DISTANCE_INFO;
queryItems[i].length = sizeof(NEO::PrelimI915::prelim_drm_i915_query_distance_info);
queryItems[i].flags = 0u;
queryItems[i].dataPtr = reinterpret_cast<uint64_t>(&distanceInfos[i]);
}
// Fill i915QueryEngineInfo with dummy values
std::vector<NEO::EngineCapabilities> i915QueryEngineInfo(numberOfEnginesInSched);
i915QueryEngineInfo[0].engine.engineClass = engineClassCopy;
i915QueryEngineInfo[0].engine.engineInstance = 0;
i915QueryEngineInfo[1].engine.engineClass = engineClassCopy;
i915QueryEngineInfo[1].engine.engineInstance = 1;
i915QueryEngineInfo[2].engine.engineClass = engineClassVideo;
i915QueryEngineInfo[2].engine.engineInstance = 0;
i915QueryEngineInfo[3].engine.engineClass = engineClassVideo;
i915QueryEngineInfo[3].engine.engineInstance = 1;
i915QueryEngineInfo[4].engine.engineClass = engineClassVideo;
i915QueryEngineInfo[4].engine.engineInstance = 2;
i915QueryEngineInfo[5].engine.engineClass = engineClassVideo;
i915QueryEngineInfo[5].engine.engineInstance = 3;
i915QueryEngineInfo[6].engine.engineClass = engineClassVideo;
i915QueryEngineInfo[6].engine.engineInstance = 4;
i915QueryEngineInfo[7].engine.engineClass = engineClassVideo;
i915QueryEngineInfo[7].engine.engineInstance = 5;
i915QueryEngineInfo[8].engine.engineClass = engineClassVideo;
i915QueryEngineInfo[8].engine.engineInstance = 6;
i915QueryEngineInfo[9].engine.engineClass = engineClassVideo;
i915QueryEngineInfo[9].engine.engineInstance = 7;
i915QueryEngineInfo[10].engine.engineClass = engineClassVideo;
i915QueryEngineInfo[10].engine.engineInstance = 8;
i915QueryEngineInfo[11].engine.engineClass = engineClassVideo;
i915QueryEngineInfo[11].engine.engineInstance = 9;
i915QueryEngineInfo[12].engine.engineClass = engineClassVideo;
i915QueryEngineInfo[12].engine.engineInstance = 10;
i915QueryEngineInfo[13].engine.engineClass = engineClassVideo;
i915QueryEngineInfo[13].engine.engineInstance = 11;
i915QueryEngineInfo[14].engine.engineClass = engineClassVideo;
i915QueryEngineInfo[14].engine.engineInstance = 12;
i915QueryEngineInfo[15].engine.engineClass = engineClassVideo;
i915QueryEngineInfo[15].engine.engineInstance = 13;
i915QueryEngineInfo[16].engine.engineClass = engineClassVideo;
i915QueryEngineInfo[16].engine.engineInstance = 14;
i915QueryEngineInfo[17].engine.engineClass = engineClassVideo;
i915QueryEngineInfo[17].engine.engineInstance = 15;
i915QueryEngineInfo[18].engine.engineClass = engineClassVideoEnhance;
i915QueryEngineInfo[18].engine.engineInstance = 0;
i915QueryEngineInfo[19].engine.engineClass = engineClassVideoEnhance;
i915QueryEngineInfo[19].engine.engineInstance = 1;
i915QueryEngineInfo[20].engine.engineClass = engineClassVideoEnhance;
i915QueryEngineInfo[20].engine.engineInstance = 2;
i915QueryEngineInfo[21].engine.engineClass = engineClassVideoEnhance;
i915QueryEngineInfo[21].engine.engineInstance = 3;
i915QueryEngineInfo[22].engine.engineClass = engineClassVideoEnhance;
i915QueryEngineInfo[22].engine.engineInstance = 4;
i915QueryEngineInfo[23].engine.engineClass = engineClassVideoEnhance;
i915QueryEngineInfo[23].engine.engineInstance = 5;
i915QueryEngineInfo[24].engine.engineClass = engineClassVideoEnhance;
i915QueryEngineInfo[24].engine.engineInstance = 6;
i915QueryEngineInfo[25].engine.engineClass = engineClassVideoEnhance;
i915QueryEngineInfo[25].engine.engineInstance = 7;
i915QueryEngineInfo[26].engine.engineClass = engineClassCompute;
i915QueryEngineInfo[26].engine.engineInstance = 0;
i915QueryEngineInfo[27].engine.engineClass = engineClassCompute;
i915QueryEngineInfo[27].engine.engineInstance = 1;
i915QueryEngineInfo[28].engine.engineClass = engineClassCompute;
i915QueryEngineInfo[28].engine.engineInstance = 2;
i915QueryEngineInfo[29].engine.engineClass = engineClassCompute;
i915QueryEngineInfo[29].engine.engineInstance = 3;
i915QueryEngineInfo[30].engine.engineClass = engineClassCompute;
i915QueryEngineInfo[30].engine.engineInstance = 4;
i915QueryEngineInfo[31].engine.engineClass = engineClassCompute;
i915QueryEngineInfo[31].engine.engineInstance = 5;
i915QueryEngineInfo[32].engine.engineClass = engineClassCompute;
i915QueryEngineInfo[32].engine.engineInstance = 6;
i915QueryEngineInfo[33].engine.engineClass = engineClassCompute;
i915QueryEngineInfo[33].engine.engineInstance = 7;
this->engineInfo.reset(new EngineInfo(this, tileCount, distanceInfos, queryItems, i915QueryEngineInfo));
return true;
}
bool queryEngineInfoMockReturnFalse() {
return false;
}
void resetEngineInfo() {
engineInfo.reset();
}
};
class SchedulerFileProperties {
bool isAvailable = false;
::mode_t mode = 0;
public:
SchedulerFileProperties() = default;
SchedulerFileProperties(bool isAvailable, ::mode_t mode) : isAvailable(isAvailable), mode(mode) {}
bool getAvailability() {
return isAvailable;
}
bool hasMode(::mode_t mode) {
return mode & this->mode;
}
};
class MockSchedulerProcfsAccess : public L0::Sysman::ProcFsAccessInterface {
public:
MockSchedulerProcfsAccess() = default;
const pid_t pid1 = 1234;
const pid_t pid2 = 1235;
const pid_t pid3 = 1236;
const pid_t pid4 = 1237;
ze_result_t listProcessesResult = ZE_RESULT_SUCCESS;
ze_result_t listProcesses(std::vector<::pid_t> &list) override {
if (listProcessesResult != ZE_RESULT_SUCCESS) {
return listProcessesResult;
}
list.push_back(pid1);
list.push_back(pid2);
list.push_back(pid3);
list.push_back(pid4);
return ZE_RESULT_SUCCESS;
}
ze_result_t getFileDescriptorsResult;
ze_result_t getFileDescriptors(const ::pid_t pid, std::vector<int> &list) override {
// push dummy fd numbers in list vector
if (pid == pid1) {
list.push_back(1);
list.push_back(2);
} else if (pid == pid2) {
list.push_back(1);
list.push_back(2);
} else if (pid == pid3) {
list.push_back(1);
list.push_back(2);
} else if (pid == pid4) {
list.push_back(1);
list.push_back(3);
}
return ZE_RESULT_SUCCESS;
}
ze_result_t getFileName(const ::pid_t pid, const int fd, std::string &val) override {
if (fd == 1) {
val = "/dev/null"; // assuming after opening /dev/null fd received is 1
return ZE_RESULT_SUCCESS;
}
if (fd == 2) {
val = "/dev/dri/renderD128"; // assuming after opening /dev/dri/renderD128 fd received is 2
return ZE_RESULT_SUCCESS;
}
if (fd == 3) {
val = "/dev/dummy"; // assuming after opening /dev/dummy fd received is 3
return ZE_RESULT_SUCCESS;
}
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
::pid_t myProcessId() override {
return pid2;
}
ADDMETHOD_NOBASE_VOIDRETURN(kill, (const ::pid_t pid));
};
typedef struct SchedulerConfigValues {
uint64_t defaultVal;
uint64_t actualVal;
} SchedulerConfigValues_t;
typedef struct SchedulerConfig {
SchedulerConfigValues_t timeOut;
SchedulerConfigValues_t timeSclice;
SchedulerConfigValues_t heartBeat;
uint64_t euDebugEnable;
} SchedulerConfig_t;
class CalledTimesUpdate {
public:
CalledTimesUpdate(int &calledTimes) : calledTimesVar(calledTimes) {}
~CalledTimesUpdate() {
calledTimesVar++;
}
private:
int &calledTimesVar;
};
struct MockSchedulerSysfsAccess : public L0::Sysman::SysFsAccessInterface {
using SysFsAccessInterface::deviceNames;
ze_result_t mockReadFileFailureError = ZE_RESULT_SUCCESS;
ze_result_t mockGetScanDirEntryError = ZE_RESULT_SUCCESS;
std::vector<ze_result_t> mockReadReturnValues{ZE_RESULT_SUCCESS, ZE_RESULT_SUCCESS, ZE_RESULT_SUCCESS, ZE_RESULT_ERROR_NOT_AVAILABLE};
uint32_t mockReadCount = 0;
bool mockReadReturnStatus = false;
bool mockGetValueForError = false;
bool mockGetValueForErrorWhileWrite = false;
std::map<std::string, SchedulerConfig_t *> engineSchedMap;
std::map<std::string, SchedulerFileProperties> engineSchedFilePropertiesMap;
ze_result_t getValForError(const std::string file, uint64_t &val) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
ze_result_t getValForErrorWhileWrite(const std::string file, const uint64_t val) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
void cleanUpMap() {
for (std::string mappedEngine : listOfMockedEngines) {
auto it = engineSchedMap.find(mappedEngine);
if (it != engineSchedMap.end()) {
delete it->second;
}
}
}
ze_result_t getFileProperties(const std::string file, SchedulerFileProperties &fileProps) {
auto iterator = engineSchedFilePropertiesMap.find(file);
if (iterator != engineSchedFilePropertiesMap.end()) {
fileProps = static_cast<SchedulerFileProperties>(iterator->second);
return ZE_RESULT_SUCCESS;
}
return ZE_RESULT_ERROR_UNKNOWN;
}
ze_result_t setFileProperties(const std::string &engine, const std::string file, bool isAvailable, ::mode_t mode) {
auto iterator = std::find(listOfMockedEngines.begin(), listOfMockedEngines.end(), engine);
if (iterator != listOfMockedEngines.end()) {
engineSchedFilePropertiesMap[engineDir + "/" + engine + "/" + file] = SchedulerFileProperties(isAvailable, mode);
return ZE_RESULT_SUCCESS;
}
if (engine.empty()) {
engineSchedFilePropertiesMap[file] = SchedulerFileProperties(isAvailable, mode);
}
return ZE_RESULT_ERROR_UNKNOWN;
}
ze_result_t canWrite(const std::string file) override {
SchedulerFileProperties fileProperties;
ze_result_t result = getFileProperties(file, fileProperties);
if (ZE_RESULT_SUCCESS == result) {
if (!fileProperties.getAvailability()) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
if (!fileProperties.hasMode(S_IWUSR)) {
return ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS;
}
return result;
}
return ZE_RESULT_ERROR_UNKNOWN;
}
ze_result_t read(const std::string file, uint64_t &val) override {
if (mockReadReturnStatus == true) {
if (mockReadCount < mockReadReturnValues.size()) {
ze_result_t returnValue = mockReadReturnValues[mockReadCount];
mockReadCount++;
return returnValue;
}
}
if (mockReadFileFailureError != ZE_RESULT_SUCCESS) {
return mockReadFileFailureError;
}
if (mockGetValueForError == true) {
return getValForError(file, val);
}
SchedulerFileProperties fileProperties;
ze_result_t result = getFileProperties(file, fileProperties);
if (ZE_RESULT_SUCCESS == result) {
if (!fileProperties.getAvailability()) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
if (!fileProperties.hasMode(S_IRUSR)) {
return ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS;
}
} else {
return ZE_RESULT_ERROR_UNKNOWN;
}
// listOfMockedEngines is as below:
// [0]: "rcs0"
// [1]: "bcs0"
// [2]: "vcs0"
// [3]: "vcs1"
// [4]: "vecs0"
// [5]: "ccs0"
for (std::string mappedEngine : listOfMockedEngines) {
if (file.compare(file.length() - enableEuDebug.length(),
enableEuDebug.length(),
enableEuDebug) == 0) {
// "prelim_enable_eu_debug" sysfs node is common node across one drm client
// This node is not engine specific. Hence it needs to be handled separately.
// All other engine specific nodes are handled outside of this if block
// As "prelim_enable_eu_debug" node is common across system, hence below we could find
// using any engine node. Lets use rcs0 here.
auto it = engineSchedMap.find("rcs0");
val = it->second->euDebugEnable;
return ZE_RESULT_SUCCESS;
}
if (file.find(mappedEngine) == std::string::npos) {
continue;
}
auto it = engineSchedMap.find(mappedEngine);
if (it == engineSchedMap.end()) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
if (file.compare(file.length() - enableEuDebug.length(),
enableEuDebug.length(),
enableEuDebug) == 0) {
val = it->second->euDebugEnable;
}
if (file.compare((file.length() - preemptTimeoutMilliSecs.length()),
preemptTimeoutMilliSecs.length(),
preemptTimeoutMilliSecs) == 0) {
if (file.find(".defaults") != std::string::npos) {
val = it->second->timeOut.defaultVal;
} else {
val = it->second->timeOut.actualVal;
}
return ZE_RESULT_SUCCESS;
}
if (file.compare((file.length() - timesliceDurationMilliSecs.length()),
timesliceDurationMilliSecs.length(),
timesliceDurationMilliSecs) == 0) {
if (file.find(".defaults") != std::string::npos) {
val = it->second->timeSclice.defaultVal;
} else {
val = it->second->timeSclice.actualVal;
}
return ZE_RESULT_SUCCESS;
}
if (file.compare((file.length() - heartbeatIntervalMilliSecs.length()),
heartbeatIntervalMilliSecs.length(),
heartbeatIntervalMilliSecs) == 0) {
if (file.find(".defaults") != std::string::npos) {
val = it->second->heartBeat.defaultVal;
} else {
val = it->second->heartBeat.actualVal;
}
return ZE_RESULT_SUCCESS;
}
}
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
int writeCalled = 0;
std::vector<ze_result_t> writeResult{ZE_RESULT_SUCCESS};
ze_result_t write(const std::string file, const uint64_t val) override {
CalledTimesUpdate update(writeCalled); // increment this method's call count while exiting this method
if (writeCalled < static_cast<int>(writeResult.size())) {
if (writeResult[writeCalled] != ZE_RESULT_SUCCESS) {
// If we are here, it means test simply wants to validate failure values from this method
return writeResult[writeCalled];
}
}
if (mockGetValueForErrorWhileWrite == true) {
return getValForErrorWhileWrite(file, val);
}
SchedulerFileProperties fileProperties;
ze_result_t result = getFileProperties(file, fileProperties);
if (ZE_RESULT_SUCCESS == result) {
if (!fileProperties.getAvailability()) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
if (!fileProperties.hasMode(S_IWUSR)) {
return ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS;
}
} else {
return ZE_RESULT_ERROR_UNKNOWN;
}
if (file.compare(file.length() - enableEuDebug.length(), enableEuDebug.length(), enableEuDebug) == 0) {
// "prelim_enable_eu_debug" sysfs node is common node across one drm client
// This node is not engine specific. Hence it needs to be handled separately.
// All other engine specific nodes are handled outside of this if block inside for loop
for (auto &mappedEngine : listOfMockedEngines) {
SchedulerConfig_t *schedConfig = new SchedulerConfig_t();
schedConfig->euDebugEnable = val;
auto ret = engineSchedMap.emplace(mappedEngine, schedConfig);
if (ret.second == false) {
auto itr = engineSchedMap.find(mappedEngine);
itr->second->euDebugEnable = val;
delete schedConfig;
}
}
return ZE_RESULT_SUCCESS;
}
for (std::string mappedEngine : listOfMockedEngines) { // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
if (file.find(mappedEngine) == std::string::npos) {
continue;
}
SchedulerConfig_t *schedConfig = new SchedulerConfig_t();
if (file.compare((file.length() - preemptTimeoutMilliSecs.length()),
preemptTimeoutMilliSecs.length(),
preemptTimeoutMilliSecs) == 0) {
if (file.find(".defaults") != std::string::npos) {
schedConfig->timeOut.defaultVal = val;
} else {
schedConfig->timeOut.actualVal = val;
}
auto ret = engineSchedMap.emplace(mappedEngine, schedConfig);
if (ret.second == false) {
auto itr = engineSchedMap.find(mappedEngine);
if (file.find(".defaults") != std::string::npos) {
itr->second->timeOut.defaultVal = val;
} else {
itr->second->timeOut.actualVal = val;
}
delete schedConfig;
}
return ZE_RESULT_SUCCESS;
}
if (file.compare((file.length() - timesliceDurationMilliSecs.length()),
timesliceDurationMilliSecs.length(),
timesliceDurationMilliSecs) == 0) {
if (file.find(".defaults") != std::string::npos) {
schedConfig->timeSclice.defaultVal = val;
} else {
schedConfig->timeSclice.actualVal = val;
}
auto ret = engineSchedMap.emplace(mappedEngine, schedConfig);
if (ret.second == false) {
auto itr = engineSchedMap.find(mappedEngine);
if (file.find(".defaults") != std::string::npos) {
itr->second->timeSclice.defaultVal = val;
} else {
itr->second->timeSclice.actualVal = val;
}
delete schedConfig;
}
return ZE_RESULT_SUCCESS;
}
if (file.compare((file.length() - heartbeatIntervalMilliSecs.length()),
heartbeatIntervalMilliSecs.length(),
heartbeatIntervalMilliSecs) == 0) {
if (file.find(".defaults") != std::string::npos) {
schedConfig->heartBeat.defaultVal = val;
} else {
schedConfig->heartBeat.actualVal = val;
}
auto ret = engineSchedMap.emplace(mappedEngine, schedConfig);
if (ret.second == false) {
auto itr = engineSchedMap.find(mappedEngine);
if (file.find(".defaults") != std::string::npos) {
itr->second->heartBeat.defaultVal = val;
} else {
itr->second->heartBeat.actualVal = val;
}
delete schedConfig;
}
return ZE_RESULT_SUCCESS;
}
}
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
ze_result_t scanDirEntries(const std::string file, std::vector<std::string> &listOfEntries) override {
if (mockGetScanDirEntryError != ZE_RESULT_SUCCESS) {
return mockGetScanDirEntryError;
}
if (!isDirectoryAccessible(engineDir)) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
if (!(engineDirectoryPermissions & S_IRUSR)) {
return ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS;
}
listOfEntries = listOfMockedEngines;
return ZE_RESULT_SUCCESS;
}
ze_result_t getscanDirEntriesStatusReturnError(const std::string file, std::vector<std::string> &listOfEntries) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
void setEngineDirectoryPermission(::mode_t permission) {
engineDirectoryPermissions = permission;
}
MockSchedulerSysfsAccess() = default;
private:
::mode_t engineDirectoryPermissions = S_IRUSR | S_IWUSR;
bool isDirectoryAccessible(const std::string dir) {
if (dir.compare(engineDir) == 0) {
return true;
}
return false;
}
};
class PublicLinuxSchedulerImp : public L0::Sysman::LinuxSchedulerImp {
public:
using LinuxSchedulerImp::isComputeUnitDebugModeEnabled;
using LinuxSchedulerImp::pSysfsAccess;
using LinuxSchedulerImp::setExclusiveModeImp;
using LinuxSchedulerImp::setHeartbeatInterval;
using LinuxSchedulerImp::setPreemptTimeout;
using LinuxSchedulerImp::setTimesliceDuration;
using LinuxSchedulerImp::subdeviceId;
};
} // namespace ult
} // namespace Sysman
} // namespace L0

View File

@@ -136,6 +136,28 @@ TEST_F(SysmanDeviceSchedulerFixtureI915, GivenComponentCountZeroWhenCallingzesDe
EXPECT_EQ(count, handleComponentCount);
}
TEST_F(SysmanDeviceSchedulerFixtureI915, GivenComponentCountZeroAndKMDVersionIsPrelimWhenCallingzesDeviceEnumSchedulersThenNonZeroCountIsReturnedAndVerifyCallSucceeds) {
pLinuxSysmanImp->pSysmanKmdInterface.reset();
pLinuxSysmanImp->pSysmanKmdInterface = std::make_unique<SysmanKmdInterfaceI915Prelim>(pLinuxSysmanImp->getProductFamily());
auto pSchedulerHandleContextTest = std::make_unique<L0::Sysman::SchedulerHandleContext>(pOsSysman);
pSchedulerHandleContextTest->init(pOsSysman->getSubDeviceCount());
uint32_t count = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumSchedulers(device->toHandle(), &count, NULL));
EXPECT_EQ(count, handleComponentCount);
uint32_t testcount = count + 1;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumSchedulers(device->toHandle(), &testcount, NULL));
EXPECT_EQ(testcount, count);
count = 0;
std::vector<zes_sched_handle_t> handles(count, nullptr);
EXPECT_EQ(zesDeviceEnumSchedulers(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS);
EXPECT_EQ(count, handleComponentCount);
}
TEST_F(SysmanDeviceSchedulerFixtureI915, GivenValidDeviceHandleWhenCallingzesSchedulerGetCurrentModeThenVerifyzesSchedulerGetCurrentModeCallSucceeds) {
auto handles = getSchedHandles(handleComponentCount);
for (auto handle : handles) {

View File

@@ -83,9 +83,9 @@ TEST_F(SysmanFixtureDeviceI915Prelim, GivenSysmanKmdInterfaceInstanceWhenCalling
EXPECT_STREQ("i915", pSysmanKmdInterface->getHwmonName(0, false).c_str());
}
TEST_F(SysmanFixtureDeviceI915Prelim, GivenSysmanKmdInterfaceInstanceWhenCallingGetEngineBasePathThenEmptyPathIsReturned) {
TEST_F(SysmanFixtureDeviceI915Prelim, GivenSysmanKmdInterfaceInstanceWhenCallingGetEngineBasePathThenCorrectPathIsReturned) {
auto pSysmanKmdInterface = pLinuxSysmanImp->getSysmanKmdInterface();
EXPECT_STREQ("", pSysmanKmdInterface->getEngineBasePath(0).c_str());
EXPECT_STREQ("engine", pSysmanKmdInterface->getEngineBasePath(0).c_str());
}
TEST_F(SysmanFixtureDeviceI915Prelim, GivenSysmanKmdInterfaceWhenGettingSysfsFileNamesThenProperPathsAreReturned) {
@@ -190,9 +190,9 @@ TEST_F(SysmanFixtureDeviceI915Prelim, GivenSysmanKmdInterfaceInstanceWhenCheckin
EXPECT_TRUE(pSysmanKmdInterface->isPhysicalMemorySizeSupported());
}
TEST_F(SysmanFixtureDeviceI915Prelim, GivenSysmanKmdInterfaceInstanceWhenCallingGetEngineClassStringThenInvalidValueIsReturned) {
TEST_F(SysmanFixtureDeviceI915Prelim, GivenSysmanKmdInterfaceInstanceWhenCallingGetEngineClassStringForComputeThenValidStringIsReturned) {
auto pSysmanKmdInterface = pLinuxSysmanImp->getSysmanKmdInterface();
EXPECT_EQ(std::nullopt, pSysmanKmdInterface->getEngineClassString(EngineClass::ENGINE_CLASS_COMPUTE));
EXPECT_EQ("ccs", pSysmanKmdInterface->getEngineClassString(EngineClass::ENGINE_CLASS_COMPUTE));
}
TEST_F(SysmanFixtureDeviceI915Prelim, GivenSysmanKmdInterfaceInstanceWhenCallingGetNumEngineTypeAndInstancesThenErrorIsReturned) {