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