xref: /aosp_15_r20/external/intel-media-driver/media_softlet/linux/common/os/mos_oca_interface_specific.h (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_interface_specific.h
24 //! \brief    Linux specfic OCA interface class
25 //!
26 
27 #ifndef __MOS_OCA_INTERFACE_SPECIFIC_H__
28 #define __MOS_OCA_INTERFACE_SPECIFIC_H__
29 
30 #include "mos_oca_interface.h"
31 #include "mos_interface.h"
32 #include "mos_oca_defs_specific.h"
33 
34 class MosOcaAutoLock
35 {
36 public:
MosOcaAutoLock(PMOS_MUTEX pMutex)37     MosOcaAutoLock(PMOS_MUTEX pMutex) : m_pMutex(pMutex)
38     {
39         if (m_pMutex)
40         {
41             MosUtilities::MosLockMutex(m_pMutex);
42         }
43         else
44         {
45             MOS_OS_ASSERTMESSAGE("Unexpected, m_pMutex cannot be null");
46         }
47     }
~MosOcaAutoLock()48     virtual ~MosOcaAutoLock()
49     {
50         if (m_pMutex)
51         {
52             MosUtilities::MosUnlockMutex(m_pMutex);
53         }
54         else
55         {
56             MOS_OS_ASSERTMESSAGE("Unexpected, m_pMutex cannot be null");
57         }
58     }
59 private:
60     PMOS_MUTEX m_pMutex = nullptr;
61 MEDIA_CLASS_DEFINE_END(MosOcaAutoLock)
62 };
63 
64 class MosOcaInterfaceSpecific : public MosOcaInterface
65 {
66 public:
67     //!
68     //! \brief  Destructor
69     //!
70     virtual ~MosOcaInterfaceSpecific();
71 
72     //!
73     //! \brief  Get the idle oca buffer, which is neither used by hw nor locked, and lock it for edit.
74     //! \param  [in] pMosContext
75     //!         pointer to MOS_INTERFACE
76     //! \param  [in] CurrentGpuContextHandle
77     //!         Gpu context handle
78     //! \return MOS_OCA_BUFFER_HANDLE
79     //!         return the handle for oca buffer
80     //!
81     virtual MOS_OCA_BUFFER_HANDLE LockOcaBufAvailable(PMOS_CONTEXT pMosContext, uint32_t CurrentGpuContextHandle);
82 
83     //!
84     //! \brief  Unlock the oca buffer when edit complete.
85     //! \param  [in] ocaBufHandle
86     //!         Oca buffer handle.
87     //! \return MOS_STATUS
88     //!         Return MOS_STATUS_SUCCESS if successful, otherwise failed
89     //!
90     virtual MOS_STATUS UnlockOcaBuf(MOS_OCA_BUFFER_HANDLE ocaBufHandle);
91 
92     //!
93     //! \brief  Delayed to Unlock the oca buffer when edit complete.
94     //! \param  [in] ocaBufHandle
95     //!         Oca buffer handle.
96     //! \return MOS_STATUS
97     //!         Return MOS_STATUS_SUCCESS if successful, otherwise failed
98     //!
99     virtual MOS_STATUS UnlockOcaBufferWithDelay(MOS_OCA_BUFFER_HANDLE ocaBufHandle);
100 
101     //!
102     //! \brief  Unlock pending oca buffers.
103     //! \param  [in] mosCtx
104     //!         mosCtx.
105     //! \param  [in] str
106     //!         Info to add into the log setion; if str==nullptr, unlock oca buffer only, without log dump
107     //! \param  [in] maxCount
108     //!         Length of str; if str==nullptr, maxCount=0.
109     //! \return MOS_STATUS
110     //!         Return MOS_STATUS_SUCCESS if successful, otherwise failed
111     //!
112     virtual void UnlockPendingOcaBuffers(PMOS_CONTEXT mosCtx, struct MOS_OCA_EXEC_LIST_INFO *info, int count);
113 
114     //!
115     //! \brief  Oca operation which should be called at the beginning of 1st level batch buffer start.
116     //! \param  [out] gpuVaOcaBuffer
117     //!         The gfx virtual address of oca buffer, which should be set to GPR11 by LRI at the
118     //!         beginning of 1st level batch buffer no matter return value is MOS_STATUS_SUCCESS or not.
119     //! \param  [in] ocaBufHandle
120     //!         Oca buffer handle.
121     //! \param  [in] pMosContext
122     //!         Pointer to MOS_CONTEXT.
123     //! \param  [in] pMosResource
124     //!         Pointer to the MOS_RESOURCE.
125     //! \param  [in] offsetOf1stLevelBB
126     //!         Offset for current BB in pMosResource.
127     //! \param  [in] bUseSizeOfResource
128     //!         If true, use size of pMosResource for batch buffer, else use sizeOf1stLevelBB.
129     //! \param  [in] sizeOf1stLevelBB
130     //!         Size of BB. Ignore if bUseSizeOfResource == true.
131     //! \return MOS_STATUS
132     //!         Return MOS_STATUS_SUCCESS if successful, otherwise failed
133     //!
134     virtual MOS_STATUS On1stLevelBBStart(uint64_t &gpuVaOcaBuffer, MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT pMosContext, void *pMosResource,
135         uint32_t offsetOf1stLevelBB, bool bUseSizeOfResource, uint32_t sizeOf1stLevelBB);
136 
137     //!
138     //! \brief  Oca operation which should be called before adding batch buffer end command for 1st
139     //!         level batch buffer.
140     //! \param  [in] ocaBufHandle
141     //!         Oca buffer handle.
142     //! \param  [in] mosCtx
143     //!         DDI device context.
144     //! \return MOS_STATUS
145     //!         Return MOS_STATUS_SUCCESS if successful, otherwise failed
146     //!
147     virtual MOS_STATUS On1stLevelBBEnd(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT mosCtx);
148 
149     //!
150     //! \brief  Oca operation which should be called before sending start sub level batch buffer command.
151     //! \param  [in] ocaBufHandle
152     //!         Oca buffer handle.
153     //! \param  [in] pMosContext
154     //!         Pointer to MOS_CONTEXT.
155     //! \param  [in] pMosResource
156     //!         Pointer to the MOS_RESOURCE.
157     //! \param  [in] offsetOfSubLevelBB
158     //!         Offset for current BB in pMosResource.
159     //! \param  [in] bUseSizeOfResource
160     //!         If true, use size of pMosResource for batch buffer, else use sizeOfIndirectState.
161     //! \param  [in] sizeOfSubLevelBB
162     //!         Size of BB. Ignore if bUseSizeOfResource == true.
163     //! \return MOS_STATUS
164     //!         Return MOS_STATUS_SUCCESS if successful, otherwise failed
165     //!
166     virtual MOS_STATUS OnSubLevelBBStart(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT pMosContext, void *pMosResource, uint32_t offsetOfSubLevelBB, bool bUseSizeOfResource, uint32_t sizeOfSubLevelBB);
167 
168     //!
169     //! \brief  Oca operation which should be called when indirect states being added.
170     //! \param  [in] ocaBufHandle
171     //!         Oca buffer handle.
172     //! \param  [in] pMosContext
173     //!         Pointer to MOS_CONTEXT.
174     //! \param  [in] pMosResource
175     //!         Pointer to the MOS_RESOURCE.
176     //! \param  [in] offsetOfIndirectState
177     //!         Offset for current state in pMosResource.
178     //! \param  [in] bUseSizeOfResource
179     //!         If true, use size of pMosResource for indirect state, else use sizeOfIndirectState.
180     //! \param  [in] sizeOfIndirectState
181     //!         Size of indirect state. Ignore if bUseSizeOfResource == true.
182     //! \return MOS_STATUS
183     //!         Return MOS_STATUS_SUCCESS if successful, otherwise failed
184     //!
185     virtual MOS_STATUS OnIndirectState(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT pMosContext, void *pMosResource, uint32_t offsetOfIndirectState, bool bUseSizeOfResource, uint32_t sizeOfIndirectState);
186 
187     //!
188     //! \brief  Oca operation which should be called before adding dispatch states,
189     //!         e.g. VEB_DI_IECP_STATE and MEDIA_OBJECT_WALKER.
190     //! \param  [out] offsetInIndirectStateHeap
191     //!         The start offset of current dispatch in indirect state heap, which should be set to low 32 bits
192     //!         of GPR12 by LRI before dispatch commands being added.
193     //!         OCA_HEAP_INVALID_OFFSET means no need to configure GPR12, otherwise the register need be configured
194     //!         no matter return value being MOS_STATUS_SUCCESS or not.
195     //! \param  [in] ocaBufHandle
196     //!         Oca buffer handle.
197     //! \param  [in] mosCtx
198     //!         DDI device context.
199     //! \return MOS_STATUS
200     //!         Return MOS_STATUS_SUCCESS if successful, otherwise failed
201     //!
202     virtual MOS_STATUS OnDispatch(uint32_t &offsetInIndirectStateHeap, MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT mosCtx);
203 
204     //!
205     //! \brief  Add string to oca log section
206     //! \param  [in] ocaBufHandle
207     //!         Oca buffer handle.
208     //! \param  [in] mosCtx
209     //!         DDI device context.
210     //! \param  [in] str
211     //!         string to be added.
212     //! \param  [in] maxCount
213     //!         size of the buffer pointed by str.
214     //! \return MOS_STATUS
215     //!         Return MOS_STATUS_SUCCESS if successful, otherwise failed
216     //!
217     virtual MOS_STATUS TraceMessage(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT mosCtx, const char *str, uint32_t maxCount);
218 
219     //!
220     //! \brief  Add resource to dump list.
221     //! \param  [in] ocaBufHandle
222     //!         Oca buffer handle.
223     //! \param  [in] mosCtx
224     //!         DDI device context.
225     //! \param  [in] resource
226     //!         Reference to MOS_RESOURCE.
227     //! \param  [in] hwCmdType
228     //!         Hw command Type.
229     //! \param  [in] locationInCmd
230     //!         Location in command.
231     //! \param  [in] offsetInRes
232     //!         Offset in resource.
233     //! \return MOS_STATUS
234     //!         Return MOS_STATUS_SUCCESS if successful, otherwise failed
235     //!
236     virtual MOS_STATUS AddResourceToDumpList(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT mosCtx, MOS_RESOURCE &resource, MOS_HW_COMMAND hwCmdType, uint32_t locationInCmd, uint32_t offsetInRes);
237 
238     //!
239     //! \brief  Add data block to oca log section.
240     //! \param  [in] ocaBufHandle
241     //!         Oca buffer handle.
242     //! \param  [in] mosCtx
243     //!         DDI device context.
244     //! \param  [in] pHeader
245     //!         Log header. It can be extended by user. The acutal size of header is pHeader->m_HeaderSize.
246     //! \param  [in] pData
247     //!         Data block without log header. The acutal size of data block is pHeader->m_DataSize.
248     //! \return MOS_STATUS
249     //!         Return MOS_STATUS_SUCCESS if successful, otherwise failed
250     //!
251     virtual MOS_STATUS DumpDataBlock(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT mosCtx, PMOS_OCA_LOG_HEADER pHeader, void *pData);
252 
253     //!
254     //! \brief  Get the mutex for oca buffer handles protection.
255     //! \return PMOS_MUTEX
256     //!         Return PMOS_MUTEX if successful, otherwise nullptr
257     //!
GetMutex()258     virtual PMOS_MUTEX GetMutex()
259     {
260         return m_ocaMutex;
261     }
262 
263     //!
264     //! \brief  Insert OCA buffer handle into m_hOcaMap
265     //! \param  [in] key
266     //!         The key of m_hOcaMap.
267     //! \param  [in] handle
268     //!         Oca buffer handle.
269     //! \return MOS_STATUS
270     //!         Return MOS_STATUS_SUCCESS if insert successfully, otherwise insert failed.
271     //!
272     virtual MOS_STATUS InsertOcaBufHandleMap(uint32_t *key, MOS_OCA_BUFFER_HANDLE handle);
273 
274     //!
275     //! \brief  Remove OCA buffer handle from m_hOcaMap
276     //! \param  [in] key
277     //!         The key of m_hOcaMap.
278     //! \return MOS_STATUS
279     //!         Return MOS_STATUS_SUCCESS if erase successfully, otherwise erase failed.
280     //!
281     virtual MOS_STATUS RemoveOcaBufHandleFromMap(uint32_t *key);
282 
283     //!
284     //! \brief  Get OCA buffer handle from m_hOcaMap
285     //! \param  [in] key
286     //!         The key of m_hOcaMap.
287     //! \return MOS_OCA_BUFFER_HANDLE
288     //!         Return oca buffer handle.
289     //!
290     virtual MOS_OCA_BUFFER_HANDLE GetOcaBufHandleFromMap(uint32_t *key);
291 
292     //!
293     //! \brief  Get OCA status
294     //! \return MOS_STATUS
295     //!         Return oca status
296     //!
GetOCAStatus()297     virtual MOS_STATUS GetOCAStatus()
298     {
299         return s_ocaStatus;
300     }
301 
302     //!
303     //! \brief  Set OCA status
304     //! \param  [in] status
305     //!         oca status
306     //! \return void
307     //!
SetOCAStatus(MOS_STATUS status)308     virtual void SetOCAStatus(MOS_STATUS status)
309     {
310         s_ocaStatus = status;
311     }
312 
313     //!
314     //! \brief  Set OCA error line number
315     //! \param  [in] num
316     //!         line number
317     //! \return void
318     //!
SetOCAErrorLineNumber(uint32_t num)319     virtual void SetOCAErrorLineNumber(uint32_t num)
320     {
321         s_lineNumForOcaErr = num;
322     }
323 
324     //!
325     //! \brief  Oca Interface Initialize.
326     //!
327     static void InitInterface(PMOS_CONTEXT mosCtx);
328 
329     //!
330     //! \brief  Oca Interface uninitialize.
331     //!
332     static void UninitInterface();
333 
334     //!
335     //! \brief  Initialize oca error handler related items.
336     //!
337     static void InitOcaErrorHandler(PMOS_CONTEXT mosCtx);
338 
339     //!
340     //! \brief  Oca Error Handler.
341     //! \param  [in] mosCtx
342     //!         ddi device context.
343     //! \param  [in] status
344     //!         status for error.
345     //! \param  [in] functionName
346     //!         The failure function name.
347     //! \param  [in] lineNumber
348     //!         The line number where the failure happened.
349     //!
350     static void OnOcaError(PMOS_CONTEXT mosCtx, MOS_STATUS status, const char *functionName, uint32_t lineNumber);
351 
IsOcaEnabled()352     bool IsOcaEnabled()
353     {
354          return m_isOcaEnabled;
355     }
356 
357     //!
358     //! \brief  return oca dump exec list info is enabled or not.
359     //!
IsOcaDumpExecListInfoEnabled()360     bool IsOcaDumpExecListInfoEnabled()
361     {
362         return m_ocaDumpExecListInfoEnabled;
363     }
364 
365     static MosOcaInterface& GetInstance();
366 
367     static uint32_t IncreaseSize(uint32_t cmdBufSize);
368 
369     static void InitOcaLogSection(MOS_LINUX_BO *bo);
370 
371 private:
372     //!
373     //! \brief  Oca Interface Initialize.
374     //!
375     void Initialize(PMOS_CONTEXT mosCtx);
376 
377     virtual MOS_STATUS InsertData(MOS_OCA_BUFFER_HANDLE ocaBufHandle, uint8_t *p, uint32_t size);
378 
379     MOS_STATUS DumpDataBlock(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_OCA_LOG_HEADER pHeader, void *pData);
380 
381     void AddResourceInfoToLogSection(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT mosCtx);
382     void AddExecListInfoToLogSection(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_CONTEXT mosCtx, struct MOS_OCA_EXEC_LIST_INFO *info, int count);
383 
384     void InitLogSection(MOS_OCA_BUFFER_HANDLE ocaBufHandle, PMOS_RESOURCE resCmdBuf);
385 
386     bool IsLogSectionEnabled(MOS_OCA_BUFFER_HANDLE ocaBufHandle);
387 
388     //!
389     //! \brief  Oca Interface uninitialize.
390     //!
391     void Uninitialize();
392 
393     MosOcaInterfaceSpecific();
394     MosOcaInterfaceSpecific(MosOcaInterfaceSpecific &);
395     MosOcaInterfaceSpecific& operator= (MosOcaInterfaceSpecific &);
396 
397     PMOS_MUTEX                      m_ocaMutex                                      = nullptr;
398     PMOS_MUTEX                      m_mutexForOcaBufPool                            = nullptr;
399 
400     std::map<uint32_t*, MOS_OCA_BUFFER_HANDLE> m_hOcaMap;    //!< Oca buffer handle map
401 
402     bool                            m_isOcaEnabled                                  = false;
403     bool                            m_isInitialized                                 = false;
404     MOS_OCA_RESOURCE_INFO           *m_resInfoPool                                  = nullptr;
405     MOS_OCA_BUF_CONTEXT             m_ocaBufContextList[MAX_NUM_OF_OCA_BUF_CONTEXT] = {};
406     MOS_OCA_BUFFER_CONFIG           m_config;
407     uint32_t                        m_indexOfNextOcaBufContext                      = 0;
408     uint32_t                        m_ocaLogSectionSizeLimit                        = OCA_LOG_SECTION_SIZE_MAX;
409     bool                            m_ocaDumpExecListInfoEnabled                    = true;
410 
411     std::vector<MOS_OCA_BUFFER_HANDLE> m_PendingOcaBuffersToUnlock;
412 
413     static MOS_STATUS               s_ocaStatus;                    //!< The status for first oca error encounterred.
414     static uint32_t                 s_lineNumForOcaErr;             //!< The line number for first oca error encounterred.
415     static bool                     s_bOcaStatusExistInReg;         //!< ture if "Oca Status" already being added to reg.
416     static int32_t                  s_refCount;
417     static bool                     s_isDestroyed;
418 MEDIA_CLASS_DEFINE_END(MosOcaInterfaceSpecific)
419 };
420 #endif  // __MOS_OCA_INTERFACE_SPECIFIC_H__
421