diff --git a/runtime/os_interface/linux/drm_buffer_object.cpp b/runtime/os_interface/linux/drm_buffer_object.cpp index f23fa3d8d0..bdebb26332 100644 --- a/runtime/os_interface/linux/drm_buffer_object.cpp +++ b/runtime/os_interface/linux/drm_buffer_object.cpp @@ -132,7 +132,7 @@ bool BufferObject::setTiling(uint32_t mode, uint32_t stride) { void BufferObject::fillExecObject(drm_i915_gem_exec_object2 &execObject) { execObject.handle = this->handle; - execObject.relocation_count = 0; //No relocations, we are SoftPinning + execObject.relocation_count = 0; //No relocations, we are SoftPinning execObject.relocs_ptr = 0ul; execObject.alignment = 0; execObject.offset = this->isSoftpin ? this->offset64 : 0; @@ -167,7 +167,9 @@ int BufferObject::exec(uint32_t used, size_t startOffset, unsigned int flags, bo execbuf.flags = flags; if (drm->peekCoherencyDisablePatchActive() && !requiresCoherency) { - execbuf.flags = execbuf.flags | I915_PRIVATE_EXEC_FORCE_NON_COHERENT; + execbuf.flags |= (uint64_t)I915_PRIVATE_EXEC_FORCE_NON_COHERENT; + } else if (drm->peekDataPortCoherencyPatchActive() && requiresCoherency) { + execbuf.flags |= (uint64_t)I915_EXEC_DATA_PORT_COHERENT; } if (lowPriority) { execbuf.rsvd1 = this->drm->lowPriorityContextId & I915_EXEC_CONTEXT_ID_MASK; diff --git a/runtime/os_interface/linux/drm_neo.cpp b/runtime/os_interface/linux/drm_neo.cpp index f8da25153b..4398ab5015 100644 --- a/runtime/os_interface/linux/drm_neo.cpp +++ b/runtime/os_interface/linux/drm_neo.cpp @@ -124,6 +124,12 @@ void Drm::obtainCoherencyDisablePatchActive() { coherencyDisablePatchActive = (ret == 0) && (value != 0); } +void Drm::obtainDataPortCoherencyPatchActive() { + int value = 0; + auto ret = getParamIoctl(I915_PARAM_HAS_EXEC_DATA_PORT_COHERENCY, &value); + dataPortCoherencyPatchActive = (ret == 0) && (value != 0); +} + std::string Drm::getSysFsPciPath(int deviceID) { std::string nullPath; std::string sysFsPciDirectory = Os::sysFsPciPath; diff --git a/runtime/os_interface/linux/drm_neo.h b/runtime/os_interface/linux/drm_neo.h index 5e175c64ca..8b3ec856f6 100644 --- a/runtime/os_interface/linux/drm_neo.h +++ b/runtime/os_interface/linux/drm_neo.h @@ -39,6 +39,9 @@ namespace OCLRT { #define I915_CONTEXT_PRIVATE_PARAM_BOOST 0x80000000 +#define I915_EXEC_DATA_PORT_COHERENT (1 << 20) +#define I915_PARAM_HAS_EXEC_DATA_PORT_COHERENCY 52 + class DeviceFactory; struct HardwareInfo; @@ -74,8 +77,10 @@ class Drm { bool is48BitAddressRangeSupported(); MOCKABLE_VIRTUAL bool hasPreemption(); bool setLowPriority(); - bool peekCoherencyDisablePatchActive() { return coherencyDisablePatchActive; } + bool peekCoherencyDisablePatchActive() const { return coherencyDisablePatchActive; } + bool peekDataPortCoherencyPatchActive() const { return dataPortCoherencyPatchActive; } virtual void obtainCoherencyDisablePatchActive(); + MOCKABLE_VIRTUAL void obtainDataPortCoherencyPatchActive(); int getFileDescriptor() const { return fd; } bool contextCreate(); void contextDestroy(); @@ -90,6 +95,7 @@ class Drm { int revisionId; GTTYPE eGtType; bool coherencyDisablePatchActive = false; + bool dataPortCoherencyPatchActive = false; Drm(int fd) : lowPriorityContextId(0), fd(fd), deviceId(0), revisionId(0), eGtType(GTTYPE_UNDEFINED) {} virtual ~Drm(); diff --git a/runtime/os_interface/linux/hw_info_config.cpp b/runtime/os_interface/linux/hw_info_config.cpp index e9e8373de1..9b90fbb73c 100644 --- a/runtime/os_interface/linux/hw_info_config.cpp +++ b/runtime/os_interface/linux/hw_info_config.cpp @@ -131,6 +131,7 @@ int HwInfoConfig::configureHwInfo(const HardwareInfo *inHwInfo, HardwareInfo *ou pSysInfo->SubSliceCount = static_cast(subSliceCount); drm->obtainCoherencyDisablePatchActive(); + drm->obtainDataPortCoherencyPatchActive(); pSkuTable->ftrSVM = drm->is48BitAddressRangeSupported(); int maxGpuFreq = 0; diff --git a/unit_tests/os_interface/linux/device_command_stream_fixture.h b/unit_tests/os_interface/linux/device_command_stream_fixture.h index 73fcca3786..133887b80e 100644 --- a/unit_tests/os_interface/linux/device_command_stream_fixture.h +++ b/unit_tests/os_interface/linux/device_command_stream_fixture.h @@ -81,6 +81,7 @@ class DrmMockCustom : public Drm { IoctlResExt(int32_t no, int32_t res) : no(no), res(res) {} }; void overideCoherencyPatchActive(bool newCoherencyPatchActiveValue) { coherencyDisablePatchActive = newCoherencyPatchActiveValue; } + void overideDataPortCoherencyPatchActive(bool newValue) { dataPortCoherencyPatchActive = newValue; } class Ioctls { public: diff --git a/unit_tests/os_interface/linux/drm_buffer_object_tests.cpp b/unit_tests/os_interface/linux/drm_buffer_object_tests.cpp index 48d3f876a9..b8d989a650 100644 --- a/unit_tests/os_interface/linux/drm_buffer_object_tests.cpp +++ b/unit_tests/os_interface/linux/drm_buffer_object_tests.cpp @@ -110,6 +110,36 @@ TEST_F(DrmBufferObjectTest, givenDrmWithCoherencyPatchActiveWhenExecIsCalledWith EXPECT_EQ(expectedFlag, currentFlag); } +TEST_F(DrmBufferObjectTest, givenDrmWithDataPortCoherencyPatchActiveWhenExecWithCoherencyRequestCalledThenSetExecFlag) { + mock->ioctl_expected.total = 1; + mock->ioctl_res = 0; + mock->overideDataPortCoherencyPatchActive(true); + + auto ret = bo->exec(0, 0, 0, true); + EXPECT_EQ(mock->ioctl_res, ret); + EXPECT_NE(0u, mock->execBuffer.flags & I915_EXEC_DATA_PORT_COHERENT); +} + +TEST_F(DrmBufferObjectTest, givenDrmWithoutDataPortCoherencyPatchActiveWhenExecWithCoherencyRequestCalledThenDontSetExecFlag) { + mock->ioctl_expected.total = 1; + mock->ioctl_res = 0; + mock->overideDataPortCoherencyPatchActive(false); + + auto ret = bo->exec(0, 0, 0, true); + EXPECT_EQ(mock->ioctl_res, ret); + EXPECT_EQ(0u, mock->execBuffer.flags & I915_EXEC_DATA_PORT_COHERENT); +} + +TEST_F(DrmBufferObjectTest, givenDrmWithDataPortCoherencyPatchActiveWhenExecWithoutCoherencyRequestCalledThenDontSetExecFlag) { + mock->ioctl_expected.total = 1; + mock->ioctl_res = 0; + mock->overideDataPortCoherencyPatchActive(true); + + auto ret = bo->exec(0, 0, 0, false); + EXPECT_EQ(mock->ioctl_res, ret); + EXPECT_EQ(0u, mock->execBuffer.flags & I915_EXEC_DATA_PORT_COHERENT); +} + TEST_F(DrmBufferObjectTest, exec_ioctlFailed) { mock->ioctl_expected.total = 1; mock->ioctl_res = -1; diff --git a/unit_tests/os_interface/linux/drm_tests.cpp b/unit_tests/os_interface/linux/drm_tests.cpp index e23e36184f..04159f2bcb 100644 --- a/unit_tests/os_interface/linux/drm_tests.cpp +++ b/unit_tests/os_interface/linux/drm_tests.cpp @@ -26,6 +26,7 @@ #include "unit_tests/os_interface/linux/drm_mock.h" #include "unit_tests/fixtures/memory_management_fixture.h" #include "gtest/gtest.h" +#include "gmock/gmock.h" #include "runtime/os_interface/os_interface.h" #include @@ -180,6 +181,50 @@ TEST(DrmTest, GivenMockDrmWhenAskedFor48BitAddressCorrectValueReturned) { delete pDrm; } +ACTION_P2(saveGetParamData, saveParamPtr, forceReturnValuePtr) { + auto getParamArg = static_cast(arg1); + *saveParamPtr = getParamArg->param; + *getParamArg->value = forceReturnValuePtr; +} +struct DrmDataPortCoherencyTests : public ::testing::Test { + struct MyMockDrm : public Drm2 { + MyMockDrm() : Drm2(){}; + MOCK_METHOD2(ioctl, int(unsigned long request, void *arg)); + } drm; + + void setupExpectCall(int expectedRetVal, int expectedGetParamValue) { + using namespace ::testing; + auto saveAndReturnAction = DoAll(saveGetParamData(&receivedGetParamType, expectedGetParamValue), + Return(expectedRetVal)); + EXPECT_CALL(drm, ioctl(DRM_IOCTL_I915_GETPARAM, _)).Times(1).WillOnce(saveAndReturnAction); + } + int receivedGetParamType = 0; +}; + +TEST_F(DrmDataPortCoherencyTests, givenDisabledPatchWhenAskedToObtainDataPortCoherencyPatchThenReturnFlase) { + setupExpectCall(1, 0); // return error == 1, dont care about assigned feature value + drm.obtainDataPortCoherencyPatchActive(); + + EXPECT_EQ(receivedGetParamType, I915_PARAM_HAS_EXEC_DATA_PORT_COHERENCY); + EXPECT_FALSE(drm.peekDataPortCoherencyPatchActive()); +} + +TEST_F(DrmDataPortCoherencyTests, givenEnabledPatchAndDisabledFeatureWhenAskedToObtainDataPortCoherencyPatchThenReturnFlase) { + setupExpectCall(0, 0); // return success(0), set disabled feature (0) + drm.obtainDataPortCoherencyPatchActive(); + + EXPECT_EQ(receivedGetParamType, I915_PARAM_HAS_EXEC_DATA_PORT_COHERENCY); + EXPECT_FALSE(drm.peekDataPortCoherencyPatchActive()); +} + +TEST_F(DrmDataPortCoherencyTests, givenEnabledPatchAndEnabledFeatureWhenAskedToObtainDataPortCoherencyPatchThenReturnTrue) { + setupExpectCall(0, 1); // return success(0), set enabled feature (1) + drm.obtainDataPortCoherencyPatchActive(); + + EXPECT_EQ(receivedGetParamType, I915_PARAM_HAS_EXEC_DATA_PORT_COHERENCY); + EXPECT_TRUE(drm.peekDataPortCoherencyPatchActive()); +} + #if defined(I915_PARAM_HAS_PREEMPTION) TEST(DrmTest, GivenMockDrmWhenAskedForPreemptionCorrectValueReturned) { Drm2 *pDrm = new Drm2; diff --git a/unit_tests/os_interface/linux/hw_info_config_tests.cpp b/unit_tests/os_interface/linux/hw_info_config_tests.cpp index 83e81c1068..67a6ecfcfe 100644 --- a/unit_tests/os_interface/linux/hw_info_config_tests.cpp +++ b/unit_tests/os_interface/linux/hw_info_config_tests.cpp @@ -358,4 +358,14 @@ TEST_F(HwInfoConfigTestLinuxDummy, givenPointerToHwInfoWhenConfigureHwInfoCalled int ret = hwConfig.configureHwInfo(pInHwInfo, &outHwInfo, osInterface); EXPECT_EQ(0, ret); EXPECT_EQ(outHwInfo.pSysInfo->CsrSizeInMb * MemoryConstants::megaByte, outHwInfo.capabilityTable.requiredPreemptionSurfaceSize); -} \ No newline at end of file +} + +TEST_F(HwInfoConfigTestLinuxDummy, whenAskedToConfigureHwInfoThenObtainDataPortCoherencyPatchStatus) { + struct MyDrm : public Drm2 { + void obtainDataPortCoherencyPatchActive() override { obtainDataPortCoherencyPatchActiveCalled = true; } + bool obtainDataPortCoherencyPatchActiveCalled = false; + } myDrm; + osInterface->get()->setDrm(&myDrm); + hwConfig.configureHwInfo(pInHwInfo, &outHwInfo, osInterface); + EXPECT_TRUE(myDrm.obtainDataPortCoherencyPatchActiveCalled); +}