Propagate exec buffer error to L0 API level

This change makes that drm file is opened in nonblocking mode for prelim
kernels. In such case when calling exec buffer ioctl and get
EAGAIN (aka EWOULDBLOCK) we may return error to API level

Related-To: NEO-7144
Signed-off-by: Mateusz Jablonski <mateusz.jablonski@intel.com>
This commit is contained in:
Mateusz Jablonski 2022-08-25 15:49:58 +00:00 committed by Compute-Runtime-Automation
parent 5c48e027b9
commit 9a95f3c62d
24 changed files with 244 additions and 18 deletions

View File

@ -1116,6 +1116,9 @@ ze_result_t CommandQueueHw<gfxCoreFamily>::handleSubmissionAndCompletionResults(
if (submitRet == NEO::SubmissionStatus::OUT_OF_MEMORY) { if (submitRet == NEO::SubmissionStatus::OUT_OF_MEMORY) {
completionRet = ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY; completionRet = ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY;
} }
if (submitRet == NEO::SubmissionStatus::OUT_OF_HOST_MEMORY) {
completionRet = ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY;
}
} }
return completionRet; return completionRet;

View File

@ -92,6 +92,9 @@ struct MockCommandQueueHw : public L0::CommandQueueHw<gfxCoreFamily> {
NEO::SubmissionStatus submitBatchBuffer(size_t offset, NEO::ResidencyContainer &residencyContainer, void *endingCmdPtr, bool isCooperative) override { NEO::SubmissionStatus submitBatchBuffer(size_t offset, NEO::ResidencyContainer &residencyContainer, void *endingCmdPtr, bool isCooperative) override {
residencyContainerSnapshot = residencyContainer; residencyContainerSnapshot = residencyContainer;
if (submitBatchBufferReturnValue.has_value()) {
return *submitBatchBufferReturnValue;
}
return BaseClass::submitBatchBuffer(offset, residencyContainer, endingCmdPtr, isCooperative); return BaseClass::submitBatchBuffer(offset, residencyContainer, endingCmdPtr, isCooperative);
} }
@ -99,6 +102,7 @@ struct MockCommandQueueHw : public L0::CommandQueueHw<gfxCoreFamily> {
NEO::ResidencyContainer residencyContainerSnapshot; NEO::ResidencyContainer residencyContainerSnapshot;
ze_result_t synchronizeReturnValue{ZE_RESULT_SUCCESS}; ze_result_t synchronizeReturnValue{ZE_RESULT_SUCCESS};
std::optional<NEO::WaitStatus> reserveLinearStreamSizeReturnValue{}; std::optional<NEO::WaitStatus> reserveLinearStreamSizeReturnValue{};
std::optional<NEO::SubmissionStatus> submitBatchBufferReturnValue{};
}; };
struct Deleter { struct Deleter {

View File

@ -0,0 +1,12 @@
#
# Copyright (C) 2022 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
if(UNIX)
target_sources(${TARGET_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/cmdqueue_linux_tests.cpp
)
endif()

View File

@ -0,0 +1,74 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/test/common/helpers/ult_hw_config.h"
#include "shared/test/common/helpers/variable_backup.h"
#include "shared/test/common/libult/create_command_stream.h"
#include "shared/test/common/libult/linux/drm_mock.h"
#include "shared/test/common/test_macros/hw_test.h"
#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h"
#include "level_zero/core/test/unit_tests/mocks/mock_cmdlist.h"
#include "level_zero/core/test/unit_tests/mocks/mock_cmdqueue.h"
#include "level_zero/core/test/unit_tests/mocks/mock_kernel.h"
namespace L0 {
namespace ult {
struct CommandQueueLinuxTests : public Test<DeviceFixture> {
void SetUp() override {
VariableBackup<UltHwConfig> backup(&ultHwConfig);
ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc = false;
ultHwConfig.useHwCsr = true;
ultHwConfig.forceOsAgnosticMemoryManager = false;
auto *executionEnvironment = new NEO::ExecutionEnvironment();
prepareDeviceEnvironments(*executionEnvironment);
executionEnvironment->initializeMemoryManager();
setupWithExecutionEnvironment(*executionEnvironment);
}
};
HWCMDTEST_F(IGFX_XE_HP_CORE, CommandQueueLinuxTests, givenExecBufferErrorWhenExecutingCommandListsThenOutOfHostMemoryIsReturned) {
auto drm = neoDevice->getRootDeviceEnvironment().osInterface->getDriverModel()->as<DrmMock>();
drm->execBufferResult = -1;
drm->baseErrno = false;
drm->errnoRetVal = EWOULDBLOCK;
const ze_command_queue_desc_t desc = {};
ze_result_t returnValue;
auto commandQueue = whiteboxCast(CommandQueue::create(productFamily,
device,
neoDevice->getDefaultEngine().commandStreamReceiver,
&desc,
false,
false,
returnValue));
EXPECT_EQ(ZE_RESULT_SUCCESS, returnValue);
Mock<Kernel> kernel;
kernel.immutableData.isaGraphicsAllocation.reset(neoDevice->getMemoryManager()->allocateGraphicsMemoryWithProperties(
{device->getRootDeviceIndex(), MemoryConstants::pageSize, NEO::AllocationType::KERNEL_ISA, neoDevice->getDeviceBitfield()}));
kernel.immutableData.device = device;
auto commandList = std::unique_ptr<CommandList>(whiteboxCast(CommandList::create(productFamily, device, NEO::EngineGroupType::RenderCompute, 0u, returnValue)));
EXPECT_EQ(ZE_RESULT_SUCCESS, returnValue);
ASSERT_NE(nullptr, commandList);
ze_group_count_t dispatchFunctionArguments{1, 1, 1};
CmdListKernelLaunchParams launchParams = {};
commandList->appendLaunchKernel(kernel.toHandle(), &dispatchFunctionArguments, nullptr, 0, nullptr, launchParams);
ze_command_list_handle_t cmdListHandles[1] = {commandList->toHandle()};
returnValue = commandQueue->executeCommandLists(1, cmdListHandles, nullptr, false);
EXPECT_EQ(ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY, returnValue);
commandQueue->destroy();
neoDevice->getMemoryManager()->freeGraphicsMemory(kernel.immutableData.isaGraphicsAllocation.release());
}
} // namespace ult
} // namespace L0

View File

@ -357,6 +357,30 @@ HWTEST2_F(CommandQueueCreate, givenLogicalStateHelperAndImmediateCmdListWhenExec
commandQueue->destroy(); commandQueue->destroy();
} }
HWTEST2_F(CommandQueueCreate, givenOutOfHostMemoryErrorFromSubmitBatchBufferWhenExecutingCommandListsThenOutOfHostMemoryIsReturned, IsAtLeastSkl) {
const ze_command_queue_desc_t desc = {};
auto commandQueue = new MockCommandQueueHw<gfxCoreFamily>(device, neoDevice->getDefaultEngine().commandStreamReceiver, &desc);
commandQueue->initialize(false, false);
commandQueue->submitBatchBufferReturnValue = NEO::SubmissionStatus::OUT_OF_HOST_MEMORY;
Mock<Kernel> kernel;
kernel.immutableData.device = device;
ze_result_t returnValue;
auto commandList = std::unique_ptr<CommandList>(whiteboxCast(CommandList::create(productFamily, device, NEO::EngineGroupType::RenderCompute, 0u, returnValue)));
ASSERT_NE(nullptr, commandList);
ze_group_count_t dispatchFunctionArguments{1, 1, 1};
CmdListKernelLaunchParams launchParams = {};
commandList->appendLaunchKernel(kernel.toHandle(), &dispatchFunctionArguments, nullptr, 0, nullptr, launchParams);
ze_command_list_handle_t cmdListHandles[1] = {commandList->toHandle()};
const auto result = commandQueue->executeCommandLists(1, cmdListHandles, nullptr, false);
EXPECT_EQ(ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY, result);
commandQueue->destroy();
}
HWTEST2_F(CommandQueueCreate, givenGpuHangInReservingLinearStreamWhenExecutingCommandListsThenDeviceLostIsReturned, IsSKL) { HWTEST2_F(CommandQueueCreate, givenGpuHangInReservingLinearStreamWhenExecutingCommandListsThenDeviceLostIsReturned, IsSKL) {
const ze_command_queue_desc_t desc = {}; const ze_command_queue_desc_t desc = {};
MockCommandQueueHw<gfxCoreFamily> commandQueue(device, neoDevice->getDefaultEngine().commandStreamReceiver, &desc); MockCommandQueueHw<gfxCoreFamily> commandQueue(device, neoDevice->getDefaultEngine().commandStreamReceiver, &desc);

View File

@ -14,6 +14,7 @@ enum class SubmissionStatus : uint32_t {
SUCCESS = 0, SUCCESS = 0,
FAILED, FAILED,
OUT_OF_MEMORY, OUT_OF_MEMORY,
OUT_OF_HOST_MEMORY,
UNSUPPORTED, UNSUPPORTED,
DEVICE_UNINITIALIZED, DEVICE_UNINITIALIZED,
}; };

View File

@ -20,6 +20,9 @@ SubmissionStatus DrmCommandStreamReceiver<GfxFamily>::flushInternal(const BatchB
int ret = this->exec(batchBuffer, 0u, static_cast<const OsContextLinux *>(osContext)->getDrmContextIds()[0], 0); int ret = this->exec(batchBuffer, 0u, static_cast<const OsContextLinux *>(osContext)->getDrmContextIds()[0], 0);
if (ret) { if (ret) {
if (ret == EWOULDBLOCK) {
return SubmissionStatus::OUT_OF_HOST_MEMORY;
}
return SubmissionStatus::FAILED; return SubmissionStatus::FAILED;
} }
return SubmissionStatus::SUCCESS; return SubmissionStatus::SUCCESS;

View File

@ -39,6 +39,9 @@ SubmissionStatus DrmCommandStreamReceiver<GfxFamily>::flushInternal(const BatchB
int ret = this->exec(batchBuffer, tileIterator, drmContextIds[contextIndex], contextIndex); int ret = this->exec(batchBuffer, tileIterator, drmContextIds[contextIndex], contextIndex);
if (ret) { if (ret) {
if (ret == EWOULDBLOCK) {
return SubmissionStatus::OUT_OF_HOST_MEMORY;
}
return SubmissionStatus::FAILED; return SubmissionStatus::FAILED;
} }

View File

@ -58,6 +58,10 @@ void Drm::queryAndSetVmBindPatIndexProgrammingSupport() {
} }
int Drm::ioctl(DrmIoctl request, void *arg) { int Drm::ioctl(DrmIoctl request, void *arg) {
auto shouldBreakIoctlLoopOnWouldBlock = false;
if (ioctlHelper) {
shouldBreakIoctlLoopOnWouldBlock = ioctlHelper->shouldBreakIoctlLoopOnWouldBlock(request);
}
auto requestValue = getIoctlRequestValue(request, ioctlHelper.get()); auto requestValue = getIoctlRequestValue(request, ioctlHelper.get());
int ret; int ret;
int returnedErrno; int returnedErrno;
@ -108,6 +112,10 @@ int Drm::ioctl(DrmIoctl request, void *arg) {
} }
} }
if (ret == -1 && returnedErrno == EWOULDBLOCK && shouldBreakIoctlLoopOnWouldBlock) {
break;
}
} while (ret == -1 && (returnedErrno == EINTR || returnedErrno == EAGAIN || returnedErrno == EBUSY || returnedErrno == -EBUSY)); } while (ret == -1 && (returnedErrno == EINTR || returnedErrno == EAGAIN || returnedErrno == EBUSY || returnedErrno == -EBUSY));
SYSTEM_LEAVE(request); SYSTEM_LEAVE(request);
return ret; return ret;

View File

@ -369,4 +369,5 @@ std::string IoctlHelper::getFileForMaxMemoryFrequencyOfSubDevice(int subDeviceId
return "/gt/gt" + std::to_string(subDeviceId) + "/mem_RP0_freq_mhz"; return "/gt/gt" + std::to_string(subDeviceId) + "/mem_RP0_freq_mhz";
} }
bool IoctlHelper::shouldBreakIoctlLoopOnWouldBlock(DrmIoctl ioctlRequest) const { return false; }
} // namespace NEO } // namespace NEO

