1 /**********************************************************************
3 * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful but, except
10 * as otherwise stated in writing, without any warranty; without even the
11 * implied warranty of merchantability or fitness for a particular purpose.
12 * See the GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
21 * Contact Information:
22 * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23 * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
25 ******************************************************************************/
28 #include "services_headers.h"
30 #include "sgxinfokm.h"
32 #include "sgxapi_km.h"
33 #include "pvr_pdump.h"
35 #include "sgx_bridge_km.h"
37 #include "pvr_debug.h"
40 #include "pvr_trace_cmd.h"
42 enum PVRSRV_ERROR SGXDoKickKM(void *hDevHandle, struct SGX_CCB_KICK *psCCBKick,
43 struct PVRSRV_PER_PROCESS_DATA *proc)
45 enum PVRSRV_ERROR eError;
46 struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
47 struct PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo =
48 (struct PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hCCBKernelMemInfo;
49 struct SGXMKIF_CMDTA_SHARED *psTACmd;
51 struct PVRSRV_DEVICE_NODE *psDeviceNode;
52 struct PVRSRV_SGXDEV_INFO *psDevInfo;
53 struct pvr_trcmd_sgxkick *ktrace;
56 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevHandle;
57 psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
59 if (psCCBKick->bKickRender)
60 ++psDevInfo->ui32KickTARenderCounter;
61 ++psDevInfo->ui32KickTACounter;
63 if (!CCB_OFFSET_IS_VALID
64 (struct SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick,
66 PVR_DPF(PVR_DBG_ERROR, "SGXDoKickKM: Invalid CCB offset");
67 return PVRSRV_ERROR_INVALID_PARAMS;
70 CCB_DATA_FROM_OFFSET(struct SGXMKIF_CMDTA_SHARED, psCCBMemInfo,
71 psCCBKick, ui32CCBOffset);
73 trcmd_type = psCCBKick->bFirstKickOrResume ?
74 PVR_TRCMD_SGX_FIRSTKICK : PVR_TRCMD_SGX_KICK;
76 ktrace = pvr_trcmd_alloc(trcmd_type, proc->ui32PID, proc->name,
79 if (psCCBKick->hTA3DSyncInfo) {
81 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
82 psTACmd->sTA3DDependency.sWriteOpsCompleteDevVAddr =
83 psSyncInfo->sWriteOpsCompleteDevVAddr;
85 psTACmd->sTA3DDependency.ui32WriteOpsPendingVal =
86 psSyncInfo->psSyncData->ui32WriteOpsPending;
88 if (psCCBKick->bTADependency)
89 psSyncInfo->psSyncData->ui32WriteOpsPending++;
91 pvr_trcmd_set_syn(&ktrace->ta3d_syn, psSyncInfo);
93 pvr_trcmd_clear_syn(&ktrace->ta3d_syn);
96 if (psCCBKick->hTASyncInfo != NULL) {
97 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
98 psCCBKick->hTASyncInfo;
100 psTACmd->sTATQSyncReadOpsCompleteDevVAddr =
101 psSyncInfo->sReadOpsCompleteDevVAddr;
102 psTACmd->sTATQSyncWriteOpsCompleteDevVAddr =
103 psSyncInfo->sWriteOpsCompleteDevVAddr;
105 psTACmd->ui32TATQSyncReadOpsPendingVal =
106 psSyncInfo->psSyncData->ui32ReadOpsPending++;
107 psTACmd->ui32TATQSyncWriteOpsPendingVal =
108 psSyncInfo->psSyncData->ui32WriteOpsPending;
110 pvr_trcmd_set_syn(&ktrace->tatq_syn, psSyncInfo);
112 pvr_trcmd_clear_syn(&ktrace->tatq_syn);
115 if (psCCBKick->h3DSyncInfo != NULL) {
116 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
117 psCCBKick->h3DSyncInfo;
119 psTACmd->s3DTQSyncReadOpsCompleteDevVAddr =
120 psSyncInfo->sReadOpsCompleteDevVAddr;
121 psTACmd->s3DTQSyncWriteOpsCompleteDevVAddr =
122 psSyncInfo->sWriteOpsCompleteDevVAddr;
124 psTACmd->ui323DTQSyncReadOpsPendingVal =
125 psSyncInfo->psSyncData->ui32ReadOpsPending++;
126 psTACmd->ui323DTQSyncWriteOpsPendingVal =
127 psSyncInfo->psSyncData->ui32WriteOpsPending;
129 pvr_trcmd_set_syn(&ktrace->_3dtq_syn, psSyncInfo);
131 pvr_trcmd_clear_syn(&ktrace->_3dtq_syn);
134 psTACmd->ui32NumTAStatusVals = psCCBKick->ui32NumTAStatusVals;
135 if (psCCBKick->ui32NumTAStatusVals != 0) {
136 for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) {
137 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
138 psCCBKick->ahTAStatusSyncInfo[i];
140 psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr =
141 psSyncInfo->sReadOpsCompleteDevVAddr;
143 psTACmd->sCtlTAStatusInfo[i].ui32StatusValue =
144 psSyncInfo->psSyncData->ui32ReadOpsPending;
148 psTACmd->ui32Num3DStatusVals = psCCBKick->ui32Num3DStatusVals;
149 if (psCCBKick->ui32Num3DStatusVals != 0) {
150 for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) {
152 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
153 ah3DStatusSyncInfo[i];
155 psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr =
156 psSyncInfo->sReadOpsCompleteDevVAddr;
158 psTACmd->sCtl3DStatusInfo[i].ui32StatusValue =
159 psSyncInfo->psSyncData->ui32ReadOpsPending;
163 /* check for duplicates while creating the new list */
164 psTACmd->ui32NumSrcSyncs = 0;
165 for (i = 0; ((i < SGX_MAX_SRC_SYNCS) &&
166 (i < psCCBKick->ui32NumSrcSyncs)); i++) {
169 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
170 psCCBKick->ahSrcKernelSyncInfo[i];
172 for (j = 0; j < i; j++) {
173 struct PVRSRV_KERNEL_SYNC_INFO *tmp =
174 psCCBKick->ahSrcKernelSyncInfo[j];
175 if (tmp->psSyncData == psSyncInfo->psSyncData) {
176 pr_err("%s: Duplicate SRC Sync detected: %p\n",
177 __func__, tmp->psSyncData);
184 /* beat the 80 char limit. */
185 j = psTACmd->ui32NumSrcSyncs;
187 psTACmd->asSrcSyncs[j].sWriteOpsCompleteDevVAddr =
188 psSyncInfo->sWriteOpsCompleteDevVAddr;
189 psTACmd->asSrcSyncs[j].sReadOpsCompleteDevVAddr =
190 psSyncInfo->sReadOpsCompleteDevVAddr;
192 psTACmd->asSrcSyncs[j].ui32ReadOpsPendingVal =
193 psSyncInfo->psSyncData->ui32ReadOpsPending++;
195 psTACmd->asSrcSyncs[j].ui32WriteOpsPendingVal =
196 psSyncInfo->psSyncData->ui32WriteOpsPending;
198 pvr_trcmd_set_syn(&ktrace->src_syn[j], psSyncInfo);
200 psTACmd->ui32NumSrcSyncs++;
203 /* clear the remaining src syncs */
204 for (i = psTACmd->ui32NumSrcSyncs; i < SGX_MAX_SRC_SYNCS; i++)
205 pvr_trcmd_clear_syn(&ktrace->src_syn[i]);
207 if (psCCBKick->bFirstKickOrResume &&
208 psCCBKick->ui32NumDstSyncObjects > 0) {
209 struct PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo =
210 (struct PVRSRV_KERNEL_MEM_INFO *)psCCBKick->
211 hKernelHWSyncListMemInfo;
212 struct SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList =
213 psHWDstSyncListMemInfo->pvLinAddrKM;
214 u32 ui32NumDstSyncs = psCCBKick->ui32NumDstSyncObjects;
216 PVR_ASSERT(((struct PVRSRV_KERNEL_MEM_INFO *)psCCBKick->
217 hKernelHWSyncListMemInfo)->ui32AllocSize >=
218 (sizeof(struct SGXMKIF_HWDEVICE_SYNC_LIST) +
219 (sizeof(struct PVRSRV_DEVICE_SYNC_OBJECT) *
222 psHWDeviceSyncList->ui32NumSyncObjects = ui32NumDstSyncs;
224 if (PDumpIsCaptureFrameKM()) {
225 PDUMPCOMMENT("HWDeviceSyncList for TACmd\r\n");
227 psHWDstSyncListMemInfo, 0,
228 sizeof(struct SGXMKIF_HWDEVICE_SYNC_LIST),
229 0, MAKEUNIQUETAG(psHWDstSyncListMemInfo));
232 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
236 psHWDeviceSyncList->asSyncData[i].
237 sWriteOpsCompleteDevVAddr =
238 psSyncInfo->sWriteOpsCompleteDevVAddr;
240 psHWDeviceSyncList->asSyncData[i].
241 sReadOpsCompleteDevVAddr =
242 psSyncInfo->sReadOpsCompleteDevVAddr;
244 psHWDeviceSyncList->asSyncData[i].
245 ui32ReadOpsPendingVal =
246 psSyncInfo->psSyncData->ui32ReadOpsPending;
248 psHWDeviceSyncList->asSyncData[i].
249 ui32WriteOpsPendingVal =
250 psSyncInfo->psSyncData->
251 ui32WriteOpsPending++;
253 pvr_trcmd_set_syn(&ktrace->dst_syn, psSyncInfo);
256 if (PDumpIsCaptureFrameKM()) {
257 u32 ui32ModifiedValue;
258 u32 ui32SyncOffset = offsetof(
259 struct SGXMKIF_HWDEVICE_SYNC_LIST,
262 struct PVRSRV_DEVICE_SYNC_OBJECT));
263 u32 ui32WOpsOffset = ui32SyncOffset +
265 struct PVRSRV_DEVICE_SYNC_OBJECT,
266 ui32WriteOpsPendingVal);
267 u32 ui32ROpsOffset = ui32SyncOffset +
269 struct PVRSRV_DEVICE_SYNC_OBJECT,
270 ui32ReadOpsPendingVal);
272 PDUMPCOMMENT("HWDeviceSyncObject for RT: "
275 PDUMPMEM(NULL, psHWDstSyncListMemInfo,
276 ui32SyncOffset, sizeof(
277 struct PVRSRV_DEVICE_SYNC_OBJECT),
279 psHWDstSyncListMemInfo));
281 if ((psSyncInfo->psSyncData->
282 ui32LastOpDumpVal == 0) &&
283 (psSyncInfo->psSyncData->
284 ui32LastReadOpDumpVal == 0)) {
286 PDUMPCOMMENT("Init RT ROpsComplete\r\n",
288 PDUMPMEM(&psSyncInfo->psSyncData->
289 ui32LastReadOpDumpVal,
290 psSyncInfo->psSyncDataMemInfoKM,
293 ui32ReadOpsComplete),
294 sizeof(psSyncInfo->psSyncData->
295 ui32ReadOpsComplete),
297 MAKEUNIQUETAG(psSyncInfo->
298 psSyncDataMemInfoKM));
300 PDUMPCOMMENT("Init RT WOpsComplete\r\n");
301 PDUMPMEM(&psSyncInfo->psSyncData->
303 psSyncInfo->psSyncDataMemInfoKM,
304 offsetof(struct PVRSRV_SYNC_DATA,
305 ui32WriteOpsComplete),
306 sizeof(psSyncInfo->psSyncData->
307 ui32WriteOpsComplete),
308 0, MAKEUNIQUETAG(psSyncInfo->
309 psSyncDataMemInfoKM));
312 psSyncInfo->psSyncData->ui32LastOpDumpVal++;
314 ui32ModifiedValue = psSyncInfo->psSyncData->
315 ui32LastOpDumpVal - 1;
317 PDUMPCOMMENT("Modify RT %d WOpPendingVal "
318 "in HWDevSyncList\r\n", i);
320 PDUMPMEM(&ui32ModifiedValue,
321 psHWDstSyncListMemInfo, ui32WOpsOffset,
323 MAKEUNIQUETAG(psHWDstSyncListMemInfo));
325 PDUMPCOMMENT("Modify RT %d ROpsPendingVal "
326 "in HWDevSyncList\r\n", i);
328 PDUMPMEM(&psSyncInfo->psSyncData->
329 ui32LastReadOpDumpVal,
330 psHWDstSyncListMemInfo,
331 ui32ROpsOffset, sizeof(u32), 0,
332 MAKEUNIQUETAG(psHWDstSyncListMemInfo));
336 psHWDeviceSyncList->asSyncData[i].
337 sWriteOpsCompleteDevVAddr.uiAddr = 0;
338 psHWDeviceSyncList->asSyncData[i].
339 sReadOpsCompleteDevVAddr.uiAddr = 0;
341 psHWDeviceSyncList->asSyncData[i].
342 ui32ReadOpsPendingVal = 0;
343 psHWDeviceSyncList->asSyncData[i].
344 ui32WriteOpsPendingVal = 0;
346 pvr_trcmd_clear_syn(&ktrace->dst_syn);
349 pvr_trcmd_clear_syn(&ktrace->dst_syn);
352 if (PDumpIsCaptureFrameKM()) {
353 PDUMPCOMMENT("Shared part of TA command\r\n");
355 PDUMPMEM(psTACmd, psCCBMemInfo, psCCBKick->ui32CCBDumpWOff,
356 sizeof(struct SGXMKIF_CMDTA_SHARED), 0,
357 MAKEUNIQUETAG(psCCBMemInfo));
359 for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
360 u32 ui32ModifiedValue;
362 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
363 ahSrcKernelSyncInfo[i];
365 if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
366 (psSyncInfo->psSyncData->ui32LastReadOpDumpVal ==
368 PDUMPCOMMENT("Init RT ROpsComplete\r\n", i);
369 PDUMPMEM(&psSyncInfo->psSyncData->
370 ui32LastReadOpDumpVal,
371 psSyncInfo->psSyncDataMemInfoKM,
372 offsetof(struct PVRSRV_SYNC_DATA,
373 ui32ReadOpsComplete),
374 sizeof(psSyncInfo->psSyncData->
375 ui32ReadOpsComplete), 0,
376 MAKEUNIQUETAG(psSyncInfo->
377 psSyncDataMemInfoKM));
378 PDUMPCOMMENT("Init RT WOpsComplete\r\n");
379 PDUMPMEM(&psSyncInfo->psSyncData->
381 psSyncInfo->psSyncDataMemInfoKM,
382 offsetof(struct PVRSRV_SYNC_DATA,
383 ui32WriteOpsComplete),
384 sizeof(psSyncInfo->psSyncData->
385 ui32WriteOpsComplete), 0,
386 MAKEUNIQUETAG(psSyncInfo->
387 psSyncDataMemInfoKM));
390 psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
393 psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
395 PDUMPCOMMENT("Modify SrcSync %d ROpsPendingVal\r\n", i);
397 PDUMPMEM(&ui32ModifiedValue,
399 psCCBKick->ui32CCBDumpWOff +
400 offsetof(struct SGXMKIF_CMDTA_SHARED,
403 sizeof(struct PVRSRV_DEVICE_SYNC_OBJECT)) +
404 offsetof(struct PVRSRV_DEVICE_SYNC_OBJECT,
405 ui32ReadOpsPendingVal), sizeof(u32),
406 0, MAKEUNIQUETAG(psCCBMemInfo));
408 PDUMPCOMMENT("Modify SrcSync %d WOpPendingVal\r\n", i);
410 PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
412 psCCBKick->ui32CCBDumpWOff +
413 offsetof(struct SGXMKIF_CMDTA_SHARED,
416 sizeof(struct PVRSRV_DEVICE_SYNC_OBJECT)) +
417 offsetof(struct PVRSRV_DEVICE_SYNC_OBJECT,
418 ui32WriteOpsPendingVal), sizeof(u32),
419 0, MAKEUNIQUETAG(psCCBMemInfo));
423 for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) {
425 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
426 ahTAStatusSyncInfo[i];
427 PDUMPCOMMENT("Modify TA status value in TA cmd\r\n");
428 PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
430 psCCBKick->ui32CCBDumpWOff +
431 offsetof(struct SGXMKIF_CMDTA_SHARED,
432 sCtlTAStatusInfo[i].ui32StatusValue),
433 sizeof(u32), 0, MAKEUNIQUETAG(psCCBMemInfo));
436 for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) {
437 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
438 psCCBKick->ah3DStatusSyncInfo[i];
440 PDUMPCOMMENT("Modify 3D status value in TA cmd\r\n");
442 PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
444 psCCBKick->ui32CCBDumpWOff +
445 offsetof(struct SGXMKIF_CMDTA_SHARED,
446 sCtl3DStatusInfo[i].ui32StatusValue),
447 sizeof(u32), 0, MAKEUNIQUETAG(psCCBMemInfo));
452 pvr_trcmd_set_data(&ktrace->ctx, psCCBKick->sCommand.ui32Data[1]);
455 /* to aid in determining the next power down delay */
456 sgx_mark_new_command(psDeviceNode);
458 eError = SGXScheduleCCBCommandKM(hDevHandle, psCCBKick->eCommand,
459 &psCCBKick->sCommand, KERNEL_ID, 0);
460 if (eError == PVRSRV_ERROR_RETRY) {
461 if (psCCBKick->bFirstKickOrResume &&
462 psCCBKick->ui32NumDstSyncObjects > 0) {
463 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
464 psCCBKick->sDstSyncHandle;
466 psSyncInfo->psSyncData->ui32WriteOpsPending--;
468 if (PDumpIsCaptureFrameKM())
469 psSyncInfo->psSyncData->
475 for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
477 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
478 ahSrcKernelSyncInfo[i];
479 psSyncInfo->psSyncData->ui32ReadOpsPending--;
483 } else if (PVRSRV_OK != eError) {
484 PVR_DPF(PVR_DBG_ERROR,
485 "SGXDoKickKM: SGXScheduleCCBCommandKM failed.");
489 #if defined(NO_HARDWARE)
491 if (psCCBKick->hTA3DSyncInfo) {
493 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
495 if (psCCBKick->bTADependency) {
496 psSyncInfo->psSyncData->ui32WriteOpsComplete =
497 psSyncInfo->psSyncData->ui32WriteOpsPending;
501 if (psCCBKick->hTASyncInfo != NULL) {
503 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
505 psSyncInfo->psSyncData->ui32ReadOpsComplete =
506 psSyncInfo->psSyncData->ui32ReadOpsPending;
509 if (psCCBKick->h3DSyncInfo != NULL) {
511 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
513 psSyncInfo->psSyncData->ui32ReadOpsComplete =
514 psSyncInfo->psSyncData->ui32ReadOpsPending;
517 for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) {
519 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
520 ahTAStatusSyncInfo[i];
521 psSyncInfo->psSyncData->ui32ReadOpsComplete =
522 psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
525 for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
527 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
528 ahSrcKernelSyncInfo[i];
530 psSyncInfo->psSyncData->ui32ReadOpsComplete =
531 psSyncInfo->psSyncData->ui32ReadOpsPending;
535 if (psCCBKick->bTerminateOrAbort) {
536 if (psCCBKick->ui32NumDstSyncObjects > 0) {
537 struct PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo =
538 (struct PVRSRV_KERNEL_MEM_INFO *)psCCBKick->
539 hKernelHWSyncListMemInfo;
540 struct SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList =
541 psHWDstSyncListMemInfo->pvLinAddrKM;
544 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
547 psSyncInfo->psSyncData->ui32WriteOpsComplete =
548 psHWDeviceSyncList->asSyncData[0].
549 ui32WriteOpsPendingVal + 1;
552 for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) {
554 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
555 ah3DStatusSyncInfo[i];
556 psSyncInfo->psSyncData->ui32ReadOpsComplete =
557 psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;