cmdq_record.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263
  1. #include <linux/slab.h>
  2. #include <linux/errno.h>
  3. #include <linux/memory.h>
  4. #include "cmdq_record.h"
  5. #include "cmdq_core.h"
  6. #include "cmdq_reg.h"
  7. #include "cmdq_platform.h"
  8. /* #include "ddp_reg.h" */
  9. int32_t cmdq_rec_realloc_addr_metadata_buffer(cmdqRecHandle handle, const uint32_t size)
  10. {
  11. void *pNewBuf = NULL;
  12. void *pOriginalBuf = (void *)CMDQ_U32_PTR(handle->secData.addrMetadatas);
  13. const uint32_t originalSize =
  14. sizeof(cmdqSecAddrMetadataStruct) * (handle->secData.addrMetadataMaxCount);
  15. if (size <= originalSize)
  16. return 0;
  17. pNewBuf = kzalloc(size, GFP_KERNEL);
  18. if (NULL == pNewBuf) {
  19. CMDQ_ERR("REC: secAddrMetadata, kzalloc %d bytes addr_metadata buffer failed\n",
  20. size);
  21. return -ENOMEM;
  22. }
  23. if (pOriginalBuf && originalSize > 0)
  24. memcpy(pNewBuf, pOriginalBuf, originalSize);
  25. CMDQ_VERBOSE("REC: secAddrMetadata, realloc size from %d to %d bytes\n", originalSize,
  26. size);
  27. kfree(pOriginalBuf);
  28. handle->secData.addrMetadatas = (cmdqU32Ptr_t) (unsigned long)(pNewBuf);
  29. handle->secData.addrMetadataMaxCount = size / sizeof(cmdqSecAddrMetadataStruct);
  30. return 0;
  31. }
  32. int cmdq_rec_realloc_cmd_buffer(cmdqRecHandle handle, uint32_t size)
  33. {
  34. void *pNewBuf = NULL;
  35. if (size <= handle->bufferSize)
  36. return 0;
  37. pNewBuf = kzalloc(size, GFP_KERNEL);
  38. if (NULL == pNewBuf) {
  39. CMDQ_ERR("REC: kzalloc %d bytes cmd_buffer failed\n", size);
  40. return -ENOMEM;
  41. }
  42. memset(pNewBuf, 0, size);
  43. if (handle->pBuffer && handle->blockSize > 0)
  44. memcpy(pNewBuf, handle->pBuffer, handle->blockSize);
  45. CMDQ_VERBOSE("REC: realloc size from %d to %d bytes\n", handle->bufferSize, size);
  46. kfree(handle->pBuffer);
  47. handle->pBuffer = pNewBuf;
  48. handle->bufferSize = size;
  49. return 0;
  50. }
  51. int32_t cmdqRecCreate(enum CMDQ_SCENARIO_ENUM scenario, cmdqRecHandle *pHandle)
  52. {
  53. cmdqRecHandle handle = NULL;
  54. if (scenario < 0 || scenario >= CMDQ_MAX_SCENARIO_COUNT) {
  55. CMDQ_ERR("Unknown scenario type %d\n", scenario);
  56. return -EINVAL;
  57. }
  58. handle = kzalloc(sizeof(uint8_t *) * sizeof(struct cmdqRecStruct), GFP_KERNEL);
  59. if (NULL == handle)
  60. return -ENOMEM;
  61. handle->scenario = scenario;
  62. handle->pBuffer = NULL;
  63. handle->bufferSize = 0;
  64. handle->blockSize = 0;
  65. handle->engineFlag = cmdq_rec_flag_from_scenario(scenario);
  66. handle->priority = CMDQ_THR_PRIO_NORMAL;
  67. handle->prefetchCount = 0;
  68. handle->finalized = false;
  69. handle->pRunningTask = NULL;
  70. /* secure path */
  71. handle->secData.isSecure = false;
  72. handle->secData.enginesNeedDAPC = 0LL;
  73. handle->secData.enginesNeedPortSecurity = 0LL;
  74. handle->secData.addrMetadatas = (cmdqU32Ptr_t) (unsigned long)NULL;
  75. handle->secData.addrMetadataMaxCount = 0;
  76. handle->secData.addrMetadataCount = 0;
  77. if (0 != cmdq_rec_realloc_cmd_buffer(handle, CMDQ_INITIAL_CMD_BLOCK_SIZE)) {
  78. kfree(handle);
  79. return -ENOMEM;
  80. }
  81. *pHandle = handle;
  82. return 0;
  83. }
  84. int32_t cmdq_append_addr_metadata(cmdqRecHandle handle, const cmdqSecAddrMetadataStruct *pMetadata)
  85. {
  86. cmdqSecAddrMetadataStruct *pAddrs;
  87. int32_t status;
  88. /* element index of the New appended addr metadat */
  89. const uint32_t index = handle->secData.addrMetadataCount;
  90. pAddrs = NULL;
  91. status = 0;
  92. if (0 >= handle->secData.addrMetadataMaxCount) {
  93. /* not init yet, initialize to allow max 8 addr metadata */
  94. status = cmdq_rec_realloc_addr_metadata_buffer(handle,
  95. sizeof(cmdqSecAddrMetadataStruct) *
  96. 8);
  97. } else if (handle->secData.addrMetadataCount >= (handle->secData.addrMetadataMaxCount)) {
  98. /* enlarge metadata buffer to twice as */
  99. status = cmdq_rec_realloc_addr_metadata_buffer(handle,
  100. sizeof(cmdqSecAddrMetadataStruct) *
  101. (handle->
  102. secData.addrMetadataMaxCount) * 2);
  103. }
  104. if (0 > status)
  105. return -ENOMEM;
  106. pAddrs = (cmdqSecAddrMetadataStruct *) (CMDQ_U32_PTR(handle->secData.addrMetadatas));
  107. /* append meatadata */
  108. pAddrs[index].instrIndex = pMetadata->instrIndex;
  109. pAddrs[index].baseHandle = pMetadata->baseHandle;
  110. pAddrs[index].offset = pMetadata->offset;
  111. pAddrs[index].size = pMetadata->size;
  112. pAddrs[index].port = pMetadata->port;
  113. pAddrs[index].type = pMetadata->type;
  114. /* meatadata count ++ */
  115. handle->secData.addrMetadataCount += 1;
  116. return 0;
  117. }
  118. int32_t cmdq_append_command(cmdqRecHandle handle, enum CMDQ_CODE_ENUM code, uint32_t argA,
  119. uint32_t argB)
  120. {
  121. int32_t subsys;
  122. uint32_t *pCommand;
  123. /* be careful that subsys encoding position is different among platforms */
  124. const uint32_t subsysBit = cmdq_core_get_subsys_LSB_in_argA();
  125. if (NULL == handle)
  126. return -EFAULT;
  127. pCommand = (uint32_t *) ((uint8_t *) handle->pBuffer + handle->blockSize);
  128. if (handle->finalized) {
  129. CMDQ_ERR("Already finalized record 0x%p, cannot add more command", handle);
  130. return -EBUSY;
  131. }
  132. /* check if we have sufficient buffer size */
  133. /* we leave a 4 instruction (8 bytes each) margin. */
  134. if ((handle->blockSize + 32) >= handle->bufferSize) {
  135. if (0 != cmdq_rec_realloc_cmd_buffer(handle, handle->bufferSize * 2))
  136. return -ENOMEM;
  137. }
  138. /* force insert MARKER if prefetch memory is full */
  139. /* GCE deadlocks if we don't do so */
  140. if (CMDQ_CODE_EOC != code && cmdq_core_should_enable_prefetch(handle->scenario)) {
  141. if (handle->prefetchCount >= CMDQ_MAX_PREFETCH_INSTUCTION) {
  142. CMDQ_MSG("prefetchCount(%d) > MAX_PREFETCH_INSTUCTION, force insert disable prefetch marker\n",
  143. handle->prefetchCount);
  144. /* Mark END of prefetch section */
  145. cmdqRecDisablePrefetch(handle);
  146. /* BEGING of next prefetch section */
  147. cmdqRecMark(handle);
  148. } else {
  149. /* prefetch enabled marker exist */
  150. if (1 <= handle->prefetchCount) {
  151. ++handle->prefetchCount;
  152. CMDQ_VERBOSE("handle->prefetchCount: %d, %s, %d\n",
  153. handle->prefetchCount, __func__, __LINE__);
  154. }
  155. }
  156. }
  157. /* we must re-calculate current PC because we may already insert MARKER inst. */
  158. pCommand = (uint32_t *) ((uint8_t *) handle->pBuffer + handle->blockSize);
  159. CMDQ_VERBOSE("REC: 0x%p CMD: 0x%p, op: 0x%02x, argA: 0x%08x, argB: 0x%08x\n", handle,
  160. pCommand, code, argA, argB);
  161. switch (code) {
  162. case CMDQ_CODE_READ:
  163. /* argA is the HW register address to read from */
  164. subsys = cmdq_subsys_from_phys_addr(argA);
  165. /* argB is the register id to read into */
  166. /* bit 54: argB type, 1 for GPR */
  167. *pCommand++ = argB;
  168. *pCommand++ =
  169. (CMDQ_CODE_READ << 24) | (argA & 0xffff) | ((subsys & 0x1f) << subsysBit) | (2
  170. <<
  171. 21);
  172. break;
  173. case CMDQ_CODE_MOVE:
  174. *pCommand++ = argB;
  175. *pCommand++ = CMDQ_CODE_MOVE << 24 | (argA & 0xffffff);
  176. break;
  177. case CMDQ_CODE_WRITE:
  178. subsys = cmdq_subsys_from_phys_addr(argA);
  179. if (-1 == subsys) {
  180. CMDQ_ERR("REC: Unsupported memory base address 0x%08x\n", argA);
  181. return -EFAULT;
  182. }
  183. *pCommand++ = argB;
  184. *pCommand++ =
  185. (CMDQ_CODE_WRITE << 24) | (argA & 0x0FFFF) | ((subsys & 0x01F) << subsysBit);
  186. break;
  187. case CMDQ_CODE_POLL:
  188. subsys = cmdq_subsys_from_phys_addr(argA);
  189. if (-1 == subsys) {
  190. CMDQ_ERR("REC: Unsupported memory base address 0x%08x\n", argA);
  191. return -EFAULT;
  192. }
  193. *pCommand++ = argB;
  194. *pCommand++ =
  195. (CMDQ_CODE_POLL << 24) | (argA & 0x0FFFF) | ((subsys & 0x01F) << subsysBit);
  196. break;
  197. case CMDQ_CODE_JUMP:
  198. *pCommand++ = argB;
  199. *pCommand++ = (CMDQ_CODE_JUMP << 24) | (argA & 0x0FFFFFF);
  200. break;
  201. case CMDQ_CODE_WFE:
  202. /* bit 0-11: wait_value, 1 */
  203. /* bit 15: to_wait, true */
  204. /* bit 31: to_update, true */
  205. /* bit 16-27: update_value, 0 */
  206. *pCommand++ = ((1 << 31) | (1 << 15) | 1);
  207. *pCommand++ = (CMDQ_CODE_WFE << 24) | argA;
  208. break;
  209. case CMDQ_CODE_SET_TOKEN:
  210. /* this is actually WFE(SYNC) but with different parameter */
  211. /* interpretation */
  212. /* bit 15: to_wait, false */
  213. /* bit 31: to_update, true */
  214. /* bit 16-27: update_value, 1 */
  215. *pCommand++ = ((1 << 31) | (1 << 16));
  216. *pCommand++ = (CMDQ_CODE_WFE << 24) | argA;
  217. break;
  218. case CMDQ_CODE_WAIT_NO_CLEAR:
  219. /* bit 0-11: wait_value, 1 */
  220. /* bit 15: to_wait, true */
  221. /* bit 31: to_update, false */
  222. *pCommand++ = ((0 << 31) | (1 << 15) | 1);
  223. *pCommand++ = (CMDQ_CODE_WFE << 24) | argA;
  224. break;
  225. case CMDQ_CODE_CLEAR_TOKEN:
  226. /* this is actually WFE(SYNC) but with different parameter */
  227. /* interpretation */
  228. /* bit 15: to_wait, false */
  229. /* bit 31: to_update, true */
  230. /* bit 16-27: update_value, 0 */
  231. *pCommand++ = ((1 << 31) | (0 << 16));
  232. *pCommand++ = (CMDQ_CODE_WFE << 24) | argA;
  233. break;
  234. case CMDQ_CODE_EOC:
  235. *pCommand++ = argB;
  236. *pCommand++ = (CMDQ_CODE_EOC << 24) | (argA & 0x0FFFFFF);
  237. break;
  238. case CMDQ_CODE_RAW:
  239. *pCommand++ = argB;
  240. *pCommand++ = argA;
  241. break;
  242. default:
  243. return -EFAULT;
  244. }
  245. handle->blockSize += CMDQ_INST_SIZE;
  246. return 0;
  247. }
  248. int32_t cmdqRecReset(cmdqRecHandle handle)
  249. {
  250. if (NULL == handle)
  251. return -EFAULT;
  252. if (NULL != handle->pRunningTask)
  253. cmdqRecStopLoop(handle);
  254. handle->blockSize = 0;
  255. handle->prefetchCount = 0;
  256. handle->finalized = false;
  257. /*reset secure path data */
  258. handle->secData.isSecure = false;
  259. handle->secData.enginesNeedDAPC = 0LL;
  260. handle->secData.enginesNeedPortSecurity = 0LL;
  261. if (handle->secData.addrMetadatas) {
  262. kfree(CMDQ_U32_PTR(handle->secData.addrMetadatas));
  263. handle->secData.addrMetadatas = (cmdqU32Ptr_t) (unsigned long)NULL;
  264. handle->secData.addrMetadataMaxCount = 0;
  265. handle->secData.addrMetadataCount = 0;
  266. }
  267. return 0;
  268. }
  269. int32_t cmdqRecSetSecure(cmdqRecHandle handle, const bool isSecure)
  270. {
  271. if (NULL == handle)
  272. return -EFAULT;
  273. if (false == isSecure) {
  274. handle->secData.isSecure = isSecure;
  275. return 0;
  276. }
  277. #ifdef CMDQ_SECURE_PATH_SUPPORT
  278. CMDQ_VERBOSE("REC: %p secure:%d\n", handle, isSecure);
  279. handle->secData.isSecure = isSecure;
  280. return 0;
  281. #else
  282. CMDQ_ERR("%s failed since not support secure path\n", __func__);
  283. return -EFAULT;
  284. #endif
  285. }
  286. #ifdef CMDQ_SECURE_PATH_SUPPORT
  287. int32_t cmdqRecSetSecureMode(cmdqRecHandle handle, enum CMDQ_DISP_MODE mode)
  288. {
  289. if (NULL == handle)
  290. return -EFAULT;
  291. handle->secData.secMode = mode;
  292. return 0;
  293. }
  294. #endif
  295. int32_t cmdqRecSecureEnableDAPC(cmdqRecHandle handle, const uint64_t engineFlag)
  296. {
  297. #ifdef CMDQ_SECURE_PATH_SUPPORT
  298. if (NULL == handle)
  299. return -EFAULT;
  300. handle->secData.enginesNeedDAPC |= engineFlag;
  301. return 0;
  302. #else
  303. CMDQ_ERR("%s failed since not support secure path\n", __func__);
  304. return -EFAULT;
  305. #endif
  306. }
  307. int32_t cmdqRecSecureEnablePortSecurity(cmdqRecHandle handle, const uint64_t engineFlag)
  308. {
  309. #ifdef CMDQ_SECURE_PATH_SUPPORT
  310. if (NULL == handle)
  311. return -EFAULT;
  312. handle->secData.enginesNeedPortSecurity |= engineFlag;
  313. return 0;
  314. #else
  315. CMDQ_ERR("%s failed since not support secure path\n", __func__);
  316. return -EFAULT;
  317. #endif
  318. }
  319. int32_t cmdqRecMark(cmdqRecHandle handle)
  320. {
  321. int32_t status;
  322. /* Do not check prefetch-ability here. */
  323. /* because cmdqRecMark may have other purposes. */
  324. /* bit 53: non-suspendable. set to 1 because we don't want */
  325. /* CPU suspend this thread during pre-fetching. */
  326. /* If CPU change PC, then there will be a mess, */
  327. /* because prefetch buffer is not properly cleared. */
  328. /* bit 48: do not increase CMD_COUNTER (because this is not the end of the task) */
  329. /* bit 20: prefetch_marker */
  330. /* bit 17: prefetch_marker_en */
  331. /* bit 16: prefetch_en */
  332. /* bit 0: irq_en (set to 0 since we don't want EOC interrupt) */
  333. status =
  334. cmdq_append_command(handle, CMDQ_CODE_EOC, (0x1 << (53 - 32)) | (0x1 << (48 - 32)),
  335. 0x00130000);
  336. /* if we're in a prefetch region, */
  337. /* this ends the region so set count to 0. */
  338. /* otherwise we start the region by setting count to 1. */
  339. handle->prefetchCount = 1;
  340. if (0 != status)
  341. return -EFAULT;
  342. return 0;
  343. }
  344. int32_t cmdqRecWrite(cmdqRecHandle handle, uint32_t addr, uint32_t value, uint32_t mask)
  345. {
  346. int32_t status;
  347. if (0xFFFFFFFF != mask) {
  348. status = cmdq_append_command(handle, CMDQ_CODE_MOVE, 0, ~mask);
  349. if (0 != status)
  350. return status;
  351. addr = addr | 0x1;
  352. }
  353. status = cmdq_append_command(handle, CMDQ_CODE_WRITE, addr, value);
  354. if (0 != status)
  355. return status;
  356. return 0;
  357. }
  358. int32_t cmdqRecWriteSecure(cmdqRecHandle handle, uint32_t addr,
  359. CMDQ_SEC_ADDR_METADATA_TYPE type,
  360. uint32_t baseHandle, uint32_t offset, uint32_t size, uint32_t port)
  361. {
  362. #ifdef CMDQ_SECURE_PATH_SUPPORT
  363. int32_t status;
  364. int32_t writeInstrIndex;
  365. cmdqSecAddrMetadataStruct metadata;
  366. const uint32_t mask = 0xFFFFFFFF;
  367. /* append command */
  368. status = cmdqRecWrite(handle, addr, baseHandle, mask);
  369. if (0 != status)
  370. return status;
  371. /* append to metadata list */
  372. writeInstrIndex = (handle->blockSize) / CMDQ_INST_SIZE - 1; /* start from 0 */
  373. memset(&metadata, 0, sizeof(cmdqSecAddrMetadataStruct));
  374. metadata.instrIndex = writeInstrIndex;
  375. metadata.type = type;
  376. metadata.baseHandle = baseHandle;
  377. metadata.offset = offset;
  378. metadata.size = size;
  379. metadata.port = port;
  380. status = cmdq_append_addr_metadata(handle, &metadata);
  381. return 0;
  382. #else
  383. CMDQ_ERR("%s failed since not support secure path\n", __func__);
  384. return -EFAULT;
  385. #endif
  386. }
  387. int32_t cmdqRecWriteSecureMask(cmdqRecHandle handle, uint32_t addr,
  388. CMDQ_SEC_ADDR_METADATA_TYPE type, uint32_t value, uint32_t mask)
  389. {
  390. #ifdef CMDQ_SECURE_PATH_SUPPORT
  391. int32_t status;
  392. int32_t writeInstrIndex;
  393. cmdqSecAddrMetadataStruct metadata;
  394. /* const uint32_t mask = 0xFFFFFFFF; */
  395. /* append command */
  396. status = cmdqRecWrite(handle, addr, value, mask);
  397. if (0 != status)
  398. return status;
  399. /* append to metadata list */
  400. writeInstrIndex = (handle->blockSize) / CMDQ_INST_SIZE - 1; /* start from 0 */
  401. memset(&metadata, 0, sizeof(cmdqSecAddrMetadataStruct));
  402. metadata.instrIndex = writeInstrIndex;
  403. metadata.type = type;
  404. metadata.baseHandle = value;
  405. metadata.offset = mask;
  406. status = cmdq_append_addr_metadata(handle, &metadata);
  407. return 0;
  408. #else
  409. CMDQ_ERR("%s failed since not support secure path\n", __func__);
  410. return -EFAULT;
  411. #endif
  412. }
  413. int32_t cmdqRecPoll(cmdqRecHandle handle, uint32_t addr, uint32_t value, uint32_t mask)
  414. {
  415. int32_t status;
  416. status = cmdq_append_command(handle, CMDQ_CODE_MOVE, 0, ~mask);
  417. if (0 != status)
  418. return status;
  419. status = cmdq_append_command(handle, CMDQ_CODE_POLL, (addr | 0x1), value);
  420. if (0 != status)
  421. return status;
  422. return 0;
  423. }
  424. int32_t cmdqRecWait(cmdqRecHandle handle, enum CMDQ_EVENT_ENUM event)
  425. {
  426. if (CMDQ_SYNC_TOKEN_INVALID == event || CMDQ_SYNC_TOKEN_MAX <= event || 0 > event)
  427. return -EINVAL;
  428. return cmdq_append_command(handle, CMDQ_CODE_WFE, event, 0);
  429. }
  430. int32_t cmdqRecWaitNoClear(cmdqRecHandle handle, enum CMDQ_EVENT_ENUM event)
  431. {
  432. if (CMDQ_SYNC_TOKEN_INVALID == event || CMDQ_SYNC_TOKEN_MAX <= event || 0 > event)
  433. return -EINVAL;
  434. return cmdq_append_command(handle, CMDQ_CODE_WAIT_NO_CLEAR, event, 0);
  435. }
  436. int32_t cmdqRecClearEventToken(cmdqRecHandle handle, enum CMDQ_EVENT_ENUM event)
  437. {
  438. if (CMDQ_SYNC_TOKEN_INVALID == event || CMDQ_SYNC_TOKEN_MAX <= event || 0 > event)
  439. return -EINVAL;
  440. return cmdq_append_command(handle, CMDQ_CODE_CLEAR_TOKEN, event, 1 /* actually this param is ignored. */
  441. );
  442. }
  443. int32_t cmdqRecSetEventToken(cmdqRecHandle handle, enum CMDQ_EVENT_ENUM event)
  444. {
  445. if (CMDQ_SYNC_TOKEN_INVALID == event || CMDQ_SYNC_TOKEN_MAX <= event || 0 > event)
  446. return -EINVAL;
  447. return cmdq_append_command(handle, CMDQ_CODE_SET_TOKEN, event, 1 /* actually this param is ignored. */
  448. );
  449. }
  450. int32_t cmdqRecReadToDataRegister(cmdqRecHandle handle, uint32_t hwRegAddr,
  451. enum CMDQ_DATA_REGISTER_ENUM dstDataReg)
  452. {
  453. #ifdef CMDQ_GPR_SUPPORT
  454. /* read from hwRegAddr(argA) to dstDataReg(argB) */
  455. return cmdq_append_command(handle, CMDQ_CODE_READ, hwRegAddr, dstDataReg);
  456. #else
  457. CMDQ_ERR("func:%s failed since CMDQ doesn't support GPR\n", __func__);
  458. return -EFAULT;
  459. #endif
  460. }
  461. int32_t cmdqRecWriteFromDataRegister(cmdqRecHandle handle,
  462. enum CMDQ_DATA_REGISTER_ENUM srcDataReg, uint32_t hwRegAddr)
  463. {
  464. #ifdef CMDQ_GPR_SUPPORT
  465. const uint32_t subsys = cmdq_subsys_from_phys_addr(hwRegAddr);
  466. const uint32_t subsysBit = cmdq_core_get_subsys_LSB_in_argA();
  467. /* write HW register(argA) with data of GPR data register(argB) */
  468. return cmdq_append_command(handle,
  469. CMDQ_CODE_RAW,
  470. ((CMDQ_CODE_WRITE << 24) | (hwRegAddr & 0x0FFFF) |
  471. ((subsys & 0x01F) << subsysBit) | (2 << 21)), srcDataReg);
  472. #else
  473. CMDQ_ERR("func:%s failed since CMDQ doesn't support GPR\n", __func__);
  474. return -EFAULT;
  475. #endif /* CMDQ_GPR_SUPPORT */
  476. }
  477. /**
  478. * Allocate 32-bit register backup slot
  479. *
  480. */
  481. int32_t cmdqBackupAllocateSlot(cmdqBackupSlotHandle *phBackupSlot, uint32_t slotCount)
  482. {
  483. #ifdef CMDQ_GPR_SUPPORT
  484. dma_addr_t paStart = 0;
  485. int status = 0;
  486. if (NULL == phBackupSlot)
  487. return -EINVAL;
  488. status = cmdqCoreAllocWriteAddress(slotCount, &paStart);
  489. *phBackupSlot = paStart;
  490. return status;
  491. #else
  492. CMDQ_ERR("func:%s failed since CMDQ doesn't support GPR\n", __func__);
  493. return -EFAULT;
  494. #endif /* CMDQ_GPR_SUPPORT */
  495. }
  496. /**
  497. * Read 32-bit register backup slot by index
  498. *
  499. */
  500. int32_t cmdqBackupReadSlot(cmdqBackupSlotHandle hBackupSlot, uint32_t slotIndex, uint32_t *value)
  501. {
  502. #ifdef CMDQ_GPR_SUPPORT
  503. if (NULL == value)
  504. return -EINVAL;
  505. if (0 == hBackupSlot) {
  506. CMDQ_ERR("%s, hBackupSlot is NULL\n", __func__);
  507. return -EINVAL;
  508. }
  509. *value = cmdqCoreReadWriteAddress(hBackupSlot + slotIndex * sizeof(uint32_t));
  510. return 0;
  511. #else
  512. CMDQ_ERR("func:%s failed since CMDQ doesn't support GPR\n", __func__);
  513. return -EFAULT;
  514. #endif /* CMDQ_GPR_SUPPORT */
  515. }
  516. int32_t cmdqBackupWriteSlot(cmdqBackupSlotHandle hBackupSlot, uint32_t slotIndex, uint32_t value)
  517. {
  518. #ifdef CMDQ_GPR_SUPPORT
  519. int status = 0;
  520. /* set the slot value directly */
  521. status = cmdqCoreWriteWriteAddress(hBackupSlot + slotIndex * sizeof(uint32_t), value);
  522. return status;
  523. #else
  524. CMDQ_ERR("func:%s failed since CMDQ doesn't support GPR\n", __func__);
  525. return -EFAULT;
  526. #endif /* CMDQ_GPR_SUPPORT */
  527. }
  528. /**
  529. * Free allocated backup slot. DO NOT free them before corresponding
  530. * task finishes. Becareful on AsyncFlush use cases.
  531. *
  532. */
  533. int32_t cmdqBackupFreeSlot(cmdqBackupSlotHandle hBackupSlot)
  534. {
  535. #ifdef CMDQ_GPR_SUPPORT
  536. return cmdqCoreFreeWriteAddress(hBackupSlot);
  537. #else
  538. CMDQ_ERR("func:%s failed since CMDQ doesn't support GPR\n", __func__);
  539. return -EFAULT;
  540. #endif /* CMDQ_GPR_SUPPORT */
  541. }
  542. /**
  543. * Insert instructions to backup given 32-bit HW register
  544. * to a backup slot.
  545. * You can use cmdqBackupReadSlot() to retrieve the result
  546. * AFTER cmdqRecFlush() returns, or INSIDE the callback of cmdqRecFlushAsyncCallback().
  547. *
  548. */
  549. int32_t cmdqRecBackupRegisterToSlot(cmdqRecHandle handle,
  550. cmdqBackupSlotHandle hBackupSlot,
  551. uint32_t slotIndex, uint32_t regAddr)
  552. {
  553. #ifdef CMDQ_GPR_SUPPORT
  554. const enum CMDQ_DATA_REGISTER_ENUM valueRegId = CMDQ_DATA_REG_DEBUG;
  555. const enum CMDQ_DATA_REGISTER_ENUM destRegId = CMDQ_DATA_REG_DEBUG_DST;
  556. const enum CMDQ_EVENT_ENUM regAccessToken = CMDQ_SYNC_TOKEN_GPR_SET_4;
  557. const dma_addr_t dramAddr = hBackupSlot + slotIndex * sizeof(uint32_t);
  558. /* lock GPR because we may access it in multiple CMDQ HW threads */
  559. cmdqRecWait(handle, regAccessToken);
  560. /* Load into 32-bit GPR (R0-R15) */
  561. cmdq_append_command(handle, CMDQ_CODE_READ, regAddr, valueRegId);
  562. /* Note that <MOVE> argB is 48-bit */
  563. /* so writeAddress is split into 2 parts */
  564. /* and we store address in 64-bit GPR (P0-P7) */
  565. cmdq_append_command(handle, CMDQ_CODE_MOVE,
  566. #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
  567. ((dramAddr >> 32) & 0xffff) |
  568. #endif
  569. ((destRegId & 0x1f) << 16) | (4 << 21), (uint32_t) dramAddr);
  570. /* write value in GPR to memory pointed by GPR */
  571. cmdq_append_command(handle,
  572. CMDQ_CODE_RAW,
  573. (CMDQ_CODE_WRITE << 24) | (0 & 0xffff) | ((destRegId & 0x1f) << 16) | (6
  574. <<
  575. 21),
  576. valueRegId);
  577. /* release the GPR lock */
  578. cmdqRecSetEventToken(handle, regAccessToken);
  579. return 0;
  580. #else
  581. CMDQ_ERR("func:%s failed since CMDQ doesn't support GPR\n", __func__);
  582. return -EFAULT;
  583. #endif /* CMDQ_GPR_SUPPORT */
  584. }
  585. int32_t cmdqRecBackupWriteRegisterFromSlot(cmdqRecHandle handle,
  586. cmdqBackupSlotHandle hBackupSlot,
  587. uint32_t slotIndex, uint32_t addr)
  588. {
  589. #ifdef CMDQ_GPR_SUPPORT
  590. const enum CMDQ_DATA_REGISTER_ENUM valueRegId = CMDQ_DATA_REG_DEBUG;
  591. const enum CMDQ_DATA_REGISTER_ENUM addrRegId = CMDQ_DATA_REG_DEBUG_DST;
  592. const enum CMDQ_EVENT_ENUM regAccessToken = CMDQ_SYNC_TOKEN_GPR_SET_4;
  593. const dma_addr_t dramAddr = hBackupSlot + slotIndex * sizeof(uint32_t);
  594. /* const uint32_t subsysBit = cmdq_core_get_subsys_LSB_in_argA(); */
  595. /* lock GPR because we may access it in multiple CMDQ HW threads */
  596. cmdqRecWait(handle, regAccessToken);
  597. /* 1. MOVE slot address to addr GPR */
  598. /* Note that <MOVE> argB is 48-bit */
  599. /* so writeAddress is split into 2 parts */
  600. /* and we store address in 64-bit GPR (P0-P7) */
  601. cmdq_append_command(handle, CMDQ_CODE_MOVE,
  602. #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
  603. ((dramAddr >> 32) & 0xffff) |
  604. #endif
  605. ((addrRegId & 0x1f) << 16) | (4 << 21), (uint32_t) dramAddr); /* argA is GPR */
  606. /* 2. read value from src address, which is stroed in GPR, to valueRegId */
  607. cmdq_append_command(handle, CMDQ_CODE_RAW,
  608. (CMDQ_CODE_READ << 24) | (0 & 0xffff) | ((addrRegId & 0x1f) << 16) | (6
  609. <<
  610. 21),
  611. valueRegId);
  612. /* 3. write from data register */
  613. cmdqRecWriteFromDataRegister(handle, valueRegId, addr);
  614. /* release the GPR lock */
  615. cmdqRecSetEventToken(handle, regAccessToken);
  616. return 0;
  617. #else
  618. CMDQ_ERR("func:%s failed since CMDQ doesn't support GPR\n", __func__);
  619. return -EFAULT;
  620. #endif /* CMDQ_GPR_SUPPORT */
  621. }
  622. /*copy value to dma memory pointed by hBackupSlot:slotIndex*/
  623. int32_t cmdqRecBackupUpdateSlot(cmdqRecHandle handle,
  624. cmdqBackupSlotHandle hBackupSlot,
  625. uint32_t slotIndex, uint32_t value)
  626. {
  627. #ifdef CMDQ_GPR_SUPPORT
  628. const enum CMDQ_DATA_REGISTER_ENUM valueRegId = CMDQ_DATA_REG_DEBUG;
  629. const enum CMDQ_DATA_REGISTER_ENUM destRegId = CMDQ_DATA_REG_DEBUG_DST;
  630. const enum CMDQ_EVENT_ENUM regAccessToken = CMDQ_SYNC_TOKEN_GPR_SET_4;
  631. const dma_addr_t dramAddr = hBackupSlot + slotIndex * sizeof(uint32_t);
  632. /* lock GPR because we may access it in multiple CMDQ HW threads */
  633. cmdqRecWait(handle, regAccessToken);
  634. /* Assign 32-bit GRP with value */
  635. /* argA is GPR */
  636. cmdq_append_command(handle, CMDQ_CODE_RAW,
  637. (CMDQ_CODE_MOVE << 24) | (valueRegId << 16) | (4 << 21), value);
  638. /* Note that <MOVE> argB is 48-bit */
  639. /* so writeAddress is split into 2 parts */
  640. /* and we store address in 64-bit GPR (P0-P7) */
  641. cmdq_append_command(handle, CMDQ_CODE_MOVE,
  642. #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
  643. ((dramAddr >> 32) & 0xffff) |
  644. #endif
  645. ((destRegId & 0x1f) << 16) | (4 << 21), (uint32_t) dramAddr);
  646. /* write value in GPR to memory pointed by GPR */
  647. cmdq_append_command(handle,
  648. CMDQ_CODE_RAW,
  649. (CMDQ_CODE_WRITE << 24) | (0 & 0xffff) | ((destRegId & 0x1f) << 16) | (6
  650. <<
  651. 21),
  652. valueRegId);
  653. /* release the GPR lock */
  654. cmdqRecSetEventToken(handle, regAccessToken);
  655. return 0;
  656. #else
  657. CMDQ_ERR("func:%s failed since CMDQ doesn't support GPR\n", __func__);
  658. return -EFAULT;
  659. #endif /* CMDQ_GPR_SUPPORT */
  660. }
  661. int32_t cmdqRecEnablePrefetch(cmdqRecHandle handle)
  662. {
  663. #if 1/* #ifdef _CMDQ_DISABLE_MARKER_ */
  664. /* disable pre-fetch marker feature but use auto prefetch mechanism */
  665. CMDQ_MSG("not allow enable prefetch, scenario: %d\n", handle->scenario);
  666. return true;
  667. #else
  668. if (cmdq_core_should_enable_prefetch(handle->scenario)) {
  669. /* enable prefetch */
  670. CMDQ_VERBOSE("REC: enable prefetch\n");
  671. cmdqRecMark(handle);
  672. return true;
  673. }
  674. CMDQ_MSG("not allow enable prefetch, scenario: %d\n", handle->scenario);
  675. return -EFAULT;
  676. #endif
  677. }
  678. int32_t cmdqRecDisablePrefetch(cmdqRecHandle handle)
  679. {
  680. uint32_t argB = 0;
  681. uint32_t argA = 0;
  682. int32_t status = 0;
  683. if (!handle->finalized) {
  684. if (handle->prefetchCount > 0) {
  685. /* with prefetch threads we should end with */
  686. /* bit 48: no_inc_exec_cmds_cnt = 1 */
  687. /* bit 20: prefetch_mark = 1 */
  688. /* bit 17: prefetch_mark_en = 0 */
  689. /* bit 16: prefetch_en = 0 */
  690. argB = 0x00100000;
  691. argA = (0x1 << 16); /* not increse execute counter */
  692. /* since we're finalized, no more prefetch */
  693. handle->prefetchCount = 0;
  694. status = cmdq_append_command(handle, CMDQ_CODE_EOC, argA, argB);
  695. }
  696. if (0 != status)
  697. return status;
  698. }
  699. CMDQ_MSG("cmdqRecDisablePrefetch, status:%d\n", status);
  700. return status;
  701. }
  702. int32_t cmdq_rec_finalize_command(cmdqRecHandle handle, bool loop)
  703. {
  704. int32_t status = 0;
  705. uint32_t argB = 0;
  706. if (NULL == handle)
  707. return -EFAULT;
  708. if (!handle->finalized) {
  709. if ((handle->prefetchCount > 0) && cmdq_core_should_enable_prefetch(handle->scenario)) {
  710. CMDQ_ERR
  711. ("not insert prefetch disble marker when prefetch enabled, prefetchCount:%d\n",
  712. handle->prefetchCount);
  713. cmdqRecDumpCommand(handle);
  714. status = -EFAULT;
  715. return status;
  716. }
  717. /* insert EOF instruction */
  718. argB = 0x1; /* generate IRQ for each command iteration */
  719. status = cmdq_append_command(handle, CMDQ_CODE_EOC, 0, argB);
  720. if (0 != status)
  721. return status;
  722. /* insert JUMP to loop to beginning or as a scheduling mark(8) */
  723. status = cmdq_append_command(handle, CMDQ_CODE_JUMP, 0, /* not absolute */
  724. loop ? -handle->blockSize : 8);
  725. if (0 != status)
  726. return status;
  727. handle->finalized = true;
  728. }
  729. return status;
  730. }
  731. int32_t cmdq_rec_setup_sec_data_of_command_desc_by_rec_handle(struct cmdqCommandStruct *pDesc,
  732. cmdqRecHandle handle)
  733. {
  734. /* fill field from user's request */
  735. pDesc->secData.isSecure = handle->secData.isSecure;
  736. pDesc->secData.enginesNeedDAPC = handle->secData.enginesNeedDAPC;
  737. pDesc->secData.enginesNeedPortSecurity = handle->secData.enginesNeedPortSecurity;
  738. pDesc->secData.addrMetadataCount = handle->secData.addrMetadataCount;
  739. pDesc->secData.addrMetadatas = handle->secData.addrMetadatas;
  740. pDesc->secData.addrMetadataMaxCount = handle->secData.addrMetadataMaxCount;
  741. #ifdef CMDQ_SECURE_PATH_SUPPORT
  742. pDesc->secData.secMode = handle->secData.secMode;
  743. #endif
  744. /* init reserved field */
  745. pDesc->secData.resetExecCnt = false;
  746. pDesc->secData.waitCookie = 0;
  747. return 0;
  748. }
  749. int32_t cmdqRecFlush(cmdqRecHandle handle)
  750. {
  751. int32_t status;
  752. struct cmdqCommandStruct desc = { 0 };
  753. status = cmdq_rec_finalize_command(handle, false);
  754. if (status < 0)
  755. return status;
  756. CMDQ_MSG("Submit task scenario: %d, priority: %d, engine: 0x%llx, buffer: 0x%p, size: %d\n",
  757. handle->scenario, handle->priority, handle->engineFlag, handle->pBuffer,
  758. handle->blockSize);
  759. desc.scenario = handle->scenario;
  760. desc.priority = handle->priority;
  761. desc.engineFlag = handle->engineFlag;
  762. desc.pVABase = (cmdqU32Ptr_t) (unsigned long)handle->pBuffer;
  763. desc.blockSize = handle->blockSize;
  764. cmdq_rec_setup_sec_data_of_command_desc_by_rec_handle(&desc, handle); /* secure path */
  765. return cmdqCoreSubmitTask(&desc);
  766. }
  767. int32_t cmdqRecFlushAndReadRegister(cmdqRecHandle handle, uint32_t regCount, uint32_t *addrArray,
  768. uint32_t *valueArray)
  769. {
  770. int32_t status;
  771. struct cmdqCommandStruct desc = { 0 };
  772. status = cmdq_rec_finalize_command(handle, false);
  773. if (status < 0)
  774. return status;
  775. CMDQ_MSG("Submit task scenario: %d, priority: %d, engine: 0x%llx, buffer: 0x%p, size: %d\n",
  776. handle->scenario, handle->priority, handle->engineFlag, handle->pBuffer,
  777. handle->blockSize);
  778. desc.scenario = handle->scenario;
  779. desc.priority = handle->priority;
  780. desc.engineFlag = handle->engineFlag;
  781. desc.pVABase = (cmdqU32Ptr_t) (unsigned long)handle->pBuffer;
  782. desc.blockSize = handle->blockSize;
  783. desc.regRequest.count = regCount;
  784. desc.regRequest.regAddresses = (cmdqU32Ptr_t) (unsigned long)addrArray;
  785. desc.regValue.count = regCount;
  786. desc.regValue.regValues = (cmdqU32Ptr_t) (unsigned long)valueArray;
  787. cmdq_rec_setup_sec_data_of_command_desc_by_rec_handle(&desc, handle); /* secure path */
  788. return cmdqCoreSubmitTask(&desc);
  789. }
  790. int32_t cmdqRecFlushAsync(cmdqRecHandle handle)
  791. {
  792. int32_t status = 0;
  793. struct cmdqCommandStruct desc = { 0 };
  794. struct TaskStruct *pTask = NULL;
  795. status = cmdq_rec_finalize_command(handle, false);
  796. if (status < 0)
  797. return status;
  798. desc.scenario = handle->scenario;
  799. desc.priority = handle->priority;
  800. desc.engineFlag = handle->engineFlag;
  801. desc.pVABase = (cmdqU32Ptr_t) (unsigned long)handle->pBuffer;
  802. desc.blockSize = handle->blockSize;
  803. desc.regRequest.count = 0;
  804. desc.regRequest.regAddresses = (cmdqU32Ptr_t) (unsigned long)NULL;
  805. desc.regValue.count = 0;
  806. desc.regValue.regValues = (cmdqU32Ptr_t) (unsigned long)NULL;
  807. cmdq_rec_setup_sec_data_of_command_desc_by_rec_handle(&desc, handle); /* secure path */
  808. status = cmdqCoreSubmitTaskAsync(&desc, NULL, 0, &pTask);
  809. CMDQ_MSG
  810. ("[Auto Release] Submit ASYNC task scenario: %d, priority: %d, engine: 0x%llx, buffer: 0x%p, size: %d\n",
  811. handle->scenario, handle->priority, handle->engineFlag, handle->pBuffer,
  812. handle->blockSize);
  813. if (pTask) {
  814. pTask->flushCallback = NULL;
  815. pTask->flushData = 0;
  816. }
  817. /* insert the task into auto-release queue */
  818. if (pTask)
  819. status = cmdqCoreAutoReleaseTask(pTask);
  820. else
  821. status = -ENOMEM;
  822. return status;
  823. }
  824. int32_t cmdqRecFlushAsyncCallback(cmdqRecHandle handle, CmdqAsyncFlushCB callback,
  825. uint32_t userData)
  826. {
  827. int32_t status = 0;
  828. struct cmdqCommandStruct desc = { 0 };
  829. struct TaskStruct *pTask = NULL;
  830. status = cmdq_rec_finalize_command(handle, false);
  831. if (status < 0)
  832. return status;
  833. desc.scenario = handle->scenario;
  834. desc.priority = handle->priority;
  835. desc.engineFlag = handle->engineFlag;
  836. desc.pVABase = (cmdqU32Ptr_t) (unsigned long)handle->pBuffer;
  837. desc.blockSize = handle->blockSize;
  838. desc.regRequest.count = 0;
  839. desc.regRequest.regAddresses = (cmdqU32Ptr_t) (unsigned long)NULL;
  840. desc.regValue.count = 0;
  841. desc.regValue.regValues = (cmdqU32Ptr_t) (unsigned long)NULL;
  842. cmdq_rec_setup_sec_data_of_command_desc_by_rec_handle(&desc, handle); /* secure path */
  843. status = cmdqCoreSubmitTaskAsync(&desc, NULL, 0, &pTask);
  844. /* insert the callback here. */
  845. /* note that, the task may be already completed at this point. */
  846. if (pTask) {
  847. pTask->flushCallback = callback;
  848. pTask->flushData = userData;
  849. }
  850. CMDQ_MSG
  851. ("[Auto Release] Submit ASYNC task scenario: %d, priority: %d, engine: 0x%llx, buffer: 0x%p, size: %d\n",
  852. handle->scenario, handle->priority, handle->engineFlag, handle->pBuffer,
  853. handle->blockSize);
  854. /* insert the task into auto-release queue */
  855. if (pTask)
  856. status = cmdqCoreAutoReleaseTask(pTask);
  857. else
  858. status = -ENOMEM;
  859. return status;
  860. }
  861. static int32_t cmdqRecIRQCallback(unsigned long data)
  862. {
  863. return 0;
  864. }
  865. int32_t cmdqRecStartLoop(cmdqRecHandle handle)
  866. {
  867. int32_t status = 0;
  868. struct cmdqCommandStruct desc = { 0 };
  869. if (NULL == handle)
  870. return -EFAULT;
  871. if (NULL != handle->pRunningTask)
  872. return -EBUSY;
  873. status = cmdq_rec_finalize_command(handle, true);
  874. if (status < 0)
  875. return status;
  876. /*line over 120 characters,so devide to two statments */
  877. CMDQ_MSG
  878. ("Submit task loop: scenario: %d, priority: %d, engine: 0x%llx, buffer: 0x%p,",
  879. handle->scenario, handle->priority, handle->engineFlag, handle->pBuffer);
  880. CMDQ_MSG
  881. (" size: %d, callback: 0x%p, data: %d\n", handle->blockSize, &cmdqRecIRQCallback, 0);
  882. desc.scenario = handle->scenario;
  883. desc.priority = handle->priority;
  884. desc.engineFlag = handle->engineFlag;
  885. desc.pVABase = (cmdqU32Ptr_t) (unsigned long)handle->pBuffer;
  886. desc.blockSize = handle->blockSize;
  887. cmdq_rec_setup_sec_data_of_command_desc_by_rec_handle(&desc, handle); /* secure path */
  888. status = cmdqCoreSubmitTaskAsync(&desc, &cmdqRecIRQCallback, 0, &handle->pRunningTask);
  889. return status;
  890. }
  891. int32_t cmdqRecStopLoop(cmdqRecHandle handle)
  892. {
  893. int32_t status = 0;
  894. struct TaskStruct *pTask = handle->pRunningTask;
  895. if (NULL == handle)
  896. return -EFAULT;
  897. if (NULL == pTask)
  898. return -EFAULT;
  899. status = cmdqCoreReleaseTask(pTask);
  900. handle->pRunningTask = NULL;
  901. return status;
  902. }
  903. int32_t cmdqRecGetInstructionCount(cmdqRecHandle handle)
  904. {
  905. if (NULL == handle)
  906. return 0;
  907. return handle->blockSize / CMDQ_INST_SIZE;
  908. }
  909. int32_t cmdqRecDumpCommand(cmdqRecHandle handle)
  910. {
  911. int32_t status = 0;
  912. struct TaskStruct *pTask = handle->pRunningTask;
  913. if (NULL == handle)
  914. return -EFAULT;
  915. if (pTask) {
  916. /* running, so dump from core task direct */
  917. status = cmdqCoreDebugDumpCommand(pTask);
  918. } else {
  919. /* not running, dump from rec->pBuffer */
  920. const uint32_t *pCmd = NULL;
  921. static char textBuf[128] = { 0 };
  922. int i = 0;
  923. CMDQ_LOG("======REC 0x%p command buffer:\n", handle->pBuffer);
  924. print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 4,
  925. handle->pBuffer, handle->blockSize, false);
  926. CMDQ_LOG("======REC 0x%p command buffer END\n", handle->pBuffer);
  927. CMDQ_LOG("REC 0x%p command buffer TRANSLATED:\n", handle->pBuffer);
  928. for (i = 0, pCmd = handle->pBuffer; i < handle->blockSize; i += 8, pCmd += 2) {
  929. cmdq_core_parse_instruction(pCmd, textBuf, 128);
  930. CMDQ_LOG("%s", textBuf);
  931. }
  932. CMDQ_LOG("======REC 0x%p command END\n", handle->pBuffer);
  933. return 0;
  934. }
  935. return status;
  936. }
  937. void cmdqRecDestroy(cmdqRecHandle handle)
  938. {
  939. if (NULL == handle)
  940. return;
  941. if (NULL != handle->pRunningTask)
  942. cmdqRecStopLoop(handle);
  943. /* Free command buffer */
  944. kfree(handle->pBuffer);
  945. handle->pBuffer = NULL;
  946. /* Free command handle */
  947. kfree(handle);
  948. }
  949. #include <linux/delay.h>
  950. int32_t cmdqRecWaitThreadIdleWithTimeout(int threadID, unsigned int retryCount)
  951. {
  952. int count = 0;
  953. int idle = 0;
  954. int threadIsRunning = 0;
  955. uint32_t currentThreadData = 0;
  956. struct ThreadStruct *pThread = NULL;
  957. CMDQ_LOG("func|cmdqRecWaitThreadIdleWithTimeout\n");
  958. /*
  959. ** disp thread 0 ~ 4
  960. ** for secure thread 12/13
  961. */
  962. if ((0 > threadID || 4 < threadID) && (12 != threadID) && (13 != threadID)) {
  963. CMDQ_ERR("invalid theadID[%d]\n", threadID);
  964. return -1;
  965. }
  966. pThread = cmdq_core_getThreadStruct(threadID);
  967. if (12 != threadID && 13 != threadID) {
  968. /*for normal thread*/
  969. while (count < retryCount) {
  970. currentThreadData = CMDQ_REG_GET32(CMDQ_CURR_LOADED_THR);
  971. if (currentThreadData & 0x8000)
  972. threadIsRunning = ((currentThreadData & 0x00FF) == (1 << threadID));
  973. else
  974. threadIsRunning = 0;
  975. idle = (!threadIsRunning &&
  976. (CMDQ_REG_GET32(CMDQ_THR_CURR_ADDR(threadID)) ==
  977. CMDQ_REG_GET32(CMDQ_THR_END_ADDR(threadID)))) &&
  978. pThread->taskCount == 0;
  979. if (idle)
  980. break;
  981. udelay(1000);
  982. count++;
  983. }
  984. } else {
  985. /*for secure thread*/
  986. while (count < retryCount) {
  987. idle = (pThread->taskCount == 0);
  988. if (idle)
  989. break;
  990. udelay(1000);
  991. count++;
  992. }
  993. }
  994. if (count > 0 && count < retryCount)
  995. CMDQ_LOG("check hw thread[%d] idle count[%d]\n", threadID, count);
  996. else if (count >= retryCount) {
  997. CMDQ_LOG("check hw thread[%d] idle timeout[%d]\n", threadID, count);
  998. CMDQ_LOG("current load thread = %x status = %x CURR_ADDR = 0x%08x END_ADDR = 0x%08x task count[%d]\n",
  999. CMDQ_REG_GET32(CMDQ_CURR_LOADED_THR),
  1000. (CMDQ_REG_GET32(CMDQ_THR_CURR_STATUS(threadID))),
  1001. CMDQ_REG_GET32(CMDQ_THR_CURR_ADDR(threadID)),
  1002. CMDQ_REG_GET32(CMDQ_THR_END_ADDR(threadID)),
  1003. pThread->taskCount);
  1004. }
  1005. CMDQ_LOG("func|cmdqRecWaitThreadIdleWithTimeout done\n");
  1006. return 0;
  1007. }