View File

@ -136,6 +136,8 @@ class IoctlHelper {
uint32_t getFlagsForPrimeHandleToFd() const; uint32_t getFlagsForPrimeHandleToFd() const;
virtual bool shouldBreakIoctlLoopOnWouldBlock(DrmIoctl ioctlRequest) const;
protected: protected:
Drm &drm; Drm &drm;
}; };
@ -207,7 +209,7 @@ class IoctlHelperImpl : public IoctlHelperUpstream {
class IoctlHelperPrelim20 : public IoctlHelper { class IoctlHelperPrelim20 : public IoctlHelper {
public: public:
using IoctlHelper::IoctlHelper; IoctlHelperPrelim20(Drm &drmArg);
bool initialize() override; bool initialize() override;
bool isSetPairAvailable() override; bool isSetPairAvailable() override;
@ -254,6 +256,7 @@ class IoctlHelperPrelim20 : public IoctlHelper {
int getDrmParamValue(DrmParam drmParam) const override; int getDrmParamValue(DrmParam drmParam) const override;
std::string getDrmParamString(DrmParam param) const override; std::string getDrmParamString(DrmParam param) const override;
std::string getIoctlString(DrmIoctl ioctlRequest) const override; std::string getIoctlString(DrmIoctl ioctlRequest) const override;
bool shouldBreakIoctlLoopOnWouldBlock(DrmIoctl ioctlRequest) const override;
}; };
} // namespace NEO } // namespace NEO

View File

@ -12,9 +12,11 @@
#include "shared/source/helpers/ptr_math.h" #include "shared/source/helpers/ptr_math.h"
#include "shared/source/helpers/string.h" #include "shared/source/helpers/string.h"
#include "shared/source/os_interface/linux/cache_info.h" #include "shared/source/os_interface/linux/cache_info.h"
#include "shared/source/os_interface/linux/drm_neo.h"
#include "shared/source/os_interface/linux/drm_wrappers.h" #include "shared/source/os_interface/linux/drm_wrappers.h"
#include "shared/source/os_interface/linux/i915_prelim.h" #include "shared/source/os_interface/linux/i915_prelim.h"
#include "shared/source/os_interface/linux/ioctl_helper.h" #include "shared/source/os_interface/linux/ioctl_helper.h"
#include "shared/source/os_interface/linux/sys_calls.h"
#include <algorithm> #include <algorithm>
#include <cerrno> #include <cerrno>
@ -25,6 +27,11 @@
namespace NEO { namespace NEO {
IoctlHelperPrelim20::IoctlHelperPrelim20(Drm &drmArg) : IoctlHelper(drmArg) {
auto fileDescriptor = this->drm.getFileDescriptor();
SysCalls::fcntl(fileDescriptor, F_SETFL, SysCalls::fcntl(fileDescriptor, F_GETFL) | O_NONBLOCK);
};
bool IoctlHelperPrelim20::isSetPairAvailable() { bool IoctlHelperPrelim20::isSetPairAvailable() {
int setPairSupported = 0; int setPairSupported = 0;
GetParam getParam{}; GetParam getParam{};
@ -645,6 +652,8 @@ std::string IoctlHelperPrelim20::getIoctlString(DrmIoctl ioctlRequest) const {
} }
} }
bool IoctlHelperPrelim20::shouldBreakIoctlLoopOnWouldBlock(DrmIoctl ioctlRequest) const { return ioctlRequest == DrmIoctl::GemExecbuffer2; }
static_assert(sizeof(MemoryClassInstance) == sizeof(prelim_drm_i915_gem_memory_class_instance)); static_assert(sizeof(MemoryClassInstance) == sizeof(prelim_drm_i915_gem_memory_class_instance));
static_assert(offsetof(MemoryClassInstance, memoryClass) == offsetof(prelim_drm_i915_gem_memory_class_instance, memory_class)); static_assert(offsetof(MemoryClassInstance, memoryClass) == offsetof(prelim_drm_i915_gem_memory_class_instance, memory_class));
static_assert(offsetof(MemoryClassInstance, memoryInstance) == offsetof(prelim_drm_i915_gem_memory_class_instance, memory_instance)); static_assert(offsetof(MemoryClassInstance, memoryInstance) == offsetof(prelim_drm_i915_gem_memory_class_instance, memory_instance));

View File

@ -29,5 +29,7 @@ ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
void *mmap(void *addr, size_t size, int prot, int flags, int fd, off_t off); void *mmap(void *addr, size_t size, int prot, int flags, int fd, off_t off);
int munmap(void *addr, size_t size); int munmap(void *addr, size_t size);
ssize_t read(int fd, void *buf, size_t count); ssize_t read(int fd, void *buf, size_t count);
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, int arg);
} // namespace SysCalls } // namespace SysCalls
} // namespace NEO } // namespace NEO

