1 /*
2 * Copyright (c) 2016-2018, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     mhw_mi_g11_X.cpp
24 //! \brief    Constructs MI commands on Gen11-based platforms
25 //! \details  Each client facing function both creates a HW command and adds
26 //!           that command to a command or batch buffer.
27 //!
28 
29 #include "mhw_mi_g11_X.h"
30 #include "mhw_mi_hwcmd_g11_X.h"
31 #include "mhw_mmio_g11.h"
32 
AddMiSemaphoreWaitCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_MI_SEMAPHORE_WAIT_PARAMS params)33 MOS_STATUS MhwMiInterfaceG11::AddMiSemaphoreWaitCmd(
34     PMOS_COMMAND_BUFFER             cmdBuffer,
35     PMHW_MI_SEMAPHORE_WAIT_PARAMS   params)
36 {
37     MHW_FUNCTION_ENTER;
38 
39     MHW_MI_CHK_NULL(cmdBuffer);
40     MHW_MI_CHK_NULL(cmdBuffer->pCmdPtr);
41     MHW_MI_CHK_NULL(params);
42 
43     mhw_mi_g11_X::MI_SEMAPHORE_WAIT_CMD *cmd =
44         (mhw_mi_g11_X::MI_SEMAPHORE_WAIT_CMD*)cmdBuffer->pCmdPtr;
45 
46     MHW_MI_CHK_STATUS(MhwMiInterfaceGeneric<mhw_mi_g11_X>::AddMiSemaphoreWaitCmd(cmdBuffer, params));
47 
48     cmd->DW0.RegisterPollMode = params->bRegisterPollMode;
49 
50     return MOS_STATUS_SUCCESS;
51 }
52 
AddMiBatchBufferStartCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_BATCH_BUFFER batchBuffer)53 MOS_STATUS MhwMiInterfaceG11::AddMiBatchBufferStartCmd(
54     PMOS_COMMAND_BUFFER                 cmdBuffer,
55     PMHW_BATCH_BUFFER                   batchBuffer)
56 {
57     MHW_FUNCTION_ENTER;
58 
59     MHW_MI_CHK_NULL(cmdBuffer);
60     MHW_MI_CHK_NULL(batchBuffer);
61 
62     bool vcsEngineUsed =
63         MOS_VCS_ENGINE_USED(m_osInterface->pfnGetGpuContext(m_osInterface));
64 
65     mhw_mi_g11_X::MI_BATCH_BUFFER_START_CMD cmd;
66     MHW_RESOURCE_PARAMS                     resourceParams;
67     MOS_ZeroMemory(&resourceParams, sizeof(resourceParams));
68     resourceParams.presResource     = &batchBuffer->OsResource;
69     resourceParams.dwOffset         = batchBuffer->dwOffset;
70     resourceParams.pdwCmd           = cmd.DW1_2.Value;
71     resourceParams.dwLocationInCmd  = 1;
72     resourceParams.dwLsbNum         = MHW_COMMON_MI_GENERAL_SHIFT;
73     resourceParams.HwCommandType    = vcsEngineUsed ?
74         MOS_MI_BATCH_BUFFER_START : MOS_MI_BATCH_BUFFER_START_RCS;
75 
76     MHW_MI_CHK_STATUS(AddResourceToCmd(
77         m_osInterface,
78         cmdBuffer,
79         &resourceParams));
80 
81     // Set BB start
82     cmd.DW0.SecondLevelBatchBuffer = true;
83     cmd.DW0.AddressSpaceIndicator = !IsGlobalGttInUse();
84 
85     // Send BB start command
86     MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, cmd.byteSize));
87 
88     return MOS_STATUS_SUCCESS;
89 }
90 
AddMiConditionalBatchBufferEndCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_MI_CONDITIONAL_BATCH_BUFFER_END_PARAMS params)91 MOS_STATUS MhwMiInterfaceG11::AddMiConditionalBatchBufferEndCmd(
92     PMOS_COMMAND_BUFFER                             cmdBuffer,
93     PMHW_MI_CONDITIONAL_BATCH_BUFFER_END_PARAMS     params)
94 {
95     MHW_FUNCTION_ENTER;
96 
97     MHW_MI_CHK_NULL(cmdBuffer);
98     MHW_MI_CHK_NULL(params);
99     MHW_MI_CHK_NULL(params->presSemaphoreBuffer);
100 
101     // Case 1 - Batch buffer condition matches - If this is not present then conditional
102     //          batch buffer will  exit to ring with terminating CP.
103     // Case 2 - Batch buffer condition DOES NOT match - Although this will disable CP
104     //          but after end of conditional batch buffer CP will be re-enabled.
105     MHW_MI_CHK_STATUS(m_cpInterface->AddEpilog(m_osInterface, cmdBuffer));
106 
107     mhw_mi_g11_X::MI_CONDITIONAL_BATCH_BUFFER_END_CMD cmd;
108     cmd.DW0.UseGlobalGtt        = IsGlobalGttInUse();
109     cmd.DW0.CompareSemaphore    = 1; // CompareDataDword is always assumed to be set
110     cmd.DW0.CompareMaskMode     = !params->bDisableCompareMask;
111     cmd.DW1.CompareDataDword    = params->dwValue;
112 
113     MHW_RESOURCE_PARAMS resourceParams;
114     MOS_ZeroMemory(&resourceParams, sizeof(resourceParams));
115     resourceParams.presResource     = params->presSemaphoreBuffer;
116     resourceParams.dwOffset         = params->dwOffset;
117     resourceParams.pdwCmd           = cmd.DW2_3.Value;
118     resourceParams.dwLocationInCmd  = 2;
119     resourceParams.dwLsbNum         = MHW_COMMON_MI_CONDITIONAL_BATCH_BUFFER_END_SHIFT;
120     resourceParams.HwCommandType    = MOS_MI_CONDITIONAL_BATCH_BUFFER_END;
121 
122     MHW_MI_CHK_STATUS(AddResourceToCmd(
123         m_osInterface,
124         cmdBuffer,
125         &resourceParams));
126 
127     // Send Conditional Batch Buffer End command
128     MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, cmd.byteSize));
129 
130     //Re-enable CP for Case 2
131     MHW_MI_CHK_STATUS(m_cpInterface->AddProlog(m_osInterface, cmdBuffer));
132 
133     return MOS_STATUS_SUCCESS;
134 }
135 
AddMiStoreRegisterMemCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_MI_STORE_REGISTER_MEM_PARAMS params)136 MOS_STATUS MhwMiInterfaceG11::AddMiStoreRegisterMemCmd(
137     PMOS_COMMAND_BUFFER                 cmdBuffer,
138     PMHW_MI_STORE_REGISTER_MEM_PARAMS   params)
139 {
140     MHW_FUNCTION_ENTER;
141 
142     MHW_MI_CHK_NULL(cmdBuffer);
143     MHW_MI_CHK_NULL(cmdBuffer->pCmdPtr);
144     MHW_MI_CHK_NULL(params);
145 
146     mhw_mi_g11_X::MI_STORE_REGISTER_MEM_CMD *cmd =
147         (mhw_mi_g11_X::MI_STORE_REGISTER_MEM_CMD*)cmdBuffer->pCmdPtr;
148 
149     MHW_MI_CHK_STATUS(MhwMiInterfaceGeneric<mhw_mi_g11_X>::AddMiStoreRegisterMemCmd(cmdBuffer, params));
150 
151     if (IsRelativeMMIO(params->dwRegister))
152     {
153         cmd->DW0.AddCsMmioStartOffset = 1;
154         cmd->DW1.RegisterAddress = params->dwRegister >> 2;
155     }
156 
157     return MOS_STATUS_SUCCESS;
158 }
159 
AddMiLoadRegisterMemCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_MI_LOAD_REGISTER_MEM_PARAMS params)160 MOS_STATUS MhwMiInterfaceG11::AddMiLoadRegisterMemCmd(
161     PMOS_COMMAND_BUFFER                 cmdBuffer,
162     PMHW_MI_LOAD_REGISTER_MEM_PARAMS    params)
163 {
164     MHW_FUNCTION_ENTER;
165 
166     MHW_MI_CHK_NULL(cmdBuffer);
167     MHW_MI_CHK_NULL(cmdBuffer->pCmdPtr);
168     MHW_MI_CHK_NULL(params);
169 
170     mhw_mi_g11_X::MI_LOAD_REGISTER_MEM_CMD *cmd =
171         (mhw_mi_g11_X::MI_LOAD_REGISTER_MEM_CMD*)cmdBuffer->pCmdPtr;
172 
173     MHW_MI_CHK_STATUS(MhwMiInterfaceGeneric<mhw_mi_g11_X>::AddMiLoadRegisterMemCmd(cmdBuffer, params));
174 
175     if (IsRelativeMMIO(params->dwRegister))
176     {
177         cmd->DW0.AddCsMmioStartOffset = 1;
178         cmd->DW1.RegisterAddress = params->dwRegister >> 2;
179     }
180 
181     return MOS_STATUS_SUCCESS;
182 }
183 
AddMiLoadRegisterImmCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_MI_LOAD_REGISTER_IMM_PARAMS params)184 MOS_STATUS MhwMiInterfaceG11::AddMiLoadRegisterImmCmd(
185     PMOS_COMMAND_BUFFER                 cmdBuffer,
186     PMHW_MI_LOAD_REGISTER_IMM_PARAMS    params)
187 {
188     MHW_FUNCTION_ENTER;
189 
190     MHW_MI_CHK_NULL(cmdBuffer);
191     MHW_MI_CHK_NULL(cmdBuffer->pCmdPtr);
192     MHW_MI_CHK_NULL(params);
193 
194     mhw_mi_g11_X::MI_LOAD_REGISTER_IMM_CMD *cmd =
195         (mhw_mi_g11_X::MI_LOAD_REGISTER_IMM_CMD*)cmdBuffer->pCmdPtr;
196 
197     MHW_MI_CHK_STATUS(MhwMiInterfaceGeneric<mhw_mi_g11_X>::AddMiLoadRegisterImmCmd(cmdBuffer, params));
198 
199     if (IsRelativeMMIO(params->dwRegister))
200     {
201         cmd->DW0.AddCsMmioStartOffset = 1;
202         cmd->DW1.RegisterOffset = params->dwRegister >> 2;
203     }
204 
205     return MOS_STATUS_SUCCESS;
206 }
207 
AddMiLoadRegisterRegCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_MI_LOAD_REGISTER_REG_PARAMS params)208 MOS_STATUS MhwMiInterfaceG11::AddMiLoadRegisterRegCmd(
209     PMOS_COMMAND_BUFFER                 cmdBuffer,
210     PMHW_MI_LOAD_REGISTER_REG_PARAMS    params)
211 {
212     MHW_FUNCTION_ENTER;
213 
214     MHW_MI_CHK_NULL(cmdBuffer);
215     MHW_MI_CHK_NULL(cmdBuffer->pCmdPtr);
216     MHW_MI_CHK_NULL(params);
217 
218     mhw_mi_g11_X::MI_LOAD_REGISTER_REG_CMD *cmd =
219         (mhw_mi_g11_X::MI_LOAD_REGISTER_REG_CMD*)cmdBuffer->pCmdPtr;
220 
221     MHW_MI_CHK_STATUS(MhwMiInterfaceGeneric<mhw_mi_g11_X>::AddMiLoadRegisterRegCmd(cmdBuffer, params));
222 
223     if (IsRelativeMMIO(params->dwSrcRegister))
224     {
225         cmd->DW0.AddCsMmioStartOffsetSource = 1;
226         cmd->DW1.SourceRegisterAddress = params->dwSrcRegister >> 2;
227     }
228     if (IsRelativeMMIO(params->dwDstRegister))
229     {
230         cmd->DW0.AddCsMmioStartOffsetDestination = 1;
231         cmd->DW2.DestinationRegisterAddress = params->dwDstRegister >> 2;
232     }
233 
234     return MOS_STATUS_SUCCESS;
235 }
236 
SetWatchdogTimerThreshold(uint32_t frameWidth,uint32_t frameHeight,bool isEncoder)237 MOS_STATUS MhwMiInterfaceG11::SetWatchdogTimerThreshold(uint32_t frameWidth, uint32_t frameHeight, bool isEncoder)
238 {
239     MHW_FUNCTION_ENTER;
240 
241     if (m_osInterface->bMediaReset == false ||
242         m_osInterface->umdMediaResetEnable == false)
243     {
244         return MOS_STATUS_SUCCESS;
245     }
246 
247     if (isEncoder)
248     {
249         if ((frameWidth * frameHeight) >= (7680 * 4320))
250         {
251             MediaResetParam.watchdogCountThreshold = MHW_MI_ENCODER_16K_WATCHDOG_THRESHOLD_IN_MS;
252         }
253         else if ((frameWidth * frameHeight) >= (3840 * 2160))
254         {
255             MediaResetParam.watchdogCountThreshold = MHW_MI_ENCODER_8K_WATCHDOG_THRESHOLD_IN_MS;
256         }
257         else if ((frameWidth * frameHeight) >= (1920 * 1080))
258         {
259             MediaResetParam.watchdogCountThreshold = MHW_MI_ENCODER_4K_WATCHDOG_THRESHOLD_IN_MS;
260         }
261         else
262         {
263             MediaResetParam.watchdogCountThreshold = MHW_MI_ENCODER_FHD_WATCHDOG_THRESHOLD_IN_MS;
264         }
265     }
266     else
267     {
268         if ((frameWidth * frameHeight) >= (7680 * 4320))
269         {
270             MediaResetParam.watchdogCountThreshold = MHW_MI_DECODER_16K_WATCHDOG_THRESHOLD_IN_MS;
271         }
272         else
273         {
274             // 60ms should be enough for decoder with resolution smaller than 8k
275             MediaResetParam.watchdogCountThreshold = MHW_MI_DEFAULT_WATCHDOG_THRESHOLD_IN_MS;
276         }
277     }
278 
279     MOS_USER_FEATURE_VALUE_DATA userFeatureData;
280     MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
281 #if (_DEBUG || _RELEASE_INTERNAL)
282     // User feature config of watchdog timer threshold
283     MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
284     MOS_UserFeature_ReadValue_ID(
285         nullptr,
286         __MEDIA_USER_FEATURE_VALUE_MEDIA_RESET_TH_ID,
287         &userFeatureData);
288     if (userFeatureData.u32Data != 0)
289     {
290         MediaResetParam.watchdogCountThreshold = userFeatureData.u32Data;
291     }
292 #endif
293 
294     return MOS_STATUS_SUCCESS;
295 }
296 
SetWatchdogTimerRegisterOffset(MOS_GPU_CONTEXT gpuContext)297 MOS_STATUS MhwMiInterfaceG11::SetWatchdogTimerRegisterOffset(
298     MOS_GPU_CONTEXT                 gpuContext)
299 {
300     MHW_FUNCTION_ENTER;
301 
302     switch (gpuContext)
303     {
304         // RCS
305     case MOS_GPU_CONTEXT_RENDER:
306     case MOS_GPU_CONTEXT_RENDER2:
307     case MOS_GPU_CONTEXT_RENDER3:
308     case MOS_GPU_CONTEXT_RENDER4:
309         MediaResetParam.watchdogCountCtrlOffset = WATCHDOG_COUNT_CTRL_OFFSET_RCS_G11;
310         MediaResetParam.watchdogCountThresholdOffset = WATCHDOG_COUNT_THRESTHOLD_OFFSET_RCS_G11;
311         break;
312         // VCS0
313     case MOS_GPU_CONTEXT_VIDEO:
314     case MOS_GPU_CONTEXT_VIDEO2:
315     case MOS_GPU_CONTEXT_VIDEO3:
316     case MOS_GPU_CONTEXT_VIDEO4:
317     case MOS_GPU_CONTEXT_VIDEO5:
318     case MOS_GPU_CONTEXT_VIDEO6:
319     case MOS_GPU_CONTEXT_VIDEO7:
320         MediaResetParam.watchdogCountCtrlOffset = WATCHDOG_COUNT_CTRL_OFFSET_VCS0_G11;
321         MediaResetParam.watchdogCountThresholdOffset = WATCHDOG_COUNT_THRESTHOLD_OFFSET_VCS0_G11;
322         break;
323         // VCS1
324     case MOS_GPU_CONTEXT_VDBOX2_VIDEO:
325     case MOS_GPU_CONTEXT_VDBOX2_VIDEO2:
326     case MOS_GPU_CONTEXT_VDBOX2_VIDEO3:
327         MediaResetParam.watchdogCountCtrlOffset = WATCHDOG_COUNT_CTRL_OFFSET_VCS1_G11;
328         MediaResetParam.watchdogCountThresholdOffset = WATCHDOG_COUNT_THRESTHOLD_OFFSET_VCS1_G11;
329         break;
330         // VECS
331     case MOS_GPU_CONTEXT_VEBOX:
332         MediaResetParam.watchdogCountCtrlOffset = WATCHDOG_COUNT_CTRL_OFFSET_VECS_G11;
333         MediaResetParam.watchdogCountThresholdOffset = WATCHDOG_COUNT_THRESTHOLD_OFFSET_VECS_G11;
334         break;
335         // Default
336     default:
337         break;
338     }
339 
340     return MOS_STATUS_SUCCESS;
341 }
342 
AddWatchdogTimerStartCmd(PMOS_COMMAND_BUFFER cmdBuffer)343 MOS_STATUS MhwMiInterfaceG11::AddWatchdogTimerStartCmd(
344     PMOS_COMMAND_BUFFER                 cmdBuffer)
345 {
346     MOS_GPU_CONTEXT     gpuContext;
347 
348     MHW_FUNCTION_ENTER;
349 
350     if (m_osInterface->bMediaReset == false ||
351         m_osInterface->umdMediaResetEnable == false)
352     {
353         return MOS_STATUS_SUCCESS;
354     }
355 
356     MHW_MI_CHK_NULL(cmdBuffer);
357 
358     // Set Watchdog Timer Register Offset
359     gpuContext = m_osInterface->pfnGetGpuContext(m_osInterface);
360     MHW_MI_CHK_STATUS(SetWatchdogTimerRegisterOffset(gpuContext));
361 
362     // Send Stop before Start is to help recover from incorrect wdt state if previous submission
363     // cause hang and not have a chance to execute the stop cmd in the end of batch buffer.
364     MHW_MI_CHK_STATUS(AddWatchdogTimerStopCmd(cmdBuffer));
365 
366     //Configure Watchdog timer Threshold
367     MHW_MI_LOAD_REGISTER_IMM_PARAMS registerImmParams;
368     MOS_ZeroMemory(&registerImmParams, sizeof(registerImmParams));
369     registerImmParams.dwData = MHW_MI_WATCHDOG_COUNTS_PER_MILLISECOND * MediaResetParam.watchdogCountThreshold *
370         (m_osInterface->bSimIsActive ? 2 : 1);
371     registerImmParams.dwRegister = MediaResetParam.watchdogCountThresholdOffset;
372     MHW_MI_CHK_STATUS(AddMiLoadRegisterImmCmd(
373         cmdBuffer,
374         &registerImmParams));
375 
376     MHW_VERBOSEMESSAGE("MediaReset Threshold is %d", MediaResetParam.watchdogCountThreshold * (m_osInterface->bSimIsActive ? 2 : 1));
377 
378     //Start Watchdog Timer
379     registerImmParams.dwData = MHW_MI_WATCHDOG_ENABLE_COUNTER;
380     registerImmParams.dwRegister = MediaResetParam.watchdogCountCtrlOffset;
381     MHW_MI_CHK_STATUS(AddMiLoadRegisterImmCmd(
382         cmdBuffer,
383         &registerImmParams));
384 
385     return MOS_STATUS_SUCCESS;
386 }
387 
AddWatchdogTimerStopCmd(PMOS_COMMAND_BUFFER cmdBuffer)388 MOS_STATUS MhwMiInterfaceG11::AddWatchdogTimerStopCmd(
389     PMOS_COMMAND_BUFFER                 cmdBuffer)
390 {
391     MOS_GPU_CONTEXT gpuContext;
392 
393     MHW_FUNCTION_ENTER;
394 
395     if (m_osInterface->bMediaReset == false ||
396         m_osInterface->umdMediaResetEnable == false)
397     {
398         return MOS_STATUS_SUCCESS;
399     }
400 
401     MHW_MI_CHK_NULL(cmdBuffer);
402 
403     // Set Watchdog Timer Register Offset
404     gpuContext = m_osInterface->pfnGetGpuContext(m_osInterface);
405     MHW_MI_CHK_STATUS(SetWatchdogTimerRegisterOffset(gpuContext));
406 
407     //Stop Watchdog Timer
408     MHW_MI_LOAD_REGISTER_IMM_PARAMS registerImmParams;
409     MOS_ZeroMemory(&registerImmParams, sizeof(registerImmParams));
410     registerImmParams.dwData = MHW_MI_WATCHDOG_DISABLE_COUNTER;
411     registerImmParams.dwRegister = MediaResetParam.watchdogCountCtrlOffset;
412     MHW_MI_CHK_STATUS(AddMiLoadRegisterImmCmd(
413         cmdBuffer,
414         &registerImmParams));
415 
416     return MOS_STATUS_SUCCESS;
417 }
418 
InitMmioRegisters()419 void MhwMiInterfaceG11::InitMmioRegisters()
420 {
421     MHW_MI_MMIOREGISTERS *mmioRegisters = &m_mmioRegisters;
422 
423     mmioRegisters->generalPurposeRegister0LoOffset            = GP_REGISTER0_LO_OFFSET_G11;
424     mmioRegisters->generalPurposeRegister0HiOffset            = GP_REGISTER0_HI_OFFSET_G11;
425     mmioRegisters->generalPurposeRegister4LoOffset            = GP_REGISTER4_LO_OFFSET_G11;
426     mmioRegisters->generalPurposeRegister4HiOffset            = GP_REGISTER4_HI_OFFSET_G11;
427     mmioRegisters->generalPurposeRegister11LoOffset           = GP_REGISTER11_LO_OFFSET_G11;
428     mmioRegisters->generalPurposeRegister11HiOffset           = GP_REGISTER11_HI_OFFSET_G11;
429     mmioRegisters->generalPurposeRegister12LoOffset           = GP_REGISTER12_LO_OFFSET_G11;
430     mmioRegisters->generalPurposeRegister12HiOffset           = GP_REGISTER12_HI_OFFSET_G11;
431 }
432