xref: /aosp_15_r20/external/intel-media-driver/media_softlet/linux/common/os/mos_oca_specific.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
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