View File

@ -93,5 +93,12 @@ ssize_t read(int fd, void *buf, size_t count) {
return ::read(fd, buf, count); return ::read(fd, buf, count);
} }
int fcntl(int fd, int cmd) {
return ::fcntl(fd, cmd);
}
int fcntl(int fd, int cmd, int arg) {
return ::fcntl(fd, cmd, arg);
}
} // namespace SysCalls } // namespace SysCalls
} // namespace NEO } // namespace NEO

View File

@ -193,7 +193,7 @@ int DrmMock::ioctl(DrmIoctl request, void *arg) {
for (uint32_t i = 0; i < execbuf->getBufferCount(); i++) { for (uint32_t i = 0; i < execbuf->getBufferCount(); i++) {
this->receivedBos.push_back(execObjects[i]); this->receivedBos.push_back(execObjects[i]);
} }
return 0; return execBufferResult;
} }
if (request == DrmIoctl::GemUserptr) { if (request == DrmIoctl::GemUserptr) {
ioctlCount.gemUserptr++; ioctlCount.gemUserptr++;

View File

@ -212,6 +212,7 @@ class DrmMock : public Drm {
//DRM_IOCTL_I915_GEM_EXECBUFFER2 //DRM_IOCTL_I915_GEM_EXECBUFFER2
std::vector<MockExecBuffer> execBuffers{}; std::vector<MockExecBuffer> execBuffers{};
std::vector<MockExecObject> receivedBos{}; std::vector<MockExecObject> receivedBos{};
int execBufferResult = 0;
//DRM_IOCTL_I915_GEM_CREATE //DRM_IOCTL_I915_GEM_CREATE
uint64_t createParamsSize = 0; uint64_t createParamsSize = 0;
uint32_t createParamsHandle = 0; uint32_t createParamsHandle = 0;

View File

@ -8,12 +8,15 @@
#pragma once #pragma once
#include "shared/source/os_interface/linux/drm_buffer_object.h" #include "shared/source/os_interface/linux/drm_buffer_object.h"
#include "shared/source/os_interface/linux/drm_memory_operations_handler_default.h" #include "shared/source/os_interface/linux/drm_memory_operations_handler_default.h"
#include "shared/source/os_interface/linux/drm_wrappers.h"
#include "shared/source/os_interface/linux/os_context_linux.h" #include "shared/source/os_interface/linux/os_context_linux.h"
#include "shared/test/common/helpers/engine_descriptor_helper.h" #include "shared/test/common/helpers/engine_descriptor_helper.h"
#include "shared/test/common/mocks/mock_execution_environment.h" #include "shared/test/common/mocks/mock_execution_environment.h"
#include <memory> #include <memory>
using namespace NEO;
class TestedBufferObject : public BufferObject { class TestedBufferObject : public BufferObject {
public: public:
using BufferObject::handle; using BufferObject::handle;

View File

@ -20,6 +20,14 @@
#include <algorithm> #include <algorithm>
template <typename GfxFamily>
struct MockDrmCsr : public DrmCommandStreamReceiver<GfxFamily> {
using DrmCommandStreamReceiver<GfxFamily>::DrmCommandStreamReceiver;
using DrmCommandStreamReceiver<GfxFamily>::dispatchMode;
using DrmCommandStreamReceiver<GfxFamily>::completionFenceValuePointer;
using DrmCommandStreamReceiver<GfxFamily>::flushInternal;
};
class DrmCommandStreamTest : public ::testing::Test { class DrmCommandStreamTest : public ::testing::Test {
public: public:
template <typename GfxFamily> template <typename GfxFamily>
@ -43,7 +51,7 @@ class DrmCommandStreamTest : public ::testing::Test {
PreemptionHelper::getDefaultPreemptionMode(*hwInfo))); PreemptionHelper::getDefaultPreemptionMode(*hwInfo)));
osContext->ensureContextInitialized(); osContext->ensureContextInitialized();
csr = new DrmCommandStreamReceiver<GfxFamily>(executionEnvironment, 0, 1, gemCloseWorkerMode::gemCloseWorkerActive); csr = new MockDrmCsr<GfxFamily>(executionEnvironment, 0, 1, gemCloseWorkerMode::gemCloseWorkerActive);
ASSERT_NE(nullptr, csr); ASSERT_NE(nullptr, csr);
csr->setupContext(*osContext); csr->setupContext(*osContext);

View File

@ -5,6 +5,8 @@
* *
*/ */
#include "shared/test/common/os_interface/linux/sys_calls_linux_ult.h"
#include "shared/source/helpers/string.h" #include "shared/source/helpers/string.h"
#include "shared/source/os_interface/linux/drm_wrappers.h" #include "shared/source/os_interface/linux/drm_wrappers.h"
#include "shared/source/os_interface/linux/i915.h" #include "shared/source/os_interface/linux/i915.h"
@ -17,6 +19,7 @@
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <dlfcn.h> #include <dlfcn.h>
#include <fcntl.h>
#include <iostream> #include <iostream>
#include <poll.h> #include <poll.h>
#include <stdio.h> #include <stdio.h>
@ -31,7 +34,6 @@ int closeFuncArgPassed = 0;
int closeFuncRetVal = 0; int closeFuncRetVal = 0;
int dlOpenFlags = 0; int dlOpenFlags = 0;
bool dlOpenCalled = 0; bool dlOpenCalled = 0;
constexpr int fakeFileDescriptor = 123;
bool makeFakeDevicePath = false; bool makeFakeDevicePath = false;
bool allowFakeDevicePath = false; bool allowFakeDevicePath = false;
constexpr unsigned long int invalidIoctl = static_cast<unsigned long int>(-1); constexpr unsigned long int invalidIoctl = static_cast<unsigned long int>(-1);
@ -43,6 +45,9 @@ uint32_t mmapFuncCalled = 0u;
uint32_t munmapFuncCalled = 0u; uint32_t munmapFuncCalled = 0u;
bool isInvalidAILTest = false; bool isInvalidAILTest = false;
const char *drmVersion = "i915"; const char *drmVersion = "i915";
int passedFileDescriptorFlagsToSet = 0;
int getFileDescriptorFlagsCalled = 0;
int setFileDescriptorFlagsCalled = 0;
int (*sysCallsOpen)(const char *pathname, int flags) = nullptr; int (*sysCallsOpen)(const char *pathname, int flags) = nullptr;
ssize_t (*sysCallsPread)(int fd, void *buf, size_t count, off_t offset) = nullptr; ssize_t (*sysCallsPread)(int fd, void *buf, size_t count, off_t offset) = nullptr;
@ -195,5 +200,21 @@ ssize_t read(int fd, void *buf, size_t count) {
return 0; return 0;
} }
int fcntl(int fd, int cmd) {
if (cmd == F_GETFL) {
getFileDescriptorFlagsCalled++;
return O_RDWR;
}
return 0;
}
int fcntl(int fd, int cmd, int arg) {
if (cmd == F_SETFL) {
setFileDescriptorFlagsCalled++;
passedFileDescriptorFlagsToSet = arg;
}
return 0;
}
} // namespace SysCalls } // namespace SysCalls
} // namespace NEO } // namespace NEO

View File

@ -21,5 +21,9 @@ extern int (*sysCallsPoll)(struct pollfd *pollFd, unsigned long int numberOfFds,
extern ssize_t (*sysCallsRead)(int fd, void *buf, size_t count); extern ssize_t (*sysCallsRead)(int fd, void *buf, size_t count);
extern const char *drmVersion; extern const char *drmVersion;
constexpr int fakeFileDescriptor = 123;
extern int passedFileDescriptorFlagsToSet;
extern int getFileDescriptorFlagsCalled;
extern int setFileDescriptorFlagsCalled;
} // namespace SysCalls } // namespace SysCalls
} // namespace NEO } // namespace NEO

