2017-12-21 07:45:38 +08:00
|
|
|
/*
|
2019-02-27 18:39:32 +08:00
|
|
|
* Copyright (C) 2017-2019 Intel Corporation
|
2017-12-21 07:45:38 +08:00
|
|
|
*
|
2018-09-18 15:11:08 +08:00
|
|
|
* SPDX-License-Identifier: MIT
|
2017-12-21 07:45:38 +08:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "drm_neo.h"
|
2019-02-27 18:39:32 +08:00
|
|
|
|
2019-11-29 22:41:47 +08:00
|
|
|
#include "core/helpers/hw_info.h"
|
2019-09-04 16:58:52 +08:00
|
|
|
#include "core/memory_manager/memory_constants.h"
|
2019-12-11 22:28:22 +08:00
|
|
|
#include "core/os_interface/linux/os_inc.h"
|
2019-09-11 15:26:24 +08:00
|
|
|
#include "core/utilities/directory.h"
|
2019-02-27 18:39:32 +08:00
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstring>
|
|
|
|
#include <fstream>
|
|
|
|
|
2019-03-26 18:59:46 +08:00
|
|
|
namespace NEO {
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
const char *Drm::sysFsDefaultGpuPath = "/drm/card0";
|
|
|
|
const char *Drm::maxGpuFrequencyFile = "/gt_max_freq_mhz";
|
|
|
|
const char *Drm::configFileName = "/config";
|
|
|
|
|
|
|
|
int Drm::ioctl(unsigned long request, void *arg) {
|
|
|
|
int ret;
|
|
|
|
SYSTEM_ENTER();
|
|
|
|
do {
|
|
|
|
ret = ::ioctl(fd, request, arg);
|
|
|
|
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
|
|
|
|
SYSTEM_LEAVE(request);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-03-12 19:03:20 +08:00
|
|
|
int Drm::getParamIoctl(int param, int *dstValue) {
|
|
|
|
drm_i915_getparam_t getParam = {};
|
|
|
|
getParam.param = param;
|
|
|
|
getParam.value = dstValue;
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2018-03-12 19:03:20 +08:00
|
|
|
return ioctl(DRM_IOCTL_I915_GETPARAM, &getParam);
|
|
|
|
}
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2018-03-12 19:03:20 +08:00
|
|
|
int Drm::getDeviceID(int &devId) {
|
|
|
|
return getParamIoctl(I915_PARAM_CHIPSET_ID, &devId);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Drm::getDeviceRevID(int &revId) {
|
2018-03-12 19:03:20 +08:00
|
|
|
return getParamIoctl(I915_PARAM_REVISION, &revId);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Drm::getExecSoftPin(int &execSoftPin) {
|
2018-03-12 19:03:20 +08:00
|
|
|
return getParamIoctl(I915_PARAM_HAS_EXEC_SOFTPIN, &execSoftPin);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Drm::enableTurboBoost() {
|
2018-03-20 17:49:09 +08:00
|
|
|
drm_i915_gem_context_param contextParam = {};
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
contextParam.param = I915_CONTEXT_PRIVATE_PARAM_BOOST;
|
|
|
|
contextParam.value = 1;
|
2018-03-20 17:49:09 +08:00
|
|
|
return ioctl(DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &contextParam);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Drm::getEnabledPooledEu(int &enabled) {
|
2018-03-12 19:03:20 +08:00
|
|
|
return getParamIoctl(I915_PARAM_HAS_POOLED_EU, &enabled);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Drm::getMaxGpuFrequency(int &maxGpuFrequency) {
|
|
|
|
maxGpuFrequency = 0;
|
|
|
|
int deviceID = 0;
|
|
|
|
int ret = getDeviceID(deviceID);
|
|
|
|
if (ret != 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
std::string clockSysFsPath = getSysFsPciPath(deviceID);
|
|
|
|
|
|
|
|
if (clockSysFsPath.size() == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
clockSysFsPath += sysFsDefaultGpuPath;
|
|
|
|
clockSysFsPath += maxGpuFrequencyFile;
|
|
|
|
|
|
|
|
std::ifstream ifs(clockSysFsPath.c_str(), std::ifstream::in);
|
|
|
|
if (ifs.fail()) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ifs >> maxGpuFrequency;
|
|
|
|
ifs.close();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string Drm::getSysFsPciPath(int deviceID) {
|
|
|
|
std::string nullPath;
|
|
|
|
std::string sysFsPciDirectory = Os::sysFsPciPath;
|
|
|
|
std::vector<std::string> files = Directory::getFiles(sysFsPciDirectory);
|
|
|
|
|
|
|
|
for (std::vector<std::string>::iterator file = files.begin(); file != files.end(); ++file) {
|
2018-03-20 17:49:09 +08:00
|
|
|
PCIConfig config = {};
|
2017-12-21 07:45:38 +08:00
|
|
|
std::string configPath = *file + configFileName;
|
|
|
|
std::string sysfsPath = *file;
|
|
|
|
std::ifstream configFile(configPath, std::ifstream::binary);
|
|
|
|
if (configFile.is_open()) {
|
|
|
|
configFile.read(reinterpret_cast<char *>(&config), sizeof(config));
|
|
|
|
|
|
|
|
if (!configFile.good() || (config.DeviceID != deviceID)) {
|
|
|
|
configFile.close();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
return sysfsPath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullPath;
|
|
|
|
}
|
|
|
|
|
2019-12-17 22:17:52 +08:00
|
|
|
int Drm::queryGttSize(uint64_t >tSizeOutput) {
|
2019-04-23 21:42:33 +08:00
|
|
|
drm_i915_gem_context_param contextParam = {0};
|
|
|
|
contextParam.param = I915_CONTEXT_PARAM_GTT_SIZE;
|
|
|
|
|
2019-12-17 22:17:52 +08:00
|
|
|
int ret = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &contextParam);
|
2019-04-23 21:42:33 +08:00
|
|
|
if (ret == 0) {
|
2019-12-17 22:17:52 +08:00
|
|
|
gttSizeOutput = contextParam.value;
|
2019-04-23 21:42:33 +08:00
|
|
|
}
|
2019-12-17 22:17:52 +08:00
|
|
|
|
|
|
|
return ret;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2018-12-07 22:03:23 +08:00
|
|
|
void Drm::checkPreemptionSupport() {
|
2017-12-21 07:45:38 +08:00
|
|
|
int value = 0;
|
2019-03-22 13:21:52 +08:00
|
|
|
auto ret = getParamIoctl(I915_PARAM_HAS_SCHEDULER, &value);
|
|
|
|
preemptionSupported = ((0 == ret) && (value & I915_SCHEDULER_CAP_PREEMPTION));
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2019-08-21 18:50:47 +08:00
|
|
|
void Drm::checkQueueSliceSupport() {
|
|
|
|
sliceCountChangeSupported = getQueueSliceCount(&sseu) == 0 ? true : false;
|
|
|
|
}
|
|
|
|
|
2018-12-11 15:21:56 +08:00
|
|
|
void Drm::setLowPriorityContextParam(uint32_t drmContextId) {
|
2018-12-07 22:03:23 +08:00
|
|
|
drm_i915_gem_context_param gcp = {};
|
2018-12-11 15:21:56 +08:00
|
|
|
gcp.ctx_id = drmContextId;
|
2017-12-21 07:45:38 +08:00
|
|
|
gcp.param = I915_CONTEXT_PARAM_PRIORITY;
|
|
|
|
gcp.value = -1023;
|
|
|
|
|
2018-12-11 15:21:56 +08:00
|
|
|
auto retVal = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &gcp);
|
|
|
|
UNRECOVERABLE_IF(retVal != 0);
|
|
|
|
}
|
|
|
|
|
2019-08-21 18:50:47 +08:00
|
|
|
int Drm::getQueueSliceCount(drm_i915_gem_context_param_sseu *sseu) {
|
|
|
|
drm_i915_gem_context_param contextParam = {};
|
|
|
|
contextParam.param = I915_CONTEXT_PARAM_SSEU;
|
|
|
|
sseu->engine.engine_class = I915_ENGINE_CLASS_RENDER;
|
|
|
|
sseu->engine.engine_instance = I915_EXEC_DEFAULT;
|
|
|
|
contextParam.value = reinterpret_cast<uint64_t>(sseu);
|
|
|
|
contextParam.size = sizeof(struct drm_i915_gem_context_param_sseu);
|
|
|
|
|
|
|
|
return ioctl(DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &contextParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t Drm::getSliceMask(uint64_t sliceCount) {
|
2019-11-28 01:00:52 +08:00
|
|
|
return maxNBitValue(sliceCount);
|
2019-08-21 18:50:47 +08:00
|
|
|
}
|
|
|
|
bool Drm::setQueueSliceCount(uint64_t sliceCount) {
|
|
|
|
if (sliceCountChangeSupported) {
|
|
|
|
drm_i915_gem_context_param contextParam = {};
|
|
|
|
sseu.slice_mask = getSliceMask(sliceCount);
|
|
|
|
|
|
|
|
contextParam.param = I915_CONTEXT_PARAM_SSEU;
|
|
|
|
contextParam.ctx_id = 0;
|
|
|
|
contextParam.value = reinterpret_cast<uint64_t>(&sseu);
|
|
|
|
contextParam.size = sizeof(struct drm_i915_gem_context_param_sseu);
|
|
|
|
int retVal = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &contextParam);
|
|
|
|
if (retVal == 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-12-24 19:20:23 +08:00
|
|
|
void Drm::checkNonPersistentContextsSupport() {
|
2019-12-19 02:38:22 +08:00
|
|
|
drm_i915_gem_context_param contextParam = {};
|
|
|
|
contextParam.param = I915_CONTEXT_PARAM_PERSISTENCE;
|
|
|
|
|
|
|
|
auto retVal = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &contextParam);
|
2019-12-24 19:20:23 +08:00
|
|
|
if (retVal == 0 && contextParam.value == 1) {
|
|
|
|
nonPersistentContextsSupported = true;
|
2019-12-19 02:38:22 +08:00
|
|
|
} else {
|
2019-12-24 19:20:23 +08:00
|
|
|
nonPersistentContextsSupported = false;
|
2019-12-19 02:38:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-24 19:20:23 +08:00
|
|
|
void Drm::setNonPersistentContext(uint32_t drmContextId) {
|
2019-12-19 02:38:22 +08:00
|
|
|
drm_i915_gem_context_param contextParam = {};
|
|
|
|
contextParam.ctx_id = drmContextId;
|
|
|
|
contextParam.param = I915_CONTEXT_PARAM_PERSISTENCE;
|
|
|
|
|
|
|
|
auto retVal = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &contextParam);
|
|
|
|
UNRECOVERABLE_IF(retVal != 0);
|
|
|
|
}
|
|
|
|
|
2018-12-11 15:21:56 +08:00
|
|
|
uint32_t Drm::createDrmContext() {
|
|
|
|
drm_i915_gem_context_create gcc = {};
|
|
|
|
auto retVal = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &gcc);
|
2018-12-07 22:03:23 +08:00
|
|
|
UNRECOVERABLE_IF(retVal != 0);
|
2018-12-11 15:21:56 +08:00
|
|
|
|
|
|
|
return gcc.ctx_id;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2018-12-11 15:21:56 +08:00
|
|
|
void Drm::destroyDrmContext(uint32_t drmContextId) {
|
2018-03-20 17:49:09 +08:00
|
|
|
drm_i915_gem_context_destroy destroy = {};
|
2018-12-11 15:21:56 +08:00
|
|
|
destroy.ctx_id = drmContextId;
|
2018-12-07 22:03:23 +08:00
|
|
|
auto retVal = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &destroy);
|
|
|
|
UNRECOVERABLE_IF(retVal != 0);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Drm::getEuTotal(int &euTotal) {
|
2019-07-23 17:45:10 +08:00
|
|
|
return getParamIoctl(I915_PARAM_EU_TOTAL, &euTotal);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Drm::getSubsliceTotal(int &subsliceTotal) {
|
2018-03-12 19:03:20 +08:00
|
|
|
return getParamIoctl(I915_PARAM_SUBSLICE_TOTAL, &subsliceTotal);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Drm::getMinEuInPool(int &minEUinPool) {
|
2018-03-12 19:03:20 +08:00
|
|
|
return getParamIoctl(I915_PARAM_MIN_EU_IN_POOL, &minEUinPool);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2018-02-28 19:09:48 +08:00
|
|
|
int Drm::getErrno() {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
2019-10-18 16:15:09 +08:00
|
|
|
int Drm::setupHardwareInfo(DeviceDescriptor *device, bool setupFeatureTableAndWorkaroundTable) {
|
|
|
|
HardwareInfo *hwInfo = const_cast<HardwareInfo *>(device->pHwInfo);
|
|
|
|
int ret;
|
|
|
|
int euTotal;
|
|
|
|
int subsliceTotal;
|
|
|
|
|
|
|
|
ret = getEuTotal(euTotal);
|
|
|
|
if (ret != 0) {
|
|
|
|
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "%s", "FATAL: Cannot query EU total parameter!\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = getSubsliceTotal(subsliceTotal);
|
|
|
|
if (ret != 0) {
|
|
|
|
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "%s", "FATAL: Cannot query subslice total parameter!\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
hwInfo->gtSystemInfo.EUCount = static_cast<uint32_t>(euTotal);
|
|
|
|
hwInfo->gtSystemInfo.SubSliceCount = static_cast<uint32_t>(subsliceTotal);
|
|
|
|
device->setupHardwareInfo(hwInfo, setupFeatureTableAndWorkaroundTable);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-03-26 18:59:46 +08:00
|
|
|
} // namespace NEO
|