1 /*
2 * Copyright (c) 2021, 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 mos_oca_specific.cpp
24 //! \brief Linux specfic OCA class
25 //!
26
27 #include "mos_os.h"
28 #include "mos_os_specific.h"
29 #include "mos_oca_interface_specific.h"
30 #include "mos_util_debug.h"
31 #include "mos_utilities.h"
32 #include <algorithm>
33
34 //!
35 //! \def MOS_OCA_CHK_NULL_RETURN(_ptr)
36 //! Check if _ptr == nullptr. If so, assert, return an error and update LastErrorStatus.
37 //! Should only be used by interface functions in MosOcaInterface.
38 //!
39 #define MOS_OCA_CHK_NULL_RETURN(mosCtx, _ptr, func, line) \
40 { \
41 if ((_ptr) == nullptr) \
42 { \
43 MosOcaInterfaceSpecific::OnOcaError(mosCtx, MOS_STATUS_NULL_POINTER, func, line); \
44 return MOS_STATUS_NULL_POINTER; \
45 } \
46 }
47
48 //!
49 //! \def MOS_OCA_CHK_STATUS_RETURN(_stmt)
50 //! Check if MOS_STATUS_SUCCESS != _stmt. If so, assert, return an error and update LastErrorStatus.
51 //! Should only be used by interface functions in MosOcaInterface.
52 //!
53 #define MOS_OCA_CHK_STATUS_RETURN(mosCtx, _stmt, func, line) \
54 { \
55 MOS_STATUS stmtStatus = (MOS_STATUS)(_stmt); \
56 if (stmtStatus != MOS_STATUS_SUCCESS) \
57 { \
58 MosOcaInterfaceSpecific::OnOcaError(mosCtx, stmtStatus, func, line); \
59 return stmtStatus; \
60 } \
61 }
62
63 /****************************************************************************************************/
64 /* MosOcaInterfaceSpecific */
65 /****************************************************************************************************/
66
67
68 MOS_STATUS MosOcaInterfaceSpecific::s_ocaStatus = MOS_STATUS_SUCCESS;
69 uint32_t MosOcaInterfaceSpecific::s_lineNumForOcaErr = 0;
70 bool MosOcaInterfaceSpecific::s_bOcaStatusExistInReg = false;
71 int32_t MosOcaInterfaceSpecific::s_refCount = 0;
72 bool MosOcaInterfaceSpecific::s_isDestroyed = false;
73
74 //!
75 //! \brief Get the idle oca buffer, which is neither used by hw nor locked, and lock it for edit.
76 //! \param [in] pMosContext
77 //! pointer to MOS_INTERFACE
78 //! \param [in] CurrentGpuContextHandle
79 //! Gpu context handle
80 //! \return MOS_OCA_BUFFER_HANDLE
81 //! return the handle for oca buffer
82 //!
LockOcaBufAvailable(PMOS_CONTEXT pMosContext,uint32_t CurrentGpuContextHandle)83 MOS_OCA_BUFFER_HANDLE MosOcaInterfaceSpecific::LockOcaBufAvailable(PMOS_CONTEXT pMosContext, uint32_t CurrentGpuContextHandle)
84 {
85 if (nullptr == m_ocaMutex)
86 {
87 MosOcaInterfaceSpecific::OnOcaError(pMosContext, MOS_STATUS_NULL_POINTER, __FUNCTION__, __LINE__);
88 return MOS_OCA_INVALID_BUFFER_HANDLE;
89 }
90
91 MosOcaAutoLock autoLock(m_ocaMutex);
92 for (int i = m_indexOfNextOcaBufContext; i < MAX_NUM_OF_OCA_BUF_CONTEXT; ++i)
93 {
94 if (m_ocaBufContextList[i].inUse)
95 {
96 continue;
97 }
98 m_ocaBufContextList[i].inUse = true;
99 m_ocaBufContextList[i].logSection.resInfo.maxResInfoCount = m_config.maxResInfoCount;
100 m_indexOfNextOcaBufContext = (i + 1) % MAX_NUM_OF_OCA_BUF_CONTEXT;
101 return i;
102 }
103
104 for (int i = 0; i < m_indexOfNextOcaBufContext; ++i)
105 {
106 if (m_ocaBufContextList[i].inUse)
107 {
108 continue;
109 }
110 m_ocaBufContextList[i].inUse = true;
111 m_ocaBufContextList[i].logSection.resInfo.maxResInfoCount = m_config.maxResInfoCount;
112 m_indexOfNextOcaBufContext = (i + 1) % MAX_NUM_OF_OCA_BUF_CONTEXT;
113 return i;
114 }
115 MosOcaInterfaceSpecific::OnOcaError(pMosContext, MOS_STATUS_INVALID_PARAMETER, __FUNCTION__, __LINE__);
116 return MOS_OCA_INVALID_BUFFER_HANDLE;
117 }
118
119 //!
120 //! \brief Unlock the oca buffer when edit complete.
121 //! \param [in] ocaBufHandle
122 //! Oca buffer handle.
123 //! \return MOS_STATUS
124 //! Return MOS_STATUS_SUCCESS if successful, otherwise failed
125 //!
UnlockOcaBuf(MOS_OCA_BUFFER_HANDLE ocaBufHandle)126 MOS_STATUS MosOcaInterfaceSpecific::UnlockOcaBuf(MOS_OCA_BUFFER_HANDLE ocaBufHandle)
127 {
128 if (ocaBufHandle >= MAX_NUM_OF_OCA_BUF_CONTEXT)
129 {
130 return MOS_STATUS_INVALID_PARAMETER;
131 }
132 m_ocaBufContextList[ocaBufHandle].logSection.offset = 0;
133 m_ocaBufContextList[ocaBufHandle].logSection.base = nullptr;
134 m_ocaBufContextList[ocaBufHandle].inUse = false;
135 m_ocaBufContextList[ocaBufHandle].is1stLevelBBStarted = false;
136 return MOS_STATUS_SUCCESS;
137 }
138
UnlockOcaBufferWithDelay(MOS_OCA_BUFFER_HANDLE ocaBufHandle)139 MOS_STATUS MosOcaInterfaceSpecific::UnlockOcaBufferWithDelay(MOS_OCA_BUFFER_HANDLE ocaBufHandle)
140 {
141 if (ocaBufHandle >= MAX_NUM_OF_OCA_BUF_CONTEXT)
142 {
143 return MOS_STATUS_INVALID_PARAMETER;
144 }
145
146 MosOcaAutoLock lock(m_mutexForOcaBufPool);
147 m_PendingOcaBuffersToUnlock.push_back(ocaBufHandle);
148 return MOS_STATUS_SUCCESS;
149 }
150
UnlockPendingOcaBuffers(PMOS_CONTEXT mosCtx,struct MOS_OCA_EXEC_LIST_INFO * info,int count)151 void MosOcaInterfaceSpecific::UnlockPendingOcaBuffers(PMOS_CONTEXT mosCtx, struct MOS_OCA_EXEC_LIST_INFO *info, int count)
152 {
153 MosOcaAutoLock lock(m_mutexForOcaBufPool);
154 if(m_PendingOcaBuffersToUnlock.size() > 1)
155 {
156 MOS_OS_NORMALMESSAGE("size of pending oca buffer > 1");
157 }
158 for (auto it = m_PendingOcaBuffersToUnlock.begin();
159 it != m_PendingOcaBuffersToUnlock.end(); ++it)
160 {
161 // Other information to log section, which is only captured after BB end, can be added here.
162 if(mosCtx != nullptr && info != nullptr && count > 0)
163 {
164 AddExecListInfoToLogSection(*it, mosCtx, info, count);
165 }
166 UnlockOcaBuf(*it);
167 }
168 m_PendingOcaBuffersToUnlock.clear();
169 }
170
171 //!
172 //! \brief Oca operation which should be called at the beginning of 1st level batch buffer start.
173 //! \param [out] gpuVaOcaBuffer
174 //! The gfx virtual address of oca buffer, which should be set to GPR11 by LRI at the
175 //! beginning of 1st level batch buffer no matter return value is MOS_STATUS_SUCCESS or not.
176 //! \param [in] ocaBufHandle
177 //! Oca buffer handle.
178 //! \param [in] pMosContext
179 //! Pointer to MOS_CONTEXT.
180 //! \param [in] pMosResource
181 //! Pointer to the MOS_RESOURCE.
182 //! \param [in] offsetOf1stLevelBB
183 //! Offset for current BB in pMosResource.
184 //! \param [in] bUseSizeOfResource
185 //! If true, use size of pMosResource for batch buffer, else use sizeOf1stLevelBB.
186 //! \param [in] sizeOf1stLevelBB
187 //! Size of BB. Ignore if bUseSizeOfResource == true.
188 //! \return MOS_STATUS
189 //! Return MOS_STATUS_SUCCESS if successful, otherwise failed
190 //!
On1stLevelBBStart(uint64_t & gpuVaOcaBuffer,MOS_OCA_BUFFER_HANDLE ocaBufHandle,PMOS_CONTEXT pMosContext,void * pMosResource,uint32_t offsetOf1stLevelBB,bool bUseSizeOfResource,uint32_t sizeOf1stLevelBB)191 MOS_STATUS MosOcaInterfaceSpecific::On1stLevelBBStart(uint64_t &gpuVaOcaBuffer, MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT pMosContext, void *pMosResource, uint32_t offsetOf1stLevelBB, bool bUseSizeOfResource, uint32_t sizeOf1stLevelBB)
192 {
193 // The GPR11 need to be reset to 0 to disable UMD_OCA for current workload if any error happened.
194 gpuVaOcaBuffer = 0;
195 if (!m_isOcaEnabled)
196 {
197 return MOS_STATUS_SUCCESS;
198 }
199
200 PMOS_RESOURCE pOsResource = (PMOS_RESOURCE)pMosResource;
201 if (ocaBufHandle >= MAX_NUM_OF_OCA_BUF_CONTEXT)
202 {
203 MosOcaInterfaceSpecific::OnOcaError(pMosContext, MOS_STATUS_INVALID_PARAMETER, __FUNCTION__, __LINE__);
204 return MOS_STATUS_INVALID_PARAMETER;
205 }
206
207 m_ocaBufContextList[ocaBufHandle].is1stLevelBBStarted = true;
208 InitLogSection(ocaBufHandle, pOsResource);
209 return MOS_STATUS_SUCCESS;
210 }
211
212 //!
213 //! \brief Oca operation which should be called before adding batch buffer end command for 1st
214 //! level batch buffer.
215 //! \param [in] ocaBufHandle
216 //! Oca buffer handle.
217 //! \param [in] mosCtx
218 //! DDI device context.
219 //! \return MOS_STATUS
220 //! Return MOS_STATUS_SUCCESS if successful, otherwise failed
221 //!
On1stLevelBBEnd(MOS_OCA_BUFFER_HANDLE ocaBufHandle,PMOS_CONTEXT mosCtx)222 MOS_STATUS MosOcaInterfaceSpecific::On1stLevelBBEnd(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT mosCtx)
223 {
224 if (!m_isOcaEnabled)
225 {
226 return MOS_STATUS_SUCCESS;
227 }
228 if (ocaBufHandle >= MAX_NUM_OF_OCA_BUF_CONTEXT)
229 {
230 MosOcaInterfaceSpecific::OnOcaError(mosCtx, MOS_STATUS_INVALID_PARAMETER, __FUNCTION__, __LINE__);
231 return MOS_STATUS_INVALID_PARAMETER;
232 }
233
234 if (!m_ocaBufContextList[ocaBufHandle].is1stLevelBBStarted)
235 {
236 MOS_OS_ASSERTMESSAGE("On1stLevelBBEnd is called without On1stLevelBBStart being called!");
237 return MOS_STATUS_INVALID_PARAMETER;
238 }
239
240 AddResourceInfoToLogSection(ocaBufHandle, mosCtx);
241
242 return MOS_STATUS_SUCCESS;
243 }
244
245 //!
246 //! \brief Oca operation which should be called before sending start sub level batch buffer command.
247 //! \param [in] ocaBufHandle
248 //! Oca buffer handle.
249 //! \param [in] pMosContext
250 //! Pointer to MOS_CONTEXT.
251 //! \param [in] pMosResource
252 //! Pointer to the MOS_RESOURCE.
253 //! \param [in] offsetOfSubLevelBB
254 //! Offset for current BB in pMosResource.
255 //! \param [in] bUseSizeOfResource
256 //! If true, use size of pMosResource for batch buffer, else use sizeOfSubLevelBB.
257 //! \param [in] sizeOfSubLevelBB
258 //! Size of BB. Ignore if bUseSizeOfResource == true.
259 //! \return MOS_STATUS
260 //! Return MOS_STATUS_SUCCESS if successful, otherwise failed
261 //!
OnSubLevelBBStart(MOS_OCA_BUFFER_HANDLE ocaBufHandle,PMOS_CONTEXT pMosContext,void * pMosResource,uint32_t offsetOfSubLevelBB,bool bUseSizeOfResource,uint32_t sizeOfSubLevelBB)262 MOS_STATUS MosOcaInterfaceSpecific::OnSubLevelBBStart(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT pMosContext, void *pMosResource, uint32_t offsetOfSubLevelBB, bool bUseSizeOfResource, uint32_t sizeOfSubLevelBB)
263 {
264 return MOS_STATUS_UNIMPLEMENTED;
265 }
266
267 //!
268 //! \brief Oca operation which should be called when indirect states being added.
269 //! \param [in] ocaBufHandle
270 //! Oca buffer handle.
271 //! \param [in] pMosContext
272 //! Pointer to MOS_CONTEXT.
273 //! \param [in] pMosResource
274 //! Pointer to the MOS_RESOURCE.
275 //! \param [in] offsetOfIndirectState
276 //! Offset for current state in pMosResource.
277 //! \param [in] bUseSizeOfResource
278 //! If true, use size of pMosResource for indirect state, else use sizeOfIndirectState.
279 //! \param [in] sizeOfIndirectState
280 //! Size of indirect state. Ignore if bUseSizeOfResource == true.
281 //! \return MOS_STATUS
282 //! Return MOS_STATUS_SUCCESS if successful, otherwise failed
283 //!
OnIndirectState(MOS_OCA_BUFFER_HANDLE ocaBufHandle,PMOS_CONTEXT pMosContext,void * pMosResource,uint32_t offsetOfIndirectState,bool bUseSizeOfResource,uint32_t sizeOfIndirectState)284 MOS_STATUS MosOcaInterfaceSpecific::OnIndirectState(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT pMosContext, void *pMosResource, uint32_t offsetOfIndirectState, bool bUseSizeOfResource, uint32_t sizeOfIndirectState)
285 {
286 return MOS_STATUS_UNIMPLEMENTED;
287 }
288
289 //!
290 //! \brief Oca operation which should be called before adding dispatch states,
291 //! e.g. VEB_DI_IECP_STATE and MEDIA_OBJECT_WALKER.
292 //! \param [out] offsetInIndirectStateHeap
293 //! The start offset of current dispatch in indirect state heap, which should be set to low 32 bits
294 //! of GPR12 by LRI before dispatch commands being added.
295 //! OCA_HEAP_INVALID_OFFSET means no need to configure GPR12, otherwise the register need be configured
296 //! no matter return value being MOS_STATUS_SUCCESS or not.
297 //! \param [in] ocaBufHandle
298 //! Oca buffer handle.
299 //! \param [in] mosCtx
300 //! DDI device context.
301 //! \return MOS_STATUS
302 //! Return MOS_STATUS_SUCCESS if successful, otherwise failed
303 //!
OnDispatch(uint32_t & offsetInIndirectStateHeap,MOS_OCA_BUFFER_HANDLE ocaBufHandle,PMOS_CONTEXT mosCtx)304 MOS_STATUS MosOcaInterfaceSpecific::OnDispatch(uint32_t &offsetInIndirectStateHeap, MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT mosCtx)
305 {
306 return MOS_STATUS_UNIMPLEMENTED;
307 }
308
309 //!
310 //! \brief Add string to oca log section
311 //! \param [in] ocaBufHandle
312 //! Oca buffer handle.
313 //! \param [in] mosCtx
314 //! DDI device context.
315 //! \param [in] str
316 //! string to be added.
317 //! \param [in] maxCount
318 //! size of the buffer pointed by str.
319 //! \return MOS_STATUS
320 //! Return MOS_STATUS_SUCCESS if successful, otherwise failed
321 //!
TraceMessage(MOS_OCA_BUFFER_HANDLE ocaBufHandle,PMOS_CONTEXT mosCtx,const char * str,uint32_t maxCount)322 MOS_STATUS MosOcaInterfaceSpecific::TraceMessage(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT mosCtx, const char *str, uint32_t maxCount)
323 {
324 if (!m_isOcaEnabled)
325 {
326 return MOS_STATUS_SUCCESS;
327 }
328 if (nullptr == str || maxCount <= 0 || maxCount > MOS_OCA_MAX_STRING_LEN)
329 {
330 return MOS_STATUS_INVALID_PARAMETER;
331 }
332 if (!IsLogSectionEnabled(ocaBufHandle))
333 {
334 return MOS_STATUS_SUCCESS;
335 }
336
337 uint32_t len = strnlen(str, maxCount);
338 MOS_OCA_LOG_HEADER header = {MOS_OCA_LOG_TYPE_STRING, sizeof(MOS_OCA_LOG_HEADER), len};
339
340 return DumpDataBlock(ocaBufHandle, &header, (void *)str);
341 }
342
343 //!
344 //! \brief Add resource to dump list.
345 //! \param [in] ocaBufHandle
346 //! Oca buffer handle.
347 //! \param [in] mosCtx
348 //! DDI device context.
349 //! \param [in] resource
350 //! Reference to MOS_RESOURCE.
351 //! \param [in] hwCmdType
352 //! Hw command Type.
353 //! \param [in] locationInCmd
354 //! Location in command.
355 //! \param [in] offsetInRes
356 //! Offset in resource.
357 //! \return MOS_STATUS
358 //! Return MOS_STATUS_SUCCESS if successful, otherwise failed
359 //!
AddResourceToDumpList(MOS_OCA_BUFFER_HANDLE ocaBufHandle,PMOS_CONTEXT mosCtx,MOS_RESOURCE & resource,MOS_HW_COMMAND hwCmdType,uint32_t locationInCmd,uint32_t offsetInRes)360 MOS_STATUS MosOcaInterfaceSpecific::AddResourceToDumpList(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT mosCtx, MOS_RESOURCE &resource, MOS_HW_COMMAND hwCmdType, uint32_t locationInCmd, uint32_t offsetInRes)
361 {
362 uint32_t i = 0;
363 MOS_MEMCOMP_STATE resMmcMode = {};
364 if (!m_isOcaEnabled || !m_isInitialized)
365 {
366 return MOS_STATUS_SUCCESS;
367 }
368
369 if (!m_ocaBufContextList[ocaBufHandle].is1stLevelBBStarted)
370 {
371 MOS_OS_ASSERTMESSAGE("AddResourceToDumpList is called before oca buffer initialized!");
372 MosOcaInterfaceSpecific::OnOcaError(mosCtx, MOS_STATUS_UNINITIALIZED, __FUNCTION__, __LINE__);
373 return MOS_STATUS_UNINITIALIZED;
374 }
375
376 if (nullptr == m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList)
377 {
378 MOS_OS_NORMALMESSAGE("OCA resource info dump not enabled.");
379 return MOS_STATUS_SUCCESS;
380 }
381
382 if (nullptr == resource.pGmmResInfo || Mos_ResourceIsNull(&resource))
383 {
384 return MOS_STATUS_SUCCESS;
385 }
386
387 if (hwCmdType >= MOS_HW_COMMAND_MAX || MOS_HW_COMMAND_MAX > 64)
388 {
389 MosOcaInterfaceSpecific::OnOcaError(mosCtx, MOS_STATUS_UNINITIALIZED, __FUNCTION__, __LINE__);
390 return MOS_STATUS_INVALID_PARAMETER;
391 }
392
393 for (i = 0; i < m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resCount; ++i)
394 {
395 if (m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].allocationHandle == resource.bo->handle)
396 {
397 if (offsetInRes > m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].offsetInRes)
398 {
399 // Only update resource info for the largest offsetInRes case.
400 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].hwCmdType = (uint32_t)hwCmdType;
401 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].offsetInRes = offsetInRes;
402 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].locationInCmd = locationInCmd;
403 }
404 return MOS_STATUS_SUCCESS;
405 }
406 }
407
408 if (m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resCount >= m_ocaBufContextList[ocaBufHandle].logSection.resInfo.maxResInfoCount)
409 {
410 // Not reture error but record the resource count skipped.
411 ++m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resCountSkipped;
412 MOS_OS_NORMALMESSAGE("The resource is skipped to be dumpped to oca buffer.");
413 return MOS_STATUS_SUCCESS;
414 }
415
416 MosStreamState steamState = {};
417 steamState.osDeviceContext = mosCtx->m_osDeviceContext;
418 if (MOS_FAILED(MosInterface::GetMemoryCompressionMode(&steamState, &resource, resMmcMode)))
419 {
420 resMmcMode = MOS_MEMCOMP_DISABLED;
421 }
422 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].gfxAddress = resource.bo->offset64;
423 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].sizeAllocation = resource.pGmmResInfo->GetSizeAllocation();
424 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].sizeSurface = resource.pGmmResInfo->GetSizeSurface();
425 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].sizeSurfacePhy = resource.pGmmResInfo->GetSizeSurface();
426 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].sizeMainSurface = resource.pGmmResInfo->GetSizeMainSurface();
427 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].allocationHandle = resource.bo->handle;
428 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].hwCmdType = (uint32_t)hwCmdType;
429 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].locationInCmd = locationInCmd;
430 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].offsetInRes = offsetInRes;
431 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].pitch = (uint32_t)resource.pGmmResInfo->GetRenderPitch();
432 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].width = (uint32_t)resource.pGmmResInfo->GetBaseWidth();
433 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].height = (uint32_t)resource.pGmmResInfo->GetBaseHeight();
434 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].format = (uint32_t)resource.Format;
435 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].gmmFormat = (uint32_t)resource.pGmmResInfo->GetResourceFormat();
436 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].gmmTileMode = (uint32_t)resource.pGmmResInfo->GmmGetTileMode();
437 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].gmmClient = (uint32_t)resource.pGmmResInfo->GetClientType();
438 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].gmmResUsageType = (uint32_t)resource.pGmmResInfo->GetCachePolicyUsage();
439 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].mmcMode = (uint32_t)resMmcMode;
440 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].mmcHint = (uint32_t)resource.pGmmResInfo->GetMmcHint(0);
441 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].auxYOffset = resource.pGmmResInfo->GetUnifiedAuxSurfaceOffset(GMM_AUX_Y_CCS);
442 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].auxUVOffset = resource.pGmmResInfo->GetUnifiedAuxSurfaceOffset(GMM_AUX_UV_CCS);
443 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].auxCCSOffset = resource.pGmmResInfo->GetUnifiedAuxSurfaceOffset(GMM_AUX_CCS);
444 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].auxCCOffset = resource.pGmmResInfo->GetUnifiedAuxSurfaceOffset(GMM_AUX_CC);
445
446 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].flags.isLocalOnly = resource.pGmmResInfo->GetResFlags().Info.LocalOnly;
447 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].flags.isNonLocalOnly = resource.pGmmResInfo->GetResFlags().Info.NonLocalOnly;
448 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].flags.isNotLockable = resource.pGmmResInfo->GetResFlags().Info.NotLockable;
449 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].flags.isShared = resource.pGmmResInfo->GetResFlags().Info.Shared;
450 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].flags.isCameraCapture = resource.pGmmResInfo->GetResFlags().Gpu.CameraCapture;
451 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList[i].flags.isRenderTarget = resource.pGmmResInfo->GetResFlags().Gpu.RenderTarget;
452
453 ++m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resCount;
454
455 return MOS_STATUS_SUCCESS;
456 }
457
AddResourceInfoToLogSection(MOS_OCA_BUFFER_HANDLE ocaBufHandle,PMOS_CONTEXT mosCtx)458 void MosOcaInterfaceSpecific::AddResourceInfoToLogSection(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT mosCtx)
459 {
460 if (!m_ocaBufContextList[ocaBufHandle].is1stLevelBBStarted)
461 {
462 return;
463 }
464 if (0 == m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resCount)
465 {
466 return;
467 }
468 if (!IsLogSectionEnabled(ocaBufHandle))
469 {
470 return;
471 }
472
473 MOS_OCA_LOG_HEADER_RESOURCE_INFO header = {};
474 header.header.type = MOS_OCA_LOG_TYPE_RESOURCE_INFO;
475 header.header.headerSize = sizeof(MOS_OCA_LOG_HEADER_RESOURCE_INFO);
476 header.header.dataSize = m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resCount * sizeof(MOS_OCA_RESOURCE_INFO);
477 header.resCount = m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resCount;
478 header.resCountSkipped = m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resCountSkipped;
479
480 MOS_STATUS status = DumpDataBlock(ocaBufHandle, (PMOS_OCA_LOG_HEADER)&header, m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resInfoList);
481 if (MOS_FAILED(status))
482 {
483 MosOcaInterfaceSpecific::OnOcaError(mosCtx, status, __FUNCTION__, __LINE__);
484 }
485 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resCount = 0;
486 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resCountSkipped = 0;
487 return;
488 }
489
AddExecListInfoToLogSection(MOS_OCA_BUFFER_HANDLE ocaBufHandle,PMOS_CONTEXT mosCtx,struct MOS_OCA_EXEC_LIST_INFO * info,int count)490 void MosOcaInterfaceSpecific::AddExecListInfoToLogSection(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT mosCtx, struct MOS_OCA_EXEC_LIST_INFO *info, int count)
491 {
492 if (!m_ocaBufContextList[ocaBufHandle].is1stLevelBBStarted)
493 {
494 return;
495 }
496 if (info == nullptr || 0 == count)
497 {
498 return;
499 }
500 if (!IsLogSectionEnabled(ocaBufHandle))
501 {
502 return;
503 }
504
505 MOS_OCA_LOG_HEADER_EXEC_LIST_INFO header = {};
506 header.header.type = MOS_OCA_LOG_TYPE_EXEC_LIST_INFO;
507 header.header.headerSize = sizeof(MOS_OCA_LOG_HEADER_EXEC_LIST_INFO);
508 header.header.dataSize = count * sizeof(struct MOS_OCA_EXEC_LIST_INFO);
509 header.count = count;
510
511 MOS_STATUS status = DumpDataBlock(ocaBufHandle, (PMOS_OCA_LOG_HEADER)&header, info);
512 if (MOS_FAILED(status))
513 {
514 MosOcaInterfaceSpecific::OnOcaError(mosCtx, status, __FUNCTION__, __LINE__);
515 }
516 return;
517 }
518
519 //!
520 //! \brief Add data block to oca log section.
521 //! \param [in] ocaBufHandle
522 //! Oca buffer handle.
523 //! \param [in] mosCtx
524 //! DDI device context.
525 //! \param [in] pHeader
526 //! Log header. It can be extended by user. The acutal size of header is pHeader->headerSize.
527 //! \param [in] pData
528 //! Data block without log header. The acutal size of data block is pHeader->dataSize.
529 //! \return MOS_STATUS
530 //! Return MOS_STATUS_SUCCESS if successful, otherwise failed
531 //!
DumpDataBlock(MOS_OCA_BUFFER_HANDLE ocaBufHandle,PMOS_CONTEXT mosCtx,PMOS_OCA_LOG_HEADER pHeader,void * pData)532 MOS_STATUS MosOcaInterfaceSpecific::DumpDataBlock(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT mosCtx, PMOS_OCA_LOG_HEADER pHeader, void *pData)
533 {
534 if (!m_isOcaEnabled)
535 {
536 return MOS_STATUS_SUCCESS;
537 }
538 if (ocaBufHandle >= MAX_NUM_OF_OCA_BUF_CONTEXT || nullptr == pHeader)
539 {
540 return MOS_STATUS_INVALID_PARAMETER;
541 }
542
543 if (!IsLogSectionEnabled(ocaBufHandle))
544 {
545 return MOS_STATUS_SUCCESS;
546 }
547
548 MOS_OCA_CHK_STATUS_RETURN(mosCtx, DumpDataBlock(ocaBufHandle, pHeader, pData), __FUNCTION__, __LINE__);
549 return MOS_STATUS_SUCCESS;
550 }
551
DumpDataBlock(MOS_OCA_BUFFER_HANDLE ocaBufHandle,PMOS_OCA_LOG_HEADER pHeader,void * pData)552 MOS_STATUS MosOcaInterfaceSpecific::DumpDataBlock(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_OCA_LOG_HEADER pHeader, void *pData)
553 {
554 if (pHeader->headerSize < sizeof(MOS_OCA_LOG_HEADER) ||
555 pHeader->type >= MOS_OCA_LOG_TYPE_COUNT || pHeader->type <= MOS_OCA_LOG_TYPE_INVALID ||
556 (pHeader->dataSize > 0 && nullptr == pData) || (pHeader->dataSize == 0 && pData))
557 {
558 return MOS_STATUS_INVALID_PARAMETER;
559 }
560
561 uint32_t copySize = pHeader->headerSize + pHeader->dataSize;
562 if (m_ocaBufContextList[ocaBufHandle].logSection.offset + copySize > m_ocaLogSectionSizeLimit)
563 {
564 return MOS_STATUS_NOT_ENOUGH_BUFFER;
565 }
566
567 MOS_OS_CHK_STATUS_RETURN(InsertData(ocaBufHandle, (uint8_t *)pHeader, pHeader->headerSize));
568 if (pHeader->dataSize > 0)
569 {
570 MOS_OS_CHK_STATUS_RETURN(InsertData(ocaBufHandle, (uint8_t *)pData, pHeader->dataSize));
571 }
572
573 return MOS_STATUS_SUCCESS;
574 }
575
InsertData(MOS_OCA_BUFFER_HANDLE ocaBufHandle,uint8_t * p,uint32_t size)576 MOS_STATUS MosOcaInterfaceSpecific::InsertData(MOS_OCA_BUFFER_HANDLE ocaBufHandle, uint8_t *p, uint32_t size)
577 {
578 if (nullptr == p || 0 == size)
579 {
580 return MOS_STATUS_INVALID_PARAMETER;
581 }
582
583 uint32_t sizeCpy = std::min(m_ocaLogSectionSizeLimit - m_ocaBufContextList[ocaBufHandle].logSection.offset, size);
584 MOS_OS_CHK_STATUS_RETURN(MOS_SecureMemcpy((uint8_t *)m_ocaBufContextList[ocaBufHandle].logSection.base + m_ocaBufContextList[ocaBufHandle].logSection.offset, sizeCpy, p, sizeCpy));
585 m_ocaBufContextList[ocaBufHandle].logSection.offset += sizeCpy;
586 return MOS_STATUS_SUCCESS;
587 }
588
IncreaseSize(uint32_t cmdBufSize)589 uint32_t MosOcaInterfaceSpecific::IncreaseSize(uint32_t cmdBufSize)
590 {
591 return cmdBufSize + OCA_LOG_SECTION_SIZE_MAX;
592 }
593
InitOcaLogSection(MOS_LINUX_BO * bo)594 void MosOcaInterfaceSpecific::InitOcaLogSection(MOS_LINUX_BO *bo)
595 {
596 if (bo == nullptr || bo->virt == nullptr || bo->size <= OCA_LOG_SECTION_SIZE_MAX)
597 {
598 return;
599 }
600 OCA_LOG_SECTION_HEADER *header = (OCA_LOG_SECTION_HEADER *)((uint64_t)bo->virt + bo->size - OCA_LOG_SECTION_SIZE_MAX);
601 header->magicNum = OCA_LOG_SECTION_MAGIC_NUMBER;
602 }
603
InitLogSection(MOS_OCA_BUFFER_HANDLE ocaBufHandle,PMOS_RESOURCE resCmdBuf)604 void MosOcaInterfaceSpecific::InitLogSection(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_RESOURCE resCmdBuf)
605 {
606 if (resCmdBuf == nullptr ||
607 resCmdBuf->bo == nullptr ||
608 resCmdBuf->bo->virt == nullptr)
609 {
610 return;
611 }
612 MOS_LINUX_BO *boCmdBuf = resCmdBuf->bo;
613 if (boCmdBuf->size <= OCA_LOG_SECTION_SIZE_MAX)
614 {
615 MOS_OS_NORMALMESSAGE("1st level BB size is not larger than OCA_LOG_SECTION_SIZE_MAX.");
616 return;
617 }
618
619 uint64_t *logSectionBase = (uint64_t*)((char *)boCmdBuf->virt + boCmdBuf->size - OCA_LOG_SECTION_SIZE_MAX);
620 OCA_LOG_SECTION_HEADER *header = (OCA_LOG_SECTION_HEADER *)logSectionBase;
621
622 if (OCA_LOG_SECTION_MAGIC_NUMBER != header->magicNum)
623 {
624 MOS_OS_NORMALMESSAGE("Log section not exists in current 1st level BB.");
625 return;
626 }
627
628 m_ocaBufContextList[ocaBufHandle].logSection.base = logSectionBase;
629 // Reserve an uint64 for magic number;
630 m_ocaBufContextList[ocaBufHandle].logSection.offset = sizeof(OCA_LOG_SECTION_HEADER);
631 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resCount = 0;
632 m_ocaBufContextList[ocaBufHandle].logSection.resInfo.resCountSkipped = 0;
633 }
634
IsLogSectionEnabled(MOS_OCA_BUFFER_HANDLE ocaBufHandle)635 bool MosOcaInterfaceSpecific::IsLogSectionEnabled(MOS_OCA_BUFFER_HANDLE ocaBufHandle)
636 {
637 return nullptr != m_ocaBufContextList[ocaBufHandle].logSection.base;
638 }
639
640 //!
641 //! \brief Oca Error Handler.
642 //! \param [in] mosCtx
643 //! DDI device context.
644 //! \param [in] status
645 //! status for error.
646 //! \param [in] functionName
647 //! The failure function name.
648 //! \param [in] lineNumber
649 //! The line number where the failure happened.
650 //!
OnOcaError(PMOS_CONTEXT mosCtx,MOS_STATUS status,const char * functionName,uint32_t lineNumber)651 void MosOcaInterfaceSpecific::OnOcaError(PMOS_CONTEXT mosCtx, MOS_STATUS status, const char *functionName, uint32_t lineNumber)
652 {
653 if (MOS_SUCCEEDED(status))
654 {
655 return;
656 }
657
658 MOS_OS_ASSERTMESSAGE("%s failed at line %d with status = %d!", functionName, lineNumber, status);
659
660 MOS_TraceEventExt(EVENT_OCA_ERROR,
661 EVENT_TYPE_INFO,
662 &status,
663 sizeof(uint32_t),
664 nullptr,
665 0);
666
667 if (MOS_SUCCEEDED(s_ocaStatus))
668 {
669 MediaUserSettingSharedPtr userSettingPtr = nullptr;
670
671 s_ocaStatus = status;
672 s_lineNumForOcaErr = lineNumber;
673
674 userSettingPtr = MosInterface::MosGetUserSettingInstance(mosCtx);
675 ReportUserSetting(
676 userSettingPtr,
677 __MEDIA_USER_FEATURE_VALUE_OCA_STATUS,
678 status,
679 MediaUserSetting::Group::Device);
680
681 ReportUserSetting(
682 userSettingPtr,
683 __MEDIA_USER_FEATURE_VALUE_OCA_ERROR_HINT,
684 lineNumber,
685 MediaUserSetting::Group::Device);
686 }
687 }
688
689 //!
690 //! \brief Initialize oca error handler related items.
691 //!
InitOcaErrorHandler(PMOS_CONTEXT mosCtx)692 void MosOcaInterfaceSpecific::InitOcaErrorHandler(PMOS_CONTEXT mosCtx)
693 {
694 if (!s_bOcaStatusExistInReg)
695 {
696 s_bOcaStatusExistInReg = true;
697
698 // "Oca Status" should already be added into reg for MOS_FAILED(s_ocaStatus) case by OnOcaError.
699 if (MOS_SUCCEEDED(s_ocaStatus))
700 {
701 MediaUserSettingSharedPtr userSettingPtr = nullptr;
702 userSettingPtr = MosInterface::MosGetUserSettingInstance(mosCtx);
703 ReportUserSetting(
704 userSettingPtr,
705 __MEDIA_USER_FEATURE_VALUE_OCA_STATUS,
706 s_ocaStatus,
707 MediaUserSetting::Group::Device);
708 }
709 }
710 }
711
712 //!
713 //! \brief Oca Interface Initialize.
714 //!
Initialize(PMOS_CONTEXT mosContext)715 void MosOcaInterfaceSpecific::Initialize(PMOS_CONTEXT mosContext)
716 {
717 MosOcaInterfaceSpecific::InitOcaErrorHandler(mosContext);
718 if (m_isInitialized == false)
719 {
720 MediaUserSettingSharedPtr userSettingPtr = MosInterface::MosGetUserSettingInstance(mosContext);
721 // read isOcaEnabled from reg key
722 int32_t value = 0;
723 ReadUserSetting(
724 userSettingPtr,
725 value,
726 __MEDIA_USER_FEATURE_VALUE_ENABLE_UMD_OCA,
727 MediaUserSetting::Group::Device);
728
729 m_isOcaEnabled = value;
730 if (!m_isOcaEnabled)
731 {
732 return;
733 }
734 char *user_ctx_env = getenv("INTEL_DISABLE_DUMP_EXEC_LIST_INFO");
735 if (nullptr != user_ctx_env)
736 {
737 uint8_t user_ctx_env_value = (bool)atoi(user_ctx_env);
738 if (user_ctx_env_value == 1)
739 {
740 m_ocaDumpExecListInfoEnabled = false;
741 }
742 }
743
744 m_config.maxResInfoCount = OCA_MAX_RESOURCE_INFO_COUNT_MAX;
745 m_resInfoPool = MOS_NewArray(MOS_OCA_RESOURCE_INFO, m_config.maxResInfoCount * MAX_NUM_OF_OCA_BUF_CONTEXT);
746 if (nullptr == m_resInfoPool)
747 {
748 return;
749 }
750 MosUtilities::MosZeroMemory(m_resInfoPool, sizeof(MOS_OCA_RESOURCE_INFO)*m_config.maxResInfoCount * MAX_NUM_OF_OCA_BUF_CONTEXT);
751 for (int i = 0; i < MAX_NUM_OF_OCA_BUF_CONTEXT; ++i)
752 {
753 m_ocaBufContextList[i].logSection.resInfo.resInfoList = m_resInfoPool + i * m_config.maxResInfoCount;
754 }
755 if (nullptr != m_ocaMutex)
756 {
757 return;
758 }
759
760 m_ocaMutex = MosUtilities::MosCreateMutex();
761 if (nullptr == m_ocaMutex)
762 {
763 MOS_DeleteArray(m_resInfoPool);
764 return;
765 }
766
767 m_mutexForOcaBufPool = MosUtilities::MosCreateMutex();
768 if (nullptr == m_mutexForOcaBufPool)
769 {
770 MOS_DeleteArray(m_resInfoPool);
771 MosUtilities::MosDestroyMutex(m_ocaMutex);
772 m_ocaMutex = nullptr;
773 return;
774 }
775
776 m_isInitialized = true;
777 }
778 }
779
GetInstance()780 MosOcaInterface& MosOcaInterfaceSpecific::GetInstance()
781 {
782 static MosOcaInterfaceSpecific instance;
783 return instance;
784 }
785
MosOcaInterfaceSpecific()786 MosOcaInterfaceSpecific::MosOcaInterfaceSpecific()
787 {
788 }
789
MosOcaInterfaceSpecific(MosOcaInterfaceSpecific &)790 MosOcaInterfaceSpecific::MosOcaInterfaceSpecific(MosOcaInterfaceSpecific&)
791 {
792 }
793
operator =(MosOcaInterfaceSpecific &)794 MosOcaInterfaceSpecific& MosOcaInterfaceSpecific::operator= (MosOcaInterfaceSpecific&)
795 {
796 return *this;
797 }
798
~MosOcaInterfaceSpecific()799 MosOcaInterfaceSpecific::~MosOcaInterfaceSpecific()
800 {
801 Uninitialize();
802 s_isDestroyed = true;
803 }
804
805 //!
806 //! \brief Oca Interface uninitialize.
807 //!
Uninitialize()808 void MosOcaInterfaceSpecific::Uninitialize()
809 {
810 if (m_isInitialized == true)
811 {
812 if (m_PendingOcaBuffersToUnlock.size() > 0)
813 {
814 MOS_OS_ASSERTMESSAGE("%d Oca Buffers in pending list!", m_PendingOcaBuffersToUnlock.size());
815 UnlockPendingOcaBuffers(nullptr, nullptr, 0);
816 }
817 if (nullptr != m_mutexForOcaBufPool)
818 {
819 MosUtilities::MosDestroyMutex(m_mutexForOcaBufPool);
820 m_mutexForOcaBufPool = nullptr;
821 }
822 if (nullptr != m_ocaMutex)
823 {
824 MosUtilities::MosDestroyMutex(m_ocaMutex);
825 m_ocaMutex = nullptr;
826 }
827 if (m_resInfoPool != nullptr)
828 {
829 MOS_DeleteArray(m_resInfoPool);
830 m_resInfoPool = nullptr;
831 for (int i = 0; i < MAX_NUM_OF_OCA_BUF_CONTEXT; ++i)
832 {
833 m_ocaBufContextList[i].logSection.resInfo.resInfoList = nullptr;
834 }
835 }
836 m_hOcaMap.clear();
837 m_isInitialized = false;
838 s_bOcaStatusExistInReg = false;
839 s_isDestroyed = false;
840 m_ocaDumpExecListInfoEnabled = true;
841 }
842 }
843
844 //!
845 //! \brief Oca Interface Initialize.
846 //!
InitInterface(PMOS_CONTEXT mosContext)847 void MosOcaInterfaceSpecific::InitInterface(PMOS_CONTEXT mosContext)
848 {
849 if (MosUtilities::MosAtomicIncrement(&s_refCount) == 1)
850 {
851 MosOcaInterfaceSpecific &ins = (MosOcaInterfaceSpecific &)MosOcaInterfaceSpecific::GetInstance();
852 ins.Initialize(mosContext);
853 }
854 return;
855 }
856
857 //!
858 //! \brief Oca Interface uninitialize.
859 //!
UninitInterface()860 void MosOcaInterfaceSpecific::UninitInterface()
861 {
862 if (MosUtilities::MosAtomicDecrement(&s_refCount) == 0)
863 {
864 if(!s_isDestroyed)
865 {
866 MosOcaInterfaceSpecific &ins = (MosOcaInterfaceSpecific &)MosOcaInterfaceSpecific::GetInstance();
867 ins.Uninitialize();
868 }
869 }
870 return;
871 }
872
873 //!
874 //! \brief Insert OCA buffer handle into m_hOcaMap
875 //! \param [in] key
876 //! The key of m_hOcaMap.
877 //! \param [in] handle
878 //! Oca buffer handle.
879 //! \return MOS_STATUS
880 //! Return MOS_STATUS_SUCCESS if insert successfully, otherwise insert failed.
881 //!
InsertOcaBufHandleMap(uint32_t * key,MOS_OCA_BUFFER_HANDLE handle)882 MOS_STATUS MosOcaInterfaceSpecific::InsertOcaBufHandleMap(uint32_t *key, MOS_OCA_BUFFER_HANDLE handle)
883 {
884 MOS_OS_CHK_NULL_RETURN(m_ocaMutex);
885 MOS_OS_CHK_NULL_RETURN(key);
886
887 MosOcaAutoLock autoLock(m_ocaMutex);
888 auto success = m_hOcaMap.insert(std::make_pair(key, handle));
889 if (!success.second)
890 {
891 // Should never come to here.
892 MOS_OS_ASSERTMESSAGE("OcaBufHandle has already been assigned to current cmdBuffer!");
893 return MOS_STATUS_UNKNOWN;
894 }
895 return MOS_STATUS_SUCCESS;
896 }
897
898 //!
899 //! \brief Remove OCA buffer handle from m_hOcaMap
900 //! \param [in] key
901 //! The key of m_hOcaMap.
902 //! \return MOS_STATUS
903 //! Return MOS_STATUS_SUCCESS if erase successfully, otherwise erase failed.
904 //!
RemoveOcaBufHandleFromMap(uint32_t * key)905 MOS_STATUS MosOcaInterfaceSpecific::RemoveOcaBufHandleFromMap(uint32_t *key)
906 {
907 MOS_OS_CHK_NULL_RETURN(m_ocaMutex);
908
909 MosOcaAutoLock autoLock(m_ocaMutex);
910 auto it = m_hOcaMap.find(key);
911 if (it != m_hOcaMap.end())
912 {
913 m_hOcaMap.erase(it);
914 }
915 return MOS_STATUS_SUCCESS;
916 }
917
918 //!
919 //! \brief Get OCA buffer handle from m_hOcaMap
920 //! \param [in] key
921 //! The key of m_hOcaMap.
922 //! \return MOS_OCA_BUFFER_HANDLE
923 //! Return oca buffer handle.
924 //!
GetOcaBufHandleFromMap(uint32_t * key)925 MOS_OCA_BUFFER_HANDLE MosOcaInterfaceSpecific::GetOcaBufHandleFromMap(uint32_t *key)
926 {
927 if (nullptr == m_ocaMutex)
928 {
929 MOS_OS_ASSERTMESSAGE("m_ocaMutex is nullptr.");
930 return MOS_OCA_INVALID_BUFFER_HANDLE;
931 }
932 MosOcaAutoLock autoLock(m_ocaMutex);
933 auto it = m_hOcaMap.find(key);
934 if (it == m_hOcaMap.end())
935 {
936 // May come here for workloads not enabling UMD_OCA.
937 return MOS_OCA_INVALID_BUFFER_HANDLE;
938 }
939 if (it->second >= MAX_NUM_OF_OCA_BUF_CONTEXT)
940 {
941 MOS_OS_ASSERTMESSAGE("Get invalid OcaBufHandle: %d!", it->second);
942 return MOS_OCA_INVALID_BUFFER_HANDLE;
943 }
944
945 return it->second;
946 }
947