View File

@ -6,7 +6,9 @@
*/ */
#include "shared/source/helpers/api_specific_config.h" #include "shared/source/helpers/api_specific_config.h"
#include "shared/test/common/mocks/linux/mock_drm_allocation.h"
#include "shared/test/common/mocks/mock_graphics_allocation.h" #include "shared/test/common/mocks/mock_graphics_allocation.h"
#include "shared/test/common/os_interface/linux/drm_buffer_object_fixture.h"
#include "shared/test/common/os_interface/linux/drm_command_stream_fixture.h" #include "shared/test/common/os_interface/linux/drm_command_stream_fixture.h"
#include "shared/test/common/test_macros/hw_test.h" #include "shared/test/common/test_macros/hw_test.h"
@ -15,13 +17,6 @@ extern ApiSpecificConfig::ApiType apiTypeForUlts;
} //namespace NEO } //namespace NEO
using namespace NEO; using namespace NEO;
template <typename GfxFamily>
struct MockDrmCsr : public DrmCommandStreamReceiver<GfxFamily> {
using DrmCommandStreamReceiver<GfxFamily>::DrmCommandStreamReceiver;
using DrmCommandStreamReceiver<GfxFamily>::dispatchMode;
using DrmCommandStreamReceiver<GfxFamily>::completionFenceValuePointer;
};
HWTEST_TEMPLATED_F(DrmCommandStreamTest, givenL0ApiConfigWhenCreatingDrmCsrThenEnableImmediateDispatch) { HWTEST_TEMPLATED_F(DrmCommandStreamTest, givenL0ApiConfigWhenCreatingDrmCsrThenEnableImmediateDispatch) {
VariableBackup<ApiSpecificConfig::ApiType> backup(&apiTypeForUlts, ApiSpecificConfig::L0); VariableBackup<ApiSpecificConfig::ApiType> backup(&apiTypeForUlts, ApiSpecificConfig::L0);
MockDrmCsr<FamilyType> csr(executionEnvironment, 0, 1, gemCloseWorkerMode::gemCloseWorkerInactive); MockDrmCsr<FamilyType> csr(executionEnvironment, 0, 1, gemCloseWorkerMode::gemCloseWorkerInactive);
@ -75,3 +70,20 @@ HWTEST_TEMPLATED_F(DrmCommandStreamTest, givenNoTagAddressWhenGettingCompletionA
EXPECT_EQ(nullptr, csr->getTagAddress()); EXPECT_EQ(nullptr, csr->getTagAddress());
EXPECT_EQ(0u, csr->getCompletionAddress()); EXPECT_EQ(0u, csr->getCompletionAddress());
} }
HWTEST_TEMPLATED_F(DrmCommandStreamTest, GivenExecBufferErrorWhenFlushInternalThenProperErrorIsReturned) {
mock->execBufferResult = -1;
mock->baseErrno = false;
mock->errnoRetVal = EWOULDBLOCK;
TestedBufferObject bo(mock, 128);
MockDrmAllocation cmdBuffer(AllocationType::COMMAND_BUFFER, MemoryPool::System4KBPages);
cmdBuffer.bufferObjects[0] = &bo;
uint8_t buff[128]{};
LinearStream cs(&cmdBuffer, buff, 128);
BatchBuffer batchBuffer{cs.getGraphicsAllocation(), 0, 0, nullptr, false, false, QueueThrottle::MEDIUM, QueueSliceCount::defaultSliceCount, cs.getUsed(), &cs, nullptr, false};
auto ret = static_cast<MockDrmCsr<FamilyType> *>(csr)->flushInternal(batchBuffer, csr->getResidencyAllocations());
EXPECT_EQ(SubmissionStatus::OUT_OF_HOST_MEMORY, ret);
}

View File

@ -884,12 +884,6 @@ HWTEST_TEMPLATED_F(DrmCommandStreamBlitterDirectSubmissionTest, givenEnabledDire
EXPECT_EQ(nullptr, static_cast<TestedDrmCommandStreamReceiver<FamilyType> *>(csr)->directSubmission.get()); EXPECT_EQ(nullptr, static_cast<TestedDrmCommandStreamReceiver<FamilyType> *>(csr)->directSubmission.get());
} }
template <typename GfxFamily>
struct MockDrmCsr : public DrmCommandStreamReceiver<GfxFamily> {
using DrmCommandStreamReceiver<GfxFamily>::DrmCommandStreamReceiver;
using DrmCommandStreamReceiver<GfxFamily>::dispatchMode;
};
HWTEST_TEMPLATED_F(DrmCommandStreamTest, givenDrmCommandStreamReceiverWhenCreatePageTableManagerIsCalledThenCreatePageTableManager) { HWTEST_TEMPLATED_F(DrmCommandStreamTest, givenDrmCommandStreamReceiverWhenCreatePageTableManagerIsCalledThenCreatePageTableManager) {
executionEnvironment.prepareRootDeviceEnvironments(2); executionEnvironment.prepareRootDeviceEnvironments(2);
executionEnvironment.rootDeviceEnvironments[1]->setHwInfo(defaultHwInfo.get()); executionEnvironment.rootDeviceEnvironments[1]->setHwInfo(defaultHwInfo.get());

View File

@ -10,7 +10,9 @@
#include "shared/source/os_interface/linux/i915_prelim.h" #include "shared/source/os_interface/linux/i915_prelim.h"
#include "shared/source/os_interface/linux/ioctl_helper.h" #include "shared/source/os_interface/linux/ioctl_helper.h"
#include "shared/test/common/helpers/debug_manager_state_restore.h" #include "shared/test/common/helpers/debug_manager_state_restore.h"
#include "shared/test/common/helpers/variable_backup.h"
#include "shared/test/common/mocks/mock_execution_environment.h" #include "shared/test/common/mocks/mock_execution_environment.h"
#include "shared/test/common/os_interface/linux/sys_calls_linux_ult.h"
#include "shared/test/common/test_macros/test.h" #include "shared/test/common/test_macros/test.h"
using namespace NEO; using namespace NEO;
@ -348,3 +350,22 @@ TEST_F(IoctlPrelimHelperTests, givenPrelimWhenGettingEuStallPropertiesThenCorrec
TEST_F(IoctlPrelimHelperTests, givenPrelimWhenGettingEuStallFdParameterThenCorrectIoctlValueIsReturned) { TEST_F(IoctlPrelimHelperTests, givenPrelimWhenGettingEuStallFdParameterThenCorrectIoctlValueIsReturned) {
EXPECT_EQ(static_cast<uint32_t>(PRELIM_I915_PERF_FLAG_FD_EU_STALL), ioctlHelper.getEuStallFdParameter()); EXPECT_EQ(static_cast<uint32_t>(PRELIM_I915_PERF_FLAG_FD_EU_STALL), ioctlHelper.getEuStallFdParameter());
} }
TEST_F(IoctlPrelimHelperTests, whenCallingIoctlWithGemExecbufferThenShouldBreakOnWouldBlock) {
EXPECT_TRUE(ioctlHelper.shouldBreakIoctlLoopOnWouldBlock(DrmIoctl::GemExecbuffer2));
EXPECT_FALSE(ioctlHelper.shouldBreakIoctlLoopOnWouldBlock(DrmIoctl::GemVmBind));
}
TEST(IoctlPrelimHelperTest, whenCreatingIoctlHelperThenProperFlagsAreSetToFileDescriptor) {
MockExecutionEnvironment executionEnvironment{};
std::unique_ptr<Drm> drm{Drm::create(std::make_unique<HwDeviceIdDrm>(0, ""), *executionEnvironment.rootDeviceEnvironments[0])};
VariableBackup<decltype(SysCalls::getFileDescriptorFlagsCalled)> backupGetFlags(&SysCalls::getFileDescriptorFlagsCalled, 0);
VariableBackup<decltype(SysCalls::setFileDescriptorFlagsCalled)> backupSetFlags(&SysCalls::setFileDescriptorFlagsCalled, 0);
VariableBackup<decltype(SysCalls::passedFileDescriptorFlagsToSet)> backupPassedFlags(&SysCalls::passedFileDescriptorFlagsToSet, 0);
IoctlHelperPrelim20 ioctlHelper{*drm};
EXPECT_EQ(1, SysCalls::getFileDescriptorFlagsCalled);
EXPECT_EQ(1, SysCalls::setFileDescriptorFlagsCalled);
EXPECT_EQ((O_RDWR | O_NONBLOCK), SysCalls::passedFileDescriptorFlagsToSet);
}

View File

@ -477,3 +477,11 @@ TEST(IoctlHelperTestsUpstream, givenUpstreamWhenInitializingThenTrueIsReturned)
IoctlHelperUpstream ioctlHelper{*drm}; IoctlHelperUpstream ioctlHelper{*drm};
EXPECT_EQ(true, ioctlHelper.initialize()); EXPECT_EQ(true, ioctlHelper.initialize());
} }
TEST(IoctlHelperUpstreamTest, whenCallingIoctlWithGemExecbufferThenShouldNotBreakOnWouldBlock) {
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
auto drm = std::make_unique<DrmTipMock>(*executionEnvironment->rootDeviceEnvironments[0]);
IoctlHelperUpstream ioctlHelper{*drm};
EXPECT_FALSE(ioctlHelper.shouldBreakIoctlLoopOnWouldBlock(DrmIoctl::GemExecbuffer2));
EXPECT_FALSE(ioctlHelper.shouldBreakIoctlLoopOnWouldBlock(DrmIoctl::GemVmBind));
}