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(®isterImmParams, 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 ®isterImmParams));
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 ®isterImmParams));
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(®isterImmParams, sizeof(registerImmParams));
410 registerImmParams.dwData = MHW_MI_WATCHDOG_DISABLE_COUNTER;
411 registerImmParams.dwRegister = MediaResetParam.watchdogCountCtrlOffset;
412 MHW_MI_CHK_STATUS(AddMiLoadRegisterImmCmd(
413 cmdBuffer,
414 ®isterImmParams));
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