diff --git a/shared/source/direct_submission/direct_submission_hw.h b/shared/source/direct_submission/direct_submission_hw.h index 5545fa6eee..2d25a08b1d 100644 --- a/shared/source/direct_submission/direct_submission_hw.h +++ b/shared/source/direct_submission/direct_submission_hw.h @@ -86,6 +86,7 @@ class DirectSubmissionHw { bool startRingBuffer(); MOCKABLE_VIRTUAL bool dispatchCommandBuffer(BatchBuffer &batchBuffer, FlushStampTracker &flushStamp); + uint32_t getDispatchErrorCode(); static std::unique_ptr> create(const DirectSubmissionInputParams &inputParams); @@ -219,6 +220,7 @@ class DirectSubmissionHw { uint32_t currentRelaxedOrderingQueueSize = 0; DirectSubmissionSfenceMode sfenceMode = DirectSubmissionSfenceMode::BeforeAndAfterSemaphore; volatile uint32_t reserved = 0u; + uint32_t dispatchErrorCode = 0; bool ringStart = false; bool disableCpuCacheFlush = true; diff --git a/shared/source/direct_submission/direct_submission_hw.inl b/shared/source/direct_submission/direct_submission_hw.inl index 350e82c8d4..6c0ccd1c08 100644 --- a/shared/source/direct_submission/direct_submission_hw.inl +++ b/shared/source/direct_submission/direct_submission_hw.inl @@ -1151,4 +1151,9 @@ size_t DirectSubmissionHw::getSizeSystemMemoryFenceAddres return EncodeMemoryFence::getSystemMemoryFenceSize(); } +template +uint32_t DirectSubmissionHw::getDispatchErrorCode() { + return dispatchErrorCode; +} + } // namespace NEO diff --git a/shared/source/direct_submission/linux/drm_direct_submission.inl b/shared/source/direct_submission/linux/drm_direct_submission.inl index 03289afc0c..9c3d8277a0 100644 --- a/shared/source/direct_submission/linux/drm_direct_submission.inl +++ b/shared/source/direct_submission/linux/drm_direct_submission.inl @@ -120,7 +120,7 @@ bool DrmDirectSubmission::submit(uint64_t gpuAddress, siz auto currentBase = this->ringCommandStream.getGraphicsAllocation()->getGpuAddress(); auto offset = ptrDiff(gpuAddress, currentBase); - bool ret = false; + bool ret = true; uint32_t drmContextId = 0u; TaskCountType completionValue = 0u; @@ -132,18 +132,22 @@ bool DrmDirectSubmission::submit(uint64_t gpuAddress, siz for (auto drmIterator = 0u; drmIterator < osContextLinux->getDeviceBitfield().size(); drmIterator++) { if (osContextLinux->getDeviceBitfield().test(drmIterator)) { - ret |= !!bb->exec(static_cast(size), - offset, - execFlags, - false, - &this->osContext, - drmIterator, - drmContextIds[drmContextId], - nullptr, - 0, - &execObject, - completionFenceGpuAddress, - completionValue); + uint32_t errorCode = bb->exec(static_cast(size), + offset, + execFlags, + false, + &this->osContext, + drmIterator, + drmContextIds[drmContextId], + nullptr, + 0, + &execObject, + completionFenceGpuAddress, + completionValue); + if (errorCode != 0) { + this->dispatchErrorCode = errorCode; + ret = false; + } drmContextId++; if (completionFenceGpuAddress) { completionFenceGpuAddress += this->postSyncOffset; @@ -151,7 +155,7 @@ bool DrmDirectSubmission::submit(uint64_t gpuAddress, siz } } - return !ret; + return ret; } template diff --git a/shared/source/os_interface/linux/drm_command_stream.inl b/shared/source/os_interface/linux/drm_command_stream.inl index 0274010851..7814aeb781 100644 --- a/shared/source/os_interface/linux/drm_command_stream.inl +++ b/shared/source/os_interface/linux/drm_command_stream.inl @@ -130,7 +130,7 @@ SubmissionStatus DrmCommandStreamReceiver::flush(BatchBuffer &batchBu this->startControllingDirectSubmissions(); bool ret = this->directSubmission->dispatchCommandBuffer(batchBuffer, *this->flushStamp.get()); if (ret == false) { - return SubmissionStatus::FAILED; + return Drm::getSubmissionStatusFromReturnCode(this->directSubmission->getDispatchErrorCode()); } return SubmissionStatus::SUCCESS; } @@ -138,7 +138,7 @@ SubmissionStatus DrmCommandStreamReceiver::flush(BatchBuffer &batchBu this->startControllingDirectSubmissions(); bool ret = this->blitterDirectSubmission->dispatchCommandBuffer(batchBuffer, *this->flushStamp.get()); if (ret == false) { - return SubmissionStatus::FAILED; + return Drm::getSubmissionStatusFromReturnCode(this->blitterDirectSubmission->getDispatchErrorCode()); } return SubmissionStatus::SUCCESS; } diff --git a/shared/test/common/mocks/linux/mock_drm_allocation.h b/shared/test/common/mocks/linux/mock_drm_allocation.h index 43a7456911..3f96baa8ca 100644 --- a/shared/test/common/mocks/linux/mock_drm_allocation.h +++ b/shared/test/common/mocks/linux/mock_drm_allocation.h @@ -10,6 +10,8 @@ #include "shared/source/os_interface/linux/drm_buffer_object.h" #include "shared/test/common/test_macros/mock_method_macros.h" +#include + namespace NEO { class MockBufferObjectHandleWrapper : public BufferObjectHandleWrapper { @@ -34,11 +36,15 @@ class MockBufferObject : public BufferObject { TaskCountType completionValue = 0; }; + std::optional execReturnValue; std::vector passedExecParams{}; MockBufferObject(Drm *drm) : BufferObject(drm, CommonConstants::unsupportedPatIndex, 0, 0, 1) { } int exec(uint32_t used, size_t startOffset, unsigned int flags, bool requiresCoherency, OsContext *osContext, uint32_t vmHandleId, uint32_t drmContextId, BufferObject *const residency[], size_t residencyCount, ExecObject *execObjectsStorage, uint64_t completionGpuAddress, TaskCountType completionValue) override { + if (execReturnValue) { + return *execReturnValue; + } passedExecParams.push_back({completionGpuAddress, completionValue}); return BufferObject::exec(used, startOffset, flags, requiresCoherency, osContext, vmHandleId, drmContextId, residency, residencyCount, execObjectsStorage, completionGpuAddress, completionValue); diff --git a/shared/test/unit_test/direct_submission/linux/drm_direct_submission_tests.cpp b/shared/test/unit_test/direct_submission/linux/drm_direct_submission_tests.cpp index 1b8077e65b..c26556beea 100644 --- a/shared/test/unit_test/direct_submission/linux/drm_direct_submission_tests.cpp +++ b/shared/test/unit_test/direct_submission/linux/drm_direct_submission_tests.cpp @@ -376,6 +376,29 @@ HWTEST_F(DrmDirectSubmissionTest, givenNoCompletionFenceSupportWhenSubmittingThe ringBuffer->getBufferObjectToModify(0) = initialBO; } +HWTEST_F(DrmDirectSubmissionTest, givenNoCompletionFenceSupportAndExecFailureWhenSubmittingThenGetDispatchErrorCode) { + uint64_t gpuAddress = 0x1000; + size_t size = 0x1000; + DebugManagerStateRestore restorer; + DebugManager.flags.EnableDrmCompletionFence.set(0); + + MockDrmDirectSubmission> drmDirectSubmission(*device->getDefaultEngine().commandStreamReceiver); + drmDirectSubmission.completionFenceAllocation = nullptr; + EXPECT_TRUE(drmDirectSubmission.allocateResources()); + auto ringBuffer = static_cast(drmDirectSubmission.ringBuffers[drmDirectSubmission.currentRingBuffer].ringBuffer); + auto initialBO = ringBuffer->getBufferObjectToModify(0); + + auto drm = executionEnvironment.rootDeviceEnvironments[0]->osInterface->getDriverModel()->as(); + MockBufferObject mockBO(drm); + ringBuffer->getBufferObjectToModify(0) = &mockBO; + + mockBO.execReturnValue = ENXIO; + EXPECT_FALSE(drmDirectSubmission.submit(gpuAddress, size)); + EXPECT_EQ((uint32_t)ENXIO, drmDirectSubmission.getDispatchErrorCode()); + + ringBuffer->getBufferObjectToModify(0) = initialBO; +} + HWTEST_F(DrmDirectSubmissionTest, givenTile0AndCompletionFenceSupportWhenSubmittingThenCompletionAddressAndValueArePassedToExec) { uint64_t gpuAddress = 0x1000; size_t size = 0x1000; diff --git a/shared/test/unit_test/os_interface/linux/drm_command_stream_tests_1.cpp b/shared/test/unit_test/os_interface/linux/drm_command_stream_tests_1.cpp index 9e0d124f97..96ef2b1dd2 100644 --- a/shared/test/unit_test/os_interface/linux/drm_command_stream_tests_1.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_command_stream_tests_1.cpp @@ -790,6 +790,10 @@ struct MockDrmDirectSubmissionDispatchCommandBuffer : public DrmDirectSubmission ADDMETHOD_NOBASE(dispatchCommandBuffer, bool, false, (BatchBuffer & batchBuffer, FlushStampTracker &flushStamp)); + + void setDispatchErrorCode(uint32_t errorCode) { + this->dispatchErrorCode = errorCode; + } }; template @@ -800,6 +804,10 @@ struct MockDrmBlitterDirectSubmissionDispatchCommandBuffer : public DrmDirectSub ADDMETHOD_NOBASE(dispatchCommandBuffer, bool, false, (BatchBuffer & batchBuffer, FlushStampTracker &flushStamp)); + + void setDispatchErrorCode(uint32_t errorCode) { + this->dispatchErrorCode = errorCode; + } }; HWTEST_TEMPLATED_F(DrmCommandStreamDirectSubmissionTest, givenDirectSubmissionFailsThenFlushReturnsError) { @@ -808,6 +816,7 @@ HWTEST_TEMPLATED_F(DrmCommandStreamDirectSubmissionTest, givenDirectSubmissionFa testedCsr->directSubmission = std::make_unique>(*device->getDefaultEngine().commandStreamReceiver); auto directSubmission = testedCsr->directSubmission.get(); static_cast *>(directSubmission)->dispatchCommandBufferResult = false; + static_cast *>(directSubmission)->setDispatchErrorCode(ENXIO); auto &cs = csr->getCS(); CommandStreamReceiverHw::addBatchBufferEnd(cs, nullptr); @@ -819,7 +828,7 @@ HWTEST_TEMPLATED_F(DrmCommandStreamDirectSubmissionTest, givenDirectSubmissionFa auto res = csr->flush(batchBuffer, csr->getResidencyAllocations()); EXPECT_GT(static_cast *>(directSubmission)->dispatchCommandBufferCalled, 0u); - EXPECT_EQ(NEO::SubmissionStatus::FAILED, res); + EXPECT_NE(NEO::SubmissionStatus::SUCCESS, res); } HWTEST_TEMPLATED_F(DrmCommandStreamBlitterDirectSubmissionTest, givenBlitterDirectSubmissionFailsThenFlushReturnsError) { @@ -828,6 +837,7 @@ HWTEST_TEMPLATED_F(DrmCommandStreamBlitterDirectSubmissionTest, givenBlitterDire testedCsr->blitterDirectSubmission = std::make_unique>(*csr); auto blitterDirectSubmission = testedCsr->blitterDirectSubmission.get(); static_cast *>(blitterDirectSubmission)->dispatchCommandBufferResult = false; + static_cast *>(blitterDirectSubmission)->setDispatchErrorCode(ENXIO); auto &cs = csr->getCS(); CommandStreamReceiverHw::addBatchBufferEnd(cs, nullptr); @@ -839,7 +849,7 @@ HWTEST_TEMPLATED_F(DrmCommandStreamBlitterDirectSubmissionTest, givenBlitterDire auto res = csr->flush(batchBuffer, csr->getResidencyAllocations()); EXPECT_GT(static_cast *>(blitterDirectSubmission)->dispatchCommandBufferCalled, 0u); - EXPECT_EQ(NEO::SubmissionStatus::FAILED, res); + EXPECT_NE(NEO::SubmissionStatus::SUCCESS, res); } template